From e664eafdac547ef8f7176a4c602eeae9fa0f6dea Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 16 Jul 2015 12:32:07 +0200 Subject: Support multiple keymaps in client --- keymaps/default/test.layout | 38 +++---- keymaps/default/test2.layout | 5 +- rcm-client-receive.c | 230 +++++++++++++++++++++++++------------------ rcm-server-main.c | 2 +- 4 files changed, 157 insertions(+), 118 deletions(-) diff --git a/keymaps/default/test.layout b/keymaps/default/test.layout index 7ec3d84..fabc573 100644 --- a/keymaps/default/test.layout +++ b/keymaps/default/test.layout @@ -4,7 +4,7 @@ Description=Samsung AA59-00581A LCD/LED TV Remote Control [Keymap] Map=nec:0x01018:KEY_POWER -Map=nec:0x01017:KEY_VIDEO +Map=nec:0x01017:KEY_OK Map=nec:0x01019:KEY_TV [Layout] @@ -16,21 +16,21 @@ Button=KEY_POWER Button=KEY_POWER Button=Blank Button=KEY_POWER -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO -Button=KEY_VIDEO +Button=KEY_TV +Button=KEY_OK +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV +Button=KEY_TV diff --git a/keymaps/default/test2.layout b/keymaps/default/test2.layout index c1ff8dc..3a49506 100644 --- a/keymaps/default/test2.layout +++ b/keymaps/default/test2.layout @@ -20,7 +20,7 @@ Map=nec:0xf00f0013:KEY_LEFT Map=nec:0xf00f0014:KEY_RIGHT [Layout] -Rows=8 +Rows=7 Cols=3 Button=KEY_NUMERIC_1 Button=KEY_NUMERIC_2 @@ -35,9 +35,6 @@ Button=Blank Button=KEY_NUMERIC_0 Button=Blank Button=Blank -Button=Blank -Button=Blank -Button=Blank Button=KEY_UP Button=Blank Button=KEY_LEFT diff --git a/rcm-client-receive.c b/rcm-client-receive.c index b54af85..734bc31 100644 --- a/rcm-client-receive.c +++ b/rcm-client-receive.c @@ -15,26 +15,29 @@ #define WINDOW_WIDTH 300 #define WINDOW_HEIGHT 300 +struct rcbutton { + char *name; + GtkWidget *button; +}; + struct remote { + char *name; + guint16 width; + guint16 height; GList *buttons; + GtkWidget *widget; + GtkWidget *grid; + GtkWidget *edit_button; +}; + +struct state { + GList *remotes; GList *header_buttons; - guint width; - guint height; bool editing; bool active; }; -struct rcbutton { - char *name; - guint row; - guint col; - guint rows; - guint cols; - GtkWidget *button; - struct rcbutton *next; -}; - -static struct remote *remote = NULL; +static struct state state; #if 0 static void @@ -162,25 +165,19 @@ out: static struct rcbutton * new_button_add(GtkGrid *grid, const gchar *protocol, guint64 scancode, - const char *keycode, GdkRGBA *color, - guint x, guint y, guint w, guint h) + const char *keycode, GdkRGBA *color, guint x, guint y) { struct rcbutton *rcb; gchar *tooltip; rcb = g_malloc0(sizeof(*rcb)); rcb->name = strdup(keycode); - rcb->col = x; - rcb->row = y; - rcb->cols = w; - rcb->rows = h; rcb->button = gtk_toggle_button_new(); gtk_widget_set_sensitive(rcb->button, false); tooltip = g_strdup_printf("Protocol: %s\nScancode: 0x%08" PRIx64 "\nKeycode : %s", protocol, scancode, keycode); gtk_widget_set_tooltip_text(rcb->button, tooltip); g_free(tooltip); - remote->buttons = g_list_append(remote->buttons, rcb); - gtk_grid_attach(grid, rcb->button, x, y, w, h); + gtk_grid_attach(grid, rcb->button, x, y, 1, 1); create_button_img(rcb->button, keycode); return rcb; } @@ -210,7 +207,7 @@ create_header_button(const gchar *label, const gchar *icon_name, g_signal_connect(button, "clicked", callback, user_data); gtk_widget_show_all(button); gtk_header_bar_pack_end(GTK_HEADER_BAR(global->header), button); - remote->header_buttons = g_list_prepend(remote->header_buttons, button); + state.header_buttons = g_list_prepend(state.header_buttons, button); } static void @@ -218,11 +215,11 @@ remove_header_buttons(void) { GList *l; - for (l = remote->header_buttons; l; l = l->next) + for (l = state.header_buttons; l; l = l->next) gtk_widget_destroy(l->data); - g_list_free(remote->header_buttons); - remote->header_buttons = NULL; + g_list_free(state.header_buttons); + state.header_buttons = NULL; } static void toggle_edit_keymap(GtkButton *button, gpointer user_data); @@ -230,6 +227,7 @@ static void toggle_edit_keymap(GtkButton *button, gpointer user_data); static void resize_keymap(GtkButton *button, gpointer user_data) { + struct remote *remote = user_data; GtkWindow *parent = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))); GtkWidget *dialog; GtkWidget *content_area; @@ -280,7 +278,7 @@ resize_keymap(GtkButton *button, gpointer user_data) width = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(width_input)); height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(height_input)); - printf("Asked to resize keylayout to %ix%i\n", width, height); + printf("Asked to resize keymap '%s' to to %ix%i\n", remote->name, width, height); out: gtk_widget_destroy(dialog); @@ -289,23 +287,36 @@ out: static void set_edit_keymap(bool editing) { - if (remote->width < 1 || remote->height < 1) - return; + GList *l; remove_header_buttons(); - if (editing) { - create_header_button("Apply", "gtk-apply", G_CALLBACK(toggle_edit_keymap), &remote); - create_header_button("Resize", "document-page-setup", G_CALLBACK(resize_keymap), &remote); - } else - create_header_button("Edit", "list-add", G_CALLBACK(toggle_edit_keymap), &remote); + if (editing) + create_header_button("Apply", "gtk-apply", G_CALLBACK(toggle_edit_keymap), NULL); + else + create_header_button("Edit", "list-add", G_CALLBACK(toggle_edit_keymap), NULL); + + for (l = state.remotes; l; l = l->next) { + struct remote *remote = l->data; + + if (editing) { + remote->edit_button = gtk_button_new_with_label("Resize"); + g_signal_connect(remote->edit_button, "clicked", G_CALLBACK(resize_keymap), remote); + gtk_grid_attach(GTK_GRID(remote->grid), remote->edit_button, 0, -1, remote->width, 1); + gtk_widget_show_all(remote->edit_button); + } else { + if (remote->edit_button) + gtk_widget_destroy(remote->edit_button); + remote->edit_button = NULL; + } + } } static void toggle_edit_keymap(GtkButton *button, gpointer user_data) { - remote->editing = !remote->editing; - set_edit_keymap(remote->editing); + state.editing = !state.editing; + set_edit_keymap(state.editing); } static void @@ -314,70 +325,55 @@ on_notebook_page_change(GtkNotebook *notebook, GtkWidget *page, guint new_page_n { if (new_page_num != own_page_num) { remove_header_buttons(); - remote->editing = false; - remote->active = false; + state.editing = false; + state.active = false; return; } - remote->active = true; - remote->editing = false; - set_edit_keymap(remote->editing); + state.active = true; + state.editing = false; + set_edit_keymap(state.editing); g_print("Page change: %i -> %u\n", own_page_num, new_page_num); } void rcng_client_receive_keypress(GDBusObject *obj, const gchar *keycode, bool pressed) { GList *l; + unsigned affected = 0; /* FIXME: Use object path, this is just test code */ - if (!remote || !remote->active) + if (!state.active) return; - for (l = remote->buttons; l; l = l->next) { - struct rcbutton *rcb = l->data; + for (l = state.remotes; l; l = l->next) { + struct remote *remote = l->data; + GList *button; - if (strcmp(keycode, rcb->name)) - continue; + for (button = remote->buttons; button; button = button->next) { + struct rcbutton *rcb = button->data; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rcb->button), pressed); + if (strcmp(keycode, rcb->name)) + continue; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rcb->button), pressed); + affected++; + } } - g_print("Key %s %s\n", keycode, pressed ? "pressed" : "released"); + g_print("Key %s %s (%u affected)\n", keycode, pressed ? "pressed" : "released", affected); } -void rcng_client_receive_init_ui(GDBusObject *new_hw) +static struct remote * +get_keymap(RCDevice *object, const gchar *keymap_name) { - 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; + struct remote *remote; GVariant *km_entries = NULL; - rcdevice_call_get_keymap_sync(object, keymaps[0], &km_width, &km_height, - &km_entries, NULL, NULL); remote = g_malloc0(sizeof(*remote)); - remote->width = km_width; - remote->height = km_height; - remote->editing = false; + remote->name = strdup(keymap_name); + + rcdevice_call_get_keymap_sync(object, keymap_name, &remote->width, + &remote->height, &km_entries, NULL, NULL); g_print("type of keymaps is %s\n", g_variant_get_type_string(km_entries)); GVariantIter iter; @@ -389,25 +385,13 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw) guint row = 0; guint col = 0; - scrollda = gtk_scrolled_window_new(NULL, NULL); - gtk_container_set_border_width(GTK_CONTAINER(scrollda), 12); - own_page_num = gtk_notebook_append_page(global->notebook, scrollda, gtk_label_new("Receive")); - - GtkWidget *rgrid; - rgrid = gtk_grid_new(); - gtk_widget_set_halign(rgrid, GTK_ALIGN_CENTER); - gtk_grid_set_column_spacing(GTK_GRID(rgrid), 12); - gtk_grid_set_row_spacing(GTK_GRID(rgrid), 12); - gtk_container_add(GTK_CONTAINER(scrollda), rgrid); - GtkWidget *fixed; fixed = gtk_fixed_new(); gtk_widget_set_name(fixed, "RemoteControlClientFixed"); - gtk_grid_attach(GTK_GRID(rgrid), fixed, 1, 1, 1, 1); + remote->widget = fixed; GtkWidget *frame; - frame = gtk_frame_new(keymaps[0]); - g_free(keymaps); + frame = gtk_frame_new(keymap_name); gtk_widget_set_name(gtk_frame_get_label_widget(GTK_FRAME(frame)), "RemoteControlClientRemoteLabel"); gtk_widget_set_name(frame, "RemoteControlClientRemoteFrame"); gtk_fixed_put(GTK_FIXED(fixed), frame, 0, 0); @@ -420,6 +404,7 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw) gtk_grid_set_column_homogeneous(GTK_GRID(grid), true); gtk_grid_set_row_homogeneous(GTK_GRID(grid), true); gtk_container_set_border_width(GTK_CONTAINER(grid), 12); + remote->grid = grid; while (g_variant_iter_loop (&iter, "@a{sv}", &item)) { gchar *type; @@ -432,18 +417,75 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw) g_variant_lookup(item, "scancode", "t", &scancode); g_variant_lookup(item, "keycode", "s", &keycode); - if (!strcmp(type, "button")) - new_button_add(GTK_GRID(grid), protocol, scancode, keycode, NULL, col, row, 1, 1); + if (!strcmp(type, "button")) { + struct rcbutton *rcb; + rcb = new_button_add(GTK_GRID(grid), protocol, scancode, + keycode, NULL, col, row); + remote->buttons = g_list_append(remote->buttons, rcb); + printf("Got a button: %s:0x%08" PRIx64 ":%s\n", protocol, scancode, keycode); + } else if (!strcmp(type, "blank")) + printf("Got a blank\n"); + else + printf("Error: unknown type: %s (treating as blank)\n", type); col++; - if (col >= km_width) { + if (col >= remote->width) { col = 0; row++; } - printf("Got a %s: %s:0x%08" PRIx64 ":%s\n", type, protocol, scancode, keycode); } + return remote; +} + +void rcng_client_receive_init_ui(GDBusObject *new_hw) +{ + static bool first = true; + unsigned i; + + if (first) { + g_signal_connect(global->notebook, "switch-page", G_CALLBACK(on_notebook_page_change), NULL); + state.remotes = NULL; + state.header_buttons = NULL; + state.editing = false; + state.active = false; + first = false; + } + + rcng_client_receive_destroy_ui(); + + /* FIXME: if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a(uuuuaa{sv}))"))) */ + scrollda = gtk_scrolled_window_new(NULL, NULL); + gtk_container_set_border_width(GTK_CONTAINER(scrollda), 12); + own_page_num = gtk_notebook_append_page(global->notebook, scrollda, gtk_label_new("Receive")); + + GtkWidget *rgrid; + rgrid = gtk_grid_new(); + gtk_widget_set_halign(rgrid, GTK_ALIGN_CENTER); + gtk_grid_set_column_spacing(GTK_GRID(rgrid), 12); + gtk_grid_set_row_spacing(GTK_GRID(rgrid), 12); + gtk_container_add(GTK_CONTAINER(scrollda), rgrid); + + GDBusInterface *interface; + interface = g_dbus_object_get_interface(new_hw, "org.gnome.RemoteControlManager.Device"); + if (!interface) + return; + + gchar **keymaps = NULL; + RCDevice *object = RCDEVICE(interface); + rcdevice_call_list_keymaps_sync(object, &keymaps, NULL, NULL); + for (i = 0; keymaps[i]; i++) { + struct remote *remote; + + g_print("Fetching keymap: %s\n", keymaps[i]); + remote = get_keymap(object, keymaps[i]); + + state.remotes = g_list_prepend(state.remotes, remote); + gtk_grid_attach(GTK_GRID(rgrid), remote->widget, i, 1, 1, 1); + } + + g_free(keymaps); gtk_widget_show_all(scrollda); } diff --git a/rcm-server-main.c b/rcm-server-main.c index 4f4e9e1..8ec3140 100644 --- a/rcm-server-main.c +++ b/rcm-server-main.c @@ -489,7 +489,7 @@ timeout_cb(sd_event_source *source, usec_t usec, void *userdata) sd_bus_emit_signal(mgr->bus, "/org/gnome/RemoteControlManager/rc0", "org.gnome.RemoteControlManager.Device", pressed ? "KeyPressed" : "KeyReleased", - "s", "KEY_VIDEO"); + "s", "KEY_OK"); if (pressed) timeout = USEC_PER_SEC / 2; -- cgit v1.2.3