diff -u -r1.46 Makefile.am
--- Makefile.am	19 Feb 2006 16:55:59 -0000	1.46
+++ Makefile.am	3 Mar 2006 11:19:54 -0000
@@ -5,7 +5,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 player rhythmdb widgets sources iradio podcast remote daapsharing shell data po help tests doc
+SUBDIRS = macros lib metadata player rhythmdb widgets sources iradio podcast remote daapsharing backends shell data po help tests doc
 
 EXTRA_DIST = 			\
 	autogen.sh		\
diff -u -r1.215 configure.ac
--- configure.ac	1 Mar 2006 15:35:22 -0000	1.215
+++ configure.ac	3 Mar 2006 11:19:55 -0000
@@ -52,6 +52,7 @@
 		  libgnomeui-2.0			\
 		  libglade-2.0				\
 		  gnome-vfs-2.0 >= $GNOME_VFS_REQS	\
+		  gnome-media-profiles			\
 		  gnome-vfs-module-2.0)
 
 PKG_CHECK_MODULES(TOTEM_PLPARSER, totem-plparser >= $TOTEM_PLPARSER_REQS, have_totem_plparser=yes, have_totem_plparser=no)
@@ -715,6 +716,8 @@
 tests/Makefile
 doc/Makefile
 doc/reference/Makefile
+backends/Makefile
+backends/gstreamer/Makefile
 ])
 
 AC_MSG_NOTICE([Rhythmbox was configured with the following options:])
diff -u -r1.12 general-prefs.glade
--- data/glade/general-prefs.glade	18 Feb 2006 06:56:17 -0000	1.12
+++ data/glade/general-prefs.glade	3 Mar 2006 11:19:56 -0000
@@ -28,6 +28,190 @@
       <property name="spacing">18</property>
 
       <child>
+	<widget class="GtkVBox" id="vbox14">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">6</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label22">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Browser Views</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox16">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label23">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes"></property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkHBox" id="hbox17">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">0</property>
+
+		  <child>
+		    <widget class="GtkLabel" id="browser_views_label">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes"></property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">False</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">8</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkVBox" id="vbox15">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">6</property>
+
+		      <child>
+			<widget class="GtkRadioButton" id="library_browser_views_radio">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="label" translatable="yes">_Artists and albums</property>
+			  <property name="use_underline">True</property>
+			  <property name="relief">GTK_RELIEF_NORMAL</property>
+			  <property name="focus_on_click">True</property>
+			  <property name="active">True</property>
+			  <property name="inconsistent">False</property>
+			  <property name="draw_indicator">True</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkRadioButton" id="library_browser_views_radio">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="label" translatable="yes">_Genres and artists</property>
+			  <property name="use_underline">True</property>
+			  <property name="relief">GTK_RELIEF_NORMAL</property>
+			  <property name="focus_on_click">True</property>
+			  <property name="active">False</property>
+			  <property name="inconsistent">False</property>
+			  <property name="draw_indicator">True</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkRadioButton" id="library_browser_views_radio">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="label" translatable="yes">G_enres, artists and albums</property>
+			  <property name="use_underline">True</property>
+			  <property name="relief">GTK_RELIEF_NORMAL</property>
+			  <property name="focus_on_click">True</property>
+			  <property name="active">False</property>
+			  <property name="inconsistent">False</property>
+			  <property name="draw_indicator">True</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
 	<widget class="GtkVBox" id="vbox2">
 	  <property name="visible">True</property>
 	  <property name="homogeneous">False</property>
diff -u -r1.11 library-prefs.glade
--- data/glade/library-prefs.glade	28 Feb 2006 10:31:22 -0000	1.11
+++ data/glade/library-prefs.glade	3 Mar 2006 11:19:56 -0000
@@ -40,195 +40,6 @@
 	  <property name="spacing">18</property>
 
 	  <child>
-	    <widget class="GtkVBox" id="vbox9">
-	      <property name="visible">True</property>
-	      <property name="homogeneous">False</property>
-	      <property name="spacing">6</property>
-
-	      <child>
-		<widget class="GtkLabel" id="browser_views_label">
-		  <property name="visible">True</property>
-		  <property name="label" translatable="yes">Browser Views</property>
-		  <property name="use_underline">False</property>
-		  <property name="use_markup">False</property>
-		  <property name="justify">GTK_JUSTIFY_LEFT</property>
-		  <property name="wrap">False</property>
-		  <property name="selectable">False</property>
-		  <property name="xalign">0</property>
-		  <property name="yalign">0.5</property>
-		  <property name="xpad">0</property>
-		  <property name="ypad">0</property>
-		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-		  <property name="width_chars">-1</property>
-		  <property name="single_line_mode">False</property>
-		  <property name="angle">0</property>
-		</widget>
-		<packing>
-		  <property name="padding">0</property>
-		  <property name="expand">False</property>
-		  <property name="fill">False</property>
-		</packing>
-	      </child>
-
-	      <child>
-		<widget class="GtkHBox" id="hbox12">
-		  <property name="visible">True</property>
-		  <property name="homogeneous">False</property>
-		  <property name="spacing">0</property>
-
-		  <child>
-		    <widget class="GtkLabel" id="label16">
-		      <property name="visible">True</property>
-		      <property name="label" translatable="yes"></property>
-		      <property name="use_underline">False</property>
-		      <property name="use_markup">False</property>
-		      <property name="justify">GTK_JUSTIFY_LEFT</property>
-		      <property name="wrap">False</property>
-		      <property name="selectable">False</property>
-		      <property name="xalign">0.5</property>
-		      <property name="yalign">0.5</property>
-		      <property name="xpad">0</property>
-		      <property name="ypad">0</property>
-		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-		      <property name="width_chars">-1</property>
-		      <property name="single_line_mode">False</property>
-		      <property name="angle">0</property>
-		    </widget>
-		    <packing>
-		      <property name="padding">0</property>
-		      <property name="expand">False</property>
-		      <property name="fill">False</property>
-		    </packing>
-		  </child>
-
-		  <child>
-		    <widget class="GtkHBox" id="hbox13">
-		      <property name="visible">True</property>
-		      <property name="homogeneous">False</property>
-		      <property name="spacing">0</property>
-
-		      <child>
-			<widget class="GtkLabel" id="label17">
-			  <property name="visible">True</property>
-			  <property name="label" translatable="yes"></property>
-			  <property name="use_underline">False</property>
-			  <property name="use_markup">False</property>
-			  <property name="justify">GTK_JUSTIFY_LEFT</property>
-			  <property name="wrap">False</property>
-			  <property name="selectable">False</property>
-			  <property name="xalign">0.5</property>
-			  <property name="yalign">0.5</property>
-			  <property name="xpad">8</property>
-			  <property name="ypad">0</property>
-			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-			  <property name="width_chars">-1</property>
-			  <property name="single_line_mode">False</property>
-			  <property name="angle">0</property>
-			</widget>
-			<packing>
-			  <property name="padding">0</property>
-			  <property name="expand">False</property>
-			  <property name="fill">False</property>
-			</packing>
-		      </child>
-
-		      <child>
-			<widget class="GtkVBox" id="vbox10">
-			  <property name="visible">True</property>
-			  <property name="homogeneous">False</property>
-			  <property name="spacing">6</property>
-
-			  <child>
-			    <widget class="GtkRadioButton" id="library_browser_views_radio">
-			      <property name="visible">True</property>
-			      <property name="can_focus">True</property>
-			      <property name="label" translatable="yes">_Artists and albums</property>
-			      <property name="use_underline">True</property>
-			      <property name="relief">GTK_RELIEF_NORMAL</property>
-			      <property name="focus_on_click">True</property>
-			      <property name="active">True</property>
-			      <property name="inconsistent">False</property>
-			      <property name="draw_indicator">True</property>
-			      <signal name="toggled" handler="rb_library_source_browser_views_activated_cb" last_modification_time="Sun, 26 Jan 2003 20:03:41 GMT"/>
-			    </widget>
-			    <packing>
-			      <property name="padding">0</property>
-			      <property name="expand">False</property>
-			      <property name="fill">False</property>
-			    </packing>
-			  </child>
-
-			  <child>
-			    <widget class="GtkRadioButton" id="radiobutton2">
-			      <property name="visible">True</property>
-			      <property name="can_focus">True</property>
-			      <property name="label" translatable="yes">_Genres and artists</property>
-			      <property name="use_underline">True</property>
-			      <property name="relief">GTK_RELIEF_NORMAL</property>
-			      <property name="focus_on_click">True</property>
-			      <property name="active">False</property>
-			      <property name="inconsistent">False</property>
-			      <property name="draw_indicator">True</property>
-			      <property name="group">library_browser_views_radio</property>
-			      <signal name="toggled" handler="rb_library_source_browser_views_activated_cb" last_modification_time="Sun, 26 Jan 2003 20:03:48 GMT"/>
-			    </widget>
-			    <packing>
-			      <property name="padding">0</property>
-			      <property name="expand">False</property>
-			      <property name="fill">False</property>
-			    </packing>
-			  </child>
-
-			  <child>
-			    <widget class="GtkRadioButton" id="radiobutton3">
-			      <property name="visible">True</property>
-			      <property name="can_focus">True</property>
-			      <property name="label" translatable="yes">G_enres, artists and albums</property>
-			      <property name="use_underline">True</property>
-			      <property name="relief">GTK_RELIEF_NORMAL</property>
-			      <property name="focus_on_click">True</property>
-			      <property name="active">False</property>
-			      <property name="inconsistent">False</property>
-			      <property name="draw_indicator">True</property>
-			      <property name="group">library_browser_views_radio</property>
-			      <signal name="toggled" handler="rb_library_source_browser_views_activated_cb" last_modification_time="Sun, 26 Jan 2003 20:03:56 GMT"/>
-			    </widget>
-			    <packing>
-			      <property name="padding">0</property>
-			      <property name="expand">False</property>
-			      <property name="fill">False</property>
-			    </packing>
-			  </child>
-			</widget>
-			<packing>
-			  <property name="padding">0</property>
-			  <property name="expand">True</property>
-			  <property name="fill">True</property>
-			</packing>
-		      </child>
-		    </widget>
-		    <packing>
-		      <property name="padding">0</property>
-		      <property name="expand">True</property>
-		      <property name="fill">True</property>
-		    </packing>
-		  </child>
-		</widget>
-		<packing>
-		  <property name="padding">0</property>
-		  <property name="expand">True</property>
-		  <property name="fill">True</property>
-		</packing>
-	      </child>
-	    </widget>
-	    <packing>
-	      <property name="padding">0</property>
-	      <property name="expand">False</property>
-	      <property name="fill">False</property>
-	    </packing>
-	  </child>
-
-	  <child>
 	    <widget class="GtkVBox" id="vbox11">
 	      <property name="visible">True</property>
 	      <property name="homogeneous">False</property>
@@ -466,32 +277,305 @@
 	    </widget>
 	    <packing>
 	      <property name="padding">0</property>
-	      <property name="expand">True</property>
-	      <property name="fill">True</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
 	    </packing>
 	  </child>
 
 	  <child>
-	    <widget class="GtkAlignment" id="alignment2">
+	    <widget class="GtkVBox" id="vbox13">
 	      <property name="visible">True</property>
-	      <property name="xalign">0.5</property>
-	      <property name="yalign">0.5</property>
-	      <property name="xscale">1</property>
-	      <property name="yscale">1</property>
-	      <property name="top_padding">0</property>
-	      <property name="bottom_padding">0</property>
-	      <property name="left_padding">0</property>
-	      <property name="right_padding">0</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">6</property>
 
 	      <child>
-		<placeholder/>
+		<widget class="GtkLabel" id="library_structure_label">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Library Structure</property>
+		  <property name="use_underline">True</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkHBox" id="hbox17">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">6</property>
+
+		  <child>
+		    <widget class="GtkLabel" id="label23">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">    </property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">False</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkTable" id="table1">
+		      <property name="visible">True</property>
+		      <property name="n_rows">5</property>
+		      <property name="n_columns">2</property>
+		      <property name="homogeneous">False</property>
+		      <property name="row_spacing">6</property>
+		      <property name="column_spacing">6</property>
+
+		      <child>
+			<widget class="GtkLabel" id="label24">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">Folder _Heirarchy:</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">0</property>
+			  <property name="right_attach">1</property>
+			  <property name="top_attach">0</property>
+			  <property name="bottom_attach">1</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label25">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_File Name:</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">0</property>
+			  <property name="right_attach">1</property>
+			  <property name="top_attach">1</property>
+			  <property name="bottom_attach">2</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label26">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">Example Path:</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">0</property>
+			  <property name="right_attach">1</property>
+			  <property name="top_attach">2</property>
+			  <property name="bottom_attach">3</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label27">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">Preferred Format:</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">0</property>
+			  <property name="right_attach">1</property>
+			  <property name="top_attach">4</property>
+			  <property name="bottom_attach">5</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="example_path_label">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">Artist/Artist - Album/Artist (Album) - 01 - Title.ogg</property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">2</property>
+			  <property name="bottom_attach">3</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkHBox" id="layout_path_menu_box">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">0</property>
+
+			  <child>
+			    <placeholder/>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">0</property>
+			  <property name="bottom_attach">1</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options">fill</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkHBox" id="layout_filename_menu_box">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">0</property>
+
+			  <child>
+			    <placeholder/>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">1</property>
+			  <property name="bottom_attach">2</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options">fill</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkHBox" id="preferred_format_menu_box">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">0</property>
+
+			  <child>
+			    <placeholder/>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">4</property>
+			  <property name="bottom_attach">5</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options">fill</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
 	      </child>
 	    </widget>
 	    <packing>
 	      <property name="padding">0</property>
-	      <property name="expand">False</property>
-	      <property name="fill">False</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
 	    </packing>
+	  </child>
+
+	  <child>
+	    <placeholder/>
 	  </child>
 	</widget>
       </child>
diff -u -r1.47 rhythmbox-ui.xml
--- data/ui/rhythmbox-ui.xml	2 Mar 2006 06:21:13 -0000	1.47
+++ data/ui/rhythmbox-ui.xml	3 Mar 2006 11:19:56 -0000
@@ -198,7 +198,7 @@
   </popup>
   
   <popup name="AudioCdSourcePopup">
-    <menuitem name="AudioCdSourcePopupImportCd" action="MusicImportCD"/>
+    <menuitem name="AudioCdSourcePopupCopyAllTracks" action="RemovableSourceCopyAllTracks"/>
     <menuitem name="AudioCdSourcePopupEjectCd" action="RemovableSourceEject"/>
   </popup>
 
diff -u -r1.4 rb-glade-helpers.c
--- lib/rb-glade-helpers.c	30 Nov 2005 07:18:29 -0000	1.4
+++ lib/rb-glade-helpers.c	3 Mar 2006 11:19:58 -0000
@@ -114,6 +114,12 @@
 rb_glade_boldify_label (GladeXML *xml, const char *name)
 {
 	GtkLabel *label = GTK_LABEL (glade_xml_get_widget (xml, name));
+
+	if (label == NULL) {
+		g_warning ("widget '%s' not found", name);
+		return;
+	}
+
 	/* this way is probably better, but for some reason doesn't work with
 	 * labels with mnemonics.
 
diff -u -r1.27 rb-preferences.h
--- lib/rb-preferences.h	23 Feb 2006 12:21:02 -0000	1.27
+++ lib/rb-preferences.h	3 Mar 2006 11:19:58 -0000
@@ -29,8 +29,6 @@
 
 #define CONF_FIRST_TIME CONF_PREFIX   "/first_time_flag"
 #define CONF_GRACE_PERIOD CONF_PREFIX "/grace_period"
-#define CONF_LIBRARY_LOCATION	CONF_PREFIX "/library_locations"
-#define CONF_MONITOR_LIBRARY	CONF_PREFIX "/monitor_library"
 #define CONF_UI_DIR               CONF_PREFIX "/ui"
 #define CONF_UI_STATUSBAR_HIDDEN  CONF_PREFIX "/ui/statusbar_hidden"
 #define CONF_UI_TOOLBAR_HIDDEN  CONF_PREFIX "/ui/toolbar_hidden"
@@ -57,6 +55,13 @@
 #define CONF_DAAP_SHARE_NAME       CONF_PREFIX "/sharing/share_name"
 #define CONF_DAAP_SHARE_PASSWORD   CONF_PREFIX "/sharing/share_password"
 #define CONF_DAAP_REQUIRE_PASSWORD CONF_PREFIX "/sharing/require_password"
+
+#define CONF_LIBRARY_LOCATION	CONF_PREFIX "/library_locations"
+#define CONF_MONITOR_LIBRARY	CONF_PREFIX "/monitor_library"
+#define CONF_LIBRARY_STRIP_CHARS	CONF_PREFIX "/library_strip_chars"
+#define CONF_LIBRARY_LAYOUT_PATH	CONF_PREFIX "/library_layout_path"
+#define CONF_LIBRARY_LAYOUT_FILENAME	CONF_PREFIX "/library_layout_filename"
+#define CONF_LIBRARY_PREFERRED_FORMAT	CONF_PREFIX "/library_preferred_format"
 
 G_END_DECLS
 
diff -u -r1.19 rb-util.c
--- lib/rb-util.c	7 Feb 2006 13:19:56 -0000	1.19
+++ lib/rb-util.c	3 Mar 2006 11:19:58 -0000
@@ -667,3 +667,51 @@
 
 	return list;
 }
+
+/*
+ * hacked up version of gnome_vfs_uri_list_parse,
+ * that it doesn't strip #s and and returns strings. 
+ */
+
+GList *
+rb_uri_list_parse (const char *uri_list)
+{
+	const gchar *p, *q;
+	gchar *retval;
+	GList *result = NULL;
+
+	g_return_val_if_fail (uri_list != NULL, NULL);
+
+	p = uri_list;
+
+	while (p != NULL) {
+		while (g_ascii_isspace (*p))
+			p++;
+
+		q = p;
+		while ((*q != '\0')
+		       && (*q != '\n')
+		       && (*q != '\r'))
+			q++;
+
+		if (q > p) {
+			q--;
+			while (q > p
+			       && g_ascii_isspace (*q))
+				q--;
+
+			retval = g_malloc (q - p + 2);
+			strncpy (retval, p, q - p + 1);
+			retval[q - p + 1] = '\0';
+
+			if (retval != NULL)
+				result = g_list_prepend (result, retval);
+		}
+		p = strchr (p, '\n');
+		if (p != NULL)
+			p++;
+	}
+
+	return g_list_reverse (result);
+}
+
diff -u -r1.15 rb-util.h
--- lib/rb-util.h	7 Feb 2006 13:19:56 -0000	1.15
+++ lib/rb-util.h	3 Mar 2006 11:19:58 -0000
@@ -59,6 +59,8 @@
 GList* rb_collate_hash_table_keys (GHashTable *table);
 GList* rb_collate_hash_table_values (GHashTable *table);
 
+GList* rb_uri_list_parse (const char *uri_list);
+
 G_END_DECLS
 
 #endif /* __RB_UTIL_H */
diff -u -r1.34 rb-podcast-manager.c
--- podcast/rb-podcast-manager.c	28 Feb 2006 13:39:06 -0000	1.34
+++ podcast/rb-podcast-manager.c	3 Mar 2006 11:20:00 -0000
@@ -143,8 +143,6 @@
 		                                	 GValue *value,
                 		                	 GParamSpec *pspec);
 static void rb_podcast_manager_copy_post 		(RBPodcastManager *pd);
-static int rb_podcast_manager_mkdir_with_parents 	(const gchar *pathname,
-					  		 int mode);
 static gboolean rb_podcast_manager_sync_head_cb 	(gpointer data);
 static gboolean rb_podcast_manager_head_query_cb 	(GtkTreeModel *query_model,
 						   	 GtkTreePath *path, 
@@ -592,7 +590,7 @@
 	g_free (conf_dir_name);
 
 	 if (!g_file_test (dir_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
-		if (rb_podcast_manager_mkdir_with_parents (dir_name, 0750) != 0) {
+		if (!g_mkdir_with_parents (dir_name, 0750)) {
 			rb_debug ("Error downloading podcast: could not create local dirs");
 			goto next_step;
 		}
@@ -684,62 +682,6 @@
 
 	g_mutex_unlock (pd->priv->mutex_job);
 	gtk_idle_add ((GtkFunction) rb_podcast_manager_next_file , pd);	
-}
-
-
-static int
-rb_podcast_manager_mkdir_with_parents (const gchar *pathname,
-		   			int          mode)
-{
-  gchar *fn, *p;
-
-  if (pathname == NULL || *pathname == '\0')
-    {
-      return -1;
-    }
-
-  fn = g_strdup (pathname);
-
-  if (g_path_is_absolute (fn))
-    p = (gchar *) g_path_skip_root (fn);
-  else
-    p = fn;
-
-  do
-    {
-      while (*p && !G_IS_DIR_SEPARATOR (*p))
-	p++;
-      
-      if (!*p)
-	p = NULL;
-      else
-	*p = '\0';
-      
-      if (!g_file_test (fn, G_FILE_TEST_EXISTS))
-	{
-	  if (g_mkdir (fn, mode) == -1)
-	    {
-	      g_free (fn);
-	      return -1;
-	    }
-	}
-      else if (!g_file_test (fn, G_FILE_TEST_IS_DIR))
-	{
-	  g_free (fn);
-	  return -1;
-	}
-      if (p)
-	{
-	  *p++ = G_DIR_SEPARATOR;
-	  while (*p && G_IS_DIR_SEPARATOR (*p))
-	    p++;
-	}
-    }
-  while (p);
-
-  g_free (fn);
-
-  return 0;
 }
 
 gboolean
diff -u -r1.68 Makefile.am
--- shell/Makefile.am	7 Feb 2006 13:19:57 -0000	1.68
+++ shell/Makefile.am	3 Mar 2006 11:20:00 -0000
@@ -87,6 +87,7 @@
 	$(top_builddir)/metadata/librbmetadata.la	\
 	$(top_builddir)/widgets/librbwidgets.la         \
 	$(top_builddir)/rhythmdb/librhythmdb.la         \
+	$(top_builddir)/backends/librbbackends.la       \
 	$(top_builddir)/lib/librb.la	                \
 	$(GDA_LIBS)					\
 	$(TOTEM_PLPARSER_LIBS)				\
@@ -137,6 +138,7 @@
 	-I$(top_srcdir)/iradio                    	\
 	-I$(top_srcdir)/podcast                    	\
 	-I$(top_srcdir)/remote				\
+	-I$(top_srcdir)/backends			\
 	-I$(top_builddir)/remote			\
 	-DPIXMAP_DIR=\""$(datadir)/pixmaps"\"		\
 	-DSHARE_DIR=\"$(pkgdatadir)\"                   \
diff -u -r1.18 rb-removable-media-manager.c
--- shell/rb-removable-media-manager.c	2 Mar 2006 18:31:40 -0000	1.18
+++ shell/rb-removable-media-manager.c	3 Mar 2006 11:20:00 -0000
@@ -46,6 +46,7 @@
 #include "rb-dialog.h"
 #include "rb-stock-icons.h"
 #include "rhythmdb.h"
+#include "rb-encoder.h"
 
 #ifndef HAVE_BURN_DRIVE_UNREF
 #define nautilus_burn_drive_unref nautilus_burn_drive_free
@@ -54,6 +55,7 @@
 static void rb_removable_media_manager_class_init (RBRemovableMediaManagerClass *klass);
 static void rb_removable_media_manager_init (RBRemovableMediaManager *mgr);
 static void rb_removable_media_manager_dispose (GObject *object);
+static void rb_removable_media_manager_finalize (GObject *object);
 static void rb_removable_media_manager_set_property (GObject *object,
 					      guint prop_id,
 					      const GValue *value,
@@ -67,6 +69,8 @@
 						       RBRemovableMediaManager *manager);
 static void rb_removable_media_manager_cmd_eject_medium (GtkAction *action,
 					       RBRemovableMediaManager *mgr);
+static void rb_removable_media_manager_cmd_copy_tracks (GtkAction *action,
+							RBRemovableMediaManager *mgr);
 static void rb_removable_media_manager_set_uimanager (RBRemovableMediaManager *mgr, 
 					     GtkUIManager *uimanager);
 
@@ -84,6 +88,7 @@
 				GnomeVFSVolume *volume, 
 				gpointer data);
 static void rb_removable_media_manager_scan (RBRemovableMediaManager *manager);
+static gboolean do_transfer (RBRemovableMediaManager *manager);
 
 typedef struct
 {
@@ -110,6 +115,9 @@
 	GList *cur_volume_list;
 
 	char *playing_uri;
+
+	GAsyncQueue *transfer_queue;
+	gboolean transfer_running;
 } RBRemovableMediaManagerPrivate;
 
 G_DEFINE_TYPE (RBRemovableMediaManager, rb_removable_media_manager, G_TYPE_OBJECT)
@@ -136,6 +144,9 @@
 	{ "RemovableSourceEject", GNOME_MEDIA_EJECT, N_("_Eject"), NULL,
 	  N_("Eject this medium"),
 	  G_CALLBACK (rb_removable_media_manager_cmd_eject_medium) },
+	{ "RemovableSourceCopyAllTracks", GTK_STOCK_CDROM, N_("_Copy to library"), NULL,
+	  N_("Copy all tracks to the library"),
+	  G_CALLBACK (rb_removable_media_manager_cmd_copy_tracks) },
 	{ "MusicScanMedia", NULL, N_("_Scan Removable Media"), NULL,
 	  N_("Scan for new Removable Media"),
 	  G_CALLBACK (rb_removable_media_manager_cmd_scan_media) },
@@ -149,7 +160,7 @@
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
 	object_class->dispose = rb_removable_media_manager_dispose;
-
+	object_class->finalize = rb_removable_media_manager_finalize;
 	object_class->set_property = rb_removable_media_manager_set_property;
 	object_class->get_property = rb_removable_media_manager_get_property;
 
@@ -195,6 +206,7 @@
 	RBRemovableMediaManagerPrivate *priv = REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr);
 
 	priv->volume_mapping = g_hash_table_new (NULL, NULL);
+	priv->transfer_queue = g_async_queue_new ();
 }
 
 static void
@@ -219,14 +231,6 @@
 		g_list_free (priv->sources);
 		priv->sources = NULL;
 	}
-	if (priv->volume_mapping) {
-		g_hash_table_destroy (priv->volume_mapping);
-		priv->volume_mapping = NULL;
-	}
-	if (priv->cd_drive_mapping) {
-		g_hash_table_destroy (priv->cd_drive_mapping);
-		priv->cd_drive_mapping = NULL;
-	}
 
 	priv->disposed = TRUE;
 
@@ -234,6 +238,18 @@
 }
 
 static void
+rb_removable_media_manager_finalize (GObject *object)
+{
+	RBRemovableMediaManagerPrivate *priv = REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (object);
+
+	g_hash_table_destroy (priv->volume_mapping);
+	g_hash_table_destroy (priv->cd_drive_mapping);
+	g_async_queue_unref (priv->transfer_queue);
+	
+	G_OBJECT_CLASS (rb_removable_media_manager_parent_class)->finalize (object);
+}
+
+static void
 rb_removable_media_manager_set_property (GObject *object,
 				  guint prop_id,
 				  const GValue *value,
@@ -779,4 +795,142 @@
 		}
 	}
 	g_list_free (list);
+}
+
+
+
+/* Track transfer */
+
+typedef struct {
+	RBRemovableMediaManager *manager;
+	RhythmDBEntry *entry;
+	char *dest;
+	char *mime_type;
+	gboolean failed;
+	RBTranferCompleteCallback callback;
+	gpointer userdata;
+} TransferData;
+
+static void
+error_cb (RBEncoder *encoder, TransferData *data, GError *error)
+{
+	rb_encoder_cancel (encoder);
+	data->failed = TRUE;
+
+	rb_debug ("Error transferring track to %s: %s", data->dest, error->message);
+	rb_error_dialog (NULL, _("Error transferring track"), "%s", error->message);
+}
+
+static void
+progress_cb (RBEncoder *encoder, TransferData *data, gint done)
+{
+	rb_debug ("transfer progress %s", done);
+}
+
+static void
+completed_cb (RBEncoder *encoder, TransferData *data)
+{
+	RBRemovableMediaManagerPrivate *priv = REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (data->manager);
+
+	rb_debug ("completed transferring track to %s", data->dest);
+	if (!data->failed)
+		(data->callback) (data->entry, data->dest, data->userdata);
+
+	priv->transfer_running = FALSE;
+	do_transfer (data->manager);
+
+	g_object_unref (G_OBJECT (encoder));
+	g_free (data->dest);
+	g_free (data->mime_type);
+	g_free (data);
+}
+
+static gboolean
+do_transfer (RBRemovableMediaManager *manager)
+{
+	RBRemovableMediaManagerPrivate *priv = REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (manager);
+	TransferData *data;
+	RBEncoder *encoder;
+	
+	if (priv->transfer_running)
+		return FALSE;
+
+	data = g_async_queue_try_pop (priv->transfer_queue);
+	if (data == NULL)
+		return FALSE;
+
+	priv->transfer_running = TRUE;
+
+	encoder = rb_encoder_new ();
+	g_signal_connect (G_OBJECT (encoder),
+			  "error", G_CALLBACK (error_cb),
+			  data);
+	g_signal_connect (G_OBJECT (encoder),
+			  "progress", G_CALLBACK (progress_cb),
+			  data);
+	g_signal_connect (G_OBJECT (encoder),
+			  "completed", G_CALLBACK (completed_cb),
+			  data);
+	if (!rb_encoder_encode (encoder, data->entry, data->dest, NULL)) {
+		data->failed = TRUE;
+		completed_cb (encoder, data);
+	}
+
+	return FALSE;
+}
+
+void
+rb_removable_media_manager_queue_transfer (RBRemovableMediaManager *manager,
+					  RhythmDBEntry *entry,
+					  const char *dest,
+					  const char *mime_type,
+					  RBTranferCompleteCallback callback,
+					  gpointer userdata)
+{
+	RBRemovableMediaManagerPrivate *priv = REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (manager);
+	TransferData *data;
+
+	data = g_new0 (TransferData, 1);
+	data->manager = manager;
+	data->entry = entry;
+	data->dest = g_strdup (dest);
+	data->mime_type = g_strdup (mime_type);
+	data->callback = callback;
+	data->userdata = userdata;
+
+	g_async_queue_push (priv->transfer_queue, data);
+	g_idle_add ((GSourceFunc)do_transfer, manager);
+}
+
+static void
+copy_entry (RhythmDBQueryModel *model,
+	    GtkTreePath *path,
+	    GtkTreeIter *iter,
+	    GList **list)
+{
+	GList *l;
+	l = g_list_append (*list, rhythmdb_query_model_iter_to_entry (model, iter));
+	*list = l;
+	rb_debug ("%p", l);
+}
+
+static void
+rb_removable_media_manager_cmd_copy_tracks (GtkAction *action, RBRemovableMediaManager *mgr)
+{
+	RBRemovableMediaManagerPrivate *priv = REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr);
+	RBRemovableMediaSource *source;
+	RBLibrarySource *library;
+	RhythmDBQueryModel *model;
+	GList *list = NULL;
+
+	source = RB_REMOVABLE_MEDIA_SOURCE (priv->selected_source);
+	g_object_get (G_OBJECT (source), "query-model", &model, NULL);
+	g_object_get (G_OBJECT (priv->shell), "library-source", &library, NULL);
+
+	gtk_tree_model_foreach (GTK_TREE_MODEL (model), (GtkTreeModelForeachFunc)copy_entry, &list);
+	rb_source_paste (RB_SOURCE (library), list);
+	g_list_free (list);
+
+	g_object_unref (G_OBJECT (model));
+	g_object_unref (G_OBJECT (library));
 }
diff -u -r1.1 rb-removable-media-manager.h
--- shell/rb-removable-media-manager.h	11 Sep 2005 04:27:15 -0000	1.1
+++ shell/rb-removable-media-manager.h	3 Mar 2006 11:20:00 -0000
@@ -36,6 +36,12 @@
 #define RB_IS_REMOVABLE_MEDIA_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_REMOVABLE_MEDIA_MANAGER))
 #define RB_REMOVABLE_MEDIA_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_REMOVABLE_MEDIA_MANAGER, RBRemovableMediaManagerClass))
 
+
+typedef void (*RBTranferCompleteCallback) (RhythmDBEntry *entry,
+					   const char *dest,
+					   gpointer userdata);
+				      
+
 typedef struct
 {
 	GObject parent;
@@ -54,6 +60,13 @@
 GType			rb_removable_media_manager_get_type	(void);
 
 gboolean		rb_removable_media_manager_load_media	(RBRemovableMediaManager *mgr);
+
+void	rb_removable_media_manager_queue_transfer (RBRemovableMediaManager *mgr,
+						   RhythmDBEntry *entry,
+						   const char *dest,
+						   const char *mime_type,
+						   RBTranferCompleteCallback callback,
+						   gpointer userdata);
 
 G_END_DECLS
 
diff -u -r1.39 rb-shell-clipboard.c
--- shell/rb-shell-clipboard.c	2 Mar 2006 13:28:53 -0000	1.39
+++ shell/rb-shell-clipboard.c	3 Mar 2006 11:20:01 -0000
@@ -419,7 +419,7 @@
 	rb_debug ("syncing clipboard");
 	
 	if (g_list_length (clipboard->priv->entries) > 0)
-		can_paste = rb_source_can_cut (clipboard->priv->source);
+		can_paste = rb_source_can_paste (clipboard->priv->source);
 
 	if (have_selection) {
 		can_cut = rb_source_can_cut (clipboard->priv->source);
diff -u -r1.57 rb-shell-preferences.c
--- shell/rb-shell-preferences.c	18 Feb 2006 06:56:17 -0000	1.57
+++ shell/rb-shell-preferences.c	3 Mar 2006 11:20:01 -0000
@@ -82,6 +82,8 @@
 	GtkWidget *quality_check;
 	GtkWidget *year_check;
 
+	GSList *browser_views_group;
+
 	gboolean loading;
 };
 
@@ -119,7 +121,7 @@
 static void
 rb_shell_preferences_init (RBShellPreferences *shell_preferences)
 {
-	GtkWidget *help;
+	GtkWidget *tmp;
 	GladeXML *xml;
 
 	shell_preferences->priv = RB_SHELL_PREFERENCES_GET_PRIVATE (shell_preferences);
@@ -136,10 +138,10 @@
 	gtk_dialog_add_button (GTK_DIALOG (shell_preferences),
 			       GTK_STOCK_CLOSE,
 			       GTK_RESPONSE_CLOSE);
-	help = gtk_dialog_add_button (GTK_DIALOG (shell_preferences),
+	tmp = gtk_dialog_add_button (GTK_DIALOG (shell_preferences),
 			              GTK_STOCK_HELP,
 			              GTK_RESPONSE_HELP);
-	g_signal_connect_object (G_OBJECT (help), "clicked",
+	g_signal_connect_object (G_OBJECT (tmp), "clicked",
 				 G_CALLBACK (help_cb), shell_preferences, 0);
 	gtk_dialog_set_default_response (GTK_DIALOG (shell_preferences),
 					 GTK_RESPONSE_CLOSE);
@@ -187,6 +189,14 @@
 	shell_preferences->priv->first_seen_check =
 		glade_xml_get_widget (xml, "first_seen_check");
 
+	/* browser options */
+	rb_glade_boldify_label (xml, "browser_views_label");
+
+	tmp = glade_xml_get_widget (xml, "library_browser_views_radio");
+	shell_preferences->priv->browser_views_group =
+		g_slist_reverse (g_slist_copy (gtk_radio_button_get_group 
+					       (GTK_RADIO_BUTTON (tmp))));
+
 	gtk_notebook_append_page (GTK_NOTEBOOK (shell_preferences->priv->notebook),
 				  glade_xml_get_widget (xml, "general_vbox"),
 				  gtk_label_new (_("General")));
@@ -533,6 +543,7 @@
 rb_shell_preferences_sync (RBShellPreferences *shell_preferences)
 {
 	char *columns;
+	GSList  *list;
 
 	shell_preferences->priv->loading = TRUE;
 
@@ -577,6 +588,10 @@
 	}
 
 	g_free (columns);
+
+	list = g_slist_nth (shell_preferences->priv->browser_views_group,
+			    eel_gconf_get_integer (CONF_UI_BROWSER_VIEWS));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (list->data), TRUE);
 
 	shell_preferences->priv->loading = FALSE;
 }
diff -u -r1.404 rb-shell.c
--- shell/rb-shell.c	3 Mar 2006 00:33:37 -0000	1.404
+++ shell/rb-shell.c	3 Mar 2006 11:20:03 -0000
@@ -311,6 +311,7 @@
 	PROP_WINDOW,
 	PROP_PREFS,
 	PROP_QUEUE_SOURCE,
+	PROP_LIBRARY_SOURCE,
 };
 
 /* prefs */
@@ -607,7 +608,7 @@
 					 g_param_spec_object ("removable-media-manager",
 						 	      "RBRemovableMediaManager",
 							      "RBRemovableMediaManager object",
-							      RB_TYPE_SHELL_PLAYER,
+							      RB_TYPE_REMOVABLE_MEDIA_MANAGER,
 							      G_PARAM_READABLE));
 	g_object_class_install_property (object_class,
 					 PROP_WINDOW,
@@ -630,6 +631,13 @@
 							      "Queue source", 
 							      RB_TYPE_PLAY_QUEUE_SOURCE,
 							      G_PARAM_READABLE));
+	g_object_class_install_property (object_class,
+					 PROP_LIBRARY_SOURCE,
+					 g_param_spec_object ("library-source", 
+							      "library-source", 
+							      "Library source", 
+							      RB_TYPE_LIBRARY_SOURCE,
+							      G_PARAM_READABLE));
 
 
 	g_type_class_add_private (klass, sizeof (RBShellPrivate));
@@ -792,6 +800,9 @@
 	case PROP_QUEUE_SOURCE:
 		g_value_set_object (value, shell->priv->queue_source);
 		break;	
+	case PROP_LIBRARY_SOURCE:
+		g_value_set_object (value, shell->priv->library_source);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
diff -u -r1.36 Makefile.am
--- sources/Makefile.am	2 Mar 2006 18:31:41 -0000	1.36
+++ sources/Makefile.am	3 Mar 2006 11:20:03 -0000
@@ -63,10 +63,13 @@
 	$(TOTEM_PLPARSER_CFLAGS)			\
 	$(HAL_CFLAGS)					\
 	$(LIBNAUTILUS_BURN_CFLAGS)			\
+	$(LIBJUICER_CFLAGS)				\
 	$(RHYTHMBOX_CFLAGS)
 
 libsources_la_LDFLAGS = -export-dynamic
 libsourcesimpl_la_LDFLAGS = -export-dynamic
+
+libsourcesimpl_la_LIBADD = $(LIBJUICER_LIBS)
 
 ipod_files =				\
 	rb-ipod-source.c		\
diff -u -r1.24 rb-audiocd-source.c
--- sources/rb-audiocd-source.c	1 Mar 2006 03:01:19 -0000	1.24
+++ sources/rb-audiocd-source.c	3 Mar 2006 11:20:04 -0000
@@ -92,6 +92,9 @@
 	/* don't bother showing the browser/search bits */
 	source_class->impl_can_search = (RBSourceFeatureFunc) rb_false_function;
 	source_class->impl_can_browse = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_paste = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
 
 	source_class->impl_show_popup = impl_show_popup;
 	source_class->impl_delete_thyself = impl_delete_thyself;
@@ -267,6 +270,7 @@
 	entry_set_string_prop (db, entry, FALSE, RHYTHMDB_PROP_ARTIST, NULL);
 	entry_set_string_prop (db, entry, FALSE, RHYTHMDB_PROP_ALBUM, NULL);
 	entry_set_string_prop (db, entry, FALSE, RHYTHMDB_PROP_GENRE, NULL);
+	entry_set_string_prop (db, entry, FALSE, RHYTHMDB_PROP_MIMETYPE, "audio/x-raw-int");
 
 	rhythmdb_commit (db);
 	g_free (audio_path);
@@ -582,7 +586,7 @@
 {
 	GList *actions = NULL;
 
-	actions = g_list_prepend (actions, "MusicImportCD");
+	actions = g_list_prepend (actions, "RemovableSourceCopyAllTracks");
 	actions = g_list_prepend (actions, "RemovableSourceEject");
 
 	return actions;
diff -u -r1.10 rb-removable-media-source.c
--- sources/rb-removable-media-source.c	9 Feb 2006 21:24:51 -0000	1.10
+++ sources/rb-removable-media-source.c	3 Mar 2006 11:20:05 -0000
@@ -87,7 +87,8 @@
 
 	source_class->impl_delete_thyself = impl_delete_thyself;
 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
-	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_paste = (RBSourceFeatureFunc) rb_false_function;
 	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_false_function;
 	source_class->impl_receive_drag = NULL;
 	source_class->impl_can_move_to_trash = (RBSourceFeatureFunc) rb_false_function;
diff -u -r1.59 rb-source.c
--- sources/rb-source.c	22 Feb 2006 13:06:02 -0000	1.59
+++ sources/rb-source.c	3 Mar 2006 11:20:05 -0000
@@ -126,6 +126,7 @@
 	klass->impl_can_rename = default_can_rename;
 	klass->impl_can_search = default_can_search;
 	klass->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
+	klass->impl_can_paste = (RBSourceFeatureFunc) rb_false_function;
 	klass->impl_can_delete = (RBSourceFeatureFunc) rb_false_function;
 	klass->impl_can_copy = (RBSourceFeatureFunc) rb_false_function;
 	klass->impl_can_add_to_queue = (RBSourceFeatureFunc) rb_false_function;
@@ -575,6 +576,14 @@
 	RBSourceClass *klass = RB_SOURCE_GET_CLASS (source);
 
 	return klass->impl_can_cut (source);
+}
+
+gboolean
+rb_source_can_paste (RBSource *source)
+{
+	RBSourceClass *klass = RB_SOURCE_GET_CLASS (source);
+
+	return klass->impl_can_paste (source);
 }
 
 gboolean
diff -u -r1.38 rb-source.h
--- sources/rb-source.h	22 Feb 2006 13:06:02 -0000	1.38
+++ sources/rb-source.h	3 Mar 2006 11:20:05 -0000
@@ -90,6 +90,7 @@
 	gboolean	(*impl_can_delete)	(RBSource *source);
 	gboolean	(*impl_can_move_to_trash) (RBSource *source);
 	gboolean	(*impl_can_copy)	(RBSource *source);
+	gboolean	(*impl_can_paste)	(RBSource *source);
 	gboolean	(*impl_can_add_to_queue)(RBSource *source);
 	
 	GList *		(*impl_cut)		(RBSource *source);
@@ -152,6 +153,7 @@
 gboolean	rb_source_can_delete		(RBSource *source);
 gboolean	rb_source_can_move_to_trash	(RBSource *source);
 gboolean	rb_source_can_copy		(RBSource *source);
+gboolean	rb_source_can_paste		(RBSource *source);
 gboolean	rb_source_can_add_to_queue	(RBSource *source);
 
 GList *		rb_source_cut			(RBSource *source);
diff -u -r1.20 rb-sourcelist-model.c
--- sources/rb-sourcelist-model.c	27 Feb 2006 00:27:43 -0000	1.20
+++ sources/rb-sourcelist-model.c	3 Mar 2006 11:20:06 -0000
@@ -345,7 +345,7 @@
 		gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
 				    RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
 		
-		return rb_source_can_cut (source);
+		return rb_source_can_paste (source);
 
 	}
 	return FALSE;
diff -u -r1.12 rb-static-playlist-source.c
--- sources/rb-static-playlist-source.c	28 Feb 2006 11:45:11 -0000	1.12
+++ sources/rb-static-playlist-source.c	3 Mar 2006 11:20:06 -0000
@@ -106,7 +106,7 @@
 	object_class->finalize = rb_static_playlist_source_finalize;
 
 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_true_function;
-	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_paste = (RBSourceFeatureFunc) rb_true_function;
 	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_true_function;
 	source_class->impl_cut = impl_cut;
 	source_class->impl_paste = impl_paste;
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ backends/gstreamer/rb-encoder-gst.h	2006-03-03 14:34:31.000000000 +1100
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * arch-tag: Interface to audio encoder backend  
+ *
+ * Copyright (C) 2006 James Livingston <jrl@ids.org.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __RB_ENCODER_GST_H__
+#define __RB_ENCODER_GST_H__
+
+#include <glib-object.h>
+
+#include "rb-encoder.h"
+
+G_BEGIN_DECLS
+
+
+#define RB_TYPE_ENCODER_GST            (rb_encoder_gst_get_type ())
+#define RB_ENCODER_GST(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), RB_TYPE_ENCODER, RBEncoderGst))
+#define RB_IS_ENCODER_GST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RB_TYPE_ENCODER))
+
+typedef struct _RBEncoderGstPrivate RBEncoderGstPrivate;
+
+typedef struct
+{
+	GObjectClass obj_class;
+} RBEncoderGstClass;
+
+typedef struct
+{
+	GObject obj;
+	RBEncoderGstPrivate *priv;
+} RBEncoderGst;
+
+RBEncoder*	rb_encoder_gst_new		(void);
+GType rb_encoder_gst_get_type (void);
+
+
+G_END_DECLS
+
+#endif /* __RB_ENCODER_GST_H__ */
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ backends/gstreamer/rb-encoder-gst.c	2006-03-03 21:52:28.000000000 +1100
@@ -0,0 +1,529 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * arch-tag: Implementation of GStreamer encoding backend
+ * 
+ * Based on Sound-Juicer's ripping code
+ *
+ * Copyright (C) 2003 Ross Burton <ross@burtonini.com>
+ * Copyright (C) 2006 James Livingston <jrl@ids.org.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
+#include <gst/gst.h>
+#include <string.h>
+#include <profiles/gnome-media-profiles.h>
+
+#include "rhythmdb.h"
+#include "eel-gconf-extensions.h"
+#include "rb-preferences.h"
+#include "rb-encoder.h"
+#include "rb-encoder-gst.h"
+#include "rb-debug.h"
+
+
+static void rb_encoder_gst_class_init (RBEncoderGstClass *klass);
+static void rb_encoder_gst_init       (RBEncoderGst *encoder);
+static void rb_encoder_gst_finalize   (GObject *object);
+static void rb_encoder_init (RBEncoderIface *iface);
+
+
+struct _RBEncoderGstPrivate {
+	GstElement *pipeline;
+};
+
+G_DEFINE_TYPE_WITH_CODE(RBEncoderGst, rb_encoder_gst, G_TYPE_OBJECT,
+			G_IMPLEMENT_INTERFACE(RB_TYPE_ENCODER,
+					      rb_encoder_init))
+#define RB_ENCODER_GST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_ENCODER_GST, RBEncoderGstPrivate))
+
+
+static gboolean rb_encoder_gst_encode (RBEncoder *encoder,
+				       RhythmDBEntry *entry,
+				       const char *dest,
+				       const char *mime_type);
+static void rb_encoder_gst_cancel (RBEncoder *encoder);
+	
+static void
+rb_encoder_gst_class_init (RBEncoderGstClass *klass)
+{
+        GObjectClass *object_class = (GObjectClass *) klass;
+
+        object_class->finalize = rb_encoder_gst_finalize;
+
+        g_type_class_add_private (klass, sizeof (RBEncoderGstPrivate));
+}
+
+static void
+rb_encoder_gst_init (RBEncoderGst *encoder)
+{
+        encoder->priv = RB_ENCODER_GST_GET_PRIVATE (encoder);
+}
+
+static void
+rb_encoder_init (RBEncoderIface *iface)
+{
+	iface->encode = rb_encoder_gst_encode;
+	iface->cancel = rb_encoder_gst_cancel;
+}
+
+static void
+rb_encoder_gst_finalize (GObject *object)
+{
+	RBEncoderGst *encoder = RB_ENCODER_GST (object);
+	
+	if (encoder->priv->pipeline) {
+		gst_element_set_state (encoder->priv->pipeline, GST_STATE_NULL);
+		g_object_unref (encoder->priv->pipeline);
+		encoder->priv->pipeline = NULL;
+	}	
+
+        G_OBJECT_CLASS (rb_encoder_gst_parent_class)->finalize (object);
+}
+
+RBEncoder*
+rb_encoder_gst_new (void)
+{
+	return RB_ENCODER (g_object_new (RB_TYPE_ENCODER_GST, NULL));
+}
+
+
+static gboolean
+bus_watch_cb (GstBus *bus, GstMessage *message, gpointer data)
+{
+	RBEncoderGst *encoder = RB_ENCODER_GST (data);
+	char *string;
+	GError *error;
+
+	/* ref ourselves, in case one of the signal handler unrefs us */
+	g_object_ref (G_OBJECT (encoder));
+
+	switch (GST_MESSAGE_TYPE (message)) {
+	case GST_MESSAGE_ERROR:
+		gst_message_parse_error (message, &error, &string);
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		rb_debug ("received error %s", string);
+		g_error_free (error);
+		g_free (string);
+		
+		/* Make sure the pipeline is not running any more */
+		gst_element_set_state (encoder->priv->pipeline, GST_STATE_NULL);
+		g_object_unref (encoder->priv->pipeline);
+		encoder->priv->pipeline = NULL;
+
+		/* should be emit completed here? */
+		break;
+
+	case GST_MESSAGE_WARNING:
+		gst_message_parse_warning (message, &error, &string);
+		rb_debug ("received warning %s", string);
+		g_error_free (error);
+		g_free (string);
+		break;
+	
+	case GST_MESSAGE_EOS:
+		rb_debug ("received EOS");
+
+		gst_element_set_state (encoder->priv->pipeline, GST_STATE_NULL);
+
+		_rb_encoder_emit_completed (RB_ENCODER (encoder));
+
+		g_object_unref (encoder->priv->pipeline);
+		encoder->priv->pipeline = NULL;
+		break;
+	
+	default:
+		rb_debug ("message of type %s", gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
+		break;
+	}
+
+	g_object_unref (G_OBJECT (encoder));
+	return TRUE;
+}
+
+static void
+start_pipeline (RBEncoderGst *encoder)
+{
+	GstBus *bus;
+
+	g_assert (encoder->priv->pipeline);
+	
+	bus = gst_pipeline_get_bus (GST_PIPELINE (encoder->priv->pipeline));
+	gst_bus_add_watch (bus, bus_watch_cb, encoder);
+
+	gst_element_set_state (encoder->priv->pipeline, GST_STATE_PLAYING);
+}
+
+static GstElement*
+add_encoding_pipeline (RBEncoderGst *encoder,
+		       GstElement *start,
+		       GMAudioProfile *profile)
+{
+	GstElement *queue, *encoding_bin;
+	GstPad *pad;
+	char *tmp;
+	GError *error = NULL;
+
+	/* Nice big buffers... */
+	queue = gst_element_factory_make ("queue", "queue");
+	if (queue == NULL)
+		return NULL;
+	g_object_set (queue, "max-size-time", 120 * GST_SECOND, NULL);
+	gst_bin_add (GST_BIN (encoder->priv->pipeline), queue);
+	gst_element_link (start, queue);
+
+	tmp = g_strdup_printf ("audioconvert ! %s", gm_audio_profile_get_pipeline (profile));
+	encoding_bin = GST_ELEMENT (gst_parse_launch (tmp, &error));
+	g_free (tmp);
+
+	if (encoding_bin == NULL)
+		return NULL;
+
+	/* find pads and ghost them if necessary */
+	if ((pad = gst_bin_find_unconnected_pad (GST_BIN (encoding_bin), GST_PAD_SRC)))
+		gst_element_add_pad (encoding_bin, gst_ghost_pad_new ("src", pad));
+	if ((pad = gst_bin_find_unconnected_pad (GST_BIN (encoding_bin), GST_PAD_SINK)))
+		gst_element_add_pad (encoding_bin, gst_ghost_pad_new ("sink", pad));
+
+	gst_bin_add (GST_BIN (encoder->priv->pipeline), encoding_bin);
+	gst_element_link (queue, encoding_bin);
+
+	return encoding_bin;
+}
+
+static void
+add_tags_from_entry (RBEncoderGst *encoder,
+		     RhythmDBEntry *entry)
+{
+	GstTagList *tags;
+	GstIterator *iter;
+	gboolean done;
+
+	tags = gst_tag_list_new ();
+	gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE_ALL,
+			  /* FIXME: add the rest of them */
+			  GST_TAG_TITLE, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
+			  GST_TAG_ARTIST, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST),
+			  GST_TAG_TRACK_NUMBER, rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER),
+			  GST_TAG_ALBUM, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM),
+			  GST_TAG_ENCODER, "Rhythmbox",
+			  GST_TAG_ENCODER_VERSION, VERSION,
+			  NULL);
+
+	iter = gst_bin_iterate_all_by_interface (GST_BIN (encoder->priv->pipeline), GST_TYPE_TAG_SETTER);
+	done = FALSE;
+	while (!done) {
+		GstTagSetter *tagger = NULL;
+
+		switch (gst_iterator_next (iter, (gpointer*)&tagger)) {
+		case GST_ITERATOR_OK:
+			gst_tag_setter_merge_tags (tagger, tags, GST_TAG_MERGE_REPLACE_ALL);
+			break;
+		case GST_ITERATOR_RESYNC:
+			gst_iterator_resync (iter);
+			break;
+		case GST_ITERATOR_ERROR:
+		{
+			GError *error;
+		
+			error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_INTERNAL,
+					     "Could not add tags to tag-setter");
+			_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+			g_error_free (error);
+			done = TRUE;
+			break;
+		}
+		case GST_ITERATOR_DONE:
+			done = TRUE;
+			break;
+		}
+		
+		if (tagger)
+			gst_object_unref (tagger);
+	}
+	gst_iterator_free (iter);
+	gst_tag_list_free (tags);
+}
+
+static void
+attach_output_pipeline (RBEncoderGst *encoder,
+			GstElement *end,
+			const char *dest)
+{
+	GstElement *sink;
+
+	sink = gst_element_make_from_uri (GST_URI_SINK, dest, "sink");
+	gst_bin_add (GST_BIN (encoder->priv->pipeline), sink);
+	gst_element_link (end, sink);
+}
+
+static GMAudioProfile*
+get_profile_from_mime_type (const char *mime_type)
+{
+	/* TODO */
+	return NULL;
+}
+
+static GstElement *
+create_pipeline_and_source (RBEncoderGst *encoder,
+			    RhythmDBEntry *entry)
+{
+	const char *uri;
+	GstElement *src;
+
+	uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	src = gst_element_make_from_uri (GST_URI_SRC, uri, "source");
+	if (src == NULL) {
+		GError *error;
+		
+		error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_INTERNAL,
+				     "could not create source element for '%s'", uri);
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		g_error_free (error);
+		return NULL;
+	}
+
+	encoder->priv->pipeline = gst_pipeline_new ("pipeline");
+	gst_bin_add (GST_BIN (encoder->priv->pipeline), src);
+
+	return src;
+}
+
+static gboolean
+copy_track (RBEncoderGst *encoder,
+	    RhythmDBEntry *entry,
+	    const char *dest)
+{
+	/* source ! sink */
+	GstElement *src;
+
+	g_assert (encoder->priv->pipeline == NULL);
+
+	src = create_pipeline_and_source (encoder, entry);
+	if (src == NULL)
+		return FALSE;
+
+	attach_output_pipeline (encoder, src, dest);
+	start_pipeline (encoder);
+	return TRUE;
+}
+
+static gboolean
+extract_track (RBEncoderGst *encoder,
+	       RhythmDBEntry *entry,
+	       const char *dest)
+{
+	/* cdsrc ! encoder ! sink */
+	const char *uri;
+	const char *device;
+	const char *profile_name;
+	GMAudioProfile *profile;
+	GstElement *src, *end;
+
+	g_assert (encoder->priv->pipeline == NULL);
+
+	profile_name = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
+	profile = gm_audio_profile_lookup (profile_name);
+	if (profile == NULL) {
+		GError *error;
+		
+		error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_FORMAT_UNSUPPORTED,
+				     "Could not find encoding profile '%s'", profile_name);
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	src = create_pipeline_and_source (encoder, entry);
+	if (src == NULL)
+		return FALSE;
+
+	/* setup cd extraction properties */
+	uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+
+	device = g_utf8_strrchr (uri, -1, '#');
+	g_object_set (G_OBJECT (src),
+		      "device", device + 1, /* skip the '#' */
+		      "track", rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER),
+		      NULL);
+	if (g_object_class_find_property (G_OBJECT_GET_CLASS (src), "paranoia-mode")) {
+		int paranoia_mode;
+
+		paranoia_mode = 255; /* TODO: make configurable */
+		g_object_set (G_OBJECT (src), "paranoia-mode", paranoia_mode, NULL);
+	}
+
+	end = add_encoding_pipeline (encoder, src, profile);
+	if (end == NULL) {
+		GError *error;
+		
+		error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_INTERNAL,
+				     "Could not create encoding profile '%s'", profile_name);
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		g_error_free (error);
+		
+		g_object_unref (encoder->priv->pipeline);
+		encoder->priv->pipeline = NULL;
+		return FALSE;
+	}
+	attach_output_pipeline (encoder, end, dest);
+
+	add_tags_from_entry (encoder, entry);
+	start_pipeline (encoder);
+	return TRUE;
+}
+
+static gboolean
+transcode_track (RBEncoderGst *encoder,
+	 	 RhythmDBEntry *entry,
+		 const char *dest,
+		 const char *mime_type)
+{
+	/* cdsrc ! encoder ! sink */
+	GMAudioProfile *profile;
+	GstElement *src, *spider, *end;
+
+	g_assert (encoder->priv->pipeline == NULL);
+
+	profile = get_profile_from_mime_type (mime_type);
+	if (profile == NULL) {
+		GError *error;
+		
+		error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_FORMAT_UNSUPPORTED,
+				     "Unable to locate encoding profile for mime-type '%s'", mime_type);
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	src = create_pipeline_and_source (encoder, entry);
+	if (src == NULL)
+		return FALSE;
+
+	spider = gst_element_factory_make ("spider", "spider");
+	if (spider == NULL) {
+		GError *error;
+		
+		error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_INTERNAL,
+				     "Could not create encoding profile '%s'", gm_audio_profile_get_id (profile));
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		g_error_free (error);
+		
+		g_object_unref (encoder->priv->pipeline);
+		encoder->priv->pipeline = NULL;
+		return FALSE;
+	}
+	gst_bin_add (GST_BIN (encoder->priv->pipeline), spider);
+	gst_element_link (src, spider);
+
+	end = add_encoding_pipeline (encoder, spider, profile);
+	if (end == NULL) {
+		GError *error;
+		
+		error = g_error_new (RB_ENCODER_ERROR, RB_ENCODER_ERROR_INTERNAL,
+				     "Could not create encoding profile '%s'", gm_audio_profile_get_id (profile));
+		_rb_encoder_emit_error (RB_ENCODER (encoder), error);
+		g_error_free (error);
+		
+		g_object_unref (encoder->priv->pipeline);
+		encoder->priv->pipeline = NULL;
+		return FALSE;
+	}
+	attach_output_pipeline (encoder, end, dest);
+
+	add_tags_from_entry (encoder, entry);
+	start_pipeline (encoder);
+	return TRUE;
+}
+
+static void
+create_parent_dirs_uri (GnomeVFSURI *uri)
+{
+	GnomeVFSURI *parent_uri;
+
+	if (gnome_vfs_uri_exists (uri))
+		return;
+
+	parent_uri = gnome_vfs_uri_get_parent (uri);
+	create_parent_dirs_uri (parent_uri);
+	gnome_vfs_uri_unref (parent_uri);
+
+	gnome_vfs_make_directory_for_uri (uri, 0750);
+}
+
+static void
+create_parent_dirs (const char *uri)
+{
+	GnomeVFSURI *vfs_uri;
+	GnomeVFSURI *parent_uri;
+
+	vfs_uri = gnome_vfs_uri_new (uri);
+	parent_uri = gnome_vfs_uri_get_parent (vfs_uri);
+
+	create_parent_dirs_uri (parent_uri);
+
+	gnome_vfs_uri_unref (parent_uri);
+	gnome_vfs_uri_unref (vfs_uri);
+}
+
+static void
+rb_encoder_gst_cancel (RBEncoder *encoder)
+{
+	RBEncoderGstPrivate *priv = RB_ENCODER_GST (encoder)->priv;
+
+	g_return_if_fail (priv->pipeline != NULL);
+
+	gst_element_set_state (priv->pipeline, GST_STATE_NULL);
+	g_object_unref (priv->pipeline);
+	priv->pipeline = NULL;
+}
+
+static gboolean
+rb_encoder_gst_encode (RBEncoder *encoder,
+		       RhythmDBEntry *entry,
+		       const char *dest,
+		       const char *mime_type)
+{
+	RBEncoderGstPrivate *priv = RB_ENCODER_GST (encoder)->priv;
+	const char *entry_mime_type;
+	gboolean was_raw;
+	gboolean result;
+
+	g_return_val_if_fail (priv->pipeline == NULL, FALSE);
+	
+	entry_mime_type = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE);
+	was_raw = g_str_has_prefix (entry_mime_type, "audio/x-raw");
+
+	create_parent_dirs (dest);
+
+	if ((mime_type == NULL && !was_raw) || (mime_type && (strcmp (mime_type, entry_mime_type) == 0))) {
+		result = copy_track (RB_ENCODER_GST (encoder), entry, dest);
+	} else {
+		if (mime_type == NULL) {
+			result = extract_track (RB_ENCODER_GST (encoder), entry, dest);
+		} else {
+			result = transcode_track (RB_ENCODER_GST (encoder), entry, dest, mime_type);
+		}
+	}
+
+	return result;
+}
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ backends/gstreamer/Makefile.am	2006-03-03 14:34:31.000000000 +1100
@@ -0,0 +1,27 @@
+## arch-tag: Automake rules for gstreamer backend library
+
+noinst_LTLIBRARIES = librbbackendsgstreamer.la
+
+librbbackendsgstreamer_la_SOURCES =	\
+	rb-encoder-gst.h		\
+	rb-encoder-gst.c
+
+librbbackendsgstreamer_la_LIBADD =				\
+	$(RHYTHMBOX_LIBS)
+
+librbbackendsgstreamer_la_LDFLAGS = -export-dynamic
+
+INCLUDES = 						\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
+	-DG_LOG_DOMAIN=\"Rhythmbox\"			\
+	-I$(top_srcdir) 				\
+	-I$(top_srcdir)/lib 				\
+	-I$(top_srcdir)/metadata			\
+	-I$(top_srcdir)/sources				\
+	-I$(top_srcdir)/rhythmdb			\
+	-I$(top_srcdir)/backends			\
+	-I$(top_srcdir)/widgets				\
+	$(LIBJUICER_CFLAGS)				\
+	$(RHYTHMBOX_CFLAGS)
+
+
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ backends/rb-encoder.h	2006-03-03 21:45:34.000000000 +1100
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * arch-tag: Interface to audio encoder backend  
+ *
+ * Copyright (C) 2006 James Livingston <jrl@ids.org.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __RB_ENCODER_H__
+#define __RB_ENCODER_H__
+
+#include <glib-object.h>
+
+#include "rhythmdb.h"
+
+G_BEGIN_DECLS
+
+#define RB_TYPE_ENCODER            (rb_encoder_get_type ())
+#define RB_ENCODER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), RB_TYPE_ENCODER, RBEncoder))
+#define RB_IS_ENCODER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RB_TYPE_ENCODER))
+#define RB_ENCODER_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), RB_TYPE_ENCODER, RBEncoderIface))
+
+
+enum
+{
+	RB_ENCODER_ERROR_FORMAT_UNSUPPORTED,
+	RB_ENCODER_ERROR_INTERNAL,
+};
+
+#define RB_ENCODER_ERROR rb_encoder_error_quark ()
+
+GQuark rb_encoder_error_quark (void);
+
+typedef struct _RBEncoder RBEncoder;
+
+typedef struct
+{
+	GTypeInterface g_iface;
+
+	/* vtable */
+	gboolean	(*encode)	(RBEncoder *encoder,
+					 RhythmDBEntry *entry,
+					 const char *dest,
+					 const char *mime_type);
+	void		(*cancel)	(RBEncoder *encoder);
+
+	/* signals */
+	void (*progress) (RBEncoder *encoder,  guint done);
+	void (*completed) (RBEncoder *encoder);
+	void (*error) (RBEncoder *encoder, GError *error);
+} RBEncoderIface;
+
+RBEncoder*	rb_encoder_new		(void);
+GType rb_encoder_get_type (void);
+
+gboolean	rb_encoder_encode	(RBEncoder *encoder,
+					 RhythmDBEntry *entry,
+					 const char *dest,
+					 const char *mime_type);
+void		rb_encoder_cancel	(RBEncoder *encoder);
+
+/* obly to be used by subclasses */
+void	_rb_encoder_emit_progress (RBEncoder *encoder, guint done);
+void	_rb_encoder_emit_completed (RBEncoder *encoder);
+void	_rb_encoder_emit_error (RBEncoder *encoder, GError *error);
+
+G_END_DECLS
+
+#endif /* __RB_ENCODER_H__ */
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ backends/rb-encoder.c	2006-03-03 21:46:06.000000000 +1100
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *  Copyright (C) 2006  James Livingston  <jrl@ids.org.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include "rb-encoder.h"
+#include "rb-encoder-gst.h"
+
+/* Signals */
+enum {
+	PROGRESS,
+	COMPLETED,
+	ERROR,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+rb_encoder_interface_init (RBEncoderIface *iface)
+{
+	signals[PROGRESS] =
+		g_signal_new ("progress",
+			      G_TYPE_FROM_INTERFACE (iface),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (RBEncoderIface, progress),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__INT,
+			      G_TYPE_NONE,
+			      1, G_TYPE_UINT);
+	signals[COMPLETED] =
+		g_signal_new ("completed",
+			      G_TYPE_FROM_INTERFACE (iface),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (RBEncoderIface, completed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE,
+			      0);
+	signals[ERROR] =
+		g_signal_new ("error",
+			      G_TYPE_FROM_INTERFACE (iface),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (RBEncoderIface, error),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE,
+			      1, G_TYPE_POINTER);
+
+}
+
+GType
+rb_encoder_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (!our_type) {
+		static const GTypeInfo our_info = {
+			sizeof (RBEncoderIface),
+			NULL,	/* base_init */
+			NULL,	/* base_finalize */
+			(GClassInitFunc)rb_encoder_interface_init,
+			NULL,	/* class_finalize */
+			NULL,	/* class_data */
+			0,
+			0,
+			NULL
+		};
+
+		our_type = g_type_register_static (G_TYPE_INTERFACE, "RBEncoder", &our_info, 0);
+	}
+
+	return our_type;
+}
+
+
+gboolean
+rb_encoder_encode (RBEncoder *encoder,
+		   RhythmDBEntry *entry,
+		   const char *dest,
+		   const char *mime_type)
+{
+	RBEncoderIface *iface = RB_ENCODER_GET_IFACE (encoder);
+
+	return iface->encode (encoder, entry, dest, mime_type);	  	 
+}
+	
+void
+rb_encoder_cancel (RBEncoder *encoder)
+{
+	RBEncoderIface *iface = RB_ENCODER_GET_IFACE (encoder);
+
+	iface->cancel (encoder);	  	 
+}
+
+RBEncoder*
+rb_encoder_new (void)
+{
+	return rb_encoder_gst_new ();
+}
+
+void
+_rb_encoder_emit_progress (RBEncoder *encoder, guint done)
+{
+	g_signal_emit (encoder, signals[PROGRESS], 0, done);
+}
+
+void
+_rb_encoder_emit_completed (RBEncoder *encoder)
+{
+	g_signal_emit (encoder, signals[COMPLETED], 0);
+}
+
+void
+_rb_encoder_emit_error (RBEncoder *encoder, GError *error)
+{
+	g_signal_emit (encoder, signals[ERROR], 0, error);
+}
+
+GQuark
+rb_encoder_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark)
+		quark = g_quark_from_static_string ("rb_encoder_error");
+
+	return quark;
+}
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ backends/Makefile.am	2006-03-03 12:44:07.000000000 +1100
@@ -0,0 +1,29 @@
+## arch-tag: Automake rules for backends library
+
+noinst_LTLIBRARIES = librbbackends.la
+
+SUBDIRS = gstreamer
+
+librbbackends_la_SOURCES =	\
+	rb-encoder.h 		\
+	rb-encoder.c
+
+librbbackends_la_LIBADD =				\
+	$(RHYTHMBOX_LIBS)				\
+	$(top_builddir)/backends/gstreamer/librbbackendsgstreamer.la
+
+librbbackends_la_LDFLAGS = -export-dynamic
+
+INCLUDES = 						\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
+	-DG_LOG_DOMAIN=\"Rhythmbox\"			\
+	-I$(top_srcdir) 				\
+	-I$(top_srcdir)/lib 				\
+	-I$(top_srcdir)/metadata			\
+	-I$(top_srcdir)/shell				\
+	-I$(top_srcdir)/rhythmdb			\
+	-I$(top_srcdir)/widgets				\
+	-I$(top_srcdir)/backends/gstreamer		\
+	$(LIBNAUTILUS_BURN_CFLAGS)			\
+	$(RHYTHMBOX_CFLAGS)
+
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ sources/rb-library-source.c	2006-03-03 22:32:21.000000000 +1100
@@ -0,0 +1,1588 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *  arch-tag: Implementation of local file source object
+ *
+ *  Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
+ *  Copyright (C) 2003,2004 Colin Walters <walters@verbum.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <glade/glade.h>
+#include <profiles/gnome-media-profiles.h>
+#include <profiles/audio-profile-choose.h>
+
+#include "rb-source.h"
+#include "rb-library-source.h"
+#include "rhythmdb-query-model.h"
+#include "rb-property-view.h"
+#include "rb-glade-helpers.h"
+#include "rb-stock-icons.h"
+#include "rb-entry-view.h"
+#include "rb-library-browser.h"
+#include "rb-util.h"
+#include "rb-file-helpers.h"
+#include "rb-dialog.h"
+#include "rb-debug.h"
+#include "eel-gconf-extensions.h"
+#include "rb-song-info.h"
+#include "rb-search-entry.h"
+#include "rb-preferences.h"
+#include "rb-shell-preferences.h"
+#include "rb-removable-media-manager.h"
+
+static void rb_library_source_class_init (RBLibrarySourceClass *klass);
+static void rb_library_source_init (RBLibrarySource *source);
+static GObject *rb_library_source_constructor (GType type, guint n_construct_properties,
+					       GObjectConstructParam *construct_properties);
+static void rb_library_source_dispose (GObject *object);
+static void rb_library_source_finalize (GObject *object);
+static void rb_library_source_set_property (GObject *object,
+			                  guint prop_id,
+			                  const GValue *value,
+			                  GParamSpec *pspec);
+static void rb_library_source_get_property (GObject *object,
+			                  guint prop_id,
+			                  GValue *value,
+			                  GParamSpec *pspec);
+static void rb_library_source_cmd_choose_genre (GtkAction *action,
+						RBShell *shell);
+static void rb_library_source_cmd_choose_artist (GtkAction *action,
+						 RBShell *shell);
+static void rb_library_source_cmd_choose_album (GtkAction *action,
+						RBShell *shell);
+static void songs_view_sort_order_changed_cb (RBEntryView *view, RBLibrarySource *source);
+static void rb_library_source_library_location_cb (GtkEntry *entry,
+						   GdkEventFocus *event,
+						   RBLibrarySource *source);
+static void rb_library_source_browser_changed_cb (RBLibraryBrowser *entry,
+						  RBLibrarySource *source);
+
+static void paned_size_allocate_cb (GtkWidget *widget,
+				    GtkAllocation *allocation,
+		                    RBLibrarySource *source);
+static void rb_library_source_state_pref_changed (GConfClient *client,
+						 guint cnxn_id,
+						 GConfEntry *entry,
+						 RBLibrarySource *source);
+static void rb_library_source_ui_pref_changed (GConfClient *client,
+					       guint cnxn_id,
+					       GConfEntry *entry,
+					       RBLibrarySource *source); 
+static void rb_library_source_library_pref_changed (GConfClient *client,
+						    guint cnxn_id,
+						    GConfEntry *entry,
+						    RBLibrarySource *source);
+static void rb_library_source_location_button_clicked_cb (GtkButton *button,
+							  RBLibrarySource *source);
+static void rb_library_source_state_prefs_sync (RBLibrarySource *source);
+static void rb_library_source_ui_prefs_sync (RBLibrarySource *source);
+static void rb_library_source_preferences_sync (RBLibrarySource *source);
+
+/* source methods */
+static const char *impl_get_browser_key (RBSource *source);
+static RBEntryView *impl_get_entry_view (RBSource *source);
+static GList *impl_get_property_views (RBSource *source);
+static void impl_delete (RBSource *source);
+static void impl_move_to_trash (RBSource *source);
+static void impl_search (RBSource *source, const char *text);
+static void impl_reset_filters (RBSource *source);
+static GtkWidget *impl_get_config_widget (RBSource *source, RBShellPreferences *prefs);
+static void impl_song_properties (RBSource *source);
+static gboolean impl_receive_drag (RBSource *source, GtkSelectionData *data);
+static gboolean impl_can_paste (RBSource *asource);
+static void impl_paste (RBSource *source, GList *entries);
+static gboolean impl_show_popup (RBSource *source);
+static const char * impl_get_paned_key (RBLibrarySource *source);
+static void rb_library_source_do_query (RBLibrarySource *source);
+
+static GPtrArray * construct_query_from_selection (RBLibrarySource *source);
+static void songs_view_drag_data_received_cb (GtkWidget *widget,
+					      GdkDragContext *dc,
+					      gint x, gint y,
+					      GtkSelectionData *data,
+					      guint info, guint time,
+					      RBLibrarySource *source);
+static void rb_library_source_watch_toggled_cb (GtkToggleButton *button,
+						RBLibrarySource *source);
+						
+static void rb_library_source_path_changed_cb (GtkComboBox *box,
+						RBLibrarySource *source);
+static void rb_library_source_filename_changed_cb (GtkComboBox *box,
+						   RBLibrarySource *source);
+static void rb_library_source_format_changed_cb (GtkWidget *widget,
+						 RBLibrarySource *source);
+
+
+#define CONF_UI_LIBRARY_DIR CONF_PREFIX "/ui/library"
+#define CONF_STATE_LIBRARY_DIR CONF_PREFIX "/state/library"
+#define CONF_STATE_LIBRARY_SORTING CONF_PREFIX "/state/library/sorting"
+#define CONF_STATE_PANED_POSITION CONF_PREFIX "/state/library/paned_position"
+#define CONF_STATE_SHOW_BROWSER   CONF_PREFIX "/state/library/show_browser"
+
+
+typedef struct {
+	char *title;
+	char *path;
+} LibraryPathElement;
+
+const LibraryPathElement library_layout_paths[] = {
+	{N_("Artist/Album"), "%aa/%at"},
+	{N_("Artist - Album"), "%aa - %at"},
+	{N_("Artist/Artist - Album"), "%aa/%aa - %at"},
+};
+const int num_library_layout_paths = G_N_ELEMENTS (library_layout_paths);
+
+const LibraryPathElement library_layout_filenames[] = {
+	{N_("Artist - Title"), "%ta - %tt"},
+	{N_("Track - Title"), "%tn - %tt"},
+	{N_("Artist - Track - Title"), "%ta - %tn - %tt"},
+	{N_("Artist (Album) - Track - Title"), "%ta (%at) - %tn - %tt"},
+};
+const int num_library_layout_filenames = G_N_ELEMENTS (library_layout_filenames);
+
+struct RBLibrarySourcePrivate
+{
+	RhythmDB *db;
+	
+	RBLibraryBrowser *browser;
+	GtkWidget *vbox;
+
+	GdkPixbuf *pixbuf;
+
+	RBEntryView *songs;
+
+	GtkWidget *paned;
+
+	gboolean lock;
+
+	RhythmDBQueryModel *cached_all_query;
+	char *search_text;
+	
+	gboolean loading_prefs;
+	RBShellPreferences *shell_prefs;
+
+	GtkActionGroup *action_group;
+	GtkWidget *config_widget;
+
+	GtkWidget *library_location_entry;
+	GtkWidget *watch_library_check;
+	GtkWidget *layout_path_menu;
+	GtkWidget *layout_filename_menu;
+	GtkWidget *preferred_format_menu;
+	
+	RhythmDBEntryType entry_type;
+
+	char *sorting_key;
+	guint ui_dir_notify_id;
+	guint state_paned_notify_id;
+	guint state_browser_notify_id;
+	guint state_sorting_notify_id;
+	guint library_pref_notify_id;
+};
+
+#define RB_LIBRARY_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_LIBRARY_SOURCE, RBLibrarySourcePrivate))
+
+static GtkActionEntry rb_library_source_actions [] =
+{
+	{ "LibrarySrcChooseGenre", NULL, N_("Browse This _Genre"), NULL,
+	  N_("Set the browser to view only this genre"),
+	  G_CALLBACK (rb_library_source_cmd_choose_genre) },
+	{ "LibrarySrcChooseArtist", NULL , N_("Browse This _Artist"), NULL,
+	  N_("Set the browser to view only this artist"),
+	  G_CALLBACK (rb_library_source_cmd_choose_artist) },
+	{ "LibrarySrcChooseAlbum", NULL, N_("Browse This A_lbum"), NULL,
+	  N_("Set the browser to view only this album"),
+	  G_CALLBACK (rb_library_source_cmd_choose_album) }
+};
+
+static const GtkTargetEntry songs_view_drag_types[] = {{  "text/uri-list", 0, 0 }};
+
+enum
+{
+	PROP_0,
+	PROP_ENTRY_TYPE,
+	PROP_SORTING_KEY
+};
+
+
+G_DEFINE_TYPE (RBLibrarySource, rb_library_source, RB_TYPE_SOURCE)
+
+static void
+rb_library_source_class_init (RBLibrarySourceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
+
+	object_class->dispose = rb_library_source_dispose;
+	object_class->finalize = rb_library_source_finalize;
+	object_class->constructor = rb_library_source_constructor;
+
+	object_class->set_property = rb_library_source_set_property;
+	object_class->get_property = rb_library_source_get_property;
+
+	source_class->impl_can_browse = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_get_browser_key = impl_get_browser_key;
+	source_class->impl_can_search = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_search = impl_search;
+	source_class->impl_get_entry_view = impl_get_entry_view;
+	source_class->impl_get_property_views = impl_get_property_views;
+	source_class->impl_get_config_widget = impl_get_config_widget;
+	source_class->impl_reset_filters = impl_reset_filters;
+	source_class->impl_song_properties = impl_song_properties;
+	source_class->impl_can_pause = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_can_paste = (RBSourceFeatureFunc) impl_can_paste;
+	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_add_to_queue = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_can_move_to_trash = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_delete = impl_delete;
+	source_class->impl_move_to_trash = impl_move_to_trash;
+	source_class->impl_have_url = (RBSourceFeatureFunc) rb_false_function;
+	source_class->impl_receive_drag = impl_receive_drag;
+	source_class->impl_show_popup = impl_show_popup;
+	source_class->impl_paste = impl_paste;
+
+	klass->impl_get_paned_key = impl_get_paned_key;
+	klass->impl_has_first_added_column = (RBLibrarySourceFeatureFunc) rb_true_function;
+	klass->impl_has_drop_support = (RBLibrarySourceFeatureFunc) rb_true_function;
+
+	g_object_class_install_property (object_class,
+					 PROP_ENTRY_TYPE,
+					 g_param_spec_uint ("entry-type",
+							    "Entry type",
+							    "Type of the entries which should be displayed by this source",
+							    0,
+							    G_MAXINT,
+							    RHYTHMDB_ENTRY_TYPE_SONG,
+							    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+					 PROP_SORTING_KEY,
+					 g_param_spec_string ("sorting-key",
+							      "Sorting key",
+							      "GConf key for storing sort-order",
+							      CONF_STATE_LIBRARY_SORTING,
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_type_class_add_private (klass, sizeof (RBLibrarySourcePrivate));
+
+	gnome_media_profiles_init (gconf_client_get_default ());
+}
+
+static void
+rb_library_source_library_pref_changed (GConfClient *client,
+					guint cnxn_id,
+					GConfEntry *entry,
+					RBLibrarySource *source)
+{
+	if (source->priv->config_widget)
+		rb_library_source_preferences_sync (source);
+}
+
+static void
+rb_library_source_ui_prefs_sync (RBLibrarySource *source)
+{
+	if (source->priv->config_widget)
+		rb_library_source_preferences_sync (source);
+}
+
+static void
+rb_library_source_ui_pref_changed (GConfClient *client,
+				   guint cnxn_id,
+				   GConfEntry *entry,
+				   RBLibrarySource *source)
+{
+	rb_debug ("ui pref changed");
+	rb_library_source_ui_prefs_sync (source);
+}
+
+static void
+rb_library_source_init (RBLibrarySource *source)
+{
+	source->priv = RB_LIBRARY_SOURCE_GET_PRIVATE (source);
+
+	/* Drag'n'Drop */
+
+	source->priv->vbox = gtk_vbox_new (FALSE, 5);
+
+	gtk_container_add (GTK_CONTAINER (source), source->priv->vbox);
+}
+
+static void
+rb_library_source_dispose (GObject *object)
+{
+	RBLibrarySource *source;
+	source = RB_LIBRARY_SOURCE (object);
+
+	if (source->priv->shell_prefs) {
+		g_object_unref (source->priv->shell_prefs);
+		source->priv->shell_prefs = NULL;
+	}
+
+	if (source->priv->db) {
+		g_object_unref (source->priv->db);
+		source->priv->db = NULL;
+	}
+
+	if (source->priv->search_text) {
+		g_free (source->priv->search_text);
+		source->priv->search_text = NULL;
+	}
+}
+
+static void
+rb_library_source_finalize (GObject *object)
+{
+	RBLibrarySource *source;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (RB_IS_LIBRARY_SOURCE (object));
+
+	source = RB_LIBRARY_SOURCE (object);
+
+	g_return_if_fail (source->priv != NULL);
+
+	rb_debug ("finalizing library source");
+	
+	eel_gconf_notification_remove (source->priv->ui_dir_notify_id);
+	eel_gconf_notification_remove (source->priv->library_pref_notify_id);
+	eel_gconf_notification_remove (source->priv->state_browser_notify_id);
+	eel_gconf_notification_remove (source->priv->state_paned_notify_id);
+	eel_gconf_notification_remove (source->priv->state_sorting_notify_id);
+
+	g_free (source->priv->sorting_key);
+
+	if (source->priv->cached_all_query)
+		g_object_unref (G_OBJECT (source->priv->cached_all_query));
+
+	G_OBJECT_CLASS (rb_library_source_parent_class)->finalize (object);
+}
+
+static void
+rb_library_source_songs_show_popup_cb (RBEntryView *view,
+				       gboolean over_entry,
+				       RBLibrarySource *source)
+{
+	if (over_entry)
+		_rb_source_show_popup (RB_SOURCE (source), "/LibraryViewPopup");
+	else
+		_rb_source_show_popup (RB_SOURCE (source), "/LibrarySourcePopup");
+}
+
+static GObject *
+rb_library_source_constructor (GType type, guint n_construct_properties,
+			       GObjectConstructParam *construct_properties)
+{
+	RBLibrarySource *source;
+	RBLibrarySourceClass *klass;
+	RBShell *shell;
+	GObject *shell_player;
+
+	klass = RB_LIBRARY_SOURCE_CLASS (g_type_class_peek (RB_TYPE_LIBRARY_SOURCE));
+
+	source = RB_LIBRARY_SOURCE (G_OBJECT_CLASS (rb_library_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, NULL);
+	shell_player = rb_shell_get_player (shell);
+	
+	source->priv->action_group = _rb_source_register_action_group (RB_SOURCE (source),
+								       "LibraryActions",
+								       rb_library_source_actions,
+								       G_N_ELEMENTS (rb_library_source_actions),
+								       shell);
+
+	g_object_unref (G_OBJECT (shell));
+
+	source->priv->paned = gtk_vpaned_new ();
+
+	source->priv->browser = rb_library_browser_new (source->priv->db);
+	gtk_paned_pack1 (GTK_PANED (source->priv->paned), GTK_WIDGET (source->priv->browser), TRUE, FALSE);
+	g_signal_connect_object (G_OBJECT (source->priv->browser), "changed",
+				 G_CALLBACK (rb_library_source_browser_changed_cb),
+				 source, 0);
+
+	/* set up songs tree view */
+	source->priv->songs = rb_entry_view_new (source->priv->db, shell_player,
+						 source->priv->sorting_key,
+						 TRUE, FALSE);
+
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_TITLE, TRUE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_GENRE, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_YEAR, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_DURATION, FALSE);
+ 	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_QUALITY, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_RATING, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
+	rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
+	if (rb_library_source_has_first_added_column (source))
+		rb_entry_view_append_column (source->priv->songs, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE);
+
+	g_signal_connect_object (G_OBJECT (source->priv->songs), "show_popup",
+				 G_CALLBACK (rb_library_source_songs_show_popup_cb), source, 0);
+	g_signal_connect_object (G_OBJECT (source->priv->songs),
+				 "sort-order-changed",
+				 G_CALLBACK (songs_view_sort_order_changed_cb),
+				 source, 0);
+
+	/* set up drag and drop for the song tree view.
+	 * we don't use RBEntryView's DnD support because it does too much.
+	 * we just want to be able to drop songs in to add them to the 
+	 * library.
+	 */
+	g_signal_connect_object (G_OBJECT (source->priv->songs), 
+				 "drag_data_received",
+				 G_CALLBACK (songs_view_drag_data_received_cb),
+				 source, 0);
+
+	/* only add drop support for the Library, subclasses can add it themselves */	
+	if (rb_library_source_has_drop_support (source)) {
+		gtk_drag_dest_set (GTK_WIDGET (source->priv->songs),
+				   GTK_DEST_DEFAULT_ALL,
+				   songs_view_drag_types, 1,
+				   GDK_ACTION_COPY | GDK_ACTION_MOVE);	/* really accept move actions? */
+	}
+
+
+	/* this gets emitted when the paned thingie is moved */
+	g_signal_connect_object (G_OBJECT (source->priv->songs),
+				 "size_allocate",
+				 G_CALLBACK (paned_size_allocate_cb),
+				 source, 0);
+
+	gtk_paned_pack2 (GTK_PANED (source->priv->paned), GTK_WIDGET (source->priv->songs), TRUE, FALSE);
+
+	gtk_box_pack_start_defaults (GTK_BOX (source->priv->vbox), source->priv->paned);
+
+	gtk_widget_show_all (GTK_WIDGET (source));
+
+	rb_library_source_state_prefs_sync (source);
+	rb_library_source_ui_prefs_sync (source);
+
+	if (source->priv->sorting_key) {
+		source->priv->state_sorting_notify_id =
+			eel_gconf_notification_add (source->priv->sorting_key,
+					    (GConfClientNotifyFunc) rb_library_source_state_pref_changed,
+					    source);
+	}
+	if (rb_library_source_get_paned_key (source)) {
+		source->priv->state_paned_notify_id =
+			eel_gconf_notification_add (rb_library_source_get_paned_key (source),
+					    (GConfClientNotifyFunc) rb_library_source_state_pref_changed,
+					    source);
+	}
+	if (rb_source_get_browser_key (RB_SOURCE (source))) {
+		source->priv->state_browser_notify_id =
+			eel_gconf_notification_add (rb_source_get_browser_key (RB_SOURCE (source)),
+					    (GConfClientNotifyFunc) rb_library_source_state_pref_changed,
+					    source);
+	}
+
+	source->priv->ui_dir_notify_id =
+		eel_gconf_notification_add (CONF_UI_LIBRARY_DIR,
+				    (GConfClientNotifyFunc) rb_library_source_ui_pref_changed, source);
+	source->priv->library_pref_notify_id =
+		eel_gconf_notification_add (CONF_PREFIX,
+				    (GConfClientNotifyFunc) rb_library_source_library_pref_changed, source);
+
+	source->priv->cached_all_query = rhythmdb_query_model_new_empty (source->priv->db);
+	rhythmdb_do_full_query_async (source->priv->db,
+				      RHYTHMDB_QUERY_RESULTS (source->priv->cached_all_query),
+				      RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, source->priv->entry_type,
+				      RHYTHMDB_QUERY_END);
+	rb_library_browser_set_model (source->priv->browser, source->priv->cached_all_query);
+	rb_library_source_do_query (source);
+
+	return G_OBJECT (source);
+}
+
+
+static void
+rb_library_source_set_property (GObject *object,
+				guint prop_id,
+				const GValue *value,
+				GParamSpec *pspec)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (object);
+
+	switch (prop_id) {
+	case PROP_ENTRY_TYPE:
+		source->priv->entry_type = g_value_get_uint (value);
+		break;
+	case PROP_SORTING_KEY:
+		g_free (source->priv->sorting_key);
+		source->priv->sorting_key = g_strdup (g_value_get_string (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+rb_library_source_get_property (GObject *object,
+				guint prop_id,
+				GValue *value,
+				GParamSpec *pspec)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (object);
+
+	switch (prop_id) {
+	case PROP_ENTRY_TYPE:
+		g_value_set_uint (value, source->priv->entry_type);
+		break;
+	case PROP_SORTING_KEY:
+		g_value_set_string (value, source->priv->sorting_key);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+RBSource *
+rb_library_source_new (RBShell *shell)
+{
+	RBSource *source;
+	GdkPixbuf *icon;
+	gint size;
+
+	gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
+	icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+					 "stock_music-library",
+					 size,
+					 0, NULL);
+
+	source = RB_SOURCE (g_object_new (RB_TYPE_LIBRARY_SOURCE,
+					  "name", _("Library"),
+					  "entry-type", RHYTHMDB_ENTRY_TYPE_SONG,
+					  "shell", shell,
+					  "icon", icon,
+					  NULL));
+	rb_shell_register_entry_type_for_source (shell, source, 
+						 RHYTHMDB_ENTRY_TYPE_SONG);
+	return source;
+}
+
+static void
+rb_library_source_cmd_choose_genre (GtkAction *action,
+				    RBShell *shell)
+{
+	GList *props;
+	RBLibrarySource *source;
+
+	rb_debug ("choosing genre");
+
+	g_object_get (G_OBJECT (shell), "selected-source", &source, NULL);
+	props = rb_source_gather_selected_properties (RB_SOURCE (source), RHYTHMDB_PROP_GENRE);
+	rb_library_browser_set_selection (source->priv->browser, RHYTHMDB_PROP_GENRE, props);
+	rb_list_deep_free (props);
+	g_object_unref (source);
+}
+
+static void
+rb_library_source_cmd_choose_artist (GtkAction *action,
+				     RBShell *shell)
+{
+	GList *props;	
+	RBLibrarySource *source;
+
+	rb_debug ("choosing artist");
+
+	g_object_get (G_OBJECT (shell), "selected-source", &source, NULL);
+	props = rb_source_gather_selected_properties (RB_SOURCE (source), RHYTHMDB_PROP_ARTIST);
+	rb_library_browser_set_selection (source->priv->browser, RHYTHMDB_PROP_ARTIST, props);
+	rb_list_deep_free (props);
+	g_object_unref (source);
+}
+
+static void
+rb_library_source_cmd_choose_album (GtkAction *action,
+				    RBShell *shell)
+{
+	GList *props;	
+	RBLibrarySource *source;
+
+	rb_debug ("choosing album");
+
+	g_object_get (G_OBJECT (shell), "selected-source", &source, NULL);
+	props = rb_source_gather_selected_properties (RB_SOURCE (source), RHYTHMDB_PROP_ALBUM);
+	rb_library_browser_set_selection (source->priv->browser, RHYTHMDB_PROP_ALBUM, props);
+	rb_list_deep_free (props);
+	g_object_unref (source);
+}
+
+static void
+songs_view_sort_order_changed_cb (RBEntryView *view, RBLibrarySource *source)
+{
+	rb_debug ("sort order changed");
+	rb_entry_view_resort_model (view);
+}
+
+static const char *
+impl_get_browser_key (RBSource *source)
+{
+	return CONF_STATE_SHOW_BROWSER;
+}
+
+static const char *
+impl_get_paned_key (RBLibrarySource *status)
+{
+	return CONF_STATE_PANED_POSITION;
+}
+
+static void
+impl_search (RBSource *asource, const char *search_text)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+
+	if (search_text == NULL && source->priv->search_text == NULL)
+		return;
+	if (search_text != NULL &&
+	    source->priv->search_text != NULL
+	    && !strcmp (search_text, source->priv->search_text))
+		return;
+
+	if (search_text[0] == '\0')
+		search_text = NULL;
+
+	rb_debug ("doing search for \"%s\"", search_text ? search_text : "(NULL)");
+
+	g_free (source->priv->search_text);
+	source->priv->search_text = g_strdup (search_text);
+	rb_library_source_do_query (source);
+
+	rb_source_notify_filter_changed (RB_SOURCE (source));
+}
+
+
+static RBEntryView *
+impl_get_entry_view (RBSource *asource)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+
+	return source->priv->songs;
+}
+
+static GList *
+impl_get_property_views (RBSource *asource)
+{
+	GList *ret;
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+
+	ret =  rb_library_browser_get_property_views (source->priv->browser);
+	return ret;
+}
+
+static void
+impl_reset_filters (RBSource *asource)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	gboolean changed = FALSE;
+
+	
+	if (rb_library_browser_reset (source->priv->browser))
+		changed = TRUE;
+
+	if (source->priv->search_text != NULL)
+		changed = TRUE;
+	g_free (source->priv->search_text);
+	source->priv->search_text = NULL;
+
+	if (changed) {
+		rb_library_source_do_query (source);
+		rb_source_notify_filter_changed (RB_SOURCE (source));
+	}
+}
+  
+static GtkWidget *
+impl_get_config_widget (RBSource *asource, RBShellPreferences *prefs)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	GtkWidget *tmp;
+	GladeXML *xml;
+	int i;
+
+	if (source->priv->config_widget)
+		return source->priv->config_widget;
+	
+	g_object_ref (G_OBJECT (prefs));
+	source->priv->shell_prefs = prefs;
+	
+	xml = rb_glade_xml_new ("library-prefs.glade", "library_vbox", source);
+	source->priv->config_widget =
+		glade_xml_get_widget (xml, "library_vbox");
+
+	source->priv->library_location_entry = glade_xml_get_widget (xml, "library_location_entry");
+	tmp = glade_xml_get_widget (xml, "library_location_button");
+	g_signal_connect (G_OBJECT (tmp),
+			  "clicked",
+			  G_CALLBACK (rb_library_source_location_button_clicked_cb),
+			  asource);
+	g_signal_connect (G_OBJECT (source->priv->library_location_entry),
+			  "focus-out-event",
+			  G_CALLBACK (rb_library_source_library_location_cb),
+			  asource);
+
+	source->priv->watch_library_check = glade_xml_get_widget (xml, "watch_library_check");
+	g_signal_connect (G_OBJECT (source->priv->watch_library_check),
+			  "toggled",
+			  G_CALLBACK (rb_library_source_watch_toggled_cb),
+			  asource);
+
+	tmp = glade_xml_get_widget (xml, "layout_path_menu_box");
+	source->priv->layout_path_menu = gtk_combo_box_new_text ();
+	gtk_box_pack_start_defaults (GTK_BOX (tmp), source->priv->layout_path_menu);
+	g_signal_connect (G_OBJECT (source->priv->layout_path_menu),
+			  "changed",
+			  G_CALLBACK (rb_library_source_path_changed_cb),
+			  asource);
+	for (i = 0; i < num_library_layout_paths; i++) {
+		gtk_combo_box_append_text (GTK_COMBO_BOX (source->priv->layout_path_menu),
+					   _(library_layout_paths[i].title));
+	}
+
+	tmp = glade_xml_get_widget (xml, "layout_filename_menu_box");
+	source->priv->layout_filename_menu = gtk_combo_box_new_text ();
+	gtk_box_pack_start_defaults (GTK_BOX (tmp), source->priv->layout_filename_menu);
+	g_signal_connect (G_OBJECT (source->priv->layout_filename_menu),
+			  "changed",
+			  G_CALLBACK (rb_library_source_filename_changed_cb),
+			  asource);
+	for (i = 0; i < num_library_layout_filenames; i++) {
+		gtk_combo_box_append_text (GTK_COMBO_BOX (source->priv->layout_filename_menu),
+					   _(library_layout_filenames[i].title));
+	}
+
+	tmp = glade_xml_get_widget (xml, "preferred_format_menu_box");
+	source->priv->preferred_format_menu = gm_audio_profile_choose_new ();
+	gtk_box_pack_start_defaults (GTK_BOX (tmp), source->priv->preferred_format_menu);
+	g_signal_connect (G_OBJECT (source->priv->preferred_format_menu),
+			  "changed",
+			  G_CALLBACK (rb_library_source_format_changed_cb),
+			  asource);
+
+	rb_glade_boldify_label (xml, "library_location_label");
+	rb_glade_boldify_label (xml, "library_structure_label");
+	g_object_unref (G_OBJECT (xml));
+	
+	rb_library_source_preferences_sync (source);
+
+	return source->priv->config_widget;
+}
+
+static void
+rb_library_source_location_button_clicked_cb (GtkButton *button, RBLibrarySource *source)
+{
+	GtkWidget *dialog;
+	
+	/* TODO display file chooser */
+	dialog = rb_file_chooser_new (_("Choose Library Location"), GTK_WINDOW (source->priv->shell_prefs),
+				      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FALSE);
+	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+		char *uri;
+		char *path;
+
+		uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+		if (uri == NULL) {
+			uri = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
+		}
+		
+		path = gnome_vfs_format_uri_for_display (uri);
+		
+		gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), path);
+		rb_library_source_library_location_cb (GTK_ENTRY (source->priv->library_location_entry),
+						       NULL, source);
+		g_free (uri);
+		g_free (path);
+	}
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+rb_library_source_preferences_sync (RBLibrarySource *source)
+{
+	GSList *list;
+	const char *str;
+	gint i;
+
+	rb_debug ("syncing pref dialog state");
+
+	/* library location */
+	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
+
+	/* don't trigger the change notification */
+	g_signal_handlers_block_by_func (G_OBJECT (source->priv->library_location_entry),
+					 G_CALLBACK (rb_library_source_library_location_cb),
+					 source);
+
+	if (g_slist_length (list) == 1) {
+		char *path;
+
+		gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
+
+		path = gnome_vfs_format_uri_for_display (list->data);
+		gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), path);
+		g_free (path);
+	} else if (g_slist_length (list) == 0) {
+		/* no library directories */
+		gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
+		gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), "");
+	} else {
+		/* multiple library directories */
+		gtk_widget_set_sensitive (source->priv->library_location_entry, FALSE);
+		gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), _("Multiple locations set"));
+	}
+
+	g_signal_handlers_unblock_by_func (G_OBJECT (source->priv->library_location_entry),
+					   G_CALLBACK (rb_library_source_library_location_cb),
+					   source);
+
+	g_slist_foreach (list, (GFunc) g_free, NULL);
+	g_slist_free (list);
+
+	/* watch checkbox */
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (source->priv->watch_library_check),
+				      eel_gconf_get_boolean (CONF_MONITOR_LIBRARY));
+
+	/* layout path */
+	str = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
+	for (i = 0; i < num_library_layout_paths; i++) {
+		if (strcmp (str, library_layout_paths[i].path) == 0)
+			gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_path_menu), i);
+	}
+
+	/* layout filename */
+	str = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
+	for (i = 0; i < num_library_layout_filenames; i++) {
+		if (strcmp (str, library_layout_filenames[i].path) == 0)
+			gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_filename_menu), i);
+	}
+
+	/* preferred format */
+	str = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
+	gm_audio_profile_choose_set_active (source->priv->preferred_format_menu, str);
+}
+
+static void
+rb_library_source_library_location_cb (GtkEntry *entry,
+				       GdkEventFocus *event,
+				       RBLibrarySource *source)
+{
+	GSList *list = NULL;
+	const char *path;
+	char *uri;
+
+	path = gtk_entry_get_text (entry);
+	uri = gnome_vfs_make_uri_from_input (path);
+
+	if (uri && uri[0])
+		list = g_slist_prepend (NULL, (gpointer)uri);
+
+	eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
+
+	g_free (uri);
+	if (list)
+		g_slist_free (list);
+	
+	/* don't do the first-run druid if the user sets the library location */
+	if (list)
+		eel_gconf_set_boolean (CONF_FIRST_TIME, TRUE);
+}
+
+static void
+rb_library_source_watch_toggled_cb (GtkToggleButton *button, RBLibrarySource *source)
+{
+	gboolean active;
+
+	active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (source->priv->watch_library_check));
+	eel_gconf_set_boolean (CONF_MONITOR_LIBRARY, active);
+}
+
+
+static void
+impl_delete (RBSource *asource)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	GList *sel, *tem;
+
+	sel = rb_entry_view_get_selected_entries (source->priv->songs);
+	for (tem = sel; tem != NULL; tem = tem->next) {
+		rhythmdb_entry_delete (source->priv->db, tem->data);
+		rhythmdb_commit (source->priv->db);
+	}
+	g_list_free (sel);
+}
+
+static void
+impl_move_to_trash (RBSource *asource)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	GList *sel, *tem;
+
+	sel = rb_entry_view_get_selected_entries (source->priv->songs);
+	for (tem = sel; tem != NULL; tem = tem->next) {
+		rhythmdb_entry_move_to_trash (source->priv->db,
+					       (RhythmDBEntry *) tem->data);
+		rhythmdb_commit (source->priv->db);
+	}
+	g_list_free (sel);
+}
+
+static void
+impl_song_properties (RBSource *asource)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+ 	GtkWidget *song_info = NULL; 
+
+	g_return_if_fail (source->priv->songs != NULL);
+        
+ 	song_info = rb_song_info_new (asource, NULL);
+
+        g_return_if_fail (song_info != NULL);
+
+ 	if (song_info) 
+ 		gtk_widget_show_all (song_info); 
+ 	else 
+		rb_debug ("failed to create dialog, or no selection!");
+}
+
+static void
+paned_size_allocate_cb (GtkWidget *widget,
+			GtkAllocation *allocation,
+		        RBLibrarySource *source)
+{
+	const char *key = rb_library_source_get_paned_key (source);;
+
+	/* save state */
+	rb_debug ("paned size allocate");
+	if (key)
+		eel_gconf_set_integer (key, gtk_paned_get_position (GTK_PANED (source->priv->paned)));
+}
+
+static void
+rb_library_source_state_prefs_sync (RBLibrarySource *source)
+{
+	const char *key;
+
+	rb_debug ("syncing state");
+	key = rb_library_source_get_paned_key (source);
+	if (key)
+		gtk_paned_set_position (GTK_PANED (source->priv->paned),
+					eel_gconf_get_integer (key));
+
+	key = rb_source_get_browser_key (RB_SOURCE (source));
+	if (key && eel_gconf_get_boolean (key))
+			gtk_widget_show (GTK_WIDGET (source->priv->browser));
+		else
+			gtk_widget_hide (GTK_WIDGET (source->priv->browser));
+}
+
+static void
+rb_library_source_state_pref_changed (GConfClient *client,
+				     guint cnxn_id,
+				     GConfEntry *entry,
+				     RBLibrarySource *source)
+{
+	rb_debug ("state prefs changed");
+	rb_library_source_state_prefs_sync (source);
+}
+
+static void
+rb_library_source_add_location_entry_changed_cb (GtkEntry *entry,
+						 GtkWidget *target)
+{
+	gtk_widget_set_sensitive (target, g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1) > 0);
+}
+
+void
+rb_library_source_add_location (RBLibrarySource *source, GtkWindow *win)
+{
+	GladeXML *xml = rb_glade_xml_new ("uri.glade",
+					  "open_uri_dialog_content",
+					  source);
+	GtkWidget *content, *uri_widget, *open_button;
+	GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Add Location"),
+							 win,
+							 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
+							 GTK_STOCK_CANCEL,
+							 GTK_RESPONSE_CANCEL,
+							 NULL);
+
+	g_return_if_fail (dialog != NULL);
+
+	open_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+					     GTK_STOCK_OPEN,
+					     GTK_RESPONSE_OK);
+	gtk_widget_set_sensitive (open_button, FALSE);
+
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+					 GTK_RESPONSE_OK);
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
+
+	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+	content = glade_xml_get_widget (xml, "open_uri_dialog_content");
+
+	g_return_if_fail (content != NULL);
+
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+			    content, FALSE, FALSE, 0);
+	gtk_container_set_border_width (GTK_CONTAINER (content), 5);
+
+	uri_widget = glade_xml_get_widget (xml, "uri");
+
+	g_return_if_fail (uri_widget != NULL);
+
+	g_signal_connect_object (G_OBJECT (uri_widget),
+				 "changed",
+				 G_CALLBACK (rb_library_source_add_location_entry_changed_cb),
+				 open_button, 0);
+
+	switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
+	case GTK_RESPONSE_OK:
+	{
+		char *uri = gtk_editable_get_chars (GTK_EDITABLE (uri_widget), 0, -1);
+		if (uri != NULL) {
+			GnomeVFSURI *vfsuri = gnome_vfs_uri_new (uri);
+			if (vfsuri != NULL) {
+				rhythmdb_add_uri (source->priv->db, uri);
+				gnome_vfs_uri_unref (vfsuri);
+			} else
+				rb_debug ("invalid uri: \"%s\"", uri);
+
+		}
+		break;
+	}
+	default:
+		rb_debug ("Location add cancelled");
+	}
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+
+}
+
+static gboolean
+impl_receive_drag (RBSource *asource, GtkSelectionData *data)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	GList *list, *i;
+	GList *entries = NULL;
+
+	rb_debug ("parsing uri list");
+	list = rb_uri_list_parse ((const char *) data->data);
+
+	for (i = list; i != NULL; i = g_list_next (i)) {
+		if (i->data != NULL) {
+			char *uri = i->data;
+			RhythmDBEntry *entry;
+
+			entry = rhythmdb_entry_lookup_by_location (source->priv->db, uri);
+
+			if (entry == NULL) {
+				/* add to the library */
+				rhythmdb_add_uri (source->priv->db, uri);
+			} else {
+				/* add to list of entries to copy */
+				entries = g_list_prepend (entries, entry);
+			}
+
+			g_free (uri);
+		}
+	}
+
+	if (entries) {
+		entries = g_list_reverse (entries);
+		if (rb_source_can_paste (asource))
+			rb_source_paste (asource, entries);
+		g_list_free (entries);
+	}
+
+	g_list_free (list);
+	return TRUE;
+}
+
+static gboolean
+impl_show_popup (RBSource *source)
+{
+	_rb_source_show_popup (RB_SOURCE (source), "/LibrarySourcePopup");
+	return TRUE;
+}
+
+const char *
+rb_library_source_get_paned_key (RBLibrarySource *source)
+{
+	RBLibrarySourceClass *klass = RB_LIBRARY_SOURCE_GET_CLASS (source);
+
+	if (klass->impl_get_paned_key)
+		return klass->impl_get_paned_key (source);
+	else
+		return NULL;
+}
+
+gboolean
+rb_library_source_has_first_added_column (RBLibrarySource *source)
+{
+	RBLibrarySourceClass *klass = RB_LIBRARY_SOURCE_GET_CLASS (source);
+
+	return klass->impl_has_first_added_column (source);
+}
+
+gboolean
+rb_library_source_has_drop_support (RBLibrarySource *source)
+{
+	RBLibrarySourceClass *klass = RB_LIBRARY_SOURCE_GET_CLASS (source);
+
+	return klass->impl_has_drop_support (source);
+}
+
+static GPtrArray *
+construct_query_from_selection (RBLibrarySource *source)
+{
+	GPtrArray *query;
+	RhythmDBEntryType entry_type;
+	GPtrArray *browser_query;
+
+	g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL);
+	query = rhythmdb_query_parse (source->priv->db,
+				      RHYTHMDB_QUERY_PROP_EQUALS,
+				      RHYTHMDB_PROP_TYPE,
+				      entry_type,
+				      RHYTHMDB_QUERY_END);
+
+	/* select where type="song"
+	 */
+
+	if (source->priv->search_text) {
+		GPtrArray *subquery = rhythmdb_query_parse (source->priv->db,
+							    RHYTHMDB_QUERY_PROP_LIKE,
+							    RHYTHMDB_PROP_SEARCH_MATCH,
+							    source->priv->search_text,
+							    RHYTHMDB_QUERY_END);
+		rhythmdb_query_append (source->priv->db,
+				       query,
+				       RHYTHMDB_QUERY_SUBQUERY,
+				       subquery,
+				       RHYTHMDB_QUERY_END);
+		/* select where type="song" and
+		 *  (genre like "foo" or artist like "foo" or album like "foo")
+		 */
+	}
+
+	
+	browser_query = rb_library_browser_construct_query (source->priv->browser);
+	rhythmdb_query_concatenate (query, browser_query);
+	rhythmdb_query_free (browser_query);
+
+	return query;
+}
+
+static void
+rb_library_source_do_query (RBLibrarySource *source)
+{
+	RhythmDBQueryModel *query_model;
+	gboolean is_all_query;
+
+	is_all_query = (!rb_library_browser_has_selection (source->priv->browser) &&
+			(source->priv->search_text == NULL));
+
+	if (is_all_query) {
+		g_object_ref (source->priv->cached_all_query);
+		query_model = source->priv->cached_all_query;
+	} else {
+		GPtrArray *query;
+	
+		query_model = rhythmdb_query_model_new_empty (source->priv->db);
+
+		query = construct_query_from_selection (source);
+		rhythmdb_do_full_query_async_parsed (source->priv->db, 
+						     RHYTHMDB_QUERY_RESULTS (query_model), 
+						     query);
+		rhythmdb_query_free (query);
+	}
+
+	rb_debug ("setting query model");
+	rb_entry_view_set_model (source->priv->songs, query_model);
+	g_object_set (RB_SOURCE (source), "query-model", query_model, NULL);
+
+	g_object_unref (G_OBJECT (query_model));
+}
+
+static void
+songs_view_drag_data_received_cb (GtkWidget *widget,
+				  GdkDragContext *dc,
+				  gint x, gint y,
+				  GtkSelectionData *selection_data,
+				  guint info, guint time,
+				  RBLibrarySource *source)
+{
+	rb_debug ("data dropped on the library source song view");
+	rb_source_receive_drag (RB_SOURCE (source), selection_data);
+}
+
+static void
+rb_library_source_browser_changed_cb (RBLibraryBrowser *entry, RBLibrarySource *source)
+{
+	rb_library_source_do_query (source);
+	rb_source_notify_filter_changed (RB_SOURCE (source));
+}
+
+static void
+rb_library_source_path_changed_cb (GtkComboBox *box, RBLibrarySource *source)
+{
+	const char *path;
+	gint index;
+
+	index = gtk_combo_box_get_active (box);
+	path = (index >= 0) ? library_layout_paths[index].path : "";
+	eel_gconf_set_string (CONF_LIBRARY_LAYOUT_PATH, path);
+}
+
+static void
+rb_library_source_filename_changed_cb (GtkComboBox *box, RBLibrarySource *source)
+{
+	const char *filename;
+	gint index;
+
+	index = gtk_combo_box_get_active (box);
+	filename = (index >= 0) ? library_layout_filenames[index].path : "";
+	eel_gconf_set_string (CONF_LIBRARY_LAYOUT_FILENAME, filename);
+}
+
+static void
+rb_library_source_format_changed_cb (GtkWidget *widget, RBLibrarySource *source)
+{
+	GMAudioProfile *profile;
+
+	profile = gm_audio_profile_choose_get_active (widget);
+	eel_gconf_set_string (CONF_LIBRARY_PREFERRED_FORMAT, gm_audio_profile_get_id (profile));
+}
+
+/**
+ * Perform magic on a path to make it safe.
+ *
+ * This will always replace '/' with ' ', and optionally make the file name
+ * shell-friendly. This involves removing [?*\ ] and replacing with '_'.  Also
+ * any leading periods are removed so that the files don't end up being hidden.
+ */
+static char*
+sanitize_path (const char* str)
+{
+  gchar *res = NULL;
+  gchar *s;
+
+  /* Skip leading periods, otherwise files disappear... */
+  while (*str == '.')
+    str++;
+  
+  s = g_strdup(str);
+  /* Replace path seperators with a hyphen */
+  g_strdelimit (s, "/", '-');
+  if (eel_gconf_get_boolean (CONF_LIBRARY_STRIP_CHARS)) {
+    /* Replace separators with a hyphen */
+    g_strdelimit (s, "\\:|", '-');
+    /* Replace all other weird characters to whitespace */
+    g_strdelimit (s, "*?&!\'\"$()`>{}", ' ');
+    /* Replace all whitespace with underscores */
+    /* TODO: I'd like this to compress whitespace aswell */
+    g_strdelimit (s, "\t ", '_');
+  }
+  res = g_filename_from_utf8(s, -1, NULL, NULL, NULL);
+  g_free(s);
+  return res ? res : g_strdup(str);
+}
+
+
+/**
+ * Parse a filename pattern and replace markers with values from a TrackDetails
+ * structure.
+ *
+ * Valid markers so far are:
+ * %at -- album title
+ * %aa -- album artist
+ * %aA -- album artist (lowercase)
+ * %as -- album artist sortname
+ * %aS -- album artist sortname (lowercase)
+ * %tn -- track number (i.e 8)
+ * %tN -- track number, zero padded (i.e 08)
+ * %tt -- track title
+ * %ta -- track artist
+ * %tA -- track artist (lowercase)
+ * %ts -- track artist sortname
+ * %tS -- track artist sortname (lowercase)
+ */
+static char*
+filepath_parse_pattern (const char* pattern, RhythmDBEntry *entry)
+{
+  /* p is the pattern iterator, i is a general purpose iterator */
+  const char *p, *i;
+  /* string is the output string, s is the iterator, t is a general string */
+  char *string, *s, *temp;
+  s = string = g_new0 (char, 256); /* TODO: bad hardcoding */
+
+  p = pattern;
+  while (*p) {
+    /* If not a % marker, copy and continue */
+    if (*p != '%') {
+      *s++ = *p++;
+      /* Explicit increment as we continue past the increment */
+      continue;
+    }
+    /* Is a % marker, go to next and see what to do */
+    switch (*++p) {
+    case '%':
+      /*
+       * Literal %
+       */
+      *s++ = '%';
+      break;
+    case 'a':
+      /*
+       * Album tag
+       */
+      switch (*++p) {
+      case 't':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'T':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_FOLDED));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'a':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'A':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      /*case 's':
+        i = temp = sanitize_path (track->album->artist_sortname);
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'S':
+	tmp = g_utf8_strdown (track->album->artist_sortname, -1);
+	i = temp = sanitize_path (tmp);
+	g_free(tmp);
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;*/
+      default:
+        *s++ = '%'; *s++ = 'a'; *s++ = *p;
+      }
+      break;
+    case 't':
+      /*
+       * Track tag
+       */
+      switch (*++p) {
+      case 't':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'T':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'a':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'A':
+        i = temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      /*case 's':
+        i = temp = sanitize_path (track->artist_sortname);
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'S':
+	tmp = g_utf8_strdown (track->artist_sortname, -1);
+        i = temp = sanitize_path (tmp);
+	g_free(tmp);
+	while (*i) *s++ = *i++;
+	g_free (temp);
+	break;*/
+      case 'n':
+        /* Track number */
+        i = temp = g_strdup_printf ("%u", (guint)rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      case 'N':
+        /* Track number, zero-padded */
+        i = temp = g_strdup_printf ("%02u", (guint)rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER));
+        while (*i) *s++ = *i++;
+        g_free (temp);
+        break;
+      default:
+        *s++ = '%'; *s++ = 't'; *s++ = *p;
+      }
+      break;
+    default:
+      *s++ = '%';
+      *s++ = *p;
+    }
+    ++p;
+  }
+  *s = '\0';
+  return string;
+}
+
+/**
+ * Build the absolute filename for the specified track.
+ *
+ * The base path is the extern variable 'base_path', the format to use
+ * is the extern variable 'file_pattern'. Free the result when you
+ * have finished with it.
+ *
+ * Stolen from Sound-Juicer
+ */
+static char*
+build_filename (RBLibrarySource *source, RhythmDBEntry *entry)
+{
+	GnomeVFSURI *uri, *new;
+	char *realfile, *realpath, *filename, *string;
+	char *extension;
+	GSList *list;
+
+
+	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
+	if (list == NULL) {
+		/* emit warning */
+		return NULL;
+	}
+
+	uri = gnome_vfs_uri_new ((const char *)list->data);
+	g_slist_free (list);
+
+	realpath = filepath_parse_pattern (eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH), entry);
+	new = gnome_vfs_uri_append_path (uri, realpath);
+	gnome_vfs_uri_unref (uri); uri = new;
+	g_free (realpath);
+
+	if (g_str_has_prefix (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE), "audio/x-raw")) {
+		GMAudioProfile *profile;
+		profile = gm_audio_profile_lookup (eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT));
+		extension = g_strdup (gm_audio_profile_get_extension (profile));
+	} else {
+		char *tmp;
+		
+		/* use the old extension. strip anything after a '?' for http/daap/etc */
+		extension = g_strdup (g_utf8_strrchr (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), -1, '.') + 1);
+
+		tmp = g_utf8_strchr (extension, -1, '?');
+		if (tmp)
+			*tmp = '\0';
+	}
+	
+	realfile = filepath_parse_pattern (eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME), entry);
+	if (extension) {
+		filename = g_strdup_printf ("%s.%s", realfile, extension);
+		g_free (realfile);
+	} else {
+		filename = realfile;
+	}
+
+	new = gnome_vfs_uri_append_file_name (uri, filename);
+	gnome_vfs_uri_unref (uri); uri = new;
+	g_free (extension);
+	g_free (filename);
+
+	string = gnome_vfs_uri_to_string (uri, 0);
+	gnome_vfs_uri_unref (uri);
+	return string;
+}
+
+static gboolean
+impl_can_paste (RBSource *asource)
+{
+	GSList *list;
+
+	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
+	if (list == NULL)
+		return FALSE;
+
+	g_slist_free (list);
+	return TRUE;
+}
+
+static void
+completed_cb (RhythmDBEntry *entry, const char *dest, RBLibrarySource *source)
+{
+	rhythmdb_add_uri (source->priv->db, dest);
+}
+
+static void
+impl_paste (RBSource *asource, GList *entries)
+{
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	RBRemovableMediaManager *rm_mgr;
+	GList *l;
+	RBShell *shell;
+
+	g_object_get (G_OBJECT (source), "shell", &shell, NULL);
+	g_object_get (G_OBJECT (shell), "removable-media-manager", &rm_mgr, NULL);
+	g_object_unref (G_OBJECT (shell));
+
+	for (l = entries; l != NULL; l = g_list_next (l)) {
+		RhythmDBEntry *entry = (RhythmDBEntry *)l->data;
+		RhythmDBEntryType entry_type;
+		char *dest;
+
+		entry_type = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TYPE);
+		if (entry_type == RHYTHMDB_ENTRY_TYPE_IRADIO_STATION ||
+		    entry_type == RHYTHMDB_ENTRY_TYPE_PODCAST_FEED ||
+		    entry_type == RHYTHMDB_ENTRY_TYPE_PODCAST_EPISODE)
+			continue;
+
+		dest = build_filename (source, entry);
+		if (dest == NULL) {
+			rb_debug ("could not create destination path for entry");
+			continue;
+		}
+
+		rb_removable_media_manager_queue_transfer (rm_mgr, entry,
+							  dest, NULL,
+							  (RBTranferCompleteCallback)completed_cb, source);
+	}
+
+	g_object_unref (G_OBJECT (rm_mgr));
+}
--- /dev/null	2006-03-02 01:39:51.000000000 +1100
+++ data/rhythmbox.schemas	2006-03-03 22:31:12.000000000 +1100
@@ -0,0 +1,642 @@
+<!-- arch-tag: Rhythmbox GConf schema file
+  -->
+
+<gconfschemafile>
+   <schemalist>
+      <schema>
+        <key>/schemas/apps/rhythmbox/first_time_flag</key>
+        <applyto>/apps/rhythmbox/first_time_flag</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+	<short>True if the initial druid has already been run.</short>
+	<long>True if the initial druid has already been run.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/grace_period</key>
+        <applyto>/apps/rhythmbox/grace_period</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>45</default>
+        <locale name="C">
+	<short>Number of days before removing a stale entry from the database</short>
+	<long>When Rhythmbox's database contains a song stored on a mount point that is no longer available, Rhythmbox won't remove it from its XML file immedialty, but will keep it for a number of days defined by this key. Setting it to a negative number makes Rhythmbox keep the songs forever.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/library_locations</key>
+        <applyto>/apps/rhythmbox/library_locations</applyto>
+        <owner>rhythmbox</owner>
+        <type>list</type>
+        <list_type>string</list_type>
+        <default>[]</default>
+        <locale name="C">
+	<short>Directories that Rhythmbox should monitor</short>
+	<long>A list of directory URIs that Rhythmbox should monitor for changes and new tracks.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/library_layout_path</key>
+        <applyto>/apps/rhythmbox/library_layout_path</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>%aa/%at</default>
+        <locale name="C">
+          <short>Directory heirarchy of library</short>
+          <long>The path used to store track in, under the chosen library. Various substitutions are done</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/library_layout_filename</key>
+        <applyto>/apps/rhythmbox/library_layout_filename</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>%tb - %tt</default>
+        <locale name="C">
+          <short>File name of tracks</short>
+          <long>The path used to store track in, under the chosen library. Various substitutions are done</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/library_preferred_format</key>
+        <applyto>/apps/rhythmbox/library_preferred_format</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>cdlossy</default>
+        <locale name="C">
+          <short>id of gnome-media audio profile</short>
+          <long>The ID of the preferred gnome audio profile, used for ripping CDs</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/monitor_library</key>
+        <applyto>/apps/rhythmbox/monitor_library</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+          <short>Whether the library location are monitored</short>
+          <long>If true, the locations listed in /apps/rhythmbox/library_locations are monitored for new files</long>
+        </locale>
+      </schema>
+
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/window_visible</key>
+        <applyto>/apps/rhythmbox/state/window_visible</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>1</default>
+        <locale name="C">
+	<short>Whether the window is visible</short>
+	<long>When set to false, causes Rhythmbox to start only as a tray icon with the window hidden.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/paned_position</key>
+        <applyto>/apps/rhythmbox/state/paned_position</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>88</default>
+        <locale name="C">
+	<short>Position of main window pane</short>
+	<long>Position of main window pane.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/window_width</key>
+        <applyto>/apps/rhythmbox/state/window_width</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>600</default>
+        <locale name="C">
+	<short>Main window width</short>
+	<long>Main window width.</long>
+        </locale>
+      </schema>
+
+
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/window_position_x</key>
+        <applyto>/apps/rhythmbox/state/window_position_x</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>0</default>
+        <locale name="C">
+	<short>Main window X position</short>
+	<long>Main window X position.</long>
+        </locale>
+      </schema>
+ 
+
+<schema>
+        <key>/schemas/apps/rhythmbox/state/window_position_y</key>
+        <applyto>/apps/rhythmbox/state/window_position_y</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>0</default>
+        <locale name="C">
+	<short>Main window Y position</short>
+	<long>Main window Y position.</long>
+        </locale>
+      </schema>
+ 
+
+
+
+<schema>
+        <key>/schemas/apps/rhythmbox/state/window_height</key>
+        <applyto>/apps/rhythmbox/state/window_height</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>600</default>
+        <locale name="C">
+	<short>Main window height</short>
+	<long>Main window height.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/small_width</key>
+        <applyto>/apps/rhythmbox/state/small_width</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>600</default>
+        <locale name="C">
+	<short>Small window width</short>
+	<long>Main window width when the player is in Small Display mode.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/window_maximized</key>
+        <applyto>/apps/rhythmbox/state/window_maximized</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+	<short>Main window maximization state</short>
+	<long>If true, the main window is maximized.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/sourcelist_height</key>
+	<applyto>/apps/rhythmbox/state/sourcelist_height</applyto>
+	<owner>rhythmbox</owner>
+	<type>int</type>
+	<default>300</default>
+	<locale name="C">
+	  <short>Source list height</short>
+	  <long>Height of the source list when the play queue is shown as a sidebar.</long>
+	</locale>
+      </schema>
+
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/sourcelist_hidden</key>
+	<applyto>/apps/rhythmbox/ui/sourcelist_hidden</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Source list visibility</short>
+	<long>If true, the main source list is hidden.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/small_display</key>
+	<applyto>/apps/rhythmbox/ui/small_display</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Small display mode</short>
+	<long>If true, the main window is displayed without the source list, browser or playlist.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/statusbar_hidden</key>
+	<applyto>/apps/rhythmbox/ui/statusbar_hidden</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Statusbar visibility</short>
+	<long>If true, the statusbar is hidden.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/queue_as_sidebar</key>
+	<applyto>/apps/rhythmbox/ui/queue_as_sidebar</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Queue display type</short>
+	<long>If true, the play queue is displayed as a sidebar. If false, the play queue is displayed as a source in the source list.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/toolbar_hidden</key>
+	<applyto>/apps/rhythmbox/ui/toolbar_hidden</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Toolbar visibility</short>
+	<long>If true, the toolbar is hidden.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/song_position_slider_hidden</key>
+	<applyto>/apps/rhythmbox/ui/song_position_slider_hidden</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Song position slider visibility</short>
+	<long>If true, the song position slider is hidden.</long>
+	</locale>
+      </schema>
+
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/play_order</key>
+        <applyto>/apps/rhythmbox/state/play_order</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>linear</default>
+        <locale name="C">
+	<short>Order to play songs in</short>
+	<long>Value identifies the order songs are played in. Legal values are:
+	"linear", "shuffle", "random-equal-weights", "random-by-age",
+	"random-by-rating".</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/add_dir</key>
+        <applyto>/apps/rhythmbox/state/add_dir</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default></default>
+        <locale name="C">
+	<short>"Add to library" filesel state</short>
+	<long>"Add to library" filesel state.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/volume</key>
+        <applyto>/apps/rhythmbox/state/volume</applyto>
+        <owner>rhythmbox</owner>
+        <type>float</type>
+        <default>1.0</default>
+        <locale name="C">
+	<short>Volume level</short>
+	<long>Volume level.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/library/sorting</key>
+        <applyto>/apps/rhythmbox/state/library/sorting</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>Artist,ascending</default>
+        <locale name="C">
+	<short>The sorting order</short>
+	<long>A comma-separated list.  The first is the title of the
+	column to sort on, the second is the sort type.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/library/show_browser</key>
+        <applyto>/apps/rhythmbox/state/library/show_browser</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>1</default>
+        <locale name="C">
+	<short>Show browser in library</short>
+	<long>Show the artist and album browser in the library.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/library/paned_position</key>
+        <applyto>/apps/rhythmbox/state/library/paned_position</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>180</default>
+        <locale name="C">
+	<short>Position of library browser pane</short>
+	<long>Position of library browser pane.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/daap/sorting</key>
+        <applyto>/apps/rhythmbox/state/daap/sorting</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>Artist,ascending</default>
+        <locale name="C">
+	<short>The sorting order</short>
+	<long>A comma-separated list.  The first is the title of the
+	column to sort on, the second is the sort type.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/daap/show_browser</key>
+        <applyto>/apps/rhythmbox/state/daap/show_browser</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>1</default>
+        <locale name="C">
+	<short>Show browser in remote music shares</short>
+	<long>Show the artist and album browser in remote music shares.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/daap/paned_position</key>
+        <applyto>/apps/rhythmbox/state/daap/paned_position</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>180</default>
+        <locale name="C">
+	<short>Position of remote music shares browser pane</short>
+	<long>Position of remote music shares browser pane.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/columns_setup</key>
+        <applyto>/apps/rhythmbox/ui/columns_setup</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>RB_TREE_MODEL_NODE_COL_TRACK_NUMBER_STR,RB_TREE_MODEL_NODE_COL_ARTIST,RB_TREE_MODEL_NODE_COL_ALBUM,RB_TREE_MODEL_NODE_COL_GENRE,RB_TREE_MODEL_NODE_COL_DURATION</default>
+        <locale name="C">
+	<short>(obsolete) List of active columns.</short>
+	<long>The list of columns that will be shown for Rhythmbox versions &lt; 0.6.0.  If a source
+              doesn't support a particular column, it won't be displayed. </long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/rhythmdb_columns_setup</key>
+        <applyto>/apps/rhythmbox/ui/rhythmdb_columns_setup</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>RHYTHMDB_PROP_TRACK_NUMBER,RHYTHMDB_PROP_ARTIST,RHYTHMDB_PROP_ALBUM,RHYTHMDB_PROP_GENRE,RHYTHMDB_PROP_DURATION,RHYTHMDB_PROP_POST_TIME</default>
+        <locale name="C">
+	<short>List of active columns.</short>
+	<long>The list of columns that will be shown.  If a source
+              doesn't support a particular column, it won't be displayed. </long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/time_display</key>
+        <applyto>/apps/rhythmbox/ui/time_display</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>1</default>
+        <locale name="C">
+        <short>Whether to show elapsed or remaining time</short>
+        <long>If true, the elapsed time will be shown in song duration
+              displays. Otherwise the remaining time will be shown.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/iradio/show_browser</key>
+        <applyto>/apps/rhythmbox/state/iradio/show_browser</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+	  <short>Show browser in radio display</short>
+	  <long>Show the genre browser in the Internet Radio display.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/iradio/sorting</key>
+        <applyto>/apps/rhythmbox/state/iradio/sorting</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>Title,ascending</default>
+        <locale name="C">
+	<short>The sorting order</short>
+	<long>A comma-separated list.  The first is the title of the
+	column to sort on, the second is the sort type.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/podcast/show_browser</key>
+        <applyto>/apps/rhythmbox/state/podcast/show_browser</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+	  <short>Show browser in podcast display</short>
+	  <long>Show the album browser in the Podcast display.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/podcast/sorting</key>
+        <applyto>/apps/rhythmbox/state/podcast/sorting</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>Title,ascending</default>
+        <locale name="C">
+	<short>The sorting order</short>
+	<long>A comma-separated list.  The first is the title of the
+	column to sort on, the second is the sort type.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/podcast/download_interval</key>
+        <applyto>/apps/rhythmbox/state/podcast/download_interval</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>0</default>
+        <locale name="C">
+	<short>The index of config update interval</short>
+	<long>
+	0 Every hour 
+	1 Every day
+	2 Every week
+	3 Manually
+	</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/podcast/download_next_time</key>
+        <applyto>/apps/rhythmbox/state/podcast/download_next_time</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>0</default>
+        <locale name="C">
+	<short>The exactly time of update</short>
+	<long>The time in secs of update</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/podcast/download_prefix</key>
+        <applyto>/apps/rhythmbox/state/podcast/download_prefix</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default></default>
+        <locale name="C">
+	<short>The dir to save your podcast files</short>
+	<long>The dir to save your podcast files</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/library/browser_views</key>
+        <applyto>/apps/rhythmbox/ui/library/browser_views</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>0</default>
+        <locale name="C">
+	<short>Views to show in the library browser.</short>
+	<long>
+	0 Artists, Albums
+	1 Genres, Artists
+	2 Genres, Artists, Albums
+        </long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/load_failure_dialog/window_width</key>
+        <applyto>/apps/rhythmbox/state/load_failure_dialog/window_width</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>300</default>
+        <locale name="C">
+	<short>Window width of the load failure dialog</short>
+	<long>Window width of the load failure dialog</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/load_failure_dialog/window_height</key>
+        <applyto>/apps/rhythmbox/state/load_failure_dialog/window_height</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>300</default>
+        <locale name="C">
+	<short>Window height of the load failure dialog</short>
+	<long>Window height of the load failure dialog</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/burn_device</key>
+        <applyto>/apps/rhythmbox/state/burn_device</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default></default>
+        <locale name="C">
+	<short>Audio disc burner device</short>
+	<long>Audio disc burner device.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/state/burn_speed</key>
+	<applyto>/apps/rhythmbox/state/burn_speed</applyto>
+	<owner>rhythmbox</owner>
+	<type>int</type>
+	<default>4</default>
+	<locale name="C">
+	  <short>Default audio disc writing speed</short>
+	  <long>Default speed at which the audio disc will be written.</long>
+	</locale>
+      </schema>
+      <schema>
+	<key>/schemas/apps/rhythmbox/sharing/enable_browsing</key>
+	<applyto>/apps/rhythmbox/sharing/enable_browsing</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>1</default>
+	<locale name="C">
+	<short>Enables browsing your network for computers with shared music</short>
+	<long>When enabled, Rhythmbox will search for computers running Rhythmbox or Apple iTunes with shared music on your local network</long>
+	</locale>
+      </schema>
+      <schema>
+	<key>/schemas/apps/rhythmbox/sharing/enable_sharing</key>
+	<applyto>/apps/rhythmbox/sharing/enable_sharing</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Enables sharing your music with computers on your network</short>
+	<long>When enabled, Rhythmbox will share your music with other computers running Rhythmbox or Apple iTunes</long>
+	</locale>
+      </schema>
+      <schema>
+	<key>/schemas/apps/rhythmbox/sharing/require_password</key>
+	<applyto>/apps/rhythmbox/sharing/require_password</applyto>
+	<owner>rhythmbox</owner>
+	<type>bool</type>
+	<default>0</default>
+	<locale name="C">
+	<short>Require a password to access your music over the network</short>
+	<long>When enabled, Rhythmbox will require a password for others to access your music over the network.</long>
+	</locale>
+      </schema>
+      <schema>
+	<key>/schemas/apps/rhythmbox/sharing/share_name</key>
+	<applyto>/apps/rhythmbox/sharing/share_name</applyto>
+	<owner>rhythmbox</owner>
+	<type>string</type>
+	<default></default>
+	<locale name="C">
+	<short>Name for your shared music</short>
+	<long>Name other computers will see your music shared as</long>
+	</locale>
+      </schema>
+      <schema>
+	<key>/schemas/apps/rhythmbox/sharing/share_password</key>
+	<applyto>/apps/rhythmbox/sharing/share_password</applyto>
+	<owner>rhythmbox</owner>
+	<type>string</type>
+	<default></default>
+	<locale name="C">
+	<short>Password for your shared music</short>
+	<long>Password that is required for accessing your shared music.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/audioscrobbler/username</key>
+        <applyto>/apps/rhythmbox/audioscrobbler/username</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default></default>
+        <locale name="C">
+	<short>Username for Audioscrobbler.com</short>
+	<long>Username for Audioscrobbler.com</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/audioscrobbler/password</key>
+        <applyto>/apps/rhythmbox/audioscrobbler/password</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default></default>
+        <locale name="C">
+	<short>Password for Audioscrobbler.com</short>
+	<long>Password for Audioscrobbler.com</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/audioscrobbler/enabled</key>
+        <applyto>/apps/rhythmbox/audioscrobbler/enabled</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+	<short>Whether to enable Audioscrobbler support.</short>
+	<long>Whether to enable Audioscrobbler support. Audioscrobbler is a computer system that builds up a detailed profile of your musical taste. See Audioscrobbler.com for more information.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/ui/show_notifications</key>
+        <applyto>/apps/rhythmbox/ui/show_notifications</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>1</default>
+        <locale name="C">
+	<short>Whether to show notifications from the tray icon</short>
+	<long>When enabled, Rhythmbox will display notification bubbles when the playing track changes, a podcast is downloaded, a CD finished burning, etc.</long>
+        </locale>
+      </schema>
+    </schemalist>
+</gconfschemafile>
