diff options
| -rw-r--r-- | RemoteControlManager.xml | 9 | ||||
| -rw-r--r-- | rcm-client-receive.c | 69 | ||||
| -rw-r--r-- | rcm-server-main.c | 240 | 
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 | 
