Index: rhythmdb/rhythmdb.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb.c,v
retrieving revision 1.249
diff -u -p -r1.249 rhythmdb.c
--- rhythmdb/rhythmdb.c	19 Aug 2006 07:26:34 -0000	1.249
+++ rhythmdb/rhythmdb.c	22 Aug 2006 23:34:47 -0000
@@ -113,6 +113,7 @@ static void rhythmdb_sync_library_locati
 static void rhythmdb_entry_sync_mirrored (RhythmDBEntry *entry,
 					  guint propid);
 static void rhythmdb_register_core_entry_types (RhythmDB *db);
+static gboolean rhythmdb_entry_extra_metadata_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer data);
 
 enum
 {
@@ -127,6 +128,8 @@ enum
 	ENTRY_ADDED,
 	ENTRY_CHANGED,
 	ENTRY_DELETED,
+	ENTRY_EXTRA_METADATA_REQUEST,
+	ENTRY_EXTRA_METADATA_NOTIFY,
 	LOAD_COMPLETE,
 	SAVE_COMPLETE,
 	SAVE_ERROR,
@@ -198,6 +201,26 @@ rhythmdb_class_init (RhythmDBClass *klas
 			      G_TYPE_NONE, 2,
 			      RHYTHMDB_TYPE_ENTRY, G_TYPE_POINTER);
 
+	rhythmdb_signals[ENTRY_EXTRA_METADATA_REQUEST] =
+		g_signal_new ("entry_extra_metadata_request",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+			      G_STRUCT_OFFSET (RhythmDBClass, entry_extra_metadata_request),
+			      rhythmdb_entry_extra_metadata_accumulator, NULL,
+			      rb_marshal_BOXED__BOXED,
+			      G_TYPE_VALUE, 1,
+			      RHYTHMDB_TYPE_ENTRY);
+
+	rhythmdb_signals[ENTRY_EXTRA_METADATA_NOTIFY] =
+		g_signal_new ("entry_extra_metadata_notify",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+			      G_STRUCT_OFFSET (RhythmDBClass, entry_extra_metadata_notify),
+			      NULL, NULL,
+			      rb_marshal_VOID__BOXED_BOXED,
+			      G_TYPE_NONE, 2,
+			      RHYTHMDB_TYPE_ENTRY, G_TYPE_VALUE);
+
 	rhythmdb_signals[LOAD_COMPLETE] =
 		g_signal_new ("load_complete",
 			      RHYTHMDB_TYPE,
@@ -3361,6 +3384,79 @@ rhythmdb_emit_entry_deleted (RhythmDB *d
 			     RhythmDBEntry *entry)
 {
 	g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_DELETED], 0, entry);
+}
+
+static gboolean
+rhythmdb_entry_extra_metadata_accumulator (GSignalInvocationHint *ihint,
+					   GValue *return_accu,
+					   const GValue *handler_return,
+					   gpointer data)
+{
+	g_value_copy (handler_return, return_accu);
+	return (g_value_get_boxed (return_accu) != NULL);
+}
+
+/**
+ * rhythmdb_entry_request_extra_metadata:
+ * @db: a #RhythmDB
+ * @entry: a #RhythmDBEntry
+ * @property_name: the metadata predicate
+ *
+ * Emits a request for extra metadata for the @entry.
+ * The @property_name argument is emitted as the ::detail part of the 
+ * "entry_extra_metadata_request" signal. It should be a namespaced RDF 
+ * predicate e.g. from Dublin Core, MusicBrainz, or internal to Rhythmbox
+ * (namespace "rb:"). Suitable predicates would be those that are expensive to
+ * acquire or only apply to a limited range of entries.
+ * Handlers capable of providing a particular predicate may ensure they only
+ * see appropriate requests by supplying an appropriate ::detail part when
+ * connecting to the signal. Upon a handler returning a non-%NULL value,
+ * emission will be stopped and the value returned to the caller; if no
+ * handlers return a non-%NULL value, the caller will receive %NULL. Priority
+ * is determined by signal connection order, with %G_CONNECT_AFTER providing a 
+ * second, lower rank of priority.
+ * A handler returning a value should do so in a #GValue allocated on the heap;
+ * the accumulator will take ownership. The caller should unset and free the
+ * #GValue if non-%NULL when finished with it.
+ *
+ * Returns: an allocated, initialised, set #GValue, or NULL
+ **/
+GValue *
+rhythmdb_entry_request_extra_metadata (RhythmDB *db,
+				       RhythmDBEntry *entry,
+				       const gchar *property_name)
+{
+	GValue value = {0, }, *value_ret;
+	g_value_init (&value, G_TYPE_VALUE);
+	g_value_set_boxed (&value, NULL);
+	g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_EXTRA_METADATA_NOTIFY], g_quark_from_string (property_name), entry, &value);
+	value_ret = (GValue *) g_value_dup_boxed (&value);
+	g_value_unset (&value);
+	return value_ret;
+}
+
+/**
+ * rhythmdb_emit_entry_extra_metadata_notify:
+ * @db: a #RhythmDB
+ * @entry: a #RhythmDBEntry
+ * @property_name: the metadata predicate
+ * @metadata: a #GValue
+ *
+ * Emits a signal describing extra metadata for the @entry.
+ * The @property_name argument is emitted as the ::detail part of the 
+ * "entry_extra_metadata_notify" signal. Handlers can ensure they only get 
+ * metadata they are interested in by supplying an appropriate ::detail part 
+ * when connecting to the signal. If handlers are interested in the metadata 
+ * they should ref or copy the contents of @metadata and unref or free it when 
+ * they are finished with it.
+ **/
+void
+rhythmdb_emit_entry_extra_metadata_notify (RhythmDB *db,
+					   RhythmDBEntry *entry,
+					   const gchar *property_name,
+					   GValue *metadata)
+{
+	g_signal_emit (G_OBJECT (db), rhythmdb_signals[ENTRY_EXTRA_METADATA_NOTIFY], g_quark_from_string (property_name), entry, metadata);
 }
 
 static gboolean
Index: rhythmdb/rhythmdb.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb.h,v
retrieving revision 1.96
diff -u -p -r1.96 rhythmdb.h
--- rhythmdb/rhythmdb.h	19 Aug 2006 07:26:38 -0000	1.96
+++ rhythmdb/rhythmdb.h	22 Aug 2006 23:34:48 -0000
@@ -254,6 +254,8 @@ typedef struct
 	void	(*entry_added)		(RhythmDB *db, RhythmDBEntry *entry);
 	void	(*entry_changed)	(RhythmDB *db, RhythmDBEntry *entry, GSList *changes); /* list of RhythmDBEntryChanges */
 	void	(*entry_deleted)	(RhythmDB *db, RhythmDBEntry *entry);
+	GValue *(*entry_extra_metadata_request) (RhythmDB *db, RhythmDBEntry *entry);
+	void	(*entry_extra_metadata_notify) (RhythmDB *db, RhythmDBEntry *entry, GValue *metadata);
 	void	(*load_complete)	(RhythmDB *db);
 	void	(*save_complete)	(RhythmDB *db);
 	void	(*load_error)		(RhythmDB *db, const char *uri, const char *msg);
@@ -393,6 +395,9 @@ int		rhythmdb_propid_from_nice_elt_name	
 
 void		rhythmdb_emit_entry_added		(RhythmDB *db, RhythmDBEntry *entry);
 void		rhythmdb_emit_entry_deleted		(RhythmDB *db, RhythmDBEntry *entry);
+
+GValue	       *rhythmdb_entry_request_extra_metadata		(RhythmDB *db, RhythmDBEntry *entry, const gchar *property_name);
+void		rhythmdb_emit_entry_extra_metadata_notify	(RhythmDB *db, RhythmDBEntry *entry, const gchar *property_name, GValue *metadata);
 
 gboolean	rhythmdb_is_busy			(RhythmDB *db);
 char *		rhythmdb_compute_status_normal		(gint n_songs, glong duration,
Index: lib/rb-marshal.list
===================================================================
RCS file: /cvs/gnome/rhythmbox/lib/rb-marshal.list,v
retrieving revision 1.20
diff -u -p -r1.20 rb-marshal.list
--- lib/rb-marshal.list	7 Jul 2006 22:41:42 -0000	1.20
+++ lib/rb-marshal.list	22 Aug 2006 23:34:48 -0000
@@ -4,6 +4,8 @@ INT:VOID
 OBJECT:OBJECT
 STRING:STRING
 VOID:BOOLEAN,BOOLEAN
+BOXED:BOXED
+VOID:BOXED,BOXED
 VOID:BOXED,INT,POINTER,POINTER
 VOID:BOXED,POINTER
 VOID:BOXED,ULONG
Index: plugins/rb-python-module.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/plugins/rb-python-module.c,v
retrieving revision 1.10
diff -u -p -r1.10 rb-python-module.c
--- plugins/rb-python-module.c	10 Aug 2006 15:12:24 -0000	1.10
+++ plugins/rb-python-module.c	22 Aug 2006 23:34:48 -0000
@@ -52,6 +52,35 @@ enum
 	PROP_MODULE
 };
 
+#ifndef PYGOBJECT_CAN_MARSHAL_GVALUE
+static PyObject *
+pyg_value_g_value_as_pyobject (const GValue *value)
+{
+	return pyg_value_as_pyobject((GValue *)g_value_get_boxed(value), FALSE);
+}
+
+static int
+pyg_value_g_value_from_pyobject (GValue *value, PyObject *obj)
+{
+	GType type;
+	GValue obj_value = { 0, };
+	
+	type = pyg_type_from_object((PyObject *) obj->ob_type);
+	if (! type) {
+		PyErr_Clear();
+		return -1;
+	}
+	g_value_init(&obj_value, type);
+	if (pyg_value_from_pyobject(&obj_value, obj) == -1) {
+		g_value_unset(&obj_value);
+		return -1;
+	}
+	g_value_set_boxed(value, &obj_value);
+	g_value_unset(&obj_value);
+	return 0;
+}
+#endif /* PYGOBJECT_CAN_MARSHAL_GVALUE */
+
 /* Exported by pyrhythmdb module */
 void pyrhythmdb_register_classes (PyObject *d);
 void pyrhythmdb_add_constants (PyObject *module, const gchar *strip_prefix);
@@ -125,6 +154,10 @@ rb_python_module_init_python (void)
 
 	/* import gobject */
 	init_pygobject ();
+
+#ifndef PYGOBJECT_CAN_MARSHAL_GVALUE
+	pyg_register_gtype_custom (G_TYPE_VALUE, pyg_value_g_value_as_pyobject, pyg_value_g_value_from_pyobject);
+#endif
 
 	/* import gtk */
 	init_pygtk ();
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/rhythmbox/configure.ac,v
retrieving revision 1.255
diff -u -p -r1.255 configure.ac
--- configure.ac	11 Aug 2006 05:32:53 -0000	1.255
+++ configure.ac	22 Aug 2006 23:34:50 -0000
@@ -898,6 +898,10 @@ if test "x$have_python" != "xno"; then
 	AC_SUBST([PYGTK_CODEGEN])
 	AC_SUBST([PYGTK_H2DEF])
 
+dnl	uncomment when http://bugzilla.gnome.org/show_bug.cgi?id=351072 fixed
+dnl	PKG_CHECK_EXISTS([pygobject-2.0 >= X.XX.X],
+dnl			 AC_DEFINE([PYGOBJECT_CAN_MARSHAL_GVALUE]))
+
 	dnl Check for -fno-strict-aliasing
 	FLAGS="-fno-strict-aliasing"
 	save_CFLAGS="$CFLAGS"
