On Sat, 21 May 2016 03:43:04 +0100 Emmanuel Gil Peyrot <emmanuel.pey...@collabora.com> wrote:
> This client uses libiio to retrieve accelerometer values from the iio > subsystem on Linux (and maybe some other kernels), and automatically > rotate the output whenever orientation changed. > > I tested it with a mma8453 accelerometer, but everything needed should > be available in the configuration to make it work with any other iio > device. > > Signed-off-by: Emmanuel Gil Peyrot <emmanuel.pey...@collabora.com> > --- > Makefile.am | 24 +++ > clients/autorotater.c | 472 > ++++++++++++++++++++++++++++++++++++++++++++ > configure.ac | 15 ++ > desktop-shell/shell.c | 1 + > protocol/weston-rotater.xml | 26 +++ > src/compositor.h | 3 + > src/rotater.c | 150 ++++++++++++++ > 7 files changed, 691 insertions(+) > create mode 100644 clients/autorotater.c > create mode 100644 protocol/weston-rotater.xml > create mode 100644 src/rotater.c Hi Emmanuel, why is there a new client for this? Could it not be a plugin? Is IIO potentially so slow and blocking we cannot use it in the server process? Why the polling approach, cannot IIO deliver events? Should there be a way to set which outputs get rotated by a specific IIO device, rather than assuming there is just one device rotating all outputs at once? Any reason why this is limited to desktop-shell rather than being a shell-agnostic feature? Thanks, pq > > diff --git a/Makefile.am b/Makefile.am > index 00b74e5..b1e0ade 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -122,6 +122,8 @@ endif > nodist_weston_SOURCES = \ > protocol/weston-screenshooter-protocol.c \ > protocol/weston-screenshooter-server-protocol.h \ > + protocol/weston-rotater-protocol.c \ > + protocol/weston-rotater-server-protocol.h \ > protocol/text-cursor-position-protocol.c \ > protocol/text-cursor-position-server-protocol.h \ > protocol/text-input-unstable-v1-protocol.c \ > @@ -611,6 +613,28 @@ nodist_weston_screenshooter_SOURCES = > \ > weston_screenshooter_LDADD = $(CLIENT_LIBS) libshared.la > weston_screenshooter_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) > > +if BUILD_AUTOROTATER > +libexec_PROGRAMS += weston-autorotater > + > +weston_autorotater_SOURCES = \ > + clients/autorotater.c > +nodist_weston_autorotater_SOURCES = \ > + protocol/weston-rotater-protocol.c \ > + protocol/weston-rotater-client-protocol.h > +weston_autorotater_LDADD = $(CLIENT_LIBS) $(LIBIIO_LIBS) libshared.la > +weston_autorotater_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) $(LIBIIO_CFLAGS) > + > +weston_SOURCES += \ > + src/rotater.c > + > +BUILT_SOURCES += \ > + protocol/weston-rotater-protocol.c \ > + protocol/weston-rotater-client-protocol.h > + > +EXTRA_DIST += \ > + protocol/weston-rotater.xml > +endif > + > weston_terminal_SOURCES = \ > clients/terminal.c \ > shared/helpers.h > diff --git a/clients/autorotater.c b/clients/autorotater.c > new file mode 100644 > index 0000000..0547f83 > --- /dev/null > +++ b/clients/autorotater.c > @@ -0,0 +1,472 @@ > +/* > + * Copyright © 2016 Collabora, Ltd. > + * > + * 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 "config.h" > + > +#include <stdint.h> > +#include <errno.h> > +#include <stdbool.h> > +#include <stdlib.h> > +#include <stdio.h> > +#include <string.h> > +#include <unistd.h> > + > +#include <wayland-client.h> > +#include "weston-rotater-client-protocol.h" > +#include "shared/config-parser.h" > +#include "shared/helpers.h" > +#include "shared/xalloc.h" > + > +#include <iio.h> > + > +#define BUFFER_SIZE 256 > + > +static struct weston_rotater *rotater; > +static struct wl_list output_list; > + > +struct rotater_output { > + struct wl_output *output; > + struct wl_list link; > +}; > + > +#define DEFAULT_SAMPLING_FREQUENCY 100. > + > +struct config { > + char *device_name; > + char *channel_x_name, *channel_y_name; > + char *sampling_frequency_name; > + double wanted_sampling_frequency; > + int threshold; > + int smooth_capture; > + struct wl_array allowed_rotations; > +}; > + > +#define MAX_CAPTURE_BUFFER_LENGTH 16 > + > +struct accelerometer { > + struct iio_context *context; > + struct iio_device *device; > + struct iio_channel *channel_x, *channel_y; > + double sampling_frequency; > + > + struct { > + int x[MAX_CAPTURE_BUFFER_LENGTH]; > + int y[MAX_CAPTURE_BUFFER_LENGTH]; > + } capture_buffer; > +}; > + > +static const struct { > + const char *name; > + int token; > +} transforms[] = { > + { "normal", WESTON_ROTATER_TRANSFORM_NORMAL }, > + { "90", WESTON_ROTATER_TRANSFORM_90 }, > + { "180", WESTON_ROTATER_TRANSFORM_180 }, > + { "270", WESTON_ROTATER_TRANSFORM_270 }, > + { "flipped", WESTON_ROTATER_TRANSFORM_FLIPPED }, > + { "flipped-90", WESTON_ROTATER_TRANSFORM_FLIPPED_90 }, > + { "flipped-180", WESTON_ROTATER_TRANSFORM_FLIPPED_180 }, > + { "flipped-270", WESTON_ROTATER_TRANSFORM_FLIPPED_270 }, > +}; > + > +static bool > +parse_transform(const char *transform, int *out) > +{ > + unsigned int i; > + > + for (i = 0; i < ARRAY_LENGTH(transforms); i++) > + if (strncmp(transforms[i].name, transform, > + strlen(transforms[i].name)) == 0) { > + *out = transforms[i].token; > + return true; > + } > + > + return false; > +} > + > +static struct config * > +read_configuration(void) > +{ > + struct config *configuration; > + const char *config_file; > + struct weston_config *config; > + struct weston_config_section *s; > + > + char *allowed_rotations, *p; > + int transform, *array_items; > + int i; > + > + configuration = zalloc(sizeof *configuration); > + if (!configuration) > + return NULL; > + > + config_file = weston_config_get_name_from_env(); > + config = weston_config_parse(config_file); > + s = weston_config_get_section(config, "autorotater", NULL, NULL); > + weston_config_section_get_string(s, "device", > + &configuration->device_name, NULL); > + weston_config_section_get_string(s, "channel_x", > + &configuration->channel_x_name, NULL); > + weston_config_section_get_string(s, "channel_y", > + &configuration->channel_y_name, NULL); > + weston_config_section_get_int(s, "threshold", > + &configuration->threshold, 128); > + weston_config_section_get_string(s, "sampling_frequency_attr", > + > &configuration->sampling_frequency_name, > + NULL); > + weston_config_section_get_double(s, "wanted_sampling_frequency", > + > &configuration->wanted_sampling_frequency, > + 0.); > + weston_config_section_get_int(s, "smooth_capture", > + &configuration->smooth_capture, 1); > + weston_config_section_get_string(s, "allowed_rotations", > + &allowed_rotations, NULL); > + weston_config_destroy(config); > + > + if (configuration->smooth_capture < 1) > + configuration->smooth_capture = 1; > + else if (configuration->smooth_capture > MAX_CAPTURE_BUFFER_LENGTH) > + configuration->smooth_capture = MAX_CAPTURE_BUFFER_LENGTH; > + > + wl_array_init(&configuration->allowed_rotations); > + if (allowed_rotations) { > + p = allowed_rotations; > + for (i = 0; i < 4; ++i) { > + if (!parse_transform(p, &transform)) > + break; > + array_items = > wl_array_add(&configuration->allowed_rotations, > + sizeof(int)); > + *array_items = transform; > + for (; *p != ' ' && *p != '\0'; p++); > + if (*p++ == '\0') > + break; > + } > + free(allowed_rotations); > + } else { > + array_items = wl_array_add(&configuration->allowed_rotations, > + sizeof(int)); > + array_items[0] = WESTON_ROTATER_TRANSFORM_NORMAL; > + array_items[1] = WESTON_ROTATER_TRANSFORM_90; > + array_items[2] = WESTON_ROTATER_TRANSFORM_180; > + array_items[3] = WESTON_ROTATER_TRANSFORM_270; > + } > + > + return configuration; > +} > + > +static void > +destroy_configuration(struct config *config) > +{ > + free(config->device_name); > + free(config->channel_x_name); > + free(config->channel_y_name); > + free(config->sampling_frequency_name); > + wl_array_release(&config->allowed_rotations); > + free(config); > +} > + > +static struct accelerometer * > +initialize_iio(struct config *config) > +{ > + struct accelerometer *accel; > + int ret; > + > + accel = zalloc(sizeof *accel); > + if (!accel) > + return NULL; > + > + accel->context = iio_create_local_context(); > + if (!accel->context) > + goto err_context; > + > + if (config->device_name) > + accel->device = iio_context_find_device(accel->context, > + config->device_name); > + > + if (!accel->device) { > + fprintf(stderr, "couldn't find device %s\n", > + config->device_name); > + goto err_device; > + } > + > + accel->channel_x = iio_device_find_channel(accel->device, > + config->channel_x_name, > + false); > + if (!accel->channel_x) { > + fprintf(stderr, "couldn't find x channel %s\n", > + config->channel_x_name); > + goto err_channel; > + } > + > + accel->channel_y = iio_device_find_channel(accel->device, > + config->channel_y_name, > + false); > + if (!accel->channel_y) { > + fprintf(stderr, "couldn't find y channel %s\n", > + config->channel_y_name); > + goto err_channel; > + } > + > + if (config->wanted_sampling_frequency) { > + ret = iio_device_attr_write_double(accel->device, > + > config->sampling_frequency_name, > + > config->wanted_sampling_frequency); > + if (ret < 0) { > + fprintf(stderr, "couldn't set sampling frequency to " > + "%f\n", > + config->wanted_sampling_frequency); > + goto err_channel; > + } > + } > + > + ret = iio_device_attr_read_double(accel->device, > + config->sampling_frequency_name, > + &accel->sampling_frequency); > + if (ret < 0) { > + fprintf(stderr, "couldn't retrieve sampling frequency, " > + "defaulting to %f\n", > + DEFAULT_SAMPLING_FREQUENCY); > + accel->sampling_frequency = DEFAULT_SAMPLING_FREQUENCY; > + } > + > + return accel; > + > +err_channel: > +err_device: > + iio_context_destroy(accel->context); > +err_context: > + free(accel); > + return NULL; > +} > + > +static void > +destroy_accelerometer(struct accelerometer *accel) > +{ > + if (accel->context) > + iio_context_destroy(accel->context); > + free(accel); > +} > + > +static bool > +capture_rotation(struct accelerometer *accel, int pos) > +{ > + char buf[BUFFER_SIZE]; > + ssize_t ret; > + > + ret = iio_channel_attr_read(accel->channel_x, "raw", buf, BUFFER_SIZE); > + if (ret < 0) { > + iio_strerror(-ret, buf, BUFFER_SIZE); > + fprintf(stderr, "%s\n", buf); > + return false; > + } > + accel->capture_buffer.x[pos] = atoi(buf); > + > + ret = iio_channel_attr_read(accel->channel_y, "raw", buf, BUFFER_SIZE); > + if (ret < 0) { > + iio_strerror(-ret, buf, BUFFER_SIZE); > + fprintf(stderr, "%s\n", buf); > + return false; > + } > + accel->capture_buffer.y[pos] = atoi(buf); > + return true; > +} > + > +static void > +smooth_input(struct accelerometer *accel, int pos, int values_count, int *x, > int *y) > +{ > + int i; > + > + *x = accel->capture_buffer.x[pos]; > + *y = accel->capture_buffer.y[pos]; > + > + if (values_count > 1) { > + for (i = 1; i < values_count; ++i) { > + *x += accel->capture_buffer.x[(pos - i) % values_count]; > + *y += accel->capture_buffer.y[(pos - i) % values_count]; > + } > + > + *x /= values_count; > + *y /= values_count; > + } > +} > + > +static int > +get_transform(int x, int y, int threshold) > +{ > + if (y > threshold && y > x) > + return WESTON_ROTATER_TRANSFORM_NORMAL; > + if (x > threshold && x > y) > + return WESTON_ROTATER_TRANSFORM_90; > + if (y < -threshold && y < x) > + return WESTON_ROTATER_TRANSFORM_180; > + if (x < -threshold && x < y) > + return WESTON_ROTATER_TRANSFORM_270; > + return -1; > +} > + > +static bool > +synchronize(struct wl_display *display, int sampling_frequency) > +{ > + if (wl_display_roundtrip(display) < 0) { > + fprintf(stderr, "lost connection, aborting\n"); > + return false; > + } > + usleep(1000 * sampling_frequency); > + return true; > +} > + > +static void > +handle_global(void *data, struct wl_registry *registry, > + uint32_t name, const char *interface, uint32_t version) > +{ > + static struct rotater_output *output; > + > + if (strcmp(interface, "wl_output") == 0) { > + output = xmalloc(sizeof *output); > + output->output = wl_registry_bind(registry, name, > + &wl_output_interface, 1); > + wl_list_insert(&output_list, &output->link); > + } else if (strcmp(interface, "weston_rotater") == 0) { > + rotater = wl_registry_bind(registry, name, > + &weston_rotater_interface, > + 1); > + } > +} > + > +static void > +handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) > +{ > + /* XXX: unimplemented */ > +} > + > +static const struct wl_registry_listener registry_listener = { > + handle_global, > + handle_global_remove > +}; > + > +int main(int argc, char *argv[]) > +{ > + struct wl_display *display; > + struct wl_registry *registry; > + struct rotater_output *output; > + struct config *config; > + struct accelerometer *accel; > + bool ret, found; > + int frame = 0; > + int x, y; > + int transform, previous_transform, *allowed_transform; > + > + if (getenv("WAYLAND_SOCKET") == NULL) { > + fprintf(stderr, "%s must be launched by weston.\n", > + program_invocation_short_name); > + return 1; > + } > + > + display = wl_display_connect(NULL); > + if (display == NULL) { > + fprintf(stderr, "failed to create display: %m\n"); > + return 2; > + } > + > + wl_list_init(&output_list); > + registry = wl_display_get_registry(display); > + wl_registry_add_listener(registry, ®istry_listener, NULL); > + wl_display_dispatch(display); > + wl_display_roundtrip(display); > + if (rotater == NULL) { > + fprintf(stderr, "display doesn't support rotater\n"); > + free(registry); > + wl_display_disconnect(display); > + return 3; > + } > + > + config = read_configuration(); > + if (!config) { > + fprintf(stderr, "failed to read configuration\n"); > + free(registry); > + wl_display_disconnect(display); > + return 4; > + } > + > + accel = initialize_iio(config); > + if (!accel) { > + fprintf(stderr, "failed to initialize iio subsystem\n"); > + free(registry); > + wl_display_disconnect(display); > + destroy_configuration(config); > + return 5; > + } > + > + previous_transform = WESTON_ROTATER_TRANSFORM_NORMAL; > + for (;;) { > + ret = capture_rotation(accel, frame); > + if (!ret) { > + fprintf(stderr, "failed to capture accelerometer " > + "values\n"); > + break; > + } > + > + smooth_input(accel, frame, config->smooth_capture, &x, &y); > + > + transform = get_transform(x, y, config->threshold); > + if (transform < 0) { > + if (!synchronize(display, accel->sampling_frequency)) > + return 6; > + continue; > + } > + > + found = false; > + wl_array_for_each(allowed_transform, > + &config->allowed_rotations) { > + if (transform == *allowed_transform) { > + found = true; > + break; > + } > + } > + > + if (!found) { > + if (!synchronize(display, accel->sampling_frequency)) > + return 6; > + continue; > + } > + > + if (transform != previous_transform) { > + wl_list_for_each(output, &output_list, link) { > + weston_rotater_rotate(rotater, > + output->output, > + transform); > + } > + } > + previous_transform = transform; > + frame = (frame + 1) % config->smooth_capture; > + > + if (!synchronize(display, accel->sampling_frequency)) > + return 6; > + } > + > + wl_display_disconnect(display); > + destroy_accelerometer(accel); > + destroy_configuration(config); > + > + return 0; > +} > diff --git a/configure.ac b/configure.ac > index e1300b4..61f9eba 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -384,6 +384,20 @@ if ! test "x$enable_simple_dmabuf_v4l_client" = "xno"; > then > fi > AM_CONDITIONAL(BUILD_SIMPLE_DMABUF_V4L_CLIENT, test > "x$enable_simple_dmabuf_v4l_client" = "xyes") > > +AC_ARG_ENABLE(weston-autorotater, > + AS_HELP_STRING([--disable-weston-autorotater], > + [do not build the autorotater client]),, > + enable_autorotater="auto") > +if ! test "x$enable_autorotater" = "xno"; then > + PKG_CHECK_MODULES(LIBIIO, [libiio], > + have_autorotater=yes, have_autorotater=no) > + if test "x$have_autorotater" = "xno" -a "x$enable_autorotater" = "xyes"; > then > + AC_MSG_ERROR([autorotater client explicitly enabled, but libiio couldn't > be found]) > + fi > + enable_autorotater="$have_autorotater" > +fi > +AM_CONDITIONAL(BUILD_AUTOROTATER, test "x$enable_autorotater" = "xyes") > + > AC_ARG_ENABLE(clients, [ --enable-clients],, enable_clients=yes) > AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes) > if test x$enable_clients = xyes; then > @@ -688,6 +702,7 @@ AC_MSG_RESULT([ > Build EGL Clients ${have_cairo_egl} > Build Simple Clients ${enable_simple_clients} > Build Simple EGL Clients ${enable_simple_egl_clients} > + Build Autorotater Client ${enable_autorotater} > > Install Demo Clients ${enable_demo_clients_install} > > diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c > index 7d5bca9..c1750a7 100644 > --- a/desktop-shell/shell.c > +++ b/desktop-shell/shell.c > @@ -6704,6 +6704,7 @@ module_init(struct weston_compositor *ec, > wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener); > > screenshooter_create(ec); > + rotater_create(ec); > > shell_add_bindings(ec, shell); > > diff --git a/protocol/weston-rotater.xml b/protocol/weston-rotater.xml > new file mode 100644 > index 0000000..90a6f84 > --- /dev/null > +++ b/protocol/weston-rotater.xml > @@ -0,0 +1,26 @@ > +<protocol name="weston_rotater"> > + > + <interface name="weston_rotater" version="1"> > + > + <enum name="transform"> > + <description summary="copied from wl_output.transform"/> > + <entry name="normal" value="0"/> > + <entry name="90" value="1"/> > + <entry name="180" value="2"/> > + <entry name="270" value="3"/> > + <entry name="flipped" value="4"/> > + <entry name="flipped_90" value="5"/> > + <entry name="flipped_180" value="6"/> > + <entry name="flipped_270" value="7"/> > + </enum> > + > + <request name="rotate"> > + <arg name="output" type="object" interface="wl_output"/> > + <arg name="transform" type="int" enum="transform"/> > + </request> > + > + <event name="done"/> > + > + </interface> > + > +</protocol> > diff --git a/src/compositor.h b/src/compositor.h > index 0bbf458..9a211c1 100644 > --- a/src/compositor.h > +++ b/src/compositor.h > @@ -1592,6 +1592,9 @@ int > weston_screenshooter_shoot(struct weston_output *output, struct > weston_buffer *buffer, > weston_screenshooter_done_func_t done, void *data); > > +void > +rotater_create(struct weston_compositor *ec); > + > struct clipboard * > clipboard_create(struct weston_seat *seat); > > diff --git a/src/rotater.c b/src/rotater.c > new file mode 100644 > index 0000000..4575ac7 > --- /dev/null > +++ b/src/rotater.c > @@ -0,0 +1,150 @@ > +/* > + * Copyright © 2016 Collabora, Ltd. > + * > + * 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 "config.h" > + > +#include <stdio.h> > +#include <stdint.h> > +#include <stdlib.h> > +#include <linux/input-event-codes.h> > + > +#include "compositor.h" > +#include "weston-rotater-server-protocol.h" > +#include "shared/helpers.h" > + > +struct rotater { > + struct weston_compositor *ec; > + struct wl_global *global; > + struct wl_client *client; > + struct weston_process process; > + struct wl_listener destroy_listener; > +}; > + > +static void > +rotater_rotate(struct wl_client *client, > + struct wl_resource *resource, > + struct wl_resource *output_resource, > + int32_t transform) > +{ > + int32_t current_width; > + struct weston_output *output = > + wl_resource_get_user_data(output_resource); > + > + /* Only swap width and height when the aspect ratio changed. */ > + if ((transform ^ output->transform) & 1) { > + current_width = output->width; > + output->width = output->height; > + output->height = current_width; > + } > + > + output->transform = transform; > + output->dirty = 1; > + weston_output_damage(output); > +} > + > +struct weston_rotater_interface rotater_implementation = { > + rotater_rotate > +}; > + > +static void > +bind_rotater(struct wl_client *client, > + void *data, uint32_t version, uint32_t id) > +{ > + struct rotater *rotater = data; > + struct wl_resource *resource; > + > + resource = wl_resource_create(client, > + &weston_rotater_interface, 1, id); > + > + if (client != rotater->client) { > + wl_resource_post_error(resource, > + WL_DISPLAY_ERROR_INVALID_OBJECT, > + "rotater failed: permission denied"); > + return; > + } > + > + wl_resource_set_implementation(resource, &rotater_implementation, > + data, NULL); > +} > + > +static void > +rotater_sigchld(struct weston_process *process, int status) > +{ > + struct rotater *rotater = > + container_of(process, struct rotater, process); > + > + rotater->client = NULL; > +} > + > +static void > +rotater_launch_autorotater(struct rotater *rotater) > +{ > + char *rotater_exe; > + int ret; > + > + ret = asprintf(&rotater_exe, "%s/%s", > + weston_config_get_libexec_dir(), > + "/weston-autorotater"); > + if (ret < 0) { > + weston_log("Could not construct rotater path.\n"); > + return; > + } > + > + if (!rotater->client) > + rotater->client = weston_client_launch(rotater->ec, > + &rotater->process, > + rotater_exe, rotater_sigchld); > + free(rotater_exe); > +} > + > +static void > +rotater_destroy(struct wl_listener *listener, void *data) > +{ > + struct rotater *rotater = > + container_of(listener, struct rotater, destroy_listener); > + > + wl_global_destroy(rotater->global); > + free(rotater); > +} > + > +WL_EXPORT void > +rotater_create(struct weston_compositor *ec) > +{ > + struct rotater *rotater; > + > + rotater = malloc(sizeof *rotater); > + if (rotater == NULL) > + return; > + > + rotater->ec = ec; > + rotater->client = NULL; > + > + rotater->global = wl_global_create(ec->wl_display, > + &weston_rotater_interface, 1, > + rotater, bind_rotater); > + rotater->destroy_listener.notify = rotater_destroy; > + wl_signal_add(&ec->destroy_signal, &rotater->destroy_listener); > + rotater_launch_autorotater(rotater); > +}
pgpwJymacqBFg.pgp
Description: OpenPGP digital signature
_______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel