summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2015-07-18 13:20:48 +0200
committerDavid Härdeman <david@hardeman.nu>2015-07-18 13:20:48 +0200
commit17d201747727157b63aaaa956071f10e35ad9942 (patch)
treee9895f322b8b5c157f1816e1e36a44c30e8fe9e8
parent48bd20a7b4d183edf2e19e17a3b7dc1d307ea8c1 (diff)
Add a method to set (update) a keymap/layout
-rw-r--r--RemoteControlManager.xml9
-rw-r--r--rcm-client-receive.c69
-rw-r--r--rcm-server-main.c240
3 files changed, 315 insertions, 3 deletions
diff --git a/RemoteControlManager.xml b/RemoteControlManager.xml
index dc6d4d5..6577dd0 100644
--- a/RemoteControlManager.xml
+++ b/RemoteControlManager.xml
@@ -14,6 +14,15 @@
<arg type='aa{sv}' name='keymap_entries' direction='out'/>
<arg type='aa{sv}' name='layout_entries' direction='out'/>
</method>
+ <method name='SetKeymap'>
+ <arg type='s' name='keymap_id' direction='in'/>
+ <arg type='s' name='keymap_name' direction='in'/>
+ <arg type='s' name='keymap_description' direction='in'/>
+ <arg type='q' name='keymap_width' direction='in'/>
+ <arg type='q' name='keymap_height' direction='in'/>
+ <arg type='aa{sv}' name='keymap_entries' direction='in'/>
+ <arg type='aa{sv}' name='layout_entries' direction='in'/>
+ </method>
<signal name='KeyPressed'>
<arg type='s' name='keycode'/>
</signal>
diff --git a/rcm-client-receive.c b/rcm-client-receive.c
index 4f21f78..9931a08 100644
--- a/rcm-client-receive.c
+++ b/rcm-client-receive.c
@@ -50,6 +50,7 @@ struct rcbutton {
};
struct state {
+ RCDevice *object;
GList *remotes;
GList *header_buttons;
bool editing;
@@ -518,6 +519,65 @@ resize_layout(struct remote *remote, guint16 new_width, guint16 new_height)
}
static void
+update_remote(struct remote *remote)
+{
+ GVariantBuilder kbuilder;
+ GVariantBuilder lbuilder;
+ GList *l;
+
+ g_variant_builder_init(&kbuilder, G_VARIANT_TYPE("aa{sv}"));
+ for (l = remote->keymap; l; l = l->next) {
+ struct keymap_entry *ke = l->data;
+
+ g_variant_builder_open(&kbuilder, G_VARIANT_TYPE ("a{sv}"));
+
+ g_variant_builder_add(&kbuilder, "{sv}", "protocol",
+ g_variant_new_string(ke->protocol));
+
+ g_variant_builder_add(&kbuilder, "{sv}", "scancode",
+ g_variant_new_uint64(ke->scancode));
+
+ g_variant_builder_add(&kbuilder, "{sv}", "keycode",
+ g_variant_new_string(ke->keycode));
+
+ g_variant_builder_close(&kbuilder);
+ }
+
+ g_variant_builder_init(&lbuilder, G_VARIANT_TYPE("aa{sv}"));
+ for (l = remote->buttons; l; l = l->next) {
+ struct rcbutton *rcb = l->data;
+
+ g_variant_builder_open(&lbuilder, G_VARIANT_TYPE ("a{sv}"));
+
+ switch (rcb->type) {
+ case RCBUTTON_TYPE_NORMAL:
+ g_variant_builder_add(&lbuilder, "{sv}", "type",
+ g_variant_new_string("button"));
+ g_variant_builder_add(&lbuilder, "{sv}", "keycode",
+ g_variant_new_string(rcb->name));
+ break;
+
+ case RCBUTTON_TYPE_BLANK:
+ g_variant_builder_add(&lbuilder, "{sv}", "type",
+ g_variant_new_string("blank"));
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ g_variant_builder_close(&lbuilder);
+ }
+
+ rcdevice_call_set_keymap_sync(state.object, remote->id,
+ remote->name, remote->description,
+ remote->width, remote->height,
+ g_variant_builder_end(&kbuilder),
+ g_variant_builder_end(&lbuilder),
+ NULL, NULL);
+}
+
+static void
resize_layout_dialog(GtkButton *button, gpointer user_data)
{
struct remote *remote = user_data;
@@ -589,6 +649,8 @@ resize_layout_dialog(GtkButton *button, gpointer user_data)
resize_layout(remote, width, height);
+ update_remote(remote);
+
out:
gtk_widget_destroy(dialog);
}
@@ -856,13 +918,14 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw)
return;
gchar **keymap_ids = NULL;
- RCDevice *object = RCDEVICE(interface);
- rcdevice_call_list_keymaps_sync(object, &keymap_ids, NULL, NULL);
+ /* FIXME: unref object */
+ state.object = RCDEVICE(interface);
+ rcdevice_call_list_keymaps_sync(state.object, &keymap_ids, NULL, NULL);
for (i = 0; keymap_ids[i]; i++) {
struct remote *remote;
g_print("Fetching keymap: %s\n", keymap_ids[i]);
- remote = get_keymap(object, keymap_ids[i]);
+ remote = get_keymap(state.object, keymap_ids[i]);
state.remotes = g_list_prepend(state.remotes, remote);
gtk_grid_attach(GTK_GRID(rgrid), remote->widget, i, 1, 1, 1);
diff --git a/rcm-server-main.c b/rcm-server-main.c
index 2a3266f..266658f 100644
--- a/rcm-server-main.c
+++ b/rcm-server-main.c
@@ -192,6 +192,245 @@ out:
return sd_bus_error_set_errno(error, r);
}
+static int
+method_setkeymap(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 *id;
+ const char *name;
+ const char *description;
+ uint16_t cols, rows;
+ int r;
+
+ dev = find_device_by_path(mgr, sd_bus_message_get_path(m));
+ if (!dev)
+ return sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device");
+
+ r = sd_bus_message_read(m, "sssqq", &id, &name, &description, &cols, &rows);
+ if (r < 0) {
+ fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
+ goto out;
+ }
+
+ keymap = find_keymap_by_id(dev, id);
+ if (!keymap)
+ return sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidKeymap", "Sorry, unknown keymap");
+
+ printf("Asked to update keymap\n");
+ printf("\tID : %s\n", id);
+ printf("\tName: %s\n", name);
+ printf("\tDesc: %s\n", description);
+ printf("\tCols: %u\n", cols);
+ printf("\tRows: %u\n", rows);
+
+ printf("\tKeymap:\n");
+ r = sd_bus_message_enter_container(m, 'a', "a{sv}");
+ if (r < 0)
+ goto out;
+
+ while ((r = sd_bus_message_enter_container(m, 'a', "{sv}")) > 0) {
+ const char *protocol;
+ uint64_t scancode;
+ const char *keycode;
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ const char *name;
+ const char *contents;
+ char type;
+
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, NULL, &contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ goto out;
+
+ if (!strcmp(name, "protocol")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for protocol (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &protocol);
+ if (r < 0)
+ goto out;
+
+ } else if (!strcmp(name, "scancode")) {
+ if (type != SD_BUS_TYPE_UINT64) {
+ printf("Invalid type for scancode (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &scancode);
+ if (r < 0)
+ goto out;
+
+ } else if (!strcmp(name, "keycode")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for keycode (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &keycode);
+ if (r < 0)
+ goto out;
+
+ } else {
+ r = sd_bus_message_skip(reply, contents);
+ if (r < 0)
+ goto out;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ printf("\t\t%s:%" PRIx64 ":%s\n", protocol, scancode, keycode);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ printf("\tLayout:\n");
+ r = sd_bus_message_enter_container(m, 'a', "a{sv}");
+ if (r < 0)
+ goto out;
+
+ while ((r = sd_bus_message_enter_container(m, 'a', "{sv}")) > 0) {
+ bool blank = false;
+ bool button = false;
+ const char *keycode = NULL;
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ const char *name;
+ const char *contents;
+ const char *button_type;
+ char type;
+
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, NULL, &contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ goto out;
+
+ if (!strcmp(name, "type")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for type (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &button_type);
+ if (r < 0)
+ goto out;
+
+ if (!strcasecmp(button_type, "button"))
+ button = true;
+ else if (!strcasecmp(button_type, "blank"))
+ blank = true;
+ else {
+ printf("Invalid button type: %s\n", button_type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ } else if (!strcmp(name, "keycode")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for keycode (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &keycode);
+ if (r < 0)
+ goto out;
+
+ } else {
+ r = sd_bus_message_skip(reply, contents);
+ if (r < 0)
+ goto out;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ if ((!blank && !button) || (blank && button) || (button && !keycode)) {
+ printf("Invalid layout specification\n");
+ r = -EINVAL;
+ goto out;
+ }
+
+ printf("\t\tButton: %s\n", button ? keycode : "blank");
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ /* FIXME: save the result */
+ return sd_bus_reply_method_return(m, NULL);
+
+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, 0, 0),
@@ -199,6 +438,7 @@ static const sd_bus_vtable device_vtable[] = {
SD_BUS_PROPERTY("HardwareType", "s", property_get, 0, 0),
SD_BUS_METHOD("ListKeymaps", NULL, "as", method_listkeymaps, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetKeymap", "s", "ssqqaa{sv}aa{sv}", method_getkeymap, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetKeymap", "sssqqaa{sv}aa{sv}", NULL, method_setkeymap, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("KeyPressed", "s", 0),
SD_BUS_SIGNAL("KeyReleased", "s", 0),
SD_BUS_VTABLE_END