[rhythmbox] port all core code to use GSettings



commit cf02733f92acdbf723610a10ae34c52925b0a4f1
Author: Jonathan Matthew <jonathan d14n org>
Date:   Thu Mar 10 20:39:35 2011 +1000

    port all core code to use GSettings
    
    A couple of general notes, for future reference:
    - widgets don't know anything about GSettings, instead they expose
      properties that can be bound to settings keys
    - when a settings key is used to store a value controlled by a slider
      or pane widget, the key is only updated once the value has gone
      unchanged for 500ms (using rb_settings_delayed_sync); writing on
      each value notification is extremely slow.

 .gitignore                           |    4 +-
 backends/gstreamer/rb-encoder-gst.c  |    5 +-
 bindings/gi/Makefile.am              |    1 -
 configure.ac                         |    2 +-
 data/Makefile.am                     |   26 +-
 data/ui/general-prefs.ui             |   14 -
 data/ui/playback-prefs.ui            |   59 +----
 data/ui/podcast-prefs.ui             |   60 ++--
 doc/reference/Makefile.am            |    1 -
 doc/reference/rhythmbox-sections.txt |   20 --
 doc/reference/rhythmbox.types        |    2 -
 lib/Makefile.am                      |    3 -
 lib/eel-gconf-extensions.c           |  507 ----------------------------
 lib/eel-gconf-extensions.h           |   79 -----
 lib/rb-debug.c                       |    1 +
 lib/rb-preferences.h                 |   83 -----
 lib/rb-util.c                        |   54 +++
 lib/rb-util.h                        |    5 +
 macros/gsettings.m4                  |   80 +++++
 po/POTFILES.in                       |    1 -
 podcast/Makefile.am                  |    1 +
 podcast/rb-podcast-main-source.c     |   94 +++---
 podcast/rb-podcast-manager.c         |  274 ++++++++--------
 podcast/rb-podcast-settings.h        |   46 +++
 podcast/rb-podcast-source.c          |  116 +++----
 rhythmbox.h                          |    1 -
 rhythmdb/rhythmdb-monitor.c          |   26 +-
 rhythmdb/rhythmdb-private.h          |    6 +-
 rhythmdb/rhythmdb-song-entry-types.c |   12 +-
 rhythmdb/rhythmdb.c                  |   77 ++---
 shell/main.c                         |    4 +-
 shell/rb-play-order-linear-loop.c    |    1 -
 shell/rb-play-order-linear.c         |    2 -
 shell/rb-play-order-queue.c          |    2 -
 shell/rb-play-order-shuffle.c        |    1 -
 shell/rb-play-order.c                |    1 -
 shell/rb-play-order.h                |    2 +-
 shell/rb-playlist-manager.c          |    1 -
 shell/rb-plugin.c                    |   14 +-
 shell/rb-plugins-engine.c            |  110 +++----
 shell/rb-shell-player.c              |  292 ++++++-----------
 shell/rb-shell-player.h              |    2 -
 shell/rb-shell-preferences.c         |  531 ++++++++++++------------------
 shell/rb-shell-preferences.h         |    1 -
 shell/rb-shell.c                     |  451 ++++++++++----------------
 shell/rb-shell.xml                   |   15 +
 shell/rb-source-header.c             |  129 ++++----
 sources/rb-auto-playlist-source.c    |   45 ++--
 sources/rb-browser-source.c          |  186 ++---------
 sources/rb-browser-source.h          |    2 -
 sources/rb-display-page-tree.c       |   69 +++--
 sources/rb-import-errors-source.c    |    2 +-
 sources/rb-library-source.c          |  600 ++++++++++++++--------------------
 sources/rb-missing-files-source.c    |   12 +-
 sources/rb-play-queue-source.c       |    2 +-
 sources/rb-playlist-source.c         |   89 +-----
 sources/rb-removable-media-source.c  |    2 -
 sources/rb-source.c                  |  205 +++++++++---
 sources/rb-source.h                  |    8 +-
 sources/rb-static-playlist-source.c  |   54 ++--
 sources/rb-streaming-source.c        |    1 -
 widgets/rb-entry-view.c              |  205 +++---------
 widgets/rb-entry-view.h              |    2 -
 widgets/rb-header.c                  |   88 +++---
 widgets/rb-library-browser.c         |   63 ++--
 widgets/rb-property-view.c           |    1 -
 widgets/rb-query-creator.c           |    1 -
 widgets/rb-song-info.c               |    2 -
 68 files changed, 1808 insertions(+), 3050 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index a69d7be..40be3ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,8 +30,6 @@ gnome-doc-utils.make
 rhythmbox.pc
 
 #
-bindings/python/rb.c
-bindings/python/rhythmdb.c
 bindings/gi/MPID-0.13.gir
 bindings/gi/MPID-0.13.typelib
 bindings/gi/RB-0.13.gir
@@ -43,6 +41,8 @@ org.gnome.Rhythmbox.service
 rhythmbox.desktop.in
 rhythmbox-device.desktop.in
 playlists.xml
+gschemas.compiled
+org.gnome.rhythmbox.gschema.valid
 
 #
 help/*.omf
diff --git a/backends/gstreamer/rb-encoder-gst.c b/backends/gstreamer/rb-encoder-gst.c
index 67e6b1e..e3641c3 100644
--- a/backends/gstreamer/rb-encoder-gst.c
+++ b/backends/gstreamer/rb-encoder-gst.c
@@ -41,8 +41,6 @@
 #include <gst/pbutils/missing-plugins.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"
@@ -1194,7 +1192,8 @@ rb_encoder_gst_get_media_type (RBEncoder *encoder,
 	 */
 	if (dest_media_types == NULL) {
 		if (g_str_has_prefix (src_media_type, "audio/x-raw")) {
-			const char *profile_name = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
+			/* hopefully encodebin stuff will land before i need to replace this with something gsettings wise */
+			const char *profile_name = "cdlossy"; /* eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT); */
 			const char *mt;
 			profile = gm_audio_profile_lookup (profile_name);
 
diff --git a/bindings/gi/Makefile.am b/bindings/gi/Makefile.am
index e3b2d48..1a81437 100644
--- a/bindings/gi/Makefile.am
+++ b/bindings/gi/Makefile.am
@@ -23,7 +23,6 @@ rb_introspection_sources = \
 		lib/rb-debug.c \
 		lib/rb-file-helpers.h \
 		lib/rb-file-helpers.c \
-		lib/rb-preferences.h \
 		lib/rb-stock-icons.h \
 		lib/rb-stock-icons.c \
 		lib/rb-string-value-map.h \
diff --git a/configure.ac b/configure.ac
index 17234af..75f2e0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,7 @@ LIBNOTIFY_REQS=0.7.0
 BRASERO_MIN_REQS=2.31.5
 WEBKIT_MIN_REQS=1.3.9
 
+GLIB_GSETTINGS
 
 
 
@@ -438,7 +439,6 @@ AC_SUBST(LDFLAGS)
 
 AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
 AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource)
-AC_PATH_PROG(GCONFTOOL, gconftool-2)
 
 AC_SUBST(RHYTHMBOX_CFLAGS)
 AC_SUBST(RHYTHMBOX_LIBS)
diff --git a/data/Makefile.am b/data/Makefile.am
index be88068..333fdae 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -7,15 +7,24 @@ Multimediadir = $(datadir)/applications
 Multimedia_in_files = rhythmbox.desktop.in rhythmbox-device.desktop.in
 Multimedia_DATA = $(Multimedia_in_files:.desktop.in=.desktop)
 
-schemadir = @GCONF_SCHEMA_FILE_DIR@
-schema_DATA = rhythmbox.schemas
-
 playlists_in_files = playlists.xml.in
 playlists_DATA = playlists.xml
 playlistsdir = $(datadir)/rhythmbox
 
 man_MANS = rhythmbox.1 rhythmbox-client.1
 
+# GSettings schemas
+# (summaries and descriptions are not translated, so no .xml.in)
+gsettings_SCHEMAS = org.gnome.rhythmbox.gschema.xml
+
+ GSETTINGS_RULES@
+
+# compile schemas for running from the source tree
+gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
+	$(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --targetdir=. .
+
+all-local: gschemas.compiled
+
 # Dbus service file
 servicedir = $(datadir)/dbus-1/services
 service_in_files = org.gnome.Rhythmbox.service.in
@@ -25,11 +34,6 @@ service_DATA = $(service_in_files:.service.in=.service)
 $(service_DATA): $(service_in_files) Makefile
 	@sed -e "s|\ bindir\@|$(bindir)|" $< > $@
 
-if GCONF_SCHEMAS_INSTALL
-install-data-local: $(schema_DATA)
-	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(schema_DATA);
-endif
-
 # Rule to update the icon cache after installing the icon
 gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
 
@@ -49,8 +53,7 @@ EXTRA_DIST = $(service_in_files)    \
 	     $(man_MANS)            \
 	     $(playlists_in_files)  \
 	     rhythmbox.desktop.in.in \
-	     rhythmbox-device.desktop.in.in \
-	     org.gnome.rhythmbox.gschema.xml
+	     rhythmbox-device.desktop.in.in
 
 CLEANFILES = 					\
 	rhythmbox.desktop			\
@@ -58,4 +61,5 @@ CLEANFILES = 					\
 	org.gnome.Rhythmbox.service		\
 	playlists.xml				\
 	rhythmbox.desktop.in			\
-	rhythmbox-device.desktop.in
+	rhythmbox-device.desktop.in		\
+	gschemas.compiled
diff --git a/data/ui/general-prefs.ui b/data/ui/general-prefs.ui
index aa3575d..c0a9d4f 100644
--- a/data/ui/general-prefs.ui
+++ b/data/ui/general-prefs.ui
@@ -224,7 +224,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="y_options"></property>
@@ -238,7 +237,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="top_attach">1</property>
@@ -254,7 +252,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="top_attach">2</property>
@@ -270,7 +267,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="top_attach">4</property>
@@ -287,7 +283,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="top_attach">3</property>
@@ -304,7 +299,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
@@ -323,7 +317,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">2</property>
@@ -340,7 +333,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">2</property>
@@ -359,7 +351,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">2</property>
@@ -378,7 +369,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">2</property>
@@ -397,7 +387,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
@@ -416,7 +405,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
@@ -435,7 +423,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
@@ -454,7 +441,6 @@
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="rb_shell_preferences_column_check_changed_cb"/>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
diff --git a/data/ui/playback-prefs.ui b/data/ui/playback-prefs.ui
index fa8a536..3397ec9 100644
--- a/data/ui/playback-prefs.ui
+++ b/data/ui/playback-prefs.ui
@@ -52,7 +52,7 @@
             </child>
             <child>
               <object class="GtkCheckButton" id="use_xfade_backend">
-                <property name="label" translatable="yes">_Use crossfading backend (requires restart)</property>
+                <property name="label" translatable="yes">_Crossfade between tracks</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
@@ -131,61 +131,6 @@
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="vbox6">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="buffer_size_label">
-            <property name="visible">True</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Network Buffer Size (kB)</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkHBox" id="hbox3">
-            <property name="visible">True</property>
-            <child>
-              <object class="GtkLabel" id="label4">
-                <property name="visible">True</property>
-                <property name="label">    </property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHScale" id="network_buffer_size">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="adjustment">adjustment2</property>
-                <property name="digits">0</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-    <child>
       <object class="GtkVBox" id="plugin_box">
         <property name="visible">True</property>
         <property name="orientation">vertical</property>
@@ -194,7 +139,7 @@
         </child>
       </object>
       <packing>
-        <property name="position">3</property>
+        <property name="position">2</property>
       </packing>
     </child>
   </object>
diff --git a/data/ui/podcast-prefs.ui b/data/ui/podcast-prefs.ui
index 647ee18..21f269a 100644
--- a/data/ui/podcast-prefs.ui
+++ b/data/ui/podcast-prefs.ui
@@ -1,27 +1,7 @@
 <?xml version="1.0"?>
 <interface>
-  <!-- interface-requires gtk+ 2.12 -->
+  <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy toplevel-contextual -->
-  <object class="GtkListStore" id="model1">
-    <columns>
-      <!-- column-name gchararray -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Every hour</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Every day</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Every week</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Manually</col>
-      </row>
-    </data>
-  </object>
   <object class="GtkVBox" id="podcast_vbox">
     <property name="visible">True</property>
     <property name="border_width">12</property>
@@ -36,8 +16,10 @@
           <object class="GtkLabel" id="download_manager_label">
             <property name="visible">True</property>
             <property name="xalign">0</property>
-            <property name="label" translatable="yes">&lt;b&gt;Download Manager&lt;/b&gt;</property>
-            <property name="use_markup">True</property>
+            <property name="label" translatable="yes">Podcast Downloads</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -99,7 +81,7 @@
                         <property name="xalign">0</property>
                         <property name="label" translatable="yes">Check for _new episodes:</property>
                         <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">cb_update_interval</property>
+                        <property name="mnemonic_widget">update_interval</property>
                       </object>
                       <packing>
                         <property name="top_attach">1</property>
@@ -109,9 +91,9 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkComboBox" id="cb_update_interval">
+                      <object class="GtkComboBox" id="update_interval">
                         <property name="visible">True</property>
-                        <property name="model">model1</property>
+                        <property name="model">interval-values</property>
                         <child>
                           <object class="GtkCellRendererText" id="renderer1"/>
                           <attributes>
@@ -173,4 +155,30 @@
       </packing>
     </child>
   </object>
+  <object class="GtkListStore" id="interval-values">
+    <columns>
+      <!-- column-name display -->
+      <column type="gchararray"/>
+      <!-- column-name setting -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Every hour</col>
+        <col id="1" translatable="no">hourly</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Every day</col>
+        <col id="1" translatable="no">daily</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Every week</col>
+        <col id="1" translatable="no">weekly</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Manually</col>
+        <col id="1" translatable="no">manual</col>
+      </row>
+    </data>
+  </object>
 </interface>
diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am
index 33c9175..21cca16 100644
--- a/doc/reference/Makefile.am
+++ b/doc/reference/Makefile.am
@@ -33,7 +33,6 @@ CFILE_GLOB=$(top_srcdir)/lib/*.c
 # - plugins (no API there)
 IGNORE_HFILES= \
 	config.h \
-	eel-gconf-extensions.h \
 	eggdesktopfile.h \
 	eggsmclient-private.h \
 	eggsmclient.h \
diff --git a/doc/reference/rhythmbox-sections.txt b/doc/reference/rhythmbox-sections.txt
index 0bc8b6f..9f1c371 100644
--- a/doc/reference/rhythmbox-sections.txt
+++ b/doc/reference/rhythmbox-sections.txt
@@ -477,8 +477,6 @@ rb_source_update_play_statistics
 rb_source_set_pixbuf
 rb_source_get_status
 rb_source_can_browse
-rb_source_get_browser_key
-rb_source_browser_toggled
 rb_source_get_entry_view
 rb_source_get_property_views
 rb_source_can_rename
@@ -992,23 +990,6 @@ rb_stock_icons_shutdown
 </SECTION>
 
 <SECTION>
-<FILE>rb-preferences</FILE>
-CONF_PREFIX
-CONF_FIRST_TIME
-CONF_GRACE_PERIOD
-CONF_UI_DIR
-CONF_UI_STATUSBAR_HIDDEN
-CONF_UI_SMALL_DISPLAY
-CONF_UI_OBSOLETE_COLUMNS_SETUP
-CONF_UI_COLUMNS_SETUP
-CONF_UI_TIME_DISPLAY
-CONF_UI_BROWSER_VIEWS
-CONF_STATE_PLAY_ORDER
-CONF_STATE_VOLUME
-CONF_STATE_BURN_DEVICE
-</SECTION>
-
-<SECTION>
 <FILE>rb-file-helpers</FILE>
 rb_file
 rb_user_data_dir
@@ -1461,7 +1442,6 @@ RB_MISSING_FILES_SOURCE_GET_CLASS
 <TITLE>RBBrowserSource</TITLE>
 RBBrowserSource
 RBBrowserSourceClass
-rb_browser_source_get_paned_key
 rb_browser_source_has_drop_support
 <SUBSECTION Standard>
 RBBrowserSourcePrivate
diff --git a/doc/reference/rhythmbox.types b/doc/reference/rhythmbox.types
index f37955a..427891c 100644
--- a/doc/reference/rhythmbox.types
+++ b/doc/reference/rhythmbox.types
@@ -2,7 +2,6 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include "eel-gconf-extensions.h"
 #include "rb-auto-playlist-source.h"
 #include "rb-cell-renderer-pixbuf.h"
 #include "rb-cell-renderer-rating.h"
@@ -36,7 +35,6 @@
 #include "rb-play-order-random.h"
 #include "rb-play-queue-source.h"
 #include "rb-plugin.h"
-#include "rb-preferences.h"
 #include "rb-property-view.h"
 #include "rb-query-creator.h"
 #include "rb-rating.h"
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a01f739..76b9cc5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -14,7 +14,6 @@ rbinclude_HEADERS =					\
 	rb-builder-helpers.h				\
 	rb-debug.h					\
 	rb-file-helpers.h				\
-	rb-preferences.h				\
 	rb-stock-icons.h				\
 	rb-string-value-map.h				\
 	rb-util.h
@@ -23,8 +22,6 @@ librb_la_SOURCES =					\
 	$(MKDTEMP_FILES)				\
 	$(rbinclude_HEADERS)				\
 	rb-debug.c					\
-	eel-gconf-extensions.c				\
-	eel-gconf-extensions.h				\
 	eggdesktopfile.c				\
 	eggdesktopfile.h				\
 	eggsmclient.c					\
diff --git a/lib/rb-debug.c b/lib/rb-debug.c
index 44d54ae..7dbce09 100644
--- a/lib/rb-debug.c
+++ b/lib/rb-debug.c
@@ -227,6 +227,7 @@ rb_debug_init_match (const char *match)
 		"libgconf-scm",
 		"libgnomevfs",
 		"librsvg",
+		"libnotify",
 		"GLib-GIO",
 	};
 
diff --git a/lib/rb-util.c b/lib/rb-util.c
index fc170df..e5168e0 100644
--- a/lib/rb-util.c
+++ b/lib/rb-util.c
@@ -1250,3 +1250,57 @@ rb_scale_pixbuf_to_size (GdkPixbuf *pixbuf, GtkIconSize size)
 
 	return gdk_pixbuf_scale_simple (pixbuf, d_width, d_height, GDK_INTERP_BILINEAR);
 }
+
+#define DELAYED_SYNC_ITEM "rb-delayed-sync"
+#define DELAYED_SYNC_FUNC_ITEM "rb-delayed-sync-func"
+#define DELAYED_SYNC_DATA_ITEM "rb-delayed-sync-data"
+
+
+static gboolean
+do_delayed_apply (GSettings *settings)
+{
+	gpointer data;
+	RBDelayedSyncFunc sync_func;
+
+	data = g_object_get_data (G_OBJECT (settings), DELAYED_SYNC_DATA_ITEM);
+	sync_func = g_object_get_data (G_OBJECT (settings), DELAYED_SYNC_FUNC_ITEM);
+	if (sync_func != NULL) {
+		GDK_THREADS_ENTER ();
+		sync_func (settings, data);
+		GDK_THREADS_LEAVE ();
+	}
+
+	g_object_set_data (G_OBJECT (settings), DELAYED_SYNC_ITEM, GUINT_TO_POINTER (0));
+	g_object_set_data (G_OBJECT (settings), DELAYED_SYNC_FUNC_ITEM, NULL);
+	g_object_set_data (G_OBJECT (settings), DELAYED_SYNC_DATA_ITEM, NULL);
+	return FALSE;
+}
+
+static void
+remove_delayed_sync (gpointer data)
+{
+	g_source_remove (GPOINTER_TO_UINT (data));
+}
+
+/**
+ * rb_settings_delayed_sync:
+ * @settings: #GSettings instance
+ * @sync_func: (allow-none): function to call
+ * @data: (allow-none): data to pass to @func
+ * @destroy: (allow-none): function to use to free @data
+ *
+ * Synchronizes settings in the @settings instance after 500ms has elapsed
+ * with no further changes.
+ */
+void
+rb_settings_delayed_sync (GSettings *settings, RBDelayedSyncFunc sync_func, gpointer data, GDestroyNotify destroy)
+{
+	if (sync_func == NULL) {
+		do_delayed_apply (settings);
+	} else {
+		guint id = g_timeout_add (500, (GSourceFunc) do_delayed_apply, settings);
+		g_object_set_data_full (G_OBJECT (settings), DELAYED_SYNC_ITEM, GUINT_TO_POINTER (id), remove_delayed_sync);
+		g_object_set_data (G_OBJECT (settings), DELAYED_SYNC_FUNC_ITEM, sync_func);
+		g_object_set_data_full (G_OBJECT (settings), DELAYED_SYNC_DATA_ITEM, data, destroy);
+	}
+}
diff --git a/lib/rb-util.h b/lib/rb-util.h
index 12601d8..126bd3a 100644
--- a/lib/rb-util.h
+++ b/lib/rb-util.h
@@ -30,6 +30,7 @@
 
 #include <stdarg.h>
 #include <glib.h>
+#include <gio/gio.h>
 #include <gtk/gtk.h>
 
 G_BEGIN_DECLS
@@ -102,6 +103,10 @@ void rb_set_tree_view_column_fixed_width (GtkWidget *treeview,
 GdkPixbuf *rb_scale_pixbuf_to_size (GdkPixbuf *pixbuf,
 				    GtkIconSize size);
 
+typedef void (*RBDelayedSyncFunc)(GSettings *settings, gpointer data);
+
+void rb_settings_delayed_sync (GSettings *settings, RBDelayedSyncFunc sync_func, gpointer data, GDestroyNotify destroy);
+
 G_END_DECLS
 
 #endif /* __RB_UTIL_H */
diff --git a/macros/gsettings.m4 b/macros/gsettings.m4
new file mode 100644
index 0000000..b686989
--- /dev/null
+++ b/macros/gsettings.m4
@@ -0,0 +1,80 @@
+dnl GLIB_GSETTINGS
+dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether
+dnl the schema should be compiled
+dnl
+
+AC_DEFUN([GLIB_GSETTINGS],
+[
+  m4_pattern_allow([AM_V_GEN])
+  AC_ARG_ENABLE(schemas-compile,
+                AC_HELP_STRING([--disable-schemas-compile],
+                               [Disable regeneration of gschemas.compiled on install]),
+                [case ${enableval} in
+                  yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE=""  ;;
+                  no)  GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;;
+                  *) AC_MSG_ERROR([bad value ${enableval} for --enable-schemas-compile]) ;;
+                 esac])
+  AC_SUBST([GSETTINGS_DISABLE_SCHEMAS_COMPILE])
+  PKG_PROG_PKG_CONFIG([0.16])
+  AC_SUBST(gsettingsschemadir, [${datadir}/glib-2.0/schemas])
+  AC_SUBST(GLIB_COMPILE_SCHEMAS, `$PKG_CONFIG --variable glib_compile_schemas gio-2.0`)
+  if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then
+    AC_MSG_ERROR([glib-compile-schemas not found.])
+  fi
+
+  GSETTINGS_RULES='
+.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas
+
+mostlyclean-am: clean-gsettings-schemas
+
+%.gschema.valid: %.gschema.xml
+	$(AM_V_GEN) if test -f "$^"; then d=; else d="$(srcdir)/"; fi; $(GLIB_COMPILE_SCHEMAS) --dry-run --schema-file=$${d}$^ && touch [$]@
+
+all-am: $(gsettings_SCHEMAS:.xml=.valid)
+uninstall-am: uninstall-gsettings-schemas
+install-data-am: install-gsettings-schemas
+
+.SECONDARY: $(gsettings_SCHEMAS)
+
+gsettings__base_list = \
+  sed "$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g" | \
+  sed "$$!N;$$!N;$$!N;$$!N;s/\n/ /g"
+
+install-gsettings-schemas: $(gsettings_SCHEMAS:.xml=.valid)
+	@$(NORMAL_INSTALL)
+	test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"
+	@list='\''$(gsettings_SCHEMAS)'\''; test -n "$(gsettingsschemadir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(gsettings__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '\''$(DESTDIR)$(gsettingsschemadir)'\''"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(gsettingsschemadir)" || exit $$?; \
+	done
+	test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir)
+
+uninstall-gsettings-schemas:
+	@$(NORMAL_UNINSTALL)
+	@list='\''$(gsettings_SCHEMAS)'\''; test -n "$(gsettingsschemadir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files
+	test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) --uninstall $(gsettingsschemadir)
+
+clean-gsettings-schemas:
+	rm -f $(gsettings_SCHEMAS:.xml=.valid)
+
+'
+  _GSETTINGS_SUBST(GSETTINGS_RULES)
+])
+
+dnl _GSETTINGS_SUBST(VARIABLE)
+dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST
+AC_DEFUN([_GSETTINGS_SUBST],
+[
+AC_SUBST([$1])
+m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])])
+]
+)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e4a8b9c..364202d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -21,7 +21,6 @@ backends/rb-player.c
 data/playlists.xml.in
 data/rhythmbox.desktop.in.in
 data/rhythmbox-device.desktop.in.in
-lib/eel-gconf-extensions.c
 lib/eggdesktopfile.c
 lib/eggsmclient.c
 lib/rb-cut-and-paste-code.c
diff --git a/podcast/Makefile.am b/podcast/Makefile.am
index c68e323..5a9fe99 100644
--- a/podcast/Makefile.am
+++ b/podcast/Makefile.am
@@ -19,6 +19,7 @@ librbpodcast_la_SOURCES =				\
 	rb-podcast-properties-dialog.h			\
 	rb-podcast-main-source.c			\
 	rb-podcast-main-source.h			\
+	rb-podcast-settings.h				\
 	rb-podcast-source.c				\
 	rb-podcast-source.h				\
 	rb-podcast-parse.c				\
diff --git a/podcast/rb-podcast-main-source.c b/podcast/rb-podcast-main-source.c
index 7b7cd4a..1f29c9b 100644
--- a/podcast/rb-podcast-main-source.c
+++ b/podcast/rb-podcast-main-source.c
@@ -31,19 +31,15 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
+#include "rb-podcast-settings.h"
 #include "rb-podcast-main-source.h"
 #include "rb-podcast-entry-types.h"
 #include "rb-shell.h"
-#include "eel-gconf-extensions.h"
 #include "rb-builder-helpers.h"
 #include "rb-file-helpers.h"
 #include "rb-util.h"
 #include "rb-stock-icons.h"
 
-#define CONF_STATE_PODCAST_PREFIX		CONF_PREFIX "/state/podcast"
-#define CONF_STATE_PODCAST_DOWNLOAD_INTERVAL	CONF_STATE_PODCAST_PREFIX "/download_interval"
-#define CONF_STATE_PODCAST_DOWNLOAD_DIR		CONF_STATE_PODCAST_PREFIX "/download_prefix"
-
 struct _RBPodcastMainSourcePrivate
 {
 	GtkWidget *config_widget;
@@ -58,6 +54,7 @@ rb_podcast_main_source_new (RBShell *shell, RBPodcastManager *podcast_manager)
 	RBSource *source;
 	RhythmDBQuery *base_query;
 	RhythmDB *db;
+	GSettings *settings;
 
 	g_object_get (shell, "db", &db, NULL);
 	base_query = rhythmdb_query_parse (db,
@@ -67,6 +64,8 @@ rb_podcast_main_source_new (RBShell *shell, RBPodcastManager *podcast_manager)
 					   RHYTHMDB_QUERY_END);
 	g_object_unref (db);
 
+	settings = g_settings_new (PODCAST_SETTINGS_SCHEMA);
+
 	source = RB_SOURCE (g_object_new (RB_TYPE_PODCAST_MAIN_SOURCE,
 					  "name", _("Podcasts"),
 					  "shell", shell,
@@ -74,7 +73,9 @@ rb_podcast_main_source_new (RBShell *shell, RBPodcastManager *podcast_manager)
 					  "search-type", RB_SOURCE_SEARCH_INCREMENTAL,
 					  "podcast-manager", podcast_manager,
 					  "base-query", base_query,
+					  "settings", g_settings_get_child (settings, "source"),
 					  NULL));
+	g_object_unref (settings);
 
 	rhythmdb_query_free (base_query);
 
@@ -233,27 +234,18 @@ feed_error_cb (RBPodcastManager *pd,
 }
 
 static void
-rb_podcast_main_source_btn_file_change_cb (GtkFileChooserButton *widget, const char *key)
+rb_podcast_main_source_btn_file_change_cb (GtkFileChooserButton *widget, RBPodcastSource *source)
 {
+	GSettings *settings;
 	char *uri;
-	
-	uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (widget));
-	eel_gconf_set_string (key, uri);
-	g_free (uri);
-}
 
-static void
-rb_podcast_main_source_cb_interval_changed_cb (GtkComboBox *box, gpointer cb_data)
-{
-	RBPodcastManager *podcast_mgr;
+	settings = g_settings_new (PODCAST_SETTINGS_SCHEMA);
 
-	guint index = gtk_combo_box_get_active (box);
-	eel_gconf_set_integer (CONF_STATE_PODCAST_DOWNLOAD_INTERVAL,
-			       index);
+	uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (widget));
+	g_settings_set_string (settings, PODCAST_DOWNLOAD_DIR_KEY, uri);
+	g_free (uri);
 
-	g_object_get (cb_data, "podcast-manager", &podcast_mgr, NULL);
-	rb_podcast_manager_start_sync (podcast_mgr);
-	g_object_unref (podcast_mgr);
+	g_object_unref (settings);
 }
 
 static GtkWidget *
@@ -262,8 +254,9 @@ impl_get_config_widget (RBDisplayPage *page, RBShellPreferences *prefs)
 	RBPodcastMainSource *source = RB_PODCAST_MAIN_SOURCE (page);
 	RBPodcastManager *podcast_mgr;
 	GtkBuilder *builder;
-	GtkWidget *cb_update_interval;
+	GtkWidget *update_interval;
 	GtkWidget *btn_file;
+	GSettings *settings;
 	char *download_dir;
 
 	if (source->priv->config_widget)
@@ -277,26 +270,29 @@ impl_get_config_widget (RBDisplayPage *page, RBShellPreferences *prefs)
 					      rb_music_dir (),
 					      NULL);
 
-	g_object_get (source, "podcast-manager", &podcast_mgr, NULL);
+	g_object_get (source,
+		      "podcast-manager", &podcast_mgr,
+		      NULL);
 	download_dir = rb_podcast_manager_get_podcast_dir (podcast_mgr);
-	g_object_unref (podcast_mgr);
 
 	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (btn_file),
 						 download_dir);
+	g_object_unref (podcast_mgr);
 	g_free (download_dir);
 
-	g_signal_connect (btn_file,
-			  "selection-changed",
-			  G_CALLBACK (rb_podcast_main_source_btn_file_change_cb),
-			  CONF_STATE_PODCAST_DOWNLOAD_DIR);
+	g_signal_connect_object (btn_file,
+				 "selection-changed",
+				 G_CALLBACK (rb_podcast_main_source_btn_file_change_cb),
+				 source, 0);
+
+	update_interval = GTK_WIDGET (gtk_builder_get_object (builder, "update_interval"));
+	g_object_set (update_interval, "id-column", 1, NULL);
 
-	cb_update_interval = GTK_WIDGET (gtk_builder_get_object (builder, "cb_update_interval"));
-	gtk_combo_box_set_active (GTK_COMBO_BOX (cb_update_interval),
-				  eel_gconf_get_integer (CONF_STATE_PODCAST_DOWNLOAD_INTERVAL));
-	g_signal_connect (cb_update_interval,
-			  "changed",
-			  G_CALLBACK (rb_podcast_main_source_cb_interval_changed_cb),
-			  source);
+	settings = g_settings_new (PODCAST_SETTINGS_SCHEMA);
+	g_settings_bind (settings, PODCAST_DOWNLOAD_INTERVAL,
+			 update_interval, "active-id",
+			 G_SETTINGS_BIND_DEFAULT);
+	g_object_unref (settings);
 
 	return source->priv->config_widget;
 }
@@ -344,31 +340,31 @@ impl_constructed (GObject *object)
 	RBPodcastManager *podcast_mgr;
 	GdkPixbuf *pixbuf;
 	gint size;
-	
+
 	RB_CHAIN_GOBJECT_METHOD (rb_podcast_main_source_parent_class, constructed, object);
 	source = RB_PODCAST_MAIN_SOURCE (object);
 
 	g_object_get (source, "podcast-manager", &podcast_mgr, NULL);
 
 	g_signal_connect_object (podcast_mgr,
-	 		        "start_download",
-			  	G_CALLBACK (start_download_cb),
-			  	source, 0);
+			        "start_download",
+				G_CALLBACK (start_download_cb),
+				source, 0);
 
 	g_signal_connect_object (podcast_mgr,
-			  	"finish_download",
-			  	G_CALLBACK (finish_download_cb),
-			  	source, 0);
+				"finish_download",
+				G_CALLBACK (finish_download_cb),
+				source, 0);
 
 	g_signal_connect_object (podcast_mgr,
-			  	"feed_updates_available",
- 			  	G_CALLBACK (feed_updates_available_cb),
-			  	source, 0);
+				"feed_updates_available",
+				G_CALLBACK (feed_updates_available_cb),
+				source, 0);
 
 	g_signal_connect_object (podcast_mgr,
-			  	 "process_error",
-			 	 G_CALLBACK (feed_error_cb),
-			  	 source, 0);
+				 "process_error",
+				 G_CALLBACK (feed_error_cb),
+				 source, 0);
 
 	gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
 	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
@@ -418,6 +414,6 @@ rb_podcast_main_source_class_init (RBPodcastMainSourceClass *klass)
 
 	source_class->impl_want_uri = impl_want_uri;
 	source_class->impl_add_uri = impl_add_uri;
-	
+
 	g_type_class_add_private (klass, sizeof (RBPodcastMainSourcePrivate));
 }
diff --git a/podcast/rb-podcast-manager.c b/podcast/rb-podcast-manager.c
index 5d2d736..a8b8cfd 100644
--- a/podcast/rb-podcast-manager.c
+++ b/podcast/rb-podcast-manager.c
@@ -37,8 +37,7 @@
 #include <gio/gio.h>
 #include <gtk/gtk.h>
 
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
+#include "rb-podcast-settings.h"
 #include "rb-podcast-manager.h"
 #include "rb-podcast-entry-types.h"
 #include "rb-file-helpers.h"
@@ -52,11 +51,6 @@
 #include "rb-util.h"
 #include "rb-missing-plugins.h"
 
-#define CONF_STATE_PODCAST_PREFIX		CONF_PREFIX "/state/podcast"
-#define CONF_STATE_PODCAST_DOWNLOAD_DIR		CONF_STATE_PODCAST_PREFIX "/download_prefix"
-#define CONF_STATE_PODCAST_DOWNLOAD_INTERVAL	CONF_STATE_PODCAST_PREFIX "/download_interval"
-#define CONF_STATE_PODCAST_DOWNLOAD_NEXT_TIME	CONF_STATE_PODCAST_PREFIX "/download_next_time"
-
 enum
 {
 	PROP_0,
@@ -65,14 +59,6 @@ enum
 
 enum
 {
-	UPDATE_EVERY_HOUR,
-	UPDATE_EVERY_DAY,
-	UPDATE_EVERY_WEEK,
-	UPDATE_MANUALLY
-};
-
-enum
-{
 	STATUS_CHANGED,
 	START_DOWNLOAD,
 	FINISH_DOWNLOAD,
@@ -123,11 +109,12 @@ struct RBPodcastManagerPrivate
 	RhythmDB *db;
 	GList *download_list;
 	RBPodcastManagerInfo *active_download;
-	guint next_time;
 	guint source_sync;
-	guint update_interval_notify_id;
 	guint next_file_id;
 	gboolean shutdown;
+
+	GSettings *settings;
+	GFile *timestamp_file;
 };
 
 #define RB_PODCAST_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_PODCAST_MANAGER, RBPodcastManagerPrivate))
@@ -158,11 +145,7 @@ static void download_file_info_cb			(GFile *source,
 static void download_podcast				(GFileInfo *src_info,
 							 RBPodcastManagerInfo *data);
 static void rb_podcast_manager_abort_download		(RBPodcastManagerInfo *data);
-static gboolean rb_podcast_manager_sync_head_cb 	(gpointer data);
-static gboolean rb_podcast_manager_head_query_cb 	(GtkTreeModel *query_model,
-						   	 GtkTreePath *path,
-							 GtkTreeIter *iter,
-						   	 RBPodcastManager *data);
+static gboolean rb_podcast_manager_update_feeds_cb 	(gpointer data);
 static void rb_podcast_manager_save_metadata		(RBPodcastManager *pd,
 						  	 RhythmDBEntry *entry);
 static void rb_podcast_manager_db_entry_added_cb 	(RBPodcastManager *pd,
@@ -175,17 +158,16 @@ static gboolean rb_podcast_manager_handle_feed_error	(RBPodcastManager *mgr,
 							 gboolean emit);
 
 static gpointer rb_podcast_manager_thread_parse_feed	(RBPodcastThreadInfo *info);
+static void podcast_settings_changed_cb			(GSettings *settings,
+							 const char *key,
+							 RBPodcastManager *mgr);
 
 /* internal functions */
 static void download_info_free				(RBPodcastManagerInfo *data);
 static gpointer podcast_download_thread			(RBPodcastManagerInfo *data);
 static gboolean end_job					(RBPodcastManagerInfo *data);
 static void cancel_job					(RBPodcastManagerInfo *pd);
-static void rb_podcast_manager_update_synctime		(RBPodcastManager *pd);
-static void rb_podcast_manager_config_changed		(GConfClient* client,
-                                        		 guint cnxn_id,
-				                         GConfEntry *entry,
-							 gpointer user_data);
+static void rb_podcast_manager_start_update_timer 	(RBPodcastManager *pd);
 
 G_DEFINE_TYPE (RBPodcastManager, rb_podcast_manager, G_TYPE_OBJECT)
 
@@ -276,17 +258,36 @@ rb_podcast_manager_init (RBPodcastManager *pd)
 
 	pd->priv->source_sync = 0;
 	pd->priv->db = NULL;
-	eel_gconf_monitor_add (CONF_STATE_PODCAST_PREFIX);
+
 }
 
 static void
 rb_podcast_manager_constructed (GObject *object)
 {
 	RBPodcastManager *pd = RB_PODCAST_MANAGER (object);
+	GFileOutputStream *st;
+	char *ts_file_path;
+
 	RB_CHAIN_GOBJECT_METHOD (rb_podcast_manager_parent_class, constructed, object);
-	pd->priv->update_interval_notify_id = eel_gconf_notification_add (CONF_STATE_PODCAST_DOWNLOAD_INTERVAL,
-	                    			       			  rb_podcast_manager_config_changed,
-	                            		       			  pd);
+
+	pd->priv->settings = g_settings_new (PODCAST_SETTINGS_SCHEMA);
+	g_signal_connect_object (pd->priv->settings,
+				 "changed",
+				 G_CALLBACK (podcast_settings_changed_cb),
+				 pd, 0);
+
+	ts_file_path = g_build_filename (rb_user_data_dir (), "podcast-timestamp", NULL);
+	pd->priv->timestamp_file = g_file_new_for_path (ts_file_path);
+	g_free (ts_file_path);
+
+	/* create it if it doesn't exist */
+	st = g_file_create (pd->priv->timestamp_file, G_FILE_CREATE_NONE, NULL, NULL);
+	if (st != NULL) {
+		g_output_stream_close (G_OUTPUT_STREAM (st), NULL, NULL);
+		g_object_unref (st);
+	}
+
+	rb_podcast_manager_start_update_timer (pd);
 }
 
 static void
@@ -299,8 +300,6 @@ rb_podcast_manager_dispose (GObject *object)
 	pd = RB_PODCAST_MANAGER (object);
 	g_return_if_fail (pd->priv != NULL);
 
-	eel_gconf_monitor_remove (CONF_STATE_PODCAST_PREFIX);
-
 	if (pd->priv->next_file_id != 0) {
 		g_source_remove (pd->priv->next_file_id);
 		pd->priv->next_file_id = 0;
@@ -311,16 +310,21 @@ rb_podcast_manager_dispose (GObject *object)
 		pd->priv->source_sync = 0;
 	}
 
-	if (pd->priv->update_interval_notify_id != 0) {
-		eel_gconf_notification_remove (pd->priv->update_interval_notify_id);
-		pd->priv->update_interval_notify_id = 0;
-	}
-
 	if (pd->priv->db != NULL) {
 		g_object_unref (pd->priv->db);
 		pd->priv->db = NULL;
 	}
 
+	if (pd->priv->settings != NULL) {
+		g_object_unref (pd->priv->settings);
+		pd->priv->settings = NULL;
+	}
+
+	if (pd->priv->timestamp_file != NULL) {
+		g_object_unref (pd->priv->timestamp_file);
+		pd->priv->timestamp_file = NULL;
+	}
+
 	G_OBJECT_CLASS (rb_podcast_manager_parent_class)->dispose (object);
 }
 
@@ -522,51 +526,93 @@ rb_podcast_manager_entry_in_download_queue (RBPodcastManager *pd, RhythmDBEntry
 	return FALSE;
 }
 
-void
-rb_podcast_manager_start_sync (RBPodcastManager *pd)
+static void
+rb_podcast_manager_start_update_timer (RBPodcastManager *pd)
 {
-	gint next_time;
+	guint64 last_time;
+	guint64 interval_sec;
+	guint64 now;
+	GFileInfo *fi;
+	RBPodcastInterval interval;
 
 	g_return_if_fail (RB_IS_PODCAST_MANAGER (pd));
 
-	if (pd->priv->next_time > 0) {
-		next_time = pd->priv->next_time;
+	if (pd->priv->source_sync != 0) {
+		g_source_remove (pd->priv->source_sync);
+		pd->priv->source_sync = 0;
+	}
+
+	interval = g_settings_get_enum (pd->priv->settings,
+					PODCAST_DOWNLOAD_INTERVAL);
+	if (interval == PODCAST_INTERVAL_MANUAL) {
+		rb_debug ("periodic podcast updates disabled");
+		return;
+	}
+
+	/* get last update time */
+	fi = g_file_query_info (pd->priv->timestamp_file,
+				G_FILE_ATTRIBUTE_TIME_MODIFIED,
+				G_FILE_QUERY_INFO_NONE,
+				NULL,
+				NULL);
+	if (fi != NULL) {
+		last_time = g_file_info_get_attribute_uint64 (fi, G_FILE_ATTRIBUTE_TIME_MODIFIED);
 	} else {
-		next_time = eel_gconf_get_integer (CONF_STATE_PODCAST_DOWNLOAD_NEXT_TIME);
+		last_time = 0;
 	}
 
-	if (next_time > 0) {
-		if (pd->priv->source_sync != 0) {
-			g_source_remove (pd->priv->source_sync);
-			pd->priv->source_sync = 0;
-		}
-		next_time = next_time - ((int)time (NULL));
-		if (next_time <= 0) {
-			rb_podcast_manager_update_feeds (pd);
-			pd->priv->next_time = 0;
-			rb_podcast_manager_update_synctime (pd);
-			return;
-		}
-		pd->priv->source_sync = g_timeout_add_seconds (next_time, (GSourceFunc) rb_podcast_manager_sync_head_cb, pd);
+	switch (interval) {
+	case PODCAST_INTERVAL_HOURLY:
+		interval_sec = 3600;
+		break;
+	case PODCAST_INTERVAL_DAILY:
+		interval_sec = (3600 * 24);
+		break;
+	case PODCAST_INTERVAL_WEEKLY:
+		interval_sec = (3600 * 24 * 7);
+		break;
+	default:
+		g_assert_not_reached ();
+		return;
 	}
 
+	/* wait until next update time */
+	now = time (NULL);
+	rb_debug ("last periodic update at %" G_GUINT64_FORMAT ", interval %" G_GUINT64_FORMAT ", time is now %" G_GUINT64_FORMAT,
+		  last_time, interval_sec, now);
+
+	if (last_time + interval_sec < now) {
+		rb_debug ("periodic update should already have happened");
+		pd->priv->source_sync = g_idle_add ((GSourceFunc) rb_podcast_manager_update_feeds_cb,
+						    pd);
+	} else {
+		rb_debug ("next periodic update in %" G_GUINT64_FORMAT " seconds", (last_time + interval_sec) - now);
+		pd->priv->source_sync = g_timeout_add_seconds ((last_time + interval_sec) - now,
+							       (GSourceFunc) rb_podcast_manager_update_feeds_cb,
+							       pd);
+	}
 }
 
 static gboolean
-rb_podcast_manager_sync_head_cb (gpointer data)
+rb_podcast_manager_head_query_cb (GtkTreeModel *query_model,
+				  GtkTreePath *path,
+				  GtkTreeIter *iter,
+				  RBPodcastManager *manager)
 {
-	RBPodcastManager *pd = RB_PODCAST_MANAGER (data);
+        const char *uri;
+        RhythmDBEntry *entry;
+	guint status;
 
-	g_assert (rb_is_main_thread ());
+        gtk_tree_model_get (query_model, iter, 0, &entry, -1);
+        uri = get_remote_location (entry);
+	status = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_STATUS);
 
-	GDK_THREADS_ENTER ();
+	if (status == 1)
+		rb_podcast_manager_subscribe_feed (manager, uri, TRUE);
 
-	rb_podcast_manager_update_feeds (pd);
-	pd->priv->source_sync = 0;
-	pd->priv->next_time = 0;
-	rb_podcast_manager_update_synctime (RB_PODCAST_MANAGER (data));
-	GDK_THREADS_LEAVE ();
-	return FALSE;
+	rhythmdb_entry_unref (entry);
+
+        return FALSE;
 }
 
 void
@@ -574,8 +620,6 @@ rb_podcast_manager_update_feeds (RBPodcastManager *pd)
 {
 	GtkTreeModel *query_model;
 
-	g_return_if_fail (RB_IS_PODCAST_MANAGER (pd));
-
 	query_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (pd->priv->db));
 
 	rhythmdb_do_full_query (pd->priv->db,
@@ -592,25 +636,29 @@ rb_podcast_manager_update_feeds (RBPodcastManager *pd)
 }
 
 static gboolean
-rb_podcast_manager_head_query_cb (GtkTreeModel *query_model,
- 	   			  GtkTreePath *path,
-				  GtkTreeIter *iter,
-				  RBPodcastManager *manager)
+rb_podcast_manager_update_feeds_cb (gpointer data)
 {
-        const char *uri;
-        RhythmDBEntry *entry;
-	guint status;
+	RBPodcastManager *pd = RB_PODCAST_MANAGER (data);
 
-        gtk_tree_model_get (query_model, iter, 0, &entry, -1);
-        uri = get_remote_location (entry);
-	status = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_STATUS);
+	g_assert (rb_is_main_thread ());
 
-	if (status == 1)
-		rb_podcast_manager_subscribe_feed (manager, uri, TRUE);
+	GDK_THREADS_ENTER ();
 
-	rhythmdb_entry_unref (entry);
+	pd->priv->source_sync = 0;
 
-        return FALSE;
+	g_file_set_attribute_uint64 (pd->priv->timestamp_file,
+				     G_FILE_ATTRIBUTE_TIME_MODIFIED,
+				     (guint64) time (NULL),
+				     G_FILE_QUERY_INFO_NONE,
+				     NULL,
+				     NULL);
+
+	rb_podcast_manager_update_feeds (pd);
+
+	rb_podcast_manager_start_update_timer (pd);
+
+	GDK_THREADS_LEAVE ();
+	return FALSE;
 }
 
 static void
@@ -843,7 +891,7 @@ download_podcast (GFileInfo *src_info, RBPodcastManagerInfo *data)
 
 	sane_local_file_uri = rb_sanitize_uri_for_filesystem (local_file_uri);
 	g_free (local_file_uri);
-	
+
 	rb_debug ("download URI: %s", sane_local_file_uri);
 
 	if (rb_uri_create_parent_dirs (sane_local_file_uri, &error) == FALSE) {
@@ -862,7 +910,7 @@ download_podcast (GFileInfo *src_info, RBPodcastManagerInfo *data)
 	if (g_file_query_exists (data->destination, NULL)) {
 		GFileInfo *dest_info;
 		guint64 local_size;
-	
+
 		dest_info = g_file_query_info (data->destination,
 					       G_FILE_ATTRIBUTE_STANDARD_SIZE,
 					       G_FILE_QUERY_INFO_NONE,
@@ -1557,7 +1605,7 @@ podcast_download_thread (RBPodcastManagerInfo *data)
 			return NULL;
 		}
 	}
-	
+
 	/* loop, copying from input stream to output stream */
 	while (TRUE) {
 		char *p;
@@ -1787,43 +1835,11 @@ rb_podcast_manager_cancel_download (RBPodcastManager *pd, RhythmDBEntry *entry)
 }
 
 static void
-rb_podcast_manager_update_synctime (RBPodcastManager *pd)
-{
-	gint value;
-	gint index = eel_gconf_get_integer (CONF_STATE_PODCAST_DOWNLOAD_INTERVAL);
-
-	switch (index)
-	{
-	case UPDATE_EVERY_HOUR:
-		value = time (NULL) + 3600;
-		break;
-	case UPDATE_EVERY_DAY:
-		value = time (NULL) + (3600 * 24);
-		break;
-	case UPDATE_EVERY_WEEK:
-		value = time (NULL) + (3600 * 24 * 7);
-		break;
-	case UPDATE_MANUALLY:
-		value = 0;
-		break;
-	default:
-		g_warning ("unknown download-inteval");
-		value = 0;
-	};
-
-	eel_gconf_set_integer (CONF_STATE_PODCAST_DOWNLOAD_NEXT_TIME, value);
-	eel_gconf_suggest_sync ();
-	pd->priv->next_time = value;
-	rb_podcast_manager_start_sync (pd);
-}
-
-static void
-rb_podcast_manager_config_changed (GConfClient* client,
-				   guint cnxn_id,
-				   GConfEntry *entry,
-				   gpointer user_data)
+podcast_settings_changed_cb (GSettings *settings, const char *key, RBPodcastManager *mgr)
 {
-	rb_podcast_manager_update_synctime (RB_PODCAST_MANAGER (user_data));
+	if (g_strcmp0 (key, PODCAST_DOWNLOAD_INTERVAL) == 0) {
+		rb_podcast_manager_start_update_timer (mgr);
+	}
 }
 
 /* this bit really wants to die */
@@ -1977,7 +1993,7 @@ rb_podcast_manager_insert_feed (RBPodcastManager *pd, RBPodcastChannel *data)
 	new_last_post = last_post;
 
 	updated = FALSE;
-	download_last = (eel_gconf_get_integer (CONF_STATE_PODCAST_DOWNLOAD_INTERVAL) != UPDATE_MANUALLY);
+	download_last = (g_settings_get_enum (pd->priv->settings, PODCAST_DOWNLOAD_INTERVAL) != PODCAST_INTERVAL_MANUAL);
 	for (lst_songs = data->posts; lst_songs != NULL; lst_songs = g_list_next (lst_songs)) {
 		RBPodcastItem *item = (RBPodcastItem *) lst_songs->data;
 		RhythmDBEntry *post_entry;
@@ -2149,11 +2165,10 @@ rb_podcast_manager_shutdown (RBPodcastManager *pd)
 char *
 rb_podcast_manager_get_podcast_dir (RBPodcastManager *pd)
 {
-	char *conf_dir_uri = eel_gconf_get_string (CONF_STATE_PODCAST_DOWNLOAD_DIR);
+	char *conf_dir_uri = g_settings_get_string (pd->priv->settings, PODCAST_DOWNLOAD_DIR_KEY);
 
 	/* if we don't have a download directory yet, use the music dir,
 	 * or the home dir if we can't find that.
-	 * if the download directory is a path, rather than a URI, convert it.
 	 */
 	if (conf_dir_uri == NULL || (strcmp (conf_dir_uri, "") == 0)) {
 		const char *conf_dir_name;
@@ -2163,14 +2178,7 @@ rb_podcast_manager_get_podcast_dir (RBPodcastManager *pd)
 			conf_dir_name = g_get_home_dir ();
 
 		conf_dir_uri = g_filename_to_uri (conf_dir_name, NULL, NULL);
-		eel_gconf_set_string (CONF_STATE_PODCAST_DOWNLOAD_DIR, conf_dir_uri);
-	} else if (conf_dir_uri[0] == '/') {
-		char *path = conf_dir_uri;
-
-		conf_dir_uri = g_filename_to_uri (path, NULL, NULL);
-		rb_debug ("converted podcast download dir %s to URI %s", path, conf_dir_uri);
-		eel_gconf_set_string (CONF_STATE_PODCAST_DOWNLOAD_DIR, conf_dir_uri);
-		g_free (path);
+		g_settings_set_string (pd->priv->settings, PODCAST_DOWNLOAD_DIR_KEY, conf_dir_uri);
 	}
 
 	return conf_dir_uri;
diff --git a/podcast/rb-podcast-settings.h b/podcast/rb-podcast-settings.h
new file mode 100644
index 0000000..376bba9
--- /dev/null
+++ b/podcast/rb-podcast-settings.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *  Copyright (C) 2010 Jonathan Matthew  <jonathan d14n 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.
+ *
+ *  The Rhythmbox authors hereby grant permission for non-GPL compatible
+ *  GStreamer plugins to be used and distributed together with GStreamer
+ *  and Rhythmbox. This permission is above and beyond the permissions granted
+ *  by the GPL license by which Rhythmbox is covered. If you modify this code
+ *  you may extend this exception to your version of the code, but you are not
+ *  obligated to do so. If you do not wish to do so, delete this exception
+ *  statement from your 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#ifndef RB_PODCAST_SETTINGS__H
+#define RB_PODCAST_SETTINGS__H
+
+#define PODCAST_SETTINGS_SCHEMA			"org.gnome.rhythmbox.podcast"
+
+#define PODCAST_DOWNLOAD_DIR_KEY		"download-location"
+#define PODCAST_DOWNLOAD_INTERVAL		"download-interval"
+#define PODCAST_PANED_POSITION			"paned-position"
+
+typedef enum {
+	PODCAST_INTERVAL_HOURLY = 0,
+	PODCAST_INTERVAL_DAILY,
+	PODCAST_INTERVAL_WEEKLY,
+	PODCAST_INTERVAL_MANUAL
+} RBPodcastInterval;
+
+
+#endif /* RB_PODCAST_SETTINGS__H */
diff --git a/podcast/rb-podcast-source.c b/podcast/rb-podcast-source.c
index 33c7c8a..9b87457 100644
--- a/podcast/rb-podcast-source.c
+++ b/podcast/rb-podcast-source.c
@@ -42,6 +42,7 @@
 #include <gtk/gtk.h>
 
 #include "rb-podcast-source.h"
+#include "rb-podcast-settings.h"
 #include "rb-podcast-entry-types.h"
 
 #include "rhythmdb.h"
@@ -52,21 +53,19 @@
 #include "rb-property-view.h"
 #include "rb-util.h"
 #include "rb-file-helpers.h"
-#include "rb-preferences.h"
 #include "rb-dialog.h"
 #include "rb-uri-dialog.h"
 #include "rb-podcast-properties-dialog.h"
 #include "rb-feed-podcast-properties-dialog.h"
 #include "rb-playlist-manager.h"
 #include "rb-debug.h"
-#include "eel-gconf-extensions.h"
 #include "rb-podcast-manager.h"
 #include "rb-static-playlist-source.h"
 #include "rb-cut-and-paste-code.h"
 #include "rb-source-search-basic.h"
 #include "rb-cell-renderer-pixbuf.h"
 
-static void podcast_cmd_new_podcast	 	(GtkAction *action,
+static void podcast_cmd_new_podcast		(GtkAction *action,
 						 RBPodcastSource *source);
 static void podcast_cmd_download_post		(GtkAction *action,
 						 RBPodcastSource *source);
@@ -81,11 +80,6 @@ static void podcast_cmd_update_all		(GtkAction *action,
 static void podcast_cmd_properties_feed		(GtkAction *action,
 						 RBPodcastSource *source);
 
-#define CONF_STATE_PODCAST_PREFIX		CONF_PREFIX "/state/podcast"
-#define CONF_STATE_PANED_POSITION 		CONF_STATE_PODCAST_PREFIX "/paned_position"
-#define CONF_STATE_PODCAST_SORTING_POSTS	CONF_STATE_PODCAST_PREFIX "/sorting_posts"
-#define CONF_STATE_SHOW_BROWSER   		CONF_STATE_PODCAST_PREFIX "/show_browser"
-
 struct _RBPodcastSourcePrivate
 {
 	RhythmDB *db;
@@ -153,48 +147,19 @@ enum
 {
 	PROP_0,
 	PROP_PODCAST_MANAGER,
-	PROP_BASE_QUERY
+	PROP_BASE_QUERY,
+	PROP_SHOW_BROWSER
 };
 
 G_DEFINE_TYPE (RBPodcastSource, rb_podcast_source, RB_TYPE_SOURCE)
 
 static void
-paned_size_allocate_cb (GtkWidget *widget,
-			GtkAllocation *allocation,
-		        RBPodcastSource *source)
-{
-	rb_debug ("paned size allocate");
-	eel_gconf_set_integer (CONF_STATE_PANED_POSITION,
-			       gtk_paned_get_position (GTK_PANED (source->priv->paned)));
-}
-
-static void
-rb_podcast_source_state_prefs_sync (RBPodcastSource *source)
-{
-	rb_debug ("syncing state");
-	gtk_paned_set_position (GTK_PANED (source->priv->paned),
-				eel_gconf_get_integer (CONF_STATE_PANED_POSITION));
-	g_object_set (source->priv->feeds,
-		      "visible", eel_gconf_get_boolean (CONF_STATE_SHOW_BROWSER),
-		      NULL);
-}
-
-static void
-podcast_pref_change_cb (GConfClient *client,
-			guint cnxn_id,
-			GConfEntry *entry,
-			RBPodcastSource *source)
-{
-	rb_debug ("state prefs changed");
-	rb_podcast_source_state_prefs_sync (source);
-}
-
-static void
-podcast_posts_view_sort_order_changed_cb (RBEntryView *view,
+podcast_posts_view_sort_order_changed_cb (GObject *object,
+					  GParamSpec *pspec,
 					  RBPodcastSource *source)
 {
 	rb_debug ("sort order changed");
-	rb_entry_view_resort_model (view);
+	rb_entry_view_resort_model (RB_ENTRY_VIEW (object));
 }
 
 static void
@@ -953,6 +918,15 @@ podcast_error_pixbuf_clicked_cb (RBCellRendererPixbuf *renderer,
 	gtk_tree_path_free (path);
 }
 
+static void
+settings_changed_cb (GSettings *settings, const char *key, RBPodcastSource *source)
+{
+	if (g_strcmp0 (key, PODCAST_PANED_POSITION) == 0) {
+		gtk_paned_set_position (GTK_PANED (source->priv->paned),
+					g_settings_get_int (settings, key));
+	}
+}
+
 RBSource *
 rb_podcast_source_new (RBShell *shell,
 		       RBPodcastManager *podcast_manager,
@@ -961,6 +935,9 @@ rb_podcast_source_new (RBShell *shell,
 		       const char *icon_name)
 {
 	RBSource *source;
+	GSettings *settings;
+
+	settings = g_settings_new (PODCAST_SETTINGS_SCHEMA);
 
 	source = RB_SOURCE (g_object_new (RB_TYPE_PODCAST_SOURCE,
 					  "name", name,
@@ -969,7 +946,9 @@ rb_podcast_source_new (RBShell *shell,
 					  "search-type", RB_SOURCE_SEARCH_INCREMENTAL,
 					  "podcast-manager", podcast_manager,
 					  "base-query", base_query,
+					  "settings", g_settings_get_child (settings, "source"),
 					  NULL));
+	g_object_unref (settings);
 
 	if (icon_name != NULL) {
 		GdkPixbuf *pixbuf;
@@ -1119,13 +1098,6 @@ impl_delete (RBSource *asource)
 	rhythmdb_commit (source->priv->db);
 }
 
-static char *
-impl_get_browser_key (RBSource *asource)
-{
-	return g_strdup (CONF_STATE_SHOW_BROWSER);
-}
-
-
 static RBEntryView *
 impl_get_entry_view (RBSource *asource)
 {
@@ -1178,7 +1150,7 @@ impl_receive_drag (RBDisplayPage *page, GtkSelectionData *selection_data)
 		if ((uri != NULL) && (!rhythmdb_entry_lookup_by_location (source->priv->db, uri))) {
 			rb_podcast_manager_subscribe_feed (source->priv->podcast_mgr, uri, FALSE);
 		}
-		
+
 		if (gtk_selection_data_get_data_type (selection_data) == gdk_atom_intern ("_NETSCAPE_URL", FALSE)) {
 			i = i->next;
 		}
@@ -1266,6 +1238,9 @@ impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSp
 	case PROP_BASE_QUERY:
 		source->priv->base_query = rhythmdb_query_copy (g_value_get_pointer (value));
 		break;
+	case PROP_SHOW_BROWSER:
+		gtk_widget_set_visible (GTK_WIDGET (source->priv->feeds), g_value_get_boolean (value));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 		break;
@@ -1284,6 +1259,9 @@ impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *ps
 	case PROP_BASE_QUERY:
 		g_value_set_pointer (value, source->priv->base_query);
 		break;
+	case PROP_SHOW_BROWSER:
+		g_value_set_boolean (value, gtk_widget_get_visible (GTK_WIDGET (source->priv->feeds)));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 		break;
@@ -1300,6 +1278,8 @@ impl_constructed (GObject *object)
 	RBShellPlayer *shell_player;
 	RhythmDBQueryModel *query_model;
 	GtkAction *action;
+	GSettings *settings;
+	int position;
 
 	RB_CHAIN_GOBJECT_METHOD (rb_podcast_source_parent_class, constructed, object);
 	source = RB_PODCAST_SOURCE (object);
@@ -1354,7 +1334,6 @@ impl_constructed (GObject *object)
 	/* set up posts view */
 	source->priv->posts = rb_entry_view_new (source->priv->db,
 						 G_OBJECT (shell_player),
-						 CONF_STATE_PODCAST_SORTING_POSTS,
 						 TRUE, FALSE);
 	g_object_unref (shell_player);
 
@@ -1450,16 +1429,11 @@ impl_constructed (GObject *object)
 					    0, NULL);
 
 	g_signal_connect_object (source->priv->posts,
-				 "sort-order-changed",
+				 "notify::sort-order",
 				 G_CALLBACK (podcast_posts_view_sort_order_changed_cb),
 				 source, 0);
 
 	g_signal_connect_object (source->priv->posts,
-				 "size_allocate",
-				 G_CALLBACK (paned_size_allocate_cb),
-				 source, 0);
-
-	g_signal_connect_object (source->priv->posts,
 				 "show_popup",
 				 G_CALLBACK (podcast_posts_show_popup_cb),
 				 source, 0);
@@ -1563,13 +1537,21 @@ impl_constructed (GObject *object)
 
 	gtk_box_pack_start (GTK_BOX (source->priv->vbox), source->priv->paned, TRUE, TRUE, 0);
 
-	/* different prefix for each source? */
-	source->priv->prefs_notify_id = eel_gconf_notification_add (CONF_STATE_PODCAST_PREFIX,
-								    (GConfClientNotifyFunc) podcast_pref_change_cb,
-								    source);
-
 	gtk_widget_show_all (GTK_WIDGET (source));
-	rb_podcast_source_state_prefs_sync (source);
+
+	g_object_get (source, "settings", &settings, NULL);
+
+	g_signal_connect_object (settings, "changed", G_CALLBACK (settings_changed_cb), source, 0);
+
+	position = g_settings_get_int (settings, PODCAST_PANED_POSITION);
+	gtk_paned_set_position (GTK_PANED (source->priv->paned), position);
+
+	rb_source_bind_settings (RB_SOURCE (source),
+				 GTK_WIDGET (source->priv->posts),
+				 source->priv->paned,
+				 GTK_WIDGET (source->priv->feeds));
+
+	g_object_unref (settings);
 
 	rb_podcast_source_do_query (source);
 }
@@ -1607,11 +1589,6 @@ impl_dispose (GObject *object)
 		source->priv->error_pixbuf = NULL;
 	}
 
-	if (source->priv->prefs_notify_id != 0) {
-		eel_gconf_notification_remove (source->priv->prefs_notify_id);
-		source->priv->prefs_notify_id = 0;
-	}
-
 	G_OBJECT_CLASS (rb_podcast_source_parent_class)->dispose (object);
 }
 
@@ -1681,7 +1658,6 @@ rb_podcast_source_class_init (RBPodcastSourceClass *klass)
 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
 	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_true_function;
 	source_class->impl_delete = impl_delete;
-	source_class->impl_get_browser_key  = impl_get_browser_key;
 	source_class->impl_get_entry_view = impl_get_entry_view;
 	source_class->impl_get_search_actions = impl_get_search_actions;
 	source_class->impl_handle_eos = impl_handle_eos;
@@ -1703,5 +1679,7 @@ rb_podcast_source_class_init (RBPodcastSourceClass *klass)
 							       "Base query for the source",
 							       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
+	g_object_class_override_property (object_class, PROP_SHOW_BROWSER, "show-browser");
+
 	g_type_class_add_private (klass, sizeof (RBPodcastSourcePrivate));
 }
diff --git a/rhythmbox.h b/rhythmbox.h
index 70226a8..2ed28c9 100644
--- a/rhythmbox.h
+++ b/rhythmbox.h
@@ -35,7 +35,6 @@
 #include <lib/rb-builder-helpers.h>
 #include <lib/rb-debug.h>
 #include <lib/rb-file-helpers.h>
-#include <lib/rb-preferences.h>
 #include <lib/rb-stock-icons.h>
 #include <lib/rb-util.h>
 #include <lib/libmediaplayerid/mediaplayerid.h>
diff --git a/rhythmdb/rhythmdb-monitor.c b/rhythmdb/rhythmdb-monitor.c
index 9484943..f8a979f 100644
--- a/rhythmdb/rhythmdb-monitor.c
+++ b/rhythmdb/rhythmdb-monitor.c
@@ -33,7 +33,6 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <glib/gi18n.h>
-#include <gconf/gconf-client.h>
 #include <gio/gio.h>
 
 #include "rb-debug.h"
@@ -42,8 +41,6 @@
 #include "rhythmdb-private.h"
 #include "rhythmdb-query-result-list.h"
 #include "rb-file-helpers.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 
 #if !GLIB_CHECK_VERSION(2,24,0)
 #define G_FILE_MONITOR_SEND_MOVED	0
@@ -160,15 +157,14 @@ monitor_entry_file (RhythmDBEntry *entry, RhythmDB *db)
 {
 	if (entry->type == RHYTHMDB_ENTRY_TYPE_SONG) {
 		const char *loc;
-		GSList *l;
+		int i;
 
 		loc = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 
 		/* don't add add monitor if it's in the library path */
-		for (l = db->priv->library_locations; l != NULL; l = g_slist_next (l)) {
-			if (g_str_has_prefix (loc, (const char*)l->data))
+		for (i = 0; db->priv->library_locations[i] != NULL; i++) {
+			if (g_str_has_prefix (loc, db->priv->library_locations[i]))
 				return;
-				
 		}
 		rhythmdb_monitor_uri_path (db, loc, NULL);
 	}
@@ -263,8 +259,12 @@ rhythmdb_start_monitoring (RhythmDB *db)
 	g_thread_create ((GThreadFunc)_monitor_entry_thread, g_object_ref (db), FALSE, NULL);
 
 	/* monitor all library locations */
-	if (db->priv->library_locations)
-		g_slist_foreach (db->priv->library_locations, (GFunc) monitor_library_directory, db);
+	if (db->priv->library_locations) {
+		int i;
+		for (i = 0; db->priv->library_locations[i] != NULL; i++) {
+			monitor_library_directory (db->priv->library_locations[i], db);
+		}
+	}
 }
 
 static void
@@ -305,18 +305,18 @@ rhythmdb_directory_change_cb (GFileMonitor *monitor,
 	switch (event_type) {
         case G_FILE_MONITOR_EVENT_CREATED:
 		{
-			GSList *cur;
 			gboolean in_library = FALSE;
+			int i;
 
-			if (!eel_gconf_get_boolean (CONF_MONITOR_LIBRARY))
+			if (!g_settings_get_boolean (db->priv->settings, "monitor-library"))
 				break;
 
 			if (rb_uri_is_hidden (canon_uri))
 				break;
 
 			/* ignore new files outside of the library locations */
-			for (cur = db->priv->library_locations; cur != NULL; cur = g_slist_next (cur)) {
-				if (g_str_has_prefix (canon_uri, cur->data)) {
+			for (i = 0; db->priv->library_locations[i] != NULL; i++) {
+				if (g_str_has_prefix (canon_uri, db->priv->library_locations[i])) {
 					in_library = TRUE;
 					break;
 				}
diff --git a/rhythmdb/rhythmdb-private.h b/rhythmdb/rhythmdb-private.h
index f38688f..c3168e4 100644
--- a/rhythmdb/rhythmdb-private.h
+++ b/rhythmdb/rhythmdb-private.h
@@ -147,10 +147,8 @@ struct _RhythmDBPrivate
 	GVolumeMonitor *volume_monitor;
 	GHashTable *monitored_directories;
 	GHashTable *changed_files;
-	guint library_location_notify_id;
 	guint changed_files_id;
-	GSList *library_locations;
-	guint monitor_notify_id;
+	char **library_locations;
 	GMutex *monitor_mutex;
 
 	gboolean dry_run;
@@ -189,6 +187,8 @@ struct _RhythmDBPrivate
 
 	gint next_entry_id;
 
+	GSettings *settings;
+
 	guint dbus_object_id;
 };
 
diff --git a/rhythmdb/rhythmdb-song-entry-types.c b/rhythmdb/rhythmdb-song-entry-types.c
index a28dd58..b028c97 100644
--- a/rhythmdb/rhythmdb-song-entry-types.c
+++ b/rhythmdb/rhythmdb-song-entry-types.c
@@ -28,11 +28,8 @@
 
 #include "config.h"
 
-#include <gconf/gconf-client.h>
-
 #include "rhythmdb-entry-type.h"
 #include "rhythmdb-private.h"
-#include "rb-preferences.h"
 #include "rb-util.h"
 #include "rb-debug.h"
 
@@ -87,16 +84,9 @@ check_entry_grace_period (RhythmDB *db, RhythmDBEntry *entry)
 	gulong last_seen;
 	gulong grace_period;
 	GError *error;
-	GConfClient *client;
 
-	client = gconf_client_get_default ();
-	if (client == NULL) {
-		return FALSE;
-	}
 	error = NULL;
-	grace_period = gconf_client_get_int (client, CONF_GRACE_PERIOD,
-					     &error);
-	g_object_unref (G_OBJECT (client));
+	grace_period = g_settings_get_int (db->priv->settings, "grace-period");
 	if (error != NULL) {
 		g_error_free (error);
 		return FALSE;
diff --git a/rhythmdb/rhythmdb.c b/rhythmdb/rhythmdb.c
index 3aeebea..70ad670 100644
--- a/rhythmdb/rhythmdb.c
+++ b/rhythmdb/rhythmdb.c
@@ -54,7 +54,6 @@
 #include <gio/gio.h>
 #include <gobject/gvaluecollector.h>
 #include <gdk/gdk.h>
-#include <gconf/gconf-client.h>
 
 
 #include "rb-marshal.h"
@@ -62,8 +61,6 @@
 #include "rb-debug.h"
 #include "rb-util.h"
 #include "rb-cut-and-paste-code.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 #include "rhythmdb-private.h"
 #include "rhythmdb-property-model.h"
 #include "rb-dialog.h"
@@ -268,10 +265,7 @@ static void rhythmdb_entry_set_mount_point (RhythmDB *db,
  					    const gchar *realuri);
 
 static gboolean rhythmdb_idle_save (RhythmDB *db);
-static void library_location_changed_cb (GConfClient *client,
-					  guint cnxn_id,
-					  GConfEntry *entry,
-					  RhythmDB *db);
+static void db_settings_changed_cb (GSettings *settings, const char *key, RhythmDB *db);
 static void rhythmdb_sync_library_location (RhythmDB *db);
 static void rhythmdb_entry_sync_mirrored (RhythmDBEntry *entry,
 					  guint propid);
@@ -280,10 +274,6 @@ static gboolean rhythmdb_entry_extra_metadata_accumulator (GSignalInvocationHint
 							   const GValue *handler_return,
 							   gpointer data);
 
-static void rhythmdb_monitor_library_changed_cb (GConfClient *client,
-						 guint cnxn_id,
-						 GConfEntry *entry,
-						 RhythmDB *db);
 static void rhythmdb_event_free (RhythmDB *db, RhythmDBEvent *event);
 static void rhythmdb_add_to_stat_list (RhythmDB *db,
 				       const char *uri,
@@ -694,6 +684,9 @@ rhythmdb_init (RhythmDB *db)
 
 	db->priv = RHYTHMDB_GET_PRIVATE (db);
 
+	db->priv->settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb");
+	g_signal_connect_object (db->priv->settings, "changed", G_CALLBACK (db_settings_changed_cb), db, 0);
+
 	db->priv->action_queue = g_async_queue_new ();
 	db->priv->event_queue = g_async_queue_new ();
 	db->priv->delayed_write_queue = g_async_queue_new ();
@@ -764,11 +757,6 @@ rhythmdb_init (RhythmDB *db)
 
 	rhythmdb_init_monitoring (db);
 
-	db->priv->monitor_notify_id = 
-		eel_gconf_notification_add (CONF_MONITOR_LIBRARY,
-					   (GConfClientNotifyFunc)rhythmdb_monitor_library_changed_cb,
-					   db);
-
 	rhythmdb_dbus_register (db);
 }
 
@@ -1028,15 +1016,9 @@ rhythmdb_shutdown (RhythmDB *db)
 	action->type = RHYTHMDB_ACTION_QUIT;
 	g_async_queue_push (db->priv->action_queue, action);
 
-	eel_gconf_notification_remove (db->priv->library_location_notify_id);
-	db->priv->library_location_notify_id = 0;
-	g_slist_foreach (db->priv->library_locations, (GFunc) g_free, NULL);
-	g_slist_free (db->priv->library_locations);
+	g_strfreev (db->priv->library_locations);
 	db->priv->library_locations = NULL;
 
-	eel_gconf_notification_remove (db->priv->monitor_notify_id);
-	db->priv->monitor_notify_id = 0;
-
 	/* abort all async io operations */
 	g_mutex_lock (db->priv->stat_mutex);
 	g_list_foreach (db->priv->outstanding_stats, (GFunc)_shutdown_foreach_swapped, db);
@@ -1059,7 +1041,6 @@ rhythmdb_shutdown (RhythmDB *db)
 	while ((action = g_async_queue_try_pop (db->priv->action_queue)) != NULL) {
 		rhythmdb_action_free (db, action);
 	}
-
 }
 
 static void
@@ -1109,6 +1090,11 @@ rhythmdb_dispose (GObject *object)
 		db->priv->exiting = NULL;
 	}
 
+	if (db->priv->settings != NULL) {
+		g_object_unref (db->priv->settings);
+		db->priv->settings = NULL;
+	}
+
 	G_OBJECT_CLASS (rhythmdb_parent_class)->dispose (object);
 }
 
@@ -2346,6 +2332,7 @@ rhythmdb_process_metadata_load (RhythmDB *db, RhythmDBEvent *event)
 	RhythmDBEntry *entry;
 	GValue value = {0,};
 	GTimeVal time;
+	gboolean monitor;
 
 	if (event->entry_type == NULL)
 		event->entry_type = RHYTHMDB_ENTRY_TYPE_SONG;
@@ -2467,7 +2454,8 @@ rhythmdb_process_metadata_load (RhythmDB *db, RhythmDBEvent *event)
 
 	/* monitor the file for changes */
 	/* FIXME: watch for errors */
-	if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY) && event->entry_type == RHYTHMDB_ENTRY_TYPE_SONG)
+	monitor = g_settings_get_boolean (db->priv->settings, "monitor-library");
+	if (monitor && event->entry_type == RHYTHMDB_ENTRY_TYPE_SONG)
 		rhythmdb_monitor_uri_path (db, rb_refstring_get (entry->location), NULL);
 
 	rhythmdb_commit_internal (db, FALSE, g_thread_self ());
@@ -4703,50 +4691,29 @@ rhythmdb_idle_save (RhythmDB *db)
 static void
 rhythmdb_sync_library_location (RhythmDB *db)
 {
-	gboolean reload = (db->priv->library_locations != NULL);
-
-	if (db->priv->library_location_notify_id == 0) {
-		db->priv->library_location_notify_id =
-			eel_gconf_notification_add (CONF_LIBRARY_LOCATION,
-						    (GConfClientNotifyFunc) library_location_changed_cb,
-						    db);
-	}
-
-	if (reload) {
+	if (db->priv->library_locations != NULL &&
+	    g_strv_length (db->priv->library_locations) > 0) {
 		rb_debug ("ending monitor of old library directories");
 
 		rhythmdb_stop_monitoring (db);
 
-		g_slist_foreach (db->priv->library_locations, (GFunc) g_free, NULL);
-		g_slist_free (db->priv->library_locations);
-		db->priv->library_locations = NULL;
+		g_strfreev (db->priv->library_locations);
 	}
 
-	if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY)) {
+	if (g_settings_get_boolean (db->priv->settings, "monitor-library")) {
 		rb_debug ("starting library monitoring");
-		db->priv->library_locations = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
+		db->priv->library_locations = g_settings_get_strv (db->priv->settings, "locations");
 
 		rhythmdb_start_monitoring (db);
 	}
 }
 
-static
-void rhythmdb_monitor_library_changed_cb (GConfClient *client,
-					  guint cnxn_id,
-					  GConfEntry *entry,
-					  RhythmDB *db)
-{
-	rb_debug ("'watch library' key changed");
-	rhythmdb_sync_library_location (db);
-}
-
 static void
-library_location_changed_cb (GConfClient *client,
-			     guint cnxn_id,
-			     GConfEntry *entry,
-			     RhythmDB *db)
+db_settings_changed_cb (GSettings *settings, const char *key, RhythmDB *db)
 {
-	rhythmdb_sync_library_location (db);
+	if (g_strcmp0 (key, "locations") == 0 || g_strcmp0 (key, "monitor-library") == 0) {
+		rhythmdb_sync_library_location (db);
+	}
 }
 
 char *
diff --git a/shell/main.c b/shell/main.c
index e4d806c..d590ffc 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -69,8 +69,6 @@
 #include "rb-file-helpers.h"
 #include "rb-stock-icons.h"
 #include "rb-util.h"
-#include "eel-gconf-extensions.h"
-#include "rb-util.h"
 #include "eggdesktopfile.h"
 #include "eggsmclient.h"
 
@@ -131,6 +129,8 @@ main (int argc, char **argv)
 
 #ifdef USE_UNINSTALLED_DIRS
 	desktop_file_path = g_build_filename (SHARE_UNINSTALLED_BUILDDIR, "rhythmbox.desktop", NULL);
+
+	g_setenv ("GSETTINGS_SCHEMA_DIR", SHARE_UNINSTALLED_BUILDDIR, TRUE);
 #else
 	desktop_file_path = g_build_filename (DATADIR, "applications", "rhythmbox.desktop", NULL);
 #endif
diff --git a/shell/rb-play-order-linear-loop.c b/shell/rb-play-order-linear-loop.c
index 479e67b..fd0d728 100644
--- a/shell/rb-play-order-linear-loop.c
+++ b/shell/rb-play-order-linear-loop.c
@@ -31,7 +31,6 @@
 
 #include "rb-debug.h"
 #include "rb-util.h"
-#include "eel-gconf-extensions.h"
 
 static void rb_linear_play_order_loop_class_init (RBLinearPlayOrderLoopClass *klass);
 
diff --git a/shell/rb-play-order-linear.c b/shell/rb-play-order-linear.c
index 1d9d081..b68092b 100644
--- a/shell/rb-play-order-linear.c
+++ b/shell/rb-play-order-linear.c
@@ -30,8 +30,6 @@
 #include "rb-play-order-linear.h"
 
 #include "rb-debug.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 
 static void rb_linear_play_order_class_init (RBLinearPlayOrderClass *klass);
 
diff --git a/shell/rb-play-order-queue.c b/shell/rb-play-order-queue.c
index b5bc0a1..946caf0 100644
--- a/shell/rb-play-order-queue.c
+++ b/shell/rb-play-order-queue.c
@@ -30,8 +30,6 @@
 #include "rb-play-order-queue.h"
 
 #include "rb-debug.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 
 static void rb_queue_play_order_class_init (RBQueuePlayOrderClass *klass);
 
diff --git a/shell/rb-play-order-shuffle.c b/shell/rb-play-order-shuffle.c
index 1e9c9d9..3635797 100644
--- a/shell/rb-play-order-shuffle.c
+++ b/shell/rb-play-order-shuffle.c
@@ -35,7 +35,6 @@
 #include "rb-history.h"
 #include "rb-debug.h"
 #include "rb-util.h"
-#include "eel-gconf-extensions.h"
 
 static void rb_shuffle_play_order_class_init (RBShufflePlayOrderClass *klass);
 static void rb_shuffle_play_order_init (RBShufflePlayOrder *sorder);
diff --git a/shell/rb-play-order.c b/shell/rb-play-order.c
index 25d6bce..85d1a32 100644
--- a/shell/rb-play-order.c
+++ b/shell/rb-play-order.c
@@ -36,7 +36,6 @@
 
 #include "rb-shell-player.h"
 #include "rb-debug.h"
-#include "rb-preferences.h"
 #include "rb-marshal.h"
 
 /**
diff --git a/shell/rb-play-order.h b/shell/rb-play-order.h
index 8bb0403..d25845f 100644
--- a/shell/rb-play-order.h
+++ b/shell/rb-play-order.h
@@ -37,7 +37,7 @@
  * defined here.
  *
  * When you add a new play order, remember to update the long description of
- * the state/play_order key in data/rhythmbox.schemas and to add the
+ * the state/play_order key in data/org.gnome.rhythmbox.gschema.xml and to add the
  * appropriate code to rb_play_order_new().
  */
 
diff --git a/shell/rb-playlist-manager.c b/shell/rb-playlist-manager.c
index 1a7fef2..db8cee3 100644
--- a/shell/rb-playlist-manager.c
+++ b/shell/rb-playlist-manager.c
@@ -58,7 +58,6 @@
 #include "rb-dialog.h"
 #include "rhythmdb.h"
 #include "rb-stock-icons.h"
-#include "eel-gconf-extensions.h"
 #include "rb-builder-helpers.h"
 #include "rb-util.h"
 
diff --git a/shell/rb-plugin.c b/shell/rb-plugin.c
index 2b84291..009dd5a 100644
--- a/shell/rb-plugin.c
+++ b/shell/rb-plugin.c
@@ -46,7 +46,6 @@
 #include "rb-util.h"
 #include "rb-debug.h"
 #include "rb-file-helpers.h"
-#include "eel-gconf-extensions.h"
 
 G_DEFINE_TYPE (RBPlugin, rb_plugin, G_TYPE_OBJECT)
 #define RB_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_PLUGIN, RBPluginPrivate))
@@ -249,19 +248,16 @@ rb_plugin_create_configure_dialog (RBPlugin *plugin)
 GList *
 rb_get_plugin_paths (void)
 {
-	GList *paths;
+	GSettings *settings;
+	GList *paths = NULL;
 	char  *path;
 
-	paths = NULL;
-
-	if (!eel_gconf_get_boolean (CONF_PLUGIN_DISABLE_USER)) {
-		/* deprecated path, should be removed some time in the future */
-		path = g_build_filename (rb_dot_dir (), "plugins", NULL);
-		paths = g_list_prepend (paths, path);
-
+	settings = g_settings_new ("org.gnome.rhythmbox.plugins");
+	if (g_settings_get_boolean (settings, "no-user-plugins") == FALSE) {
 		path = g_build_filename (rb_user_data_dir (), "plugins", NULL);
 		paths = g_list_prepend (paths, path);
 	}
+	g_object_unref (settings);
 
 #ifdef USE_UNINSTALLED_DIRS
 	path = g_build_filename (UNINSTALLED_PLUGINS_LOCATION, NULL);
diff --git a/shell/rb-plugins-engine.c b/shell/rb-plugins-engine.c
index 77b1a42..492c151 100644
--- a/shell/rb-plugins-engine.c
+++ b/shell/rb-plugins-engine.c
@@ -38,9 +38,7 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
-#include "eel-gconf-extensions.h"
 #include "rb-file-helpers.h"
-#include "rb-preferences.h"
 #include "rb-util.h"
 #include "rb-plugin.h"
 #include "rb-debug.h"
@@ -87,20 +85,13 @@ struct _RBPluginInfo
 };
 
 static void rb_plugin_info_free (RBPluginInfo *info);
-static void rb_plugins_engine_plugin_active_cb (GConfClient *client,
-						guint cnxn_id,
-						GConfEntry *entry,
-						RBPluginInfo *info);
-static void rb_plugins_engine_plugin_visible_cb (GConfClient *client,
-						 guint cnxn_id,
-						 GConfEntry *entry,
-						 RBPluginInfo *info);
 static gboolean rb_plugins_engine_activate_plugin_real (RBPluginInfo *info,
 							RBShell *shell);
 static void rb_plugins_engine_deactivate_plugin_real (RBPluginInfo *info,
 						      RBShell *shell);
 
 static GHashTable *rb_plugins = NULL;
+static GSettings *rb_plugin_settings = NULL;
 guint garbage_collect_id = 0;
 RBShell *rb_plugins_shell = NULL;
 
@@ -264,9 +255,10 @@ rb_plugins_engine_load_cb (GFile *file, gboolean dir, gpointer userdata)
 {
 	char *plugin_path;
 	RBPluginInfo *info;
-	char *key_name;
 	gboolean activate;
 	const char *sep;
+	char **active_plugins;
+	char **hidden_plugins;
 
 	plugin_path = g_file_get_path (file);
 
@@ -304,19 +296,13 @@ rb_plugins_engine_load_cb (GFile *file, gboolean dir, gpointer userdata)
 	g_hash_table_insert (rb_plugins, info->location, info);
 	rb_debug ("Plugin %s loaded", info->name);
 
-	key_name = g_strdup_printf (CONF_PLUGIN_ACTIVE_KEY, info->location);
-	info->active_notification_id = eel_gconf_notification_add (key_name,
-								   (GConfClientNotifyFunc)rb_plugins_engine_plugin_active_cb,
-								   info);
-	activate = eel_gconf_get_boolean (key_name);
-	g_free (key_name);
+	active_plugins = g_settings_get_strv (rb_plugin_settings, "active-plugins");
+	activate = rb_str_in_strv (info->location, (const char **)active_plugins);
+	g_strfreev (active_plugins);
 
-	key_name = g_strdup_printf (CONF_PLUGIN_HIDDEN_KEY, info->location);
-	info->visible_notification_id = eel_gconf_notification_add (key_name,
-								    (GConfClientNotifyFunc)rb_plugins_engine_plugin_visible_cb,
-								    info);
-	info->visible = !eel_gconf_get_boolean (key_name);
-	g_free (key_name);
+	hidden_plugins = g_settings_get_strv (rb_plugin_settings, "hidden-plugins");
+	info->visible = (rb_str_in_strv (info->location, (const char **)hidden_plugins) == FALSE);
+	g_strfreev (hidden_plugins);
 
 	if (activate)
 		rb_plugins_engine_activate_plugin (info);
@@ -372,6 +358,8 @@ rb_plugins_engine_init (RBShell *shell)
 
 	rb_plugins = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)rb_plugin_info_free);
 
+	rb_plugin_settings = g_settings_new ("org.gnome.rhythmbox.plugins");
+
 	rb_plugins_shell = shell;
 	g_object_ref (G_OBJECT (rb_plugins_shell));
 #ifdef ENABLE_PYTHON
@@ -410,9 +398,6 @@ rb_plugin_info_free (RBPluginInfo *info)
 		 * a type module */
 	}
 
-	eel_gconf_notification_remove (info->active_notification_id);
-	eel_gconf_notification_remove (info->visible_notification_id);
-
 	g_free (info->file);
 	g_free (info->location);
 	g_free (info->name);
@@ -534,6 +519,39 @@ rb_plugins_engine_activate_plugin_real (RBPluginInfo *info, RBShell *shell)
 	return res;
 }
 
+static void
+modify_active_plugin_list (RBPluginInfo *info, gboolean add)
+{
+	GVariant *active;
+	GVariantIter *iter;
+	GVariantBuilder *builder;
+	const char *name;
+	gboolean present = FALSE;
+
+	builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+	active = g_settings_get_value (rb_plugin_settings, "active-plugins");
+	iter = g_variant_iter_new (active);
+	while (g_variant_iter_loop (iter, "s", &name)) {
+		if (g_strcmp0 (info->location, name) == 0) {
+			present = TRUE;
+		}
+
+		if (add || g_strcmp0 (info->location, name) != 0) {
+			g_variant_builder_add (builder, "s", name);
+		}
+	}
+	g_variant_iter_free (iter);
+
+	if (add && (present == FALSE)) {
+		g_variant_builder_add (builder, "s", info->location);
+	}
+
+	g_settings_set_value (rb_plugin_settings, "active-plugins", g_variant_builder_end (builder));
+	g_variant_builder_unref (builder);
+	g_variant_unref (active);
+}
+
 gboolean
 rb_plugins_engine_activate_plugin (RBPluginInfo *info)
 {
@@ -547,17 +565,14 @@ rb_plugins_engine_activate_plugin (RBPluginInfo *info)
 	ret = rb_plugins_engine_activate_plugin_real (info, rb_plugins_shell);
 
 	if (info->visible != FALSE || ret != FALSE) {
-		char *key_name;
-
-		key_name = g_strdup_printf (CONF_PLUGIN_ACTIVE_KEY, info->location);
-		eel_gconf_set_boolean (key_name, ret);
-		g_free (key_name);
+		modify_active_plugin_list (info, FALSE);
 	}
         info->active = ret;
 
-        if (ret != FALSE)
+        if (ret != FALSE) {
+		modify_active_plugin_list (info, TRUE);
                 return TRUE;
-
+	}
 
 	rb_error_dialog (NULL, _("Plugin Error"), _("Unable to activate plugin %s"), info->name);
 
@@ -573,8 +588,6 @@ rb_plugins_engine_deactivate_plugin_real (RBPluginInfo *info, RBShell *shell)
 gboolean
 rb_plugins_engine_deactivate_plugin (RBPluginInfo *info)
 {
-	char *key_name;
-
 	g_return_val_if_fail (info != NULL, FALSE);
 
 	if (!info->active)
@@ -585,10 +598,7 @@ rb_plugins_engine_deactivate_plugin (RBPluginInfo *info)
 	/* Update plugin state */
 	info->active = FALSE;
 
-	key_name = g_strdup_printf (CONF_PLUGIN_ACTIVE_KEY, info->location);
-	eel_gconf_set_boolean (key_name, FALSE);
-	g_free (key_name);
-
+	modify_active_plugin_list (info, FALSE);
 	return TRUE;
 }
 
@@ -650,28 +660,6 @@ rb_plugins_engine_configure_plugin (RBPluginInfo *info,
 	gtk_widget_show (conf_dlg);
 }
 
-static void
-rb_plugins_engine_plugin_active_cb (GConfClient *client,
-				    guint cnxn_id,
-				    GConfEntry *entry,
-				    RBPluginInfo *info)
-{
-	if (gconf_value_get_bool (entry->value)) {
-		rb_plugins_engine_activate_plugin (info);
-	} else {
-		rb_plugins_engine_deactivate_plugin (info);
-	}
-}
-
-static void
-rb_plugins_engine_plugin_visible_cb (GConfClient *client,
-				     guint cnxn_id,
-				     GConfEntry *entry,
-				     RBPluginInfo *info)
-{
-	info->visible = !gconf_value_get_bool (entry->value);
-}
-
 const gchar *
 rb_plugins_engine_get_plugin_name (RBPluginInfo *info)
 {
diff --git a/shell/rb-shell-player.c b/shell/rb-shell-player.c
index c3edf76..a388152 100644
--- a/shell/rb-shell-player.c
+++ b/shell/rb-shell-player.c
@@ -69,14 +69,12 @@
 #include "rb-file-helpers.h"
 #include "rb-cut-and-paste-code.h"
 #include "rb-dialog.h"
-#include "rb-preferences.h"
 #include "rb-debug.h"
 #include "rb-player.h"
 #include "rb-header.h"
 #include "totem-pl-parser.h"
 #include "rb-metadata.h"
 #include "rb-library-source.h"
-#include "eel-gconf-extensions.h"
 #include "rb-util.h"
 #include "rb-play-order.h"
 #include "rb-statusbar.h"
@@ -129,8 +127,6 @@ static void rb_shell_player_shuffle_changed_cb (GtkAction *action,
 						RBShellPlayer *player);
 static void rb_shell_player_repeat_changed_cb (GtkAction *action,
 					       RBShellPlayer *player);
-static void rb_shell_player_view_song_position_slider_changed_cb (GtkAction *action,
-								  RBShellPlayer *player);
 static void rb_shell_player_set_playing_source_internal (RBShellPlayer *player,
 							 RBSource *source,
 							 gboolean sync_entry_view);
@@ -155,8 +151,6 @@ static void playing_stream_cb (RBPlayer *player, RhythmDBEntry *entry, RBShellPl
 static void player_image_cb (RBPlayer *player, RhythmDBEntry *entry, GdkPixbuf *image, RBShellPlayer *shell_player);
 static void rb_shell_player_error (RBShellPlayer *player, gboolean async, const GError *err);
 
-static void rb_shell_player_set_play_order (RBShellPlayer *player,
-					    const gchar *new_val);
 static void rb_shell_player_play_order_update_cb (RBPlayOrder *porder,
 						  gboolean has_next,
 						  gboolean has_previous,
@@ -164,17 +158,11 @@ static void rb_shell_player_play_order_update_cb (RBPlayOrder *porder,
 
 static void rb_shell_player_sync_play_order (RBShellPlayer *player);
 static void rb_shell_player_sync_control_state (RBShellPlayer *player);
-static void rb_shell_player_sync_song_position_slider_visibility (RBShellPlayer *player);
 static void rb_shell_player_sync_buttons (RBShellPlayer *player);
 
-static void gconf_play_order_changed (GConfClient *client,guint cnxn_id,
-				      GConfEntry *entry, RBShellPlayer *player);
-static void gconf_song_position_slider_visibility_changed (GConfClient *client, guint cnxn_id,
-							   GConfEntry *entry, RBShellPlayer *player);
-static void gconf_track_transition_time_changed (GConfClient *client, guint cnxn_id,
-						 GConfEntry *entry, RBShellPlayer *player);
-static void gconf_network_buffer_size_changed (GConfClient *client, guint cnxn_id,
-					       GConfEntry *entry, RBShellPlayer *player);
+static void player_settings_changed_cb (GSettings *settings,
+					const char *key,
+					RBShellPlayer *player);
 static void rb_shell_player_playing_changed_cb (RBShellPlayer *player,
 						GParamSpec *arg1,
 						gpointer user_data);
@@ -202,7 +190,7 @@ static void rb_shell_player_volume_changed_cb (RBPlayer *player,
 
 
 typedef struct {
-	/** Value of the state/play-order gconf key */
+	/** Value of the state/play-order setting */
 	char *name;
 	/** Contents of the play order dropdown; should be gettext()ed before use. */
 	char *description;
@@ -216,8 +204,6 @@ static void _play_order_description_free (RBPlayOrderDescription *order);
 
 static RBPlayOrder* rb_play_order_new (RBShellPlayer *player, const char* porder_name);
 
-#define CONF_STATE		CONF_PREFIX "/state"
-
 /* number of nanoseconds before the end of a track to start prerolling the next */
 #define PREROLL_TIME		RB_PLAYER_SECOND
 
@@ -260,10 +246,8 @@ struct RBShellPlayerPrivate
 	RBHeader *header_widget;
 	RBStatusbar *statusbar_widget;
 
-	guint gconf_play_order_id;
-	guint gconf_song_position_slider_visibility_id;
-	guint gconf_track_transition_time_id;
-	guint gconf_network_buffer_size_id;
+	GSettings *settings;
+	GSettings *ui_settings;
 
 	gboolean mute;
 	float volume;
@@ -289,6 +273,7 @@ enum
 	PROP_QUEUE_ONLY,
 	PROP_PLAYING_FROM_QUEUE,
 	PROP_PLAYER,
+	PROP_MUTE
 };
 
 enum
@@ -334,7 +319,7 @@ static GtkToggleActionEntry rb_shell_player_toggle_entries [] =
 	  G_CALLBACK (rb_shell_player_repeat_changed_cb) },
 	{ "ViewSongPositionSlider", NULL, N_("_Song Position Slider"), NULL,
 	  N_("Change the visibility of the song position slider"),
-	  G_CALLBACK (rb_shell_player_view_song_position_slider_changed_cb), TRUE },
+	  NULL, TRUE },
 };
 static guint rb_shell_player_n_toggle_entries = G_N_ELEMENTS (rb_shell_player_toggle_entries);
 
@@ -507,6 +492,18 @@ rb_shell_player_class_init (RBShellPlayerClass *klass)
 							      "RBStatusbar object",
 							      RB_TYPE_STATUSBAR,
 							      G_PARAM_READWRITE));
+	/**
+	 * RBShellPlayer:mute:
+	 *
+	 * Whether playback is currently muted.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_MUTE,
+					 g_param_spec_boolean ("mute",
+							       "mute",
+							       "Whether playback is muted",
+							       FALSE,
+							       G_PARAM_READWRITE));
 
 	/**
 	 * RBShellPlayer::window-title-changed:
@@ -672,14 +669,6 @@ rb_shell_player_constructed (GObject *object)
 
 	player = RB_SHELL_PLAYER (object);
 
-	player->priv->header_widget = rb_header_new (player, player->priv->db);
-	gtk_widget_show (GTK_WIDGET (player->priv->header_widget));
-	gtk_box_pack_start (GTK_BOX (player), GTK_WIDGET (player->priv->header_widget), TRUE, TRUE, 0);
-	g_signal_connect_object (player->priv->header_widget,
-				 "notify::slider-dragging",
-				 G_CALLBACK (rb_shell_player_slider_dragging_cb),
-				 player, 0);
-
 	gtk_action_group_add_actions (player->priv->actiongroup,
 				      rb_shell_player_actions,
 				      rb_shell_player_n_actions,
@@ -689,6 +678,25 @@ rb_shell_player_constructed (GObject *object)
 					     rb_shell_player_n_toggle_entries,
 					     player);
 
+	player_settings_changed_cb (player->priv->settings, "transition-time", player);
+	player_settings_changed_cb (player->priv->settings, "play-order", player);
+
+	player->priv->header_widget = rb_header_new (player, player->priv->db);
+	gtk_widget_show (GTK_WIDGET (player->priv->header_widget));
+	gtk_box_pack_start (GTK_BOX (player), GTK_WIDGET (player->priv->header_widget), TRUE, TRUE, 0);
+	g_signal_connect_object (player->priv->header_widget,
+				 "notify::slider-dragging",
+				 G_CALLBACK (rb_shell_player_slider_dragging_cb),
+				 player, 0);
+	g_settings_bind (player->priv->ui_settings, "show-song-position-slider",
+			 player->priv->header_widget, "show-position-slider",
+			 G_SETTINGS_BIND_INVERT_BOOLEAN | G_SETTINGS_BIND_NO_SENSITIVITY);
+	action = gtk_action_group_get_action (player->priv->actiongroup,
+					      "ViewSongPositionSlider");
+	g_settings_bind (player->priv->ui_settings, "show-song-position-slider",
+			 action, "active",
+			 G_SETTINGS_BIND_INVERT_BOOLEAN | G_SETTINGS_BIND_NO_SENSITIVITY);
+
 	action = gtk_action_group_get_action (player->priv->actiongroup,
 					      "ControlPlay");
 	g_object_set (action, "is-important", TRUE, NULL);
@@ -700,8 +708,6 @@ rb_shell_player_constructed (GObject *object)
 	rb_shell_player_sync_volume (player, FALSE, TRUE);
 	player->priv->syncing_state = FALSE;
 
-	rb_shell_player_sync_song_position_slider_visibility (player);
-
 	g_signal_connect (player,
 			  "notify::playing",
 			  G_CALLBACK (rb_shell_player_playing_changed_cb),
@@ -972,6 +978,13 @@ rb_shell_player_init (RBShellPlayer *player)
 
 	player->priv = RB_SHELL_PLAYER_GET_PRIVATE (player);
 
+	player->priv->settings = g_settings_new ("org.gnome.rhythmbox.player");
+	player->priv->ui_settings = g_settings_new ("org.gnome.rhythmbox");
+	g_signal_connect_object (player->priv->settings,
+				 "changed",
+				 G_CALLBACK (player_settings_changed_cb),
+				 player, 0);
+
 	player->priv->play_orders = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)_play_order_description_free);
 	
 	rb_shell_player_add_play_order (player, "linear", N_("Linear"),
@@ -991,7 +1004,7 @@ rb_shell_player_init (RBShellPlayer *player)
 	rb_shell_player_add_play_order (player, "queue", N_("Linear, removing entries once played"),
 					RB_TYPE_QUEUE_PLAY_ORDER, TRUE);
 
-	player->priv->mmplayer = rb_player_new (eel_gconf_get_boolean (CONF_PLAYER_USE_XFADE_BACKEND),
+	player->priv->mmplayer = rb_player_new (g_settings_get_boolean (player->priv->settings, "use-xfade-backend"),
 					        &error);
 	if (error != NULL) {
 		GtkWidget *dialog;
@@ -1055,31 +1068,10 @@ rb_shell_player_init (RBShellPlayer *player)
 		g_object_unref (monitor);	/* hmm */
 	}
 
-	player->priv->gconf_play_order_id =
-		eel_gconf_notification_add (CONF_STATE_PLAY_ORDER,
-					    (GConfClientNotifyFunc)gconf_play_order_changed,
-					    player);
-
-	player->priv->volume = eel_gconf_get_float (CONF_STATE_VOLUME);
-
-	player->priv->track_transition_time = eel_gconf_get_float (CONF_PLAYER_TRANSITION_TIME) * RB_PLAYER_SECOND;
-	player->priv->gconf_track_transition_time_id =
-		eel_gconf_notification_add (CONF_PLAYER_TRANSITION_TIME,
-					    (GConfClientNotifyFunc) gconf_track_transition_time_changed,
-					    player);
-	player->priv->gconf_network_buffer_size_id =
-		eel_gconf_notification_add (CONF_PLAYER_NETWORK_BUFFER_SIZE,
-					    (GConfClientNotifyFunc) gconf_network_buffer_size_changed,
-					    player);
-	gconf_network_buffer_size_changed (NULL, 0, NULL, player);
+	player->priv->volume = g_settings_get_double (player->priv->settings, "volume");
 
 	g_signal_connect (player, "notify::playing",
 			  G_CALLBACK (reemit_playing_signal), NULL);
-
-	player->priv->gconf_song_position_slider_visibility_id =
-		eel_gconf_notification_add (CONF_UI_SONG_POSITION_SLIDER_HIDDEN,
-					    (GConfClientNotifyFunc) gconf_song_position_slider_visibility_changed,
-					    player);
 }
 
 static void
@@ -1242,9 +1234,19 @@ rb_shell_player_dispose (GObject *object)
 
 	g_return_if_fail (player->priv != NULL);
 
-	if (player->priv->gconf_play_order_id != 0) {
-		eel_gconf_notification_remove (player->priv->gconf_play_order_id);
-		player->priv->gconf_play_order_id = 0;
+	if (player->priv->ui_settings != NULL) {
+		g_object_unref (player->priv->ui_settings);
+		player->priv->ui_settings = NULL;
+	}
+
+	if (player->priv->settings != NULL) {
+		/* hm, is this really the place to do this? */
+		g_settings_set_double (player->priv->settings,
+				       "volume",
+				       player->priv->volume);
+
+		g_object_unref (player->priv->settings);
+		player->priv->settings = NULL;
 	}
 
 	if (player->priv->mmplayer != NULL) {
@@ -1289,8 +1291,6 @@ rb_shell_player_finalize (GObject *object)
 
 	g_hash_table_destroy (player->priv->play_orders);
 	
-	eel_gconf_set_float (CONF_STATE_VOLUME, player->priv->volume);
-
 	G_OBJECT_CLASS (rb_shell_player_parent_class)->finalize (object);
 }
 
@@ -1316,8 +1316,9 @@ rb_shell_player_set_property (GObject *object,
 		player->priv->actiongroup = g_value_get_object (value);
 		break;
 	case PROP_PLAY_ORDER:
-		eel_gconf_set_string (CONF_STATE_PLAY_ORDER,
-				      g_value_get_string (value));
+		g_settings_set_string (player->priv->settings,
+				       "play-order",
+				       g_value_get_string (value));
 		break;
 	case PROP_VOLUME:
 		player->priv->volume = g_value_get_float (value);
@@ -1332,6 +1333,9 @@ rb_shell_player_set_property (GObject *object,
 	case PROP_QUEUE_ONLY:
 		player->priv->queue_only = g_value_get_boolean (value);
 		break;
+	case PROP_MUTE:
+		player->priv->mute = g_value_get_boolean (value);
+		rb_shell_player_sync_volume (player, FALSE, TRUE);
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1361,8 +1365,9 @@ rb_shell_player_get_property (GObject *object,
 		break;
 	case PROP_PLAY_ORDER:
 	{
-		char *play_order = eel_gconf_get_string (CONF_STATE_PLAY_ORDER);
-		if (!play_order)
+		char *play_order = g_settings_get_string (player->priv->settings,
+							  "play-order");
+		if (play_order == NULL)
 			play_order = g_strdup ("linear");
 		g_value_take_string (value, play_order);
 		break;
@@ -1391,6 +1396,9 @@ rb_shell_player_get_property (GObject *object,
 	case PROP_PLAYER:
 		g_value_set_object (value, player->priv->mmplayer);
 		break;
+	case PROP_MUTE:
+		g_value_set_boolean (value, player->priv->mute);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1793,18 +1801,22 @@ rb_shell_player_set_playing_entry (RBShellPlayer *player,
 }
 
 static void
-gconf_play_order_changed (GConfClient *client,
-			  guint cnxn_id,
-			  GConfEntry *entry,
-			  RBShellPlayer *player)
+player_settings_changed_cb (GSettings *settings, const char *key, RBShellPlayer *player)
 {
-	rb_debug ("gconf play order changed");
-	player->priv->syncing_state = TRUE;
-	rb_shell_player_sync_play_order (player);
-	rb_shell_player_sync_buttons (player);
-	rb_shell_player_sync_control_state (player);
-	g_object_notify (G_OBJECT (player), "play-order");
-	player->priv->syncing_state = FALSE;
+	if (g_strcmp0 (key, "play-order") == 0) {
+		rb_debug ("play order setting changed");
+		player->priv->syncing_state = TRUE;
+		rb_shell_player_sync_play_order (player);
+		rb_shell_player_sync_buttons (player);
+		rb_shell_player_sync_control_state (player);
+		g_object_notify (G_OBJECT (player), "play-order");
+		player->priv->syncing_state = FALSE;
+	} else if (g_strcmp0 (key, "transition-time") == 0) {
+		double newtime;
+		rb_debug ("track transition time changed");
+		newtime = g_settings_get_double (player->priv->settings, "transition-time");
+		player->priv->track_transition_time = newtime * RB_PLAYER_SECOND;
+	}
 }
 
 /**
@@ -1825,12 +1837,7 @@ rb_shell_player_get_playback_state (RBShellPlayer *player,
 	int i, j;
 	char *play_order;
 
-	play_order = eel_gconf_get_string (CONF_STATE_PLAY_ORDER);
-	if (!play_order) {
-		g_warning (CONF_STATE_PLAY_ORDER " gconf key not found!");
-		return FALSE;
-	}
-
+	play_order = g_settings_get_string (player->priv->settings, "play-order");
 	for (i = 0; i < G_N_ELEMENTS(state_to_play_order); i++)
 		for (j = 0; j < G_N_ELEMENTS(state_to_play_order[0]); j++)
 			if (!strcmp (play_order, state_to_play_order[i][j]))
@@ -1850,20 +1857,6 @@ found:
 	return TRUE;
 }
 
-static void
-rb_shell_player_set_play_order (RBShellPlayer *player,
-				const gchar *new_val)
-{
-	char *old_val;
-
-	g_object_get (player, "play-order", &old_val, NULL);
-	if (strcmp (old_val, new_val) != 0) {
-		/* The notify signal will be emitted by the gconf notifier */
-		eel_gconf_set_string (CONF_STATE_PLAY_ORDER, new_val);
-	}
-	g_free (old_val);
-}
-
 /**
  * rb_shell_player_set_playback_state:
  * @player: the #RBShellPlayer
@@ -1878,7 +1871,7 @@ rb_shell_player_set_playback_state (RBShellPlayer *player,
 				    gboolean repeat)
 {
 	const char *neworder = state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
-	rb_shell_player_set_play_order (player, neworder);
+	g_settings_set_string (player->priv->settings, "play-order", neworder);
 }
 
 static void
@@ -1888,12 +1881,7 @@ rb_shell_player_sync_play_order (RBShellPlayer *player)
 	RhythmDBEntry *playing_entry = NULL;
 	RBSource *source;
 
-	new_play_order = eel_gconf_get_string (CONF_STATE_PLAY_ORDER);
-	if (new_play_order == NULL) {
-		g_warning (CONF_STATE_PLAY_ORDER " gconf key not found!");
-		new_play_order = g_strdup ("linear");
-	}
-
+	new_play_order = g_settings_get_string (player->priv->settings, "play-order");
 	if (player->priv->play_order != NULL) {
 		playing_entry = rb_play_order_get_playing_entry (player->priv->play_order);
 		g_signal_handlers_disconnect_by_func (player->priv->play_order,
@@ -1969,23 +1957,6 @@ rb_shell_player_play_order_update_cb (RBPlayOrder *porder,
 	g_object_set (action, "sensitive", have_next, NULL);
 }
 
-static void
-rb_shell_player_sync_song_position_slider_visibility (RBShellPlayer *player)
-{
-	gboolean visible;
-	GtkAction *action;
-
-	visible = !eel_gconf_get_boolean (CONF_UI_SONG_POSITION_SLIDER_HIDDEN);
-
-	rb_header_set_show_position_slider (player->priv->header_widget,
-					    visible);
-
-	action = gtk_action_group_get_action (player->priv->actiongroup,
-					      "ViewSongPositionSlider");
-	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-				      visible);
-}
-
 /**
  * rb_shell_player_jump_to_current:
  * @player: the #RBShellPlayer
@@ -2521,8 +2492,9 @@ rb_shell_player_sync_volume (RBShellPlayer *player,
 				      player->priv->mute ? 0.0 : player->priv->volume);
 	}
 
-	eel_gconf_set_float (CONF_STATE_VOLUME, player->priv->volume);
-
+	g_settings_set_double (player->priv->settings,
+			       "volume",
+			       player->priv->volume);
 
 	entry = rb_shell_player_get_playing_entry (player);
 	if (entry != NULL) {
@@ -2534,19 +2506,6 @@ rb_shell_player_sync_volume (RBShellPlayer *player,
 }
 
 /**
- * rb_shell_player_toggle_mute:
- * @player: the #RBShellPlayer
- *
- * Toggles the mute setting on the player.
- */
-void
-rb_shell_player_toggle_mute (RBShellPlayer *player)
-{
-	player->priv->mute = !player->priv->mute;
-	rb_shell_player_sync_volume (player, FALSE, TRUE);
-}
-
-/**
  * rb_shell_player_set_volume:
  * @player: the #RBShellPlayer
  * @volume: the volume level (between 0 and 1)
@@ -2655,16 +2614,6 @@ rb_shell_player_get_mute (RBShellPlayer *player,
 }
 
 static void
-gconf_song_position_slider_visibility_changed (GConfClient *client,
-					       guint cnxn_id,
-					       GConfEntry *entry,
-					       RBShellPlayer *player)
-{
-	rb_debug ("song position slider visibility visibility changed");
-	rb_shell_player_sync_song_position_slider_visibility (player);
-}
-
-static void
 rb_shell_player_shuffle_changed_cb (GtkAction *action,
 				    RBShellPlayer *player)
 {
@@ -2681,7 +2630,7 @@ rb_shell_player_shuffle_changed_cb (GtkAction *action,
 
 	shuffle = !shuffle;
 	neworder = state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
-	rb_shell_player_set_play_order (player, neworder);
+	g_settings_set_string (player->priv->settings, "play-order", neworder);
 }
 
 static void
@@ -2700,15 +2649,7 @@ rb_shell_player_repeat_changed_cb (GtkAction *action,
 
 	repeat = !repeat;
 	neworder = state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
-	rb_shell_player_set_play_order (player, neworder);
-}
-
-static void
-rb_shell_player_view_song_position_slider_changed_cb (GtkAction *action,
-						      RBShellPlayer *player)
-{
-	eel_gconf_set_boolean (CONF_UI_SONG_POSITION_SLIDER_HIDDEN,
-			       !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+	g_settings_set_string (player->priv->settings, "play-order", neworder);
 }
 
 static void
@@ -3060,7 +3001,7 @@ rb_shell_player_sync_buttons (RBShellPlayer *player)
 
 	rb_debug ("syncing with source %p", source);
 
-        not_small = !eel_gconf_get_boolean (CONF_UI_SMALL_DISPLAY);
+        not_small = !g_settings_get_boolean (player->priv->ui_settings, "small-display");
 	action = gtk_action_group_get_action (player->priv->actiongroup,
 					      "ViewJumpToPlaying");
 	g_object_set (action, "sensitive", entry != NULL && not_small, NULL);
@@ -3299,9 +3240,11 @@ rb_shell_player_get_playing (RBShellPlayer *player,
 char *
 rb_shell_player_get_playing_time_string (RBShellPlayer *player)
 {
+	gboolean elapsed;
+	elapsed = g_settings_get_boolean (player->priv->ui_settings, "time-display");
 	return rb_make_elapsed_time_string (player->priv->elapsed,
 					    rb_shell_player_get_playing_song_duration (player),
-					    !eel_gconf_get_boolean (CONF_UI_TIME_DISPLAY));
+					    elapsed);
 }
 
 /**
@@ -3905,39 +3848,6 @@ rb_shell_player_error_get_type (void)
 }
 
 static void
-gconf_track_transition_time_changed (GConfClient *client,
-				     guint cnxn_id,
-				     GConfEntry *entry,
-				     RBShellPlayer *player)
-{
-	rb_debug ("track transition time changed");
-	player->priv->track_transition_time = eel_gconf_get_float (CONF_PLAYER_TRANSITION_TIME) * RB_PLAYER_SECOND;
-}
-
-static void
-gconf_network_buffer_size_changed (GConfClient *client,
-				   guint cnxn_id,
-				   GConfEntry *entry,
-				   RBShellPlayer *player)
-{
-	guint buffer_size;
-
-	if (player->priv->mmplayer == NULL
-	    || (g_object_class_find_property (G_OBJECT_GET_CLASS (player->priv->mmplayer),
-			    		      "buffer-size") == NULL)) {
-		return;
-	}
-
-	rb_debug ("network buffer size changed");
-	buffer_size = eel_gconf_get_integer (CONF_PLAYER_NETWORK_BUFFER_SIZE);
-	if (buffer_size < 64)
-		buffer_size = 64;
-
-	g_object_set (player->priv->mmplayer, "buffer-size", buffer_size, NULL);
-}
-
-
-static void
 _play_order_description_free (RBPlayOrderDescription *order)
 {
 	g_free (order->name);
@@ -3968,7 +3878,7 @@ rb_play_order_new (RBShellPlayer *player, const char* porder_name)
 	order = g_hash_table_lookup (player->priv->play_orders, porder_name);
 
 	if (order == NULL) {
-		g_warning ("Unknown value \"%s\" in GConf key \"" CONF_STATE_PLAY_ORDER
+		g_warning ("Unknown value \"%s\" in GSettings key \"play-order"
 				"\". Using %s play order.", porder_name, DEFAULT_PLAY_ORDER);
 		order = g_hash_table_lookup (player->priv->play_orders, DEFAULT_PLAY_ORDER);
 	}
diff --git a/shell/rb-shell-player.h b/shell/rb-shell-player.h
index f8340fe..f98fe0b 100644
--- a/shell/rb-shell-player.h
+++ b/shell/rb-shell-player.h
@@ -142,8 +142,6 @@ gboolean                rb_shell_player_get_playback_state(RBShellPlayer *player
 
 RhythmDBEntry *         rb_shell_player_get_playing_entry (RBShellPlayer *player);
 
-void			rb_shell_player_toggle_mute	(RBShellPlayer *player);
-
 gboolean		rb_shell_player_set_volume	(RBShellPlayer *player,
 							 gdouble volume,
 							 GError **error);
diff --git a/shell/rb-shell-preferences.c b/shell/rb-shell-preferences.c
index 16a86a1..1fa506c 100644
--- a/shell/rb-shell-preferences.c
+++ b/shell/rb-shell-preferences.c
@@ -59,80 +59,83 @@
 #include "rb-builder-helpers.h"
 #include "rb-dialog.h"
 #include "rb-debug.h"
-#include "eel-gconf-extensions.h"
-#include "rb-preferences.h"
 #include "rb-shell.h"
+#include "rb-util.h"
 
 static void rb_shell_preferences_class_init (RBShellPreferencesClass *klass);
 static void rb_shell_preferences_init (RBShellPreferences *shell_preferences);
-static void rb_shell_preferences_finalize (GObject *object);
+static void impl_finalize (GObject *object);
+static void impl_dispose (GObject *object);
 static gboolean rb_shell_preferences_window_delete_cb (GtkWidget *window,
 				                       GdkEventAny *event,
 				                       RBShellPreferences *shell_preferences);
 static void rb_shell_preferences_response_cb (GtkDialog *dialog,
 				              int response_id,
 				              RBShellPreferences *shell_preferences);
-static void rb_shell_preferences_ui_pref_changed (GConfClient *client,
-						  guint cnxn_id,
-						  GConfEntry *entry,
-						  RBShellPreferences *shell_preferences);
-static void rb_shell_preferences_sync (RBShellPreferences *shell_preferences);
 
 void rb_shell_preferences_column_check_changed_cb (GtkCheckButton *butt,
 						   RBShellPreferences *shell_preferences);
 void rb_shell_preferences_browser_views_activated_cb (GtkWidget *widget,
 						      RBShellPreferences *shell_preferences);
-static void rb_shell_preferences_toolbar_style_cb (GtkComboBox *box,
-						   RBShellPreferences *preferences);
-static void rb_shell_preferences_player_backend_cb (GtkToggleButton *button,
-						    RBShellPreferences *preferences);
-static void rb_shell_preferences_transition_duration_cb (GtkRange *range,
-							 RBShellPreferences *preferences);
-static void rb_shell_preferences_network_buffer_size_cb (GtkRange *range,
-							 RBShellPreferences *preferences);
-static void update_playback_prefs_sensitivity (RBShellPreferences *preferences);
+static gboolean toolbar_style_get_map (GValue *value, GVariant *variant, gpointer data);
+static GVariant *toolbar_style_set_map (const GValue *value, const GVariantType *variant_type, gpointer data);
+
+static void column_check_toggled_cb (GtkWidget *widget, RBShellPreferences *preferences);
+
+static void player_settings_changed_cb (GSettings *settings, const char *key, RBShellPreferences *preferences);
+static void source_settings_changed_cb (GSettings *settings, const char *key, RBShellPreferences *preferences);
+static void transition_time_changed_cb (GtkRange *range, RBShellPreferences *preferences);
 
 enum
 {
 	PROP_0,
 };
 
-const char *styles[] = { "desktop_default", "both", "both_horiz", "icon", "text" };
+#define COLUMN_CHECK_PROP_NAME	"rb-column-prop-name"
+
+struct {
+	const char *widget;
+	RhythmDBPropType prop;
+} column_checks[] = {
+	{ "track_check",	RHYTHMDB_PROP_TRACK_NUMBER },
+	{ "artist_check",	RHYTHMDB_PROP_ARTIST },
+	{ "album_check",	RHYTHMDB_PROP_ALBUM },
+	{ "year_check",		RHYTHMDB_PROP_DATE },
+	{ "last_played_check",	RHYTHMDB_PROP_LAST_PLAYED },
+	{ "genre_check",	RHYTHMDB_PROP_GENRE },
+	{ "first_seen_check",	RHYTHMDB_PROP_FIRST_SEEN },
+	{ "play_count_check",	RHYTHMDB_PROP_PLAY_COUNT },
+	{ "comment_check",	RHYTHMDB_PROP_COMMENT },
+	{ "bpm_check",		RHYTHMDB_PROP_BPM },
+	{ "rating_check",	RHYTHMDB_PROP_RATING },
+	{ "duration_check",	RHYTHMDB_PROP_DURATION },
+	{ "location_check",	RHYTHMDB_PROP_LOCATION },
+	{ "quality_check",	RHYTHMDB_PROP_BITRATE }
+};
+
 
 struct RBShellPreferencesPrivate
 {
 	GtkWidget *notebook;
 
-	GtkWidget *config_widget;
-	GtkWidget *artist_check;
-	GtkWidget *album_check;
-	GtkWidget *genre_check;
-	GtkWidget *comment_check;
-	GtkWidget *duration_check;
-	GtkWidget *track_check;
-	GtkWidget *rating_check;
-	GtkWidget *play_count_check;
-	GtkWidget *last_played_check;
-	GtkWidget *first_seen_check;
-	GtkWidget *bpm_check;
-	GtkWidget *quality_check;
-	GtkWidget *year_check;
-	GtkWidget *location_check;
+	GHashTable *column_checks;
 	GtkWidget *general_prefs_plugin_box;
 
 	GtkWidget *xfade_backend_check;
 	GtkWidget *transition_duration;
-	GtkWidget *network_buffer_size;
 	GtkWidget *playback_prefs_plugin_box;
 
 	GSList *browser_views_group;
 
 	GtkWidget *toolbar_style_menu;
 
-	gboolean loading;
+	gboolean applying_settings;
+
+	GSettings *main_settings;
+	GSettings *source_settings;
+	GSettings *player_settings;
 };
 
-#define RB_SHELL_PREFERENCES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_SHELL_PREFERENCES, RBShellPreferencesPrivate))
 
 G_DEFINE_TYPE (RBShellPreferences, rb_shell_preferences, GTK_TYPE_DIALOG)
 
@@ -141,7 +144,8 @@ rb_shell_preferences_class_init (RBShellPreferencesClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	object_class->finalize = rb_shell_preferences_finalize;
+	object_class->finalize = impl_finalize;
+	object_class->dispose = impl_dispose;
 
 	g_type_class_add_private (klass, sizeof (RBShellPreferencesPrivate));
 }
@@ -172,8 +176,11 @@ rb_shell_preferences_init (RBShellPreferences *shell_preferences)
 	GtkWidget *tmp;
 	GtkWidget *content_area;
 	GtkBuilder *builder;
+	int i;
 
-	shell_preferences->priv = RB_SHELL_PREFERENCES_GET_PRIVATE (shell_preferences);
+	shell_preferences->priv = G_TYPE_INSTANCE_GET_PRIVATE (shell_preferences,
+							       RB_TYPE_SHELL_PREFERENCES,
+							       RBShellPreferencesPrivate);
 
 	g_signal_connect_object (shell_preferences,
 				 "delete_event",
@@ -202,46 +209,34 @@ rb_shell_preferences_init (RBShellPreferences *shell_preferences)
 	gtk_container_set_border_width (GTK_CONTAINER (shell_preferences->priv->notebook), 5);
 
 	content_area = gtk_dialog_get_content_area (GTK_DIALOG (shell_preferences));
-
 	gtk_container_add (GTK_CONTAINER (content_area),
 			   shell_preferences->priv->notebook);
 
 	gtk_container_set_border_width (GTK_CONTAINER (shell_preferences), 5);
 	gtk_box_set_spacing (GTK_BOX (content_area), 2);
 
+	shell_preferences->priv->source_settings = g_settings_new ("org.gnome.rhythmbox.sources");
+
 	builder = rb_builder_load ("general-prefs.ui", shell_preferences);
 
 	rb_builder_boldify_label (builder, "visible_columns_label");
 
 	/* Columns */
-	shell_preferences->priv->artist_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "artist_check"));
-	shell_preferences->priv->album_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "album_check"));
-	shell_preferences->priv->genre_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "genre_check"));
-	shell_preferences->priv->comment_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "comment_check"));
-	shell_preferences->priv->duration_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "duration_check"));
-	shell_preferences->priv->track_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "track_check"));
-	shell_preferences->priv->rating_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "rating_check"));
-	shell_preferences->priv->play_count_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "play_count_check"));
-	shell_preferences->priv->last_played_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "last_played_check"));
-	shell_preferences->priv->quality_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "quality_check"));
-	shell_preferences->priv->bpm_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "bpm_check"));
-	shell_preferences->priv->year_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "year_check"));
-	shell_preferences->priv->first_seen_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "first_seen_check"));
-	shell_preferences->priv->location_check =
-		GTK_WIDGET (gtk_builder_get_object (builder, "location_check"));
+	shell_preferences->priv->column_checks = g_hash_table_new (g_str_hash, g_str_equal);
+	for (i = 0; i < G_N_ELEMENTS (column_checks); i++) {
+		GtkWidget *widget;
+		const char *name;
+
+		widget = GTK_WIDGET (gtk_builder_get_object (builder, column_checks[i].widget));
+		/* XXX kind of nasty, we know rhythmdb_nice_elt_name_from_propid doesn't actually use the db */
+		name = (const char *)rhythmdb_nice_elt_name_from_propid (NULL, column_checks[i].prop);
+		g_assert (name != NULL);
+
+		g_signal_connect_object (widget, "toggled", G_CALLBACK (column_check_toggled_cb), shell_preferences, 0);
+		g_object_set_data (G_OBJECT (widget), COLUMN_CHECK_PROP_NAME, (gpointer)name);
+
+		g_hash_table_insert (shell_preferences->priv->column_checks, (gpointer)name, widget);
+	}
 
 	/* browser options */
 	rb_builder_boldify_label (builder, "browser_views_label");
@@ -255,6 +250,17 @@ rb_shell_preferences_init (RBShellPreferences *shell_preferences)
 				  GTK_WIDGET (gtk_builder_get_object (builder, "general_vbox")),
 				  gtk_label_new (_("General")));
 
+	g_signal_connect_object (shell_preferences->priv->source_settings,
+				 "changed",
+				 G_CALLBACK (source_settings_changed_cb),
+				 shell_preferences, 0);
+	source_settings_changed_cb (shell_preferences->priv->source_settings,
+				    "visible-columns",
+				    shell_preferences);
+	source_settings_changed_cb (shell_preferences->priv->source_settings,
+				    "browser-views",
+				    shell_preferences);
+
 	/* toolbar button style */
 	rb_builder_boldify_label (builder, "toolbar_style_label");
 	shell_preferences->priv->toolbar_style_menu =
@@ -262,74 +268,99 @@ rb_shell_preferences_init (RBShellPreferences *shell_preferences)
 	gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (shell_preferences->priv->toolbar_style_menu),
 					      rb_combo_box_hyphen_separator_func,
 					      NULL, NULL);
-	g_signal_connect_object (G_OBJECT (shell_preferences->priv->toolbar_style_menu),
-				 "changed", G_CALLBACK (rb_shell_preferences_toolbar_style_cb),
-				 shell_preferences, 0);
 
-	eel_gconf_notification_add (CONF_UI_DIR,
-				    (GConfClientNotifyFunc) rb_shell_preferences_ui_pref_changed,
-				    shell_preferences);
+	shell_preferences->priv->main_settings = g_settings_new ("org.gnome.rhythmbox");
+
+	g_settings_bind_with_mapping (shell_preferences->priv->main_settings, "toolbar-style",
+				      shell_preferences->priv->toolbar_style_menu, "active",
+				      G_SETTINGS_BIND_DEFAULT,
+				      (GSettingsBindGetMapping) toolbar_style_get_map,
+				      (GSettingsBindSetMapping) toolbar_style_set_map,
+				      NULL, NULL);
 
 	/* box for stuff added by plugins */
 	shell_preferences->priv->general_prefs_plugin_box =
 		GTK_WIDGET (gtk_builder_get_object (builder, "plugin_box"));
 
 	g_object_unref (builder);
-
-	/* playback preferences */
 	builder = rb_builder_load ("playback-prefs.ui", shell_preferences);
 
+	/* playback preferences */
 	rb_builder_boldify_label (builder, "backend_label");
 	rb_builder_boldify_label (builder, "duration_label");
-	rb_builder_boldify_label (builder, "buffer_size_label");
 
 	shell_preferences->priv->xfade_backend_check =
 		GTK_WIDGET (gtk_builder_get_object (builder, "use_xfade_backend"));
 	shell_preferences->priv->transition_duration =
 		GTK_WIDGET (gtk_builder_get_object (builder, "duration"));
-	shell_preferences->priv->network_buffer_size =
-		GTK_WIDGET (gtk_builder_get_object (builder, "network_buffer_size"));
 	shell_preferences->priv->playback_prefs_plugin_box =
 		GTK_WIDGET (gtk_builder_get_object (builder, "plugin_box"));
 
-	g_signal_connect_object (shell_preferences->priv->xfade_backend_check,
-				 "toggled",
-				 G_CALLBACK (rb_shell_preferences_player_backend_cb),
-				 shell_preferences, 0);
 
-	g_signal_connect_object (shell_preferences->priv->transition_duration,
-				 "value-changed",
-				 G_CALLBACK (rb_shell_preferences_transition_duration_cb),
+	shell_preferences->priv->player_settings = g_settings_new ("org.gnome.rhythmbox.player");
+	g_signal_connect_object (shell_preferences->priv->player_settings,
+				 "changed",
+				 G_CALLBACK (player_settings_changed_cb),
 				 shell_preferences, 0);
+	player_settings_changed_cb (shell_preferences->priv->player_settings,
+				    "transition-time",
+				    shell_preferences);
+
+
+	g_settings_bind (shell_preferences->priv->player_settings,
+			 "use-xfade-backend",
+			 shell_preferences->priv->xfade_backend_check,
+			 "active",
+			 G_SETTINGS_BIND_DEFAULT);
+
+	/* unfortunately the GtkRange value can't be bound to a GSettings key.. */
+	g_settings_bind (shell_preferences->priv->player_settings,
+			 "use-xfade-backend",
+			 shell_preferences->priv->transition_duration,
+			 "sensitive",
+			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY);
 
-	g_signal_connect_object (shell_preferences->priv->network_buffer_size,
+	g_signal_connect_object (gtk_builder_get_object (builder, "duration"),
 				 "value-changed",
-				 G_CALLBACK (rb_shell_preferences_network_buffer_size_cb),
+				 G_CALLBACK (transition_time_changed_cb),
 				 shell_preferences, 0);
 
 	gtk_notebook_append_page (GTK_NOTEBOOK (shell_preferences->priv->notebook),
 				  GTK_WIDGET (gtk_builder_get_object (builder, "playback_prefs_box")),
 				  gtk_label_new (_("Playback")));
 	g_object_unref (builder);
-
-	eel_gconf_notification_add (CONF_PLAYER_DIR,
-				    (GConfClientNotifyFunc) rb_shell_preferences_ui_pref_changed,
-				    shell_preferences);
-
-	rb_shell_preferences_sync (shell_preferences);
 }
 
 static void
-rb_shell_preferences_finalize (GObject *object)
+impl_dispose (GObject *object)
 {
-	RBShellPreferences *shell_preferences;
+	RBShellPreferences *shell_preferences = RB_SHELL_PREFERENCES (object);
 
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (RB_IS_SHELL_PREFERENCES (object));
+	if (shell_preferences->priv->main_settings != NULL) {
+		g_object_unref (shell_preferences->priv->main_settings);
+		shell_preferences->priv->main_settings = NULL;
+	}
 
-	shell_preferences = RB_SHELL_PREFERENCES (object);
+	if (shell_preferences->priv->source_settings != NULL) {
+		g_object_unref (shell_preferences->priv->source_settings);
+		shell_preferences->priv->source_settings = NULL;
+	}
+
+	if (shell_preferences->priv->player_settings != NULL) {
+		rb_settings_delayed_sync (shell_preferences->priv->player_settings, NULL, NULL, NULL);
+		g_object_unref (shell_preferences->priv->player_settings);
+		shell_preferences->priv->player_settings = NULL;
+	}
+
+	G_OBJECT_CLASS (rb_shell_preferences_parent_class)->dispose (object);
+}
 
-	g_return_if_fail (shell_preferences->priv != NULL);
+static void
+impl_finalize (GObject *object)
+{
+	/*RBShellPreferences *shell_preferences = RB_SHELL_PREFERENCES (object);*/
+
+	/* anything to do here? */
 
 	G_OBJECT_CLASS (rb_shell_preferences_parent_class)->finalize (object);
 }
@@ -430,214 +461,67 @@ rb_shell_preferences_response_cb (GtkDialog *dialog,
 }
 
 static void
-rb_shell_preferences_ui_pref_changed (GConfClient *client,
-				      guint cnxn_id,
-				      GConfEntry *entry,
-				      RBShellPreferences *shell_preferences)
+column_check_toggled_cb (GtkWidget *widget, RBShellPreferences *preferences)
 {
-	if (shell_preferences->priv->loading == TRUE)
-		return;
-
-	rb_shell_preferences_sync (shell_preferences);
-}
-
-/**
- * rb_shell_preferences_column_check_changed_cb:
- * @butt: the #GtkCheckButton that was changed
- * @shell_preferences: the #RBShellPreferences instance
- *
- * Signal handler used for the checkboxes used to configure the set of visible columns.
- * This updates the GConf key that contains the list of visible columns.
- */
-void
-rb_shell_preferences_column_check_changed_cb (GtkCheckButton *butt,
-					      RBShellPreferences *shell_preferences)
-{
-	GString *newcolumns = g_string_new ("");
-	char *currentcols = eel_gconf_get_string (CONF_UI_COLUMNS_SETUP);
-	char **colnames = currentcols ? g_strsplit (currentcols, ",", 0) : NULL;
-	char *colname = NULL;
-	int i;
-
-	if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->artist_check))
-		colname = "RHYTHMDB_PROP_ARTIST";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->album_check))
-		colname = "RHYTHMDB_PROP_ALBUM";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->genre_check))
-		colname = "RHYTHMDB_PROP_GENRE";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->comment_check))
-		colname = "RHYTHMDB_PROP_COMMENT";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->duration_check))
-		colname = "RHYTHMDB_PROP_DURATION";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->track_check))
-		colname = "RHYTHMDB_PROP_TRACK_NUMBER";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->rating_check))
-		colname = "RHYTHMDB_PROP_RATING";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->play_count_check))
-		colname = "RHYTHMDB_PROP_PLAY_COUNT";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->last_played_check))
-		colname = "RHYTHMDB_PROP_LAST_PLAYED";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->year_check))
-		colname = "RHYTHMDB_PROP_DATE";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->bpm_check))
-		colname = "RHYTHMDB_PROP_BPM";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->quality_check))
-		colname = "RHYTHMDB_PROP_BITRATE";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->first_seen_check))
-		colname = "RHYTHMDB_PROP_FIRST_SEEN";
-	else if (butt == GTK_CHECK_BUTTON (shell_preferences->priv->location_check))
-		colname = "RHYTHMDB_PROP_LOCATION";
-	else
-		g_assert_not_reached ();
-
-	rb_debug ("\"%s\" changed, current cols are \"%s\"", colname, currentcols);
-
-	/* Append this if we want it */
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (butt))) {
-		g_string_append (newcolumns, colname);
-		g_string_append (newcolumns, ",");
-	}
-
-	/* Append everything else */
-	for (i = 0; colnames != NULL && colnames[i] != NULL; i++) {
-		if (strcmp (colnames[i], colname)) {
-			g_string_append (newcolumns, colnames[i]);
-			if (colnames[i+1] != NULL)
-				g_string_append (newcolumns, ",");
+	const char *prop_name;
+	const char *column;
+	GVariantBuilder *b;
+	GVariantIter *iter;
+	GVariant *v;
+
+	prop_name = (const char *)g_object_get_data (G_OBJECT (widget), COLUMN_CHECK_PROP_NAME);
+	g_assert (prop_name);
+
+	v = g_settings_get_value (preferences->priv->source_settings, "visible-columns");
+
+	/* remove from current column list */
+	b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+	iter = g_variant_iter_new (v);
+	while (g_variant_iter_loop (iter, "s", &column)) {
+		if (g_strcmp0 (column, prop_name) != 0) {
+			g_variant_builder_add (b, "s", column);
 		}
 	}
+	g_variant_unref (v);
 
-	eel_gconf_set_string (CONF_UI_COLUMNS_SETUP, newcolumns->str);
-	g_string_free (newcolumns, TRUE);
-}
+	/* if enabled, add it */
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+		g_variant_builder_add (b, "s", prop_name);
+	}
 
-static void
-rb_shell_preferences_sync_column_button (RBShellPreferences *preferences,
-					 GtkWidget *button,
-					 const char *columns,
-					 const char *propid)
-{
-	g_signal_handlers_block_by_func (G_OBJECT (button),
-					 rb_shell_preferences_column_check_changed_cb,
-					 preferences);
+	v = g_variant_builder_end (b);
 
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
-				      strstr (columns, propid) != NULL);
+	g_settings_set_value (preferences->priv->source_settings, "visible-columns", v);
 
-	g_signal_handlers_unblock_by_func (G_OBJECT (button),
-					   rb_shell_preferences_column_check_changed_cb,
-					   preferences);
+	g_variant_unref (v);
+	g_variant_builder_unref (b);
 }
 
-static void
-rb_shell_preferences_sync (RBShellPreferences *shell_preferences)
+static GVariant *
+toolbar_style_set_map (const GValue *value,
+		       const GVariantType *expected_type,
+		       gpointer data)
 {
-	char *columns;
-	GSList  *l;
-	gint view, i;
-	gboolean b;
-	float duration;
-	int buffer_size;
-
-	shell_preferences->priv->loading = TRUE;
-
-	rb_debug ("syncing prefs");
-
-	columns = eel_gconf_get_string (CONF_UI_COLUMNS_SETUP);
-	if (columns != NULL)
-	{
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->artist_check,
-							 columns, "RHYTHMDB_PROP_ARTIST");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->album_check,
-							 columns, "RHYTHMDB_PROP_ALBUM");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->genre_check,
-							 columns, "RHYTHMDB_PROP_GENRE");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-							 shell_preferences->priv->comment_check,
-							 columns, "RHYTHMDB_PROP_COMMENT");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->duration_check,
-							 columns, "RHYTHMDB_PROP_DURATION");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->track_check,
-							 columns, "RHYTHMDB_PROP_TRACK_NUMBER");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->rating_check,
-							 columns, "RHYTHMDB_PROP_RATING");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->play_count_check,
-							 columns, "RHYTHMDB_PROP_PLAY_COUNT");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->last_played_check,
-							 columns, "RHYTHMDB_PROP_LAST_PLAYED");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->year_check,
-							 columns, "RHYTHMDB_PROP_DATE");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->first_seen_check,
-							 columns, "RHYTHMDB_PROP_FIRST_SEEN");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-							 shell_preferences->priv->quality_check,
-							 columns, "RHYTHMDB_PROP_BITRATE");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-							 shell_preferences->priv->bpm_check,
-							 columns, "RHYTHMDB_PROP_BPM");
-		rb_shell_preferences_sync_column_button (shell_preferences,
-			       				 shell_preferences->priv->location_check,
-							 columns, "RHYTHMDB_PROP_LOCATION");
-	}
-
-	g_free (columns);
-
-	view = eel_gconf_get_integer (CONF_UI_BROWSER_VIEWS);
-	for (l = shell_preferences->priv->browser_views_group, i = 0; l != NULL; l = g_slist_next (l), i++)
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (l->data), (i == view));
-
-	/* toolbar style */
-	g_signal_handlers_block_by_func (G_OBJECT (shell_preferences->priv->toolbar_style_menu),
-					 G_CALLBACK (rb_shell_preferences_toolbar_style_cb),
-					 shell_preferences);
-
-	view = eel_gconf_get_integer (CONF_UI_TOOLBAR_STYLE);
-	/* skip the separator row */
-	if (view >= 1)
-		view++;
-	gtk_combo_box_set_active (GTK_COMBO_BOX (shell_preferences->priv->toolbar_style_menu), view);
+	int index = g_value_get_int (value);
 
-	g_signal_handlers_unblock_by_func (G_OBJECT (shell_preferences->priv->toolbar_style_menu),
-					   G_CALLBACK (rb_shell_preferences_toolbar_style_cb),
-					   shell_preferences);
+	/* ignore the separator row */
+	if (index >= 1)
+		index--;
 
-	/* player preferences */
-	b = eel_gconf_get_boolean (CONF_PLAYER_USE_XFADE_BACKEND);
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (shell_preferences->priv->xfade_backend_check), b);
-
-	duration = eel_gconf_get_float (CONF_PLAYER_TRANSITION_TIME);
-	gtk_range_set_value (GTK_RANGE (shell_preferences->priv->transition_duration), duration);
-
-	buffer_size = eel_gconf_get_integer (CONF_PLAYER_NETWORK_BUFFER_SIZE);
-	gtk_range_set_value (GTK_RANGE (shell_preferences->priv->network_buffer_size), buffer_size);
-
-	update_playback_prefs_sensitivity (shell_preferences);
-
-	shell_preferences->priv->loading = FALSE;
+	return g_variant_new_int32 (index);
 }
 
-static void
-rb_shell_preferences_toolbar_style_cb (GtkComboBox *box, RBShellPreferences *preferences)
+static gboolean
+toolbar_style_get_map (GValue *value, GVariant *variant, gpointer data)
 {
-	int selection;
-
-	selection = gtk_combo_box_get_active (box);
+	int index = g_variant_get_int32 (variant);
 
 	/* skip the separator row */
-	if (selection >= 1)
-		selection--;
+	if (index >= 1)
+		index++;
 
-	eel_gconf_set_integer (CONF_UI_TOOLBAR_STYLE, selection);
+	g_value_set_int (value, index);
+	return TRUE;
 }
 
 /**
@@ -654,52 +538,71 @@ rb_shell_preferences_browser_views_activated_cb (GtkWidget *widget,
 {
 	int index;
 
-	if (shell_preferences->priv->loading)
+	if (shell_preferences->priv->applying_settings)
 		return;
 
 	index = g_slist_index (shell_preferences->priv->browser_views_group, widget);
 
-	eel_gconf_set_integer (CONF_UI_BROWSER_VIEWS, index);
+	g_settings_set_enum (shell_preferences->priv->source_settings, "browser-views", index);
 }
 
 static void
-update_playback_prefs_sensitivity (RBShellPreferences *preferences)
+source_settings_changed_cb (GSettings *settings, const char *key, RBShellPreferences *preferences)
 {
-	gboolean backend;
-
-	backend = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (preferences->priv->xfade_backend_check));
+	if (g_strcmp0 (key, "browser-views") == 0) {
+		int view;
+		GtkWidget *widget;
+
+		view = g_settings_get_enum (preferences->priv->source_settings, "browser-views");
+		widget = GTK_WIDGET (g_slist_nth_data (preferences->priv->browser_views_group, view));
+		preferences->priv->applying_settings = TRUE;
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+		preferences->priv->applying_settings = FALSE;
+
+	} else if (g_strcmp0 (key, "visible-columns") == 0) {
+		char **columns;
+		GHashTableIter iter;
+		gpointer name_ptr;
+		gpointer widget_ptr;
+
+		columns = g_settings_get_strv (preferences->priv->source_settings, "visible-columns");
+
+		g_hash_table_iter_init (&iter, preferences->priv->column_checks);
+		while (g_hash_table_iter_next (&iter, &name_ptr, &widget_ptr)) {
+			gboolean enabled;
+
+			enabled = rb_str_in_strv (name_ptr, (const char **)columns);
+			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget_ptr), enabled);
+		}
 
-	gtk_widget_set_sensitive (preferences->priv->transition_duration, backend);
+		g_strfreev (columns);
+	}
 }
 
 static void
-rb_shell_preferences_player_backend_cb (GtkToggleButton *button,
-					RBShellPreferences *preferences)
+player_settings_changed_cb (GSettings *settings, const char *key, RBShellPreferences *preferences)
 {
-	update_playback_prefs_sensitivity (preferences);
-
-	eel_gconf_set_boolean (CONF_PLAYER_USE_XFADE_BACKEND,
-			       gtk_toggle_button_get_active (button));
+	if (g_strcmp0 (key, "transition-time") == 0) {
+		gtk_range_set_value (GTK_RANGE (preferences->priv->transition_duration),
+				     g_settings_get_double (settings, key));
+	}
 }
 
 static void
-rb_shell_preferences_transition_duration_cb (GtkRange *range,
-					     RBShellPreferences *preferences)
+sync_transition_time (GSettings *settings, GtkRange *range)
 {
-	gdouble v;
-
-	v = gtk_range_get_value (range);
-	eel_gconf_set_float (CONF_PLAYER_TRANSITION_TIME, (float)v);
+	g_settings_set_double (settings,
+			       "transition-time",
+			       gtk_range_get_value (range));
 }
 
 static void
-rb_shell_preferences_network_buffer_size_cb (GtkRange *range,
-					     RBShellPreferences *preferences)
+transition_time_changed_cb (GtkRange *range, RBShellPreferences *preferences)
 {
-	gdouble v;
-
-	v = gtk_range_get_value (range);
-	eel_gconf_set_integer (CONF_PLAYER_NETWORK_BUFFER_SIZE, (int)v);
+	rb_settings_delayed_sync (preferences->priv->player_settings,
+				  (RBDelayedSyncFunc) sync_transition_time,
+				  g_object_ref (range),
+				  g_object_unref);
 }
 
 static GtkWidget *
diff --git a/shell/rb-shell-preferences.h b/shell/rb-shell-preferences.h
index 2377097..df9d543 100644
--- a/shell/rb-shell-preferences.h
+++ b/shell/rb-shell-preferences.h
@@ -26,7 +26,6 @@
  */
 
 #include <gtk/gtk.h>
-#include <lib/rb-preferences.h>
 
 #ifndef __RB_SHELL_PREFERENCES_H
 #define __RB_SHELL_PREFERENCES_H
diff --git a/shell/rb-shell.c b/shell/rb-shell.c
index 1c2040e..828e101 100644
--- a/shell/rb-shell.c
+++ b/shell/rb-shell.c
@@ -68,7 +68,6 @@
 #include "rb-playlist-manager.h"
 #include "rb-removable-media-manager.h"
 #include "rb-track-transfer-queue.h"
-#include "rb-preferences.h"
 #include "rb-shell-clipboard.h"
 #include "rb-shell-player.h"
 #include "rb-source-header.h"
@@ -81,7 +80,6 @@
 #include "rb-playlist-source.h"
 #include "rb-static-playlist-source.h"
 #include "rb-play-queue-source.h"
-#include "eel-gconf-extensions.h"
 #include "rb-missing-files-source.h"
 #include "rb-import-errors-source.h"
 #include "rb-plugins-engine.h"
@@ -172,10 +170,6 @@ static void rb_shell_jump_to_entry_with_source (RBShell *shell, RBSource *source
 static void rb_shell_play_entry (RBShell *shell, RhythmDBEntry *entry);
 static void rb_shell_cmd_view_all (GtkAction *action,
 				   RBShell *shell);
-static void rb_shell_view_sidepane_changed_cb (GtkAction *action,
-						 RBShell *shell);
-static void rb_shell_view_toolbar_changed_cb (GtkAction *action,
-					      RBShell *shell);
 static void rb_shell_view_party_mode_changed_cb (GtkAction *action,
 						 RBShell *shell);
 static void rb_shell_view_smalldisplay_changed_cb (GtkAction *action,
@@ -185,7 +179,6 @@ static void rb_shell_view_statusbar_changed_cb (GtkAction *action,
 static void rb_shell_view_queue_as_sidebar_changed_cb (GtkAction *action,
 						       RBShell *shell);
 static void rb_shell_load_complete_cb (RhythmDB *db, RBShell *shell);
-static void rb_shell_sync_sidepane_visibility (RBShell *shell);
 static void rb_shell_sync_toolbar_state (RBShell *shell);
 static void rb_shell_sync_smalldisplay (RBShell *shell);
 static void rb_shell_sync_pane_visibility (RBShell *shell);
@@ -193,18 +186,6 @@ static void rb_shell_sync_statusbar_visibility (RBShell *shell);
 static void rb_shell_set_visibility (RBShell *shell,
 				     gboolean initial,
 				     gboolean visible);
-static void sidepane_visibility_changed_cb (GConfClient *client,
-					    guint cnxn_id,
-					    GConfEntry *entry,
-					    RBShell *shell);
-static void toolbar_state_changed_cb (GConfClient *client,
-				      guint cnxn_id,
-				      GConfEntry *entry,
-				      RBShell *shell);
-static void smalldisplay_changed_cb (GConfClient *client,
-				     guint cnxn_id,
-				     GConfEntry *entry,
-				     RBShell *shell);
 static void display_page_tree_drag_received_cb (RBDisplayPageTree *display_page_tree,
 						RBDisplayPage *page,
 						GtkSelectionData *data,
@@ -213,15 +194,13 @@ static void display_page_tree_drag_received_cb (RBDisplayPageTree *display_page_
 static void paned_size_allocate_cb (GtkWidget *widget,
 				    GtkAllocation *allocation,
 				    RBShell *shell);
-static void sidebar_paned_size_allocate_cb (GtkWidget *widget,
-					    GtkAllocation *allocation,
-					    RBShell *shell);
 static void rb_shell_volume_widget_changed_cb (GtkScaleButton *vol,
 					       gdouble volume,
 					       RBShell *shell);
 static void rb_shell_player_volume_changed_cb (RBShellPlayer *player,
 					       GParamSpec *arg,
 					       RBShell *shell);
+static void settings_changed_cb (GSettings *settings, const char *key, RBShell *shell);
 
 static void rb_shell_session_init (RBShell *shell);
 
@@ -256,18 +235,6 @@ enum
 	PROP_DISABLE_PLUGINS
 };
 
-/* prefs */
-#define CONF_STATE_WINDOW_WIDTH     CONF_PREFIX "/state/window_width"
-#define CONF_STATE_WINDOW_HEIGHT    CONF_PREFIX "/state/window_height"
-#define CONF_STATE_SMALL_WIDTH      CONF_PREFIX "/state/small_width"
-#define CONF_STATE_WINDOW_MAXIMIZED CONF_PREFIX "/state/window_maximized"
-#define CONF_STATE_ADD_DIR          CONF_PREFIX "/state/add_dir"
-#define CONF_STATE_PANED_POSITION   CONF_PREFIX "/state/paned_position"
-#define CONF_STATE_RIGHT_PANED_POSITION   CONF_PREFIX "/state/right_paned_position"
-#define CONF_STATE_WINDOW_X_POSITION CONF_PREFIX "/state/window_x_position"
-#define CONF_STATE_WINDOW_Y_POSITION CONF_PREFIX "/state/window_y_position"
-#define CONF_STATE_SOURCELIST_HEIGHT CONF_PREFIX "/state/sourcelist_height"
-
 enum
 {
 	VISIBILITY_CHANGED,
@@ -360,27 +327,11 @@ struct _RBShellPrivate
 	guint smalldisplay_notify_id;
 
 	glong last_small_time; /* when we last changed small mode */
-
-	/* Cached copies of the gconf keys.
-	 *
-	 * To avoid race conditions, the only time the keys are actually read is at startup
-	 */
-	guint window_width;
-	guint window_height;
-	guint small_width;
-	gboolean window_maximised;
-	gboolean window_small;
-	gboolean queue_as_sidebar;
-	gboolean statusbar_hidden;
 	gboolean party_mode;
-	gint window_x;
-	gint window_y;
-	gint paned_position;
-	gint right_paned_position;
-	gint display_page_tree_height;
+
+	GSettings *settings;
 };
 
-#define RB_SHELL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_SHELL, RBShellPrivate))
 
 static GtkActionEntry rb_shell_actions [] =
 {
@@ -425,10 +376,10 @@ static GtkToggleActionEntry rb_shell_toggle_entries [] =
 {
 	{ "ViewSidePane", NULL, N_("Side _Pane"), "F9",
 	  N_("Change the visibility of the side pane"),
-	  G_CALLBACK (rb_shell_view_sidepane_changed_cb), TRUE },
+	  NULL, TRUE },
 	{ "ViewToolbar", NULL, N_("T_oolbar"), NULL,
 	  N_("Change the visibility of the toolbar"),
-	  G_CALLBACK (rb_shell_view_toolbar_changed_cb), TRUE },
+	  NULL, TRUE },
 	{ "ViewSmallDisplay", NULL, N_("_Small Display"), "<control>D",
 	  N_("Make the main window smaller"),
 	  G_CALLBACK (rb_shell_view_smalldisplay_changed_cb), },
@@ -886,13 +837,11 @@ rb_shell_class_init (RBShellClass *klass)
 static void
 rb_shell_init (RBShell *shell)
 {
-	shell->priv = RB_SHELL_GET_PRIVATE (shell);
+	shell->priv = G_TYPE_INSTANCE_GET_PRIVATE (shell, RB_TYPE_SHELL, RBShellPrivate);
 
 	rb_user_data_dir ();
 
         rb_shell_session_init (shell);
-
-	eel_gconf_monitor_add (CONF_PREFIX);
 }
 
 static void
@@ -1102,11 +1051,10 @@ rb_shell_finalize (GObject *object)
 
 	rb_shell_player_stop (shell->priv->player_shell);
 
-	eel_gconf_monitor_remove (CONF_PREFIX);
-	eel_gconf_notification_remove (shell->priv->sidepane_visibility_notify_id);
-	eel_gconf_notification_remove (shell->priv->toolbar_visibility_notify_id);
-	eel_gconf_notification_remove (shell->priv->toolbar_style_notify_id);
-	eel_gconf_notification_remove (shell->priv->smalldisplay_notify_id);
+	if (shell->priv->settings != NULL) {
+		rb_settings_delayed_sync (shell->priv->settings, NULL, NULL, NULL);
+		g_object_unref (shell->priv->settings);
+	}
 
 	g_free (shell->priv->cached_title);
 
@@ -1408,7 +1356,7 @@ construct_widgets (RBShell *shell)
 
 	g_signal_connect_object (G_OBJECT (shell->priv->queue_paned),
 				 "size-allocate",
-				 G_CALLBACK (sidebar_paned_size_allocate_cb),
+				 G_CALLBACK (paned_size_allocate_cb),
 				 shell, 0);
 	gtk_widget_show (shell->priv->paned);
 
@@ -1522,6 +1470,9 @@ construct_load_ui (RBShell *shell)
 	toolbar = gtk_ui_manager_get_widget (shell->priv->ui_manager, "/ToolBar");
 	gtk_style_context_add_class (gtk_widget_get_style_context (toolbar),
 				     GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
+	g_settings_bind (shell->priv->settings, "toolbar-visible",
+			 toolbar, "visible",
+			 G_SETTINGS_BIND_DEFAULT);
 	gtk_box_pack_start (GTK_BOX (shell->priv->main_vbox), toolbar, FALSE, FALSE, 0);
 	gtk_box_reorder_child (GTK_BOX (shell->priv->main_vbox), toolbar, 1);
 	gtk_widget_show (toolbar);
@@ -1571,6 +1522,7 @@ static void
 rb_shell_constructed (GObject *object)
 {
 	RBShell *shell;
+	GtkAction *action;
 
 	RB_CHAIN_GOBJECT_METHOD (rb_shell_parent_class, constructed, object);
 
@@ -1579,6 +1531,8 @@ rb_shell_constructed (GObject *object)
 	rb_debug ("Constructing shell");
 	rb_profile_start ("constructing shell");
 
+	shell->priv->settings = g_settings_new ("org.gnome.rhythmbox");
+
 	shell->priv->actiongroup = gtk_action_group_new ("MainActions");
 	gtk_action_group_set_translation_domain (shell->priv->actiongroup,
 						 GETTEXT_PACKAGE);
@@ -1595,41 +1549,22 @@ rb_shell_constructed (GObject *object)
 	/* initialize shell services */
 	construct_widgets (shell);
 
-	rb_debug ("shell: adding gconf notification");
-	/* sync state */
-	shell->priv->sidepane_visibility_notify_id =
-		eel_gconf_notification_add (CONF_UI_SIDEPANE_HIDDEN,
-					    (GConfClientNotifyFunc) sidepane_visibility_changed_cb,
-					    shell);
-	shell->priv->toolbar_visibility_notify_id =
-		eel_gconf_notification_add (CONF_UI_TOOLBAR_HIDDEN,
-					    (GConfClientNotifyFunc) toolbar_state_changed_cb,
-					    shell);
-	shell->priv->toolbar_style_notify_id =
-		eel_gconf_notification_add (CONF_UI_TOOLBAR_STYLE,
-					    (GConfClientNotifyFunc) toolbar_state_changed_cb,
-					    shell);
-	shell->priv->smalldisplay_notify_id =
-		eel_gconf_notification_add (CONF_UI_SMALL_DISPLAY,
-					    (GConfClientNotifyFunc) smalldisplay_changed_cb,
-					    shell);
-
-	/* read the cached copies of the gconf keys */
-	shell->priv->window_width = eel_gconf_get_integer (CONF_STATE_WINDOW_WIDTH);
-	shell->priv->window_height = eel_gconf_get_integer (CONF_STATE_WINDOW_HEIGHT);
-	shell->priv->small_width = eel_gconf_get_integer (CONF_STATE_SMALL_WIDTH);
-	shell->priv->window_maximised = eel_gconf_get_boolean (CONF_STATE_WINDOW_MAXIMIZED);
-	shell->priv->window_small = eel_gconf_get_boolean (CONF_UI_SMALL_DISPLAY);
-	shell->priv->queue_as_sidebar = eel_gconf_get_boolean (CONF_UI_QUEUE_AS_SIDEBAR);
-	shell->priv->window_x = eel_gconf_get_integer (CONF_STATE_WINDOW_X_POSITION);
-	shell->priv->window_y = eel_gconf_get_integer (CONF_STATE_WINDOW_Y_POSITION);
-	shell->priv->paned_position = eel_gconf_get_integer (CONF_STATE_PANED_POSITION);
-	shell->priv->right_paned_position = eel_gconf_get_integer (CONF_STATE_RIGHT_PANED_POSITION);
-	shell->priv->display_page_tree_height = eel_gconf_get_integer (CONF_STATE_SOURCELIST_HEIGHT);
-	shell->priv->statusbar_hidden = eel_gconf_get_boolean (CONF_UI_STATUSBAR_HIDDEN);
-
-	rb_debug ("shell: syncing with gconf");
-	rb_shell_sync_sidepane_visibility (shell);
+	g_signal_connect_object (shell->priv->settings, "changed", G_CALLBACK (settings_changed_cb), shell, 0);
+
+	action = gtk_action_group_get_action (shell->priv->actiongroup, "ViewSidePane");
+	g_settings_bind (shell->priv->settings, "display-page-tree-visible",
+			 action, "active",
+			 G_SETTINGS_BIND_DEFAULT);
+	g_settings_bind (shell->priv->settings, "display-page-tree-visible",
+			 shell->priv->sidebar_container, "visible",
+			 G_SETTINGS_BIND_DEFAULT);
+
+	action = gtk_action_group_get_action (shell->priv->actiongroup, "ViewToolbar");
+	g_settings_bind (shell->priv->settings, "toolbar-visible",
+			 action, "active",
+			 G_SETTINGS_BIND_DEFAULT);
+
+	rb_debug ("shell: syncing with settings");
 	rb_shell_sync_pane_visibility (shell);
 
 	g_signal_connect_object (G_OBJECT (shell->priv->db), "save-error",
@@ -1666,17 +1601,13 @@ rb_shell_constructed (GObject *object)
 	rb_debug ("shell: syncing window state");
 	rb_shell_sync_paned (shell);
 
-	/* Do as if we ran the first time druid */
-	if (!eel_gconf_get_boolean (CONF_FIRST_TIME))
-		eel_gconf_set_boolean (CONF_FIRST_TIME, TRUE);
-
 	/* set initial visibility */
 	rb_shell_set_visibility (shell, TRUE, TRUE);
 
 	gdk_notify_startup_complete ();
 
 	/* focus play if small, the entry view if not */
-	if (shell->priv->window_small) {
+	if (g_settings_get_boolean (shell->priv->settings, "small-display")) {
 		GtkWidget *play_button;
 
 		play_button = gtk_ui_manager_get_widget (shell->priv->ui_manager, "/ToolBar/Play");
@@ -1712,10 +1643,10 @@ rb_shell_window_state_cb (GtkWidget *widget,
 	if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
 		gboolean maximised = ((event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0);
 
-		if (!shell->priv->window_small) {
-			shell->priv->window_maximised = maximised;
-			eel_gconf_set_boolean (CONF_STATE_WINDOW_MAXIMIZED,
-					       shell->priv->window_maximised);
+		if (!g_settings_get_boolean (shell->priv->settings, "small-display")) {
+			g_settings_set_boolean (shell->priv->settings,
+						"maximized",
+						maximised);
 		}
 		rb_shell_sync_window_state (shell, TRUE);
 		rb_shell_sync_paned (shell);
@@ -1788,36 +1719,71 @@ rb_shell_set_visibility (RBShell *shell,
 	rb_profile_end ("changing shell visibility");
 }
 
-static gboolean
-rb_shell_window_configure_cb (GtkWidget *win,
-			      GdkEventConfigure *event,
-			      RBShell *shell)
+static void
+sync_window_settings (GSettings *settings, RBShell *shell)
 {
-	if (shell->priv->window_maximised || shell->priv->iconified)
-		return FALSE;
+	int width, height;
+	int oldx, oldy;
+	int x, y;
+	int pos;
 
-	if (shell->priv->window_small) {
-		rb_debug ("storing small window width of %d", event->width);
-		shell->priv->small_width = event->width;
-		eel_gconf_set_integer (CONF_STATE_SMALL_WIDTH, event->width);
+	gtk_window_get_size (GTK_WINDOW (shell->priv->window), &width, &height);
+	if (g_settings_get_boolean (shell->priv->settings, "small-display")) {
+		if (width != g_settings_get_int (shell->priv->settings, "small-width")) {
+			rb_debug ("storing small window width of %d", width);
+			g_settings_set_int (shell->priv->settings, "small-width", width);
+		}
 	} else {
-		rb_debug ("storing window size of %d:%d", event->width, event->height);
-		shell->priv->window_width = event->width;
-		shell->priv->window_height = event->height;
-		eel_gconf_set_integer (CONF_STATE_WINDOW_WIDTH, event->width);
-		eel_gconf_set_integer (CONF_STATE_WINDOW_HEIGHT, event->height);
+		int oldwidth, oldheight;
+
+		g_settings_get (shell->priv->settings, "size", "(ii)", &oldwidth, &oldheight);
+		if ((width != oldwidth) || (height != oldheight)) {
+			rb_debug ("storing window size of %d:%d", width, height);
+			g_settings_set (shell->priv->settings, "size", "(ii)", width, height);
+		}
+	}
+
+	gtk_window_get_position (GTK_WINDOW(shell->priv->window), &x, &y);
+	g_settings_get (shell->priv->settings, "position", "(ii)", &oldx, &oldy);
+	if ((x != oldx) || (y != oldy)) {
+		rb_debug ("storing window position of %d:%d", x, y);
+		g_settings_set (shell->priv->settings, "position", "(ii)", x, y);
+	}
+
+	pos = gtk_paned_get_position (GTK_PANED (shell->priv->paned));
+	rb_debug ("paned position %d", pos);
+
+	if (pos != g_settings_get_int (shell->priv->settings, "paned-position")) {
+		g_settings_set_int (shell->priv->settings, "paned-position", pos);
+	}
+
+	pos = gtk_paned_get_position (GTK_PANED (shell->priv->right_paned));
+	rb_debug ("right_paned position %d", pos);
+
+	if (pos != g_settings_get_int (shell->priv->settings, "right-paned-position")) {
+		g_settings_set_int (shell->priv->settings, "right-paned-position", pos);
 	}
 
-	gtk_window_get_position (GTK_WINDOW(shell->priv->window),
-				 &shell->priv->window_x,
-				 &shell->priv->window_y);
-	rb_debug ("storing window position of %d:%d",
-		  shell->priv->window_x,
-		  shell->priv->window_y);
+	pos = gtk_paned_get_position (GTK_PANED (shell->priv->queue_paned));
+	rb_debug ("sidebar paned position %d", pos);
 
-	eel_gconf_set_integer (CONF_STATE_WINDOW_X_POSITION, shell->priv->window_x);
-	eel_gconf_set_integer (CONF_STATE_WINDOW_Y_POSITION, shell->priv->window_y);
+	if (pos != g_settings_get_int (shell->priv->settings, "display-page-tree-height")) {
+		g_settings_set_int (shell->priv->settings, "display-page-tree-height", pos);
+	}
+}
 
+static gboolean
+rb_shell_window_configure_cb (GtkWidget *win,
+			      GdkEventConfigure *event,
+			      RBShell *shell)
+{
+	if (g_settings_get_boolean (shell->priv->settings, "maximized") || shell->priv->iconified)
+		return FALSE;
+
+	rb_settings_delayed_sync (shell->priv->settings,
+				  (RBDelayedSyncFunc) sync_window_settings,
+				  g_object_ref (shell),
+				  g_object_unref);
 	return FALSE;
 }
 
@@ -1866,47 +1832,47 @@ rb_shell_sync_window_state (RBShell *shell,
 			    gboolean dont_maximise)
 {
 	GdkGeometry hints;
+	int x, y;
 
 	rb_profile_start ("syncing window state");
 
-	if (shell->priv->window_small) {
+	if (g_settings_get_boolean (shell->priv->settings, "small-display")) {
+		int width;
+
+		width = g_settings_get_int (shell->priv->settings, "small-width");
 		hints.min_height = -1;
 		hints.min_width = -1;
 		hints.max_height = -1;
 		hints.max_width = 3000;
-		gtk_window_set_default_size (GTK_WINDOW (shell->priv->window),
-					     shell->priv->small_width, 0);
-		gtk_window_resize (GTK_WINDOW (shell->priv->window),
-				   shell->priv->small_width, 1);
+		gtk_window_set_default_size (GTK_WINDOW (shell->priv->window), width, 0);
+		gtk_window_resize (GTK_WINDOW (shell->priv->window), width, 1);
 		gtk_window_set_geometry_hints (GTK_WINDOW (shell->priv->window),
 						NULL,
 						&hints,
 						GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
 		gtk_window_unmaximize (GTK_WINDOW (shell->priv->window));
-		rb_debug ("syncing small window width to %d", shell->priv->small_width);
+		rb_debug ("syncing small window width to %d", width);
 	} else {
+		int width, height;
 		if (!dont_maximise) {
-			if (shell->priv->window_maximised)
+			if (g_settings_get_boolean (shell->priv->settings, "maximized"))
 				gtk_window_maximize (GTK_WINDOW (shell->priv->window));
 			else
 				gtk_window_unmaximize (GTK_WINDOW (shell->priv->window));
 		}
 
-		gtk_window_set_default_size (GTK_WINDOW (shell->priv->window),
-					     shell->priv->window_width,
-					     shell->priv->window_height);
-		gtk_window_resize (GTK_WINDOW (shell->priv->window),
-				   shell->priv->window_width,
-				   shell->priv->window_height);
+		g_settings_get (shell->priv->settings, "size", "(ii)", &width, &height);
+
+		gtk_window_set_default_size (GTK_WINDOW (shell->priv->window), width, height);
+		gtk_window_resize (GTK_WINDOW (shell->priv->window), width, height);
 		gtk_window_set_geometry_hints (GTK_WINDOW (shell->priv->window),
 						NULL,
 						&hints,
 						0);
 	}
 
-	gtk_window_move (GTK_WINDOW (shell->priv->window),
-			 shell->priv->window_x,
-			 shell->priv->window_y);
+	g_settings_get (shell->priv->settings, "position", "(ii)", &x, &y);
+	gtk_window_move (GTK_WINDOW (shell->priv->window), x, y);
 	rb_profile_end ("syncing window state");
 }
 
@@ -2045,9 +2011,8 @@ rb_shell_playlist_created_cb (RBPlaylistManager *mgr,
 			      RBSource *source,
 			      RBShell *shell)
 {
-	shell->priv->window_small = FALSE;
-	eel_gconf_set_boolean (CONF_UI_SMALL_DISPLAY, shell->priv->window_small);
-	eel_gconf_set_boolean (CONF_UI_SIDEPANE_HIDDEN, shell->priv->window_small);
+	g_settings_set_boolean (shell->priv->settings, "small-display", FALSE);
+	g_settings_set_boolean (shell->priv->settings, "sourcelist-hidden", FALSE);
 
 	rb_shell_sync_window_state (shell, FALSE);
 }
@@ -2118,7 +2083,7 @@ rb_shell_playing_from_queue_cb (RBShellPlayer *player,
 	gboolean from_queue;
 
 	g_object_get (player, "playing-from-queue", &from_queue, NULL);
-	if (!shell->priv->queue_as_sidebar) {
+	if (!g_settings_get_boolean (shell->priv->settings, "queue-as-sidebar")) {
 		RBSource *source;
 		source = rb_shell_player_get_playing_source (shell->priv->player_shell);
 		rb_display_page_model_set_playing_source (shell->priv->display_page_model, RB_DISPLAY_PAGE (source));
@@ -2276,22 +2241,6 @@ rb_shell_set_window_title (RBShell *shell,
 }
 
 static void
-rb_shell_view_sidepane_changed_cb (GtkAction *action,
-				   RBShell *shell)
-{
-	eel_gconf_set_boolean (CONF_UI_SIDEPANE_HIDDEN,
-			       !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
-}
-
-static void
-rb_shell_view_toolbar_changed_cb (GtkAction *action,
-				  RBShell *shell)
-{
-	eel_gconf_set_boolean (CONF_UI_TOOLBAR_HIDDEN,
-			       !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
-}
-
-static void
 rb_shell_view_smalldisplay_changed_cb (GtkAction *action,
 				       RBShell *shell)
 {
@@ -2304,16 +2253,18 @@ rb_shell_view_smalldisplay_changed_cb (GtkAction *action,
 
 	shell->priv->last_small_time = time.tv_sec;
 
-	shell->priv->window_small = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
-	eel_gconf_set_boolean (CONF_UI_SMALL_DISPLAY, shell->priv->window_small);
+	g_settings_set_boolean (shell->priv->settings,
+				"small-display",
+				gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
 }
 
 static void
 rb_shell_view_statusbar_changed_cb (GtkAction *action,
 				    RBShell *shell)
 {
-	shell->priv->statusbar_hidden = !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
-	eel_gconf_set_boolean (CONF_UI_STATUSBAR_HIDDEN, shell->priv->statusbar_hidden);
+	g_settings_set_boolean (shell->priv->settings,
+				"statusbar-hidden",
+				!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
 
 	rb_shell_sync_statusbar_visibility (shell);
 }
@@ -2322,10 +2273,13 @@ static void
 rb_shell_view_queue_as_sidebar_changed_cb (GtkAction *action,
 					   RBShell *shell)
 {
-	shell->priv->queue_as_sidebar = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
-	eel_gconf_set_boolean (CONF_UI_QUEUE_AS_SIDEBAR, shell->priv->queue_as_sidebar);
+	gboolean queue_as_sidebar = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+	/* maybe use a settings binding? */
+	g_settings_set_boolean (shell->priv->settings,
+				"queue-as-sidebar",
+				queue_as_sidebar);
 
-	if (shell->priv->queue_as_sidebar &&
+	if (queue_as_sidebar &&
 	    shell->priv->selected_page == RB_DISPLAY_PAGE (shell->priv->queue_source)) {
 		/* queue no longer exists as a source, so change to the library */
 		rb_shell_select_page (shell, RB_DISPLAY_PAGE (shell->priv->library_source));
@@ -2531,14 +2485,17 @@ add_to_library_response_cb (GtkDialog *dialog,
 
 	char *current_dir = NULL;
 	GSList *uri_list = NULL, *uris = NULL;
+	GSettings *library_settings;
 
 	if (response_id != GTK_RESPONSE_ACCEPT) {
 		gtk_widget_destroy (GTK_WIDGET (dialog));
 		return;
 	}
 
+	library_settings = g_settings_new ("org.gnome.rhythmbox.library");
 	current_dir = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
-	eel_gconf_set_string (CONF_STATE_ADD_DIR, current_dir);
+	g_settings_set_string (library_settings, "add-dir", current_dir);
+	g_object_unref (library_settings);
 
 	uri_list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
 	if (uri_list == NULL) {
@@ -2560,10 +2517,25 @@ add_to_library_response_cb (GtkDialog *dialog,
 }
 
 static void
+set_current_folder_uri (RBShell *shell, GtkWidget *dialog)
+{
+	GSettings *settings;
+	char *dir;
+
+	settings = g_settings_new ("org.gnome.rhythmbox.library");
+	dir = g_settings_get_string (settings, "add-dir");
+	if (dir && dir[0] != '\0') {
+		gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog),
+							 dir);
+	}
+	g_free (dir);
+	g_object_unref (settings);
+}
+
+static void
 rb_shell_cmd_add_folder_to_library (GtkAction *action,
 				    RBShell *shell)
 {
-	char * dir = eel_gconf_get_string (CONF_STATE_ADD_DIR);
 	GtkWidget *dialog;
 
 	dialog = rb_file_chooser_new (_("Import Folder into Library"),
@@ -2571,9 +2543,7 @@ rb_shell_cmd_add_folder_to_library (GtkAction *action,
 				      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
 				      FALSE);
 	gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
-	if (dir && dir[0] != '\0')
-		gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog),
-							 dir);
+	set_current_folder_uri (shell, dialog);
 
 	g_signal_connect_object (G_OBJECT (dialog),
 				 "response",
@@ -2585,7 +2555,6 @@ static void
 rb_shell_cmd_add_file_to_library (GtkAction *action,
 				  RBShell *shell)
 {
-	char * dir = eel_gconf_get_string (CONF_STATE_ADD_DIR);
 	GtkWidget *dialog;
 
 	dialog = rb_file_chooser_new (_("Import File into Library"),
@@ -2593,9 +2562,7 @@ rb_shell_cmd_add_file_to_library (GtkAction *action,
 				      GTK_FILE_CHOOSER_ACTION_OPEN,
 				      FALSE);
 	gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
-	if (dir && dir[0] != '\0')
-		gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog),
-							 dir);
+	set_current_folder_uri (shell, dialog);
 
 	g_signal_connect_object (G_OBJECT (dialog),
 				 "response",
@@ -2674,35 +2641,16 @@ rb_shell_load_complete_cb (RhythmDB *db,
 }
 
 static void
-rb_shell_sync_sidepane_visibility (RBShell *shell)
-{
-	gboolean visible;
-	GtkAction *action;
-
-	visible = !eel_gconf_get_boolean (CONF_UI_SIDEPANE_HIDDEN);
-
-	if (visible) {
-		gtk_widget_show (GTK_WIDGET (shell->priv->sidebar_container));
-	} else {
-		gtk_widget_hide (GTK_WIDGET (shell->priv->sidebar_container));
-	}
-
-	action = gtk_action_group_get_action (shell->priv->actiongroup,
-					      "ViewSidePane");
-	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-				      visible);
-}
-
-static void
 rb_shell_sync_pane_visibility (RBShell *shell)
 {
 	GtkAction *action;
+	gboolean queue_as_sidebar = g_settings_get_boolean (shell->priv->settings, "queue-as-sidebar");
 
 	if (shell->priv->queue_source != NULL) {
-		g_object_set (shell->priv->queue_source, "visibility", !shell->priv->queue_as_sidebar, NULL);
+		g_object_set (shell->priv->queue_source, "visibility", !queue_as_sidebar, NULL);
 	}
 
-	if (shell->priv->queue_as_sidebar) {
+	if (queue_as_sidebar) {
 		gtk_widget_show (shell->priv->queue_sidebar);
 	} else {
 		gtk_widget_hide (shell->priv->queue_sidebar);
@@ -2710,36 +2658,22 @@ rb_shell_sync_pane_visibility (RBShell *shell)
 
 	action = gtk_action_group_get_action (shell->priv->actiongroup,
 					      "ViewQueueAsSidebar");
-	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-				      shell->priv->queue_as_sidebar);
+	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), queue_as_sidebar);
 }
 
 static void
 rb_shell_sync_toolbar_state (RBShell *shell)
 {
 	GtkWidget *toolbar;
-	gboolean visible;
-	GtkAction *action;
 	guint toolbar_style;
 
-	visible = !eel_gconf_get_boolean (CONF_UI_TOOLBAR_HIDDEN);
-
 	toolbar = gtk_ui_manager_get_widget (shell->priv->ui_manager, "/ToolBar");
-	if (visible)
-		gtk_widget_show (toolbar);
-	else
-		gtk_widget_hide (toolbar);
-
-	action = gtk_action_group_get_action (shell->priv->actiongroup,
-					      "ViewToolbar");
-	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-				      visible);
 
 	/* icons-only in small mode */
-	if (shell->priv->window_small)
+	if (g_settings_get_boolean (shell->priv->settings, "small-display"))
 		toolbar_style = 3;
 	else
-		toolbar_style = eel_gconf_get_integer (CONF_UI_TOOLBAR_STYLE);
+		toolbar_style = g_settings_get_int (shell->priv->settings, "toolbar-style");
 
 	switch (toolbar_style) {
 	case 0:
@@ -2785,7 +2719,7 @@ rb_shell_sync_party_mode (RBShell *shell)
 {
 	GtkAction *action;
 
-	/* party mode does not use gconf as a model since it
+	/* party mode does not use gsettings as a model since it
 	   should not be persistent */
 
 	/* disable/enable quit action */
@@ -2836,7 +2770,7 @@ rb_shell_sync_smalldisplay (RBShell *shell)
 	jump_to_playing_action = gtk_action_group_get_action (shell->priv->actiongroup,
 							      "ViewJumpToPlaying");
 
-	if (shell->priv->window_small) {
+	if (g_settings_get_boolean (shell->priv->settings, "small-display")) {
 		g_object_set (action, "sensitive", FALSE, NULL);
 		g_object_set (queue_action, "sensitive", FALSE, NULL);
 		g_object_set (party_mode_action, "sensitive", FALSE, NULL);
@@ -2865,7 +2799,7 @@ rb_shell_sync_smalldisplay (RBShell *shell)
 	action = gtk_action_group_get_action (shell->priv->actiongroup,
 					      "ViewSmallDisplay");
 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-				      shell->priv->window_small);
+				      g_settings_get_boolean (shell->priv->settings, "small-display"));
 }
 
 static void
@@ -2874,55 +2808,36 @@ rb_shell_sync_statusbar_visibility (RBShell *shell)
 	gboolean visible;
 	GtkAction *action;
 
-	visible = !shell->priv->statusbar_hidden;
+	visible = !g_settings_get_boolean (shell->priv->settings, "statusbar-hidden");
 
 	action = gtk_action_group_get_action (shell->priv->actiongroup, "ViewStatusbar");
 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
 
 	gtk_widget_set_visible (GTK_WIDGET (shell->priv->statusbar),
-				visible && !shell->priv->window_small);
+				visible && !g_settings_get_boolean (shell->priv->settings, "small-display"));
 }
 
 static void
-sidepane_visibility_changed_cb (GConfClient *client,
-				guint cnxn_id,
-				GConfEntry *entry,
-				RBShell *shell)
+settings_changed_cb (GSettings *settings, const char *key, RBShell *shell)
 {
-	rb_debug ("sidepane visibility changed");
-	rb_shell_sync_sidepane_visibility (shell);
-}
-
-static void
-toolbar_state_changed_cb (GConfClient *client,
-			       guint cnxn_id,
-			       GConfEntry *entry,
-			       RBShell *shell)
-{
-	rb_debug ("toolbar state changed");
-	rb_shell_sync_toolbar_state (shell);
-}
-
-static void
-smalldisplay_changed_cb (GConfClient *client,
-			 guint cnxn_id,
-			 GConfEntry *entry,
-			 RBShell *shell)
-{
-	rb_debug ("small display mode changed");
-	shell->priv->window_small = eel_gconf_get_boolean (CONF_UI_SMALL_DISPLAY);
-	rb_shell_sync_smalldisplay (shell);
+	if (g_strcmp0 (key, "toolbar-style") == 0) {
+		rb_debug ("toolbar state changed");
+		rb_shell_sync_toolbar_state (shell);
+	} else if (g_strcmp0 (key, "small-display") == 0) {
+		rb_debug ("small display mode changed");
+		rb_shell_sync_smalldisplay (shell);
+	}
 }
 
 static void
 rb_shell_sync_paned (RBShell *shell)
 {
 	gtk_paned_set_position (GTK_PANED (shell->priv->right_paned),
-				shell->priv->right_paned_position);
+				g_settings_get_int (shell->priv->settings, "right-paned-position"));
 	gtk_paned_set_position (GTK_PANED (shell->priv->paned),
-				shell->priv->paned_position);
+				g_settings_get_int (shell->priv->settings, "paned-position"));
 	gtk_paned_set_position (GTK_PANED (shell->priv->queue_paned),
-				shell->priv->display_page_tree_height);
+				g_settings_get_int (shell->priv->settings, "display-page-tree-height"));
 }
 
 static void
@@ -2930,22 +2845,10 @@ paned_size_allocate_cb (GtkWidget *widget,
 			GtkAllocation *allocation,
 		        RBShell *shell)
 {
-	shell->priv->paned_position = gtk_paned_get_position (GTK_PANED (shell->priv->paned));
-	shell->priv->right_paned_position = gtk_paned_get_position (GTK_PANED (shell->priv->right_paned));
-	rb_debug ("paned position %d", shell->priv->paned_position);
-	rb_debug ("right_paned position %d", shell->priv->right_paned_position);
-	eel_gconf_set_integer (CONF_STATE_PANED_POSITION, shell->priv->paned_position);
-	eel_gconf_set_integer (CONF_STATE_RIGHT_PANED_POSITION, shell->priv->right_paned_position);
-}
-
-static void
-sidebar_paned_size_allocate_cb (GtkWidget *widget,
-				GtkAllocation *allocation,
-				RBShell *shell)
-{
-	shell->priv->display_page_tree_height = gtk_paned_get_position (GTK_PANED (shell->priv->queue_paned));
-	rb_debug ("sidebar paned position %d", shell->priv->display_page_tree_height);
-	eel_gconf_set_integer (CONF_STATE_SOURCELIST_HEIGHT, shell->priv->display_page_tree_height);
+	rb_settings_delayed_sync (shell->priv->settings,
+				  (RBDelayedSyncFunc) sync_window_settings,
+				  g_object_ref (shell),
+				  g_object_unref);
 }
 
 static void
@@ -3000,7 +2903,7 @@ rb_shell_jump_to_entry_with_source (RBShell *shell,
 	g_return_if_fail (entry != NULL);
 
 	if ((source == RB_SOURCE (shell->priv->queue_source) &&
-	     shell->priv->queue_as_sidebar) ||
+	     g_settings_get_boolean (shell->priv->settings, "queue-as-sidebar")) ||
 	     source == NULL) {
 		RhythmDBEntryType *entry_type;
 		entry_type = rhythmdb_entry_get_entry_type (entry);
diff --git a/shell/rb-shell.xml b/shell/rb-shell.xml
index 8b6e804..30e56b1 100644
--- a/shell/rb-shell.xml
+++ b/shell/rb-shell.xml
@@ -3,18 +3,21 @@
 <node name="/">
   <interface name="org.gnome.Rhythmbox.Shell">
 
+    <!-- might stay? -->
     <method name="loadURI">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_load_uri"/>
       <arg type="s"/>
       <arg type="b"/>
     </method>
 
+    <!-- this stays, perhaps? -->
     <method name="activateSource">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_activate_source_by_uri"/>
       <arg type="s" name="uri"/>
       <arg type="u" name="play"/> <!-- 0 = only select, 1 = play if not already playing, 2 = play -->
     </method>
 
+    <!-- no -->
     <method name="getPlayer">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_get_player_path"/>
       <arg type="o" direction="out">
@@ -23,6 +26,7 @@
       </arg>
     </method>
 
+    <!-- no -->
     <method name="getPlaylistManager">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_get_playlist_manager_path"/>
       <arg type="o" direction="out">
@@ -31,45 +35,56 @@
       </arg>
     </method>
 
+    <!-- no, action -->
     <method name="present">
       <arg type="u"/>
     </method>
 
+    <!-- no, db interface -->
     <method name="getSongProperties">
       <arg type="s" name="uri"/>
       <arg type="a{sv}" direction="out"/>
     </method>
 
+    <!-- no, db interface -->
     <method name="setSongProperty">
       <arg type="s" name="uri"/>
       <arg type="s" name="propname"/>
       <arg type="v" name="value"/>
     </method>
 
+    <!-- probably stays? -->
     <method name="addToQueue">
       <arg type="s" name="uri"/>
     </method>
 
+    <!-- no -->
     <method name="quit"/>
 
+    <!-- probably stays? -->
     <method name="removeFromQueue">
       <arg type="s" name="uri"/>
     </method>
 
+    <!-- probably stays? -->
     <method name="clearQueue"/>
 
+    <!-- ugh -->
     <method name="notify">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_do_notify"/>
       <arg type="b" name="userRequested"/>
     </method>
 
+    <!-- no, action -->
     <signal name="visibilityChanged">
       <arg type="b" name="visibility"/>
     </signal>
 
+    <!-- no, managed on the app side -->
     <signal name="removableMediaScanFinished"/>
     <signal name="databaseLoadComplete"/>
 
+    <!-- no, action -->
     <!-- Until a version of dbus with bug #7057 fixed is widely available,
          this does more harm than good.  -->
     <!-- <property name="visibility" type="b" access="readwrite"/> -->
diff --git a/shell/rb-source-header.c b/shell/rb-source-header.c
index 0e38199..5727961 100644
--- a/shell/rb-source-header.c
+++ b/shell/rb-source-header.c
@@ -33,15 +33,14 @@
 #include <string.h>
 
 #include <glib/gi18n.h>
+#include <gio/gio.h>
 #include <gtk/gtk.h>
 
 #include "rb-source-header.h"
 #include "rb-stock-icons.h"
-#include "rb-preferences.h"
 #include "rb-search-entry.h"
 #include "rb-debug.h"
 #include "rb-entry-view.h"
-#include "eel-gconf-extensions.h"
 #include "rb-util.h"
 #include "rb-marshal.h"
 
@@ -81,6 +80,9 @@ static void rb_source_header_search_activate_cb (RBSearchEntry *search,
 						 RBSourceHeader *header);
 static void rb_source_header_view_browser_changed_cb (GtkAction *action,
 						      RBSourceHeader *header);
+static void rb_source_header_source_browser_changed_cb (GObject *source,
+							GParamSpec *pspec,
+							RBSourceHeader *header);
 static void rb_source_header_source_weak_destroy_cb (RBSourceHeader *header, RBSource *source);
 static void search_action_changed_cb (GtkRadioAction *action,
 				      GtkRadioAction *current,
@@ -88,7 +90,6 @@ static void search_action_changed_cb (GtkRadioAction *action,
 static void rb_source_header_refresh_search_bar (RBSourceHeader *header);
 
 typedef struct {
-	gboolean 	disclosed;
 	char     	*search_text;
 	GtkRadioAction  *search_action;
 } SourceState;
@@ -115,17 +116,13 @@ struct RBSourceHeaderPrivate
 	GtkWidget *search_bar;
 	GtkRadioAction *search_group_head;
 
-	guint browser_notify_id;
-	guint search_notify_id;
 	RBSourceSearchType search_type;
-	gboolean have_browser;
-	gboolean disclosed;
-	char *browser_key;
 
 	GHashTable *source_states;
+
+	GSettings *settings;
 };
 
-#define RB_SOURCE_HEADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_SOURCE_HEADER, RBSourceHeaderPrivate))
 
 enum
 {
@@ -294,7 +291,9 @@ rb_source_header_init (RBSourceHeader *header)
 	GtkWidget *align;
 	GtkEventBox *ebox;
 
-	header->priv = RB_SOURCE_HEADER_GET_PRIVATE (header);
+	header->priv = G_TYPE_INSTANCE_GET_PRIVATE (header, RB_TYPE_SOURCE_HEADER, RBSourceHeaderPrivate);
+
+	header->priv->settings = g_settings_new ("org.gnome.rhythmbox");
 
 	gtk_table_set_col_spacings (GTK_TABLE (header), 5);
 	gtk_table_resize (GTK_TABLE (header), 1, 3);
@@ -360,6 +359,11 @@ rb_source_header_dispose (GObject *object)
 		header->priv->search_group_head = NULL;
 	}
 
+	if (header->priv->settings != NULL) {
+		g_object_unref (header->priv->settings);
+		header->priv->settings = NULL;
+	}
+
 	G_OBJECT_CLASS (rb_source_header_parent_class)->dispose (object);
 }
 
@@ -380,8 +384,6 @@ rb_source_header_finalize (GObject *object)
 			      header);
 	g_hash_table_destroy (header->priv->source_states);
 
-	g_free (header->priv->browser_key);
-
 	G_OBJECT_CLASS (rb_source_header_parent_class)->finalize (object);
 }
 
@@ -492,9 +494,12 @@ rb_source_header_set_source_internal (RBSourceHeader *header,
 				      RBSource *source)
 {
 	if (header->priv->selected_source != NULL) {
-		g_signal_handlers_disconnect_by_func (G_OBJECT (header->priv->selected_source),
+		g_signal_handlers_disconnect_by_func (header->priv->selected_source,
 						      G_CALLBACK (rb_source_header_filter_changed_cb),
 						      header);
+		g_signal_handlers_disconnect_by_func (header->priv->selected_source,
+						      G_CALLBACK (rb_source_header_source_browser_changed_cb),
+						      header);
 	}
 
 	header->priv->selected_source = source;
@@ -503,56 +508,39 @@ rb_source_header_set_source_internal (RBSourceHeader *header,
 	if (header->priv->selected_source != NULL) {
 		SourceState *source_state;
 		char        *text;
-		gboolean    disclosed;
 
 		source_state = g_hash_table_lookup (header->priv->source_states,
 						    header->priv->selected_source);
 
 		if (source_state) {
 			text = g_strdup (source_state->search_text);
-			disclosed = source_state->disclosed;
 		} else {
 			text = NULL;
-			disclosed = FALSE;
 		}
 
-		g_free (header->priv->browser_key);
-		header->priv->browser_key = rb_source_get_browser_key (header->priv->selected_source);
-
 		rb_search_entry_set_text (RB_SEARCH_ENTRY (header->priv->search), text);
 		g_signal_connect_object (G_OBJECT (header->priv->selected_source),
 					 "filter_changed",
 					 G_CALLBACK (rb_source_header_filter_changed_cb),
 					 header, 0);
+		g_signal_connect_object (header->priv->selected_source,
+					 "notify::show-browser",
+					 G_CALLBACK (rb_source_header_source_browser_changed_cb),
+					 header, 0);
 
 		g_object_get (header->priv->selected_source, "search-type", &header->priv->search_type, NULL);
 		gtk_widget_set_sensitive (GTK_WIDGET (header->priv->search),
 					  (header->priv->search_type != RB_SOURCE_SEARCH_NONE));
-		header->priv->have_browser = rb_source_can_browse (header->priv->selected_source);
 
-		if (!header->priv->have_browser) {
-			header->priv->disclosed = FALSE;
-		} else if (header->priv->browser_key) {
-			header->priv->disclosed = eel_gconf_get_boolean (header->priv->browser_key);
+		if (rb_source_can_browse (header->priv->selected_source) ||
+		    (header->priv->search_type != RB_SOURCE_SEARCH_NONE)) {
+			gtk_widget_show (GTK_WIDGET (header));
 		} else {
-			/* restore the previous state of the source*/
-			header->priv->disclosed = disclosed;
-		}
-
-		if (!header->priv->have_browser && (header->priv->search_type == RB_SOURCE_SEARCH_NONE)) {
 			gtk_widget_hide (GTK_WIDGET (header));
-		} else {
-			gtk_widget_show (GTK_WIDGET (header));
 		}
-
 	} else {
 		/* no selected source -> hide source header */
 		gtk_widget_hide (GTK_WIDGET (header));
-		header->priv->have_browser = FALSE;
-		header->priv->disclosed = FALSE;
-
-		g_free (header->priv->browser_key);
-		header->priv->browser_key = NULL;
 	}
 
 	rb_source_header_refresh_search_bar (header);
@@ -725,7 +713,7 @@ rb_source_state_sync (RBSourceHeader *header,
 	}
 
 	if (set_disclosure) {
-		state->disclosed = disclosed;
+		g_object_set (header->priv->selected_source, "show-browser", disclosed, NULL);
 	}
 
 	if (set_search) {
@@ -833,21 +821,22 @@ static void
 rb_source_header_view_browser_changed_cb (GtkAction *action,
 					  RBSourceHeader *header)
 {
-	rb_debug ("got view browser toggle");
-	header->priv->disclosed = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+	/* hmm, maybe use GBinding for this? */
 
-	if (header->priv->browser_key) {
-		eel_gconf_set_boolean (header->priv->browser_key,
-				       header->priv->disclosed);
-	} else {
-		rb_source_state_sync (header,
-				      FALSE, NULL,
-				      FALSE, NULL,
-				      TRUE, header->priv->disclosed);
+	rb_debug ("got view browser toggle");
+	if (header->priv->selected_source != NULL) {
+		gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+		g_object_set (header->priv->selected_source, "show-browser", active, NULL);
 	}
 
-	rb_debug ("got view browser toggle");
+	/* shouldn't need this, we'll do it when the source emits notify::show-browser */
+	/*rb_source_header_sync_control_state (header);*/
+}
 
+static void
+rb_source_header_source_browser_changed_cb (GObject *source, GParamSpec *pspec, RBSourceHeader *header)
+{
+	rb_debug ("source show-browser property changed");
 	rb_source_header_sync_control_state (header);
 }
 
@@ -864,26 +853,28 @@ rb_source_header_sync_control_state (RBSourceHeader *header)
 	GtkAction *viewbrowser_action;
 	GtkAction *viewstatusbar_action;
 	GtkAction *viewall_action;
-	gboolean not_small = !eel_gconf_get_boolean (CONF_UI_SMALL_DISPLAY);
-
-	viewbrowser_action = gtk_action_group_get_action (header->priv->actiongroup,
-							  "ViewBrowser");
-	g_object_set (G_OBJECT (viewbrowser_action), "sensitive",
-		      header->priv->have_browser && not_small, NULL);
-	viewstatusbar_action = gtk_action_group_get_action (header->priv->actiongroup,
-							    "ViewStatusbar");
-	g_object_set (G_OBJECT (viewstatusbar_action), "sensitive",
-		      not_small, NULL);
-	viewall_action = gtk_action_group_get_action (header->priv->actiongroup,
-						      "ViewAll");
-	g_object_set (G_OBJECT (viewall_action), "sensitive",
-		      (header->priv->have_browser || (header->priv->search_type != RB_SOURCE_SEARCH_NONE)) && not_small, NULL);
-
-	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (viewbrowser_action),
-				      header->priv->disclosed);
-
-	if (header->priv->selected_source)
-		rb_source_browser_toggled (header->priv->selected_source, header->priv->disclosed);
+	gboolean show_browser = FALSE;
+	gboolean small_mode = g_settings_get_boolean (header->priv->settings, "small-display");
+
+	viewbrowser_action = gtk_action_group_get_action (header->priv->actiongroup, "ViewBrowser");
+	viewstatusbar_action = gtk_action_group_get_action (header->priv->actiongroup, "ViewStatusbar");
+	viewall_action = gtk_action_group_get_action (header->priv->actiongroup, "ViewAll");
+
+	g_object_set (viewstatusbar_action, "sensitive", (small_mode == FALSE), NULL);
+	if (small_mode || (header->priv->selected_source == NULL)) {
+		g_object_set (viewbrowser_action, "sensitive", FALSE, NULL);
+		g_object_set (viewall_action, "sensitive", FALSE, NULL);
+	} else if (header->priv->selected_source) {
+		gboolean have_browser = rb_source_can_browse (header->priv->selected_source);
+
+		if (have_browser) {
+			g_object_get (header->priv->selected_source, "show-browser", &show_browser, NULL);
+		}
+		g_object_set (viewbrowser_action, "sensitive", have_browser, NULL);
+		g_object_set (viewall_action, "sensitive", have_browser || (header->priv->search_type != RB_SOURCE_SEARCH_NONE), NULL);
+	}
+
+	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (viewbrowser_action), show_browser);
 }
 
 static void
diff --git a/sources/rb-auto-playlist-source.c b/sources/rb-auto-playlist-source.c
index 71f5caf..a3cf079 100644
--- a/sources/rb-auto-playlist-source.c
+++ b/sources/rb-auto-playlist-source.c
@@ -38,7 +38,6 @@
 #include "rb-library-browser.h"
 #include "rb-util.h"
 #include "rb-debug.h"
-#include "eel-gconf-extensions.h"
 #include "rb-stock-icons.h"
 #include "rb-playlist-xml.h"
 #include "rb-source-search-basic.h"
@@ -79,14 +78,14 @@ static gboolean impl_show_popup (RBDisplayPage *page);
 static gboolean impl_receive_drag (RBDisplayPage *page, GtkSelectionData *data);
 static void impl_search (RBSource *source, RBSourceSearch *search, const char *cur_text, const char *new_text);
 static void impl_reset_filters (RBSource *asource);
-static void impl_browser_toggled (RBSource *source, gboolean enabled);
 static GList *impl_get_search_actions (RBSource *source);
 
 /* playlist methods */
 static void impl_save_contents_to_xml (RBPlaylistSource *source,
 				       xmlNodePtr node);
 
-static void rb_auto_playlist_source_songs_sort_order_changed_cb (RBEntryView *view,
+static void rb_auto_playlist_source_songs_sort_order_changed_cb (GObject *object,
+								 GParamSpec *pspec,
 								 RBAutoPlaylistSource *source);
 static void rb_auto_playlist_source_do_query (RBAutoPlaylistSource *source,
 					      gboolean subset);
@@ -110,7 +109,8 @@ static GtkRadioActionEntry rb_auto_playlist_source_radio_actions [] =
 enum
 {
 	PROP_0,
-	PROP_BASE_QUERY_MODEL
+	PROP_BASE_QUERY_MODEL,
+	PROP_SHOW_BROWSER
 };
 
 #define AUTO_PLAYLIST_SOURCE_POPUP_PATH "/AutoPlaylistSourcePopup"
@@ -130,7 +130,6 @@ struct _RBAutoPlaylistSourcePrivate
 
 	GtkWidget *paned;
 	RBLibraryBrowser *browser;
-	gboolean browser_shown;
 
 	RBSourceSearch *default_search;
 	RhythmDBQuery *search_query;
@@ -163,7 +162,6 @@ rb_auto_playlist_source_class_init (RBAutoPlaylistSourceClass *klass)
 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
 	source_class->impl_can_delete = (RBSourceFeatureFunc) rb_false_function;
 	source_class->impl_can_browse = (RBSourceFeatureFunc) rb_true_function;
-	source_class->impl_browser_toggled = impl_browser_toggled;
 	source_class->impl_search = impl_search;
 	source_class->impl_reset_filters = impl_reset_filters;
 	source_class->impl_get_property_views = impl_get_property_views;
@@ -171,6 +169,9 @@ rb_auto_playlist_source_class_init (RBAutoPlaylistSourceClass *klass)
 
 	playlist_class->impl_save_contents_to_xml = impl_save_contents_to_xml;
 
+	g_object_class_override_property (object_class, PROP_BASE_QUERY_MODEL, "base-query-model");
+	g_object_class_override_property (object_class, PROP_SHOW_BROWSER, "show-browser");
+
 	g_type_class_add_private (klass, sizeof (RBAutoPlaylistSourcePrivate));
 }
 
@@ -267,7 +268,7 @@ rb_auto_playlist_source_constructed (GObject *object)
 				 source, 0);
 
 	songs = rb_source_get_entry_view (RB_SOURCE (source));
-	g_signal_connect_object (G_OBJECT (songs), "sort-order-changed",
+	g_signal_connect_object (songs, "notify::sort-order",
 				 G_CALLBACK (rb_auto_playlist_source_songs_sort_order_changed_cb),
 				 source, 0);
 
@@ -297,6 +298,8 @@ rb_auto_playlist_source_constructed (GObject *object)
 	gtk_container_remove (GTK_CONTAINER (source), GTK_WIDGET (songs));
 	gtk_paned_pack2 (GTK_PANED (priv->paned), GTK_WIDGET (songs), TRUE, FALSE);
 	gtk_container_add (GTK_CONTAINER (source), priv->paned);
+
+	rb_source_bind_settings (RB_SOURCE (source), GTK_WIDGET (songs), priv->paned, GTK_WIDGET (priv->browser));
 	g_object_unref (songs);
 
 	gtk_widget_show_all (GTK_WIDGET (source));
@@ -333,9 +336,15 @@ rb_auto_playlist_source_set_property (GObject *object,
 				      const GValue *value,
 				      GParamSpec *pspec)
 {
-	/*RBAutoPlaylistSourcePrivate *priv = GET_PRIVATE (source);*/
+	RBAutoPlaylistSourcePrivate *priv = GET_PRIVATE (object);
 
 	switch (prop_id) {
+	case PROP_SHOW_BROWSER:
+		if (g_value_get_boolean (value))
+			gtk_widget_show (GTK_WIDGET (priv->browser));
+		else
+			gtk_widget_hide (GTK_WIDGET (priv->browser));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -354,6 +363,9 @@ rb_auto_playlist_source_get_property (GObject *object,
 	case PROP_BASE_QUERY_MODEL:
 		g_value_set_object (value, priv->cached_all_query);
 		break;
+	case PROP_SHOW_BROWSER:
+		g_value_set_boolean (value, gtk_widget_get_visible (GTK_WIDGET (priv->browser)));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -551,19 +563,6 @@ rb_auto_playlist_source_drag_atom_to_prop (GdkAtom smasher)
 	}
 }
 
-static void
-impl_browser_toggled (RBSource *source, gboolean enabled)
-{
-	RBAutoPlaylistSourcePrivate *priv = GET_PRIVATE (source);
-
-	priv->browser_shown = enabled;
-
-	if (enabled)
-		gtk_widget_show (GTK_WIDGET (priv->browser));
-	else
-		gtk_widget_hide (GTK_WIDGET (priv->browser));
-}
-
 static gboolean
 impl_receive_drag (RBDisplayPage *page, GtkSelectionData *data)
 {
@@ -887,7 +886,7 @@ rb_auto_playlist_source_get_query (RBAutoPlaylistSource *source,
 }
 
 static void
-rb_auto_playlist_source_songs_sort_order_changed_cb (RBEntryView *view, RBAutoPlaylistSource *source)
+rb_auto_playlist_source_songs_sort_order_changed_cb (GObject *object, GParamSpec *pspec, RBAutoPlaylistSource *source)
 {
 	RBAutoPlaylistSourcePrivate *priv = GET_PRIVATE (source);
 
@@ -896,7 +895,7 @@ rb_auto_playlist_source_songs_sort_order_changed_cb (RBEntryView *view, RBAutoPl
 		return;
 	rb_debug ("sort order changed");
 
-	rb_entry_view_resort_model (view);
+	rb_entry_view_resort_model (RB_ENTRY_VIEW (object));
 }
 
 static void
diff --git a/sources/rb-browser-source.c b/sources/rb-browser-source.c
index b96dba2..a6db245 100644
--- a/sources/rb-browser-source.c
+++ b/sources/rb-browser-source.c
@@ -58,10 +58,8 @@
 #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"
 
 static void rb_browser_source_class_init (RBBrowserSourceClass *klass);
@@ -80,20 +78,11 @@ static void rb_browser_source_get_property (GObject *object,
 static void rb_browser_source_cmd_choose_genre (GtkAction *action, RBSource *source);
 static void rb_browser_source_cmd_choose_artist (GtkAction *action, RBSource *source);
 static void rb_browser_source_cmd_choose_album (GtkAction *action, RBSource *source);
-static void songs_view_sort_order_changed_cb (RBEntryView *view, RBBrowserSource *source);
+static void songs_view_sort_order_changed_cb (GObject *object, GParamSpec *pspec, RBBrowserSource *source);
 static void rb_browser_source_browser_changed_cb (RBLibraryBrowser *entry,
 						  GParamSpec *param,
 						  RBBrowserSource *source);
 
-static void rb_browser_source_state_prefs_sync (RBBrowserSource *source);
-static void rb_browser_source_state_pref_changed (GConfClient *client,
-							 guint cnxn_id,
-							 GConfEntry *entry,
-							 RBBrowserSource *source);
-
-static void paned_size_allocate_cb (GtkWidget *widget,
-				    GtkAllocation *allocation,
-		                    RBBrowserSource *source);
 /* source methods */
 static RBEntryView *impl_get_entry_view (RBSource *source);
 static GList *impl_get_property_views (RBSource *source);
@@ -102,7 +91,6 @@ static void impl_search (RBSource *source, RBSourceSearch *search, const char *c
 static void impl_reset_filters (RBSource *source);
 static void impl_song_properties (RBSource *source);
 static GList *impl_get_search_actions (RBSource *source);
-static void impl_browser_toggled (RBSource *asource, gboolean disclosed);
 static void default_show_entry_popup (RBBrowserSource *source);
 static void default_pack_paned (RBBrowserSource *source, GtkWidget *paned);
 
@@ -138,11 +126,6 @@ struct RBBrowserSourcePrivate
 	GtkActionGroup *action_group;
 	GtkActionGroup *search_action_group;
 
-	char *sorting_key;
-	guint state_paned_notify_id;
-	guint state_browser_notify_id;
-	guint state_sorting_notify_id;
-
 	gboolean dispose_has_run;
 };
 
@@ -177,10 +160,10 @@ static const GtkTargetEntry songs_view_drag_types[] = {
 enum
 {
 	PROP_0,
-	PROP_SORTING_KEY,
 	PROP_BASE_QUERY_MODEL,
 	PROP_POPULATE,
-	PROP_SEARCH_TYPE
+	PROP_SEARCH_TYPE,
+	PROP_SHOW_BROWSER
 };
 
 G_DEFINE_ABSTRACT_TYPE (RBBrowserSource, rb_browser_source, RB_TYPE_SOURCE)
@@ -211,21 +194,11 @@ rb_browser_source_class_init (RBBrowserSourceClass *klass)
 	source_class->impl_can_move_to_trash = (RBSourceFeatureFunc) rb_true_function;
 	source_class->impl_delete = impl_delete;
 	source_class->impl_get_search_actions = impl_get_search_actions;
-	source_class->impl_browser_toggled = impl_browser_toggled;
 
 	klass->impl_pack_paned = default_pack_paned;
-	klass->impl_get_paned_key = (RBBrowserSourceStringFunc)rb_null_function;
 	klass->impl_has_drop_support = (RBBrowserSourceFeatureFunc) rb_false_function;
 	klass->impl_show_entry_popup = default_show_entry_popup;
 
-	g_object_class_install_property (object_class,
-					 PROP_SORTING_KEY,
-					 g_param_spec_string ("sorting-key",
-							      "Sorting key",
-							      "GConf key for storing sort-order",
-							      NULL,
-							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
 	g_object_class_override_property (object_class,
 					  PROP_BASE_QUERY_MODEL,
 					  "base-query-model");
@@ -241,6 +214,9 @@ rb_browser_source_class_init (RBBrowserSourceClass *klass)
 	g_object_class_override_property (object_class,
 					  PROP_SEARCH_TYPE,
 					  "search-type");
+	g_object_class_override_property (object_class,
+					  PROP_SHOW_BROWSER,
+					  "show-browser");
 
 	g_type_class_add_private (klass, sizeof (RBBrowserSourcePrivate));
 }
@@ -289,10 +265,6 @@ rb_browser_source_dispose (GObject *object)
 		source->priv->default_search = NULL;
 	}
 
-	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_OBJECT_CLASS (rb_browser_source_parent_class)->dispose (object);
 }
 
@@ -308,8 +280,6 @@ rb_browser_source_finalize (GObject *object)
 
 	g_return_if_fail (source->priv != NULL);
 
-	g_free (source->priv->sorting_key);
-
 	G_OBJECT_CLASS (rb_browser_source_parent_class)->finalize (object);
 }
 
@@ -340,8 +310,6 @@ rb_browser_source_constructed (GObject *object)
 	RBBrowserSourceClass *klass;
 	RBShell *shell;
 	GObject *shell_player;
-	char *browser_key;
-	char *paned_key;
 	RhythmDBEntryType *entry_type;
 
 	RB_CHAIN_GOBJECT_METHOD (rb_browser_source_parent_class, constructed, object);
@@ -386,6 +354,7 @@ rb_browser_source_constructed (GObject *object)
 	source->priv->paned = gtk_vpaned_new ();
 
 	source->priv->browser = rb_library_browser_new (source->priv->db, entry_type);
+	gtk_widget_set_no_show_all (GTK_WIDGET (source->priv->browser), TRUE);
 	gtk_paned_pack1 (GTK_PANED (source->priv->paned), GTK_WIDGET (source->priv->browser), TRUE, FALSE);
 	gtk_container_child_set (GTK_CONTAINER (source->priv->paned),
 				 GTK_WIDGET (source->priv->browser),
@@ -397,7 +366,6 @@ rb_browser_source_constructed (GObject *object)
 
 	/* 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);
@@ -415,35 +383,15 @@ rb_browser_source_constructed (GObject *object)
 
 	g_signal_connect_object (G_OBJECT (source->priv->songs), "show_popup",
 				 G_CALLBACK (rb_browser_source_songs_show_popup_cb), source, 0);
-	g_signal_connect_object (G_OBJECT (source->priv->songs),
-				 "sort-order-changed",
+	g_signal_connect_object (source->priv->songs,
+				 "notify::sort-order",
 				 G_CALLBACK (songs_view_sort_order_changed_cb),
 				 source, 0);
 
-	if (source->priv->sorting_key) {
-		source->priv->state_sorting_notify_id =
-			eel_gconf_notification_add (source->priv->sorting_key,
-					    (GConfClientNotifyFunc) rb_browser_source_state_pref_changed,
-					    source);
-	}
-	paned_key = rb_browser_source_get_paned_key (source);
-	if (paned_key) {
-		source->priv->state_paned_notify_id =
-			eel_gconf_notification_add (paned_key,
-					    (GConfClientNotifyFunc) rb_browser_source_state_pref_changed,
-					    source);
-		g_free (paned_key);
-	}
-	browser_key = rb_source_get_browser_key (RB_SOURCE (source));
-	if (browser_key) {
-		source->priv->state_browser_notify_id =
-			eel_gconf_notification_add (browser_key,
-					    (GConfClientNotifyFunc) rb_browser_source_state_pref_changed,
-					    source);
-		g_free (browser_key);
-	}
-
-	rb_browser_source_state_prefs_sync (source);
+	rb_source_bind_settings (RB_SOURCE (source),
+				 GTK_WIDGET (source->priv->songs),
+				 source->priv->paned,
+				 GTK_WIDGET (source->priv->browser));
 
 	if (rb_browser_source_has_drop_support (source)) {
 		gtk_drag_dest_set (GTK_WIDGET (source->priv->songs),
@@ -462,12 +410,6 @@ rb_browser_source_constructed (GObject *object)
 					 source, 0);
 	}
 
-	/* 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);
 
 	klass = RB_BROWSER_SOURCE_GET_CLASS (source);
@@ -496,10 +438,6 @@ rb_browser_source_set_property (GObject *object,
 	RBBrowserSource *source = RB_BROWSER_SOURCE (object);
 
 	switch (prop_id) {
-	case PROP_SORTING_KEY:
-		g_free (source->priv->sorting_key);
-		source->priv->sorting_key = g_strdup (g_value_get_string (value));
-		break;
 	case PROP_POPULATE:
 		source->priv->populate = g_value_get_boolean (value);
 
@@ -511,6 +449,14 @@ rb_browser_source_set_property (GObject *object,
 	case PROP_SEARCH_TYPE:
 		/* ignored */
 		break;
+	case PROP_SHOW_BROWSER:
+		if (g_value_get_boolean (value)) {
+			gtk_widget_show (GTK_WIDGET (source->priv->browser));
+		} else {
+			gtk_widget_hide (GTK_WIDGET (source->priv->browser));
+			rb_library_browser_reset (source->priv->browser);
+		}
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -526,9 +472,6 @@ rb_browser_source_get_property (GObject *object,
 	RBBrowserSource *source = RB_BROWSER_SOURCE (object);
 
 	switch (prop_id) {
-	case PROP_SORTING_KEY:
-		g_value_set_string (value, source->priv->sorting_key);
-		break;
 	case PROP_BASE_QUERY_MODEL:
 		g_value_set_object (value, source->priv->cached_all_query);
 		break;
@@ -538,6 +481,9 @@ rb_browser_source_get_property (GObject *object,
 	case PROP_SEARCH_TYPE:
 		g_value_set_enum (value, RB_SOURCE_SEARCH_INCREMENTAL);
 		break;
+	case PROP_SHOW_BROWSER:
+		g_value_set_boolean (value, gtk_widget_get_visible (GTK_WIDGET (source->priv->browser)));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -622,10 +568,10 @@ rb_browser_source_cmd_choose_album (GtkAction *action, RBSource *source)
 }
 
 static void
-songs_view_sort_order_changed_cb (RBEntryView *view, RBBrowserSource *source)
+songs_view_sort_order_changed_cb (GObject *object, GParamSpec *pspec, RBBrowserSource *source)
 {
 	rb_debug ("sort order changed");
-	rb_entry_view_resort_model (view);
+	rb_entry_view_resort_model (RB_ENTRY_VIEW (object));
 }
 
 static void
@@ -730,53 +676,6 @@ impl_song_properties (RBSource *asource)
 		rb_debug ("failed to create dialog, or no selection!");
 }
 
-static void
-paned_size_allocate_cb (GtkWidget *widget,
-			GtkAllocation *allocation,
-		        RBBrowserSource *source)
-{
-	char *key = rb_browser_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)));
-	g_free (key);
-}
-
-static void
-rb_browser_source_state_pref_changed (GConfClient *client,
-				     guint cnxn_id,
-				     GConfEntry *entry,
-				     RBBrowserSource *source)
-{
-	rb_debug ("state prefs changed");
-	rb_browser_source_state_prefs_sync (source);
-}
-
-static void
-rb_browser_source_state_prefs_sync (RBBrowserSource *source)
-{
-	char *paned_key;
-	char *browser_key;
-
-	rb_debug ("syncing state");
-	paned_key = rb_browser_source_get_paned_key (source);
-	if (paned_key)
-		gtk_paned_set_position (GTK_PANED (source->priv->paned),
-					eel_gconf_get_integer (paned_key));
-
-	browser_key = rb_source_get_browser_key (RB_SOURCE (source));
-	if (browser_key && eel_gconf_get_boolean (browser_key)) {
-		gtk_widget_show (GTK_WIDGET (source->priv->browser));
-	} else {
-		gtk_widget_hide (GTK_WIDGET (source->priv->browser));
-	}
-
-	g_free (paned_key);
-	g_free (browser_key);
-}
-
 static GList *
 impl_get_search_actions (RBSource *source)
 {
@@ -790,39 +689,6 @@ impl_get_search_actions (RBSource *source)
 	return actions;
 }
 
-static void
-impl_browser_toggled (RBSource *asource, gboolean disclosed)
-{
-	RBBrowserSource *source = RB_BROWSER_SOURCE (asource);
-
-	if (disclosed) {
-		gtk_widget_show (GTK_WIDGET (source->priv->browser));
-	} else {
-		gtk_widget_hide (GTK_WIDGET (source->priv->browser));
-		rb_library_browser_reset (source->priv->browser);
-	}
-}
-
-/**
- * rb_browser_source_get_paned_key:
- * @source: a #RBBrowserSource
- *
- * Retrieves the GConf key that stores the height of the browser pane for the source.
- * This is a virtual method that should be implemented by subclasses.
- *
- * Return value: (transfer full): allocated string containing the GConf key name
- */
-char *
-rb_browser_source_get_paned_key (RBBrowserSource *source)
-{
-	RBBrowserSourceClass *klass = RB_BROWSER_SOURCE_GET_CLASS (source);
-
-	if (klass->impl_get_paned_key)
-		return klass->impl_get_paned_key (source);
-	else
-		return NULL;
-}
-
 /**
  * rb_browser_source_has_drop_support:
  * @source: a #RBBrowserSource
diff --git a/sources/rb-browser-source.h b/sources/rb-browser-source.h
index 5010b4e..7d319f3 100644
--- a/sources/rb-browser-source.h
+++ b/sources/rb-browser-source.h
@@ -59,7 +59,6 @@ struct _RBBrowserSourceClass
 	RBSourceClass parent;
 
 	void		(*impl_pack_paned)		(RBBrowserSource *source, GtkWidget *paned);
-	char *		(*impl_get_paned_key)		(RBBrowserSource *source);
 	gboolean	(*impl_has_drop_support)	(RBBrowserSource *source);
 	void		(*impl_show_entry_popup)	(RBBrowserSource *source);
 };
@@ -69,7 +68,6 @@ typedef char*		(*RBBrowserSourceStringFunc)	(RBBrowserSource *source);
 
 GType		rb_browser_source_get_type		(void);
 
-char *		rb_browser_source_get_paned_key		(RBBrowserSource *source);
 gboolean	rb_browser_source_has_drop_support	(RBBrowserSource *source);
 
 G_END_DECLS
diff --git a/sources/rb-display-page-tree.c b/sources/rb-display-page-tree.c
index 88c4b08..87794bb 100644
--- a/sources/rb-display-page-tree.c
+++ b/sources/rb-display-page-tree.c
@@ -38,7 +38,6 @@
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
 
-#include "eel-gconf-extensions.h"
 #include "rb-display-page-group.h"
 #include "rb-display-page-tree.h"
 #include "rb-display-page-model.h"
@@ -87,6 +86,8 @@ struct _RBDisplayPageTreePrivate
 	GList *expand_rows;
 	GtkTreeRowReference *expand_select_row;
 	guint expand_rows_id;
+
+	GSettings *settings;
 };
 
 
@@ -109,36 +110,58 @@ static guint signals[LAST_SIGNAL] = { 0 };
 G_DEFINE_TYPE (RBDisplayPageTree, rb_display_page_tree, GTK_TYPE_SCROLLED_WINDOW)
 
 
-static char *
-expander_state_gconf_key (RBDisplayPageGroup *group)
+static gboolean
+retrieve_expander_state (RBDisplayPageTree *display_page_tree, RBDisplayPageGroup *group)
 {
+	char **groups;
 	char *id;
-	char *gconf_key;
+	gboolean collapsed;
 
+	groups = g_settings_get_strv (display_page_tree->priv->settings, "collapsed-groups");
 	g_object_get (group, "id", &id, NULL);
-	gconf_key = g_strconcat (CONF_UI_DIR "/page-groups/", id, NULL);
+	collapsed = rb_str_in_strv (id, (const char **)groups);
 	g_free (id);
+	g_strfreev (groups);
 
-	return gconf_key;
+	return (collapsed == FALSE);
 }
 
-static gboolean
-retrieve_expander_state (RBDisplayPageGroup *group)
+static void
+store_expander_state (RBDisplayPageTree *display_page_tree, RBDisplayPageGroup *group, gboolean expanded)
 {
-	gboolean state;
-	char *gconf_key = expander_state_gconf_key (group);
-	state = eel_gconf_get_boolean (gconf_key);
-	g_free (gconf_key);
+	char **newgroups = NULL;
+	char **groups;
+	char *id;
+	int num;
+	int i;
+	int p;
 
-	return (state == FALSE);
-}
+	groups = g_settings_get_strv (display_page_tree->priv->settings, "collapsed-groups");
+	g_object_get (group, "id", &id, NULL);
 
-static void
-store_expander_state (RBDisplayPageGroup *group, gboolean expanded)
-{
-	char *gconf_key = expander_state_gconf_key (group);
-	eel_gconf_set_boolean (gconf_key, (expanded == FALSE));
-	g_free (gconf_key);
+	num = g_strv_length (groups);
+	p = 0;
+	if (rb_str_in_strv (id, (const char **)groups) && expanded) {
+		newgroups = g_new0(char *, num);
+		for (i = 0; i < num; i++) {
+			if (g_strcmp0 (groups[i], id) != 0) {
+				newgroups[p++] = g_strdup (groups[i]);
+			}
+		}
+	} else if (expanded == FALSE) {
+		newgroups = g_new0(char *, num + 2);
+		for (i = 0; i < num; i++) {
+			newgroups[i] = g_strdup (groups[i]);
+		}
+		newgroups[i] = g_strdup (id);
+	}
+
+	if (newgroups != NULL) {
+		g_settings_set_strv (display_page_tree->priv->settings, "collapsed-groups", (const char * const *)newgroups);
+		g_strfreev (newgroups);
+	}
+	g_strfreev (groups);
+	g_free (id);
 }
 
 static void
@@ -350,7 +373,7 @@ update_expanded_state (RBDisplayPageTree *display_page_tree,
 			    RB_DISPLAY_PAGE_MODEL_COLUMN_PAGE, &page,
 			    -1);
 	if (RB_IS_DISPLAY_PAGE_GROUP (page)) {
-		store_expander_state (RB_DISPLAY_PAGE_GROUP (page), expanded);
+		store_expander_state (display_page_tree, RB_DISPLAY_PAGE_GROUP (page), expanded);
 	}
 }
 
@@ -434,7 +457,7 @@ model_row_inserted_cb (GtkTreeModel *model,
 					    -1);
 			g_object_get (page, "loaded", &loaded, "category", &category, NULL);
 			if (category == RB_DISPLAY_PAGE_GROUP_CATEGORY_TRANSIENT || loaded == FALSE) {
-				expand = retrieve_expander_state (RB_DISPLAY_PAGE_GROUP (page));
+				expand = retrieve_expander_state (display_page_tree, RB_DISPLAY_PAGE_GROUP (page));
 			}
 		}
 	}
@@ -870,6 +893,8 @@ impl_constructed (GObject *object)
 	display_page_tree = RB_DISPLAY_PAGE_TREE (object);
 
 	gtk_container_add (GTK_CONTAINER (display_page_tree), display_page_tree->priv->treeview);
+
+	display_page_tree->priv->settings = g_settings_new ("org.gnome.rhythmbox.display-page-tree");
 }
 
 static void
diff --git a/sources/rb-import-errors-source.c b/sources/rb-import-errors-source.c
index 1a18d0b..e48fbc9 100644
--- a/sources/rb-import-errors-source.c
+++ b/sources/rb-import-errors-source.c
@@ -210,7 +210,7 @@ rb_import_errors_source_constructed (GObject *object)
 
 	/* set up entry view */
 	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
-						NULL, FALSE, FALSE);
+						FALSE, FALSE);
 	g_object_unref (shell_player);
 
 	rb_entry_view_set_model (source->priv->view, model);
diff --git a/sources/rb-library-source.c b/sources/rb-library-source.c
index 262f799..5e2d64e 100644
--- a/sources/rb-library-source.c
+++ b/sources/rb-library-source.c
@@ -39,7 +39,7 @@
  * the library from another source, and the preferred audio encoding
  * to use.
  *
- * If multiple library locations are set in GConf, the library source
+ * If multiple library locations are configured, the library source
  * creates a child source for each location, which will only show
  * files found under that location.
  */
@@ -63,7 +63,6 @@
 #include "rb-builder-helpers.h"
 #include "rb-file-helpers.h"
 #include "rb-util.h"
-#include "eel-gconf-extensions.h"
 #include "rb-library-source.h"
 #include "rb-auto-playlist-source.h"
 #include "rb-encoder.h"
@@ -80,8 +79,6 @@ static GtkWidget *impl_get_config_widget (RBDisplayPage *source, RBShellPreferen
 static gboolean impl_receive_drag (RBDisplayPage *source, GtkSelectionData *data);
 static void impl_get_status (RBDisplayPage *source, char **text, char **progress_text, float *progress);
 
-static char *impl_get_browser_key (RBSource *source);
-static char *impl_get_paned_key (RBBrowserSource *source);
 static gboolean impl_can_paste (RBSource *asource);
 static RBTrackTransferBatch *impl_paste (RBSource *source, GList *entries);
 static guint impl_want_uri (RBSource *source, const char *uri);
@@ -93,32 +90,13 @@ static void impl_add_uri (RBSource *source,
 			  gpointer data,
 			  GDestroyNotify destroy_data);
 
-static void rb_library_source_ui_prefs_sync (RBLibrarySource *source);
-static void rb_library_source_preferences_sync (RBLibrarySource *source);
-
-static void rb_library_source_library_location_changed (GConfClient *client,
-						    guint cnxn_id,
-						    GConfEntry *entry,
-						    RBLibrarySource *source);
-static void rb_library_source_layout_path_changed (GConfClient *client,
-						   guint cnxn_id,
-						   GConfEntry *entry,
-						   RBLibrarySource *source);
-static void rb_library_source_layout_filename_changed (GConfClient *client,
-						       guint cnxn_id,
-						       GConfEntry *entry,
-						       RBLibrarySource *source);
+static void library_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source);
+static void db_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source);
 static void rb_library_source_edit_profile_clicked_cb (GtkButton *button,
 						       RBLibrarySource *source);
-static void rb_library_source_ui_pref_changed (GConfClient *client,
-					       guint cnxn_id,
-					       GConfEntry *entry,
-					       RBLibrarySource *source);
 static gboolean rb_library_source_library_location_cb (GtkEntry *entry,
 						       GdkEventFocus *event,
 						       RBLibrarySource *source);
-static void rb_library_source_watch_toggled_cb (GtkToggleButton *button,
-						RBLibrarySource *source);
 static void rb_library_source_sync_child_sources (RBLibrarySource *source);
 static void rb_library_source_path_changed_cb (GtkComboBox *box,
 						RBLibrarySource *source);
@@ -129,12 +107,6 @@ static void rb_library_source_format_changed_cb (GtkWidget *widget,
 static void layout_example_label_update (RBLibrarySource *source);
 static RhythmDBImportJob *maybe_create_import_job (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;
@@ -180,10 +152,8 @@ struct RBLibrarySourcePrivate
 	GList *import_jobs;
 	guint start_import_job_id;
 
-	guint library_location_notify_id;
-	guint ui_dir_notify_id;
-	guint layout_path_notify_id;
-	guint layout_filename_notify_id;
+	GSettings *settings;
+	GSettings *db_settings;
 };
 
 #define RB_LIBRARY_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_LIBRARY_SOURCE, RBLibrarySourcePrivate))
@@ -206,19 +176,17 @@ rb_library_source_class_init (RBLibrarySourceClass *klass)
 	page_class->receive_drag = impl_receive_drag;
 	page_class->get_status = impl_get_status;
 
-	source_class->impl_get_browser_key = impl_get_browser_key;
 	source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
 	source_class->impl_can_paste = (RBSourceFeatureFunc) impl_can_paste;
 	source_class->impl_paste = impl_paste;
 	source_class->impl_want_uri = impl_want_uri;
 	source_class->impl_add_uri = impl_add_uri;
 
-	browser_source_class->impl_get_paned_key = impl_get_paned_key;
 	browser_source_class->impl_has_drop_support = (RBBrowserSourceFeatureFunc) rb_true_function;
 
 	g_type_class_add_private (klass, sizeof (RBLibrarySourcePrivate));
 
-	gnome_media_profiles_init (eel_gconf_client_get_global ());
+	gnome_media_profiles_init (gconf_client_get_default ());
 }
 
 static void
@@ -243,24 +211,14 @@ rb_library_source_dispose (GObject *object)
 		source->priv->db = NULL;
 	}
 
-	if (source->priv->ui_dir_notify_id != 0) {
-		eel_gconf_notification_remove (source->priv->ui_dir_notify_id);
-		source->priv->ui_dir_notify_id = 0;
-	}
-
-	if (source->priv->library_location_notify_id != 0) {
-		eel_gconf_notification_remove (source->priv->library_location_notify_id);
-		source->priv->library_location_notify_id = 0;
-	}
-
-	if (source->priv->layout_path_notify_id != 0) {
-		eel_gconf_notification_remove (source->priv->layout_path_notify_id);
-		source->priv->layout_path_notify_id = 0;
+	if (source->priv->settings) {
+		g_object_unref (source->priv->settings);
+		source->priv->settings = NULL;
 	}
 
-	if (source->priv->layout_filename_notify_id != 0) {
-		eel_gconf_notification_remove (source->priv->layout_filename_notify_id);
-		source->priv->layout_filename_notify_id = 0;
+	if (source->priv->db_settings) {
+		g_object_unref (source->priv->db_settings);
+		source->priv->db_settings = NULL;
 	}
 
 	if (source->priv->import_jobs != NULL) {
@@ -298,16 +256,6 @@ rb_library_source_finalize (GObject *object)
 	G_OBJECT_CLASS (rb_library_source_parent_class)->finalize (object);
 }
 
-static gboolean
-add_child_sources_idle (RBLibrarySource *source)
-{
-	GDK_THREADS_ENTER ();
-	rb_library_source_sync_child_sources (source);
-	GDK_THREADS_LEAVE ();
-
-	return FALSE;
-}
-
 static void
 db_load_complete_cb (RhythmDB *db, RBLibrarySource *source)
 {
@@ -321,7 +269,7 @@ rb_library_source_constructed (GObject *object)
 	RBLibrarySource *source;
 	RBShell *shell;
 	RBEntryView *songs;
-	GSList *list;
+	char **locations;
 
 	RB_CHAIN_GOBJECT_METHOD (rb_library_source_parent_class, constructed, object);
 	source = RB_LIBRARY_SOURCE (object);
@@ -329,52 +277,30 @@ rb_library_source_constructed (GObject *object)
 	g_object_get (source, "shell", &shell, NULL);
 	g_object_get (shell, "db", &source->priv->db, NULL);
 
-	g_signal_connect_object (source->priv->db, "load-complete", G_CALLBACK (db_load_complete_cb), source, 0);
+	source->priv->settings = g_settings_new ("org.gnome.rhythmbox.library");
+	g_signal_connect_object (source->priv->settings, "changed", G_CALLBACK (library_settings_changed_cb), source, 0);
+
+	source->priv->db_settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb");
+	g_signal_connect_object (source->priv->db_settings, "changed", G_CALLBACK (db_settings_changed_cb), source, 0);
 
-	rb_library_source_ui_prefs_sync (source);
+	g_signal_connect_object (source->priv->db, "load-complete", G_CALLBACK (db_load_complete_cb), source, 0);
 
 	/* Set up the default library location if there's no library location set */
-	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
-	if (g_slist_length (list) == 0) {
+	locations = g_settings_get_strv (source->priv->db_settings, "locations");
+	if (g_strv_length (locations) == 0) {
 		char *music_dir_uri;
 
 		music_dir_uri = g_filename_to_uri (rb_music_dir (), NULL, NULL);
 		if (music_dir_uri != NULL) {
-			list = g_slist_prepend (list, music_dir_uri);
-			eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
-		}
-	} else {
-		/* ensure all library locations are URIs and not file paths */
-		GSList *t;
-		gboolean update = FALSE;
-		for (t = list; t != NULL; t = t->next) {
-			char *location;
-
-			location = (char *)t->data;
-			if (location[0] == '/') {
-				char *uri = g_filename_to_uri (location, NULL, NULL);
-				if (uri != NULL) {
-					rb_debug ("converting library location path %s to URI %s", location, uri);
-					g_free (location);
-					t->data = uri;
-					update = TRUE;
-				}
-			}
-		}
+			const char *set_locations[2];
+			set_locations[0] = music_dir_uri;
+			set_locations[1] = NULL;
+			g_settings_set_strv (source->priv->db_settings, "locations", set_locations);
 
-		if (update) {
-			eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
+			g_free (music_dir_uri);
 		}
 	}
-	rb_slist_deep_free (list);
-
-	source->priv->library_location_notify_id =
-		eel_gconf_notification_add (CONF_LIBRARY_LOCATION,
-				    (GConfClientNotifyFunc) rb_library_source_library_location_changed, source);
-
-	source->priv->ui_dir_notify_id =
-		eel_gconf_notification_add (CONF_UI_LIBRARY_DIR,
-				    (GConfClientNotifyFunc) rb_library_source_ui_pref_changed, source);
+	g_strfreev (locations);
 
 	songs = rb_source_get_entry_view (RB_SOURCE (source));
 
@@ -382,7 +308,7 @@ rb_library_source_constructed (GObject *object)
 	rb_entry_view_append_column (songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
 	rb_entry_view_append_column (songs, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE);
 
-	g_idle_add ((GSourceFunc)add_child_sources_idle, source);
+	rb_library_source_sync_child_sources (source);
 
 	g_object_unref (shell);
 }
@@ -400,6 +326,7 @@ rb_library_source_new (RBShell *shell)
 {
 	RBSource *source;
 	GdkPixbuf *icon;
+	GSettings *settings;
 	gint size;
 
 	gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
@@ -407,17 +334,19 @@ rb_library_source_new (RBShell *shell)
 					 "audio-x-generic",
 					 size,
 					 0, NULL);
+	settings = g_settings_new ("org.gnome.rhythmbox.library");
 	source = RB_SOURCE (g_object_new (RB_TYPE_LIBRARY_SOURCE,
 					  "name", _("Music"),
 					  "entry-type", RHYTHMDB_ENTRY_TYPE_SONG,
-					  "sorting-key", CONF_STATE_LIBRARY_SORTING,
 					  "shell", shell,
 					  "pixbuf", icon,
 					  "populate", FALSE,		/* wait until the database is loaded */
+					  "settings", g_settings_get_child (settings, "source"),
 					  NULL));
 	if (icon != NULL) {
 		g_object_unref (icon);
 	}
+	g_object_unref (settings);
 
 	rb_shell_register_entry_type_for_source (shell, source, RHYTHMDB_ENTRY_TYPE_SONG);
 
@@ -429,7 +358,7 @@ rb_library_source_edit_profile_clicked_cb (GtkButton *button, RBLibrarySource *s
 {
 	GtkWidget *dialog;
 
-	dialog = gm_audio_profiles_edit_new (eel_gconf_client_get_global (),
+	dialog = gm_audio_profiles_edit_new (gconf_client_get_default (),
 					     GTK_WINDOW (source->priv->shell_prefs));
 	gtk_widget_show_all (dialog);
 	gtk_dialog_run (GTK_DIALOG (dialog));
@@ -463,6 +392,129 @@ rb_library_source_location_button_clicked_cb (GtkButton *button, RBLibrarySource
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
+static void
+update_library_locations (RBLibrarySource *source)
+{
+	char **locations;
+
+	if (source->priv->library_location_entry == NULL) {
+		return;
+	}
+
+	locations = g_settings_get_strv (source->priv->db_settings, "locations");
+
+	/* 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_strv_length (locations) == 1) {
+		char *path;
+
+		gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
+
+		path = g_uri_unescape_string (locations[0], NULL);
+		gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), path);
+		g_free (path);
+	} else if (g_strv_length (locations) == 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_strfreev (locations);
+}
+
+static void
+update_layout_path (RBLibrarySource *source)
+{
+	char *value;
+	int active;
+	int i;
+
+	value = g_settings_get_string (source->priv->settings, "layout-path");
+
+	active = -1;
+	for (i = 0; library_layout_paths[i].path != NULL; i++) {
+		if (g_strcmp0 (library_layout_paths[i].path, value) == 0) {
+			active = i;
+			break;
+		}
+	}
+
+	g_free (value);
+	if (source->priv->layout_path_menu != NULL) {
+		gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_path_menu), active);
+	}
+
+	layout_example_label_update (source);
+}
+
+static void
+update_layout_filename (RBLibrarySource *source)
+{
+	char *value;
+	int active;
+	int i;
+
+	value = g_settings_get_string (source->priv->settings, "layout-filename");
+
+	active = -1;
+	for (i = 0; library_layout_filenames[i].path != NULL; i++) {
+		if (strcmp (library_layout_filenames[i].path, value) == 0) {
+			active = i;
+			break;
+		}
+	}
+	g_free (value);
+
+	gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_filename_menu), active);
+
+	layout_example_label_update (source);
+}
+
+static void
+update_preferred_format (RBLibrarySource *source)
+{
+	char *str = g_settings_get_string (source->priv->settings, "preferred-format");
+	if (str) {
+		gm_audio_profile_choose_set_active (source->priv->preferred_format_menu, str);
+		g_free (str);
+	}
+}
+
+static void
+db_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source)
+{
+	if (g_strcmp0 (key, "locations") == 0) {
+		update_library_locations (source);
+		rb_library_source_sync_child_sources (source);
+	}
+}
+
+static void
+library_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source)
+{
+	if (g_strcmp0 (key, "layout-path") == 0) {
+		rb_debug ("layout path changed");
+		update_layout_path (source);
+	} else if (g_strcmp0 (key, "layout-filename") == 0) {
+		rb_debug ("layout filename changed");
+		update_layout_filename (source);
+	} else if (g_strcmp0 (key, "preferred-format") == 0) {
+		rb_debug ("preferred format changed");
+		update_preferred_format (source);
+	}
+}
+
 static GtkWidget *
 impl_get_config_widget (RBDisplayPage *asource, RBShellPreferences *prefs)
 {
@@ -496,10 +548,9 @@ impl_get_config_widget (RBDisplayPage *asource, RBShellPreferences *prefs)
 			  asource);
 
 	source->priv->watch_library_check = GTK_WIDGET (gtk_builder_get_object (builder, "watch_library_check"));
-	g_signal_connect (G_OBJECT (source->priv->watch_library_check),
-			  "toggled",
-			  G_CALLBACK (rb_library_source_watch_toggled_cb),
-			  asource);
+	g_settings_bind (source->priv->db_settings, "monitor-library",
+			 source->priv->watch_library_check, "active",
+			 G_SETTINGS_BIND_DEFAULT);
 
 	rb_builder_boldify_label (builder, "library_structure_label");
 
@@ -549,108 +600,13 @@ impl_get_config_widget (RBDisplayPage *asource, RBShellPreferences *prefs)
 
 	source->priv->layout_example_label = GTK_WIDGET (gtk_builder_get_object (builder, "layout_example_label"));
 
-	rb_library_source_preferences_sync (source);
+	update_library_locations (source);
+	update_preferred_format (source);
 
-	return source->priv->config_widget;
-}
+	update_layout_path (source);
+	update_layout_filename (source);
 
-static void
-rb_library_source_library_location_changed (GConfClient *client,
-					    guint cnxn_id,
-					    GConfEntry *entry,
-					    RBLibrarySource *source)
-{
-	if (source->priv->config_widget)
-		rb_library_source_preferences_sync (source);
-
-	rb_library_source_sync_child_sources (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_preferences_sync (RBLibrarySource *source)
-{
-	GSList *list;
-	char *str;
-	GConfClient *gconf_client;
-
-	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 = g_uri_unescape_string (list->data, NULL);
-		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);
-
-	rb_slist_deep_free (list);
-
-	/* watch checkbox */
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (source->priv->watch_library_check),
-				      eel_gconf_get_boolean (CONF_MONITOR_LIBRARY));
-
-	/* preferred format */
-	str = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
-	if (str) {
-		gm_audio_profile_choose_set_active (source->priv->preferred_format_menu, str);
-		g_free (str);
-	}
-
-	source->priv->layout_path_notify_id =
-		eel_gconf_notification_add (CONF_LIBRARY_LAYOUT_PATH,
-				    (GConfClientNotifyFunc) rb_library_source_layout_path_changed, source);
-	source->priv->layout_filename_notify_id =
-		eel_gconf_notification_add (CONF_LIBRARY_LAYOUT_FILENAME,
-				    (GConfClientNotifyFunc) rb_library_source_layout_filename_changed, source);
-
-	gconf_client = eel_gconf_client_get_global ();
-	/* layout path */
-	rb_library_source_layout_path_changed (gconf_client, -1,
-					       gconf_client_get_entry (gconf_client, CONF_LIBRARY_LAYOUT_PATH, NULL, TRUE, NULL),
-					       source);
-	/* layout filename */
-	rb_library_source_layout_filename_changed (gconf_client, -1,
-						   gconf_client_get_entry (gconf_client, CONF_LIBRARY_LAYOUT_FILENAME, NULL, TRUE, NULL),
-						   source);
+	return source->priv->config_widget;
 }
 
 static gboolean
@@ -658,8 +614,8 @@ rb_library_source_library_location_cb (GtkEntry *entry,
 				       GdkEventFocus *event,
 				       RBLibrarySource *source)
 {
-	GSList *list = NULL;
 	const char *path;
+	const char *locations[2] = { NULL, NULL };
 	GFile *file;
 	char *uri;
 
@@ -668,37 +624,16 @@ rb_library_source_library_location_cb (GtkEntry *entry,
 	uri = g_file_get_uri (file);
 	g_object_unref (file);
 
-	if (uri && uri[0])
-		list = g_slist_prepend (NULL, (gpointer)uri);
-
-	eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
+	if (uri && uri[0]) {
+		locations[0] = uri;
+	}
 
-	rb_slist_deep_free (list);
+	g_settings_set_strv (source->priv->db_settings, "locations", locations);
 
+	g_free (uri);
 	return FALSE;
 }
 
-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 char *
-impl_get_browser_key (RBSource *source)
-{
-	return g_strdup (CONF_STATE_SHOW_BROWSER);
-}
-
-static char *
-impl_get_paned_key (RBBrowserSource *status)
-{
-	return g_strdup (CONF_STATE_PANED_POSITION);
-}
-
 static gboolean
 impl_receive_drag (RBDisplayPage *asource, GtkSelectionData *data)
 {
@@ -759,7 +694,8 @@ rb_library_source_path_changed_cb (GtkComboBox *box, RBLibrarySource *source)
 	index = gtk_combo_box_get_active (box);
 	if (index >= 0) {
 		path = library_layout_paths[index].path;
-		eel_gconf_set_string (CONF_LIBRARY_LAYOUT_PATH, path);
+
+		g_settings_set_string (source->priv->settings, "layout-path", path);
 	}
 }
 
@@ -772,7 +708,7 @@ rb_library_source_filename_changed_cb (GtkComboBox *box, RBLibrarySource *source
 	index = gtk_combo_box_get_active (box);
 	if (index >= 0) {
 		filename = library_layout_filenames[index].path;
-		eel_gconf_set_string (CONF_LIBRARY_LAYOUT_FILENAME, filename);
+		g_settings_set_string (source->priv->settings, "layout-filename", filename);
 	}
 }
 
@@ -782,7 +718,7 @@ 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));
+	g_settings_set_string (source->priv->settings, "preferred-format", gm_audio_profile_get_id (profile));
 	
 	layout_example_label_update (source);
 }
@@ -796,7 +732,7 @@ rb_library_source_format_changed_cb (GtkWidget *widget, RBLibrarySource *source)
  * don't end up being hidden.
  */
 static char *
-sanitize_path (const char *str)
+sanitize_path (gboolean strip_chars, const char *str)
 {
 	gchar *s;
 
@@ -807,7 +743,7 @@ sanitize_path (const char *str)
 	s = g_strdup(str);
 	/* Replace path seperators with a hyphen */
 	g_strdelimit (s, "/", '-');
-	if (eel_gconf_get_boolean (CONF_LIBRARY_STRIP_CHARS)) {
+	if (strip_chars) {
 		/* Replace separators with a hyphen */
 		g_strdelimit (s, "\\:|", '-');
 		/* Replace all other weird characters to whitespace */
@@ -821,9 +757,9 @@ sanitize_path (const char *str)
 }
 
 static char *
-sanitize_pattern (const char *pat)
+sanitize_pattern (gboolean strip_chars, const char *pat)
 {
-	if (eel_gconf_get_boolean (CONF_LIBRARY_STRIP_CHARS)) {
+	if (strip_chars) {
 		gchar *s;
 
 		s = g_strdup (pat);
@@ -857,7 +793,7 @@ sanitize_pattern (const char *pat)
  * %tS -- track artist sortname (lowercase)
  */
 static char *
-filepath_parse_pattern (RhythmDB *db,
+filepath_parse_pattern (RBLibrarySource *source,
 			const char *pattern,
 			RhythmDBEntry *entry)
 {
@@ -867,10 +803,13 @@ filepath_parse_pattern (RhythmDB *db,
 	GString *s;
 	RBRefString *albumartist;
 	RBRefString *albumartist_sort;
+	gboolean strip_chars;
 
 	if (pattern == NULL || pattern[0] == 0)
 		return g_strdup (" ");
 
+	strip_chars = g_settings_get_boolean (source->priv->settings, "strip-chars");
+
 	/* figure out album artist - use the plain artist field if not specified */
 	albumartist = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_ALBUM_ARTIST);
 	if (albumartist == NULL || g_strcmp0 (rb_refstring_get (albumartist), "") == 0) {
@@ -908,22 +847,22 @@ filepath_parse_pattern (RhythmDB *db,
 			 */
 			switch (*++p) {
 			case 't':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
 				break;
 			case 'T':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_FOLDED));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_FOLDED));
 				break;
 			case 'a':
-				string = sanitize_path (rb_refstring_get (albumartist));
+				string = sanitize_path (strip_chars, rb_refstring_get (albumartist));
 				break;
 			case 'A':
-				string = sanitize_path (rb_refstring_get_folded (albumartist));
+				string = sanitize_path (strip_chars, rb_refstring_get_folded (albumartist));
 				break;
 			case 's':
-				string = sanitize_path (rb_refstring_get (albumartist_sort));
+				string = sanitize_path (strip_chars, rb_refstring_get (albumartist_sort));
 				break;
 			case 'S':
-				string = sanitize_path (rb_refstring_get_folded (albumartist_sort));
+				string = sanitize_path (strip_chars, rb_refstring_get_folded (albumartist_sort));
 				break;
 			case 'y':
 				string = g_strdup_printf ("%u", (guint)rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_YEAR));
@@ -935,10 +874,10 @@ filepath_parse_pattern (RhythmDB *db,
 				string = g_strdup_printf ("%02u", (guint)rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DISC_NUMBER));
 				break;
 			case 'g':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE));
 				break;
 			case 'G':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE_FOLDED));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE_FOLDED));
 				break;
 			default:
 				string = g_strdup_printf ("%%a%c", *p);
@@ -952,22 +891,22 @@ filepath_parse_pattern (RhythmDB *db,
 			 */
 			switch (*++p) {
 			case 't':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
 				break;
 			case 'T':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED));
 				break;
 			case 'a':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
 				break;
 			case 'A':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
 				break;
 			case 's':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME));
 				break;
 			case 'S':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME_FOLDED));
+				string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME_FOLDED));
 				break;
 			case 'n':
 				/* Track number */
@@ -1010,22 +949,23 @@ layout_example_label_update (RBLibrarySource *source)
 	char *example;
 	char *format;
 	char *tmp;
+	gboolean strip_chars;
 	GMAudioProfile *profile;
 	RhythmDBEntryType *entry_type;
 	RhythmDBEntry *sample_entry;
 
   	profile = gm_audio_profile_choose_get_active (source->priv->preferred_format_menu);
 
-	/* TODO: sucky. Replace with get-gconf-key-with-default mojo */
-	file_pattern = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
+	file_pattern = g_settings_get_string (source->priv->settings, "layout-filename");
 	if (file_pattern == NULL) {
 		file_pattern = g_strdup (library_layout_filenames[0].path);
 	}
-	tmp = sanitize_pattern (file_pattern);
+	strip_chars = g_settings_get_boolean (source->priv->settings, "strip-chars");
+	tmp = sanitize_pattern (strip_chars, file_pattern);
 	g_free (file_pattern);
 	file_pattern = tmp;
 
-	path_pattern = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
+	path_pattern = g_settings_get_string (source->priv->settings, "layout-path");
 	if (path_pattern == NULL) {
 		path_pattern = g_strdup (library_layout_paths[0].path);
 	}
@@ -1034,8 +974,8 @@ layout_example_label_update (RBLibrarySource *source)
 	sample_entry = rhythmdb_entry_example_new (source->priv->db, entry_type, NULL);
 	g_object_unref (entry_type);
 
-	file_value = filepath_parse_pattern (source->priv->db, file_pattern, sample_entry);
-	path_value = filepath_parse_pattern (source->priv->db, path_pattern, sample_entry);
+	file_value = filepath_parse_pattern (source, file_pattern, sample_entry);
+	path_value = filepath_parse_pattern (source, path_pattern, sample_entry);
 	rhythmdb_entry_unref (sample_entry);
 
 	example = g_build_filename (G_DIR_SEPARATOR_S, path_value, file_value, NULL);
@@ -1057,80 +997,6 @@ layout_example_label_update (RBLibrarySource *source)
 	g_free (format);
 }
 
-static void
-rb_library_source_layout_path_changed (GConfClient *client,
-				       guint cnxn_id,
-				       GConfEntry *entry,
-				       RBLibrarySource *source)
-{
-	char *value;
-	int active;
-	int i;
-
-	g_return_if_fail (entry != NULL);
-	g_return_if_fail (strcmp (entry->key, CONF_LIBRARY_LAYOUT_PATH) == 0);
-
-	rb_debug ("layout path changed");
-
-	if (entry->value == NULL) {
-		value = g_strdup (library_layout_paths[0].path);
-	} else if (entry->value->type == GCONF_VALUE_STRING) {
-		value = g_strdup (gconf_value_get_string (entry->value));
-	} else {
-		return;
-	}
-
-	active = -1;
-	for (i = 0; library_layout_paths[i].path != NULL; i++) {
-		if (strcmp (library_layout_paths[i].path, value) == 0) {
-			active = i;
-			break;
-		}
-	}
-
-	g_free (value);
-	gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_path_menu), active);
-
-	layout_example_label_update (source);
-}
-
-static void
-rb_library_source_layout_filename_changed (GConfClient *client,
-					   guint cnxn_id,
-					   GConfEntry *entry,
-					   RBLibrarySource *source)
-{
-	char *value;
-	int active;
-	int i;
-
-	g_return_if_fail (entry != NULL);
-	g_return_if_fail (strcmp (entry->key, CONF_LIBRARY_LAYOUT_FILENAME) == 0);
-
-	rb_debug ("layout filename changed");
-
-	if (entry->value == NULL) {
-		value = g_strdup (library_layout_filenames[0].path);
-	} else if (entry->value->type == GCONF_VALUE_STRING) {
-		value = g_strdup (gconf_value_get_string (entry->value));
-	} else {
-		return;
-	}
-
-	active = -1;
-	for (i = 0; library_layout_filenames[i].path != NULL; i++) {
-		if (strcmp (library_layout_filenames[i].path, value) == 0) {
-			active = i;
-			break;
-		}
-	}
-	g_free (value);
-
-	gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_filename_menu), active);
-
-	layout_example_label_update (source);
-}
-
 /*
  * Build the absolute filename for the specified track.
  *
@@ -1151,32 +1017,34 @@ build_filename (RBLibrarySource *source, RhythmDBEntry *entry, const char *exten
 	char *filename;
 	char *string = NULL;
 	char *tmp;
-	GSList *list;
+	char **locations;
 	char *layout_path;
 	char *layout_filename;
+	gboolean strip_chars;
 
-	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
-	layout_path = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
-	layout_filename = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
+	locations = g_settings_get_strv (source->priv->db_settings, "locations");
+	layout_path = g_settings_get_string (source->priv->settings, "layout-path");
+	layout_filename = g_settings_get_string (source->priv->settings, "layout-filename");
+	strip_chars = g_settings_get_boolean (source->priv->settings, "strip-chars");
 
-	if (list == NULL || layout_path == NULL || layout_filename == NULL) {
+	if (locations == NULL || layout_path == NULL || layout_filename == NULL) {
 		/* emit warning */
-		rb_debug ("Could not retrieve settings from GConf");
+		rb_debug ("Could not retrieve library layout settings");
 		goto out;
 	}
 
-	tmp = sanitize_pattern (layout_filename);
+	tmp = sanitize_pattern (strip_chars, layout_filename);
 	g_free (layout_filename);
 	layout_filename = tmp;
 
-	realpath = filepath_parse_pattern (source->priv->db, layout_path, entry);
+	realpath = filepath_parse_pattern (source, layout_path, entry);
 
-	library_location = g_file_new_for_uri ((const char *)list->data);
+	library_location = g_file_new_for_uri ((const char *)locations[0]);
 	dir = g_file_resolve_relative_path (library_location, realpath);
 	g_object_unref (library_location);
 	g_free (realpath);
 
-	realfile = filepath_parse_pattern (source->priv->db, layout_filename, entry);
+	realfile = filepath_parse_pattern (source, layout_filename, entry);
 	if (extension) {
 		filename = g_strdup_printf ("%s.%s", realfile, extension);
 		g_free (realfile);
@@ -1191,7 +1059,7 @@ build_filename (RBLibrarySource *source, RhythmDBEntry *entry, const char *exten
 	string = g_file_get_uri (dest);
 	g_object_unref (dest);
  out:
-	rb_slist_deep_free (list);
+	g_strfreev (locations);
 	g_free (layout_path);
 	g_free (layout_filename);
 
@@ -1201,25 +1069,27 @@ build_filename (RBLibrarySource *source, RhythmDBEntry *entry, const char *exten
 static gboolean
 impl_can_paste (RBSource *asource)
 {
-	GSList *list;
+	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	char **locations;
 	gboolean can_paste = TRUE;
 	char *str;
 
-	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
-	can_paste = (list != NULL);
-	rb_slist_deep_free (list);
+	locations = g_settings_get_strv (source->priv->db_settings, "locations");
+	can_paste = (g_strv_length (locations) > 0);
+	g_strfreev (locations);
 
-	str = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
+	str = g_settings_get_string (source->priv->settings, "layout-path");
 	can_paste &= (str != NULL);
 	g_free (str);
 
-	str = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
+	str = g_settings_get_string (source->priv->settings, "layout-filename");
 	can_paste &= (str != NULL);
 	g_free (str);
 
-	str = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
+	str = g_settings_get_string (source->priv->settings, "preferred-format");
 	can_paste &= (str != NULL);
 	g_free (str);
+
 	return can_paste;
 }
 
@@ -1294,7 +1164,7 @@ impl_paste (RBSource *asource, GList *entries)
 	gboolean start_batch = FALSE;
 
 	if (impl_can_paste (asource) == FALSE) {
-		g_warning ("RBLibrarySource impl_paste called when gconf keys unset");
+		g_warning ("RBLibrarySource impl_paste called when layout settings unset");
 		return NULL;
 	}
 
@@ -1500,7 +1370,7 @@ rb_library_source_add_child_source (const char *path, RBLibrarySource *library_s
 		      "entry-type", &entry_type,
 		      NULL);
 
-	file = g_file_new_for_uri (path);		/* ? */
+	file = g_file_new_for_uri (path);
 	name = g_file_get_basename (file);
 	g_object_unref (file);
 
@@ -1535,18 +1405,24 @@ rb_library_source_add_child_source (const char *path, RBLibrarySource *library_s
 static void
 rb_library_source_sync_child_sources (RBLibrarySource *source)
 {
-	GSList *list;
+	char **locations;
+	int num_locations;
 
-	list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
+	locations = g_settings_get_strv (source->priv->db_settings, "locations");
 
 	/* FIXME: don't delete and re-create sources that are still there */
 	g_list_foreach (source->priv->child_sources, (GFunc)rb_display_page_delete_thyself, NULL);
 	g_list_free (source->priv->child_sources);
 	source->priv->child_sources = NULL;
 
-	if (g_slist_length (list) > 1)
-		g_slist_foreach (list, (GFunc)rb_library_source_add_child_source, source);
-	rb_slist_deep_free (list);
+	num_locations = g_strv_length (locations);
+	if (num_locations > 1) {
+		int i;
+		for (i = 0; i < num_locations; i++) {
+			rb_library_source_add_child_source (locations[i], source);
+		}
+	}
+	g_strfreev (locations);
 }
 
 static void
diff --git a/sources/rb-missing-files-source.c b/sources/rb-missing-files-source.c
index d8fec4f..53ec1fe 100644
--- a/sources/rb-missing-files-source.c
+++ b/sources/rb-missing-files-source.c
@@ -72,7 +72,8 @@ static void impl_get_status (RBDisplayPage *page, char **text, char **progress_t
 static void rb_missing_files_source_songs_show_popup_cb (RBEntryView *view,
 							 gboolean over_entry,
 							 RBMissingFilesSource *source);
-static void rb_missing_files_source_songs_sort_order_changed_cb (RBEntryView *view,
+static void rb_missing_files_source_songs_sort_order_changed_cb (GObject *object,
+								 GParamSpec *pspec,
 								 RBMissingFilesSource *source);
 
 #define MISSING_FILES_SOURCE_SONGS_POPUP_PATH "/MissingFilesViewPopup"
@@ -181,7 +182,7 @@ rb_missing_files_source_constructed (GObject *object)
 
 	/* set up entry view */
 	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
-						NULL, FALSE, FALSE);
+						FALSE, FALSE);
 	g_object_unref (shell_player);
 
 	rb_entry_view_set_model (source->priv->view, model);
@@ -199,7 +200,7 @@ rb_missing_files_source_constructed (GObject *object)
 	gtk_container_add (GTK_CONTAINER (source), GTK_WIDGET (source->priv->view));
 	g_signal_connect_object (source->priv->view, "show_popup",
 				 G_CALLBACK (rb_missing_files_source_songs_show_popup_cb), source, 0);
-	g_signal_connect_object (source->priv->view, "sort-order-changed",
+	g_signal_connect_object (source->priv->view, "notify::sort-order",
 				 G_CALLBACK (rb_missing_files_source_songs_sort_order_changed_cb), source, 0);
 
 	gtk_widget_show_all (GTK_WIDGET (source));
@@ -333,10 +334,11 @@ impl_delete (RBSource *asource)
 }
 
 static void
-rb_missing_files_source_songs_sort_order_changed_cb (RBEntryView *view,
+rb_missing_files_source_songs_sort_order_changed_cb (GObject *object,
+						     GParamSpec *pspec,
 						     RBMissingFilesSource *source)
 {
-	rb_entry_view_resort_model (view);
+	rb_entry_view_resort_model (RB_ENTRY_VIEW (object));
 }
 
 static void
diff --git a/sources/rb-play-queue-source.c b/sources/rb-play-queue-source.c
index 968fc27..82948c7 100644
--- a/sources/rb-play-queue-source.c
+++ b/sources/rb-play-queue-source.c
@@ -285,7 +285,7 @@ rb_play_queue_source_constructed (GObject *object)
 	/* Translators: this is the toolbutton label for Clear Queue action */
 	g_object_set (G_OBJECT (action), "short-label", _("Clear"), NULL);
 
-	priv->sidebar = rb_entry_view_new (db, shell_player, NULL, TRUE, TRUE);
+	priv->sidebar = rb_entry_view_new (db, shell_player, TRUE, TRUE);
 	g_object_unref (shell_player);
 
 	g_object_set (G_OBJECT (priv->sidebar), "vscrollbar-policy", GTK_POLICY_AUTOMATIC, NULL);
diff --git a/sources/rb-playlist-source.c b/sources/rb-playlist-source.c
index 1090565..b9ae1ff 100644
--- a/sources/rb-playlist-source.c
+++ b/sources/rb-playlist-source.c
@@ -40,12 +40,10 @@
 #include "rb-entry-view.h"
 #include "rb-search-entry.h"
 #include "rb-file-helpers.h"
-#include "rb-preferences.h"
 #include "rb-dialog.h"
 #include "rb-util.h"
 #include "rb-playlist-source.h"
 #include "rb-debug.h"
-#include "eel-gconf-extensions.h"
 #include "rb-song-info.h"
 
 #include "rb-playlist-xml.h"
@@ -85,7 +83,6 @@ static void rb_playlist_source_get_property (GObject *object,
 					     GParamSpec *pspec);
 
 /* source methods */
-static char *impl_get_browser_key (RBSource *source);
 static RBEntryView *impl_get_entry_view (RBSource *source);
 static void impl_song_properties (RBSource *source);
 static gboolean impl_show_popup (RBDisplayPage *page);
@@ -114,14 +111,13 @@ static void rb_playlist_source_track_cell_data_func (GtkTreeViewColumn *column,
 						     GtkTreeModel *tree_model, GtkTreeIter *iter,
 						     RBPlaylistSource *source);
 static void default_mark_dirty (RBPlaylistSource *source);
-static void rb_playlist_source_songs_sort_order_changed_cb (RBEntryView *view,
-						RBStaticPlaylistSource *source);
-static char *rb_playlist_source_make_sorting_key (RBPlaylistSource *source);
+static void rb_playlist_source_songs_sort_order_changed_cb (GObject *object,
+							    GParamSpec *pspec,
+							    RBPlaylistSource *source);
 
 static void remove_from_playlist_cmd (GtkAction *action, RBSource *source);
 static char *impl_get_delete_action (RBSource *source);
 
-#define CONF_STATE_SORTING_PREFIX CONF_PREFIX "/state/sorting/"
 #define PLAYLIST_SOURCE_SONGS_POPUP_PATH "/PlaylistViewPopup"
 #define PLAYLIST_SOURCE_POPUP_PATH "/PlaylistSourcePopup"
 
@@ -149,7 +145,6 @@ struct RBPlaylistSourcePrivate
 	gboolean dispose_has_run;
 
 	char *title;
-	char *sorting_name;
 };
 
 #define RB_PLAYLIST_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_PLAYLIST_SOURCE, RBPlaylistSourcePrivate))
@@ -160,7 +155,6 @@ enum
 	PROP_DB,
 	PROP_DIRTY,
 	PROP_LOCAL,
-	PROP_SORTING_NAME
 };
 
 static const GtkTargetEntry target_uri [] = { { "text/uri-list", 0, 0 } };
@@ -182,7 +176,6 @@ rb_playlist_source_class_init (RBPlaylistSourceClass *klass)
 
 	page_class->show_popup = impl_show_popup;
 
-	source_class->impl_get_browser_key = impl_get_browser_key;
 	source_class->impl_get_entry_view = impl_get_entry_view;
 	source_class->impl_can_rename = (RBSourceFeatureFunc) rb_true_function;
 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
@@ -234,19 +227,6 @@ rb_playlist_source_class_init (RBPlaylistSourceClass *klass)
 							       "whether this playlist is attached to the local library",
 							       TRUE,
 							       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-	/**
-	 * RBPlaylistSource:sorting-name:
-	 *
-	 * A unique-ish name for the playlist, used to construct gconf keys
-	 * to store information relating to the playlist.
-	 */
-	g_object_class_install_property (object_class,
-					 PROP_SORTING_NAME,
-					 g_param_spec_string ("sorting-name",
-					 		      "sorting-name",
-							      "globally unique name for storing sort-order",
-					 		      NULL,
-							      G_PARAM_READWRITE));
 
 	g_type_class_add_private (klass, sizeof (RBPlaylistSourcePrivate));
 }
@@ -288,7 +268,6 @@ rb_playlist_source_constructed (GObject *object)
 	RBShell *shell;
 	RhythmDB *db;
 	RhythmDBQueryModel *query_model;
-	char *sorting_key;
 
 	RB_CHAIN_GOBJECT_METHOD (rb_playlist_source_parent_class, constructed, object);
 	source = RB_PLAYLIST_SOURCE (object);
@@ -315,17 +294,13 @@ rb_playlist_source_constructed (GObject *object)
 	source->priv->entries = g_hash_table_new_full (rb_refstring_hash, rb_refstring_equal,
 						       (GDestroyNotify)rb_refstring_unref, NULL);
 
-	/* If a sorting key is available at construction time, use it. This may be
-	 * NULL in which case a key may be assigned later through a set property. */
-	sorting_key = rb_playlist_source_make_sorting_key (source);
 	source->priv->songs = rb_entry_view_new (source->priv->db,
 						 shell_player,
-					 	 sorting_key, TRUE, TRUE);
-	g_free (sorting_key);
+						 TRUE, TRUE);
 	g_object_unref (shell_player);
 
 	g_signal_connect_object (source->priv->songs,
-				 "sort-order-changed",
+				 "notify::sort-order",
 				 G_CALLBACK (rb_playlist_source_songs_sort_order_changed_cb),
 				 source, 0);
 
@@ -443,21 +418,11 @@ rb_playlist_source_set_property (GObject *object,
 				 GParamSpec *pspec)
 {
 	RBPlaylistSource *source = RB_PLAYLIST_SOURCE (object);
-	char *sorting_key;
 
 	switch (prop_id) {
 	case PROP_LOCAL:
 		source->priv->is_local = g_value_get_boolean (value);
 		break;
-	case PROP_SORTING_NAME:
-		g_free (source->priv->sorting_name);
-		source->priv->sorting_name = g_value_dup_string (value);
-
-		/* propagate sorting key to the entry view */
-		sorting_key = rb_playlist_source_make_sorting_key (source);
-		g_object_set (source->priv->songs, "sort-key", sorting_key, NULL);
-		g_free (sorting_key);
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -482,9 +447,6 @@ rb_playlist_source_get_property (GObject *object,
 	case PROP_LOCAL:
 		g_value_set_boolean (value, source->priv->is_local);
 		break;
-	case PROP_SORTING_NAME:
-		g_value_set_string (value, source->priv->sorting_name);
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -511,12 +473,6 @@ rb_playlist_source_songs_show_popup_cb (RBEntryView *view,
 		klass->impl_show_entry_view_popup (source, view, over_entry);
 }
 
-static char *
-impl_get_browser_key (RBSource *source)
-{
-	return NULL;
-}
-
 static RBEntryView *
 impl_get_entry_view (RBSource *asource)
 {
@@ -1126,39 +1082,12 @@ rb_playlist_source_add_to_map (RBPlaylistSource *source,
 }
 
 static void
-rb_playlist_source_songs_sort_order_changed_cb (RBEntryView *view,
-						RBStaticPlaylistSource *source)
+rb_playlist_source_songs_sort_order_changed_cb (GObject *object,
+						GParamSpec *pspec,
+						RBPlaylistSource *source)
 {
 	rb_debug ("sort order changed");
-	rb_entry_view_resort_model (view);
-}
-
-/* takes the 'sorting-name' property and produces a full GConf key for storing
- * the playlist's column sort order
- */
-static char *
-rb_playlist_source_make_sorting_key (RBPlaylistSource *source)
-{
-	char *sorting_name;
-	char *sorting_key;
-	char *sorting_key_tail;
-	g_object_get (source, "sorting-name", &sorting_name, NULL);
-
-	if (sorting_name && sorting_name[0] != '\0') {
-		/* escape invalid characters in the key name */
-		sorting_key_tail = gconf_escape_key (sorting_name, -1);
-
-		/* bind column sort order to a full gconf key */
-		sorting_key = g_strjoin (NULL, CONF_STATE_SORTING_PREFIX, 
-					sorting_key_tail, NULL);
-
-		g_free (sorting_key_tail);
-	} else {
-		sorting_key = NULL;
-	}
-	g_free (sorting_name);
-
-	return sorting_key;
+	rb_entry_view_resort_model (RB_ENTRY_VIEW (object));
 }
 
 static void
diff --git a/sources/rb-removable-media-source.c b/sources/rb-removable-media-source.c
index 70eab4d..75fd0c2 100644
--- a/sources/rb-removable-media-source.c
+++ b/sources/rb-removable-media-source.c
@@ -45,7 +45,6 @@
 #include <gtk/gtk.h>
 
 #include "rhythmdb.h"
-#include "eel-gconf-extensions.h"
 #include "rb-removable-media-source.h"
 #include "rb-removable-media-manager.h"
 #include "rb-encoder.h"
@@ -138,7 +137,6 @@ rb_removable_media_source_class_init (RBRemovableMediaSourceClass *klass)
 	source_class->impl_uri_is_source = impl_uri_is_source;
 	source_class->impl_get_delete_action = impl_get_delete_action;
 
-	browser_source_class->impl_get_paned_key = NULL;
 	browser_source_class->impl_has_drop_support = (RBBrowserSourceFeatureFunc) rb_false_function;
 
 	klass->impl_should_paste = impl_should_paste;
diff --git a/sources/rb-source.c b/sources/rb-source.c
index 03b7659..227a31f 100644
--- a/sources/rb-source.c
+++ b/sources/rb-source.c
@@ -61,7 +61,6 @@ static void rb_source_get_property (GObject *object,
 
 static void default_get_status (RBDisplayPage *page, char **text, char **progress_text, float *progress);
 static void default_activate (RBDisplayPage *page);
-static char * default_get_browser_key (RBSource *source);
 static GList *default_get_property_views (RBSource *source);
 static gboolean default_can_rename (RBSource *source);
 static GList *default_copy (RBSource *source);
@@ -112,6 +111,8 @@ struct _RBSourcePrivate
 	guint update_status_id;
 	RhythmDBEntryType *entry_type;
 	RBSourceSearchType search_type;
+
+	GSettings *settings;
 };
 
 enum
@@ -122,7 +123,9 @@ enum
 	PROP_ENTRY_TYPE,
 	PROP_BASE_QUERY_MODEL,
 	PROP_PLAY_ORDER,
-	PROP_SEARCH_TYPE
+	PROP_SEARCH_TYPE,
+	PROP_SETTINGS,
+	PROP_SHOW_BROWSER
 };
 
 enum
@@ -148,8 +151,6 @@ rb_source_class_init (RBSourceClass *klass)
 	page_class->get_status = default_get_status;
 
 	klass->impl_can_browse = (RBSourceFeatureFunc) rb_false_function;
-	klass->impl_get_browser_key = default_get_browser_key;
-	klass->impl_browser_toggled = NULL;
 	klass->impl_get_property_views = default_get_property_views;
 	klass->impl_can_rename = default_can_rename;
 	klass->impl_can_cut = (RBSourceFeatureFunc) rb_false_function;
@@ -251,6 +252,32 @@ rb_source_class_init (RBSourceClass *klass)
 							    RB_SOURCE_SEARCH_NONE,
 							    G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 	/**
+	 * RBSource:settings:
+	 *
+	 * The #GSettings instance storing settings for the source.  The instance must
+	 * have a schema of org.gnome.Rhythmbox.Source.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_SETTINGS,
+					 g_param_spec_object ("settings",
+							      "settings",
+							      "GSettings instance",
+							      G_TYPE_SETTINGS,
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	/**
+	 * RBSource:show-browser:
+	 *
+	 * Whether the browser widget for the source (if any) should be displayed.
+	 * This should be overridden in sources that include a browser widget.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_SHOW_BROWSER,
+					 g_param_spec_boolean ("show-browser",
+							       "show browser",
+							       "whether the browser widget should be shown",
+							       TRUE,
+							       G_PARAM_READWRITE));
+	/**
 	 * RBSource::filter-changed:
 	 * @source: the #RBSource
 	 *
@@ -295,6 +322,10 @@ rb_source_dispose (GObject *object)
 		g_source_remove (source->priv->update_status_id);
 		source->priv->update_status_id = 0;
 	}
+	if (source->priv->settings != NULL) {
+		g_object_unref (source->priv->settings);
+		source->priv->settings = NULL;
+	}
 
 	G_OBJECT_CLASS (rb_source_parent_class)->dispose (object);
 }
@@ -416,6 +447,12 @@ rb_source_set_property (GObject *object,
 	case PROP_SEARCH_TYPE:
 		source->priv->search_type = g_value_get_enum (value);
 		break;
+	case PROP_SETTINGS:
+		source->priv->settings = g_value_dup_object (value);
+		break;
+	case PROP_SHOW_BROWSER:
+		/* not connected to anything here */
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -449,6 +486,12 @@ rb_source_get_property (GObject *object,
 	case PROP_SEARCH_TYPE:
 		g_value_set_enum (value, source->priv->search_type);
 		break;
+	case PROP_SETTINGS:
+		g_value_set_object (value, source->priv->settings);
+		break;
+	case PROP_SHOW_BROWSER:
+		g_value_set_boolean (value, FALSE);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -491,28 +534,6 @@ default_get_status (RBDisplayPage *page,
 	}
 }
 
-static char *
-default_get_browser_key (RBSource *source)
-{
-	return NULL;
-}
-
-/**
- * rb_source_get_browser_key:
- * @source: a #RBSource
- *
- * Gets the GConf key controlling browser visibility
- *
- * Return value: the GConf key name (allocated)
- */
-char *
-rb_source_get_browser_key (RBSource *source)
-{
-	RBSourceClass *klass = RB_SOURCE_GET_CLASS (source);
-
-	return klass->impl_get_browser_key (source);
-}
-
 /**
  * rb_source_can_browse:
  * @source: a #RBSource
@@ -530,23 +551,6 @@ rb_source_can_browse (RBSource *source)
 }
 
 /**
- * rb_source_browser_toggled:
- * @source: a #RBSource
- * @enabled: TRUE if the browser should be visible
- *
- * Called when the visibility of the browser changes.
- */
-void
-rb_source_browser_toggled (RBSource *source,
-			   gboolean enabled)
-{
-	RBSourceClass *klass = RB_SOURCE_GET_CLASS (source);
-
-	if (klass->impl_browser_toggled != NULL)
-		klass->impl_browser_toggled (source, enabled);
-}
-
-/**
  * rb_source_notify_filter_changed:
  * @source: a #RBSource
  *
@@ -1342,6 +1346,121 @@ _rb_source_set_import_status (RBSource *source, RhythmDBImportJob *job, char **p
 	*progress = ((float)imported / (float)total);
 }
 
+static gboolean
+sort_order_get_mapping (GValue *value, GVariant *variant, gpointer data)
+{
+	const char *column;
+	gboolean sort_type;
+	char *str;
+
+	g_variant_get (variant, "(&sb)", &column, &sort_type);
+	str = g_strdup_printf ("%s,%s", column, sort_type ? "ascending" : "descending");
+	g_value_take_string (value, str);
+	return TRUE;
+}
+
+static GVariant *
+sort_order_set_mapping (const GValue *value, const GVariantType *expected_type, gpointer data)
+{
+	gboolean sort_type;
+	GVariant *var;
+	char **strs;
+
+	strs = g_strsplit (g_value_get_string (value), ",", 0);
+	if (!strcmp ("ascending", strs[1])) {
+		sort_type = TRUE;
+	} else if (!strcmp ("descending", strs[1])) {
+		sort_type = FALSE;
+	} else {
+		g_warning ("atttempting to sort in unknown direction");
+		sort_type = TRUE;
+	}
+
+	var = g_variant_new ("(sb)", strs[0], sort_type);
+	g_strfreev (strs);
+	return var;
+}
+
+static void
+sync_paned_position (GSettings *settings, GObject *paned)
+{
+	int pos;
+	g_object_get (paned, "position", &pos, NULL);
+
+	if (pos != g_settings_get_int (settings, "paned-position")) {
+		g_settings_set_int (settings, "paned-position", pos);
+	}
+}
+
+static void
+paned_position_changed_cb (GObject *paned, GParamSpec *pspec, GSettings *settings)
+{
+	rb_settings_delayed_sync (settings,
+				  (RBDelayedSyncFunc) sync_paned_position,
+				  g_object_ref (paned),
+				  g_object_unref);
+}
+
+/**
+ * rb_source_bind_settings:
+ * @source: the #RBSource
+ * @entry_view: (allow-none): the #RBEntryView for the source
+ * @paned: (allow-none): the #GtkPaned containing the entry view and the browser
+ * @browser: (allow-none):  the browser (typically a #RBLibraryBrowser) for the source
+ *
+ * Binds the source's #GSettings instance to the given widgets.  Should be called
+ * from the source's constructed method.
+ *
+ * If the browser widget has a browser-views property, it will be bound to the
+ * browser-views settings key.
+ */
+void
+rb_source_bind_settings (RBSource *source, GtkWidget *entry_view, GtkWidget *paned, GtkWidget *browser)
+{
+	char *name;
+	GSettings *common_settings;
+
+	common_settings = g_settings_new ("org.gnome.rhythmbox.sources");
+	g_object_get (source, "name", &name, NULL);
+
+	if (entry_view != NULL) {
+		rb_debug ("binding entry view sort order for %s", name);
+		if (source->priv->settings) {
+			g_settings_bind_with_mapping (source->priv->settings, "sorting", entry_view, "sort-order",
+						      G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_NO_SENSITIVITY,
+						      (GSettingsBindGetMapping) sort_order_get_mapping,
+						      (GSettingsBindSetMapping) sort_order_set_mapping,
+						      NULL, NULL);
+		}
+
+		g_settings_bind (common_settings, "visible-columns",
+				 entry_view, "visible-columns",
+				 G_SETTINGS_BIND_DEFAULT);
+	}
+
+	if (paned != NULL && source->priv->settings != NULL) {
+		rb_debug ("binding paned position for %s", name);
+		/* can't use a normal binding here, as we want to delay writing to the
+		 * setting while the separator is being dragged.
+		 */
+		g_settings_bind (source->priv->settings, "paned-position", paned, "position", G_SETTINGS_BIND_GET);
+		g_signal_connect_object (paned, "notify::position", G_CALLBACK (paned_position_changed_cb), source->priv->settings, 0);
+	}
+
+	if (browser) {
+		rb_debug ("binding show-browser for %s", name);
+		if (source->priv->settings) {
+			g_settings_bind (source->priv->settings, "show-browser", source, "show-browser", G_SETTINGS_BIND_DEFAULT);
+		}
+
+		if (g_object_class_find_property (G_OBJECT_GET_CLASS (browser), "browser-views")) {
+			g_settings_bind (common_settings, "browser-views", browser, "browser-views", G_SETTINGS_BIND_DEFAULT);
+		}
+	}
+
+	g_free (name);
+}
+
 /* This should really be standard. */
 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
 
diff --git a/sources/rb-source.h b/sources/rb-source.h
index f7d0ff8..81f835d 100644
--- a/sources/rb-source.h
+++ b/sources/rb-source.h
@@ -94,8 +94,6 @@ struct _RBSourceClass
 	/* methods */
 
 	gboolean	(*impl_can_browse)	(RBSource *source);
-	char *		(*impl_get_browser_key)	(RBSource *source);
-	void		(*impl_browser_toggled)	(RBSource *source, gboolean enabled);
 
 	RBEntryView *	(*impl_get_entry_view)	(RBSource *source);
 	GList *		(*impl_get_property_views)	(RBSource *source);
@@ -152,8 +150,6 @@ void		rb_source_update_play_statistics(RBSource *source, RhythmDB *db,
 /* general interface */
 
 gboolean	rb_source_can_browse		(RBSource *source);
-char *		rb_source_get_browser_key	(RBSource *source);
-void		rb_source_browser_toggled	(RBSource *source, gboolean enabled);
 
 RBEntryView *	rb_source_get_entry_view	(RBSource *source);
 
@@ -216,6 +212,10 @@ void		_rb_source_set_import_status	(RBSource *source,
 						 RhythmDBImportJob *job,
 						 char **progress_text,
 						 float *progress);
+void		rb_source_bind_settings		(RBSource *source,
+						 GtkWidget *entry_view,
+						 GtkWidget *paned,
+						 GtkWidget *browser);
 
 G_END_DECLS
 
diff --git a/sources/rb-static-playlist-source.c b/sources/rb-static-playlist-source.c
index a119ab4..3cd50a0 100644
--- a/sources/rb-static-playlist-source.c
+++ b/sources/rb-static-playlist-source.c
@@ -76,7 +76,6 @@ static GList * impl_cut (RBSource *source);
 static RBTrackTransferBatch *impl_paste (RBSource *asource, GList *entries);
 static void impl_delete (RBSource *source);
 static void impl_search (RBSource *asource, RBSourceSearch *search, const char *cur_text, const char *new_text);
-static void impl_browser_toggled (RBSource *source, gboolean enabled);
 static void impl_reset_filters (RBSource *asource);
 static gboolean impl_receive_drag (RBDisplayPage *page, GtkSelectionData *data);
 static GList *impl_get_search_actions (RBSource *source);
@@ -130,7 +129,8 @@ static GtkRadioActionEntry rb_static_playlist_source_radio_actions [] =
 enum
 {
 	PROP_0,
-	PROP_BASE_QUERY_MODEL
+	PROP_BASE_QUERY_MODEL,
+	PROP_SHOW_BROWSER
 };
 
 G_DEFINE_TYPE (RBStaticPlaylistSource, rb_static_playlist_source, RB_TYPE_PLAYLIST_SOURCE)
@@ -181,7 +181,6 @@ rb_static_playlist_source_class_init (RBStaticPlaylistSourceClass *klass)
 	source_class->impl_search = impl_search;
 	source_class->impl_reset_filters = impl_reset_filters;
 	source_class->impl_can_browse = (RBSourceFeatureFunc) rb_true_function;
-	source_class->impl_browser_toggled = impl_browser_toggled;
 	source_class->impl_get_property_views = impl_get_property_views;
 	source_class->impl_get_search_actions = impl_get_search_actions;
 	source_class->impl_want_uri = impl_want_uri;
@@ -191,6 +190,9 @@ rb_static_playlist_source_class_init (RBStaticPlaylistSourceClass *klass)
 	g_object_class_override_property (object_class,
 					  PROP_BASE_QUERY_MODEL,
 					  "base-query-model");
+	g_object_class_override_property (object_class,
+					  PROP_SHOW_BROWSER,
+					  "show-browser");
 
 	g_type_class_add_private (klass, sizeof (RBStaticPlaylistSourcePrivate));
 }
@@ -340,6 +342,8 @@ rb_static_playlist_source_constructed (GObject *object)
 	gtk_container_remove (GTK_CONTAINER (source), GTK_WIDGET (songs));
 	gtk_paned_pack2 (GTK_PANED (priv->paned), GTK_WIDGET (songs), TRUE, FALSE);
 	gtk_container_add (GTK_CONTAINER (source), priv->paned);
+
+	rb_source_bind_settings (RB_SOURCE (source), GTK_WIDGET (songs), priv->paned, GTK_WIDGET (priv->browser));
 	g_object_unref (songs);
 
 	/* watch these to find out when things are dropped into the entry view */
@@ -360,7 +364,7 @@ rb_static_playlist_source_constructed (GObject *object)
  * rb_static_playlist_source_new:
  * @shell: the #RBShell
  * @name: the playlist name
- * @sorting_name: the sorting name for the playlist (GConf key friendly)
+ * @settings_name: the settings name for the playlist (GSettings path friendly)
  * @local: if %TRUE, the playlist is local to the library
  * @entry_type: type of database entries that can be added to the playlist.
  *
@@ -369,17 +373,25 @@ rb_static_playlist_source_constructed (GObject *object)
  * Return value: new playlist.
  */
 RBSource *
-rb_static_playlist_source_new (RBShell *shell, const char *name, const char *sorting_name, gboolean local, RhythmDBEntryType *entry_type)
+rb_static_playlist_source_new (RBShell *shell, const char *name, const char *settings_name, gboolean local, RhythmDBEntryType *entry_type)
 {
+	GSettings *settings;
+
 	if (name == NULL)
 		name = "";
 
-	if (sorting_name == NULL)
-		sorting_name = "";
+	if (settings_name != NULL) {
+		char *path;
+		path = g_strdup_printf ("/org/gnome/rhythmbox/playlist/%s/", settings_name);
+		settings = g_settings_new_with_path ("org.gnome.rhythmbox.source", path);
+		g_free (path);
+	} else {
+		settings = NULL;
+	}
 
 	return RB_SOURCE (g_object_new (RB_TYPE_STATIC_PLAYLIST_SOURCE,
 					"name", name,
-					"sorting-name", sorting_name,
+					"settings", settings,
 					"shell", shell,
 					"is-local", local,
 					"entry-type", entry_type,
@@ -393,9 +405,15 @@ rb_static_playlist_source_set_property (GObject *object,
 					const GValue *value,
 					GParamSpec *pspec)
 {
-	/*RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);*/
+	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);
 
 	switch (prop_id) {
+	case PROP_SHOW_BROWSER:
+		if (g_value_get_boolean (value))
+			gtk_widget_show (GTK_WIDGET (priv->browser));
+		else
+			gtk_widget_hide (GTK_WIDGET (priv->browser));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -414,6 +432,9 @@ rb_static_playlist_source_get_property (GObject *object,
 	case PROP_BASE_QUERY_MODEL:
 		g_value_set_object (value, priv->base_model);
 		break;
+	case PROP_SHOW_BROWSER:
+		g_value_set_boolean (value, gtk_widget_get_visible (GTK_WIDGET (priv->browser)));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -564,19 +585,6 @@ impl_get_property_views (RBSource *source)
 	return ret;
 }
 
-static void
-impl_browser_toggled (RBSource *source, gboolean enabled)
-{
-	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source);
-
-	priv->browser_shown = enabled;
-
-	if (enabled)
-		gtk_widget_show (GTK_WIDGET (priv->browser));
-	else
-		gtk_widget_hide (GTK_WIDGET (priv->browser));
-}
-
 static GPtrArray *
 construct_query_from_selection (RBStaticPlaylistSource *source)
 {
@@ -791,7 +799,7 @@ _add_location_cb (GFile *file,
 		rb_static_playlist_source_add_location_internal (source, uri, -1);
 		g_free (uri);
 	}
-	return TRUE;	
+	return TRUE;
 }
 
 /**
diff --git a/sources/rb-streaming-source.c b/sources/rb-streaming-source.c
index 34cc9e2..37f6b31 100644
--- a/sources/rb-streaming-source.c
+++ b/sources/rb-streaming-source.c
@@ -47,7 +47,6 @@
 #include "rhythmdb-query-model.h"
 #include "rb-util.h"
 #include "rb-file-helpers.h"
-#include "rb-preferences.h"
 #include "rb-dialog.h"
 #include "rb-debug.h"
 #include "rb-shell.h"
diff --git a/widgets/rb-entry-view.c b/widgets/rb-entry-view.c
index 2b8004d..390cb12 100644
--- a/widgets/rb-entry-view.c
+++ b/widgets/rb-entry-view.c
@@ -42,14 +42,6 @@
  * minimum width set.  Otherwise, the tree view must measure the contents of each
  * row to assign sizes, which is very slow for large track lists.  All the predefined
  * column types handle this correctly.
- *
- * The set of visible columns is controlled by a (single) GConf key, which
- * contains a comma-delimited list of property names for which the associated
- * columns are visible.  The entry view object tracks this automatically.
- *
- * If a GConf key for sorting is provided when constructing the entry view,
- * it is watched and updated.  The sort settings consist of a column name
- * and an order (ascending or descending).
  */
 
 /**
@@ -87,6 +79,7 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <gio/gio.h>
 #include <glib.h>
 
 #include "rb-tree-dnd.h"
@@ -99,8 +92,6 @@
 #include "rb-cell-renderer-pixbuf.h"
 #include "rb-cell-renderer-rating.h"
 #include "rb-stock-icons.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 #include "rb-shell-player.h"
 #include "rb-cut-and-paste-code.h"
 
@@ -155,14 +146,6 @@ static void rb_entry_view_rows_reordered_cb (GtkTreeModel *model,
 					     gint *order,
 					     RBEntryView *view);
 static void rb_entry_view_sync_columns_visible (RBEntryView *view);
-static void rb_entry_view_columns_config_changed_cb (GConfClient* client,
-						    guint cnxn_id,
-						    GConfEntry *entry,
-						    gpointer user_data);
-static void rb_entry_view_sort_key_changed_cb (GConfClient* client,
-					       guint cnxn_id,
-					       GConfEntry *entry,
-					       gpointer user_data);
 static void rb_entry_view_rated_cb (RBCellRendererRating *cellrating,
 				   const char *path,
 				   double rating,
@@ -206,22 +189,20 @@ struct RBEntryViewPrivate
 	gboolean is_drag_dest;
 
 	char *sorting_key;
-	guint sorting_gconf_notification_id;
 	GtkTreeViewColumn *sorting_column;
 	gint sorting_order;
 	char *sorting_column_name;
 	RhythmDBPropType type_ahead_propid;
+	char **visible_columns;
 
 	gboolean have_selection, have_complete_selection;
 
 	GHashTable *column_key_map;
 
-	guint gconf_notification_id;
 	GHashTable *propid_column_map;
 	GHashTable *column_sort_data_map;
 };
 
-#define RB_ENTRY_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_ENTRY_VIEW, RBEntryViewPrivate))
 
 enum
 {
@@ -232,7 +213,6 @@ enum
 	ENTRY_ACTIVATED,
 	SHOW_POPUP,
 	HAVE_SEL_CHANGED,
-	SORT_ORDER_CHANGED,
 	LAST_SIGNAL
 };
 
@@ -242,10 +222,11 @@ enum
 	PROP_DB,
 	PROP_SHELL_PLAYER,
 	PROP_MODEL,
-	PROP_SORTING_KEY,
+	PROP_SORT_ORDER,
 	PROP_IS_DRAG_SOURCE,
 	PROP_IS_DRAG_DEST,
-	PROP_PLAYING_STATE
+	PROP_PLAYING_STATE,
+	PROP_VISIBLE_COLUMNS
 };
 
 G_DEFINE_TYPE (RBEntryView, rb_entry_view, GTK_TYPE_SCROLLED_WINDOW)
@@ -333,16 +314,16 @@ rb_entry_view_class_init (RBEntryViewClass *klass)
 							      RHYTHMDB_TYPE_QUERY_MODEL,
 							      G_PARAM_READWRITE));
 	/**
-	 * RBEntryView:sort-key:
+	 * RBEntryView:sort-order:
 	 *
-	 * The GConf key that controls the sort order for the view
+	 * The sort order for the track listing.
 	 */
 	g_object_class_install_property (object_class,
-					 PROP_SORTING_KEY,
-					 g_param_spec_string ("sort-key",
-							      "sorting key",
-							      "sorting key",
-							      "",
+					 PROP_SORT_ORDER,
+					 g_param_spec_string ("sort-order",
+							      "sorting order",
+							      "sorting order",
+							      NULL,
 							      G_PARAM_READWRITE));
 	/**
 	 * RBEntryView:is-drag-source:
@@ -384,6 +365,18 @@ rb_entry_view_class_init (RBEntryViewClass *klass)
 							   RB_ENTRY_VIEW_NOT_PLAYING,
 							   G_PARAM_READWRITE));
 	/**
+	 * RBEntryView:visible-columns:
+	 *
+	 * An array containing the names of the visible columns.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_VISIBLE_COLUMNS,
+					 g_param_spec_boxed ("visible-columns",
+							     "visible columns",
+							     "visible columns",
+							     G_TYPE_STRV,
+							     G_PARAM_READWRITE));
+	/**
 	 * RBEntryView::entry-added
 	 * @view: the #RBEntryView
 	 * @entry: the #RhythmDBEntry that was added
@@ -505,21 +498,6 @@ rb_entry_view_class_init (RBEntryViewClass *klass)
 			      G_TYPE_NONE,
 			      1,
 			      G_TYPE_BOOLEAN);
-	/**
-	 * RBEntryView::sort-order-changed:
-	 * @view: the #RBEntryView
-	 *
-	 * Emitted when the user changes the sort order for the view
-	 */
-	rb_entry_view_signals[SORT_ORDER_CHANGED] =
-		g_signal_new ("sort-order-changed",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (RBEntryViewClass, sort_order_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE,
-			      0);
 
 	g_type_class_add_private (klass, sizeof (RBEntryViewPrivate));
 
@@ -529,7 +507,7 @@ rb_entry_view_class_init (RBEntryViewClass *klass)
 static void
 rb_entry_view_init (RBEntryView *view)
 {
-	view->priv = RB_ENTRY_VIEW_GET_PRIVATE (view);
+	view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, RB_TYPE_ENTRY_VIEW, RBEntryViewPrivate);
 
 	view->priv->propid_column_map = g_hash_table_new (NULL, NULL);
 	view->priv->column_sort_data_map = g_hash_table_new_full (NULL, NULL, NULL, g_free);
@@ -549,16 +527,6 @@ rb_entry_view_dispose (GObject *object)
 
 	g_return_if_fail (view->priv != NULL);
 
-	if (view->priv->gconf_notification_id > 0) {
-		eel_gconf_notification_remove (view->priv->gconf_notification_id);
-		view->priv->gconf_notification_id = 0;
-	}
-
-	if (view->priv->sorting_gconf_notification_id > 0) {
-		eel_gconf_notification_remove (view->priv->sorting_gconf_notification_id);
-		view->priv->sorting_gconf_notification_id = 0;
-	}
-
 	if (view->priv->selection_changed_id > 0) {
 		g_source_remove (view->priv->selection_changed_id);
 		view->priv->selection_changed_id = 0;
@@ -601,7 +569,6 @@ rb_entry_view_finalize (GObject *object)
 	g_hash_table_destroy (view->priv->column_sort_data_map);
 	g_hash_table_destroy (view->priv->column_key_map);
 
-	g_free (view->priv->sorting_key);
 	g_free (view->priv->sorting_column_name);
 
 	G_OBJECT_CLASS (rb_entry_view_parent_class)->finalize (object);
@@ -699,7 +666,6 @@ rb_entry_view_set_property (GObject *object,
 			    const GValue *value,
 			    GParamSpec *pspec)
 {
-	char *old_sorting_key;
 	RBEntryView *view = RB_ENTRY_VIEW (object);
 
 	switch (prop_id) {
@@ -709,43 +675,8 @@ rb_entry_view_set_property (GObject *object,
 	case PROP_SHELL_PLAYER:
 		rb_entry_view_set_shell_player_internal (view, g_value_get_object (value));
 		break;
-	case PROP_SORTING_KEY:
-		/* Remove notification on old key, if any. */
-		if (view->priv->sorting_key) {
-			eel_gconf_notification_remove (view->priv->sorting_gconf_notification_id);
-			view->priv->sorting_gconf_notification_id = 0;
-		}
-
-		old_sorting_key = view->priv->sorting_key;
-		view->priv->sorting_key = g_value_dup_string (value);
-
-		if (view->priv->sorting_key && view->priv->sorting_key[0] != '\0') {
-			char *new_sorting_type;
-
-			/* Set up notification on the new key. */
-			view->priv->sorting_gconf_notification_id =
-				eel_gconf_notification_add (view->priv->sorting_key,
-							    rb_entry_view_sort_key_changed_cb,
-							    view);
-
-			rb_entry_view_set_columns_clickable (view, TRUE);
-
-			/* If there was already a sorting key, assume this is a rename. */
-			if (old_sorting_key && old_sorting_key[0] != '\0') {
-				/* Propagate existing sort order into the new GConf key. */
-				eel_gconf_set_string (view->priv->sorting_key,
-						      rb_entry_view_get_sorting_type (view));
-
-				eel_gconf_unset (old_sorting_key);
-			}
-
-			/* Synchronise UI sorting order with the new key. */
-			new_sorting_type = eel_gconf_get_string (view->priv->sorting_key);
-			rb_entry_view_set_sorting_type (view, new_sorting_type);
-			g_free (new_sorting_type);
-		}
-
-		g_free (old_sorting_key);
+	case PROP_SORT_ORDER:
+		rb_entry_view_set_sorting_type (view, g_value_get_string (value));
 		break;
 	case PROP_MODEL:
 		rb_entry_view_set_model_internal (view, g_value_get_object (value));
@@ -764,6 +695,11 @@ rb_entry_view_set_property (GObject *object,
 			rb_entry_view_emit_row_changed (view, view->priv->playing_entry);
 		}
 		break;
+	case PROP_VISIBLE_COLUMNS:
+		g_strfreev (view->priv->visible_columns);
+		view->priv->visible_columns = g_value_dup_boxed (value);
+		rb_entry_view_sync_columns_visible (view);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -785,8 +721,8 @@ rb_entry_view_get_property (GObject *object,
 	case PROP_SHELL_PLAYER:
 		g_value_set_object (value, view->priv->shell_player);
 		break;
-	case PROP_SORTING_KEY:
-		g_value_set_string (value, view->priv->sorting_key);
+	case PROP_SORT_ORDER:
+		g_value_take_string (value, rb_entry_view_get_sorting_type (view));
 		break;
 	case PROP_MODEL:
 		g_value_set_object (value, view->priv->model);
@@ -800,6 +736,9 @@ rb_entry_view_get_property (GObject *object,
 	case PROP_PLAYING_STATE:
 		g_value_set_int (value, view->priv->playing_state);
 		break;
+	case PROP_VISIBLE_COLUMNS:
+		g_value_set_boxed (value, view->priv->visible_columns);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -810,7 +749,6 @@ rb_entry_view_get_property (GObject *object,
  * rb_entry_view_new:
  * @db: the #RhythmDB instance
  * @shell_player: the #RBShellPlayer instance
- * @sort_key: the GConf key controlling the sort order for the view
  * @is_drag_source: if TRUE, the view should act as a drag and drop data source
  * @is_drag_dest: if TRUE, the view should act as a drag and drop destination
  *
@@ -826,7 +764,6 @@ rb_entry_view_get_property (GObject *object,
 RBEntryView *
 rb_entry_view_new (RhythmDB *db,
 		   GObject *shell_player,
-		   const char *sort_key,
 		   gboolean is_drag_source,
 		   gboolean is_drag_dest)
 {
@@ -840,7 +777,6 @@ rb_entry_view_new (RhythmDB *db,
 					   "shadow_type", GTK_SHADOW_IN,
 					   "db", db,
 					   "shell-player", RB_SHELL_PLAYER (shell_player),
-					   "sort-key", sort_key,
 					   "is-drag-source", is_drag_source,
 					   "is-drag-dest", is_drag_dest,
 					   NULL));
@@ -1139,6 +1075,7 @@ rb_entry_view_sync_sorting (RBEntryView *view)
 
 	column = g_hash_table_lookup (view->priv->column_key_map, column_name);
 	if (column == NULL) {
+		rb_debug ("couldn't find column %s", column_name);
 		g_free (column_name);
 		return;
 	}
@@ -1164,7 +1101,7 @@ rb_entry_view_sync_sorting (RBEntryView *view)
 		view->priv->type_ahead_propid = RHYTHMDB_PROP_TITLE;
 
 	rb_debug ("emitting sort order changed");
-	g_signal_emit (G_OBJECT (view), rb_entry_view_signals[SORT_ORDER_CHANGED], 0);
+	g_object_notify (G_OBJECT (view), "sort-order");
 
 	g_free (column_name);
 }
@@ -1311,10 +1248,6 @@ rb_entry_view_column_clicked_cb (GtkTreeViewColumn *column, RBEntryView *view)
 		sort_order = GTK_SORT_ASCENDING;
 
 	rb_entry_view_set_sorting_order (view, clicked_column, sort_order);
-
-	/* update the sort order in GConf */
-	if (view->priv->sorting_key)
-		eel_gconf_set_string (view->priv->sorting_key, rb_entry_view_get_sorting_type(view));
 }
 
 /**
@@ -1919,11 +1852,6 @@ rb_entry_view_constructed (GObject *object)
 					     _("Now Playing"));
 	}
 
-	view->priv->gconf_notification_id =
-		eel_gconf_notification_add (CONF_UI_COLUMNS_SETUP,
-					    rb_entry_view_columns_config_changed_cb,
-					    view);
-
 	{
 		RhythmDBQueryModel *query_model;
 		query_model = rhythmdb_query_model_new_empty (view->priv->db);
@@ -2452,47 +2380,6 @@ rb_entry_view_enable_drag_source (RBEntryView *view,
 }
 
 static void
-rb_entry_view_sort_key_changed_cb (GConfClient* client,
-				   guint cnxn_id,
-				   GConfEntry *entry,
-				   gpointer user_data)
-{
-	RBEntryView *view = user_data;
-
-	g_return_if_fail (RB_IS_ENTRY_VIEW (view));
-
-	rb_entry_view_set_sorting_type (view, eel_gconf_get_string (view->priv->sorting_key));
-}
-
-static void
-rb_entry_view_columns_config_changed_cb (GConfClient* client,
-					guint cnxn_id,
-					GConfEntry *entry,
-					gpointer user_data)
-{
-	RBEntryView *view = user_data;
-
-	g_return_if_fail (RB_IS_ENTRY_VIEW (view));
-
-	rb_entry_view_sync_columns_visible (view);
-}
-
-static gint
-propid_from_name (const char *name)
-{
-	GEnumClass *prop_class = g_type_class_ref (RHYTHMDB_TYPE_PROP_TYPE);
-	GEnumValue *ev;
-	int ret;
-
-	ev = g_enum_get_value_by_name (prop_class, name);
-	if (ev)
-		ret = ev->value;
-	else
-		ret = -1;
-	return ret;
-}
-
-static void
 set_column_visibility (guint propid,
 		       GtkTreeViewColumn *column,
 		       GList *visible_props)
@@ -2511,29 +2398,23 @@ set_column_visibility (guint propid,
 static void
 rb_entry_view_sync_columns_visible (RBEntryView *view)
 {
-	char **items;
 	GList *visible_properties = NULL;
-	char *config = eel_gconf_get_string (CONF_UI_COLUMNS_SETUP);
 
 	g_return_if_fail (view != NULL);
-	g_return_if_fail (config != NULL);
 
-	items = g_strsplit (config, ",", 0);
-	if (items != NULL) {
+	if (view->priv->visible_columns != NULL) {
 		int i;
-		for (i = 0; items[i] != NULL && *(items[i]); i++) {
-			int value = propid_from_name (items[i]);
+		for (i = 0; view->priv->visible_columns[i] != NULL && *(view->priv->visible_columns[i]); i++) {
+			int value = rhythmdb_propid_from_nice_elt_name (view->priv->db, (const xmlChar *)view->priv->visible_columns[i]);
+			rb_debug ("visible columns: %s => %d\n", view->priv->visible_columns[i], value);
 
 			if ((value >= 0) && (value < RHYTHMDB_NUM_PROPERTIES))
 				visible_properties = g_list_prepend (visible_properties, GINT_TO_POINTER (value));
 		}
-		g_strfreev (items);
 	}
 
 	g_hash_table_foreach (view->priv->propid_column_map, (GHFunc) set_column_visibility, visible_properties);
-
 	g_list_free (visible_properties);
-	g_free (config);
 }
 
 /**
diff --git a/widgets/rb-entry-view.h b/widgets/rb-entry-view.h
index ff2612b..e9741e4 100644
--- a/widgets/rb-entry-view.h
+++ b/widgets/rb-entry-view.h
@@ -99,7 +99,6 @@ struct _RBEntryViewClass
 
 	void (*have_selection_changed) (RBEntryView *view, gboolean have_selection);
 	void (*selection_changed)       (RBEntryView *view);
-	void (*sort_order_changed)     (RBEntryView *view);
 
 	void (*show_popup)             (RBEntryView *view, gboolean over_entry);
 };
@@ -108,7 +107,6 @@ GType		rb_entry_view_get_type			(void);
 
 RBEntryView *	rb_entry_view_new			(RhythmDB *db,
                                                          GObject *shell_player,
-							 const char *sort_key,
                                                          gboolean is_drag_source,
 							 gboolean is_drag_dest);
 
diff --git a/widgets/rb-header.c b/widgets/rb-header.c
index c2e4a6a..2a21756 100644
--- a/widgets/rb-header.c
+++ b/widgets/rb-header.c
@@ -38,9 +38,7 @@
 #include "rb-stock-icons.h"
 #include "rb-header.h"
 #include "rb-debug.h"
-#include "rb-preferences.h"
 #include "rb-shell-player.h"
-#include "eel-gconf-extensions.h"
 #include "rb-util.h"
 #include "rhythmdb.h"
 #include "rb-player.h"
@@ -71,8 +69,6 @@ static void rb_header_get_property (GObject *object,
 				    guint prop_id,
 				    GValue *value,
 				    GParamSpec *pspec);
-static void rb_header_set_show_timeline (RBHeader *header,
-			                 gboolean show);
 static void rb_header_update_elapsed (RBHeader *header);
 static void apply_slider_position (RBHeader *header);
 static gboolean slider_press_callback (GtkWidget *widget, GdkEventButton *event, RBHeader *header);
@@ -96,7 +92,7 @@ struct RBHeaderPrivate
 
 	GtkWidget *timeline;
 	GtkWidget *scaleline;
-	gboolean scaleline_shown;
+	gboolean show_remaining;
 
 	GtkWidget *scale;
 	GtkAdjustment *adjustment;
@@ -117,7 +113,9 @@ enum
 	PROP_DB,
 	PROP_SHELL_PLAYER,
 	PROP_SEEKABLE,
-	PROP_SLIDER_DRAGGING
+	PROP_SLIDER_DRAGGING,
+	PROP_SHOW_REMAINING,
+	PROP_SHOW_POSITION_SLIDER
 };
 
 #define TITLE_FORMAT  "<big><b>%s</b></big>"
@@ -190,6 +188,32 @@ rb_header_class_init (RBHeaderClass *klass)
 							       "slider dragging",
 							       FALSE,
 							       G_PARAM_READABLE));
+	/**
+	 * RBHeader:show-remaining:
+	 *
+	 * Whether to show remaining time (as opposed to elapsed time) in the numeric
+	 * time display.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_SHOW_REMAINING,
+					 g_param_spec_boolean ("show-remaining",
+							       "show remaining",
+							       "whether to show remaining or elapsed time",
+							       FALSE,
+							       G_PARAM_READWRITE));
+
+	/**
+	 * RBHeader:show-position-slider:
+	 *
+	 * Whether to show the playback position slider.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_SHOW_POSITION_SLIDER,
+					 g_param_spec_boolean ("show-position-slider",
+							       "show position slider",
+							       "whether to show the playback position slider",
+							       TRUE,
+							       G_PARAM_READWRITE));
 
 	g_type_class_add_private (klass, sizeof (RBHeaderPrivate));
 }
@@ -243,7 +267,6 @@ rb_header_init (RBHeader *header)
 	/* row for the position slider */
 	header->priv->scaleline = gtk_hbox_new (FALSE, 3);
 	gtk_box_pack_start (GTK_BOX (vbox), header->priv->scaleline, FALSE, FALSE, 0);
-	header->priv->scaleline_shown = FALSE;
 
 	header->priv->adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 10.0, 1.0, 10.0, 0.0));
 	header->priv->scale = gtk_hscale_new (header->priv->adjustment);
@@ -341,6 +364,13 @@ rb_header_set_property (GObject *object,
 	case PROP_SEEKABLE:
 		header->priv->seekable = g_value_get_boolean (value);
 		break;
+	case PROP_SHOW_REMAINING:
+		header->priv->show_remaining = g_value_get_boolean (value);
+		rb_header_update_elapsed (header);
+		break;
+	case PROP_SHOW_POSITION_SLIDER:
+		gtk_widget_set_visible (header->priv->scaleline, g_value_get_boolean (value));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -368,6 +398,12 @@ rb_header_get_property (GObject *object,
 	case PROP_SLIDER_DRAGGING:
 		g_value_set_boolean (value, header->priv->slider_dragging);
 		break;
+	case PROP_SHOW_REMAINING:
+		g_value_set_boolean (value, header->priv->show_remaining);
+		break;
+	case PROP_SHOW_POSITION_SLIDER:
+		g_value_set_boolean (value, gtk_widget_get_visible (header->priv->scaleline));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -538,7 +574,7 @@ rb_header_sync (RBHeader *header)
 		gtk_label_set_markup (GTK_LABEL (header->priv->song), label_text);
 		g_free (label_text);
 
-		rb_header_set_show_timeline (header, have_duration && header->priv->seekable);
+		gtk_widget_set_sensitive (header->priv->scaleline, have_duration && header->priv->seekable);
 		if (have_duration)
 			rb_header_sync_time (header);
 
@@ -551,7 +587,7 @@ rb_header_sync (RBHeader *header)
 		gtk_label_set_markup (GTK_LABEL (header->priv->song), label_text);
 		g_free (label_text);
 
-		rb_header_set_show_timeline (header, FALSE);
+		gtk_widget_set_sensitive (header->priv->scaleline, FALSE);
 
 		header->priv->slider_locked = TRUE;
 		gtk_adjustment_set_value (header->priv->adjustment, 0.0);
@@ -563,38 +599,6 @@ rb_header_sync (RBHeader *header)
 }
 
 /**
- * rb_header_set_show_position_slider:
- * @header: the #RBHeader
- * @show: whether the position slider should be shown
- *
- * Sets the visibility of the position slider.  This is not currently
- * used properly.
- */
-void
-rb_header_set_show_position_slider (RBHeader *header,
-				    gboolean show)
-{
-	if (header->priv->scaleline_shown == show)
-		return;
-
-	header->priv->scaleline_shown = show;
-
-	if (show) {
-		gtk_widget_show_all (GTK_WIDGET (header->priv->scaleline));
-		rb_header_sync_time (header);
-	} else {
-		gtk_widget_hide (GTK_WIDGET (header->priv->scaleline));
-	}
-}
-
-static void
-rb_header_set_show_timeline (RBHeader *header,
-			     gboolean show)
-{
-	gtk_widget_set_sensitive (header->priv->scaleline, show);
-}
-
-/**
  * rb_header_sync_time:
  * @header: the #RBHeader
  *
@@ -787,7 +791,7 @@ rb_header_update_elapsed (RBHeader *header)
 
 		elapsed_text = rb_make_elapsed_time_string (seconds,
 							    header->priv->duration,
-							    !eel_gconf_get_boolean (CONF_UI_TIME_DISPLAY));
+							    header->priv->show_remaining);
 		gtk_label_set_text (GTK_LABEL (header->priv->elapsed), elapsed_text);
 		g_free (elapsed_text);
 	} else {
diff --git a/widgets/rb-library-browser.c b/widgets/rb-library-browser.c
index 8b19bba..79fec72 100644
--- a/widgets/rb-library-browser.c
+++ b/widgets/rb-library-browser.c
@@ -36,8 +36,6 @@
 #include <gtk/gtk.h>
 
 #include "rb-library-browser.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 #include "rhythmdb-property-model.h"
 #include "rhythmdb-query-model.h"
 #include "rb-property-view.h"
@@ -65,10 +63,6 @@ static void view_selection_reset_cb (RBPropertyView *view,
 				     RBLibraryBrowser *widget);
 
 static void update_browser_views_visibility (RBLibraryBrowser *widget);
-static void rb_library_browser_views_changed (GConfClient *client,
-					      guint cnxn_id,
-					      GConfEntry *entry,
-					      RBLibraryBrowser *widget);
 
 typedef struct _RBLibraryBrowserRebuildData RBLibraryBrowserRebuildData;
 
@@ -112,8 +106,8 @@ typedef struct
 	RhythmDBQueryModel *input_model;
 	RhythmDBQueryModel *output_model;
 
-	guint browser_view_notify_id;
 	GSList *browser_views_group;
+	char *browser_views;
 
 	GHashTable *property_views;
 	GHashTable *selections;
@@ -127,7 +121,8 @@ enum
 	PROP_DB,
 	PROP_INPUT_MODEL,
 	PROP_OUTPUT_MODEL,
-	PROP_ENTRY_TYPE
+	PROP_ENTRY_TYPE,
+	PROP_BROWSER_VIEWS
 };
 
 typedef struct {
@@ -211,6 +206,18 @@ rb_library_browser_class_init (RBLibraryBrowserClass *klass)
 							      "Type of entry to display in this browser",
 							      RHYTHMDB_TYPE_ENTRY_TYPE,
 							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	/**
+	 * RBLibraryBrowser:browser-views:
+	 *
+	 * The set of browsers to display.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_BROWSER_VIEWS,
+					 g_param_spec_string ("browser-views",
+							      "browser views",
+							      "browser view selection",
+							      "artists-albums",
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	g_type_class_add_private (klass, sizeof (RBLibraryBrowserPrivate));
 }
@@ -261,9 +268,6 @@ rb_library_browser_constructed (GObject *object)
 	}
 
 	update_browser_views_visibility (browser);
-	priv->browser_view_notify_id =
-		eel_gconf_notification_add (CONF_UI_BROWSER_VIEWS,
-				(GConfClientNotifyFunc) rb_library_browser_views_changed, browser);
 }
 
 static void
@@ -271,11 +275,6 @@ rb_library_browser_dispose (GObject *object)
 {
 	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (object);
 	
-	if (priv->browser_view_notify_id != 0) {
-		eel_gconf_notification_remove (priv->browser_view_notify_id);
-		priv->browser_view_notify_id = 0;
-	}
-
 	if (priv->rebuild_data != NULL) {
 		/* this looks a bit odd, but removing the idle handler cleans up the
 		 * data too.
@@ -310,6 +309,7 @@ rb_library_browser_finalize (GObject *object)
 
 	g_hash_table_destroy (priv->property_views);
 	g_hash_table_destroy (priv->selections);
+	g_free (priv->browser_views);
 
 	G_OBJECT_CLASS (rb_library_browser_parent_class)->finalize (object);
 }
@@ -336,6 +336,11 @@ rb_library_browser_set_property (GObject *object,
 	case PROP_ENTRY_TYPE:
 		priv->entry_type = g_value_get_object (value);
 		break;
+	case PROP_BROWSER_VIEWS:
+		g_free (priv->browser_views);
+		priv->browser_views = g_value_dup_string (value);
+		update_browser_views_visibility (RB_LIBRARY_BROWSER (object));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -363,6 +368,9 @@ rb_library_browser_get_property (GObject *object,
 	case PROP_ENTRY_TYPE:
 		g_value_set_object (value, priv->entry_type);
 		break;
+	case PROP_BROWSER_VIEWS:
+		g_value_set_string (value, priv->browser_views);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -418,30 +426,17 @@ update_browser_views_visibility (RBLibraryBrowser *widget)
 	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (widget);
 	GList *properties = NULL;
 
-	{
-		int views = eel_gconf_get_integer (CONF_UI_BROWSER_VIEWS);
-
-		if (views == 0 || views == 2)
-			properties = g_list_prepend (properties, (gpointer)RHYTHMDB_PROP_ALBUM);
-		properties = g_list_prepend (properties, (gpointer)RHYTHMDB_PROP_ARTIST);
-		if (views == 1 || views == 2)
-			properties = g_list_prepend (properties, (gpointer)RHYTHMDB_PROP_GENRE);
-	}
+	if (strstr (priv->browser_views, "albums") != NULL)
+		properties = g_list_prepend (properties, (gpointer)RHYTHMDB_PROP_ALBUM);
+	properties = g_list_prepend (properties, (gpointer)RHYTHMDB_PROP_ARTIST);
+	if (strstr (priv->browser_views, "genres") != NULL)
+		properties = g_list_prepend (properties, (gpointer)RHYTHMDB_PROP_GENRE);
 
 	g_hash_table_foreach (priv->property_views, (GHFunc)update_browser_property_visibilty, properties);
 	g_list_free (properties);
 }
 
 static void
-rb_library_browser_views_changed (GConfClient *client,
-			          guint cnxn_id,
-			          GConfEntry *entry,
-			          RBLibraryBrowser *widget)
-{
-	update_browser_views_visibility (widget);
-}
-
-static void
 view_property_selected_cb (RBPropertyView *view,
 			   GList *selection,
 			   RBLibraryBrowser *widget)
diff --git a/widgets/rb-property-view.c b/widgets/rb-property-view.c
index 2340277..849c7d8 100644
--- a/widgets/rb-property-view.c
+++ b/widgets/rb-property-view.c
@@ -41,7 +41,6 @@
 #include "rhythmdb.h"
 #include "rhythmdb-property-model.h"
 #include "rb-stock-icons.h"
-#include "eel-gconf-extensions.h"
 #include "rb-util.h"
 
 static void rb_property_view_class_init (RBPropertyViewClass *klass);
diff --git a/widgets/rb-query-creator.c b/widgets/rb-query-creator.c
index f05584a..0a887a2 100644
--- a/widgets/rb-query-creator.c
+++ b/widgets/rb-query-creator.c
@@ -38,7 +38,6 @@
 #include "rb-query-creator-private.h"
 #include "rb-dialog.h"
 #include "rb-debug.h"
-#include "rb-preferences.h"
 #include "rb-builder-helpers.h"
 #include "rb-util.h"
 
diff --git a/widgets/rb-song-info.c b/widgets/rb-song-info.c
index 1250966..835ef49 100644
--- a/widgets/rb-song-info.c
+++ b/widgets/rb-song-info.c
@@ -49,8 +49,6 @@
 #include "rb-builder-helpers.h"
 #include "rb-dialog.h"
 #include "rb-rating.h"
-#include "rb-preferences.h"
-#include "eel-gconf-extensions.h"
 #include "rb-source.h"
 #include "rb-shell.h"
 #include "rb-file-helpers.h"



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