static void
rb_metadata_dbus_save (GVariant *parameters,
		       GDBusMethodInvocation *invocation,
		       ServiceData *svc)
{
	const char *uri;
	GError *error = NULL;
	GVariantIter *metadata;
	RBMetaDataField key;
	GVariant *value;

	g_variant_get (parameters, "(&sa{iv})", &uri, &metadata);

	/* pass metadata to real metadata instance */
	rb_metadata_reset (svc->metadata);
	while (g_variant_iter_next (metadata, "{iv}", &key, &value)) {
		GValue val = {0,};

		switch (rb_metadata_get_field_type (key)) {
		case G_TYPE_STRING:
			g_value_init (&val, G_TYPE_STRING);
			g_value_set_string (&val, g_variant_get_string (value, NULL));
			break;
		case G_TYPE_ULONG:
			g_value_init (&val, G_TYPE_ULONG);
			g_value_set_ulong (&val, g_variant_get_uint32 (value));
			break;
		case G_TYPE_DOUBLE:
			g_value_init (&val, G_TYPE_DOUBLE);
			g_value_set_double (&val, g_variant_get_double (value));
			break;
		default:
			g_assert_not_reached ();
			break;
		}
		rb_metadata_set (svc->metadata, key, &val);
		g_variant_unref (value);
		g_value_unset (&val);
	}

	rb_metadata_save (svc->metadata, uri, &error);
	g_dbus_method_invocation_return_value (invocation,
					       g_variant_new ("(bis)",
							      (error == NULL),
							      (error != NULL ? error->code : 0),
							      (error != NULL ? error->message : "")));
}
static DBusHandlerResult
rb_metadata_dbus_save (DBusConnection *connection,
		       DBusMessage *message,
		       ServiceData *svc)
{
	char *uri;
	DBusMessageIter iter;
	DBusMessage *reply;
	GHashTable *data;
	GError *error = NULL;

	/* get URI and metadata from message */
	if (!dbus_message_iter_init (message, &iter)) {
		return DBUS_HANDLER_RESULT_NEED_MEMORY;
	}
	if (!rb_metadata_dbus_get_string (&iter, &uri)) {
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	data = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)rb_value_free);
	if (!rb_metadata_dbus_read_from_message (svc->metadata,
						 data,
						 &iter)) {
		/* make translatable? */
		g_free (uri);
		return send_error (connection, message,
				   RB_METADATA_ERROR_INTERNAL,
				   "Unable to read metadata from message");
	}

	/* pass to real metadata instance, and save it */
	rb_metadata_reset (svc->metadata);
	g_hash_table_foreach_remove (data, (GHRFunc) _set_metadata, svc->metadata);
	g_hash_table_destroy (data);

	rb_metadata_save (svc->metadata, uri, &error);
	g_free (uri);

	if (error) {
		DBusHandlerResult r;
		rb_debug ("metadata error: %s", error->message);

		r = send_error (connection, message, error->code, error->message);
		g_clear_error (&error);
		return r;
	}

	reply = dbus_message_new_method_return (message);
	if (!reply) {
		rb_debug ("out of memory creating return message");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	if (!dbus_connection_send (connection, reply, NULL)) {
		rb_debug ("failed to send return message");
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}

	dbus_message_unref (reply);

	return DBUS_HANDLER_RESULT_HANDLED;
}