mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 15:14:38 +01:00
resolutions: switch to using objects for resolutions
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
@@ -81,7 +81,8 @@ ratbagd_SOURCES = \
|
||||
src/ratbagd.h \
|
||||
src/ratbagd.c \
|
||||
src/ratbagd-device.c \
|
||||
src/ratbagd-profile.c
|
||||
src/ratbagd-profile.c \
|
||||
src/ratbagd-resolution.c
|
||||
|
||||
ratbagd_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
|
||||
@@ -349,6 +349,7 @@ void ratbagd_device_link(struct ratbagd_device *device)
|
||||
struct ratbagd_device *iter;
|
||||
RBNode **node, *parent;
|
||||
int r, v;
|
||||
unsigned int i;
|
||||
|
||||
assert(device);
|
||||
assert(!ratbagd_device_linked(device));
|
||||
@@ -398,6 +399,18 @@ void ratbagd_device_link(struct ratbagd_device *device)
|
||||
fprintf(stderr,
|
||||
"Cannot register profile interfaces for '%s': %m\n",
|
||||
device->name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < device->n_profiles; i++) {
|
||||
r = ratbagd_profile_register_resolutions(device->ctx->bus,
|
||||
device,
|
||||
device->profiles[i]);
|
||||
if (r < 0) {
|
||||
fprintf(stderr,
|
||||
"Cannot register resolutions for '%s': %m\n",
|
||||
device->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,44 @@ struct ratbagd_profile {
|
||||
struct ratbag_profile *lib_profile;
|
||||
unsigned int index;
|
||||
char *path;
|
||||
|
||||
sd_bus_slot *resolution_vtable_slot;
|
||||
sd_bus_slot *resolution_enum_slot;
|
||||
unsigned int n_resolutions;
|
||||
struct ratbagd_resolution **resolutions;
|
||||
};
|
||||
|
||||
static int ratbagd_profile_find_resolution(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *userdata,
|
||||
void **found,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
_cleanup_(freep) char *name = NULL;
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
unsigned int index;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode_many(path,
|
||||
"/org/freedesktop/ratbag1/resolution/%/p%/r%",
|
||||
NULL,
|
||||
NULL,
|
||||
&name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou(name, &index);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
if (index >= profile->n_resolutions || !profile->resolutions[index])
|
||||
return 0;
|
||||
|
||||
*found = profile->resolutions[index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_get_resolutions(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
@@ -49,60 +85,22 @@ static int ratbagd_profile_get_resolutions(sd_bus *bus,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
unsigned int i, n_resolutions;
|
||||
struct ratbagd_resolution *resolution;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "a{sv}");
|
||||
r = sd_bus_message_open_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n_resolutions = ratbag_profile_get_num_resolutions(profile->lib_profile);
|
||||
for (i = 0; i < n_resolutions; ++i) {
|
||||
struct ratbag_resolution *resolution;
|
||||
bool cap_separate_xy_resolution;
|
||||
unsigned int dpi_x, dpi_y, report_rate;
|
||||
|
||||
resolution = ratbag_profile_get_resolution(profile->lib_profile, i);
|
||||
for (i = 0; i < profile->n_resolutions; ++i) {
|
||||
resolution = profile->resolutions[i];
|
||||
if (!resolution)
|
||||
continue;
|
||||
|
||||
cap_separate_xy_resolution = ratbag_resolution_has_capability(resolution,
|
||||
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
|
||||
report_rate = ratbag_resolution_get_report_rate(resolution);
|
||||
if (cap_separate_xy_resolution) {
|
||||
dpi_x = ratbag_resolution_get_dpi_x(resolution);
|
||||
dpi_y = ratbag_resolution_get_dpi_y(resolution);
|
||||
} else {
|
||||
dpi_x = ratbag_resolution_get_dpi(resolution);
|
||||
}
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "{sv}");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (cap_separate_xy_resolution) {
|
||||
r = sd_bus_message_append(reply, "{sv}",
|
||||
"dpi-x", "u", dpi_x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(reply, "{sv}",
|
||||
"dpi-y", "u", dpi_y);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = sd_bus_message_append(reply, "{sv}",
|
||||
"dpi", "u", dpi_x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(reply, "{sv}",
|
||||
"report-rate", "u", report_rate);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(reply);
|
||||
r = sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_resolution_get_path(resolution));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -186,7 +184,7 @@ static int ratbagd_profile_set_active(sd_bus_message *m,
|
||||
const sd_bus_vtable ratbagd_profile_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_profile, index), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Resolutions", "aa{sv}", ratbagd_profile_get_resolutions, 0, 0),
|
||||
SD_BUS_PROPERTY("Resolutions", "ao", ratbagd_profile_get_resolutions, 0, 0),
|
||||
SD_BUS_PROPERTY("ActiveResolution", "u", ratbagd_profile_get_active_resolution, 0, 0),
|
||||
SD_BUS_PROPERTY("DefaultResolution", "u", ratbagd_profile_get_default_resolution, 0, 0),
|
||||
SD_BUS_METHOD("SetActive", "", "u", ratbagd_profile_set_active, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
@@ -199,7 +197,9 @@ int ratbagd_profile_new(struct ratbagd_profile **out,
|
||||
unsigned int index)
|
||||
{
|
||||
_cleanup_(ratbagd_profile_freep) struct ratbagd_profile *profile = NULL;
|
||||
struct ratbag_resolution *resolution;
|
||||
char index_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
@@ -220,6 +220,29 @@ int ratbagd_profile_new(struct ratbagd_profile **out,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
profile->n_resolutions = ratbag_profile_get_num_resolutions(profile->lib_profile);
|
||||
profile->resolutions = calloc(profile->n_resolutions, sizeof(*profile->resolutions));
|
||||
if (!profile->resolutions)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < profile->n_resolutions; ++i) {
|
||||
resolution = ratbag_profile_get_resolution(profile->lib_profile, i);
|
||||
if (!resolution)
|
||||
continue;
|
||||
|
||||
r = ratbagd_resolution_new(&profile->resolutions[i],
|
||||
device,
|
||||
profile,
|
||||
resolution,
|
||||
i);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr,
|
||||
"Cannot allocate resolution for '%s': %m\n",
|
||||
ratbagd_device_get_name(device));
|
||||
}
|
||||
}
|
||||
|
||||
*out = profile;
|
||||
profile = NULL;
|
||||
return 0;
|
||||
@@ -250,3 +273,88 @@ bool ratbagd_profile_is_active(struct ratbagd_profile *profile)
|
||||
assert(profile);
|
||||
return ratbag_profile_is_active(profile->lib_profile) != 0;
|
||||
}
|
||||
|
||||
unsigned int ratbagd_profile_get_index(struct ratbagd_profile *profile)
|
||||
{
|
||||
assert(profile);
|
||||
return profile->index;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_list_resolutions(sd_bus *bus,
|
||||
const char *path,
|
||||
void *userdata,
|
||||
char ***paths,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_resolution *resolution;
|
||||
char **resolutions;
|
||||
unsigned int i;
|
||||
|
||||
resolutions = calloc(profile->n_resolutions + 1, sizeof(char *));
|
||||
if (!resolutions)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < profile->n_resolutions; ++i) {
|
||||
resolution = profile->resolutions[i];
|
||||
if (!resolution)
|
||||
continue;
|
||||
|
||||
resolutions[i] = strdup(ratbagd_resolution_get_path(resolution));
|
||||
if (!resolutions[i])
|
||||
goto error;
|
||||
}
|
||||
|
||||
resolutions[i] = NULL;
|
||||
*paths = resolutions;
|
||||
return 1;
|
||||
|
||||
error:
|
||||
for (i = 0; resolutions[i]; ++i)
|
||||
free(resolutions[i]);
|
||||
free(resolutions);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
int ratbagd_profile_register_resolutions(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile)
|
||||
{
|
||||
_cleanup_(freep) char *prefix = NULL;
|
||||
char index_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
sprintf(index_buffer, "p%u", profile->index);
|
||||
|
||||
/* register resolution interfaces */
|
||||
r = sd_bus_path_encode_many(&prefix,
|
||||
"/org/freedesktop/ratbag1/resolution/%/%",
|
||||
ratbagd_device_get_name(device),
|
||||
index_buffer);
|
||||
|
||||
|
||||
if (r >= 0) {
|
||||
r = sd_bus_add_fallback_vtable(bus,
|
||||
&profile->resolution_vtable_slot,
|
||||
prefix,
|
||||
"org.freedesktop.ratbag1.Resolution",
|
||||
ratbagd_resolution_vtable,
|
||||
ratbagd_profile_find_resolution,
|
||||
profile);
|
||||
if (r >= 0)
|
||||
r = sd_bus_add_node_enumerator(bus,
|
||||
&profile->resolution_enum_slot,
|
||||
prefix,
|
||||
ratbagd_profile_list_resolutions,
|
||||
profile);
|
||||
}
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr,
|
||||
"Cannot register resolutions for '%s': %m\n",
|
||||
ratbagd_device_get_name(device));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
114
src/ratbagd-resolution.c
Normal file
114
src/ratbagd-resolution.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2016 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
***/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libratbag.h>
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "ratbagd.h"
|
||||
#include "shared-macro.h"
|
||||
|
||||
struct ratbagd_resolution {
|
||||
struct ratbag_resolution *lib_resolution;
|
||||
unsigned int index;
|
||||
char *path;
|
||||
unsigned int xres, yres;
|
||||
unsigned int rate;
|
||||
|
||||
sd_bus_slot *profile_vtable_slot;
|
||||
sd_bus_slot *profile_enum_slot;
|
||||
};
|
||||
|
||||
const sd_bus_vtable ratbagd_resolution_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_resolution, index), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("XResolution", "u", NULL, offsetof(struct ratbagd_resolution, xres), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("YResolution", "u", NULL, offsetof(struct ratbagd_resolution, yres), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ReportRate", "u", NULL, offsetof(struct ratbagd_resolution, rate), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
int ratbagd_resolution_new(struct ratbagd_resolution **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_resolution *lib_resolution,
|
||||
unsigned int index)
|
||||
{
|
||||
_cleanup_(ratbagd_resolution_freep) struct ratbagd_resolution *resolution = NULL;
|
||||
char profile_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1],
|
||||
resolution_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
assert(lib_resolution);
|
||||
|
||||
resolution = calloc(1, sizeof(*resolution));
|
||||
if (!resolution)
|
||||
return -ENOMEM;
|
||||
|
||||
resolution->lib_resolution = lib_resolution;
|
||||
resolution->index = index;
|
||||
resolution->xres = ratbag_resolution_get_dpi_x(lib_resolution);
|
||||
resolution->yres = ratbag_resolution_get_dpi_y(lib_resolution);
|
||||
resolution->rate = ratbag_resolution_get_report_rate(lib_resolution);
|
||||
|
||||
sprintf(profile_buffer, "p%u", ratbagd_profile_get_index(profile));
|
||||
sprintf(resolution_buffer, "r%u", index);
|
||||
r = sd_bus_path_encode_many(&resolution->path,
|
||||
"/org/freedesktop/ratbag1/resolution/%/%/%",
|
||||
ratbagd_device_get_name(device),
|
||||
profile_buffer,
|
||||
resolution_buffer);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*out = resolution;
|
||||
resolution = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ratbagd_resolution_get_path(struct ratbagd_resolution *resolution)
|
||||
{
|
||||
assert(resolution);
|
||||
return resolution->path;
|
||||
}
|
||||
|
||||
struct ratbagd_resolution *ratbagd_resolution_free(struct ratbagd_resolution *resolution)
|
||||
{
|
||||
if (!resolution)
|
||||
return NULL;
|
||||
|
||||
resolution->path = mfree(resolution->path);
|
||||
|
||||
/* we cannot assume the resolution is gone, so set NULL explicitly */
|
||||
ratbag_resolution_unref(resolution->lib_resolution);
|
||||
resolution->lib_resolution = NULL;
|
||||
|
||||
return mfree(resolution);
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
struct ratbagd;
|
||||
struct ratbagd_device;
|
||||
struct ratbagd_profile;
|
||||
struct ratbagd_resolution;
|
||||
|
||||
/*
|
||||
* Profiles
|
||||
@@ -54,9 +55,28 @@ struct ratbagd_profile *ratbagd_profile_free(struct ratbagd_profile *profile);
|
||||
const char *ratbagd_profile_get_path(struct ratbagd_profile *profile);
|
||||
bool ratbagd_profile_is_active(struct ratbagd_profile *profile);
|
||||
bool ratbagd_profile_is_default(struct ratbagd_profile *profile);
|
||||
unsigned int ratbagd_profile_get_index(struct ratbagd_profile *profile);
|
||||
int ratbagd_profile_register_resolutions(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_profile *, ratbagd_profile_free);
|
||||
|
||||
/*
|
||||
* Resolutions
|
||||
*/
|
||||
extern const sd_bus_vtable ratbagd_resolution_vtable[];
|
||||
|
||||
int ratbagd_resolution_new(struct ratbagd_resolution **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_resolution *lib_resolution,
|
||||
unsigned int index);
|
||||
struct ratbagd_resolution *ratbagd_resolution_free(struct ratbagd_resolution *resolution);
|
||||
const char *ratbagd_resolution_get_path(struct ratbagd_resolution *resolution);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_resolution *, ratbagd_resolution_free);
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user