[rhythmbox] metadata: replace libdbus with GDBus



commit 17b40961d68485a1d17b488916acb76bb5f46b64
Author: Jonathan Matthew <jonathan d14n org>
Date:   Fri Feb 25 09:23:52 2011 +1000

    metadata: replace libdbus with GDBus
    
    This mostly reduces the amount of code involved, but also means we
    can change the metadata item format a lot more easily.

 metadata/Makefile.am                |   10 +-
 metadata/rb-metadata-dbus-client.c  |  412 +++++++++++---------------------
 metadata/rb-metadata-dbus-service.c |  448 ++++++++++++-----------------------
 metadata/rb-metadata-dbus.c         |  297 ++++-------------------
 metadata/rb-metadata-dbus.h         |   26 +--
 metadata/test-metadata.c            |    1 -
 6 files changed, 355 insertions(+), 839 deletions(-)
---
diff --git a/metadata/Makefile.am b/metadata/Makefile.am
index 35895be..3bb3622 100644
--- a/metadata/Makefile.am
+++ b/metadata/Makefile.am
@@ -11,7 +11,7 @@ INCLUDES = 						\
 
 INSTALLED_METADATA_HELPER=`echo rhythmbox-metadata | sed '$(transform)'`
 
-INCLUDES += $(DBUS_CFLAGS)				\
+INCLUDES +=						\
 	-DLIBEXEC_DIR=\"$(libexecdir)\"			\
 	-DINSTALLED_METADATA_HELPER=\"$(INSTALLED_METADATA_HELPER)\"
 
@@ -32,7 +32,6 @@ librbmetadata_la_SOURCES =				\
 	rb-metadata-dbus-client.c
 
 librbmetadata_la_LIBADD = 				\
-	$(DBUS_LIBS)					\
 	$(RHYTHMBOX_LIBS)
 
 # service
@@ -56,8 +55,7 @@ rhythmbox_metadata_LDADD = 				\
 	librbmetadatasvc.la				\
 	$(top_builddir)/lib/librb.la			\
 	$(RHYTHMBOX_LIBS)				\
-	-lgstpbutils-0.10				\
-	$(DBUS_LIBS)
+	-lgstpbutils-0.10
 
 # test program?
 noinst_PROGRAMS = test-metadata
@@ -68,8 +66,6 @@ test_metadata_LDADD =					\
 	librbmetadata.la				\
 	$(top_builddir)/lib/librb.la			\
 	$(RHYTHMBOX_LIBS)				\
-	-lgstpbutils-0.10				\
-	$(DBUS_LIBS)
+	-lgstpbutils-0.10
 
 librbmetadata_la_LDFLAGS = -export-dynamic
-
diff --git a/metadata/rb-metadata-dbus-client.c b/metadata/rb-metadata-dbus-client.c
index 56e83bb..429b5ed 100644
--- a/metadata/rb-metadata-dbus-client.c
+++ b/metadata/rb-metadata-dbus-client.c
@@ -51,7 +51,6 @@
  * @short_description: metadata reader and writer interface
  *
  * Provides a simple synchronous interface for metadata extraction and updating.
- *
  */
 
 #include <config.h>
@@ -61,10 +60,8 @@
 #include "rb-debug.h"
 #include "rb-util.h"
 
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <glib/gi18n.h>
+#include <gio/gio.h>
 
 #include <unistd.h>
 #include <sys/types.h>
@@ -78,7 +75,7 @@ static void rb_metadata_init (RBMetaData *md);
 static void rb_metadata_finalize (GObject *object);
 
 static gboolean tried_env_address = FALSE;
-static DBusConnection *dbus_connection = NULL;
+static GDBusConnection *dbus_connection = NULL;
 static GPid metadata_child = 0;
 static int metadata_stdout = -1;
 static GMainContext *main_context = NULL;
@@ -147,13 +144,13 @@ static void
 kill_metadata_service (void)
 {
 	if (dbus_connection) {
-		if (dbus_connection_get_is_connected (dbus_connection)) {
+		if (g_dbus_connection_is_closed (dbus_connection) == FALSE) {
 			rb_debug ("closing dbus connection");
-			dbus_connection_close (dbus_connection);
+			g_dbus_connection_close_sync (dbus_connection, NULL, NULL);
 		} else {
 			rb_debug ("dbus connection already closed");
 		}
-		dbus_connection_unref (dbus_connection);
+		g_object_unref (dbus_connection);
 		dbus_connection = NULL;
 	}
 
@@ -174,47 +171,44 @@ kill_metadata_service (void)
 static gboolean
 ping_metadata_service (GError **error)
 {
-	DBusMessage *message, *response;
-	DBusError dbus_error = {0,};
+	GDBusMessage *message;
+	GDBusMessage *response;
 
-	if (!dbus_connection_get_is_connected (dbus_connection))
+	if (g_dbus_connection_is_closed (dbus_connection))
 		return FALSE;
 
-	message = dbus_message_new_method_call (RB_METADATA_DBUS_NAME,
-						RB_METADATA_DBUS_OBJECT_PATH,
-						RB_METADATA_DBUS_INTERFACE,
-						"ping");
-	if (!message) {
-		return FALSE;
-	}
-	response = dbus_connection_send_with_reply_and_block (dbus_connection,
-							      message,
-							      RB_METADATA_DBUS_TIMEOUT,
-							      &dbus_error);
-	dbus_message_unref (message);
-	if (dbus_error_is_set (&dbus_error)) {
-		/* ignore 'no reply': just means the service is dead */
-		if (strcmp (dbus_error.name, DBUS_ERROR_NO_REPLY)) {
-			dbus_set_g_error (error, &dbus_error);
+	message = g_dbus_message_new_method_call (RB_METADATA_DBUS_NAME,
+						  RB_METADATA_DBUS_OBJECT_PATH,
+						  RB_METADATA_DBUS_INTERFACE,
+						  "ping");
+	response = g_dbus_connection_send_message_with_reply_sync (dbus_connection,
+								   message,
+								   G_DBUS_MESSAGE_FLAGS_NONE,
+								   RB_METADATA_DBUS_TIMEOUT,
+								   NULL,
+								   NULL,
+								   error);
+	g_object_unref (message);
+
+	if (*error != NULL) {
+		/* ignore 'no reply', just means the service is dead */
+		if ((*error)->domain == G_DBUS_ERROR && (*error)->code == G_DBUS_ERROR_NO_REPLY) {
+			g_clear_error (error);
 		}
-		dbus_error_free (&dbus_error);
 		return FALSE;
 	}
-	dbus_message_unref (response);
+	g_object_unref (response);
 	return TRUE;
 }
 
 static gboolean
 start_metadata_service (GError **error)
 {
-	DBusError dbus_error = {0,};
-	DBusMessage *message;
-	DBusMessage *response;
-	DBusMessageIter iter;
 	GIOChannel *stdout_channel;
 	GIOStatus status;
 	gchar *dbus_address = NULL;
 	char *saveable_type_list;
+	GVariant *response_body;
 
 	if (dbus_connection) {
 		if (ping_metadata_service (error))
@@ -298,18 +292,18 @@ start_metadata_service (GError **error)
 		rb_debug ("Got metadata helper D-BUS address %s", dbus_address);
 	}
 
-	dbus_connection = dbus_connection_open_private (dbus_address, &dbus_error);
+	dbus_connection = g_dbus_connection_new_for_address_sync (dbus_address,
+								  G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+								  NULL,
+								  NULL,
+								  error);
 	g_free (dbus_address);
-	if (!dbus_connection) {
+	if (*error != NULL) {
 		kill_metadata_service ();
-
-		dbus_set_g_error (error, &dbus_error);
-		dbus_error_free (&dbus_error);
 		return FALSE;
 	}
-	dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
 
-	dbus_connection_setup_with_g_main (dbus_connection, main_context);
+	g_dbus_connection_set_exit_on_close (dbus_connection, FALSE);
 
 	rb_debug ("Metadata process %d started", metadata_child);
 
@@ -318,37 +312,23 @@ start_metadata_service (GError **error)
 		g_strfreev (saveable_types);
 	}
 
-	message = dbus_message_new_method_call (RB_METADATA_DBUS_NAME,
-						RB_METADATA_DBUS_OBJECT_PATH,
-						RB_METADATA_DBUS_INTERFACE,
-						"getSaveableTypes");
-	if (!message) {
-		/* what now? */
-		rb_debug ("unable to query metadata helper for saveable types");
-		return FALSE;
-	}
-
-	rb_debug ("sending metadata saveable types query");
-	response = dbus_connection_send_with_reply_and_block (dbus_connection,
-							      message,
-							      RB_METADATA_DBUS_TIMEOUT,
-							      &dbus_error);
-
-	if (!response) {
-		rb_debug ("saveable type query failed");
-		return FALSE;
-	}
-
-	if (!dbus_message_iter_init (response, &iter)) {
-		rb_debug ("couldn't read saveable type query response");
-		return FALSE;
-	}
-
-	if (!rb_metadata_dbus_get_strv (&iter, &saveable_types)) {
-		rb_debug ("couldn't get saveable type data from response message");
+	response_body = g_dbus_connection_call_sync (dbus_connection,
+						     RB_METADATA_DBUS_NAME,
+						     RB_METADATA_DBUS_OBJECT_PATH,
+						     RB_METADATA_DBUS_INTERFACE,
+						     "getSaveableTypes",
+						     NULL,
+						     NULL,
+						     G_DBUS_CALL_FLAGS_NONE,
+						     RB_METADATA_DBUS_TIMEOUT,
+						     NULL,
+						     error);
+	if (response_body == NULL) {
+		rb_debug ("saveable type query failed: %s", (*error)->message);
 		return FALSE;
 	}
 
+	g_variant_get (response_body, "(^as)", &saveable_types);
 	if (saveable_types != NULL) {
 		saveable_type_list = g_strjoinv (", ", saveable_types);
 		rb_debug ("saveable types from metadata helper: %s", saveable_type_list);
@@ -356,56 +336,11 @@ start_metadata_service (GError **error)
 	} else {
 		rb_debug ("unable to save metadata for any file types");
 	}
+	g_variant_unref (response_body);
 
-	if (message)
-		dbus_message_unref (message);
-	if (response)
-		dbus_message_unref (response);
 	return TRUE;
 }
 
-static void
-handle_dbus_error (RBMetaData *md, DBusError *dbus_error, GError **error)
-{
-	/*
-	 * If the error is 'no reply within the specified time',
-	 * then we assume that either the metadata process died, or
-	 * it's stuck in a loop and needs to be killed.
-	 */
-	if (strcmp (dbus_error->name, DBUS_ERROR_NO_REPLY) == 0) {
-		kill_metadata_service ();
-
-		g_set_error (error,
-			     RB_METADATA_ERROR,
-			     RB_METADATA_ERROR_INTERNAL,
-			     _("Internal GStreamer problem; file a bug"));
-	} else {
-		dbus_set_g_error (error, dbus_error);
-		dbus_error_free (dbus_error);
-	}
-}
-
-static void
-read_error_from_message (RBMetaData *md, DBusMessageIter *iter, GError **error)
-{
-	guint32 error_code;
-	gchar *error_message;
-
-	if (!rb_metadata_dbus_get_uint32 (iter, &error_code) ||
-	    !rb_metadata_dbus_get_string (iter, &error_message)) {
-		g_set_error (error,
-			     RB_METADATA_ERROR,
-			     RB_METADATA_ERROR_INTERNAL,
-			     _("D-BUS communication error"));
-		return;
-	}
-
-	g_set_error (error, RB_METADATA_ERROR,
-		     error_code,
-		     "%s", error_message);
-	g_free (error_message);
-}
-
 /**
  * rb_metadata_reset:
  * @md: a #RBMetaData
@@ -416,6 +351,9 @@ read_error_from_message (RBMetaData *md, DBusMessageIter *iter, GError **error)
 void
 rb_metadata_reset (RBMetaData *md)
 {
+	g_free (md->priv->mimetype);
+	md->priv->mimetype = NULL;
+
 	if (md->priv->metadata)
 		g_hash_table_destroy (md->priv->metadata);
 	md->priv->metadata = g_hash_table_new_full (g_direct_hash,
@@ -440,140 +378,97 @@ rb_metadata_load (RBMetaData *md,
 		  const char *uri,
 		  GError **error)
 {
-	DBusMessage *message = NULL;
-	DBusMessage *response = NULL;
-	DBusMessageIter iter;
-	DBusError dbus_error = {0,};
-	gboolean ok;
+	GVariant *response;
 	GError *fake_error = NULL;
-	GError *dbus_gerror;
-
-	dbus_gerror = g_error_new (RB_METADATA_ERROR,
-				   RB_METADATA_ERROR_INTERNAL,
-				   _("D-BUS communication error"));
 
 	if (error == NULL)
 		error = &fake_error;
 
-	g_free (md->priv->mimetype);
-	md->priv->mimetype = NULL;
-
+	rb_metadata_reset (md);
 	if (uri == NULL)
 		return;
-
-	rb_metadata_reset (md);
-
 	g_static_mutex_lock (&conn_mutex);
 
 	start_metadata_service (error);
 
 	if (*error == NULL) {
-		message = dbus_message_new_method_call (RB_METADATA_DBUS_NAME,
+		rb_debug ("sending metadata load request: %s", uri);
+		response = g_dbus_connection_call_sync (dbus_connection,
+							RB_METADATA_DBUS_NAME,
 							RB_METADATA_DBUS_OBJECT_PATH,
 							RB_METADATA_DBUS_INTERFACE,
-							"load");
-		if (!message) {
-			g_propagate_error (error, dbus_gerror);
-		} else if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_INVALID)) {
-			g_propagate_error (error, dbus_gerror);
-		}
-	}
-
-	if (*error == NULL) {
-		rb_debug ("sending metadata load request");
-		response = dbus_connection_send_with_reply_and_block (dbus_connection,
-								      message,
-								      RB_METADATA_DBUS_TIMEOUT,
-								      &dbus_error);
-
-		if (!response)
-			handle_dbus_error (md, &dbus_error, error);
+							"load",
+							g_variant_new ("(s)", uri),
+							NULL, /* complicated return type */
+							G_DBUS_CALL_FLAGS_NONE,
+							RB_METADATA_DBUS_TIMEOUT,
+							NULL,
+							error);
 	}
 
 	if (*error == NULL) {
-		if (!dbus_message_iter_init (response, &iter)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't read response message");
-		}
-	}
-	
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_strv (&iter, &md->priv->missing_plugins)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't get missing plugin data from response message");
-		}
-	}
-
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_strv (&iter, &md->priv->plugin_descriptions)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't get missing plugin descriptions from response message");
-		}
-	}
-
-	/* if we're missing some plugins, we'll need to make sure the
-	 * metadata helper rereads the registry before the next load.
-	 * the easiest way to do this is to kill it.
-	 */
-	if (*error == NULL && md->priv->missing_plugins != NULL) {
-		rb_debug ("missing plugins; killing metadata service to force registry reload");
-		kill_metadata_service ();
-	}
-
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_boolean (&iter, &md->priv->has_audio)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't get has-audio flag from response message");
-		} else {
-			rb_debug ("has audio: %d", md->priv->has_audio);
-		}
-	}
-
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_boolean (&iter, &md->priv->has_video)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't get has-video flag from response message");
-		} else {
-			rb_debug ("has video: %d", md->priv->has_video);
-		}
-	}
+		GVariantIter *metadata;
+		gboolean ok = FALSE;
+		int error_code;
+		char *error_string = NULL;
+
+		g_variant_get (response,
+			       "(^as^asbbbsbisa{iv})",
+			       &md->priv->missing_plugins,
+			       &md->priv->plugin_descriptions,
+			       &md->priv->has_audio,
+			       &md->priv->has_video,
+			       &md->priv->has_other_data,
+			       &md->priv->mimetype,
+			       &ok,
+			       &error_code,
+			       &error_string,
+			       &metadata);
+
+		if (ok) {
+			guint32 key;
+			GVariant *value;
+
+			while (g_variant_iter_next (metadata, "{iv}", &key, &value)) {
+				GValue *val = g_slice_new0 (GValue);
+
+				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;
+				}
+				g_hash_table_insert (md->priv->metadata, GINT_TO_POINTER (key), val);
+				g_variant_unref (value);
+			}
 
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_boolean (&iter, &md->priv->has_other_data)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't get has-other-data flag from response message");
 		} else {
-			rb_debug ("has other data: %d", md->priv->has_other_data);
+			g_set_error (error, RB_METADATA_ERROR,
+				     error_code,
+				     "%s", error_string);
 		}
-	}
+		g_variant_iter_free (metadata);
 
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_string (&iter, &md->priv->mimetype)) {
-			g_propagate_error (error, dbus_gerror);
-		} else {
-			rb_debug ("got mimetype: %s", md->priv->mimetype);
-		}
-	}
-
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_get_boolean (&iter, &ok)) {
-			g_propagate_error (error, dbus_gerror);
-			rb_debug ("couldn't get success flag from response message");
-		} else if (ok == FALSE) {
-			read_error_from_message (md, &iter, error);
+		/* if we're missing some plugins, we'll need to make sure the
+		 * metadata helper rereads the registry before the next load.
+		 * the easiest way to do this is to kill it.
+		 */
+		if (*error == NULL && g_strv_length (md->priv->missing_plugins) > 0) {
+			rb_debug ("missing plugins; killing metadata service to force registry reload");
+			kill_metadata_service ();
 		}
 	}
-
-	if (*error == NULL) {
-		rb_metadata_dbus_read_from_message (md, md->priv->metadata, &iter);
-	}
-
-	if (message)
-		dbus_message_unref (message);
-	if (response)
-		dbus_message_unref (response);
-	if (*error != dbus_gerror)
-		g_error_free (dbus_gerror);
 	if (fake_error)
 		g_error_free (fake_error);
 
@@ -609,7 +504,8 @@ rb_metadata_get_mime (RBMetaData *md)
 gboolean
 rb_metadata_has_missing_plugins (RBMetaData *md)
 {
-	return (md->priv->missing_plugins != NULL);
+	return (md->priv->missing_plugins != NULL &&
+	        g_strv_length (md->priv->missing_plugins) > 0);
 }
 
 /**
@@ -765,11 +661,8 @@ rb_metadata_get_saveable_types (RBMetaData *md)
 void
 rb_metadata_save (RBMetaData *md, const char *uri, GError **error)
 {
+	GVariant *response;
 	GError *fake_error = NULL;
-	DBusMessage *message = NULL;
-	DBusMessage *response = NULL;
-	DBusError dbus_error = {0,};
-	DBusMessageIter iter;
 
 	if (error == NULL)
 		error = &fake_error;
@@ -779,53 +672,36 @@ rb_metadata_save (RBMetaData *md, const char *uri, GError **error)
 	start_metadata_service (error);
 
 	if (*error == NULL) {
-		message = dbus_message_new_method_call (RB_METADATA_DBUS_NAME,
+		response = g_dbus_connection_call_sync (dbus_connection,
+							RB_METADATA_DBUS_NAME,
 							RB_METADATA_DBUS_OBJECT_PATH,
 							RB_METADATA_DBUS_INTERFACE,
-							"save");
-		if (!message) {
-			g_set_error (error,
-				     RB_METADATA_ERROR,
-				     RB_METADATA_ERROR_INTERNAL,
-				     _("D-BUS communication error"));
-		}
+							"save",
+							g_variant_new ("(sa{iv})",
+								       uri,
+								       rb_metadata_dbus_get_variant_builder (md)),
+							NULL,
+							G_DBUS_CALL_FLAGS_NONE,
+							RB_METADATA_SAVE_DBUS_TIMEOUT,
+							NULL,
+							error);
 	}
 
 	if (*error == NULL) {
-		dbus_message_iter_init_append (message, &iter);
-		if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &uri)) {
-			g_set_error (error,
-				     RB_METADATA_ERROR,
-				     RB_METADATA_ERROR_INTERNAL,
-				     _("D-BUS communication error"));
+		gboolean ok = TRUE;
+		int error_code;
+		const char *error_message;
+
+		g_variant_get (response, "(bis)", &ok, &error_code, &error_message);
+		if (ok == FALSE) {
+			g_set_error (error, RB_METADATA_ERROR,
+				     error_code,
+				     "%s", error_message);
 		}
-	}
-	if (*error == NULL) {
-		if (!rb_metadata_dbus_add_to_message (md, &iter)) {
-			g_set_error (error,
-				     RB_METADATA_ERROR,
-				     RB_METADATA_ERROR_INTERNAL,
-				     _("D-BUS communication error"));
-		}
-	}
 
-	if (*error == NULL) {
-		response = dbus_connection_send_with_reply_and_block (dbus_connection,
-								      message,
-								      RB_METADATA_SAVE_DBUS_TIMEOUT,
-								      &dbus_error);
-		if (!response) {
-			handle_dbus_error (md, &dbus_error, error);
-		} else if (dbus_message_iter_init (response, &iter)) {
-			/* if there's any return data at all, it'll be an error */
-			read_error_from_message (md, &iter, error);
-		}
+		g_variant_unref (response);
 	}
 
-	if (message)
-		dbus_message_unref (message);
-	if (response)
-		dbus_message_unref (response);
 	if (fake_error)
 		g_error_free (fake_error);
 
diff --git a/metadata/rb-metadata-dbus-service.c b/metadata/rb-metadata-dbus-service.c
index 21dbcae..37bf58d 100644
--- a/metadata/rb-metadata-dbus-service.c
+++ b/metadata/rb-metadata-dbus-service.c
@@ -36,10 +36,7 @@
 
 #include <glib/gi18n.h>
 #include <gst/gst.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <gio/gio.h>
 
 #include "rb-metadata.h"
 #include "rb-metadata-dbus.h"
@@ -50,277 +47,121 @@
 #define ATTENTION_SPAN		30
 
 typedef struct {
-	DBusServer *server;
-	DBusConnection *connection;
+	GDBusServer *server;
+	GDBusConnection *connection;
+	GDBusNodeInfo *node_info;
 	GMainLoop *loop;
 	time_t last_active;
 	RBMetaData *metadata;
 	gboolean external;
 } ServiceData;
 
-static gboolean
-append_error (DBusMessageIter *iter,
-	      gint error_type,
-	      const char *message)
-{
-	if (!dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &error_type) ||
-	    !dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &message)) {
-		rb_debug ("couldn't append error data");
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static DBusHandlerResult
-send_error (DBusConnection *connection,
-	    DBusMessage *request,
-	    gint error_type,
-	    const char *message)
-{
-	DBusMessage *reply = dbus_message_new_method_return (request);
-	DBusMessageIter iter;
-
-	if (!message) {
-		message = "";
-		rb_debug ("attempting to return error with no message");
-	} else {
-		rb_debug ("attempting to return error: %s", message);
-	}
-
-	dbus_message_iter_init_append (reply, &iter);
-	if (append_error (&iter, error_type, message) == FALSE) {
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
-
-	dbus_connection_send (connection, reply, NULL);
-	dbus_message_unref (reply);
-	return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static DBusHandlerResult
-rb_metadata_dbus_load (DBusConnection *connection,
-		       DBusMessage *message,
+static void
+rb_metadata_dbus_load (GVariant *parameters,
+		       GDBusMethodInvocation *invocation,
 		       ServiceData *svc)
 {
-	char *uri;
-	DBusMessageIter iter;
-	DBusMessage *reply;
+	const char *uri;
 	GError *error = NULL;
-	gboolean ok;
-	const char *mimetype = NULL;
+	GVariant *response;
+	const char *nothing[] = { NULL };
 	char **missing_plugins = NULL;
 	char **plugin_descriptions = NULL;
-	gboolean has_audio;
-	gboolean has_video;
-	gboolean has_other_data;
-
-	if (!dbus_message_iter_init (message, &iter)) {
-		return DBUS_HANDLER_RESULT_NEED_MEMORY;
-	}
+	const char *mediatype;
 
-	if (!rb_metadata_dbus_get_string (&iter, &uri)) {
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
+	g_variant_get (parameters, "(&s)", &uri);
 
 	rb_debug ("loading metadata from %s", uri);
 	rb_metadata_load (svc->metadata, uri, &error);
-	rb_debug ("metadata load finished (type %s)", rb_metadata_get_mime (svc->metadata));
-	g_free (uri);
-
-	/* construct reply */
-	reply = dbus_message_new_method_return (message);
-	if (!reply) {
-		rb_debug ("out of memory creating return message");
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
-	
-	dbus_message_iter_init_append (reply, &iter);
+	mediatype = rb_metadata_get_mime (svc->metadata);
+	rb_debug ("metadata load finished (type %s)", mediatype);
 
 	rb_metadata_get_missing_plugins (svc->metadata, &missing_plugins, &plugin_descriptions);
-	if (!rb_metadata_dbus_add_strv (&iter, missing_plugins)) {
-		rb_debug ("out of memory adding data to return message");
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
-	if (!rb_metadata_dbus_add_strv (&iter, plugin_descriptions)) {
-		rb_debug ("out of memory adding data to return message");
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
-
-	mimetype = rb_metadata_get_mime (svc->metadata);
-	if (mimetype == NULL) {
-		mimetype = "";
-	}
-	has_audio = rb_metadata_has_audio (svc->metadata);
-	has_video = rb_metadata_has_video (svc->metadata);
-	has_other_data = rb_metadata_has_other_data (svc->metadata);
-
-	if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &has_audio) ||
-	    !dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &has_video) ||
-	    !dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &has_other_data) ||
-	    !dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &mimetype)) {
-		rb_debug ("out of memory adding data to return message");
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
-
-	ok = (error == NULL);
-	if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &ok)) {
-		rb_debug ("out of memory adding error flag to return message");
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
 
-	if (error != NULL) {
-		rb_debug ("metadata error: %s", error->message);
-		if (append_error (&iter, error->code, error->message) == FALSE) {
-			rb_debug ("out of memory adding error details to return message");
-			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-		}
-	}
-
-	if (!rb_metadata_dbus_add_to_message (svc->metadata, &iter)) {
-		rb_debug ("unable to add metadata to 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;
+	response = g_variant_new ("(^as^asbbbsbisa{iv})",
+				  missing_plugins ? missing_plugins : (char **)nothing,
+				  plugin_descriptions ? plugin_descriptions : (char **)nothing,
+				  rb_metadata_has_audio (svc->metadata),
+				  rb_metadata_has_video (svc->metadata),
+				  rb_metadata_has_other_data (svc->metadata),
+				  mediatype ? mediatype : "",
+				  (error == NULL),
+				  (error != NULL ? error->code : 0),
+				  (error != NULL ? error->message : ""),
+				  rb_metadata_dbus_get_variant_builder (svc->metadata));
+	g_strfreev (missing_plugins);
+	g_strfreev (plugin_descriptions);
+
+	g_dbus_method_invocation_return_value (invocation, response);
 }
 
-static DBusHandlerResult
-rb_metadata_dbus_get_saveable_types (DBusConnection *connection,
-				     DBusMessage *message,
+static void
+rb_metadata_dbus_get_saveable_types (GVariant *parameters,
+				     GDBusMethodInvocation *invocation,
 				     ServiceData *svc)
 {
-	DBusMessageIter iter;
-	DBusMessage *reply;
 	char **saveable_types;
 
-	/* construct reply */
-	reply = dbus_message_new_method_return (message);
-	if (!reply) {
-		rb_debug ("out of memory creating return message");
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
-
-	dbus_message_iter_init_append (reply, &iter);
-
 	saveable_types = rb_metadata_get_saveable_types (svc->metadata);
-
-	if (!rb_metadata_dbus_add_strv (&iter, saveable_types)) {
-		rb_debug ("out of memory adding saveable types to return message");
-		g_strfreev (saveable_types);
-		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-	}
+	g_dbus_method_invocation_return_value (invocation, g_variant_new ("(^as)", saveable_types));
 	g_strfreev (saveable_types);
-
-	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;
 }
 
-static gboolean
-_set_metadata (gpointer key, GValue *data, RBMetaData *metadata)
-{
-	RBMetaDataField field = GPOINTER_TO_INT (key);
-	rb_metadata_set (metadata, field, data);
-	return TRUE;
-}
-
-static DBusHandlerResult
-rb_metadata_dbus_save (DBusConnection *connection,
-		       DBusMessage *message,
+static void
+rb_metadata_dbus_save (GVariant *parameters,
+		       GDBusMethodInvocation *invocation,
 		       ServiceData *svc)
 {
-	char *uri;
-	DBusMessageIter iter;
-	DBusMessage *reply;
-	GHashTable *data;
+	const char *uri;
 	GError *error = NULL;
+	GVariantIter *metadata;
+	RBMetaDataField key;
+	GVariant *value;
 
-	/* 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");
-	}
+	g_variant_get (parameters, "(&sa{iv})", &uri, &metadata);
 
-	/* pass to real metadata instance, and save it */
+	/* pass metadata to real metadata instance */
 	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;
+	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);
 	}
 
-	dbus_message_unref (reply);
-
-	return DBUS_HANDLER_RESULT_HANDLED;
+	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_ping (DBusConnection *connection,
-		       DBusMessage *message,
+static void
+rb_metadata_dbus_ping (GVariant *parameters,
+		       GDBusMethodInvocation *invocation,
 		       ServiceData *svc)
 {
-	gboolean ok = TRUE;
-
 	rb_debug ("ping");
-
-	DBusMessage *reply = dbus_message_new_method_return (message);
-	if (!message)
-		return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-	if (!dbus_message_append_args (reply,
-				       DBUS_TYPE_BOOLEAN, &ok,
-				       DBUS_TYPE_INVALID)) {
-		return DBUS_HANDLER_RESULT_NEED_MEMORY;
-	}
-
-	dbus_connection_send (connection, reply, NULL);
-	dbus_message_unref (reply);
-	return DBUS_HANDLER_RESULT_HANDLED;
+	g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
 }
 
 static gboolean
@@ -340,46 +181,48 @@ electromagnetic_shotgun (gpointer data)
 }
 
 static void
-_unregister_handler (DBusConnection *connection, void *data)
-{
-	/* nothing? */
-}
-
-static DBusHandlerResult
-_handle_message (DBusConnection *connection, DBusMessage *message, void *data)
+handle_method_call (GDBusConnection *connection,
+		    const char *sender,
+		    const char *object_path,
+		    const char *interface_name,
+		    const char *method_name,
+		    GVariant *parameters,
+		    GDBusMethodInvocation *invocation,
+		    ServiceData *svc)
 {
-	ServiceData *svc = (ServiceData *)data;
-	DBusHandlerResult result;
-	rb_debug ("handling metadata service message: %s", dbus_message_get_member (message));
-
-	if (dbus_message_is_method_call (message, RB_METADATA_DBUS_INTERFACE, "load")) {
-		result = rb_metadata_dbus_load (connection, message, svc);
-	} else if (dbus_message_is_method_call (message, RB_METADATA_DBUS_INTERFACE, "getSaveableTypes")) {
-		result = rb_metadata_dbus_get_saveable_types (connection, message, svc);
-	} else if (dbus_message_is_method_call (message, RB_METADATA_DBUS_INTERFACE, "save")) {
-		result = rb_metadata_dbus_save (connection, message, svc);
-	} else if (dbus_message_is_method_call (message, RB_METADATA_DBUS_INTERFACE, "ping")) {
-		result = rb_metadata_dbus_ping (connection, message, svc);
-	} else {
-		result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	rb_debug ("handling metadata service message: %s.%s", interface_name, method_name);
+	if (g_strcmp0 (method_name, "ping") == 0) {
+		rb_metadata_dbus_ping (parameters, invocation, svc);
+	} else if (g_strcmp0 (method_name, "load") == 0) {
+		rb_metadata_dbus_load (parameters, invocation, svc);
+	} else if (g_strcmp0 (method_name, "getSaveableTypes") == 0) {
+		rb_metadata_dbus_get_saveable_types (parameters, invocation, svc);
+	} else if (g_strcmp0 (method_name, "save") == 0) {
+		rb_metadata_dbus_save (parameters, invocation, svc);
 	}
-
 	svc->last_active = time (NULL);
-	return result;
 }
 
+static const GDBusInterfaceVTable metadata_vtable = {
+	(GDBusInterfaceMethodCallFunc) handle_method_call,
+	NULL,
+	NULL
+};
+
 static void
-_new_connection (DBusServer *server,
-		 DBusConnection *connection,
-		 void *data)
+connection_closed_cb (GDBusConnection *connection, ServiceData *svc)
 {
-	ServiceData *svc = (ServiceData *)data;
-	DBusObjectPathVTable vt = {
-		_unregister_handler,
-		_handle_message,
-		NULL, NULL, NULL, NULL
-	};
+	rb_debug ("client connection closed");
+	g_assert (connection == svc->connection);
+	svc->connection = NULL;
+}
 
+static void
+new_connection_cb (GDBusServer *server,
+		   GDBusConnection *connection,
+		   ServiceData *svc)
+{
+	GError *error = NULL;
 	rb_debug ("new connection to metadata service");
 
 	/* don't allow more than one connection at a time */
@@ -387,16 +230,22 @@ _new_connection (DBusServer *server,
 		rb_debug ("metadata service already has a client.  go away.");
 		return;
 	}
+	g_dbus_connection_register_object (connection,
+					   RB_METADATA_DBUS_OBJECT_PATH,
+					   g_dbus_node_info_lookup_interface (svc->node_info, RB_METADATA_DBUS_INTERFACE),
+					   &metadata_vtable,
+					   svc,
+					   NULL,
+					   &error);
+	if (error != NULL) {
+		rb_debug ("unable to register metadata object: %s", error->message);
+		g_clear_error (&error);
+	} else {
+		svc->connection = g_object_ref (connection);
+		g_signal_connect (connection, "closed", G_CALLBACK (connection_closed_cb), svc);
 
-	dbus_connection_register_object_path (connection,
-					      RB_METADATA_DBUS_OBJECT_PATH,
-					      &vt,
-					      svc);
-	dbus_connection_ref (connection);
-	dbus_connection_setup_with_g_main (connection,
-					   g_main_loop_get_context (svc->loop));
-	if (!svc->external)
-		dbus_connection_set_exit_on_disconnect (connection, TRUE);
+		g_dbus_connection_set_exit_on_close (connection, (svc->external == FALSE));
+	}
 }
 
 static int
@@ -473,8 +322,9 @@ int
 main (int argc, char **argv)
 {
 	ServiceData svc = {0,};
-	DBusError dbus_error = {0,};
+	GError *error = NULL;
 	const char *address = NULL;
+	char *guid;
 
 #ifdef ENABLE_NLS
 	/* initialize i18n */
@@ -516,49 +366,57 @@ main (int argc, char **argv)
 
 	rb_debug ("initializing metadata service; pid = %d; address = %s", getpid (), address);
 	svc.metadata = rb_metadata_new ();
+	svc.loop = g_main_loop_new (NULL, TRUE);
+
+	/* create the server */
+	guid = g_dbus_generate_guid ();
+	svc.server = g_dbus_server_new_sync (address,
+					     G_DBUS_SERVER_FLAGS_NONE,
+					     guid,
+					     NULL,
+					     NULL,
+					     &error);
+	g_free (guid);
+	if (error != NULL) {
+		g_warning ("D-Bus server init failed: %s", error->message);
+		return -1;
+	}
 
-	/* set up D-BUS server */
-	svc.server = dbus_server_listen (address, &dbus_error);
-	if (!svc.server) {
-		rb_debug ("D-BUS server init failed: %s", dbus_error.message);
+	/* set up interface info */
+	svc.node_info = g_dbus_node_info_new_for_xml (rb_metadata_iface_xml, &error);
+	if (error != NULL) {
+		g_warning ("D-Bus server init failed: %s", error->message);
 		return -1;
 	}
 
-	dbus_server_set_new_connection_function (svc.server,
-						 _new_connection,
-						 (gpointer) &svc,
-						 NULL);
+	g_signal_connect (svc.server, "new-connection", G_CALLBACK (new_connection_cb), &svc);
+	g_dbus_server_start (svc.server);
 
 	/* write the server address back to the parent process */
 	{
-		char *addr;
-		addr = dbus_server_get_address (svc.server);
+		const char *addr;
+		addr = g_dbus_server_get_client_address (svc.server);
 		rb_debug ("D-BUS server listening on address %s", addr);
 		printf ("%s\n", addr);
 		fflush (stdout);
-		free (addr);
 	}
 
 	/* run main loop until we get bored */
-	svc.loop = g_main_loop_new (NULL, TRUE);
-	dbus_server_setup_with_g_main (svc.server,
-				       g_main_loop_get_context (svc.loop));
-
 	if (!svc.external)
 		g_timeout_add_seconds (ATTENTION_SPAN / 2, (GSourceFunc) electromagnetic_shotgun, &svc);
 
 	g_main_loop_run (svc.loop);
 
 	if (svc.connection) {
-		dbus_connection_close (svc.connection);
-		dbus_connection_unref (svc.connection);
+		g_dbus_connection_close_sync (svc.connection, NULL, NULL);
+		g_object_unref (svc.connection);
 	}
 
 	g_object_unref (svc.metadata);
 	g_main_loop_unref (svc.loop);
 
-	dbus_server_disconnect (svc.server);
-	dbus_server_unref (svc.server);
+	g_dbus_server_stop (svc.server);
+	g_object_unref (svc.server);
 	gst_deinit ();
 
 	return 0;
diff --git a/metadata/rb-metadata-dbus.c b/metadata/rb-metadata-dbus.c
index 0afb54e..3e1921f 100644
--- a/metadata/rb-metadata-dbus.c
+++ b/metadata/rb-metadata-dbus.c
@@ -36,268 +36,71 @@
 #include "rb-metadata-dbus.h"
 #include "rb-debug.h"
 
-static gboolean
-_get_basic_checked (DBusMessageIter *iter, gpointer value, int type)
+const char *rb_metadata_iface_xml = "				\
+<node>								\
+  <interface name='org.gnome.Rhythmbox.Metadata'>		\
+    <method name='ping'>					\
+      <arg direction='out' type='b' name='ok'/>			\
+    </method>							\
+    <method name='load'>					\
+      <arg direction='in' type='s' name='uri'/>			\
+      <arg direction='out' type='as' name='missingPlugins'/>	\
+      <arg direction='out' type='as' name='pluginDescriptions'/> \
+      <arg direction='out' type='b' name='hasAudio'/>		\
+      <arg direction='out' type='b' name='hasVideo'/>		\
+      <arg direction='out' type='b' name='hasOtherData'/>	\
+      <arg direction='out' type='s' name='mimeType'/>		\
+      <arg direction='out' type='b' name='ok'/>			\
+      <arg direction='out' type='i' name='errorCode'/>		\
+      <arg direction='out' type='s' name='errorString'/>	\
+      <arg direction='out' type='a{iv}' name='metadata'/>	\
+    </method>							\
+    <method name='getSaveableTypes'>				\
+      <arg direction='out' type='as' name='types'/>		\
+    </method>							\
+    <method name='save'>					\
+      <arg direction='in' type='s' name='uri'/>			\
+      <arg direction='in' type='a{iv}' name='metadata'/>	\
+      <arg direction='out' type='b' name='ok'/>			\
+      <arg direction='out' type='i' name='errorCode'/>		\
+      <arg direction='out' type='s' name='errorString'/>	\
+    </method>							\
+  </interface>							\
+</node>";
+
+GVariantBuilder *
+rb_metadata_dbus_get_variant_builder (RBMetaData *md)
 {
-	if (dbus_message_iter_get_arg_type (iter) != type) {
-		rb_debug ("Expected D-BUS type '%c', got '%c'",
-			  type, dbus_message_iter_get_arg_type (iter));
-		return FALSE;
-	}
-	dbus_message_iter_get_basic (iter, value);
-	dbus_message_iter_next (iter);
-	return TRUE;
-}
-
-gboolean
-rb_metadata_dbus_get_boolean (DBusMessageIter *iter, gboolean *value)
-{
-	return _get_basic_checked (iter, value, DBUS_TYPE_BOOLEAN);
-}
-
-gboolean
-rb_metadata_dbus_get_uint32 (DBusMessageIter *iter, guint32 *value)
-{
-	return _get_basic_checked (iter, value, DBUS_TYPE_UINT32);
-}
-
-gboolean
-rb_metadata_dbus_get_string (DBusMessageIter *iter, gchar **value)
-{
-	gchar *msg_value;
-	if (!_get_basic_checked (iter, &msg_value, DBUS_TYPE_STRING))
-		return FALSE;
-	*value = g_strdup (msg_value);
-	return TRUE;
-}
-
-gboolean
-rb_metadata_dbus_get_strv (DBusMessageIter *iter, char ***strv)
-{
-	guint32 count;
-	guint32 i;
-
-	/* strv is stored as a count followed by that many strings */
-	if (rb_metadata_dbus_get_uint32 (iter, &count) == FALSE) {
-		return FALSE;
-	}
-
-	if (count == 0) {
-		*strv = NULL;
-		return TRUE;
-	}
-
-	*strv = g_new0 (char *, count+1);
-	for (i = 0; i < count; i++) {
-		if (rb_metadata_dbus_get_string (iter, (*strv)+i) == FALSE) {
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
-gboolean
-rb_metadata_dbus_add_strv (DBusMessageIter *iter, char **strv)
-{
-	guint32 count;
-	guint32 i;
-
-	if (strv == NULL) {
-		count = 0;
-	} else {
-		count = g_strv_length ((char **)strv);
-	}
-
-	if (!dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &count)) {
-		return FALSE;
-	}
-
-	for (i=0; i < count; i++) {
-		if (!dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &strv[i])) {
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
-gboolean
-rb_metadata_dbus_add_to_message (RBMetaData *md, DBusMessageIter *iter)
-{
-	DBusMessageIter a_iter;
+	GVariantBuilder *b;
 	RBMetaDataField field;
-	const char *etype =
-		DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-		DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
-	rb_debug ("opening container type %s", etype);
-	if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, etype, &a_iter)) {
-		return FALSE;
-	}
+	int count = 0;
 
+	b = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
 	for (field = RB_METADATA_FIELD_TITLE; field < RB_METADATA_FIELD_LAST; field++) {
-		GType vtype = rb_metadata_get_field_type (field);
 		GValue v = {0,};
-		DBusMessageIter d_iter;
-		DBusMessageIter v_iter;
-		const char *v_sig = NULL;
+		GVariant *value;
 
 		if (!rb_metadata_get (md, field, &v))
 			continue;
 
-		if (!dbus_message_iter_open_container (&a_iter, DBUS_TYPE_DICT_ENTRY, NULL, &d_iter)) {
-			return FALSE;
-		}
-
-		if (!dbus_message_iter_append_basic (&d_iter, DBUS_TYPE_UINT32, &field)) {
-			return FALSE;
-		}
-
-		switch (vtype) {
-		case G_TYPE_ULONG:
-			v_sig = DBUS_TYPE_UINT32_AS_STRING;
-			break;
-		case G_TYPE_DOUBLE:
-			v_sig = DBUS_TYPE_DOUBLE_AS_STRING;
-			break;
-		case G_TYPE_STRING:
-			v_sig = DBUS_TYPE_STRING_AS_STRING;
-			break;
-		}
-		if (!dbus_message_iter_open_container (&d_iter, DBUS_TYPE_VARIANT, v_sig, &v_iter)) {
-			return FALSE;
-		}
-
-		/* not exactly stolen from dbus-gvalue.c */
-		switch (vtype) {
-		case G_TYPE_ULONG:
-			{
-				dbus_uint32_t n = g_value_get_ulong (&v);
-				if (!dbus_message_iter_append_basic (&v_iter, DBUS_TYPE_UINT32, &n)) {
-					return FALSE;
-				}
-				break;
-			}
-
-		case G_TYPE_DOUBLE:
-			{
-				double n = g_value_get_double (&v);
-				if (!dbus_message_iter_append_basic (&v_iter, DBUS_TYPE_DOUBLE, &n)) {
-					return FALSE;
-				}
-				break;
-			}
-
-		case G_TYPE_STRING:
-			{
-				const char *s = g_value_get_string (&v);
-				if (!s)
-					s = "";
-				if (!dbus_message_iter_append_basic (&v_iter, DBUS_TYPE_STRING, &s)) {
-					return FALSE;
-				}
-				break;
-			}
-
-		default:
+		if (G_VALUE_HOLDS_STRING (&v)) {
+			value = g_variant_new_string (g_value_get_string (&v));
+		} else if (G_VALUE_HOLDS_ULONG (&v)) {
+			value = g_variant_new_uint32 (g_value_get_ulong (&v));
+		} else if (G_VALUE_HOLDS_DOUBLE (&v)) {
+			value = g_variant_new_double (g_value_get_double (&v));
+		} else {
 			g_assert_not_reached ();
-			break;
 		}
-
 		g_value_unset (&v);
-		if (!dbus_message_iter_close_container (&d_iter, &v_iter)) {
-			return FALSE;
-		}
-
-		if (!dbus_message_iter_close_container (&a_iter, &d_iter)) {
-			return FALSE;
-		}
-	}
-
-	if (!dbus_message_iter_close_container (iter, &a_iter)) {
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-gboolean
-rb_metadata_dbus_read_from_message (RBMetaData *md, GHashTable *metadata, DBusMessageIter *iter)
-{
-	DBusMessageIter a_iter;
-	int current_type;
 
-	if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY) {
-		rb_debug ("Expected D-BUS array, got type '%c'",
-			  dbus_message_iter_get_arg_type (iter));
-		return FALSE;
+		g_variant_builder_add (b, "{iv}", field, value);
+		count++;
 	}
 
-	dbus_message_iter_recurse (iter, &a_iter);
-
-	current_type = dbus_message_iter_get_arg_type (&a_iter);
-	if (current_type != DBUS_TYPE_INVALID && current_type != DBUS_TYPE_DICT_ENTRY) {
-		rb_debug ("Expected D-BUS dict entry, got type '%c'", (guchar) current_type);
-		return FALSE;
-	}
-
-	while (current_type != DBUS_TYPE_INVALID) {
-		DBusMessageIter e_iter;
-		DBusMessageIter v_iter;
-		RBMetaDataField field;
-		GValue *val;
-
-		dbus_message_iter_recurse (&a_iter, &e_iter);
-
-		if (!rb_metadata_dbus_get_uint32 (&e_iter, &field)) {
-			return FALSE;
-		}
-
-		if (dbus_message_iter_get_arg_type (&e_iter) != DBUS_TYPE_VARIANT) {
-			rb_debug ("Expected D-BUS variant type for value; got type '%c'",
-				  dbus_message_iter_get_arg_type (&e_iter));
-			return FALSE;
-		}
-
-		dbus_message_iter_recurse (&e_iter, &v_iter);
-		val = g_slice_new0 (GValue);
-		switch (dbus_message_iter_get_arg_type (&v_iter)) {
-		case DBUS_TYPE_UINT32:
-			{
-				dbus_uint32_t n;
-				dbus_message_iter_get_basic (&v_iter, &n);
-				g_value_init (val, G_TYPE_ULONG);
-				g_value_set_ulong (val, n);
-				break;
-			}
-
-		case DBUS_TYPE_DOUBLE:
-			{
-				double n;
-				dbus_message_iter_get_basic (&v_iter, &n);
-				g_value_init (val, G_TYPE_DOUBLE);
-				g_value_set_double (val, n);
-				break;
-			}
-
-		case DBUS_TYPE_STRING:
-			{
-				const gchar *n;
-				dbus_message_iter_get_basic (&v_iter, &n);
-				g_value_init (val, G_TYPE_STRING);
-				g_value_set_string (val, n);
-				break;
-			}
-
-		default:
-			g_assert_not_reached ();
-			break;
-		}
-
-		g_hash_table_insert (metadata, GINT_TO_POINTER (field), val);
-
-		dbus_message_iter_next (&a_iter);
-		current_type = dbus_message_iter_get_arg_type (&a_iter);
+	if (count == 0) {
+		g_variant_builder_add (b, "{iv}", RB_METADATA_FIELD_TRACK_NUMBER, g_variant_new_uint32 (0));
 	}
 
-	return TRUE;
+	return b;
 }
diff --git a/metadata/rb-metadata-dbus.h b/metadata/rb-metadata-dbus.h
index e365426..8187da6 100644
--- a/metadata/rb-metadata-dbus.h
+++ b/metadata/rb-metadata-dbus.h
@@ -32,13 +32,11 @@
 #ifndef __RB_METADATA_DBUS_H
 #define __RB_METADATA_DBUS_H
 
-#include <dbus/dbus.h>
-
 G_BEGIN_DECLS
 
-#define RB_METADATA_DBUS_NAME		"org.gnome.rhythmbox.Metadata"
-#define RB_METADATA_DBUS_OBJECT_PATH	"/org/gnome/rhythmbox/MetadataService"
-#define RB_METADATA_DBUS_INTERFACE	"org.gnome.rhythmbox.Metadata"
+#define RB_METADATA_DBUS_NAME		"org.gnome.Rhythmbox.Metadata"
+#define RB_METADATA_DBUS_OBJECT_PATH	"/org/gnome/Rhythmbox/MetadataService"
+#define RB_METADATA_DBUS_INTERFACE	"org.gnome.Rhythmbox.Metadata"
 
 /* Timeouts in milliseconds.  If a metadata operation takes longer than this,
  * the metadata process will be killed and the operation will fail.  We use a
@@ -48,23 +46,9 @@ G_BEGIN_DECLS
 #define RB_METADATA_DBUS_TIMEOUT	(15000)
 #define RB_METADATA_SAVE_DBUS_TIMEOUT	(120000)
 
-gboolean	rb_metadata_dbus_get_boolean (DBusMessageIter *iter,
-					      gboolean *value);
-gboolean	rb_metadata_dbus_get_uint32 (DBusMessageIter *iter,
-					     guint32 *value);
-gboolean	rb_metadata_dbus_get_string (DBusMessageIter *iter,
-					     gchar **value);
-gboolean	rb_metadata_dbus_get_strv (DBusMessageIter *iter,
-					   char ***strv);
-
-gboolean	rb_metadata_dbus_add_strv (DBusMessageIter *iter,
-					   char **strv);
+const char *rb_metadata_iface_xml;
 
-gboolean	rb_metadata_dbus_add_to_message (RBMetaData *md,
-						 DBusMessageIter *iter);
-gboolean	rb_metadata_dbus_read_from_message (RBMetaData *md,
-						    GHashTable *metadata,
-						    DBusMessageIter *iter);
+GVariantBuilder *rb_metadata_dbus_get_variant_builder (RBMetaData *md);
 
 G_END_DECLS
 
diff --git a/metadata/test-metadata.c b/metadata/test-metadata.c
index cdc9a31..e42a2a3 100644
--- a/metadata/test-metadata.c
+++ b/metadata/test-metadata.c
@@ -165,7 +165,6 @@ int main(int argc, char **argv)
 		rb_debug_init (TRUE);
 	}
 
-
 	loop = g_main_loop_new (NULL, FALSE);
 	md = rb_metadata_new ();
 	while (argv[1] != NULL) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]