diff -rN -u -p old-iradio/configure.ac new-iradio/configure.ac
--- old-iradio/configure.ac	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/configure.ac	2006-09-22 08:37:38.000000000 +1000
@@ -944,7 +944,6 @@ metadata/Makefile
 rhythmdb/Makefile
 widgets/Makefile
 widgets/libsexy/Makefile
-iradio/Makefile
 podcast/Makefile
 shell/Makefile
 data/Makefile
@@ -960,6 +959,7 @@ plugins/audiocd/Makefile
 plugins/audioscrobbler/Makefile
 plugins/cd-recorder/Makefile
 plugins/ipod/Makefile
+plugins/iradio/Makefile
 plugins/lirc/Makefile
 plugins/lyrics/Makefile
 plugins/sample-python/Makefile
diff -rN -u -p old-iradio/data/rhythmbox.schemas new-iradio/data/rhythmbox.schemas
--- old-iradio/data/rhythmbox.schemas	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/data/rhythmbox.schemas	2006-09-22 08:37:38.000000000 +1000
@@ -822,5 +822,27 @@
 	<long>True if the audio cd plugin is hidden.</long>
 	</locale>
       </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/iradio/active</key>
+	<applyto>/apps/rhythmbox/plugins/iradio/active</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>TRUE</default>
+	<locale name="C">
+	<short>True if the iradio plugin is enabled.</short>
+	<long>True if the iradio plugin is enabled.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/iradio/hidden</key>
+	<applyto>/apps/rhythmbox/plugins/iradio/hidden</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>TRUE</default>
+	<locale name="C">
+	<short>True if the iradio plugin is hidden.</short>
+	<long>True if the iradio plugin is hidden.</long>
+	</locale>
+      </schema>
     </schemalist>
 </gconfschemafile>
diff -rN -u -p old-iradio/data/ui/rhythmbox-ui.xml new-iradio/data/ui/rhythmbox-ui.xml
--- old-iradio/data/ui/rhythmbox-ui.xml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/data/ui/rhythmbox-ui.xml	2006-09-22 08:37:38.000000000 +1000
@@ -16,7 +16,7 @@
 	<separator name="MusicPlaylistSeparator1"/>
 	<menuitem name="MusicPlaylistDeletePlaylistMenu" action="MusicPlaylistDeletePlaylist"/>
       </menu>
-      <menuitem name="MusicNewInternetRadioStationMenu" action="MusicNewInternetRadioStation"/>
+      <placeholder name="MusicMenuNewPluginPlaceholder" />
       <menuitem name="MusicNewPodcastMenu" action="MusicNewPodcast"/>
       <separator/>
       <menuitem name="MusicPropertiesMenu" action="MusicProperties"/>
@@ -190,15 +190,6 @@
     <menuitem name="LibrarySrcPopupAddFolder" action="MusicImportFolder"/>
   </popup>
 
-  <popup name="IRadioSourcePopup">
-    <menuitem name="IRadioSrcPopupNewStation" action="MusicNewInternetRadioStation"/>
-  </popup>
-
-  <popup name="IRadioViewPopup">
-    <menuitem name="DeleteIRadioPopup" action="EditDelete"/>
-    <separator/>
-    <menuitem name="PropertiesIRadioPopup" action="MusicProperties"/>
-  </popup>
   <popup name="PodcastSourcePopup">
     <menuitem name="PodcastSrcPopupNew" action="MusicNewPodcast"/>
     <menuitem name="PodcastSrcPopupUpdateAllFeeds" action="PodcastUpdateAllFeeds"/>
diff -rN -u -p old-iradio/doc/reference/Makefile.am new-iradio/doc/reference/Makefile.am
--- old-iradio/doc/reference/Makefile.am	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/Makefile.am	2006-09-22 08:37:38.000000000 +1000
@@ -33,7 +33,6 @@ INCLUDES=\
 	-I$(top_srcdir)/metadata \
 	-I$(top_srcdir)/widgets \
 	-I$(top_srcdir)/lib \
-	-I$(top_srcdir)/iradio \
 	-I$(top_srcdir)/daapsharing \
 	-I$(top_srcdir)/plugins \
 	-I$(top_srcdir)/backends \
@@ -46,7 +45,6 @@ GTKDOC_LIBS=\
 	$(top_builddir)/sources/libsources.la	        \
 	$(top_builddir)/sources/libsourcesimpl.la	\
 	$(top_builddir)/rhythmdb/librhythmdb.la         \
-	$(top_builddir)/iradio/librbiradio.la	        \
 	$(top_builddir)/podcast/librbpodcast.la		\
 	$(top_builddir)/metadata/librbmetadata.la	\
 	$(top_builddir)/widgets/librbwidgets.la         \
diff -rN -u -p old-iradio/doc/reference/rhythmbox-sections.txt new-iradio/doc/reference/rhythmbox-sections.txt
--- old-iradio/doc/reference/rhythmbox-sections.txt	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/rhythmbox-sections.txt	2006-09-22 08:37:38.000000000 +1000
@@ -520,21 +520,6 @@ RB_SOURCELIST_MODEL_GET_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>rb-iradio-source</FILE>
-RBIRadioSourcePrivate
-rb_iradio_source_new
-rb_iradio_source_add_station
-<SUBSECTION Standard>
-RB_IRADIO_SOURCE
-RB_IS_IRADIO_SOURCE
-RB_TYPE_IRADIO_SOURCE
-rb_iradio_source_get_type
-RB_IRADIO_SOURCE_CLASS
-RB_IS_IRADIO_SOURCE_CLASS
-RB_IRADIO_SOURCE_GET_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>rb-ipod-source</FILE>
 rb_ipod_source_new
 rb_ipod_is_volume_ipod
@@ -652,34 +637,6 @@ RB_SOURCE_GET_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>rb-station-properties-dialog</FILE>
-RBStationPropertiesDialogPrivate
-rb_station_properties_dialog_new
-<SUBSECTION Standard>
-RB_STATION_PROPERTIES_DIALOG
-RB_IS_STATION_PROPERTIES_DIALOG
-RB_TYPE_STATION_PROPERTIES_DIALOG
-rb_station_properties_dialog_get_type
-RB_STATION_PROPERTIES_DIALOG_CLASS
-RB_IS_STATION_PROPERTIES_DIALOG_CLASS
-RB_STATION_PROPERTIES_DIALOG_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>rb-new-station-dialog</FILE>
-RBNewStationDialogPrivate
-rb_new_station_dialog_new
-<SUBSECTION Standard>
-RB_NEW_STATION_DIALOG
-RB_IS_NEW_STATION_DIALOG
-RB_TYPE_NEW_STATION_DIALOG
-rb_new_station_dialog_get_type
-RB_NEW_STATION_DIALOG_CLASS
-RB_IS_NEW_STATION_DIALOG_CLASS
-RB_NEW_STATION_DIALOG_GET_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>rb-player</FILE>
 RBPlayerError
 RB_PLAYER_TICK_HZ
diff -rN -u -p old-iradio/doc/reference/rhythmbox.types new-iradio/doc/reference/rhythmbox.types
--- old-iradio/doc/reference/rhythmbox.types	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/rhythmbox.types	2006-09-22 08:37:38.000000000 +1000
@@ -14,7 +14,6 @@
 #include "rb-glade-helpers.h"
 #include "rb-header.h"
 #include "rb-history.h"
-#include "rb-iradio-source.h"
 #include "rb-library-source.h"
 #include "rb-marshal.h"
 #include "rb-metadata.h"
@@ -46,7 +45,6 @@
 #include "rb-source-header.h"
 #include "rb-sourcelist.h"
 #include "rb-sourcelist-model.h"
-#include "rb-station-properties-dialog.h"
 #include "rb-statusbar.h"
 #include "rb-stock-icons.h"
 #include "rb-tray-icon.h"
@@ -62,7 +60,6 @@ rb_druid_get_type
 rb_entry_view_get_type
 rb_header_get_type
 rb_history_get_type
-rb_iradio_source_get_type
 rb_library_source_get_type
 rb_linear_play_order_get_type
 rb_linear_play_order_loop_get_type
@@ -89,7 +86,6 @@ rb_source_get_type
 rb_source_header_get_type
 rb_sourcelist_get_type
 rb_sourcelist_model_get_type
-rb_station_properties_dialog_get_type
 rb_statusbar_get_type
 rb_tray_icon_get_type
 rb_tree_drag_dest_get_type
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-daap-dialog.sgml new-iradio/doc/reference/tmpl/rb-daap-dialog.sgml
--- old-iradio/doc/reference/tmpl/rb-daap-dialog.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-daap-dialog.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -17,16 +17,6 @@ rb-daap-dialog
 <!-- ##### SECTION Stability_Level ##### -->
 
 
-<!-- ##### FUNCTION rb_daap_password_dialog_new_run ##### -->
-<para>
-
-</para>
-
-@parent: 
-@name: 
-@Returns: 
-
-
 <!-- ##### FUNCTION rb_daap_collision_dialog_new_run ##### -->
 <para>
 
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-debug.sgml new-iradio/doc/reference/tmpl/rb-debug.sgml
--- old-iradio/doc/reference/tmpl/rb-debug.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-debug.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -42,6 +42,8 @@ rb-debug
 
 @...:
 
+@...:
+
 @...: 
 
 
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-header.sgml new-iradio/doc/reference/tmpl/rb-header.sgml
--- old-iradio/doc/reference/tmpl/rb-header.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-header.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -39,6 +39,7 @@ rb-header
 
 @header: 
 @entry: 
+@seekable: 
 
 
 <!-- ##### FUNCTION rb_header_set_title ##### -->
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-query-creator-private.sgml new-iradio/doc/reference/tmpl/rb-query-creator-private.sgml
--- old-iradio/doc/reference/tmpl/rb-query-creator-private.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-query-creator-private.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -22,7 +22,7 @@ rb-query-creator-private
 
 </para>
 
-@constrain: 
+@rain: 
 @Returns: 
 
 
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-shell.sgml new-iradio/doc/reference/tmpl/rb-shell.sgml
--- old-iradio/doc/reference/tmpl/rb-shell.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-shell.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -64,23 +64,12 @@ rb-shell
 @Returns: 
 
 
-<!-- ##### FUNCTION rb_shell_guess_type_for_uri ##### -->
-<para>
-
-</para>
-
-@shell: 
-@uri: 
-@Returns: 
-
-
 <!-- ##### FUNCTION rb_shell_add_uri ##### -->
 <para>
 
 </para>
 
 @shell: 
-@entry_type: 
 @uri: 
 @title: 
 @genre: 
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-source.sgml new-iradio/doc/reference/tmpl/rb-source.sgml
--- old-iradio/doc/reference/tmpl/rb-source.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-source.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -239,15 +239,6 @@ RBSource
 @Returns: 
 
 
-<!-- ##### FUNCTION rb_source_have_url ##### -->
-<para>
-
-</para>
-
-@source: 
-@Returns: 
-
-
 <!-- ##### FUNCTION rb_source_receive_drag ##### -->
 <para>
 
diff -rN -u -p old-iradio/doc/reference/tmpl/rb-statusbar.sgml new-iradio/doc/reference/tmpl/rb-statusbar.sgml
--- old-iradio/doc/reference/tmpl/rb-statusbar.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rb-statusbar.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -29,7 +29,7 @@ rb-statusbar
 </para>
 
 @db: 
-@actiongroup: 
+@uimanager: 
 @Returns: 
 
 
diff -rN -u -p old-iradio/doc/reference/tmpl/rhythmbox-unused.sgml new-iradio/doc/reference/tmpl/rhythmbox-unused.sgml
--- old-iradio/doc/reference/tmpl/rhythmbox-unused.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rhythmbox-unused.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -1,3 +1,75 @@
+<!-- ##### SECTION ./tmpl/rb-iradio-source.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/rb-iradio-source.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/rb-iradio-source.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/rb-iradio-source.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/rb-iradio-source.sgml:Title ##### -->
+rb-iradio-source
+
+
+<!-- ##### SECTION ./tmpl/rb-new-station-dialog.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/rb-new-station-dialog.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/rb-new-station-dialog.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/rb-new-station-dialog.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/rb-new-station-dialog.sgml:Title ##### -->
+rb-new-station-dialog
+
+
+<!-- ##### SECTION ./tmpl/rb-station-properties-dialog.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/rb-station-properties-dialog.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/rb-station-properties-dialog.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/rb-station-properties-dialog.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/rb-station-properties-dialog.sgml:Title ##### -->
+rb-station-properties-dialog
+
+
 <!-- ##### TYPEDEF CDDBDisclosurePrivate ##### -->
 <para>
 
@@ -140,12 +212,24 @@
 @RB_DIRECTION_UP: 
 @RB_DIRECTION_DOWN: 
 
+<!-- ##### TYPEDEF RBIRadioSourcePrivate ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### TYPEDEF RBLoadFailureDialogPrivate ##### -->
 <para>
 
 </para>
 
 
+<!-- ##### TYPEDEF RBNewStationDialogPrivate ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### TYPEDEF RBPlayerPrivate ##### -->
 <para>
 
@@ -189,6 +273,12 @@
 </para>
 
 
+<!-- ##### TYPEDEF RBStationPropertiesDialogPrivate ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### TYPEDEF RBTreeModelSortPrivate ##### -->
 <para>
 
@@ -522,6 +612,15 @@
 
 @resolver: 
 
+<!-- ##### FUNCTION rb_daap_password_dialog_new_run ##### -->
+<para>
+
+</para>
+
+@parent: 
+@name: 
+@Returns: 
+
 <!-- ##### FUNCTION rb_daap_src_init ##### -->
 <para>
 
@@ -687,6 +786,24 @@
 @urltext: 
 @urllink: 
 
+<!-- ##### FUNCTION rb_iradio_source_add_station ##### -->
+<para>
+
+</para>
+
+@source: 
+@uri: 
+@title: 
+@genre: 
+
+<!-- ##### FUNCTION rb_iradio_source_new ##### -->
+<para>
+
+</para>
+
+@shell: 
+@Returns: 
+
 <!-- ##### FUNCTION rb_library_source_class_add_actions ##### -->
 <para>
 
@@ -719,6 +836,14 @@
 
 @Returns: 
 
+<!-- ##### FUNCTION rb_new_station_dialog_new ##### -->
+<para>
+
+</para>
+
+@view: 
+@Returns: 
+
 <!-- ##### FUNCTION rb_play_order_get_entry_view ##### -->
 <para>
 
@@ -873,6 +998,15 @@
 
 @shell: 
 
+<!-- ##### FUNCTION rb_shell_guess_type_for_uri ##### -->
+<para>
+
+</para>
+
+@shell: 
+@uri: 
+@Returns: 
+
 <!-- ##### FUNCTION rb_shell_player_get_mm_player ##### -->
 <para>
 
@@ -935,6 +1069,22 @@
 @source: 
 @Returns: 
 
+<!-- ##### FUNCTION rb_source_have_url ##### -->
+<para>
+
+</para>
+
+@source: 
+@Returns: 
+
+<!-- ##### FUNCTION rb_station_properties_dialog_new ##### -->
+<para>
+
+</para>
+
+@view: 
+@Returns: 
+
 <!-- ##### FUNCTION rb_statusbar_sync_state ##### -->
 <para>
 
diff -rN -u -p old-iradio/doc/reference/tmpl/rhythmdb.sgml new-iradio/doc/reference/tmpl/rhythmdb.sgml
--- old-iradio/doc/reference/tmpl/rhythmdb.sgml	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/doc/reference/tmpl/rhythmdb.sgml	2006-09-22 08:37:38.000000000 +1000
@@ -95,6 +95,7 @@ rhythmdb
 </para>
 
 @RHYTHMDB_PROP_TYPE: 
+@RHYTHMDB_PROP_ENTRY_ID: 
 @RHYTHMDB_PROP_TITLE: 
 @RHYTHMDB_PROP_GENRE: 
 @RHYTHMDB_PROP_ARTIST: 
diff -rN -u -p old-iradio/Makefile.am new-iradio/Makefile.am
--- old-iradio/Makefile.am	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/Makefile.am	2006-09-22 08:37:38.000000000 +1000
@@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = 1.7
 DISTCHECK_CONFIGURE_FLAGS = --disable-schemas-install --enable-gtk-doc --disable-scrollkeeper
 distuninstallcheck_listfiles = find . -type f -print | grep -v '^\./var/scrollkeeper'
 
-SUBDIRS = macros lib metadata rhythmdb widgets sources iradio podcast \
+SUBDIRS = macros lib metadata rhythmdb widgets sources podcast \
 	daapsharing backends plugins bindings shell remote data po help tests doc
 
 EXTRA_DIST = 			\
diff -rN -u -p old-iradio/plugins/audioscrobbler/rb-audioscrobbler.c new-iradio/plugins/audioscrobbler/rb-audioscrobbler.c
--- old-iradio/plugins/audioscrobbler/rb-audioscrobbler.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/plugins/audioscrobbler/rb-audioscrobbler.c	2006-09-22 08:37:38.000000000 +1000
@@ -1007,9 +1007,8 @@ rb_audioscrobbler_song_changed_cb (RBShe
 	}
 
 	type = rhythmdb_entry_get_entry_type (entry);
-	if (type == RHYTHMDB_ENTRY_TYPE_IRADIO_STATION ||
+	if (type->category != RHYTHMDB_ENTRY_NORMAL ||
 	    type == RHYTHMDB_ENTRY_TYPE_PODCAST_POST ||
-	    type == RHYTHMDB_ENTRY_TYPE_PODCAST_FEED ||
 	    rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_PLAYBACK_ERROR) != NULL) {
 		audioscrobbler->priv->should_queue = FALSE;
 		return;
diff -rN -u -p old-iradio/plugins/Makefile.am new-iradio/plugins/Makefile.am
--- old-iradio/plugins/Makefile.am	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/plugins/Makefile.am	2006-09-22 08:37:38.000000000 +1000
@@ -3,6 +3,7 @@
 SUBDIRS = 						\
 	generic-player					\
 	audiocd						\
+	iradio						\
 	sample
 
 if WITH_AUDIOSCROBBLER
diff -rN -u -p old-iradio/rhythmdb/rhythmdb.c new-iradio/rhythmdb/rhythmdb.c
--- old-iradio/rhythmdb/rhythmdb.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/rhythmdb/rhythmdb.c	2006-09-22 08:37:38.000000000 +1000
@@ -3706,7 +3780,6 @@ static RhythmDBEntryType ignore_type = R
 static RhythmDBEntryType import_error_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 
 /* to be evicted */
-static RhythmDBEntryType iradio_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 static RhythmDBEntryType podcast_post_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 static RhythmDBEntryType podcast_feed_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 
@@ -3717,26 +3790,24 @@ rhythmdb_register_core_entry_types (Rhyt
 	song_type = rhythmdb_entry_register_type (db, "song");
 	rhythmdb_entry_register_type_alias (db, song_type, "0");
 	song_type->save_to_disk = TRUE;
+	song_type->category = RHYTHMDB_ENTRY_NORMAL;
 	song_type->can_sync_metadata = song_can_sync_metadata;
 
 	/* import errors */
 	import_error_type = rhythmdb_entry_register_type (db, "import-error");
 	import_error_type->get_playback_uri = (RhythmDBEntryStringFunc)rb_null_function;
+	import_error_type->category = RHYTHMDB_ENTRY_VIRTUAL;
 
 	/* ignored files */
 	ignore_type = rhythmdb_entry_register_type (db, "ignore");
 	ignore_type->save_to_disk = TRUE;
-
-	/* iradio streams */
-	iradio_type = rhythmdb_entry_register_type (db, "iradio");
-	iradio_type->save_to_disk = TRUE;
-	iradio_type->can_sync_metadata = (RhythmDBEntryCanSyncFunc)rb_true_function;
-	iradio_type->sync_metadata = (RhythmDBEntrySyncFunc)rb_null_function;
+	ignore_type->category = RHYTHMDB_ENTRY_VIRTUAL;
 
 	/* podcast posts */
 	podcast_post_type = rhythmdb_entry_register_type (db, "podcast-post");
 	podcast_post_type->entry_type_data_size = sizeof (RhythmDBPodcastFields);
 	podcast_post_type->save_to_disk = TRUE;
+	podcast_post_type->category = RHYTHMDB_ENTRY_NORMAL;
 	podcast_post_type->pre_entry_destroy = (RhythmDBEntryActionFunc) podcast_data_destroy;
 	podcast_post_type->get_playback_uri = podcast_get_playback_uri;
 
@@ -3744,6 +3815,7 @@ rhythmdb_register_core_entry_types (Rhyt
 	podcast_feed_type = rhythmdb_entry_register_type (db, "podcast-feed");
 	podcast_feed_type->entry_type_data_size = sizeof (RhythmDBPodcastFields);
 	podcast_feed_type->save_to_disk = TRUE;
+	podcast_post_type->category = RHYTHMDB_ENTRY_VIRTUAL;
 	podcast_feed_type->pre_entry_destroy = (RhythmDBEntryActionFunc) podcast_data_destroy;
 }
 
@@ -3765,14 +3837,8 @@ rhythmdb_entry_import_error_get_type (vo
 	return import_error_type;
 }
 
-RhythmDBEntryType
-rhythmdb_entry_iradio_get_type (void)
-{
-	return iradio_type;
-}
-
-RhythmDBEntryType
-rhythmdb_entry_podcast_post_get_type (void)
+RhythmDBEntryType 
+rhythmdb_entry_podcast_post_get_type (void) 
 {
 	return podcast_post_type;
 }
diff -rN -u -p old-iradio/rhythmdb/rhythmdb.h new-iradio/rhythmdb/rhythmdb.h
--- old-iradio/rhythmdb/rhythmdb.h	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/rhythmdb/rhythmdb.h	2006-09-22 08:37:38.000000000 +1000
@@ -55,11 +55,19 @@ typedef char* (*RhythmDBEntryStringFunc)
 typedef gboolean (*RhythmDBEntryCanSyncFunc) (RhythmDB *db, RhythmDBEntry *entry, gpointer data);
 typedef void (*RhythmDBEntrySyncFunc) (RhythmDB *db, RhythmDBEntry *entry, GError **error, gpointer data);
 
+enum RhythmDBEntryCategory {
+	RHYTHMDB_ENTRY_NORMAL,		/* anything that doesn't match the other categories */
+	RHYTHMDB_ENTRY_STREAM,		/* endless streams (eg shoutcast, last.fm) */
+	RHYTHMDB_ENTRY_CONTAINER,	/* things that point to other entries (eg podcast feeds) */
+	RHYTHMDB_ENTRY_VIRTUAL		/* import errors, ignored files */
+};
+
 typedef struct {
 	char 				*name;
 
 	guint				entry_type_data_size;
 	gboolean			save_to_disk;
+	enum RhythmDBEntryCategory	category;
 
 	/* virtual functions here */
 	RhythmDBEntryActionFunc		post_entry_create;
@@ -96,7 +104,6 @@ GType rhythmdb_query_get_type (void);
 #define RHYTHMDB_IS_QUERY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RHYTHMDB_TYPE_QUERY))
 
 #define RHYTHMDB_ENTRY_TYPE_SONG (rhythmdb_entry_song_get_type ())
-#define RHYTHMDB_ENTRY_TYPE_IRADIO_STATION (rhythmdb_entry_iradio_get_type ())
 #define RHYTHMDB_ENTRY_TYPE_PODCAST_POST (rhythmdb_entry_podcast_post_get_type ())
 #define RHYTHMDB_ENTRY_TYPE_PODCAST_FEED (rhythmdb_entry_podcast_feed_get_type ())
 #define RHYTHMDB_ENTRY_TYPE_IMPORT_ERROR (rhythmdb_entry_import_error_get_type ())
@@ -198,6 +205,10 @@ enum {
 	RHYTHMDB_PODCAST_STATUS_PAUSED = 103,
 };
 
+/* commonly used extra entry metadata */
+#define RHYTHMDB_PROP_STREAM_SONG_TITLE		"rb:stream-song-title"
+#define RHYTHMDB_PROP_STREAM_SONG_ARTIST	"rb:stream-song-artist"
+
 GType rhythmdb_query_type_get_type (void);
 GType rhythmdb_prop_type_get_type (void);
 
@@ -404,7 +419,6 @@ RhythmDBEntryType rhythmdb_entry_registe
 RhythmDBEntryType rhythmdb_entry_type_get_by_name       (RhythmDB *db, const char *name);
 
 RhythmDBEntryType rhythmdb_entry_song_get_type          (void);
-RhythmDBEntryType rhythmdb_entry_iradio_get_type        (void);
 RhythmDBEntryType rhythmdb_entry_podcast_post_get_type  (void);
 RhythmDBEntryType rhythmdb_entry_podcast_feed_get_type  (void);
 RhythmDBEntryType rhythmdb_entry_import_error_get_type	(void);
diff -rN -u -p old-iradio/shell/Makefile.am new-iradio/shell/Makefile.am
--- old-iradio/shell/Makefile.am	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/shell/Makefile.am	2006-09-22 08:37:38.000000000 +1000
@@ -35,7 +35,6 @@ INCLUDES = 						\
 	-I$(top_srcdir)/rhythmdb                       	\
 	-I$(top_srcdir)/widgets                    	\
 	-I$(top_srcdir)/sources                    	\
-	-I$(top_srcdir)/iradio                    	\
 	-I$(top_srcdir)/podcast                    	\
 	-I$(top_builddir)/lib				\
 	-I$(top_srcdir)/plugins				\
@@ -97,7 +96,6 @@ rhythmbox_LDADD =					\
 	librbshell.la					\
 	$(top_builddir)/sources/libsources.la	        \
 	$(top_builddir)/sources/libsourcesimpl.la	\
-	$(top_builddir)/iradio/librbiradio.la	        \
 	$(top_builddir)/podcast/librbpodcast.la	        \
 	$(top_builddir)/metadata/librbmetadata.la	\
 	$(top_builddir)/widgets/librbwidgets.la         \
diff -rN -u -p old-iradio/shell/rb-shell.c new-iradio/shell/rb-shell.c
--- old-iradio/shell/rb-shell.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/shell/rb-shell.c	2006-09-22 08:37:38.000000000 +1000
@@ -76,7 +76,6 @@
 #include "rb-daap-source.h"
 #include "rb-daap-sharing.h"
 #endif /* WITH_DAAP_SUPPORT */
-#include "rb-iradio-source.h"
 #include "rb-shell-preferences.h"
 #include "rb-playlist-source.h"
 #include "rb-static-playlist-source.h"
@@ -163,9 +162,6 @@ static void rb_shell_player_window_title
 static void rb_shell_player_elapsed_changed_cb (RBShellPlayer *player,
 						guint elapsed,
 						RBShell *shell);
-static void rb_shell_player_stream_song_changed_cb (RBShellPlayer *player,
-						    GParamSpec *arg,
-						    RBShell *shell);
 static void rb_shell_cmd_about (GtkAction *action,
 		                RBShell *shell);
 static void rb_shell_cmd_contents (GtkAction *action,
@@ -355,7 +351,6 @@ struct RBShellPrivate
 	GList *supported_media_extensions;
 
 	RBLibrarySource *library_source;
-	RBIRadioSource *iradio_source;
 	RBPodcastSource *podcast_source;
 	RBPlaylistSource *queue_source;
 	RBSource *missing_files_source;
@@ -1061,10 +1056,6 @@ construct_widgets (RBShell *shell)
 				 "elapsed_changed",
 				 G_CALLBACK (rb_shell_player_elapsed_changed_cb),
 				 shell, 0);
-	g_signal_connect_object (G_OBJECT (shell->priv->player_shell),
-				 "notify::stream-song",
-				 G_CALLBACK (rb_shell_player_stream_song_changed_cb),
-				 shell, 0);
 	shell->priv->clipboard_shell = rb_shell_clipboard_new (shell->priv->actiongroup,
 							       shell->priv->ui_manager,
 							       shell->priv->db);
@@ -1178,8 +1169,6 @@ construct_sources (RBShell *shell)
 
 	shell->priv->library_source = RB_LIBRARY_SOURCE (rb_library_source_new (shell));
 	rb_shell_append_source (shell, RB_SOURCE (shell->priv->library_source), NULL);
-	shell->priv->iradio_source = RB_IRADIO_SOURCE (rb_iradio_source_new (shell));
-	rb_shell_append_source (shell, RB_SOURCE (shell->priv->iradio_source), NULL);
 	shell->priv->podcast_source = RB_PODCAST_SOURCE (rb_podcast_source_new (shell));
 	rb_shell_append_source (shell, RB_SOURCE (shell->priv->podcast_source), NULL);
 	shell->priv->missing_files_source = rb_missing_files_source_new (shell, shell->priv->library_source);
@@ -1986,20 +1975,6 @@ rb_shell_player_elapsed_changed_cb (RBSh
 }
 
 static void
-rb_shell_player_stream_song_changed_cb (RBShellPlayer *player,
-					GParamSpec *arg,
-					RBShell *shell)
-{
-	char *song;
-
-	g_object_get (player, "stream-song", &song, NULL);
-	if (song) {
-		rb_shell_hidden_notify (shell, 4000, song, NULL, NULL);
-		g_free (song);
-	}
-}
-
-static void
 rb_shell_set_elapsed (RBShell *shell,
 		      guint elapsed)
 {
diff -rN -u -p old-iradio/shell/rb-shell-player.c new-iradio/shell/rb-shell-player.c
--- old-iradio/shell/rb-shell-player.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/shell/rb-shell-player.c	2006-09-22 08:37:38.000000000 +1000
@@ -54,7 +54,6 @@
 #include "rb-header.h"
 #include "totem-pl-parser.h"
 #include "rb-metadata.h"
-#include "rb-iradio-source.h"
 #include "rb-library-source.h"
 #include "eel-gconf-extensions.h"
 #include "rb-util.h"
@@ -125,13 +124,8 @@ static void rb_shell_player_sync_replayg
                                              RhythmDBEntry *entry);
 static void tick_cb (RBPlayer *player, long elapsed, gpointer data);
 static void error_cb (RBPlayer *player, const GError *err, gpointer data);
-static void buffering_cb (RBPlayer *player, guint progress, gpointer data);
 static void rb_shell_player_error (RBShellPlayer *player, gboolean async, const GError *err);
 
-static void info_available_cb (RBPlayer *player,
-                               RBMetaDataField field,
-                               GValue *value,
-                               gpointer data);
 static void rb_shell_player_set_play_order (RBShellPlayer *player,
 					    const gchar *new_val);
 static void rb_shell_player_play_order_update_cb (RBPlayOrder *porder,
@@ -222,7 +216,6 @@ enum
 	PROP_STATUSBAR,
 	PROP_QUEUE_SOURCE,
 	PROP_QUEUE_ONLY,
-	PROP_STREAM_SONG,
 	PROP_PLAYING_FROM_QUEUE,
 	PROP_PLAYER,
 };
@@ -352,8 +345,6 @@ rb_shell_player_class_init (RBShellPlaye
 							      G_TYPE_OBJECT,
 							      G_PARAM_READABLE));
 
-	/* If you change these, be sure to update the CORBA interface
-	 * in rb-remote-bonobo.c! */
 	g_object_class_install_property (object_class,
 					 PROP_PLAY_ORDER,
 					 g_param_spec_string ("play-order",
@@ -385,14 +376,6 @@ rb_shell_player_class_init (RBShellPlaye
 							      RB_TYPE_STATUSBAR,
 							      G_PARAM_READWRITE));
 
-	g_object_class_install_property (object_class,
-					 PROP_STREAM_SONG,
-					 g_param_spec_string ("stream-song",
-							      "stream-song",
-							      "Current stream song title",
-							      "",
-							      G_PARAM_READABLE));
-
 	rb_shell_player_signals[WINDOW_TITLE_CHANGED] =
 		g_signal_new ("window_title_changed",
 			      G_OBJECT_CLASS_TYPE (object_class),
@@ -488,6 +471,10 @@ rb_shell_player_constructor (GType type,
 	player = RB_SHELL_PLAYER (G_OBJECT_CLASS (rb_shell_player_parent_class)->
 			constructor (type, n_construct_properties, construct_properties));
 
+	player->priv->header_widget = rb_header_new (player, player->priv->db);
+	gtk_widget_show (GTK_WIDGET (player->priv->header_widget));
+	gtk_box_pack_start (GTK_BOX (player), GTK_WIDGET (player->priv->header_widget), TRUE, TRUE, 0);
+
 	gtk_action_group_add_actions (player->priv->actiongroup,
 				      rb_shell_player_actions,
 				      rb_shell_player_n_actions,
@@ -709,11 +696,6 @@ rb_shell_player_init (RBShellPlayer *pla
 	gtk_container_set_border_width (GTK_CONTAINER (player), 3);
 
 	g_signal_connect_object (G_OBJECT (player->priv->mmplayer),
-				 "info",
-				 G_CALLBACK (info_available_cb),
-				 player, 0);
-
-	g_signal_connect_object (player->priv->mmplayer,
 				 "eos",
 				 G_CALLBACK (rb_shell_player_handle_eos),
 				 player, G_CONNECT_SWAPPED);
@@ -728,11 +710,6 @@ rb_shell_player_init (RBShellPlayer *pla
 				 G_CALLBACK (error_cb),
 				 player, 0);
 
-	g_signal_connect_object (G_OBJECT (player->priv->mmplayer),
-				 "buffering",
-				 G_CALLBACK (buffering_cb),
-				 player, 0);
-
 	g_signal_connect (G_OBJECT (gnome_vfs_get_volume_monitor ()),
 			  "volume-pre-unmount",
 			  G_CALLBACK (volume_pre_unmount_cb),
@@ -743,10 +720,6 @@ rb_shell_player_init (RBShellPlayer *pla
 					    (GConfClientNotifyFunc)gconf_play_order_changed,
 					    player);
 
-	player->priv->header_widget = rb_header_new (player);
-	gtk_widget_show (GTK_WIDGET (player->priv->header_widget));
-	gtk_box_pack_start (GTK_BOX (player), GTK_WIDGET (player->priv->header_widget), TRUE, TRUE, 0);
-
 	player->priv->volume = eel_gconf_get_float (CONF_STATE_VOLUME);
 
 	g_signal_connect (player, "notify::playing",
@@ -1003,9 +976,6 @@ rb_shell_player_get_property (GObject *o
 	case PROP_QUEUE_ONLY:
 		g_value_set_boolean (value, player->priv->queue_only);
 		break;
-	case PROP_STREAM_SONG:
-		g_value_set_string (value, player->priv->song);
-		break;
 	case PROP_PLAYING_FROM_QUEUE:
 		g_value_set_boolean (value, player->priv->current_playing_source == RB_SOURCE (player->priv->queue_source));
 		break;
@@ -1109,10 +1079,6 @@ open_location_thread (OpenLocationThread
 	TotemPlParser *playlist;
 	TotemPlParserResult playlist_result;
 
-	GDK_THREADS_ENTER ();
-	rb_statusbar_set_progress (data->player->priv->statusbar_widget, 0.0, _("Connecting"));
-	GDK_THREADS_LEAVE ();
-
 	playlist = totem_pl_parser_new ();
 	g_signal_connect_data (G_OBJECT (playlist), "entry",
 			       G_CALLBACK (playlist_entry_cb),
@@ -1163,10 +1129,6 @@ rb_shell_player_open_location (RBShellPl
 
 	was_playing = rb_player_playing (player->priv->mmplayer);
 
-	g_free (player->priv->song);
-	player->priv->song = NULL;
-	g_object_notify (G_OBJECT (player), "stream-song");
-
 	if (rb_source_try_playlist (player->priv->source)) {
 		OpenLocationThreadData *data;
 
@@ -2316,41 +2278,75 @@ rb_shell_player_sync_with_source (RBShel
 {
 	const char *entry_title = NULL;
 	const char *artist = NULL;
-	char *title;
+	const char *stream_name = NULL;
+	char *streaming_title = NULL;
+	char *streaming_artist = NULL;
 	RhythmDBEntry *entry;
+	char *title = NULL;
 
 	entry = rb_shell_player_get_playing_entry (player);
 	rb_debug ("playing source: %p, active entry: %p", player->priv->current_playing_source, entry);
 
 	if (entry != NULL) {
+		GValue *value;
+
 		entry_title = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
 		artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST);
+
+		value = rhythmdb_entry_request_extra_metadata (player->priv->db,
+							       entry,
+							       RHYTHMDB_PROP_STREAM_SONG_TITLE);
+		if (value != NULL) {
+			streaming_title = g_value_dup_string (value);
+			g_value_unset (value);
+			g_free (value);
+
+			rb_debug ("got streaming title \"%s\"", streaming_title);
+			/* use entry title for stream name */
+			stream_name = entry_title;
+			entry_title = streaming_title;
+		}
+
+		value = rhythmdb_entry_request_extra_metadata (player->priv->db,
+							       entry,
+							       RHYTHMDB_PROP_STREAM_SONG_ARTIST);
+		if (value != NULL) {
+			streaming_artist = g_value_dup_string (value);
+			g_value_unset (value);
+			g_free (value);
+
+			rb_debug ("got streaming artist \"%s\"", streaming_artist);
+			/* override artist from entry */
+			artist = streaming_artist;
+		}
 	}
 
-	if (player->priv->song && entry_title)
-		title = g_strdup_printf ("%s (%s)", player->priv->song,
-					 entry_title);
-	else if (entry_title && artist && artist[0] != '\0')
-		title = g_strdup_printf ("%s - %s", artist, entry_title);
-	else if (entry_title)
-		title = g_strdup (entry_title);
-	else
-		title = NULL;
+	if ((artist && artist[0] != '\0') || entry_title || stream_name) {
+
+		GString *title_str = g_string_sized_new (100);
+		if (artist && artist[0] != '\0') {
+			g_string_append (title_str, artist);
+			g_string_append (title_str, " - ");
+		}
+		if (entry_title != NULL)
+			g_string_append (title_str, entry_title);
+
+		if (stream_name != NULL)
+			g_string_append_printf (title_str, " (%s)", stream_name);
+
+		title = g_string_free (title_str, FALSE);
+	}
 
 	player->priv->elapsed = rb_player_get_time (player->priv->mmplayer);
 
 	g_signal_emit (G_OBJECT (player), rb_shell_player_signals[WINDOW_TITLE_CHANGED], 0,
 		       title);
+	g_free (title);
+
 	g_signal_emit (G_OBJECT (player), rb_shell_player_signals[ELAPSED_CHANGED], 0,
 		       (guint) player->priv->elapsed);
 
 	/* Sync the header */
-	if (player->priv->song)
-		rb_header_set_title (player->priv->header_widget, title);
-	else
-		rb_header_set_title (player->priv->header_widget, entry_title);
-	g_free (title);
-
 	rb_header_set_playing_entry (player->priv->header_widget,
 				     entry,
 				     TRUE /*rb_player_seekable (player->priv->mmplayer)*/);
@@ -2359,6 +2355,9 @@ rb_shell_player_sync_with_source (RBShel
 	if (entry != NULL) {
 		rhythmdb_entry_unref (entry);
 	}
+
+	g_free (streaming_artist);
+	g_free (streaming_title);
 }
 
 static void
@@ -2490,8 +2489,6 @@ rb_shell_player_set_playing_source_inter
 	}
 
 	g_free (player->priv->url);
-	g_free (player->priv->song);
-	player->priv->song = NULL;
 	player->priv->url = NULL;
 
 	if (player->priv->current_playing_source == NULL)
@@ -2747,162 +2744,6 @@ tick_cb (RBPlayer *mmplayer,
 	GDK_THREADS_LEAVE ();
 }
 
-static void
-info_available_cb (RBPlayer *mmplayer,
-                   RBMetaDataField field,
-                   GValue *value,
-                   gpointer data)
-{
-        RBShellPlayer *player = RB_SHELL_PLAYER (data);
-        RhythmDBEntry *entry;
-        RhythmDBPropType entry_field = 0;
-        gboolean changed = FALSE;
-        gboolean set_field = FALSE;
-	RhythmDBEntryType type;
-
-        rb_debug ("info: %d", field);
-
-        /* Sanity check, this signal may come in after we stopped the
-         * player */
-        if (player->priv->source == NULL
-            || !rb_player_opened (player->priv->mmplayer)) {
-                rb_debug ("Got info_available but no playing source!");
-                return;
-        }
-
-        GDK_THREADS_ENTER ();
-
-	entry = rb_shell_player_get_playing_entry (player);
-        if (entry == NULL) {
-                rb_debug ("Got info_available but no playing entry!");
-                goto out_unlock;
-        }
-
-	type = rhythmdb_entry_get_entry_type (entry);
-	if (type != RHYTHMDB_ENTRY_TYPE_IRADIO_STATION) {
-		rb_debug ("Got info_available but entry isn't an iradio station");
-		goto out_unlock;
-	}
-
-	switch (field)	{
-	case RB_METADATA_FIELD_TITLE:
-	{
-		char *song = g_value_dup_string (value);
-		if (!g_utf8_validate (song, -1, NULL)) {
-			g_warning ("Invalid UTF-8 from internet radio: %s", song);
-			goto out_unlock;
-		}
-
-		if ((!song && player->priv->song)
-		    || !player->priv->song
-		    || strcmp (song, player->priv->song)) {
-			changed = TRUE;
-			g_free (player->priv->song);
-			player->priv->song = song;
-			g_object_notify (G_OBJECT (player), "stream-song");
-		}
-		else
-			g_free (song);
-		break;
-	}
-	case RB_METADATA_FIELD_GENRE:
-	{
-		const char *genre = g_value_get_string (value);
-		const char *existing;
-		if (!g_utf8_validate (genre, -1, NULL)) {
-			g_warning ("Invalid UTF-8 from internet radio: %s", genre);
-			goto out_unlock;
-		}
-
-		/* check if the db entry already has a genre; if so, don't change it */
-		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE);
-		if ((existing == NULL) ||
-		    (strcmp (existing, "") == 0) ||
-		    (strcmp (existing, _("Unknown")) == 0)) {
-			entry_field = RHYTHMDB_PROP_GENRE;
-			rb_debug ("setting genre of iradio station to %s", genre);
-			set_field = TRUE;
-		} else {
-			rb_debug ("iradio station already has genre: %s; ignoring %s", existing, genre);
-		}
-		break;
-	}
-	case RB_METADATA_FIELD_COMMENT:
-	{
-		const char *name = g_value_get_string (value);
-		const char *existing;
-		const char *location;
-
-		if (!g_utf8_validate (name, -1, NULL)) {
-			g_warning ("Invalid UTF-8 from internet radio: %s", name);
-			goto out_unlock;
-		}
-
-		/* check if the db entry already has a title; if so, don't change it.
-		 * consider title==URI to be the same as no title, since that's what
-		 * happens for stations imported by DnD or commandline args.
-		 * if the station title really is the same as the URI, then surely
-		 * the station title in the stream metadata will say that too..
-		 */
-		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
-		location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
-		if ((existing == NULL) ||
-		    (strcmp (existing, "") == 0) ||
-		    (strcmp (existing, location) == 0)) {
-			entry_field = RHYTHMDB_PROP_TITLE;
-			rb_debug ("setting title of iradio station to %s", name);
-			set_field = TRUE;
-		} else {
-			rb_debug ("iradio station already has title: %s; ignoring %s", existing, name);
-		}
-		break;
-	}
-	case RB_METADATA_FIELD_BITRATE:
-		if (!rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_BITRATE)) {
-			gulong bitrate;
-
-			/* GStreamer sends us bitrate in bps, but we need it in kbps*/
-			bitrate = g_value_get_ulong (value);
-			g_value_set_ulong (value, bitrate/1000);
-
-			rb_debug ("setting bitrate of iradio station to %lu",
-				  g_value_get_ulong (value));
-			entry_field = RHYTHMDB_PROP_BITRATE;
-			set_field = TRUE;
-		}
-		break;
-	default:
-		break;
-	}
-
-	if (changed)
-		rb_shell_player_sync_with_source (player);
-
-	if (set_field && entry_field != 0) {
-		rhythmdb_entry_set (player->priv->db, entry, entry_field, value);
-		rhythmdb_commit (player->priv->db);
-	}
-
- out_unlock:
-	if (entry != NULL) {
-		rhythmdb_entry_unref (entry);
-	}
-
-	GDK_THREADS_LEAVE ();
-}
-
-static void
-buffering_cb (RBPlayer *mmplayer,
-	      guint progress,
-	      gpointer data)
-{
- 	RBShellPlayer *player = RB_SHELL_PLAYER (data);
-
-	GDK_THREADS_ENTER ();
-	rb_statusbar_set_progress (player->priv->statusbar_widget, ((double)progress)/100, _("Buffering"));
-	GDK_THREADS_LEAVE ();
-}
-
 gboolean
 rb_shell_player_get_playing_path (RBShellPlayer *shell_player,
 				  const gchar **path,
diff -rN -u -p old-iradio/sources/Makefile.am new-iradio/sources/Makefile.am
--- old-iradio/sources/Makefile.am	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/sources/Makefile.am	2006-09-22 08:37:38.000000000 +1000
@@ -12,8 +12,6 @@ libsourcesimpl_la_SOURCES =		\
 	rb-browser-source.h	\
 	rb-library-source.c		\
 	rb-library-source.h		\
-	rb-iradio-source.c		\
-	rb-iradio-source.h		\
 	rb-podcast-source.c		\
 	rb-podcast-source.h		\
 	rb-removable-media-source.c	\
diff -rN -u -p old-iradio/sources/rb-audiocd-source.c new-iradio/sources/rb-audiocd-source.c
--- old-iradio/sources/rb-audiocd-source.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/sources/rb-audiocd-source.c	2006-09-22 08:37:38.000000000 +1000
@@ -166,6 +166,7 @@ rb_audiocd_source_new (RBShell *shell,
 	entry_type =  rhythmdb_entry_register_type (db, NULL);
 	g_object_unref (db);
 
+	entry_type->category = RHYTHMDB_ENTRY_NORMAL;
 	entry_type->can_sync_metadata = (RhythmDBEntryCanSyncFunc)rb_true_function;
 	/* TODO same the metadata somewhere */
 	entry_type->sync_metadata = (RhythmDBEntrySyncFunc)rb_null_function;
diff -rN -u -p old-iradio/sources/rb-daap-source.c new-iradio/sources/rb-daap-source.c
--- old-iradio/sources/rb-daap-source.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/sources/rb-daap-source.c	2006-09-22 08:37:38.000000000 +1000
@@ -317,6 +317,8 @@ rb_daap_source_new (RBShell *shell,
 
 	g_object_get (shell, "db", &db, NULL);
 	type = rhythmdb_entry_register_type (db, NULL);
+	type->save_to_disk = FALSE;
+	type->category = RHYTHMDB_ENTRY_NORMAL;
 	g_object_unref (db);
 
 	icon = rb_daap_get_icon (password_protected, FALSE);
diff -rN -u -p old-iradio/sources/rb-ipod-source.c new-iradio/sources/rb-ipod-source.c
--- old-iradio/sources/rb-ipod-source.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/sources/rb-ipod-source.c	2006-09-22 08:37:38.000000000 +1000
@@ -208,6 +208,8 @@ rb_ipod_source_new (RBShell *shell,
 
 	g_object_get (shell, "db", &db, NULL);
 	entry_type =  rhythmdb_entry_register_type (db, NULL);
+	entry_type->save_to_disk = FALSE;
+	entry_type->category = RHYTHMDB_ENTRY_NORMAL;
 	g_object_unref (db);
 
 	source = RB_IPOD_SOURCE (g_object_new (RB_TYPE_IPOD_SOURCE,
@@ -949,10 +951,8 @@ impl_paste (RBSource *asource, GList *en
 		g_object_get (asource,
 			      "entry-type", &ipod_entry_type,
 			      NULL);
-		if (entry_type == RHYTHMDB_ENTRY_TYPE_IRADIO_STATION ||
-		    entry_type == RHYTHMDB_ENTRY_TYPE_PODCAST_FEED ||
-		    /*entry_type == RHYTHMDB_ENTRY_TYPE_PODCAST_EPISODE ||*/
-		    entry_type == ipod_entry_type) {
+		if (entry_type == ipod_entry_type ||
+		    entry_type->category != RHYTHMDB_ENTRY_NORMAL) {
 			g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type);
 			continue;
 		}
diff -rN -u -p old-iradio/sources/rb-iradio-source.c new-iradio/sources/rb-iradio-source.c
--- old-iradio/sources/rb-iradio-source.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/sources/rb-iradio-source.c	2006-09-22 08:37:38.000000000 +1000
@@ -46,6 +46,9 @@
 #include "rb-new-station-dialog.h"
 #include "rb-debug.h"
 #include "eel-gconf-extensions.h"
+#include "rb-shell-player.h"
+#include "rb-player.h"
+#include "rb-metadata.h"
 
 static void rb_iradio_source_class_init (RBIRadioSourceClass *klass);
 static void rb_iradio_source_init (RBIRadioSource *source);
@@ -110,6 +113,23 @@ static void stations_view_drag_data_rece
 static void rb_iradio_source_cmd_new_station (GtkAction *action,
 					      RBIRadioSource *source);
 
+static void playing_entry_changed_cb (RBShellPlayer *player,
+				      RhythmDBEntry *entry,
+				      RBIRadioSource *iradio_source);
+static void playing_source_changed_cb (RBShellPlayer *player,
+				       RBSource *source,
+				       RBIRadioSource *iradio_source);
+static GValue * streaming_title_request_cb (RhythmDB *db,
+					    RhythmDBEntry *entry,
+					    RBIRadioSource *source);
+static GValue * streaming_artist_request_cb (RhythmDB *db,
+					     RhythmDBEntry *entry,
+					     RBIRadioSource *source);
+static void extra_metadata_gather_cb (RhythmDB *db,
+				      RhythmDBEntry *entry,
+				      GHashTable *data,
+				      RBIRadioSource *source);
+
 #define CMD_PATH_SHOW_BROWSER "/commands/ShowBrowser"
 #define CMD_PATH_CURRENT_STATION "/commands/CurrentStation"
 #define CMD_PATH_SONG_INFO    "/commands/SongInfo"
@@ -142,6 +162,14 @@ struct RBIRadioSourcePrivate
 	guint first_time_notify_id;
 	gboolean firstrun_done;
 
+	RBShellPlayer *player;
+	char *streaming_title;
+	char *streaming_artist;
+
+	gint buffering_id;
+	gint info_available_id;
+	guint buffering;
+
 	gboolean dispose_has_run;
 };
 
@@ -232,6 +260,11 @@ rb_iradio_source_dispose (GObject *objec
 	/* Make sure dispose does not run twice. */
 	source->priv->dispose_has_run = TRUE;
 
+	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;
@@ -272,7 +305,6 @@ rb_iradio_source_constructor (GType type
 	RBIRadioSource *source;
 	RBIRadioSourceClass *klass;
 	RBShell *shell;
-	GObject *shell_player;
 
 	klass = RB_IRADIO_SOURCE_CLASS (g_type_class_peek (RB_TYPE_IRADIO_SOURCE));
 
@@ -281,11 +313,29 @@ rb_iradio_source_constructor (GType type
 
 	source->priv->paned = gtk_hpaned_new ();
 
-	g_object_get (source, "shell", &shell, NULL);
-	g_object_get (shell, "db", &source->priv->db, NULL);
-	shell_player = rb_shell_get_player (shell);
+	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 (shell);
 
+	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-gather",
+				 G_CALLBACK (extra_metadata_gather_cb),
+				 source, 0);
+
+
 	source->priv->action_group = _rb_source_register_action_group (RB_SOURCE (source),
 								       "IRadioActions",
 								       rb_iradio_source_actions,
@@ -293,7 +343,7 @@ rb_iradio_source_constructor (GType type
 								       source);
 
 	/* set up stations view */
-	source->priv->stations = rb_entry_view_new (source->priv->db, shell_player,
+	source->priv->stations = rb_entry_view_new (source->priv->db, G_OBJECT (source->priv->player),
 						    CONF_STATE_IRADIO_SORTING,
 						    FALSE, FALSE);
 
@@ -366,6 +416,13 @@ rb_iradio_source_constructor (GType type
 
 	rb_iradio_source_state_prefs_sync (source);
 
+	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);
+
 	rb_iradio_source_do_query (source);
 
 	return G_OBJECT (source);
@@ -406,16 +463,26 @@ rb_iradio_source_new (RBShell *shell)
 {
 	RBSource *source;
 	RhythmDBEntryType entry_type;
+	RhythmDB *db;
+
+	g_object_get (shell, "db", &db, NULL);
+
+	entry_type = rhythmdb_entry_type_get_by_name (db, "iradio");
+	if (entry_type == RHYTHMDB_ENTRY_TYPE_INVALID) {
+		entry_type = rhythmdb_entry_register_type (db, "iradio");
+		entry_type->save_to_disk = TRUE;
+		entry_type->category = RHYTHMDB_ENTRY_STREAM;
+		entry_type->can_sync_metadata = (RhythmDBEntryCanSyncFunc) rb_true_function;
+		entry_type->sync_metadata = (RhythmDBEntrySyncFunc) rb_null_function;
+	}
+	g_object_unref (db);
 
-	entry_type = RHYTHMDB_ENTRY_TYPE_IRADIO_STATION;
 	source = RB_SOURCE (g_object_new (RB_TYPE_IRADIO_SOURCE,
 					  "name", _("Radio"),
 					  "shell", shell,
 					  "entry-type", entry_type,
 					  NULL));
-
 	rb_shell_register_entry_type_for_source (shell, source, entry_type);
-
 	return source;
 }
 
@@ -576,6 +643,7 @@ impl_get_status (RBSource *asource,
 {
 	RhythmDBQueryModel *model;
 	guint num_entries;
+	RBIRadioSource *source = RB_IRADIO_SOURCE (asource);
 
 	g_object_get (asource, "query-model", &model, NULL);
 	num_entries = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL);
@@ -583,6 +651,14 @@ impl_get_status (RBSource *asource,
 
 	*text = g_strdup_printf (ngettext ("%d station", "%d stations", num_entries),
 				 num_entries);
+
+	*progress = 0.0;
+	if (source->priv->buffering == -1) {
+		*progress_text = g_strdup (_("Connecting"));
+	} else if (source->priv->buffering > 0) {
+		*progress = ((float)source->priv->buffering)/100;
+		*progress_text = g_strdup (_("Buffering"));
+	}
 }
 
 static char *
@@ -625,8 +701,8 @@ static guint
 impl_want_uri (RBSource *source, const char *uri)
 {
 	if (g_str_has_prefix (uri, "http://")) {
-		/* other entry types might have 
-		 * more specific guesses for HTTP 
+		/* other entry types might have
+		 * more specific guesses for HTTP
 		 */
 		return 50;
 	} else if (g_str_has_prefix (uri, "pnm://") ||
@@ -1017,3 +1093,318 @@ rb_iradio_source_cmd_new_station (GtkAct
 
 	gtk_widget_destroy (dialog);
 }
+
+static void
+buffering_cb (GObject *backend, guint progress, RBIRadioSource *source)
+{
+	if (progress == 0)
+		return;
+
+	if (progress == 100)
+		progress = 0;
+
+	GDK_THREADS_ENTER ();
+	source->priv->buffering = progress;
+	rb_source_notify_status_changed (RB_SOURCE (source));
+	GDK_THREADS_LEAVE ();
+}
+
+static gboolean
+check_entry_type (RBIRadioSource *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 GValue *
+streaming_title_request_cb (RhythmDB *db,
+			    RhythmDBEntry *entry,
+			    RBIRadioSource *source)
+{
+	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;
+
+	rb_debug ("returning streaming title \"%s\" to extra metadata request", source->priv->streaming_title);
+	value = g_new0 (GValue, 1);
+	g_value_init (value, G_TYPE_STRING);
+	g_value_set_string (value, source->priv->streaming_title);
+	return value;
+}
+
+static GValue *
+streaming_artist_request_cb (RhythmDB *db,
+			     RhythmDBEntry *entry,
+			     RBIRadioSource *source)
+{
+	GValue *value;
+
+	if (check_entry_type (source, entry) == FALSE ||
+	    entry != rb_shell_player_get_playing_entry (source->priv->player) ||
+	    source->priv->streaming_artist == NULL)
+		return NULL;
+
+	rb_debug ("returning streaming artist \"%s\" to extra metadata request", source->priv->streaming_artist);
+	value = g_new0 (GValue, 1);
+	g_value_init (value, G_TYPE_STRING);
+	g_value_set_string (value, source->priv->streaming_artist);
+	return value;
+}
+
+static void
+extra_metadata_gather_cb (RhythmDB *db,
+			  RhythmDBEntry *entry,
+			  GHashTable *data,
+			  RBIRadioSource *source)
+{
+	/* our extra metadata only applies to the playing entry */
+	if (entry != rb_shell_player_get_playing_entry (source->priv->player) ||
+	    check_entry_type (source, entry) == FALSE)
+		return;
+
+	if (source->priv->streaming_title != NULL) {
+		GValue *value;
+
+		value = g_new0 (GValue, 1);
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, source->priv->streaming_title);
+		g_hash_table_insert (data, g_strdup (RHYTHMDB_PROP_STREAM_SONG_TITLE), value);
+	}
+
+	if (source->priv->streaming_artist != NULL) {
+		GValue *value;
+
+		value = g_new0 (GValue, 1);
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, source->priv->streaming_artist);
+		g_hash_table_insert (data, g_strdup (RHYTHMDB_PROP_STREAM_SONG_ARTIST), value);
+	}
+}
+
+static void
+info_available_cb (RBPlayer *backend,
+		   RBMetaDataField field,
+		   GValue *value,
+		   RBIRadioSource *source)
+{
+	RhythmDBEntry *entry;
+        RhythmDBPropType entry_field = 0;
+        gboolean set_field = FALSE;
+	char *str = NULL;
+
+	/* sanity check */
+	if (!rb_player_opened (backend)) {
+		rb_debug ("Got info_available but not playing");
+		return;
+	}
+
+	GDK_THREADS_ENTER ();
+
+	entry = rb_shell_player_get_playing_entry (source->priv->player);
+	if (check_entry_type (source, entry) == FALSE)
+		goto out_unlock;
+
+	/* validate the value */
+	switch (field) {
+	case RB_METADATA_FIELD_TITLE:
+	case RB_METADATA_FIELD_ARTIST:
+	case RB_METADATA_FIELD_GENRE:
+	case RB_METADATA_FIELD_COMMENT:
+		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) {
+		/* streaming song information */
+	case RB_METADATA_FIELD_TITLE:
+	{
+		if ((!str && source->priv->streaming_title)
+		    || !source->priv->streaming_title
+		    || strcmp (str, source->priv->streaming_title)) {
+
+			g_free (source->priv->streaming_title);
+			source->priv->streaming_title = str;
+			rb_debug ("got streaming song title \"%s\"", str);
+
+			rhythmdb_emit_entry_extra_metadata_notify (source->priv->db,
+								   entry,
+								   RHYTHMDB_PROP_STREAM_SONG_TITLE,
+								   value);
+		} else {
+			g_free (str);
+		}
+		break;
+	}
+	case RB_METADATA_FIELD_ARTIST:
+	{
+		if ((!str && source->priv->streaming_artist)
+		    || !source->priv->streaming_artist
+		    || strcmp (str, source->priv->streaming_artist)) {
+
+			g_free (source->priv->streaming_artist);
+			source->priv->streaming_artist = str;
+			rb_debug ("got streaming song artist \"%s\"", str);
+
+			rhythmdb_emit_entry_extra_metadata_notify (source->priv->db,
+								   entry,
+								   RHYTHMDB_PROP_STREAM_SONG_ARTIST,
+								   value);
+		} else {
+			g_free (str);
+		}
+		break;
+	}
+
+		/* station information */
+	case RB_METADATA_FIELD_GENRE:
+	{
+		const char *existing;
+
+		/* check if the db entry already has a genre; if so, don't change it */
+		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE);
+		if ((existing == NULL) ||
+		    (strcmp (existing, "") == 0) ||
+		    (strcmp (existing, _("Unknown")) == 0)) {
+			entry_field = RHYTHMDB_PROP_GENRE;
+			rb_debug ("setting genre of iradio station to %s", str);
+			set_field = TRUE;
+		} else {
+			rb_debug ("iradio station already has genre: %s; ignoring %s", existing, str);
+		}
+		break;
+	}
+	case RB_METADATA_FIELD_COMMENT:
+	{
+		const char *name = g_value_get_string (value);
+		const char *existing;
+		const char *location;
+
+		if (!g_utf8_validate (name, -1, NULL)) {
+			g_warning ("Invalid UTF-8 from internet radio: %s", name);
+			goto out_unlock;
+		}
+
+		/* check if the db entry already has a title; if so, don't change it.
+		 * consider title==URI to be the same as no title, since that's what
+		 * happens for stations imported by DnD or commandline args.
+		 * if the station title really is the same as the URI, then surely
+		 * the station title in the stream metadata will say that too..
+		 */
+		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
+		location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		if ((existing == NULL) ||
+		    (strcmp (existing, "") == 0) ||
+		    (strcmp (existing, location) == 0)) {
+			entry_field = RHYTHMDB_PROP_TITLE;
+			rb_debug ("setting title of iradio station to %s", name);
+			set_field = TRUE;
+		} else {
+			rb_debug ("iradio station already has title: %s; ignoring %s", existing, name);
+		}
+		break;
+	}
+	case RB_METADATA_FIELD_BITRATE:
+		if (!rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_BITRATE)) {
+			gulong bitrate;
+
+			/* GStreamer sends us bitrate in bps, but we need it in kbps*/
+			bitrate = g_value_get_ulong (value);
+			g_value_set_ulong (value, bitrate/1000);
+
+			rb_debug ("setting bitrate of iradio station to %lu",
+				  g_value_get_ulong (value));
+			entry_field = RHYTHMDB_PROP_BITRATE;
+			set_field = TRUE;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (set_field && entry_field != 0) {
+		rhythmdb_entry_set (source->priv->db, entry, entry_field, value);
+		rhythmdb_commit (source->priv->db);
+	}
+ out_unlock:
+	GDK_THREADS_LEAVE ();
+}
+
+static void
+playing_entry_changed_cb (RBShellPlayer *player,
+			  RhythmDBEntry *entry,
+			  RBIRadioSource *iradio_source)
+{
+	g_free (iradio_source->priv->streaming_title);
+	g_free (iradio_source->priv->streaming_artist);
+	iradio_source->priv->streaming_title = NULL;
+	iradio_source->priv->streaming_artist = NULL;
+
+	if (check_entry_type (iradio_source, entry) == FALSE) {
+		iradio_source->priv->buffering = 0;
+	} else {
+		rb_debug ("playing new stream; resetting buffering");
+		iradio_source->priv->buffering = -1;
+	}
+	rb_source_notify_status_changed (RB_SOURCE (iradio_source));
+}
+
+static void
+playing_source_changed_cb (RBShellPlayer *player,
+			   RBSource *source,
+			   RBIRadioSource *iradio_source)
+{
+	GObject *backend;
+
+	g_object_get (G_OBJECT (player), "player", &backend, NULL);
+	if (source == RB_SOURCE (iradio_source)) {
+		rb_debug ("connecting buffering and info-available signal handlers");
+		if (iradio_source->priv->buffering_id == 0) {
+			iradio_source->priv->buffering_id =
+				g_signal_connect_object (backend, "buffering",
+							 G_CALLBACK (buffering_cb),
+							 source, 0);
+		}
+		if (iradio_source->priv->info_available_id == 0) {
+			iradio_source->priv->info_available_id =
+				g_signal_connect_object (backend, "info",
+							 G_CALLBACK (info_available_cb),
+							 source, 0);
+		}
+		/* display 'connecting' status until we get a buffering message */
+		iradio_source->priv->buffering = -1;
+		rb_source_notify_status_changed (source);
+	} else {
+		rb_debug ("disconnecting buffering and info-available signal handlers");
+		if (iradio_source->priv->buffering_id) {
+			g_signal_handler_disconnect (G_OBJECT (backend),
+						     iradio_source->priv->buffering_id);
+			iradio_source->priv->buffering_id = 0;
+		}
+		if (iradio_source->priv->info_available_id) {
+			g_signal_handler_disconnect (G_OBJECT (backend),
+						     iradio_source->priv->info_available_id);
+			iradio_source->priv->info_available_id = 0;
+		}
+		iradio_source->priv->buffering = 0;
+		rb_source_notify_status_changed (source);
+	}
+	g_object_unref (backend);
+}
+
diff -rN -u -p old-iradio/tests/bench-rhythmdb-load.c new-iradio/tests/bench-rhythmdb-load.c
--- old-iradio/tests/bench-rhythmdb-load.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/tests/bench-rhythmdb-load.c	2006-09-22 08:37:38.000000000 +1000
@@ -90,7 +90,7 @@ main (int argc, char **argv)
 			wait_for_signal ();
 
 			rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_SONG);
-			rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_IRADIO_STATION);
+			rhythmdb_entry_delete_by_type (db, rhythmdb_entry_type_get_by_name (db, "iradio"));
 			rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_PODCAST_FEED);
 			rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_PODCAST_POST);
 		}
diff -rN -u -p old-iradio/widgets/rb-header.c new-iradio/widgets/rb-header.c
--- old-iradio/widgets/rb-header.c	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/widgets/rb-header.c	2006-09-22 08:37:38.000000000 +1000
@@ -36,6 +36,7 @@
 #include "rb-shell-player.h"
 #include "eel-gconf-extensions.h"
 #include "rb-util.h"
+#include "rhythmdb.h"
 
 static void rb_header_class_init (RBHeaderClass *klass);
 static void rb_header_init (RBHeader *header);
@@ -63,8 +64,6 @@ struct RBHeaderPrivate
 	RhythmDB *db;
 	RhythmDBEntry *entry;
 
-	char *title;
-
 	RBShellPlayer *shell_player;
 
 	GtkWidget *image;
@@ -94,12 +93,13 @@ enum
 	PROP_DB,
 	PROP_SHELL_PLAYER,
 	PROP_ENTRY,
-	PROP_TITLE,
 	PROP_SEEKABLE,
 };
 
-#define SONG_MARKUP(xSONG) g_markup_printf_escaped ("<big><b>%s</b></big>", xSONG);
-#define SONG_MARKUP_ALBUM_ARTIST(xSONG, xALBUM, xARTIST) g_markup_printf_escaped ("<big><b>%s</b></big> %s <i>%s</i> %s <i>%s</i>", xSONG, _("by"), xARTIST, _("from"), xALBUM);
+#define TITLE_MARKUP(xTITLE) g_markup_printf_escaped ("<big><b>%s</b></big>", xTITLE)
+#define ALBUM_MARKUP(xALBUM) g_markup_printf_escaped (" %s <i>%s</i>", _("from"), xALBUM)
+#define ARTIST_MARKUP(xARTIST) g_markup_printf_escaped (" %s <i>%s</i>", _("by"), xARTIST)
+#define STREAM_MARKUP(xSTREAM) g_markup_printf_escaped (" (%s)", xSTREAM)
 
 G_DEFINE_TYPE (RBHeader, rb_header, GTK_TYPE_HBOX)
 
@@ -136,14 +136,6 @@ rb_header_class_init (RBHeaderClass *kla
 							      RB_TYPE_SHELL_PLAYER,
 							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 	g_object_class_install_property (object_class,
-					 PROP_TITLE,
-					 g_param_spec_string ("title",
-							      "title",
-							      "title",
-							      NULL,
-							      G_PARAM_READWRITE));
-
-	g_object_class_install_property (object_class,
 					 PROP_SEEKABLE,
 					 g_param_spec_boolean ("seekable",
 						 	       "seekable",
@@ -270,10 +262,6 @@ rb_header_set_property (GObject *object,
 				  (GCallback) rb_header_elapsed_changed_cb,
 				  header);
 		break;
-	case PROP_TITLE:
-		g_free (header->priv->title);
-		header->priv->title = g_value_dup_string (value);
-		break;
 	case PROP_SEEKABLE:
 		header->priv->seekable = g_value_get_boolean (value);
 		break;
@@ -301,9 +289,6 @@ rb_header_get_property (GObject *object,
 	case PROP_SHELL_PLAYER:
 		g_value_set_object (value, header->priv->shell_player);
 		break;
-	case PROP_TITLE:
-		g_value_set_string (value, header->priv->title);
-		break;
 	case PROP_SEEKABLE:
 		g_value_set_boolean (value, header->priv->seekable);
 		break;
@@ -314,13 +299,13 @@ rb_header_get_property (GObject *object,
 }
 
 RBHeader *
-rb_header_new (RBShellPlayer *shell_player)
+rb_header_new (RBShellPlayer *shell_player, RhythmDB *db)
 {
 	RBHeader *header;
 
 	header = RB_HEADER (g_object_new (RB_TYPE_HEADER,
 					  "shell-player", shell_player,
-					  "title", NULL,
+					  "db", db,
 					  "spacing", 6, NULL));
 
 	g_return_val_if_fail (header->priv != NULL, NULL);
@@ -339,10 +324,12 @@ rb_header_set_playing_entry (RBHeader *h
 		      NULL);
 }
 
-void
-rb_header_set_title (RBHeader *header, const char *title)
+static void
+append_and_free (GString *str,
+		 char *text)
 {
-	g_object_set (header, "title", title, NULL);
+	g_string_append (str, text);
+	g_free (text);
 }
 
 void
@@ -353,23 +340,60 @@ rb_header_sync (RBHeader *header)
 	rb_debug ("syncing with entry = %p", header->priv->entry);
 
 	if (header->priv->entry != NULL) {
-		const char *song = header->priv->title;
+		const char *title;
 		const char *album;
 		const char *artist;
+		const char *stream_name = NULL;
+		char *streaming_title = NULL;
+		char *streaming_artist = NULL;
+		GValue *value;
+		GString *label_str;
 
 		gboolean have_duration = (header->priv->duration > 0);
 
+		title = rhythmdb_entry_get_string (header->priv->entry, RHYTHMDB_PROP_TITLE);
 		album = rhythmdb_entry_get_string (header->priv->entry, RHYTHMDB_PROP_ALBUM);
 		artist = rhythmdb_entry_get_string (header->priv->entry, RHYTHMDB_PROP_ARTIST);
 
-		/* check for artist and album */
-		if ((album != NULL && artist != NULL)
-		    && (strlen (album) > 0 && strlen (artist) > 0)) {
-			label_text = SONG_MARKUP_ALBUM_ARTIST (song, album, artist);
-		} else {
-			label_text = SONG_MARKUP (song);
+		value = rhythmdb_entry_request_extra_metadata (header->priv->db,
+							       header->priv->entry,
+							       RHYTHMDB_PROP_STREAM_SONG_TITLE);
+		if (value != NULL) {
+			streaming_title = g_value_dup_string (value);
+			g_value_unset (value);
+			g_free (value);
+
+			/* use entry title as stream name */
+			stream_name = title;
+			title = streaming_title;
 		}
 
+		value = rhythmdb_entry_request_extra_metadata (header->priv->db,
+							       header->priv->entry,
+							       RHYTHMDB_PROP_STREAM_SONG_ARTIST);
+		if (value != NULL) {
+			streaming_artist = g_value_dup_string (value);
+			g_value_unset (value);
+			g_free (value);
+
+			/* override artist from entry */
+			artist = streaming_artist;
+		}
+
+		label_str = g_string_sized_new (100);
+
+		append_and_free (label_str, TITLE_MARKUP (title));
+
+		if (artist != NULL && artist[0] != '\0')
+			append_and_free (label_str, ARTIST_MARKUP (artist));
+
+		if (album != NULL && album[0] != '\0')
+			append_and_free (label_str, ALBUM_MARKUP (album));
+
+		if (stream_name && stream_name[0] != '\0')
+			append_and_free (label_str, STREAM_MARKUP (stream_name));
+
+		label_text = g_string_free (label_str, FALSE);
 		gtk_label_set_markup (GTK_LABEL (header->priv->song), label_text);
 		g_free (label_text);
 
@@ -380,7 +404,7 @@ rb_header_sync (RBHeader *header)
 		char *tmp;
 
 		rb_debug ("not playing");
-		label_text = SONG_MARKUP (_("Not Playing"));
+		label_text = TITLE_MARKUP (_("Not Playing"));
 		gtk_label_set_markup (GTK_LABEL (header->priv->song), label_text);
 		g_free (label_text);
 
diff -rN -u -p old-iradio/widgets/rb-header.h new-iradio/widgets/rb-header.h
--- old-iradio/widgets/rb-header.h	2006-09-22 08:37:38.000000000 +1000
+++ new-iradio/widgets/rb-header.h	2006-09-22 08:37:38.000000000 +1000
@@ -53,15 +53,13 @@ typedef struct
 
 GType		rb_header_get_type		(void);
 
-RBHeader *	rb_header_new			(RBShellPlayer *header);
+RBHeader *	rb_header_new			(RBShellPlayer *header,
+						 RhythmDB *db);
 
 void		rb_header_set_playing_entry	(RBHeader *header,
 						 RhythmDBEntry *entry,
 						 gboolean seekable);
 
-void		rb_header_set_title		(RBHeader *header,
-						 const char *title);
-
 void		rb_header_set_show_position_slider (RBHeader *header,
                                                     gboolean show);
 

