From 018efc8ef96a77529507b8a1614067821be8b90d Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Wed, 8 Jul 2015 23:16:06 +0200 Subject: Add simple test client embryo --- .gitignore | 2 + Makefile | 38 ++- RemoteControlManager.xml | 31 +++ rcm-client-hardware-info.c | 74 ++++++ rcm-client-hardware-info.h | 3 + rcm-client-hardware-list.c | 140 +++++++++++ rcm-client-hardware-list.h | 6 + rcm-client-main.c | 216 ++++++++++++++++ rcm-client-main.h | 10 + rcm-client-receive.c | 612 +++++++++++++++++++++++++++++++++++++++++++++ rcm-client-receive.h | 4 + rcm-client-transmit.c | 31 +++ rcm-client-transmit.h | 4 + rcm-server-keymap.c | 61 ++++- rcm-server-keymap.h | 5 +- rcm-server-main.c | 564 +++++++++++++++++++++++++++++++++++++++++ rcm-server-main.h | 24 ++ rcm-server.c | 563 ----------------------------------------- rcm-server.h | 24 -- 19 files changed, 1812 insertions(+), 600 deletions(-) create mode 100644 RemoteControlManager.xml create mode 100644 rcm-client-hardware-info.c create mode 100644 rcm-client-hardware-info.h create mode 100644 rcm-client-hardware-list.c create mode 100644 rcm-client-hardware-list.h create mode 100644 rcm-client-main.c create mode 100644 rcm-client-main.h create mode 100644 rcm-client-receive.c create mode 100644 rcm-client-receive.h create mode 100644 rcm-client-transmit.c create mode 100644 rcm-client-transmit.h create mode 100644 rcm-server-main.c create mode 100644 rcm-server-main.h delete mode 100644 rcm-server.c delete mode 100644 rcm-server.h diff --git a/.gitignore b/.gitignore index a558115..b4d4283 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.o rcm-server +rcm-client *.swp keymaps +generated.* diff --git a/Makefile b/Makefile index 9b601f3..571427b 100644 --- a/Makefile +++ b/Makefile @@ -11,16 +11,26 @@ GENERIC_CFLAGS = -g -Wall -Werror -D_FILE_OFFSET_BITS=64 \ EXTRA_CFLAGS = GENERIC_LDFLAGS = EXTRA_LDFLAGS = + RCM_PACKAGES = libudev libsystemd RCM_CFLAGS = ${GENERIC_CFLAGS} ${EXTRA_CFLAGS} $(shell pkg-config --cflags ${RCM_PACKAGES}) RCM_LDFLAGS = ${GENERIC_LDFLAGS} ${EXTRA_LDFLAGS} $(shell pkg-config --libs ${RCM_PACKAGES}) +RCM_COMPILE = $(CC) $(RCM_CFLAGS) +RCM_LINK = $(CC) $(RCM_CFLAGS) $(RCM_LDFLAGS) +RCM_OBJECTS = rcm-server-main.o rcm-server-keymap.o +RCM_HEADERS = rcm-server-main.h rcm-server-keymap.h utils.h + +RCC_PACKAGES = gtk+-3.0 +RCC_CFLAGS = ${GENERIC_CFLAGS} ${EXTRA_CFLAGS} $(shell pkg-config --cflags ${RCC_PACKAGES}) +RCC_LDFLAGS = ${GENERIC_LDFLAGS} ${EXTRA_LDFLAGS} $(shell pkg-config --libs ${RCC_PACKAGES}) +RCC_COMPILE = $(CC) $(RCC_CFLAGS) +RCC_LINK = $(CC) $(RCC_CFLAGS) $(RCC_LDFLAGS) +RCC_OBJECTS = rcm-client-main.o rcm-client-hardware-list.o rcm-client-hardware-info.o rcm-client-receive.o rcm-client-transmit.o generated.o +RCC_HEADERS = rcm-client-main.h rcm-client-hardware-list.h rcm-client-hardware-info.h rcm-client-receive.h rcm-client-transmit.h generated.h + INSTALL = install -c INSTALL_PROGRAM = ${INSTALL} INSTALL_DATA = ${INSTALL} -m 644 -RCM_COMPILE = $(CC) $(RCM_CFLAGS) -RCM_LINK = $(CC) $(RCM_CFLAGS) $(RCM_LDFLAGS) -RCM_SERVER_OBJ = rcm-server.o rcm-server-keymap.o -RCM_SERVER_HDR = rcm-server.h rcm-server-keymap.h utils.h DESTDIR ?= prefix = /usr @@ -33,13 +43,25 @@ mandir = ${prefix}/share/man # Targets # -all: rcm-server +all: rcm-server rcm-client .DEFAULT: all -%.o: %.c $(RCM_SERVER_HDR) +rcm-client-%.o: rcm-client-%.c $(RCC_HEADERS) + $(RCC_COMPILE) -o $@ -c $< + +generated.o: generated.c generated.h + $(RCC_COMPILE) -o $@ -c $< + +generated.c generated.h: RemoteControlManager.xml + gdbus-codegen --interface-prefix org.gnome --c-generate-object-manager --generate-c-code generated RemoteControlManager.xml + +rcm-client: $(RCC_OBJECTS) + $(RCC_LINK) -o $@ $^ + +rcm-server-%.o: rcm-server-%.c $(RCM_HEADERS) $(RCM_COMPILE) -o $@ -c $< -rcm-server: $(RCM_SERVER_OBJ) +rcm-server: $(RCM_OBJECTS) $(RCM_LINK) -o $@ $^ install: all @@ -49,7 +71,7 @@ uninstall: - rm -f $(DESTDIR)$(usrbindir)/rcm-server clean: - - rm -f *.o rcm-server + - rm -f generated.[ch] *.o rcm-server rcm-client .PHONY: install uninstall clean all diff --git a/RemoteControlManager.xml b/RemoteControlManager.xml new file mode 100644 index 0000000..ede8f69 --- /dev/null +++ b/RemoteControlManager.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rcm-client-hardware-info.c b/rcm-client-hardware-info.c new file mode 100644 index 0000000..662f526 --- /dev/null +++ b/rcm-client-hardware-info.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include + +#include "generated.h" +#include "rcm-client-main.h" +#include "rcm-client-hardware-list.h" +#include "rcm-client-hardware-info.h" +#include "rcm-client-receive.h" +#include "rcm-client-transmit.h" + +static GtkWidget *info = NULL; +static GDBusObject *hw = NULL; + +void +rcng_client_hardware_init_info_ui(GDBusObject *new_hw) +{ + GtkWidget *icon; + GtkWidget *hbox; + GtkWidget *title; + GtkWidget *line; + + if (new_hw == hw) + return; + + hw = new_hw; + if (info) + gtk_widget_destroy(info); + info = NULL; + rcng_client_receive_destroy_ui(); + rcng_client_transmit_destroy_ui(); + + if (!hw) + return; + + icon = gtk_image_new_from_icon_name("gtk-harddisk", GTK_ICON_SIZE_DIALOG); + gtk_widget_set_valign(icon, GTK_ALIGN_START); + gtk_widget_set_halign(icon, GTK_ALIGN_START); + gtk_widget_set_margin_start(icon, 12); + gtk_widget_set_margin_end(icon, 12); + + hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); + + title = gtk_label_new(NULL); + gtk_label_set_markup(GTK_LABEL(title), "Hardware"); + gtk_widget_set_halign(title, GTK_ALIGN_START); + gtk_box_pack_start(GTK_BOX(hbox), title, FALSE, FALSE, 0); + + line = gtk_label_new("Apan 1"); + gtk_widget_set_halign(line, GTK_ALIGN_START); + gtk_box_pack_start(GTK_BOX(hbox), line, FALSE, FALSE, 0); + + line = gtk_label_new("Apan 2"); + line = gtk_label_new(g_dbus_object_get_object_path(hw)); + gtk_widget_set_halign(line, GTK_ALIGN_START); + gtk_box_pack_start(GTK_BOX(hbox), line, FALSE, FALSE, 0); + + info = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_margin_start(info, 12); + gtk_widget_set_margin_end(info, 12); + gtk_widget_set_margin_top(info, 12); + gtk_widget_set_margin_bottom(info, 12); + gtk_box_pack_start(GTK_BOX(info), icon, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(info), hbox, FALSE, FALSE, 0); + + gtk_widget_show_all(info); + gtk_notebook_append_page(global->notebook, info, gtk_label_new("Details")); + gtk_notebook_set_current_page(global->notebook, 1); + + rcng_client_receive_init_ui(new_hw); +} diff --git a/rcm-client-hardware-info.h b/rcm-client-hardware-info.h new file mode 100644 index 0000000..37e65f0 --- /dev/null +++ b/rcm-client-hardware-info.h @@ -0,0 +1,3 @@ + +void rcng_client_hardware_init_info_ui(GDBusObject *); + diff --git a/rcm-client-hardware-list.c b/rcm-client-hardware-list.c new file mode 100644 index 0000000..eec0d03 --- /dev/null +++ b/rcm-client-hardware-list.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include + +#include "generated.h" +#include "rcm-client-main.h" +#include "rcm-client-hardware-list.h" +#include "rcm-client-hardware-info.h" + +static GtkWidget *status_msg; +static GtkWidget *hw_list_box; +static GtkWidget *stack; +static GList *hw_list = NULL; + +struct hwentry { + GDBusObject *hw; + GtkWidget *widget; +}; + +static gint +find_hwentry_by_object(gconstpointer a, gconstpointer user_data) +{ + const struct hwentry *hwe = a; + + return hwe->hw == user_data ? 0 : -1; +} + +static gint +find_hwentry_by_widget(gconstpointer a, gconstpointer user_data) +{ + const struct hwentry *hwe = a; + + return hwe->widget == user_data ? 0 : -1; +} + +void rcng_client_hardware_list_remove(GDBusObject *hw) +{ + GList *entry; + struct hwentry *hwe; + + entry = g_list_find_custom(hw_list, hw, find_hwentry_by_object); + if (!entry) + return; + + hwe = entry->data; + hw_list = g_list_remove_all(hw_list, hwe); + + g_print(" - Object removed %s\n", g_dbus_object_get_object_path(hwe->hw)); + gtk_widget_destroy(hwe->widget); + g_free(hwe); + + if (!hw_list) + gtk_stack_set_visible_child(GTK_STACK(stack), status_msg); +} + +void rcng_client_hardware_list_add(GDBusObject *hw) +{ + GList *interfaces; + GList *ll; + GtkWidget *box; + GtkWidget *icon; + GtkWidget *label; + struct hwentry *hwe; + + g_print(" - Object at %s\n", g_dbus_object_get_object_path(hw)); + + interfaces = g_dbus_object_get_interfaces(hw); + for (ll = interfaces; ll != NULL; ll = ll->next) { + GDBusInterface *interface = G_DBUS_INTERFACE(ll->data); + g_print (" - Interface %s\n", g_dbus_interface_get_info(interface)->name); + } + g_list_free_full (interfaces, g_object_unref); + + if (!hw_list) + gtk_stack_set_visible_child(GTK_STACK(stack), hw_list_box); + + box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + icon = gtk_image_new_from_icon_name("gtk-harddisk", GTK_ICON_SIZE_DIALOG); + gtk_widget_set_valign(icon, GTK_ALIGN_START); + gtk_widget_set_halign(icon, GTK_ALIGN_START); + gtk_widget_set_margin_start(icon, 12); + gtk_widget_set_margin_end(icon, 12); + label = gtk_label_new(g_dbus_object_get_object_path(hw)); + gtk_box_pack_start(GTK_BOX(box), icon, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); + gtk_widget_show_all(box); + + gtk_list_box_insert(GTK_LIST_BOX(hw_list_box), box, -1); + + hwe = g_malloc(sizeof(*hwe)); + hwe->hw = hw; + hwe->widget = box; + hw_list = g_list_append(hw_list, hwe); +} + +static void +on_hw_selected(GtkListBox *box, + GtkListBoxRow *row, + gpointer user_data) +{ + GList *entry; + GtkWidget *child; + struct hwentry *hwe; + + child = row ? gtk_bin_get_child(GTK_BIN(row)) : NULL; + entry = g_list_find_custom(hw_list, child, find_hwentry_by_widget); + hwe = entry ? entry->data : NULL; + + rcng_client_hardware_init_info_ui(hwe ? hwe->hw : NULL); +} + +void rcng_client_hardware_list_update_status(gchar *status) +{ + gtk_label_set_text(GTK_LABEL(status_msg), status); +} + +void rcng_client_hardware_list_init_ui() +{ + stack = gtk_stack_new(); + gtk_widget_set_margin_start(stack, 12); + gtk_widget_set_margin_end(stack, 12); + gtk_widget_set_margin_top(stack, 12); + gtk_widget_set_margin_bottom(stack, 12); + gtk_stack_set_transition_type(GTK_STACK(stack), GTK_STACK_TRANSITION_TYPE_CROSSFADE); + + status_msg = gtk_label_new("Connecting to server..."); + gtk_stack_add_named(GTK_STACK(stack), status_msg, "nohw"); + gtk_stack_set_visible_child(GTK_STACK(stack), status_msg); + + hw_list_box = gtk_list_box_new(); + gtk_stack_add_named(GTK_STACK(stack), hw_list_box, "yeshw"); + g_signal_connect(hw_list_box, "row-selected", G_CALLBACK(on_hw_selected), NULL); + + gtk_notebook_append_page(global->notebook, stack, gtk_label_new("Hardware")); +} + + diff --git a/rcm-client-hardware-list.h b/rcm-client-hardware-list.h new file mode 100644 index 0000000..47314e0 --- /dev/null +++ b/rcm-client-hardware-list.h @@ -0,0 +1,6 @@ + +void rcng_client_hardware_list_remove(GDBusObject *); +void rcng_client_hardware_list_add(GDBusObject *); +void rcng_client_hardware_list_init_ui(); +void rcng_client_hardware_list_update_status(gchar *); + diff --git a/rcm-client-main.c b/rcm-client-main.c new file mode 100644 index 0000000..cd119a3 --- /dev/null +++ b/rcm-client-main.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include + +#include "generated.h" +#include "rcm-client-main.h" +#include "rcm-client-hardware-list.h" + +#define WINDOW_WIDTH 300 +#define WINDOW_HEIGHT 300 + +static GDBusObjectManager *mgr = NULL; + +struct global_variables *global; + +void +poke_objects() +{ + GList *objects; + GList *l; + GDBusObjectManager *manager = mgr; + + objects = g_dbus_object_manager_get_objects (manager); + for (l = objects; l != NULL; l = l->next) + { + GDBusInterface *interface; + + interface = g_dbus_object_get_interface(G_DBUS_OBJECT(l->data), + "org.gnome.RemoteControlManager.Device"); + if (!interface) { + g_print("That's weird, an object which is not a device...\n"); + continue; + } + + RCDevice *object = RCDEVICE(interface); + gchar *reply = NULL; + rcdevice_call_echo_string_sync(object, "Roeven", &reply, NULL, NULL); + printf("Called object %s: %s\n", g_dbus_object_get_object_path (G_DBUS_OBJECT(l->data)), reply); + printf("Driver name is: %s\n", rcdevice_get_driver_name(object)); + printf("Keymap name is: %s\n", rcdevice_get_kernel_keymap_name(object)); + g_free(reply); + + g_object_unref(interface); + } + g_list_free_full (objects, g_object_unref); +} + +void +poke_objects2() +{ + GList *objects; + GList *l; + GDBusObjectManager *manager = mgr; + + objects = g_dbus_object_manager_get_objects (manager); + for (l = objects; l != NULL; l = l->next) + { + GDBusInterface *interface; + + interface = g_dbus_object_get_interface(G_DBUS_OBJECT(l->data), + "org.gnome.RemoteControlManager.IRDevice"); + if (!interface) { + g_print("That's weird, an object which is not an ir device...\n"); + continue; + } + + RCIRDevice *object = RCIRDEVICE(interface); + GVariant *reply = NULL; + rcirdevice_call_get_irrxparameters_sync(object, &reply, NULL, NULL); + + printf("Got a reply %p\n", reply); + gchar *ans = NULL; + + g_variant_lookup(reply, "name", "s", &ans); + printf("The rsult is %s\n", ans); +/* + printf("Called object %s: %s\n", g_dbus_object_get_object_path (G_DBUS_OBJECT(l->data)), reply); + printf("Driver name is: %s\n", rcdevice_get_driver_name(object)); + printf("Keymap name is: %s\n", rcdevice_get_kernel_keymap_name(object)); + */ + //g_free(reply); + + g_object_unref(interface); + } + g_list_free_full (objects, g_object_unref); +} + +static void +on_object_added(GDBusObjectManager *manager, + GDBusObject *object, + gpointer user_data) +{ + g_print("Added object at %s\n", g_dbus_object_get_object_path(object)); + rcng_client_hardware_list_add(object); +} + +static void +on_object_removed(GDBusObjectManager *manager, + GDBusObject *object, + gpointer user_data) +{ + g_print("Removed object at %s\n", g_dbus_object_get_object_path(object)); + rcng_client_hardware_list_remove(object); +} + +static void +on_owner_change(GDBusObjectManager *manager, gpointer user_data) +{ + g_print("Owner changed, now: %s\n", g_dbus_object_manager_client_get_name_owner(G_DBUS_OBJECT_MANAGER_CLIENT(manager))); + + if (!g_dbus_object_manager_client_get_name_owner(G_DBUS_OBJECT_MANAGER_CLIENT(manager))) + rcng_client_hardware_list_update_status("Server not running...\n"); + else + rcng_client_hardware_list_update_status("No hardware connected..."); +} + +static void +manager_ready_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GList *objects; + GList *l; + + mgr = object_manager_client_new_for_bus_finish(res, &error); + if (!mgr) { + gchar *msg; + + msg = g_strdup_printf("Error creating object manager client: %s", + error->message); + rcng_client_hardware_list_update_status(msg); + + g_free(msg); + g_error_free(error); + return; + } + + g_signal_connect(mgr, "object-added", G_CALLBACK(on_object_added), NULL); + g_signal_connect(mgr, "object-removed", G_CALLBACK(on_object_removed), NULL); + g_signal_connect(mgr, "notify::name-owner", G_CALLBACK(on_owner_change), NULL); + + on_owner_change(mgr, NULL); + g_print("Object manager at %s\n", g_dbus_object_manager_get_object_path(mgr)); + objects = g_dbus_object_manager_get_objects(mgr); + for (l = objects; l != NULL; l = l->next) { + rcng_client_hardware_list_add(G_DBUS_OBJECT(l->data)); + rcng_client_hardware_list_add(G_DBUS_OBJECT(l->data)); + } + + g_list_free_full (objects, g_object_unref); + +} + +int main (int argc, char *argv[]) +{ + GtkWidget *win; + GdkScreen *screen; + gint monitor; + GdkRectangle rect; + + global = g_malloc(sizeof(*global)); + + gtk_init (&argc, &argv); + + object_manager_client_new_for_bus(G_BUS_TYPE_SESSION, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, + "org.gnome.RemoteControlManager", + "/org/gnome/RemoteControlManager", + NULL, manager_ready_cb, NULL); + + win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + global->window = GTK_WINDOW(win); + g_signal_connect(win, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + screen = gtk_window_get_screen(global->window); + monitor = gdk_screen_get_monitor_at_point(screen, 0, 0); + gdk_screen_get_monitor_geometry(screen, monitor, &rect); + gtk_window_set_default_size(global->window, + rect.width * 4 / 5, + rect.height * 1 / 2); + + global->header = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_header_bar_set_title(global->header, "Remote Control Configuration"); + gtk_header_bar_set_has_subtitle(global->header, FALSE); + gtk_header_bar_set_show_close_button(global->header, TRUE); + gtk_window_set_titlebar(global->window, GTK_WIDGET(global->header)); + + /* + GtkWidget *label; + label = gtk_label_new("Pack Start"); + gtk_header_bar_pack_start(GTK_HEADER_BAR(header), label); + label = gtk_label_new("Pack End"); + gtk_header_bar_pack_end(GTK_HEADER_BAR(header), label); + GtkWidget *test = gtk_button_new_from_icon_name("gtk-add", GTK_ICON_SIZE_BUTTON); + gtk_button_set_label(GTK_BUTTON(test), "Test"); + gtk_button_set_always_show_image(GTK_BUTTON(test), TRUE); + gtk_header_bar_pack_end(GTK_HEADER_BAR(header), test); + */ + + + global->notebook = GTK_NOTEBOOK(gtk_notebook_new()); + gtk_notebook_set_tab_pos(global->notebook, GTK_POS_LEFT); + + rcng_client_hardware_list_init_ui(global->notebook); + + gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(global->notebook)); + //gtk_window_set_title(window, "Remote Control Configuration"); + gtk_window_set_icon_name(global->window, "gnome-multimedia"); + gtk_widget_show_all(win); + + gtk_main(); + + return 0; +} diff --git a/rcm-client-main.h b/rcm-client-main.h new file mode 100644 index 0000000..d27fb24 --- /dev/null +++ b/rcm-client-main.h @@ -0,0 +1,10 @@ +void poke_objects(); +void poke_objects2(); + +struct global_variables { + GtkWindow *window; + GtkHeaderBar *header; + GtkNotebook *notebook; +}; + +extern struct global_variables *global; diff --git a/rcm-client-receive.c b/rcm-client-receive.c new file mode 100644 index 0000000..8abc64a --- /dev/null +++ b/rcm-client-receive.c @@ -0,0 +1,612 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "generated.h" +#include "rcm-client-main.h" +#include "rcm-client-receive.h" + +#define WINDOW_WIDTH 300 +#define WINDOW_HEIGHT 300 + +struct remote { + GList *buttons; + guint width; + guint height; + struct rcbutton *hover; +}; + +struct rcbutton { + char *name; + bool clicked; + guint x; + guint y; + guint row; + guint col; + guint rows; + guint cols; + guint width; + guint height; + guint padding; + guint corner_radius; + struct rcbutton *next; + GdkRGBA *color; + void (*on_hover)(struct rcbutton *rcb, GtkWidget *widget, bool hover); +}; + +static struct remote *remote = NULL; + +static void +curve_rectangle(cairo_t * cr, gdouble x0, gdouble y0, + gdouble width, gdouble height, gdouble radius) +{ + gdouble x1, y1; + + if (!width || !height) + return; + + x1 = x0 + width; + y1 = y0 + height; + + radius = MIN (radius, MIN (width / 2, height / 2)); + + cairo_move_to (cr, x0, y0 + radius); + cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, + 3 * M_PI / 2); + cairo_line_to (cr, x1 - radius, y0); + cairo_arc (cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2, + 2 * M_PI); + cairo_line_to (cr, x1, y1 - radius); + cairo_arc (cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2); + cairo_line_to (cr, x0 + radius, y1); + cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI); + + cairo_close_path (cr); +} + +GdkRGBA *c; +GdkRGBA *cd; +GdkRGBA *cre; +GdkRGBA *cb; +GdkRGBA cgreen; +GdkRGBA cred; + +static void +draw_curve_rectangle(cairo_t * cr, struct rcbutton *rcb) +{ + double tx, ty; + cairo_text_extents_t extents; + const char *label = rcb->name ? rcb->name : "?"; + + curve_rectangle(cr, rcb->x, rcb->y, + rcb->width, rcb->height, rcb->corner_radius); + + if (rcb->color) + gdk_cairo_set_source_rgba(cr, rcb->color); + else + gdk_cairo_set_source_rgba(cr, rcb->clicked ? cre : cd); + cairo_fill_preserve(cr); + + gdk_cairo_set_source_rgba(cr, cb); + cairo_set_line_width(cr, 1.0); + cairo_stroke(cr); + /* + if (filled) + cairo_fill(cr); + else { + cairo_set_line_width(cr, 1.0); + cairo_stroke(cr); + } + */ + + cairo_save(cr); + cairo_rectangle(cr, + rcb->x + rcb->padding, + rcb->y + rcb->padding, + rcb->width - rcb->padding * 2, + rcb->height - rcb->padding * 2); + cairo_clip(cr); + cairo_set_font_size(cr, 13); + cairo_text_extents (cr, label, &extents); + tx = rcb->x + (rcb->width / 2) - (extents.width / 2 + extents.x_bearing); + ty = rcb->y + (rcb->height / 2) - (extents.height / 2 + extents.y_bearing); + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_move_to(cr, tx, ty); + cairo_show_text(cr, label); + cairo_restore(cr); + cairo_new_sub_path(cr); +} + +#define SPACING 5 +#define PADDING 5 +#define BW 56 +#define BH 56 + +static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) +{ + struct rcbutton *rcb; + guint w = 0, h = 0; + + /* Set color for background */ + gdk_cairo_set_source_rgba(cr, c); + + /* fill in the background color*/ + cairo_paint(cr); + + GList *l; + + for (l = remote->buttons; l; l = l->next) { + rcb = l->data; + + draw_curve_rectangle(cr, rcb); + + if (rcb->x + rcb->width > w) + w = rcb->x + rcb->width; + + if (rcb->y + rcb->height > h) + h = rcb->y + rcb->height; + } + + w += (SPACING + BW) / 2; + h += (SPACING + BH) / 2; + + /*->name ? rcb->name : "?", false, + rcb->clicked ? cre : cd, + rcb->x, rcb->y, rcb->width, rcb->height, + rcb->padding, rcb->corner_radius); +*/ + gtk_widget_set_size_request(widget, w, h); + gtk_widget_set_halign(widget, GTK_ALIGN_CENTER); + gtk_widget_set_valign(widget, GTK_ALIGN_CENTER); + gtk_widget_set_margin_top(widget, BH / 2); + gtk_widget_set_margin_bottom(widget, BH / 2); + gtk_widget_set_margin_start(widget, BW / 2); + gtk_widget_set_margin_end(widget, BW / 2); + + + return FALSE; +} + +#if 0 +static struct rcbutton *new_button(const char *name, guint row, guint col) +{ + struct rcbutton *rcb; + + rcb = g_malloc(sizeof(*rcb)); + rcb->name = strdup(name); + rcb->clicked = false; + rcb->x = (SPACING + BW) * (col) + (SPACING + BW) / 2; + rcb->y = (SPACING + BH) * (row) + (SPACING + BH) / 2; + rcb->width = BW; + rcb->height = BH; + rcb->padding = PADDING; + rcb->corner_radius = 3; + rcb->color = NULL; + return rcb; +} +#endif + +static void +button_calculate_position(struct rcbutton *rcb) +{ + rcb->x = (SPACING + BW) * (rcb->col) + (SPACING + BW) / 2; + rcb->y = (SPACING + BH) * (rcb->row) + (SPACING + BH) / 2; + rcb->width = BW + (rcb->cols - 1) * (BW + SPACING); + rcb->height = BH + (rcb->rows - 1) * (BH + SPACING); +} + +static void +move_buttons(gint row, gint col) +{ + GList *l; + + for (l = remote->buttons; l; l = l->next) { + struct rcbutton *rcb = l->data; + + rcb->row += row; + rcb->col += col; + button_calculate_position(rcb); + } +} + +static struct rcbutton * +new_button_add(const char *name, GdkRGBA *color, + guint x, guint y, guint w, guint h) +{ + struct rcbutton *rcb; + + rcb = g_malloc0(sizeof(*rcb)); + rcb->name = strdup(name); + rcb->clicked = false; + rcb->col = x; + rcb->row = y; + rcb->cols = w; + rcb->rows = h; + button_calculate_position(rcb); + rcb->padding = PADDING; + rcb->corner_radius = 3; + rcb->color = color; + remote->buttons = g_list_append(remote->buttons, rcb); + remote->width = MAX(remote->width, w); + remote->height = MAX(remote->height, h); + return rcb; +} + +#if 0 +static struct rcbutton *new_button_addr(const char *name, guint row, guint col) +{ + struct rcbutton *rcb; + + rcb = g_malloc(sizeof(*rcb)); + rcb->name = strdup(name); + rcb->clicked = false; + rcb->x = (SPACING + BW) / 2; + rcb->y = (SPACING + BH) / 2; + rcb->width = (SPACING + BW) * (col) - SPACING; + rcb->height = BH; + rcb->padding = PADDING; + rcb->corner_radius = 3; + rcb->color = &cred; + return rcb; +} +#endif +static void +button_redraw(struct rcbutton *rcb, GtkWidget *widget) +{ + printf("Asked to redraw: X,Y,W,H - %u,%u,%u,%u\n", + rcb->x - 1, rcb->y - 1, rcb->width + 2, rcb->height + 2); + gtk_widget_queue_draw_area(widget, rcb->x - 1, rcb->y - 1, + rcb->width + 2, rcb->height + 2); +} + +static gboolean +button_press_event_cb(GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + struct rcbutton *rcb; + GList *l; + char buf[1024]; + + if (event->button != GDK_BUTTON_PRIMARY) + return true; + + for (l = remote->buttons; l; l = l->next) { + rcb = l->data; + + if (event->x < rcb->x || event->x > (rcb->x + rcb->width)) + continue; + + if (event->y < rcb->y || event->y > (rcb->y + rcb->height)) + continue; + + rcb->clicked = true; + button_redraw(rcb, widget); + sprintf(buf, "Button at %ux%u clicked\n", rcb->x, rcb->y); + poke_objects(); + poke_objects2(); + } + + return true; +} + +static gboolean +button_release_event_cb(GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + struct rcbutton *rcb; + GList *l; + + if (event->button != GDK_BUTTON_PRIMARY) + return true; + + for (l = remote->buttons; l; l = l->next) { + rcb = l->data; + + if (!rcb->clicked) + continue; + + rcb->clicked = false; + + button_redraw(rcb, widget); + } + + return true; +} + +static gboolean +motion_notify_event_cb (GtkWidget *widget, + GdkEventMotion *event, + gpointer data) +{ + struct rcbutton *rcb; + static GdkCursor *cursor = NULL; + GdkWindow* win = gtk_widget_get_parent_window(widget); + GList *l; + + if (!cursor) + cursor = gdk_cursor_new_for_display(gdk_window_get_display(win), GDK_HAND1); + + for (l = remote->buttons; l; l = l->next) { + rcb = l->data; + + if (event->x < rcb->x || event->x > (rcb->x + rcb->width)) + continue; + + if (event->y < rcb->y || event->y > (rcb->y + rcb->height)) + continue; + + break; + } + + if (!l) + rcb = NULL; + + if (remote->hover == rcb) + return true; + + gdk_window_set_cursor(win, rcb ? cursor : NULL); + + if (remote->hover && remote->hover->on_hover) { + remote->hover->on_hover(remote->hover, widget, false); + remote->hover = NULL; + } + + if (rcb && rcb->on_hover) { + rcb->on_hover(rcb, widget, true); + remote->hover = rcb; + } + + return true; +} + +static GtkWidget *scrollda = NULL; + +void rcng_client_receive_destroy_ui() +{ + if (scrollda) + gtk_widget_destroy(scrollda); + + scrollda = NULL; +} + +static gint own_page_num = -1; +static GtkWidget *header_button = NULL; +static GtkWidget *da; + +#if 0 +static void +edit_keymap_done(GtkButton *button, gpointer user_data) +{ + +} +#endif +static void +on_hover_delete(struct rcbutton *rcb, GtkWidget *widget, bool hover) +{ + if (hover) { + if (rcb->col == 0 && rcb->cols == 1) { + rcb->cols = 2 + remote->width; + button_calculate_position(rcb); + button_redraw(rcb, widget); + } else if (rcb->row == 0 && rcb->rows == 1) { + rcb->rows = 2 + remote->height; + button_calculate_position(rcb); + button_redraw(rcb, widget); + } + } else { + if (rcb->col == 0 && rcb->cols != 1) { + button_redraw(rcb, widget); + rcb->cols = 1; + button_calculate_position(rcb); + } else if (rcb->row == 0 && rcb->rows != 1) { + button_redraw(rcb, widget); + rcb->rows = 1; + button_calculate_position(rcb); + } + } + +} + +static void +edit_keymap(GtkButton *button, gpointer user_data) +{ + guint i; + gboolean *do_edit = user_data; + struct rcbutton *rcb; + + g_print("Button clicked\n"); + g_print("Remote width: %u x %u\n", remote->width, remote->height); + if (remote->width < 1 || remote->height < 1) + return; + + if (!*do_edit) { + move_buttons(2, 2); + new_button_add("+", &cgreen, 2, 1, remote->width, 1); + new_button_add("+", &cgreen, 2, 2 + remote->height, remote->width, 1); + new_button_add("+", &cgreen, 1, 2, 1, remote->height); + new_button_add("+", &cgreen, 2 + remote->width, 2, 1, remote->height); + + for (i = 0; i < remote->height; i++) { + rcb = new_button_add("-", &cred, 0, 2 + i, 1, 1); + rcb->on_hover = on_hover_delete; + } + + for (i = 0; i < remote->width; i++) { + rcb = new_button_add("-", &cred, 2 + i, 0, 1, 1); + rcb->on_hover = on_hover_delete; + } + + /* + new_button_add("+", &cgreen, 5, 2, 1, 7); + new_button_add("+", &cgreen, 2, 4, 1, 1); + new_button_add("+", &cgreen, 2, 4, 10, 10); + new_button_add("+", &cgreen, 2, 4, 10, 10); + new_button_add("-", &cred, 2, 2, 0, 0); + new_button_add("Del", &cred, 3, 3, 0, 0); + */ + + gtk_widget_queue_draw(da); + *do_edit = true; + } else { + GList *l = remote->buttons; + + while (l) { + GList *next = l->next; + struct rcbutton *rcb = l->data; + + if (rcb->color) { + g_free(rcb); + remote->buttons = g_list_delete_link (remote->buttons, l); + } + + l = next; + } + move_buttons(-2, -2); + gtk_widget_queue_draw(da); + *do_edit = false; + + } +} + +static void +on_notebook_page_change(GtkNotebook *notebook, GtkWidget *page, guint new_page_num, + gpointer user_data) +{ + static gboolean do_edit = false; + + if (new_page_num != own_page_num) { + if (header_button) { + gtk_widget_destroy(header_button); + header_button = NULL; + do_edit = false; + } + return; + } + + GtkWidget *test = gtk_button_new_from_icon_name("gtk-add", GTK_ICON_SIZE_BUTTON); + gtk_button_set_label(GTK_BUTTON(test), "Edit Keymap"); + gtk_button_set_always_show_image(GTK_BUTTON(test), TRUE); + g_signal_connect(test, "clicked", G_CALLBACK(edit_keymap), &do_edit); + gtk_widget_show_all(test); + gtk_header_bar_pack_end(GTK_HEADER_BAR(global->header), test); + header_button = test; + g_print("Page change: %i -> %u\n", own_page_num, new_page_num); +} + +void rcng_client_receive_init_ui(GDBusObject *new_hw) +{ + GtkStateFlags state; + GtkStyleContext *style_context; + static bool first = true; + + if (first) { + g_signal_connect(global->notebook, "switch-page", G_CALLBACK(on_notebook_page_change), NULL); + first = false; + } + + rcng_client_receive_destroy_ui(); + + GDBusInterface *interface; + interface = g_dbus_object_get_interface(new_hw, "org.gnome.RemoteControlManager.Device"); + if (!interface) + return; + + /* FIXME: if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a(uuuuaa{sv}))"))) */ + + gchar **keymaps = NULL; + RCDevice *object = RCDEVICE(interface); + rcdevice_call_list_keymaps_sync(object, &keymaps, NULL, NULL); + g_print("I should look at keymap: %s\n", keymaps[0]); + + guint16 km_width; + guint16 km_height; + GVariant *km_entries = NULL; + rcdevice_call_get_keymap_sync(object, keymaps[0], &km_width, &km_height, + &km_entries, NULL, NULL); + + g_free(keymaps); + remote = g_malloc0(sizeof(*remote)); + remote->width = km_width; + remote->height = km_height; + + g_print("type of keymaps is %s\n", g_variant_get_type_string(km_entries)); + GVariantIter iter; + gsize n_items; + GVariant *item; + + style_context = gtk_widget_get_style_context(GTK_WIDGET(global->window)); + state = gtk_widget_get_state_flags(GTK_WIDGET(global->window)); + gtk_style_context_get(style_context, state, "background-color", &c, NULL); + + cd = gdk_rgba_copy(c); + cd->red *= 0.7; + cd->green *= 0.7; + cd->blue *= 0.7; + + cre = gdk_rgba_copy(c); + cre->red *= 2.0; + + cb = gdk_rgba_copy(c); + cb->red = 0.0; + cb->green = 0.0; + cb->blue = 0.0; + cb->alpha = 1.0; + + gdk_rgba_parse(&cgreen, "#a9b68f"); + gdk_rgba_parse(&cred, "#cf8989"); + cred.alpha = 0.8; + + n_items = g_variant_iter_init(&iter, km_entries); + g_print("Key items: %zu\n", n_items); + guint row = 0; + guint col = 0; + + while (g_variant_iter_loop (&iter, "@a{sv}", &item)) { + gchar *protocol; + guint64 scancode; + gchar *keycode; + + g_variant_lookup(item, "protocol", "s", &protocol); + g_variant_lookup(item, "scancode", "t", &scancode); + g_variant_lookup(item, "keycode", "s", &keycode); + + new_button_add(keycode, NULL, col, row, 1, 1); + + col++; + if (col >= km_width) { + col = 0; + row++; + } + + printf("Got a key: %s:0x%08" PRIx64 ":%s\n", protocol, scancode, keycode); + } + + da = gtk_drawing_area_new(); +// gtk_widget_set_size_request (da, WINDOW_WIDTH, WINDOW_HEIGHT); + g_signal_connect (da, "draw", G_CALLBACK(draw_cb), NULL); + + g_signal_connect(da, "button-press-event", + G_CALLBACK (button_press_event_cb), NULL); + + g_signal_connect(da, "button-release-event", + G_CALLBACK (button_release_event_cb), NULL); + + g_signal_connect(da, "motion-notify-event", + G_CALLBACK (motion_notify_event_cb), NULL); + + gtk_widget_set_events (da, gtk_widget_get_events (da) + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); + + scrollda = gtk_scrolled_window_new(NULL, NULL); + + gtk_container_add(GTK_CONTAINER(scrollda), da); + gtk_widget_show_all(scrollda); + own_page_num = gtk_notebook_append_page(global->notebook, scrollda, gtk_label_new("Receive")); +} + diff --git a/rcm-client-receive.h b/rcm-client-receive.h new file mode 100644 index 0000000..19adad0 --- /dev/null +++ b/rcm-client-receive.h @@ -0,0 +1,4 @@ + +void rcng_client_receive_destroy_ui(); +void rcng_client_receive_init_ui(GDBusObject *new_hw); + diff --git a/rcm-client-transmit.c b/rcm-client-transmit.c new file mode 100644 index 0000000..62b0a7f --- /dev/null +++ b/rcm-client-transmit.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include + +#include "generated.h" +#include "rcm-client-main.h" +#include "rcm-client-transmit.h" + +static GtkWidget *label = NULL; + +void rcng_client_transmit_destroy_ui() +{ + if (label) + gtk_widget_destroy(label); + + label = NULL; +} + +void rcng_client_transmit_init_ui() +{ + GtkWidget *label; + + rcng_client_transmit_destroy_ui(); + label = gtk_label_new("Transmitting"); + gtk_widget_show_all(label); + gtk_notebook_append_page(global->notebook, label, gtk_label_new("Transmit")); +} + diff --git a/rcm-client-transmit.h b/rcm-client-transmit.h new file mode 100644 index 0000000..92b3786 --- /dev/null +++ b/rcm-client-transmit.h @@ -0,0 +1,4 @@ + +void rcng_client_transmit_destroy_ui(); +void rcng_client_transmit_init_ui(); + diff --git a/rcm-server-keymap.c b/rcm-server-keymap.c index d0f772e..39b4440 100644 --- a/rcm-server-keymap.c +++ b/rcm-server-keymap.c @@ -14,7 +14,7 @@ #include #include "utils.h" -#include "rcm-server.h" +#include "rcm-server-main.h" #include "rcm-server-keymap.h" enum ini_section { @@ -63,6 +63,33 @@ static int strtol_strict(const char *str, int *result) return 0; } +static int strtoull_strict(const char *str, uint64_t *result) +{ + char *end; + unsigned long long val; + + errno = 0; + val = strtoull(str, &end, 16); + + if (errno == ERANGE && (val == ULLONG_MAX || val == 0)) + return -EINVAL; + + if (errno != 0 && val == 0) + return -EINVAL; + + if (end == str) + return -EINVAL; + + if (*end != '\0') + return -EINVAL; + + if (val > UINT64_MAX) + return -EINVAL; + + *result = val; + return 0; +} + static int keymap_parse(FILE *fp, char **line, size_t *buf_size, struct keymap *keymap, uint16_t *rows_return, uint16_t *cols_return, @@ -142,9 +169,37 @@ keymap_parse(FILE *fp, char **line, size_t *buf_size, struct keymap *keymap, break; case INI_SECTION_KEYMAP: if (!strcasecmp(p, "Map")) { + char *protocol; + char *scanstr; + char *keycode; + char *end; + uint64_t scancode; + + printf("Map %s\n", tmp); + protocol = strtok(tmp, " :"); + scanstr = strtok(NULL, " :"); + keycode = strtok(NULL, " :"); + end = strtok(NULL, " :"); + + if (!protocol || !scancode || !keycode || end) { + fprintf(stderr, "Invalid map directive\n"); + return -ENOMEM; + } + + r = strtoull_strict(scanstr, &scancode); + if (r < 0) { + fprintf(stderr, "Invalid scancode value\n"); + return r; + } + + printf("Map means protocol %s scancode 0x%08" PRIx64 " keycode %s\n", + protocol, scancode, keycode); + if (keymap) { - keymap->keycodes[keycode_count].name = "apan"; - keymap->keycodes[keycode_count].value = "papan"; + /* FIXME: leaks */ + keymap->keycodes[keycode_count].protocol = strdup(protocol); + keymap->keycodes[keycode_count].scancode = scancode; + keymap->keycodes[keycode_count].keycode = strdup(keycode); } keycode_count++; } else { diff --git a/rcm-server-keymap.h b/rcm-server-keymap.h index 6ece017..8676fbc 100644 --- a/rcm-server-keymap.h +++ b/rcm-server-keymap.h @@ -2,8 +2,9 @@ #define foorcmserverkeymaphfoo struct keycode { - char *name; - char *value; + char *protocol; + uint64_t scancode; + char *keycode; }; struct keymap { diff --git a/rcm-server-main.c b/rcm-server-main.c new file mode 100644 index 0000000..02387a1 --- /dev/null +++ b/rcm-server-main.c @@ -0,0 +1,564 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "rcm-server-main.h" +#include "rcm-server-keymap.h" + +static int +method_echostring(sd_bus_message *m, void *userdata, sd_bus_error *error) +{ + const char *msg; + int r; + + r = sd_bus_message_read(m, "s", &msg); + if (r < 0) { + fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r)); + return sd_bus_error_set_errno(error, r); + } + + return sd_bus_reply_method_return(m, "s", msg); +} + +static struct device * +find_device_by_path(struct manager *mgr, const char *path) +{ + struct device *dev; + + list_for_each_entry(dev, &mgr->devices, list) + if (!strcmp(dev->path, path)) + return dev; + + return NULL; +} + +static int +property_get_driver_name(sd_bus *bus, const char *path, const char *interface, + const char *property, sd_bus_message *reply, void *userdata, + sd_bus_error *error) +{ + struct manager *mgr = userdata; + struct device *dev; + + dev = find_device_by_path(mgr, path); + if (!dev) { + sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); + return -EINVAL; + } + + if (!strcmp(property, "DriverName")) + return sd_bus_message_append(reply, "s", dev->driver_name); + else if (!strcmp(property, "KernelKeymapName")) + return sd_bus_message_append(reply, "s", dev->keymap_name); + + sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidProperty", "Sorry, invalid property"); + return -EINVAL; +} + + +static int +method_listkeymaps(sd_bus_message *m, void *userdata, sd_bus_error *error) +{ + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + struct manager *mgr = userdata; + struct device *dev; + struct keymap *keymap; + int r; + + dev = find_device_by_path(mgr, sd_bus_message_get_path(m)); + if (!dev) { + sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); + return -EINVAL; + } + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + goto out; + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + goto out; + + list_for_each_entry(keymap, &dev->keymaps, list) { + printf("Listing keymaps for %s: %s\n", dev->name, keymap->name); + r = sd_bus_message_append(reply, "s", keymap->name); + if (r < 0) + goto out; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto out; + + r = sd_bus_send(NULL, reply, NULL); + if (r < 0) + goto out; + + return 1; + +out: + return sd_bus_error_set_errno(error, r); +} + +static int +method_getkeymap(sd_bus_message *m, void *userdata, sd_bus_error *error) +{ + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + struct manager *mgr = userdata; + struct device *dev; + struct keymap *keymap; + const char *name; + int r; + unsigned i; + + dev = find_device_by_path(mgr, sd_bus_message_get_path(m)); + if (!dev) { + sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); + return -EINVAL; + } + + r = sd_bus_message_read(m, "s", &name); + if (r < 0) { + fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r)); + return r; + } + + keymap = find_keymap_by_name(dev, name); + if (!keymap) { + sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidKeymap", "Sorry, unknown keymap"); + return -EINVAL; + } + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + goto out; + + r = sd_bus_message_append(reply, "q", keymap->cols); + if (r < 0) + goto out; + + r = sd_bus_message_append(reply, "q", keymap->rows); + if (r < 0) + goto out; + + r = sd_bus_message_open_container(reply, 'a', "a{sv}"); + if (r < 0) + goto out; + + for (i = 0; i < (keymap->rows * keymap->cols); i++) { + r = sd_bus_message_append(reply, "a{sv}", 3, + "protocol", "s", keymap->layout[i]->protocol, + "scancode", "t", keymap->layout[i]->scancode, + "keycode", "s", keymap->layout[i]->keycode); + if (r < 0) + goto out; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto out; + + r = sd_bus_send(NULL, reply, NULL); + if (r < 0) + goto out; + + return 1; + +out: + return sd_bus_error_set_errno(error, r); +} + +static const sd_bus_vtable device_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("DriverName", "s", property_get_driver_name, 0, 0), + SD_BUS_PROPERTY("KernelKeymapName", "s", property_get_driver_name, 0, 0), + SD_BUS_METHOD("EchoString", "s", "s", method_echostring, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListKeymaps", NULL, "as", method_listkeymaps, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetKeymap", "s", "qqaa{sv}", method_getkeymap, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +static int +my_bus_emit_object_changed(sd_bus *bus, const char *path, bool added) +{ + int r; + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + + printf("Sending signal %s for path %s\n", + added ? "InterfacesAdded" : "InterfacesRemoved", + path); + + r = sd_bus_message_new_signal(bus, &m, "/org/gnome/RemoteControlManager", + "org.freedesktop.DBus.ObjectManager", + added ? "InterfacesAdded" : "InterfacesRemoved"); + if (r < 0) + return r; + + r = sd_bus_message_append_basic(m, 'o', path); + if (r < 0) + return r; + + if (added) { + r = sd_bus_message_open_container(m, 'a', "{sa{sv}}"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "{sa{sv}}", "org.gnome.RemoteControlManager.Device", 0); + if (r < 0) + return r; + } else { + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", "org.gnome.RemoteControlManager.Device"); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_send(bus, m, NULL); + return r; +} + +static void +remove_device(struct manager *mgr, struct udev_device *udev) +{ + const char *name; + struct device *device; + + name = udev_device_get_sysname(udev); + printf("Asked to remove device %s\n", name); + + list_for_each_entry(device, &mgr->devices, list) { + if (strcmp(device->name, name)) + continue; + list_del(&device->list); + my_bus_emit_object_changed(mgr->bus, device->path, false); + mgr->num_devices--; + break; + } +} + +static void +add_device(struct manager *mgr, struct udev_device *udev) +{ + const char *name; + const char *str; + char *path; + struct device *device; + + name = udev_device_get_sysname(udev); + if (asprintf(&path, "/org/gnome/RemoteControlManager/%s", name) < 0) { + fprintf(stderr, "asprintf failed: %m\n"); + return; + } + + device = malloc(sizeof(*device)); + if (!device) { + fprintf(stderr, "malloc failed: %m\n"); + free(path); + return; + } + + list_init(&device->keymaps); + device->path = path; + device->name = device->path + strlen("/org/gnome/RemoteControlManager/"); + + if (keymaps_load(device) < 0) { + fprintf(stderr, "failed to load keymaps: %m\n"); + free(path); + free(device); + } + + str = udev_device_get_sysattr_value(udev, "uevent"); + if (str) { + char tmp[strlen(str) + 1]; + char *token; + + strcpy(tmp, str); + + for (token = strtok(tmp, "\n"); token; token = strtok(NULL, "\n")) { + if (!strncmp(token, "DRV_NAME=", strlen("DRV_NAME="))) + device->driver_name = strdup(token + strlen("DRV_NAME=")); + else if (!strncmp(token, "NAME=", strlen("NAME="))) + device->keymap_name = strdup(token + strlen("NAME=")); + else + printf("Unused uevent: %s\n", token); + } + } + + printf("Adding Device Object\n"); + printf(" Path : %s\n", udev_device_get_syspath(udev)); + printf(" Node : %s\n", udev_device_get_devnode(udev)); + printf(" Subsystem : %s\n", udev_device_get_subsystem(udev)); + printf(" Devtype : %s\n", udev_device_get_devtype(udev)); + printf(" Action : %s\n", udev_device_get_action(udev)); + printf(" Protocols : %s\n", + udev_device_get_sysattr_value(udev, "protocols")); + printf(" Uevent : %s\n", + udev_device_get_sysattr_value(udev, "uevent")); + + list_add(&device->list, &mgr->devices); + mgr->num_devices++; + + my_bus_emit_object_changed(mgr->bus, path, true); +} + +static int +udev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) +{ + struct manager *mgr = userdata; + struct udev_device *dev; + + if (revents & EPOLLHUP) { + fprintf(stderr, "udev connection closed!\n"); + return 0; + } + + if (!(revents & EPOLLIN)) { + fprintf(stderr, "unexpected udev event: %" PRIu32 "\n", revents); + return 0; + } + + while ((dev = udev_monitor_receive_device(mgr->udev_mon))) { + printf("Read device: %s\n", udev_device_get_syspath(dev)); + if (!strcmp(udev_device_get_action(dev), "add")) + add_device(mgr, dev); + else if (!strcmp(udev_device_get_action(dev), "remove")) + remove_device(mgr, dev); + udev_device_unref(dev); + } + + return 1; +} + +static int +udev_setup(struct manager *mgr) +{ + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + + mgr->udev = udev_new(); + if (!mgr->udev) + return -ENOMEM; + + mgr->udev_mon = udev_monitor_new_from_netlink(mgr->udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(mgr->udev_mon, "rc", NULL); + udev_monitor_enable_receiving(mgr->udev_mon); + + enumerate = udev_enumerate_new(mgr->udev); + udev_enumerate_add_match_subsystem(enumerate, "rc"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + + path = udev_list_entry_get_name(dev_list_entry); + if (!path) { + printf("Failed to get udev name\n"); + continue; + } + + dev = udev_device_new_from_syspath(mgr->udev, path); + if (!dev) { + printf("Failed to create udev device\n"); + continue; + } + + add_device(mgr, dev); + + udev_device_unref(dev); + } + udev_enumerate_unref(enumerate); + + return sd_event_add_io(mgr->event, &mgr->udev_ev, + udev_monitor_get_fd(mgr->udev_mon), + EPOLLIN, udev_read, mgr); +} + +static int +enumerator(sd_bus *bus, const char *path, void *userdata, char ***retnodes, sd_bus_error *error) +{ + _cleanup_strv_free_ char **nodes = NULL; + struct manager *mgr = userdata; + struct device *device; + int i = 0; + + if (!path) + return 0; + + nodes = zmalloc((mgr->num_devices + 1) * sizeof(char *)); + if (!nodes) + return -ENOMEM; + + list_for_each_entry(device, &mgr->devices, list) { + nodes[i] = strdup(device->path); + if (!nodes[i]) + return -ENOMEM; + i++; + } + + nodes[i++] = NULL; + *retnodes = nodes; + nodes = NULL; + + return 1; +} + +static void +free_manager(struct manager *mgr) { + if (!mgr) + return; + + sd_event_source_unref(mgr->udev_ev); + sd_bus_detach_event(mgr->bus); + sd_event_unref(mgr->event); + udev_monitor_unref(mgr->udev_mon); + udev_unref(mgr->udev); + + while (!list_empty(&mgr->devices)) { + struct device *dev = list_first_entry(&mgr->devices, typeof(*dev), list); + list_del(&dev->list); + free(dev->path); + free(dev->driver_name); + free(dev->keymap_name); + + while (!list_empty(&dev->keymaps)) { + struct keymap *keymap = list_first_entry(&dev->keymaps, typeof(*keymap), list); + list_del(&keymap->list); + free(keymap->name); + free(keymap); + } + + free(dev); + } + free(mgr); +} + +static int +block_signals(void) +{ + sigset_t sigset; + int r; + + r = sigemptyset(&sigset); + if (r < 0) + return r; + + r = sigaddset(&sigset, SIGINT); + if (r < 0) + return r; + + r = sigaddset(&sigset, SIGTERM); + if (r < 0) + return r; + + return sigprocmask(SIG_BLOCK, &sigset, NULL); +} + +int +main(int argc, char **argv) +{ + int r; + struct manager *mgr; + _cleanup_bus_close_unref_ sd_bus *bus = NULL; + _cleanup_bus_slot_unref_ struct sd_bus_slot *vtable_slot = NULL; + _cleanup_bus_slot_unref_ struct sd_bus_slot *enumerator_slot = NULL; + _cleanup_bus_slot_unref_ struct sd_bus_slot *objm_slot = NULL; + _cleanup_event_source_unref_ sd_event_source *sigint_ev = NULL; + _cleanup_event_source_unref_ sd_event_source *sigterm_ev = NULL; + + mgr = zmalloc(sizeof(*mgr)); + if (!mgr) { + fprintf(stderr, "Failed to allocate memory: %m\n"); + goto finish; + } + list_init(&mgr->devices); + + r = sd_bus_open_user(&bus); + if (r < 0) { + fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r)); + goto finish; + } + mgr->bus = bus; + + r = sd_bus_request_name(mgr->bus, "org.gnome.RemoteControlManager", 0); + if (r < 0) { + fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r)); + goto finish; + } + + r = sd_bus_add_fallback_vtable(mgr->bus, &vtable_slot, "/org/gnome/RemoteControlManager", + "org.gnome.RemoteControlManager.Device", + device_vtable, NULL, mgr); + if (r < 0) { + fprintf(stderr, "Failed to add vtable: %s\n", strerror(-r)); + goto finish; + } + + r = sd_bus_add_node_enumerator(mgr->bus, &enumerator_slot, "/org/gnome/RemoteControlManager", enumerator, mgr); + if (r < 0) { + fprintf(stderr, "Failed to create node enumerator: %s\n", strerror(-r)); + goto finish; + } + + r = sd_bus_add_object_manager(mgr->bus, &objm_slot, "/org/gnome/RemoteControlManager"); + if (r < 0) { + fprintf(stderr, "Failed to create object manager: %s\n", strerror(-r)); + goto finish; + } + + r = sd_event_default(&mgr->event); + if (r < 0) { + fprintf(stderr, "Failed to create sd_event: %s\n", strerror(-r)); + goto finish; + } + + r = sd_bus_attach_event(mgr->bus, mgr->event, 0); + if (r < 0) { + fprintf(stderr, "Failed to attach bus to event loop: %s\n", strerror(-r)); + goto finish; + } + + r = udev_setup(mgr); + if (r < 0) { + fprintf(stderr, "Failed to setup udev monitoring: %s\n", strerror(-r)); + goto finish; + } + + r = block_signals(); + if (r < 0) { + fprintf(stderr, "Failed to block signals: %m\n"); + goto finish; + } + + sd_event_add_signal(mgr->event, &sigint_ev, SIGINT, NULL, NULL); + sd_event_add_signal(mgr->event, &sigterm_ev, SIGTERM, NULL, NULL); + + r = sd_event_loop(mgr->event); + if (r < 0) { + fprintf(stderr, "Event loop failed: %s\n", strerror(-r)); + goto finish; + } + + sd_event_get_exit_code(mgr->event, &r); + +finish: + free_manager(mgr); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + diff --git a/rcm-server-main.h b/rcm-server-main.h new file mode 100644 index 0000000..188ffab --- /dev/null +++ b/rcm-server-main.h @@ -0,0 +1,24 @@ +#ifndef foorcmserverhfoo +#define foorcmserverhfoo + +struct device { + char *name; + char *path; + char *driver_name; + char *keymap_name; + struct list_head list; + struct list_head keymaps; +}; + +struct manager { + sd_bus *bus; + sd_event *event; + struct udev *udev; + struct udev_monitor *udev_mon; + sd_event_source *udev_ev; + struct list_head devices; + unsigned num_devices; +}; + +#endif + diff --git a/rcm-server.c b/rcm-server.c deleted file mode 100644 index 11223b1..0000000 --- a/rcm-server.c +++ /dev/null @@ -1,563 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" -#include "rcm-server.h" -#include "rcm-server-keymap.h" - -static int -method_echostring(sd_bus_message *m, void *userdata, sd_bus_error *error) -{ - const char *msg; - int r; - - r = sd_bus_message_read(m, "s", &msg); - if (r < 0) { - fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r)); - return sd_bus_error_set_errno(error, r); - } - - return sd_bus_reply_method_return(m, "s", msg); -} - -static struct device * -find_device_by_path(struct manager *mgr, const char *path) -{ - struct device *dev; - - list_for_each_entry(dev, &mgr->devices, list) - if (!strcmp(dev->path, path)) - return dev; - - return NULL; -} - -static int -property_get_driver_name(sd_bus *bus, const char *path, const char *interface, - const char *property, sd_bus_message *reply, void *userdata, - sd_bus_error *error) -{ - struct manager *mgr = userdata; - struct device *dev; - - dev = find_device_by_path(mgr, path); - if (!dev) { - sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); - return -EINVAL; - } - - if (!strcmp(property, "DriverName")) - return sd_bus_message_append(reply, "s", dev->driver_name); - else if (!strcmp(property, "KernelKeymapName")) - return sd_bus_message_append(reply, "s", dev->keymap_name); - - sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidProperty", "Sorry, invalid property"); - return -EINVAL; -} - - -static int -method_listkeymaps(sd_bus_message *m, void *userdata, sd_bus_error *error) -{ - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - struct manager *mgr = userdata; - struct device *dev; - struct keymap *keymap; - int r; - - dev = find_device_by_path(mgr, sd_bus_message_get_path(m)); - if (!dev) { - sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); - return -EINVAL; - } - - r = sd_bus_message_new_method_return(m, &reply); - if (r < 0) - goto out; - - r = sd_bus_message_open_container(reply, 'a', "s"); - if (r < 0) - goto out; - - list_for_each_entry(keymap, &dev->keymaps, list) { - printf("Listing keymaps for %s: %s\n", dev->name, keymap->name); - r = sd_bus_message_append(reply, "s", keymap->name); - if (r < 0) - goto out; - } - - r = sd_bus_message_close_container(reply); - if (r < 0) - goto out; - - r = sd_bus_send(NULL, reply, NULL); - if (r < 0) - goto out; - - return 1; - -out: - return sd_bus_error_set_errno(error, r); -} - -static int -method_getkeymap(sd_bus_message *m, void *userdata, sd_bus_error *error) -{ - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - struct manager *mgr = userdata; - struct device *dev; - struct keymap *keymap; - const char *name; - int r; - unsigned i; - - dev = find_device_by_path(mgr, sd_bus_message_get_path(m)); - if (!dev) { - sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); - return -EINVAL; - } - - r = sd_bus_message_read(m, "s", &name); - if (r < 0) { - fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r)); - return r; - } - - keymap = find_keymap_by_name(dev, name); - if (!keymap) { - sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidKeymap", "Sorry, unknown keymap"); - return -EINVAL; - } - - r = sd_bus_message_new_method_return(m, &reply); - if (r < 0) - goto out; - - r = sd_bus_message_append(reply, "q", keymap->cols); - if (r < 0) - goto out; - - r = sd_bus_message_append(reply, "q", keymap->rows); - if (r < 0) - goto out; - - r = sd_bus_message_open_container(reply, 'a', "a{sv}"); - if (r < 0) - goto out; - - for (i = 0; i < (keymap->rows * keymap->cols); i++) { - r = sd_bus_message_append(reply, "a{sv}", 2, - "name", "s", keymap->layout[i]->name, - "keycode", "s", keymap->layout[i]->value); - if (r < 0) - goto out; - } - - r = sd_bus_message_close_container(reply); - if (r < 0) - goto out; - - r = sd_bus_send(NULL, reply, NULL); - if (r < 0) - goto out; - - return 1; - -out: - return sd_bus_error_set_errno(error, r); -} - -static const sd_bus_vtable device_vtable[] = { - SD_BUS_VTABLE_START(0), - SD_BUS_PROPERTY("DriverName", "s", property_get_driver_name, 0, 0), - SD_BUS_PROPERTY("KernelKeymapName", "s", property_get_driver_name, 0, 0), - SD_BUS_METHOD("EchoString", "s", "s", method_echostring, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("ListKeymaps", NULL, "as", method_listkeymaps, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetKeymap", "s", "qqaa{sv}", method_getkeymap, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_VTABLE_END -}; - -static int -my_bus_emit_object_changed(sd_bus *bus, const char *path, bool added) -{ - int r; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - - printf("Sending signal %s for path %s\n", - added ? "InterfacesAdded" : "InterfacesRemoved", - path); - - r = sd_bus_message_new_signal(bus, &m, "/org/gnome/RemoteControlManager", - "org.freedesktop.DBus.ObjectManager", - added ? "InterfacesAdded" : "InterfacesRemoved"); - if (r < 0) - return r; - - r = sd_bus_message_append_basic(m, 'o', path); - if (r < 0) - return r; - - if (added) { - r = sd_bus_message_open_container(m, 'a', "{sa{sv}}"); - if (r < 0) - return r; - - r = sd_bus_message_append(m, "{sa{sv}}", "org.gnome.RemoteControlManager.Device", 0); - if (r < 0) - return r; - } else { - r = sd_bus_message_open_container(m, 'a', "s"); - if (r < 0) - return r; - - r = sd_bus_message_append(m, "s", "org.gnome.RemoteControlManager.Device"); - if (r < 0) - return r; - } - - r = sd_bus_message_close_container(m); - if (r < 0) - return r; - - r = sd_bus_send(bus, m, NULL); - return r; -} - -static void -remove_device(struct manager *mgr, struct udev_device *udev) -{ - const char *name; - struct device *device; - - name = udev_device_get_sysname(udev); - printf("Asked to remove device %s\n", name); - - list_for_each_entry(device, &mgr->devices, list) { - if (strcmp(device->name, name)) - continue; - list_del(&device->list); - my_bus_emit_object_changed(mgr->bus, device->path, false); - mgr->num_devices--; - break; - } -} - -static void -add_device(struct manager *mgr, struct udev_device *udev) -{ - const char *name; - const char *str; - char *path; - struct device *device; - - name = udev_device_get_sysname(udev); - if (asprintf(&path, "/org/gnome/RemoteControlManager/%s", name) < 0) { - fprintf(stderr, "asprintf failed: %m\n"); - return; - } - - device = malloc(sizeof(*device)); - if (!device) { - fprintf(stderr, "malloc failed: %m\n"); - free(path); - return; - } - - list_init(&device->keymaps); - device->path = path; - device->name = device->path + strlen("/org/gnome/RemoteControlManager/"); - - if (keymaps_load(device) < 0) { - fprintf(stderr, "failed to load keymaps: %m\n"); - free(path); - free(device); - } - - str = udev_device_get_sysattr_value(udev, "uevent"); - if (str) { - char tmp[strlen(str) + 1]; - char *token; - - strcpy(tmp, str); - - for (token = strtok(tmp, "\n"); token; token = strtok(NULL, "\n")) { - if (!strncmp(token, "DRV_NAME=", strlen("DRV_NAME="))) - device->driver_name = strdup(token + strlen("DRV_NAME=")); - else if (!strncmp(token, "NAME=", strlen("NAME="))) - device->keymap_name = strdup(token + strlen("NAME=")); - else - printf("Unused uevent: %s\n", token); - } - } - - printf("Adding Device Object\n"); - printf(" Path : %s\n", udev_device_get_syspath(udev)); - printf(" Node : %s\n", udev_device_get_devnode(udev)); - printf(" Subsystem : %s\n", udev_device_get_subsystem(udev)); - printf(" Devtype : %s\n", udev_device_get_devtype(udev)); - printf(" Action : %s\n", udev_device_get_action(udev)); - printf(" Protocols : %s\n", - udev_device_get_sysattr_value(udev, "protocols")); - printf(" Uevent : %s\n", - udev_device_get_sysattr_value(udev, "uevent")); - - list_add(&device->list, &mgr->devices); - mgr->num_devices++; - - my_bus_emit_object_changed(mgr->bus, path, true); -} - -static int -udev_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) -{ - struct manager *mgr = userdata; - struct udev_device *dev; - - if (revents & EPOLLHUP) { - fprintf(stderr, "udev connection closed!\n"); - return 0; - } - - if (!(revents & EPOLLIN)) { - fprintf(stderr, "unexpected udev event: %" PRIu32 "\n", revents); - return 0; - } - - while ((dev = udev_monitor_receive_device(mgr->udev_mon))) { - printf("Read device: %s\n", udev_device_get_syspath(dev)); - if (!strcmp(udev_device_get_action(dev), "add")) - add_device(mgr, dev); - else if (!strcmp(udev_device_get_action(dev), "remove")) - remove_device(mgr, dev); - udev_device_unref(dev); - } - - return 1; -} - -static int -udev_setup(struct manager *mgr) -{ - struct udev_enumerate *enumerate; - struct udev_list_entry *devices, *dev_list_entry; - struct udev_device *dev; - - mgr->udev = udev_new(); - if (!mgr->udev) - return -ENOMEM; - - mgr->udev_mon = udev_monitor_new_from_netlink(mgr->udev, "udev"); - udev_monitor_filter_add_match_subsystem_devtype(mgr->udev_mon, "rc", NULL); - udev_monitor_enable_receiving(mgr->udev_mon); - - enumerate = udev_enumerate_new(mgr->udev); - udev_enumerate_add_match_subsystem(enumerate, "rc"); - udev_enumerate_scan_devices(enumerate); - devices = udev_enumerate_get_list_entry(enumerate); - - udev_list_entry_foreach(dev_list_entry, devices) { - const char *path; - - path = udev_list_entry_get_name(dev_list_entry); - if (!path) { - printf("Failed to get udev name\n"); - continue; - } - - dev = udev_device_new_from_syspath(mgr->udev, path); - if (!dev) { - printf("Failed to create udev device\n"); - continue; - } - - add_device(mgr, dev); - - udev_device_unref(dev); - } - udev_enumerate_unref(enumerate); - - return sd_event_add_io(mgr->event, &mgr->udev_ev, - udev_monitor_get_fd(mgr->udev_mon), - EPOLLIN, udev_read, mgr); -} - -static int -enumerator(sd_bus *bus, const char *path, void *userdata, char ***retnodes, sd_bus_error *error) -{ - _cleanup_strv_free_ char **nodes = NULL; - struct manager *mgr = userdata; - struct device *device; - int i = 0; - - if (!path) - return 0; - - nodes = zmalloc((mgr->num_devices + 1) * sizeof(char *)); - if (!nodes) - return -ENOMEM; - - list_for_each_entry(device, &mgr->devices, list) { - nodes[i] = strdup(device->path); - if (!nodes[i]) - return -ENOMEM; - i++; - } - - nodes[i++] = NULL; - *retnodes = nodes; - nodes = NULL; - - return 1; -} - -static void -free_manager(struct manager *mgr) { - if (!mgr) - return; - - sd_event_source_unref(mgr->udev_ev); - sd_bus_detach_event(mgr->bus); - sd_event_unref(mgr->event); - udev_monitor_unref(mgr->udev_mon); - udev_unref(mgr->udev); - - while (!list_empty(&mgr->devices)) { - struct device *dev = list_first_entry(&mgr->devices, typeof(*dev), list); - list_del(&dev->list); - free(dev->path); - free(dev->driver_name); - free(dev->keymap_name); - - while (!list_empty(&dev->keymaps)) { - struct keymap *keymap = list_first_entry(&dev->keymaps, typeof(*keymap), list); - list_del(&keymap->list); - free(keymap->name); - free(keymap); - } - - free(dev); - } - free(mgr); -} - -static int -block_signals(void) -{ - sigset_t sigset; - int r; - - r = sigemptyset(&sigset); - if (r < 0) - return r; - - r = sigaddset(&sigset, SIGINT); - if (r < 0) - return r; - - r = sigaddset(&sigset, SIGTERM); - if (r < 0) - return r; - - return sigprocmask(SIG_BLOCK, &sigset, NULL); -} - -int -main(int argc, char **argv) -{ - int r; - struct manager *mgr; - _cleanup_bus_close_unref_ sd_bus *bus = NULL; - _cleanup_bus_slot_unref_ struct sd_bus_slot *vtable_slot = NULL; - _cleanup_bus_slot_unref_ struct sd_bus_slot *enumerator_slot = NULL; - _cleanup_bus_slot_unref_ struct sd_bus_slot *objm_slot = NULL; - _cleanup_event_source_unref_ sd_event_source *sigint_ev = NULL; - _cleanup_event_source_unref_ sd_event_source *sigterm_ev = NULL; - - mgr = zmalloc(sizeof(*mgr)); - if (!mgr) { - fprintf(stderr, "Failed to allocate memory: %m\n"); - goto finish; - } - list_init(&mgr->devices); - - r = sd_bus_open_user(&bus); - if (r < 0) { - fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r)); - goto finish; - } - mgr->bus = bus; - - r = sd_bus_request_name(mgr->bus, "org.gnome.RemoteControlManager", 0); - if (r < 0) { - fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r)); - goto finish; - } - - r = sd_bus_add_fallback_vtable(mgr->bus, &vtable_slot, "/org/gnome/RemoteControlManager", - "org.gnome.RemoteControlManager.Device", - device_vtable, NULL, mgr); - if (r < 0) { - fprintf(stderr, "Failed to add vtable: %s\n", strerror(-r)); - goto finish; - } - - r = sd_bus_add_node_enumerator(mgr->bus, &enumerator_slot, "/org/gnome/RemoteControlManager", enumerator, mgr); - if (r < 0) { - fprintf(stderr, "Failed to create node enumerator: %s\n", strerror(-r)); - goto finish; - } - - r = sd_bus_add_object_manager(mgr->bus, &objm_slot, "/org/gnome/RemoteControlManager"); - if (r < 0) { - fprintf(stderr, "Failed to create object manager: %s\n", strerror(-r)); - goto finish; - } - - r = sd_event_default(&mgr->event); - if (r < 0) { - fprintf(stderr, "Failed to create sd_event: %s\n", strerror(-r)); - goto finish; - } - - r = sd_bus_attach_event(mgr->bus, mgr->event, 0); - if (r < 0) { - fprintf(stderr, "Failed to attach bus to event loop: %s\n", strerror(-r)); - goto finish; - } - - r = udev_setup(mgr); - if (r < 0) { - fprintf(stderr, "Failed to setup udev monitoring: %s\n", strerror(-r)); - goto finish; - } - - r = block_signals(); - if (r < 0) { - fprintf(stderr, "Failed to block signals: %m\n"); - goto finish; - } - - sd_event_add_signal(mgr->event, &sigint_ev, SIGINT, NULL, NULL); - sd_event_add_signal(mgr->event, &sigterm_ev, SIGTERM, NULL, NULL); - - r = sd_event_loop(mgr->event); - if (r < 0) { - fprintf(stderr, "Event loop failed: %s\n", strerror(-r)); - goto finish; - } - - sd_event_get_exit_code(mgr->event, &r); - -finish: - free_manager(mgr); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} - diff --git a/rcm-server.h b/rcm-server.h deleted file mode 100644 index 188ffab..0000000 --- a/rcm-server.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef foorcmserverhfoo -#define foorcmserverhfoo - -struct device { - char *name; - char *path; - char *driver_name; - char *keymap_name; - struct list_head list; - struct list_head keymaps; -}; - -struct manager { - sd_bus *bus; - sd_event *event; - struct udev *udev; - struct udev_monitor *udev_mon; - sd_event_source *udev_ev; - struct list_head devices; - unsigned num_devices; -}; - -#endif - -- cgit v1.2.3