--- ../rhythmbox-0.11.2/plugins/daap/rb-daap-source.c	2007-12-31 18:49:04.000000000 +0000
+++ plugins/daap/rb-daap-source.c	2007-12-31 19:01:05.000000000 +0000
@@ -43,6 +43,8 @@
 #include "rb-dialog.h"
 #include "rb-preferences.h"
 #include "rb-daap-src.h"
+#include "rb-player.h"
+#include "rb-shell-player.h"
 
 #include "rb-daap-connection.h"
 #include "rb-daap-mdns-browser.h"
@@ -51,6 +53,9 @@
 
 #include "rb-static-playlist-source.h"
 
+static GObject *rb_daap_source_constructor (GType type,
+					  guint n_construct_properties,
+					  GObjectConstructParam *construct_properties);
 static void rb_daap_source_dispose (GObject *object);
 static void rb_daap_source_set_property  (GObject *object,
 					  guint prop_id,
@@ -67,6 +72,26 @@
 static char * rb_daap_source_get_paned_key (RBBrowserSource *source);
 static void rb_daap_source_get_status (RBSource *source, char **text, char **progress_text, float *progress);
 static char * rb_daap_source_get_playback_uri (RhythmDBEntry *entry, gpointer data);
+static void playing_source_changed_cb (RBShellPlayer *player,
+					  RBSource *source,
+					  RBDAAPSource *daap_source);
+static void playing_entry_changed_cb (RBShellPlayer *player,
+					  RhythmDBEntry *entry,
+					  RBDAAPSource *source);
+static void info_available_cb (RBPlayer *backend,
+					  const char *uri,
+					  RBMetaDataField field,
+					  GValue *value,
+					  RBDAAPSource *source);
+static GValue * streaming_title_request_cb (RhythmDB *db,
+					  RhythmDBEntry *entry,
+					  RBDAAPSource *source);
+static GValue * streaming_artist_request_cb (RhythmDB *db,
+					  RhythmDBEntry *entry,
+					  RBDAAPSource *source);
+static GValue * streaming_album_request_cb (RhythmDB *db,
+					  RhythmDBEntry *entry,
+					  RBDAAPSource *source);
 
 #define CONF_STATE_SORTING CONF_PREFIX "/state/daap/sorting"
 #define CONF_STATE_PANED_POSITION CONF_PREFIX "/state/daap/paned_position"
@@ -90,6 +115,14 @@
 
 	gboolean tried_password;
 	gboolean disconnecting;
+
+	RhythmDB *db;
+	RhythmDBEntry *playing_stream;
+	RBShellPlayer *player;
+
+	char *streaming_title;
+
+	gint info_available_id;
 };
 
 enum {
@@ -110,6 +143,23 @@
 	/* we should already have been disconnected */
 	g_assert (source->priv->connection == NULL);
 
+	if (source->priv->player) {
+		g_object_unref (source->priv->player);
+		source->priv->player = NULL;
+	}
+
+	if (source->priv->db) {
+		g_object_unref (source->priv->db);
+		source->priv->db = NULL;
+	}
+
+	if (source->priv->playing_stream) {
+		rhythmdb_entry_unref (source->priv->playing_stream);
+		source->priv->playing_stream = NULL;
+	}
+
+	g_free (source->priv->streaming_title);
+
 	G_OBJECT_CLASS (rb_daap_source_parent_class)->dispose (object);
 }
 
@@ -132,6 +182,7 @@
 	RBBrowserSourceClass *browser_source_class = RB_BROWSER_SOURCE_CLASS (klass);
 
 	object_class->dispose      = rb_daap_source_dispose;
+	object_class->constructor  = rb_daap_source_constructor;
 	object_class->finalize     = rb_daap_source_finalize;
 	object_class->get_property = rb_daap_source_get_property;
 	object_class->set_property = rb_daap_source_set_property;
@@ -196,6 +247,49 @@
 						    RBDAAPSourcePrivate);
 }
 
+static GObject *rb_daap_source_constructor (GType type,
+				  guint n_construct_properties,
+				  GObjectConstructParam *construct_properties)
+{
+	RBDAAPSource *source;
+	RBShell *shell;
+
+	source = RB_DAAP_SOURCE (G_OBJECT_CLASS (rb_daap_source_parent_class)
+				->constructor (type, n_construct_properties, construct_properties));
+
+	g_object_get (G_OBJECT (source), "shell", &shell, NULL);
+	g_object_get (G_OBJECT (shell),
+				"db", &source->priv->db,
+				"shell-player", &source->priv->player,
+				NULL);
+	g_object_unref (G_OBJECT (shell));
+
+	g_signal_connect_object (source->priv->player, "playing-source-changed",
+				G_CALLBACK (playing_source_changed_cb),
+				source, 0);
+
+	g_signal_connect_object (source->priv->player, "playing-song-changed",
+				G_CALLBACK (playing_entry_changed_cb),
+				source, 0);
+
+	g_signal_connect_object (G_OBJECT (source->priv->db),
+				"entry-extra-metadata-request::" RHYTHMDB_PROP_STREAM_SONG_TITLE,
+				G_CALLBACK (streaming_title_request_cb),
+				source, 0);
+
+	g_signal_connect_object (G_OBJECT (source->priv->db),
+				"entry-extra-metadata-request::" RHYTHMDB_PROP_STREAM_SONG_ARTIST,
+				G_CALLBACK (streaming_artist_request_cb),
+				source, 0);
+
+	g_signal_connect_object (G_OBJECT (source->priv->db),
+				"entry-extra-metadata-request::" RHYTHMDB_PROP_STREAM_SONG_ALBUM,
+				G_CALLBACK (streaming_album_request_cb),
+				source, 0);
+
+	return G_OBJECT (source);
+}
+
 static void
 rb_daap_source_set_property (GObject *object,
 			    guint prop_id,
@@ -757,3 +851,178 @@
 
 	return g_strdup (location);
 }
+
+static void
+playing_source_changed_cb (RBShellPlayer *player,
+			  RBSource *source,
+			  RBDAAPSource *daap_source)
+{
+	GObject *backend;
+
+	g_object_get (player, "player", &backend, NULL);
+
+	/* Disconnect if switching between our own sources or to somebody else's */
+	if (daap_source->priv->info_available_id) {
+		rb_debug ("disconnecting info-available signal handler");
+		g_signal_handler_disconnect (backend,
+						 daap_source->priv->info_available_id);
+		daap_source->priv->info_available_id = 0;
+	}
+
+	/* Connect if the new source is our main browser or one of our playlists */
+	if (source == RB_SOURCE (daap_source) ||
+		g_slist_find (daap_source->priv->playlist_sources, source))
+	{
+		rb_debug ("connecting info-available signal handler");
+		daap_source->priv->info_available_id =
+			g_signal_connect_object (backend, "info",
+						 G_CALLBACK (info_available_cb),
+						 daap_source, 0);
+	}
+
+	g_object_unref (backend);
+}
+
+static void
+playing_entry_changed_cb (RBShellPlayer *player,
+			  RhythmDBEntry *entry,
+			  RBDAAPSource *source)
+{
+	if (!entry || source->priv->playing_stream == entry) {
+		return;
+	}
+
+	/* Forget the old streaming title - a new one will be set on-demand */
+	g_free (source->priv->streaming_title);
+	source->priv->streaming_title = NULL;
+
+	if (source->priv->playing_stream) {
+		rhythmdb_entry_unref (source->priv->playing_stream);
+	}
+
+	source->priv->playing_stream = rhythmdb_entry_ref (entry);
+}
+
+static gboolean
+check_entry_type (RBDAAPSource *source, RhythmDBEntry *entry)
+{
+	RhythmDBEntryType entry_type;
+	gboolean matches = FALSE;
+
+	g_object_get (source, "entry-type", &entry_type, NULL);
+	if (entry != NULL && rhythmdb_entry_get_entry_type (entry) == entry_type)
+		matches = TRUE;
+	g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type);
+
+	return matches;
+}
+
+static void
+info_available_cb (RBPlayer *backend,
+			  const char *uri,
+			  RBMetaDataField field,
+			  GValue *value,
+			  RBDAAPSource *source)
+{
+	char *str = NULL;
+	const char *location;
+	GValue v = {0,};
+	RhythmDBEntry *entry;
+
+	/* sanity check */
+	if (!rb_player_opened (backend)) {
+		rb_debug ("Got info_available but not playing");
+		return;
+	}
+
+	entry = rb_shell_player_get_playing_entry (source->priv->player);
+	if (check_entry_type (source, entry) == FALSE)
+		goto out_unlock;
+
+	/* Ignore entries that do not point to a radio station URL */
+	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MOUNTPOINT);
+	if(!location || location[0] == '\0') {
+		return;
+	}
+
+	/* validate the value */
+	switch (field) {
+	case RB_METADATA_FIELD_TITLE:
+		str = g_value_dup_string (value);
+		if (!g_utf8_validate (str, -1, NULL)) {
+			g_warning ("Invalid UTF-8 from internet radio: %s", str);
+			g_free (str);
+			goto out_unlock;
+		}
+		break;
+	default:
+		break;
+	}
+
+	switch (field) {
+	case RB_METADATA_FIELD_TITLE:
+		/* Record streaming radio title and notify shell */
+		g_free (source->priv->streaming_title);
+		source->priv->streaming_title = g_strdup (str);
+
+		g_value_init (&v, G_TYPE_STRING);
+		g_value_set_string (&v, source->priv->streaming_title);
+		rhythmdb_emit_entry_extra_metadata_notify (source->priv->db,
+					  source->priv->playing_stream,
+						RHYTHMDB_PROP_STREAM_SONG_TITLE,
+						&v);
+		g_value_unset (&v);
+		break;
+	default:
+		break;
+	}
+
+	g_free (str);
+
+ out_unlock:
+	GDK_THREADS_LEAVE ();
+}
+
+static GValue *
+handle_streaming_request (RhythmDBEntry *entry,
+				RBDAAPSource *source,
+				char *metadata)
+{
+	GValue *value;
+	if (check_entry_type (source, entry) == FALSE ||
+		entry != rb_shell_player_get_playing_entry (source->priv->player) ||
+		source->priv->streaming_title == NULL)
+	{
+		return NULL;
+	}
+
+	value = g_new0 (GValue, 1);
+	g_value_init (value, G_TYPE_STRING);
+	g_value_set_string (value, metadata);
+
+	return value;
+}
+
+static GValue *
+streaming_title_request_cb (RhythmDB *db,
+			  RhythmDBEntry *entry,
+			  RBDAAPSource *source)
+{
+	return handle_streaming_request (entry, source, source->priv->streaming_title);
+}
+
+static GValue *
+streaming_artist_request_cb (RhythmDB *db,
+			  RhythmDBEntry *entry,
+			  RBDAAPSource *source)
+{
+	return handle_streaming_request (entry, source, "");
+}
+
+static GValue *
+streaming_album_request_cb (RhythmDB *db,
+			  RhythmDBEntry *entry,
+			  RBDAAPSource *source)
+{
+	return handle_streaming_request (entry, source, "");
+}
--- ../rhythmbox-0.11.2/plugins/daap/Makefile.am	2007-08-01 09:04:10.000000000 +0100
+++ plugins/daap/Makefile.am	2007-12-31 18:47:57.000000000 +0000
@@ -62,6 +62,7 @@
 	-I$(top_srcdir)/plugins				\
 	-I$(top_srcdir)/shell				\
 	-I$(top_srcdir)/plugins				\
+	-I$(top_srcdir)/backends				\
 	-DPIXMAP_DIR=\""$(datadir)/pixmaps"\"		\
 	-DSHARE_DIR=\"$(pkgdatadir)\"                   \
 	-DDATADIR=\""$(datadir)"\"			\
