Index: plugins/ipod/rb-ipod-static-playlist-source.c
===================================================================
--- plugins/ipod/rb-ipod-static-playlist-source.c	(revision 0)
+++ plugins/ipod/rb-ipod-static-playlist-source.c	(revision 0)
@@ -0,0 +1,267 @@
+/*
+ *  Copyright (C) 2007 James Livingston  <doclivingston@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gpod/itdb.h>
+
+#include "rb-plugin.h"
+#include "rb-debug.h"
+#include "rb-util.h"
+#include "rhythmdb.h"
+
+#include "rb-ipod-static-playlist-source.h"
+
+static GObject *rb_ipod_static_playlist_source_constructor (GType type,
+					    guint n_construct_properties,
+					    GObjectConstructParam *construct_properties);
+static void rb_ipod_static_playlist_source_dispose (GObject *object);
+static void rb_ipod_static_playlist_source_set_property (GObject *object,
+			                  guint prop_id,
+			                  const GValue *value,
+			                  GParamSpec *pspec);
+static void rb_ipod_static_playlist_source_get_property (GObject *object,
+			                  guint prop_id,
+			                  GValue *value,
+			                  GParamSpec *pspec);
+
+static gboolean impl_show_popup (RBSource *source);
+
+
+static void source_name_changed_cb (RBIpodStaticPlaylistSource *source,
+				    GParamSpec *spec,
+				    gpointer data);
+
+typedef struct
+{
+	RbIpodDb	*ipod_db;
+	Itdb_Playlist	*itdb_playlist;
+	RBiPodSource	*ipod_source;
+} RBIpodStaticPlaylistSourcePrivate;
+
+RB_PLUGIN_DEFINE_TYPE(RBIpodStaticPlaylistSource,
+		      rb_ipod_static_playlist_source,
+		      RB_TYPE_STATIC_PLAYLIST_SOURCE)
+
+#define IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE(o)   (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE, RBIpodStaticPlaylistSourcePrivate))
+
+enum {
+	PROP_0,
+	PROP_IPOD_SOURCE,
+	PROP_IPOD_DB,
+	PROP_ITDB_PLAYLIST
+};
+
+
+static void
+rb_ipod_static_playlist_source_class_init (RBIpodStaticPlaylistSourceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
+
+	object_class->constructor = rb_ipod_static_playlist_source_constructor;
+	object_class->dispose = rb_ipod_static_playlist_source_dispose;
+	object_class->get_property = rb_ipod_static_playlist_source_get_property;
+	object_class->set_property = rb_ipod_static_playlist_source_set_property;
+
+	source_class->impl_show_popup = impl_show_popup;
+
+	g_object_class_install_property (object_class,
+					 PROP_IPOD_SOURCE,
+					 g_param_spec_object ("ipod-source",
+							      "ipod-source",
+							      "ipod-source",
+							      RB_TYPE_IPOD_SOURCE,
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+					 PROP_IPOD_DB,
+					 g_param_spec_object ("ipod-db",
+							      "ipod-db",
+							      "ipod-db",
+							      RB_TYPE_IPOD_DB,
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+					 PROP_ITDB_PLAYLIST,
+					 g_param_spec_pointer ("itdb-playlist",
+							      "itdb-playlist",
+							      "itdb-playlist",
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_type_class_add_private (klass, sizeof (RBIpodStaticPlaylistSourcePrivate));
+}
+
+static void
+rb_ipod_static_playlist_source_init (RBIpodStaticPlaylistSource *source)
+{
+
+}
+
+static GObject *
+rb_ipod_static_playlist_source_constructor (GType type, guint n_construct_properties,
+					    GObjectConstructParam *construct_properties)
+{
+	RBIpodStaticPlaylistSource *source;
+
+	source = RB_IPOD_STATIC_PLAYLIST_SOURCE  (G_OBJECT_CLASS (rb_ipod_static_playlist_source_parent_class)->
+			constructor (type, n_construct_properties, construct_properties));
+
+	g_signal_connect (G_OBJECT (source), "notify::name",
+			  (GCallback)source_name_changed_cb, NULL);
+
+	return G_OBJECT (source);
+}
+
+static void
+rb_ipod_static_playlist_source_dispose (GObject *object)
+{
+	RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);
+
+	if (priv->ipod_source) {
+		g_object_unref (priv->ipod_source);
+		priv->ipod_source = NULL;
+	}
+
+	if (priv->ipod_db) {
+		g_object_unref (priv->ipod_db);
+		priv->ipod_db = NULL;
+	}
+
+	G_OBJECT_CLASS (rb_ipod_static_playlist_source_parent_class)->dispose (object);
+}
+
+RBIpodStaticPlaylistSource *
+rb_ipod_static_playlist_source_new (RBShell *shell,
+				    RBiPodSource *ipod_source,
+				    RbIpodDb *ipod_db,
+				    Itdb_Playlist *playlist,
+				    RhythmDBEntryType entry_type)
+{
+	RBIpodStaticPlaylistSource *source;
+
+	g_assert (RB_IS_IPOD_SOURCE (ipod_source));
+
+	source = RB_IPOD_STATIC_PLAYLIST_SOURCE (g_object_new (RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE,
+							       "entry-type", entry_type,
+							       "shell", shell,
+							       "is-local", FALSE,
+							       "name", playlist->name,
+							       "ipod-source", ipod_source,
+							       "ipod-db", ipod_db,
+							       "itdb-playlist", playlist,
+							       NULL));
+
+	return source;
+}
+
+
+static void
+rb_ipod_static_playlist_source_set_property (GObject *object,
+				guint prop_id,
+				const GValue *value,
+				GParamSpec *pspec)
+{
+	RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_IPOD_SOURCE:
+		priv->ipod_source = g_value_dup_object (value);
+		break;
+	case PROP_IPOD_DB:
+		priv->ipod_db = g_value_dup_object (value);
+		break;
+	case PROP_ITDB_PLAYLIST:
+		priv->itdb_playlist = g_value_get_pointer (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+rb_ipod_static_playlist_source_get_property (GObject *object,
+				guint prop_id,
+				GValue *value,
+				GParamSpec *pspec)
+{
+	RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_IPOD_SOURCE:
+		g_value_set_object (value, priv->ipod_source);
+		break;
+	case PROP_IPOD_DB:
+		g_value_set_object (value, priv->ipod_db);
+		break;
+	case PROP_ITDB_PLAYLIST:
+		g_value_set_pointer (value, priv->itdb_playlist);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+
+Itdb_Playlist*
+rb_ipod_static_playlist_source_get_itdb_playlist (RBIpodStaticPlaylistSource *playlist)
+{
+	RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (playlist);
+
+	return priv->itdb_playlist;
+}
+
+RBiPodSource*
+rb_ipod_static_playlist_source_get_ipod_source (RBIpodStaticPlaylistSource *playlist)
+{
+	RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (playlist);
+
+	return priv->ipod_source;
+}
+
+static gboolean
+impl_show_popup (RBSource *source)
+{
+	_rb_source_show_popup (RB_SOURCE (source), "/iPodPlaylistSourcePopup");
+	return TRUE;
+}
+
+static void
+source_name_changed_cb (RBIpodStaticPlaylistSource *source,
+			GParamSpec *spec,
+			gpointer data)
+{
+	RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source);
+	char *name;
+
+	g_object_get (source, "name", &name, NULL);
+
+	if ((priv->itdb_playlist != NULL) && (strcmp (name, priv->itdb_playlist->name) != 0)) {
+		rb_debug ("changing playlist name to %s", name);
+		rb_ipod_db_rename_playlist (priv->ipod_db, priv->itdb_playlist, name);
+	}
+	g_free (name);
+}
+
Index: plugins/ipod/rb-ipod-source.h
===================================================================
--- plugins/ipod/rb-ipod-source.h	(revision 5249)
+++ plugins/ipod/rb-ipod-source.h	(working copy)
@@ -22,6 +22,8 @@
 #ifndef __RB_IPOD_SOURCE_H
 #define __RB_IPOD_SOURCE_H
 
+#include <libgnomevfs/gnome-vfs.h>
+
 #include "rb-shell.h"
 #include "rb-removable-media-source.h"
 #include "rhythmdb.h"
@@ -51,6 +53,10 @@ GType                   rb_ipod_source_r
 
 gboolean		rb_ipod_is_volume_ipod		(GnomeVFSVolume *volume);
 
+void			rb_ipod_source_new_playlist	(RBiPodSource *source);
+void			rb_ipod_source_remove_playlist	(RBiPodSource *ipod_source,
+							 RBSource *source);
+
 G_END_DECLS
 
 #endif /* __RB_IPOD_SOURCE_H */
Index: plugins/ipod/rb-ipod-db.c
===================================================================
--- plugins/ipod/rb-ipod-db.c	(revision 5249)
+++ plugins/ipod/rb-ipod-db.c	(working copy)
@@ -71,11 +71,16 @@ static void rb_ipod_db_queue_set_ipod_na
 static void rb_ipod_db_queue_add_track (RbIpodDb *db, Itdb_Track *track);
 static void rb_ipod_db_queue_add_playlist (RbIpodDb *db, 
 					   Itdb_Playlist *playlist);
+static void rb_ipod_db_queue_remove_playlist (RbIpodDb *db, 
+					   Itdb_Playlist *playlist);
+static void rb_ipod_db_queue_rename_playlist (RbIpodDb *db, 
+					   Itdb_Playlist *playlist,
+					   const char *name);
 static void rb_ipod_db_queue_add_to_playlist (RbIpodDb *ipod_db, 
 					      Itdb_Playlist *playlist,
 					      Itdb_Track *track);
 static void rb_ipod_db_queue_remove_from_playlist (RbIpodDb *ipod_db, 
-						   Itdb_Playlist *playlist,
+						  Itdb_Playlist *playlist,
 						   Itdb_Track *track);
 static void rb_ipod_db_queue_set_thumbnail (RbIpodDb *db,
 					    Itdb_Track *track,
@@ -107,7 +112,8 @@ G_DEFINE_TYPE (RbIpodDb, rb_ipod_db, G_T
 
 #define IPOD_DB_GET_PRIVATE(o)   (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_IPOD_DB, RbIpodDbPrivate))
 
-static void rb_itdb_save (RbIpodDb *ipod_db, GError **error)
+static void
+rb_itdb_save (RbIpodDb *ipod_db, GError **error)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -197,8 +203,10 @@ rb_ipod_db_class_init (RbIpodDbClass *kl
 enum _RbIpodDelayedActionType {
 	RB_IPOD_ACTION_SET_NAME,
 	RB_IPOD_ACTION_ADD_TRACK,
-	RB_IPOD_ACTION_ADD_PLAYLIST,
 	RB_IPOD_ACTION_REMOVE_TRACK,
+	RB_IPOD_ACTION_ADD_PLAYLIST,
+	RB_IPOD_ACTION_REMOVE_PLAYLIST,
+	RB_IPOD_ACTION_RENAME_PLAYLIST,
 	RB_IPOD_ACTION_SET_THUMBNAIL,
 	RB_IPOD_ACTION_ADD_TO_PLAYLIST,
 	RB_IPOD_ACTION_REMOVE_FROM_PLAYLIST
@@ -228,7 +236,8 @@ struct _RbIpodDelayedAction {
 	};
 };
 
-static void rb_ipod_free_delayed_action (RbIpodDelayedAction *action) 
+static void
+rb_ipod_free_delayed_action (RbIpodDelayedAction *action) 
 {
 	switch (action->type) {
 	case RB_IPOD_ACTION_SET_NAME:
@@ -241,7 +250,13 @@ static void rb_ipod_free_delayed_action 
 		itdb_track_free (action->track);
 		break;
 	case RB_IPOD_ACTION_ADD_PLAYLIST:
-		itdb_playlist_free (action->playlist);
+		/* Do nothing */
+		break;
+	case RB_IPOD_ACTION_REMOVE_PLAYLIST:
+		/* Do nothing */
+		break;
+	case RB_IPOD_ACTION_RENAME_PLAYLIST:
+		g_free (action->name);
 		break;
 	case RB_IPOD_ACTION_REMOVE_TRACK:
 		/* Do nothing */
@@ -256,7 +271,8 @@ static void rb_ipod_free_delayed_action 
 	g_free (action);
 }
 
-const char *rb_ipod_db_get_ipod_name (RbIpodDb *db)
+const char *
+rb_ipod_db_get_ipod_name (RbIpodDb *db)
 {
 	Itdb_Playlist *mpl;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (db);
@@ -307,7 +323,8 @@ rb_ipod_db_remove_track_internal (RbIpod
 }
 
 static void
-rb_ipod_db_set_thumbnail_internal (RbIpodDb *ipod_db, Itdb_Track *track, 
+rb_ipod_db_set_thumbnail_internal (RbIpodDb *ipod_db,
+				   Itdb_Track *track, 
 				   GdkPixbuf *pixbuf)
 {
 #ifndef HAVE_ITDB_TRACK_SET_THUMBNAILS_FROM_PIXBUF
@@ -357,6 +374,24 @@ rb_ipod_db_add_playlist_internal (RbIpod
 }
 
 static void
+rb_ipod_db_remove_playlist_internal (RbIpodDb *ipod_db, 
+				     Itdb_Playlist *playlist)
+{
+	itdb_playlist_remove (playlist);
+	rb_ipod_db_save_async (ipod_db);
+}
+
+static void
+rb_ipod_db_rename_playlist_internal (RbIpodDb *ipod_db, 
+				     Itdb_Playlist *playlist,
+				     const char *name)
+{
+	g_free (playlist->name);
+	playlist->name = g_strdup (name);
+	rb_ipod_db_save_async (ipod_db);
+}
+
+static void
 rb_ipod_db_add_track_internal (RbIpodDb *ipod_db, Itdb_Track *track)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -387,8 +422,10 @@ rb_ipod_db_remove_from_playlist_internal
 }
 
 
-void rb_ipod_db_set_thumbnail (RbIpodDb* ipod_db, Itdb_Track *track, 
-			       GdkPixbuf *pixbuf)
+void
+rb_ipod_db_set_thumbnail (RbIpodDb* ipod_db,
+			  Itdb_Track *track, 
+			  GdkPixbuf *pixbuf)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -399,7 +436,8 @@ void rb_ipod_db_set_thumbnail (RbIpodDb*
 	}
 }
 
-void rb_ipod_db_add_track (RbIpodDb* ipod_db, Itdb_Track *track)
+void
+rb_ipod_db_add_track (RbIpodDb* ipod_db, Itdb_Track *track)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -410,7 +448,8 @@ void rb_ipod_db_add_track (RbIpodDb* ipo
 	}
 }
 
-void rb_ipod_db_add_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist)
+void
+rb_ipod_db_add_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -421,7 +460,33 @@ void rb_ipod_db_add_playlist (RbIpodDb* 
 	}
 }
 
-void rb_ipod_db_remove_track (RbIpodDb* ipod_db, Itdb_Track *track)
+void
+rb_ipod_db_remove_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist)
+{
+	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
+
+	if (priv->read_only) {
+		rb_ipod_db_queue_remove_playlist (ipod_db, playlist);
+	} else {
+		rb_ipod_db_remove_playlist_internal (ipod_db, playlist);
+	}
+}
+
+void
+rb_ipod_db_rename_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist, const char *name)
+{
+	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
+
+	if (priv->read_only) {
+		rb_ipod_db_queue_rename_playlist (ipod_db, playlist, name);
+	} else {
+		rb_ipod_db_rename_playlist_internal (ipod_db, playlist, name);
+	}
+}
+
+
+void
+rb_ipod_db_remove_track (RbIpodDb* ipod_db, Itdb_Track *track)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -432,7 +497,8 @@ void rb_ipod_db_remove_track (RbIpodDb* 
 	}
 }
 
-void rb_ipod_db_set_ipod_name (RbIpodDb *ipod_db, const char *name)
+void
+rb_ipod_db_set_ipod_name (RbIpodDb *ipod_db, const char *name)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -443,7 +509,8 @@ void rb_ipod_db_set_ipod_name (RbIpodDb 
 	}
 }
 
-void rb_ipod_db_add_to_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist,
+void
+rb_ipod_db_add_to_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist,
 				 Itdb_Track *track)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -455,9 +522,10 @@ void rb_ipod_db_add_to_playlist (RbIpodD
 	}	
 }
 
-void rb_ipod_db_remove_from_playlist (RbIpodDb* ipod_db, 
-				      Itdb_Playlist *playlist,
-				      Itdb_Track *track)
+void
+rb_ipod_db_remove_from_playlist (RbIpodDb* ipod_db, 
+				 Itdb_Playlist *playlist,
+				 Itdb_Track *track)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -517,11 +585,17 @@ rb_ipod_db_process_delayed_actions (RbIp
 			rb_debug ("IPOD_ACTION_ADD_PLAYLIST");
 			rb_ipod_db_add_playlist_internal (ipod_db, 
 							  action->playlist);
-			/* The playlist was added to the iPod database, 
-			 * 'action' is no longer responsible for its memory 
-			 * handling
-			 */
-			action->playlist = NULL;
+			break;
+		case RB_IPOD_ACTION_REMOVE_PLAYLIST:
+			rb_debug ("IPOD_ACTION_REMOVE_PLAYLIST");
+			rb_ipod_db_remove_playlist_internal (ipod_db, 
+							     action->playlist);
+			break;
+		case RB_IPOD_ACTION_RENAME_PLAYLIST:
+			rb_debug ("IPOD_ACTION_RENAME_PLAYLIST");
+			rb_ipod_db_rename_playlist_internal (ipod_db, 
+							     action->playlist,
+							     action->name);
 			break;
 		case RB_IPOD_ACTION_ADD_TO_PLAYLIST:
 			rb_debug ("IPOD_ACTION_ADD_TO_PLAYLIST");
@@ -541,8 +615,9 @@ rb_ipod_db_process_delayed_actions (RbIp
 	}
 }
 
-static void rb_ipod_db_queue_remove_track (RbIpodDb *ipod_db,
-					   Itdb_Track *track)
+static void
+rb_ipod_db_queue_remove_track (RbIpodDb *ipod_db,
+			       Itdb_Track *track)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -555,8 +630,9 @@ static void rb_ipod_db_queue_remove_trac
 	g_queue_push_tail (priv->delayed_actions, action);
 }
 
-static void rb_ipod_db_queue_set_ipod_name (RbIpodDb *ipod_db, 
-					    const char *new_name)
+static void
+rb_ipod_db_queue_set_ipod_name (RbIpodDb *ipod_db, 
+				const char *new_name)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -569,21 +645,55 @@ static void rb_ipod_db_queue_set_ipod_na
 	g_queue_push_tail (priv->delayed_actions, action);
 }
 
-static void rb_ipod_db_queue_add_playlist (RbIpodDb *ipod_db,
-					   Itdb_Playlist *playlist)
+static void
+rb_ipod_db_queue_add_playlist (RbIpodDb *ipod_db,
+			       Itdb_Playlist *playlist)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 	
 	g_assert (priv->read_only);
-	rb_debug ("Queueing add track action since the iPod database is currently read-only");
+	rb_debug ("Queueing add playlist action since the iPod database is currently read-only");
 	action = g_new0 (RbIpodDelayedAction, 1);
 	action->type = RB_IPOD_ACTION_ADD_PLAYLIST;
 	action->playlist = playlist;
 	g_queue_push_tail (priv->delayed_actions, action);
 }
 
-static void rb_ipod_db_queue_add_track (RbIpodDb *ipod_db, Itdb_Track *track)
+static void
+rb_ipod_db_queue_remove_playlist (RbIpodDb *ipod_db,
+				  Itdb_Playlist *playlist)
+{
+	RbIpodDelayedAction *action;
+	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
+	
+	g_assert (priv->read_only);
+	rb_debug ("Queueing remove playlist action since the iPod database is currently read-only");
+	action = g_new0 (RbIpodDelayedAction, 1);
+	action->type = RB_IPOD_ACTION_REMOVE_PLAYLIST;
+	action->playlist = playlist;
+	g_queue_push_tail (priv->delayed_actions, action);
+}
+
+static void
+rb_ipod_db_queue_rename_playlist (RbIpodDb *ipod_db,
+				  Itdb_Playlist *playlist,
+				  const char *name)
+{
+	RbIpodDelayedAction *action;
+	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
+	
+	g_assert (priv->read_only);
+	rb_debug ("Queueing rename playlist action since the iPod database is currently read-only");
+	action = g_new0 (RbIpodDelayedAction, 1);
+	action->type = RB_IPOD_ACTION_RENAME_PLAYLIST;
+	action->playlist = playlist;
+	action->name = g_strdup (name);
+	g_queue_push_tail (priv->delayed_actions, action);
+}
+
+static void
+rb_ipod_db_queue_add_track (RbIpodDb *ipod_db, Itdb_Track *track)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -596,9 +706,10 @@ static void rb_ipod_db_queue_add_track (
 	g_queue_push_tail (priv->delayed_actions, action);
 }
 
-static void rb_ipod_db_queue_add_to_playlist (RbIpodDb *ipod_db, 
-					      Itdb_Playlist *playlist,
-					      Itdb_Track *track)
+static void
+rb_ipod_db_queue_add_to_playlist (RbIpodDb *ipod_db, 
+				  Itdb_Playlist *playlist,
+				  Itdb_Track *track)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -612,9 +723,10 @@ static void rb_ipod_db_queue_add_to_play
 	g_queue_push_tail (priv->delayed_actions, action);
 }
 
-static void rb_ipod_db_queue_remove_from_playlist (RbIpodDb *ipod_db, 
-						   Itdb_Playlist *playlist,
-						   Itdb_Track *track)
+static void
+rb_ipod_db_queue_remove_from_playlist (RbIpodDb *ipod_db, 
+				       Itdb_Playlist *playlist,
+				       Itdb_Track *track)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -628,9 +740,10 @@ static void rb_ipod_db_queue_remove_from
 	g_queue_push_tail (priv->delayed_actions, action);
 }
 
-static void rb_ipod_db_queue_set_thumbnail (RbIpodDb *ipod_db,
-					    Itdb_Track *track,
-					    GdkPixbuf *pixbuf)
+static void
+rb_ipod_db_queue_set_thumbnail (RbIpodDb *ipod_db,
+				Itdb_Track *track,
+				GdkPixbuf *pixbuf)
 {
 	RbIpodDelayedAction *action;
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
@@ -658,7 +771,8 @@ rb_ipod_db_get_volume_path (GnomeVFSVolu
 	return path;
 }
 
-static void rb_ipod_db_load (RbIpodDb *ipod_db, GnomeVFSVolume *volume)
+static void
+rb_ipod_db_load (RbIpodDb *ipod_db, GnomeVFSVolume *volume)
 {
 	char *mount_path;
 	const Itdb_IpodInfo *info;
@@ -677,7 +791,8 @@ static void rb_ipod_db_load (RbIpodDb *i
 	}
 }
 
-RbIpodDb *rb_ipod_db_new (GnomeVFSVolume *volume)
+RbIpodDb *
+rb_ipod_db_new (GnomeVFSVolume *volume)
 {
 	RbIpodDb *db;
 
@@ -714,7 +829,8 @@ ipod_db_saved_idle_cb (RbIpodDb *ipod_db
 	return FALSE;
 }
 
-static gpointer saving_thread (RbIpodDb *ipod_db)
+static gpointer
+saving_thread (RbIpodDb *ipod_db)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -762,28 +878,57 @@ rb_ipod_db_save_async (RbIpodDb *ipod_db
 	}
 }
 
-GList *rb_ipod_db_get_playlists (RbIpodDb *ipod_db)
+void
+rb_ipod_db_flush (RbIpodDb *db)
+{
+	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (db);
+
+	if (priv->save_timeout_id != 0) {
+		rb_debug ("running schedules save immediately");
+		g_source_remove (priv->save_timeout_id);
+		priv->save_timeout_id = 0;
+
+		if (priv->saving_thread != NULL) {
+			/* wait for the current save to finish */
+			g_thread_join (priv->saving_thread);
+			priv->saving_thread = NULL;
+
+			/* then remove the cleanup idle it added */
+			g_source_remove (priv->save_idle_id);
+			ipod_db_saved_idle_cb (db);
+		}
+
+		/* do the save synchronously */
+		rb_itdb_save (db, NULL);
+	}
+}
+
+GList *
+rb_ipod_db_get_playlists (RbIpodDb *ipod_db)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
 	return priv->itdb->playlists;
 }
 
-GList *rb_ipod_db_get_tracks (RbIpodDb *ipod_db)
+GList *
+rb_ipod_db_get_tracks (RbIpodDb *ipod_db)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
 	return priv->itdb->tracks;
 }
 
-const char *rb_ipod_db_get_mount_path (RbIpodDb *ipod_db)
+const char *
+rb_ipod_db_get_mount_path (RbIpodDb *ipod_db)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
 	return itdb_get_mountpoint (priv->itdb);
 }
 
-Itdb_Device *rb_ipod_db_get_device (RbIpodDb *ipod_db)
+Itdb_Device *
+rb_ipod_db_get_device (RbIpodDb *ipod_db)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 	if (priv->itdb == NULL) {
@@ -792,3 +937,4 @@ Itdb_Device *rb_ipod_db_get_device (RbIp
 
 	return priv->itdb->device;
 }
+
Index: plugins/ipod/rb-ipod-static-playlist-source.h
===================================================================
--- plugins/ipod/rb-ipod-static-playlist-source.h	(revision 0)
+++ plugins/ipod/rb-ipod-static-playlist-source.h	(revision 0)
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (C) 2007 James Livingston <doclivingston@gmail.co>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#ifndef __RB_IPOD_STATIC_PLAYLIST_SOURCE_H
+#define __RB_IPOD_STATIC_PLAYLIST_SOURCE_H
+
+#include <gpod/itdb.h>
+
+#include "rb-static-playlist-source.h"
+#include "rb-ipod-source.h"
+#include "rb-ipod-db.h"
+
+G_BEGIN_DECLS
+
+#define RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE         (rb_ipod_static_playlist_source_get_type ())
+#define RB_IPOD_STATIC_PLAYLIST_SOURCE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE, RBIpodStaticPlaylistSource))
+#define RB_IPOD_STATIC_PLAYLIST_SOURCE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE, RBIpodStaticPlaylistSourceClass))
+#define RB_IS_IPOD_STATIC_PLAYLIST_SOURCE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE))
+#define RB_IS_IPOD_STATIC_PLAYLIST_SOURCE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE))
+#define RB_IPOD_STATIC_PLAYLIST_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_IPOD_STATIC_PLAYLIST_SOURCE, RBIpodStaticPlaylistSourceClass))
+
+typedef struct
+{
+	RBStaticPlaylistSource parent;
+} RBIpodStaticPlaylistSource;
+
+typedef struct
+{
+	RBStaticPlaylistSourceClass parent;
+} RBIpodStaticPlaylistSourceClass;
+
+GType		rb_ipod_static_playlist_source_get_type 	(void);
+GType           rb_ipod_static_playlist_source_register_type    (GTypeModule *module);
+
+RBIpodStaticPlaylistSource *	rb_ipod_static_playlist_source_new (RBShell *shell,
+								    RBiPodSource *source,
+								    RbIpodDb *ipod_db,
+								    Itdb_Playlist *playlist,
+								    RhythmDBEntryType entry_type);
+
+Itdb_Playlist* rb_ipod_static_playlist_source_get_itdb_playlist (RBIpodStaticPlaylistSource *playlist);
+RBiPodSource* rb_ipod_static_playlist_source_get_ipod_source (RBIpodStaticPlaylistSource *playlist);
+
+G_END_DECLS
+
+#endif /* __RB_IPOD_STATIC_PLAYLIST_SOURCE_H */
Index: plugins/ipod/ipod-ui.xml
===================================================================
--- plugins/ipod/ipod-ui.xml	(revision 5249)
+++ plugins/ipod/ipod-ui.xml	(working copy)
@@ -2,5 +2,11 @@
   <popup name="iPodSourcePopup">
     <menuitem name="iPodSrcPopupRename" action="iPodSourceRename"/>
     <menuitem name="iPodSrcPopupEject" action="RemovableSourceEject"/>
+    <separator />
+    <menuitem name="iPodSrcPopupPlaylistNew" action="iPodSourcePlaylistNew"/>
   </popup>
-</ui>
\ No newline at end of file
+  <popup name="iPodPlaylistSourcePopup">
+    <menuitem name="iPodPlaylistSrcPopupRename" action="iPodPlaylistSourceRename"/>
+    <menuitem name="iPodPlaylistSrcPopupDelete" action="iPodPlaylistSourceDelete"/>
+  </popup>
+</ui>
Index: plugins/ipod/rb-ipod-db.h
===================================================================
--- plugins/ipod/rb-ipod-db.h	(revision 5249)
+++ plugins/ipod/rb-ipod-db.h	(working copy)
@@ -50,11 +50,14 @@ RbIpodDb *rb_ipod_db_new (GnomeVFSVolume
 GType rb_ipod_db_get_type (void);
 
 void rb_ipod_db_save_async (RbIpodDb *db);
+void rb_ipod_db_flush (RbIpodDb *db);
 
 void rb_ipod_db_set_thumbnail (RbIpodDb* ipod_db, Itdb_Track *track, 
 			       GdkPixbuf *pixbuf);
 void rb_ipod_db_add_track (RbIpodDb* ipod_db, Itdb_Track *track);
 void rb_ipod_db_add_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist);
+void rb_ipod_db_remove_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist);
+void rb_ipod_db_rename_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist, const char *name);
 void rb_ipod_db_add_to_playlist (RbIpodDb* ipod_db, Itdb_Playlist *playlist,
 				 Itdb_Track *track);
 void rb_ipod_db_remove_from_playlist (RbIpodDb* ipod_db, 
Index: plugins/ipod/Makefile.am
===================================================================
--- plugins/ipod/Makefile.am	(revision 5249)
+++ plugins/ipod/Makefile.am	(working copy)
@@ -4,9 +4,11 @@ plugin_LTLIBRARIES = libipod.la
 libipod_la_SOURCES = \
 	rb-ipod-db.c				\
 	rb-ipod-db.h				\
-	rb-ipod-plugin.c			\
+	rb-ipod-static-playlist-source.c	\
+	rb-ipod-static-playlist-source.h	\
 	rb-ipod-source.c			\
-	rb-ipod-source.h
+	rb-ipod-source.h			\
+	rb-ipod-plugin.c
 
 libipod_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
 libipod_la_LIBADD = 					\
Index: plugins/ipod/rb-ipod-plugin.c
===================================================================
--- plugins/ipod/rb-ipod-plugin.c	(revision 5249)
+++ plugins/ipod/rb-ipod-plugin.c	(working copy)
@@ -33,6 +33,7 @@
 #include "rb-sourcelist.h"
 #include "rb-source.h"
 #include "rb-ipod-source.h"
+#include "rb-ipod-static-playlist-source.h"
 #include "rb-plugin.h"
 #include "rb-debug.h"
 #include "rb-file-helpers.h"
@@ -77,6 +78,12 @@ static RBSource * create_source_cb (RBRe
 				    RBIpodPlugin *plugin);
 static void  rb_ipod_plugin_cmd_rename (GtkAction *action,
 					RBIpodPlugin *plugin);
+static void  rb_ipod_plugin_cmd_playlist_new (GtkAction *action,
+					RBIpodPlugin *plugin);
+static void  rb_ipod_plugin_cmd_playlist_rename (GtkAction *action,
+					RBIpodPlugin *plugin);
+static void  rb_ipod_plugin_cmd_playlist_delete (GtkAction *action,
+					RBIpodPlugin *plugin);
 
 RB_PLUGIN_REGISTER(RBIpodPlugin, rb_ipod_plugin)
 
@@ -85,7 +92,16 @@ static GtkActionEntry rb_ipod_plugin_act
 {
 	{ "iPodSourceRename", NULL, N_("_Rename"), NULL,
 	  N_("Rename iPod"),
-	  G_CALLBACK (rb_ipod_plugin_cmd_rename) }
+	  G_CALLBACK (rb_ipod_plugin_cmd_rename) },
+	{ "iPodSourcePlaylistNew", NULL, N_("_New Playlist"), NULL,
+	  N_("Add new playlist to iPod"),
+	  G_CALLBACK (rb_ipod_plugin_cmd_playlist_new) },
+	{ "iPodPlaylistSourceRename", NULL, N_("_Rename"), NULL,
+	  N_("Rename playlist"),
+	  G_CALLBACK (rb_ipod_plugin_cmd_playlist_rename) },
+	{ "iPodPlaylistSourceDelete", GTK_STOCK_REMOVE, N_("_Delete"), NULL,
+	  N_("Delete playlist"),
+	  G_CALLBACK (rb_ipod_plugin_cmd_playlist_delete) },
 };
 
 
@@ -101,7 +117,8 @@ rb_ipod_plugin_class_init (RBIpodPluginC
 	plugin_class->deactivate = impl_deactivate;
 
 	/* register types used by the plugin */
-	RB_PLUGIN_REGISTER_TYPE(rb_ipod_source);
+	RB_PLUGIN_REGISTER_TYPE (rb_ipod_source);
+	RB_PLUGIN_REGISTER_TYPE (rb_ipod_static_playlist_source);
 }
 
 static void
@@ -247,3 +264,76 @@ rb_ipod_plugin_cmd_rename (GtkAction *ac
 	g_object_unref (source);
 }
 
+static void
+rb_ipod_plugin_cmd_playlist_rename (GtkAction *action,
+			   RBIpodPlugin *plugin)
+{
+	RBSource *source = NULL;
+	RBSourceList *sourcelist = NULL;
+
+	g_object_get (G_OBJECT (plugin->shell),
+		      "selected-source", &source,
+		      "sourcelist", &sourcelist,
+		      NULL);
+
+	if ((source == NULL) || !RB_IS_IPOD_STATIC_PLAYLIST_SOURCE (source)) {
+		g_critical ("got iPodPlaylistSourceRename action for non-ipod playlist source");
+		g_object_unref (sourcelist);
+		if (source != NULL)
+			g_object_unref (source);
+		return;
+	}
+
+	rb_sourcelist_edit_source_name (sourcelist, source);
+
+	g_object_unref (sourcelist);
+	g_object_unref (source);
+}
+
+static void
+rb_ipod_plugin_cmd_playlist_delete (GtkAction *action,
+			   RBIpodPlugin *plugin)
+{
+	RBIpodStaticPlaylistSource *source = NULL;
+	RBiPodSource *ipod_source;
+
+	g_object_get (G_OBJECT (plugin->shell),
+		      "selected-source", &source,
+		      NULL);
+
+	if ((source == NULL) || !RB_IS_IPOD_STATIC_PLAYLIST_SOURCE (source)) {
+		g_critical ("got iPodPlaylistSourceDelete action for non-ipod playlist source");
+		if (source != NULL)
+			g_object_unref (source);
+		return;
+	}
+
+	/* delete playlist*/
+	ipod_source = rb_ipod_static_playlist_source_get_ipod_source (source);
+	rb_ipod_source_remove_playlist (ipod_source, RB_SOURCE (source));
+
+	g_object_unref (source);
+}
+
+static void
+rb_ipod_plugin_cmd_playlist_new (GtkAction *action,
+			   RBIpodPlugin *plugin)
+{
+	RBSource *source = NULL;
+
+	g_object_get (G_OBJECT (plugin->shell),
+		      "selected-source", &source,
+		      NULL);
+
+	if ((source == NULL) || !RB_IS_IPOD_SOURCE (source)) {
+		g_critical ("got iPodSourceRename action for non-ipod source");
+		if (source != NULL)
+			g_object_unref (source);
+		return;
+	}
+
+	rb_ipod_source_new_playlist (RB_IPOD_SOURCE (source));
+
+	g_object_unref (source);
+}
+
Index: plugins/ipod/rb-ipod-source.c
===================================================================
--- plugins/ipod/rb-ipod-source.c	(revision 5249)
+++ plugins/ipod/rb-ipod-source.c	(working copy)
@@ -41,7 +41,7 @@
 #include "rb-file-helpers.h"
 #include "rb-plugin.h"
 #include "rb-removable-media-manager.h"
-#include "rb-static-playlist-source.h"
+#include "rb-ipod-static-playlist-source.h"
 #include "rb-util.h"
 #include "rhythmdb.h"
 #include "rb-cut-and-paste-code.h"
@@ -51,10 +51,6 @@ static GObject *rb_ipod_source_construct
 					    GObjectConstructParam *construct_properties);
 static void rb_ipod_source_dispose (GObject *object);
 
-static GObject *rb_ipod_source_constructor (GType type, guint n_construct_properties,
-			       GObjectConstructParam *construct_properties);
-static void rb_ipod_source_dispose (GObject *object);
-
 static gboolean impl_show_popup (RBSource *source);
 static void impl_move_to_trash (RBSource *asource);
 static void rb_ipod_load_songs (RBiPodSource *source);
@@ -89,7 +85,7 @@ typedef struct
 	GHashTable *entry_map;
 
 	gboolean needs_shuffle_db;
-	RBStaticPlaylistSource *podcast_pl;
+	RBIpodStaticPlaylistSource *podcast_pl;
 
 	guint load_idle_id;
 
@@ -155,9 +151,8 @@ rb_ipod_source_name_changed_cb (RBiPodSo
 
 static void
 rb_ipod_source_init (RBiPodSource *source)
-{	
-	g_signal_connect (G_OBJECT (source), "notify::name",
-			  (GCallback)rb_ipod_source_name_changed_cb, NULL);
+{
+
 }
 
 static GObject *
@@ -169,6 +164,10 @@ rb_ipod_source_constructor (GType type, 
 
 	source = RB_IPOD_SOURCE (G_OBJECT_CLASS (rb_ipod_source_parent_class)->
 			constructor (type, n_construct_properties, construct_properties));
+
+	g_signal_connect (G_OBJECT (source), "notify::name",
+			  (GCallback)rb_ipod_source_name_changed_cb, NULL);
+
 	songs = rb_source_get_entry_view (RB_SOURCE (source));
 	rb_entry_view_append_column (songs, RB_ENTRY_VIEW_COL_RATING, FALSE);
 	rb_entry_view_append_column (songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
@@ -283,16 +282,16 @@ playlist_track_removed (RhythmDBQueryMod
 			RhythmDBEntry *entry,
 			gpointer data)
 {
-	RBStaticPlaylistSource *playlist = RB_STATIC_PLAYLIST_SOURCE (data);
-	Itdb_Playlist *ipod_pl = g_object_get_data (G_OBJECT (playlist), "itdb-playlist");
-	RBiPodSource *ipod = g_object_get_data (G_OBJECT (playlist), "ipod-source");
+	RBIpodStaticPlaylistSource *playlist = RB_IPOD_STATIC_PLAYLIST_SOURCE (data);
+	Itdb_Playlist *ipod_pl = rb_ipod_static_playlist_source_get_itdb_playlist (playlist);
+	RBiPodSource *ipod = rb_ipod_static_playlist_source_get_ipod_source (playlist);
 	RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (ipod);
 	Itdb_Track *track;
 
 	g_return_if_fail (ipod != NULL);
 	g_return_if_fail (ipod_pl != NULL);
 
-        track = g_hash_table_lookup (priv->entry_map, entry);
+	track = g_hash_table_lookup (priv->entry_map, entry);
 	g_return_if_fail (track != NULL);
 	rb_ipod_db_remove_from_playlist (priv->ipod_db, ipod_pl, track);
 }
@@ -301,9 +300,9 @@ static void
 playlist_track_added (GtkTreeModel *model, GtkTreePath *path,
 		      GtkTreeIter *iter, gpointer data)
 {
-	RBStaticPlaylistSource *playlist = RB_STATIC_PLAYLIST_SOURCE (data);
-	Itdb_Playlist *ipod_pl = g_object_get_data (G_OBJECT (playlist), "itdb-playlist");
-	RBiPodSource *ipod = g_object_get_data (G_OBJECT (playlist), "ipod-source");
+	RBIpodStaticPlaylistSource *playlist = RB_IPOD_STATIC_PLAYLIST_SOURCE (data);
+	Itdb_Playlist *ipod_pl = rb_ipod_static_playlist_source_get_itdb_playlist (playlist);
+	RBiPodSource *ipod = rb_ipod_static_playlist_source_get_ipod_source (playlist);
 	RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (ipod);
 	Itdb_Track *track;
 	RhythmDBEntry *entry;
@@ -322,7 +321,7 @@ static void
 add_rb_playlist (RBiPodSource *source, Itdb_Playlist *playlist)
 {
 	RBShell *shell;
-	RBSource *playlist_source;
+	RBIpodStaticPlaylistSource *playlist_source;
 	GList *it;
 	RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
 	RhythmDBEntryType entry_type;
@@ -333,10 +332,11 @@ add_rb_playlist (RBiPodSource *source, I
 			  "entry-type", &entry_type,
 			  NULL);
 
-	playlist_source = rb_static_playlist_source_new (shell,
-							 playlist->name,
-							 FALSE,
-							 entry_type);
+	playlist_source = rb_ipod_static_playlist_source_new (shell,
+							      source,
+							      priv->ipod_db,
+							      playlist,
+							      entry_type);
 	g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, entry_type);
 
 	for (it = playlist->members; it != NULL; it = it->next) {
@@ -365,13 +365,9 @@ add_rb_playlist (RBiPodSource *source, I
 			          G_CALLBACK (playlist_track_removed),
 			          playlist_source);
 
-	g_object_set_data (G_OBJECT (playlist_source),
-			           "ipod-source", source);
-	g_object_set_data (G_OBJECT (playlist_source),
-			           "itdb-playlist", playlist);
 	if (itdb_playlist_is_podcasts(playlist))
-			priv->podcast_pl = RB_STATIC_PLAYLIST_SOURCE (playlist_source);
-	rb_shell_append_source (shell, playlist_source, RB_SOURCE (source));
+		priv->podcast_pl = playlist_source;
+	rb_shell_append_source (shell, RB_SOURCE (playlist_source), RB_SOURCE (source));
 	g_object_unref (shell);
 }
 
@@ -389,8 +385,7 @@ load_ipod_playlists (RBiPodSource *sourc
 		playlist = (Itdb_Playlist *)it->data;
 		if (itdb_playlist_is_mpl (playlist)) {
 			continue;
-		}
-		if (playlist->is_spl) {
+		} else if (playlist->is_spl) {
 			continue;
 		}
 
@@ -1051,7 +1046,7 @@ add_to_podcasts (RBiPodSource *source, I
 
 	mount_path = rb_ipod_db_get_mount_path (priv->ipod_db);
   	filename = ipod_path_to_uri (mount_path, song->ipod_path);
- 	rb_static_playlist_source_add_location (priv->podcast_pl, filename, -1);
+ 	rb_static_playlist_source_add_location (RB_STATIC_PLAYLIST_SOURCE (priv->podcast_pl), filename, -1);
 	g_free (filename);
 }
 
@@ -1361,10 +1356,8 @@ impl_delete_thyself (RBSource *source)
 		}
 	}
 
-	if (priv->ipod_db != NULL) {
-		g_object_unref (G_OBJECT (priv->ipod_db));
-		priv->ipod_db = NULL;
-	}
+	/* force a db save */
+	rb_ipod_db_flush (priv->ipod_db);
 
 	RB_SOURCE_CLASS (rb_ipod_source_parent_class)->impl_delete_thyself (source);
 }
@@ -1384,3 +1377,27 @@ impl_get_mime_types (RBRemovableMediaSou
 }
 
 #endif
+
+
+void
+rb_ipod_source_new_playlist (RBiPodSource *source)
+{
+	RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+	Itdb_Playlist *ipod_playlist;
+
+	ipod_playlist = itdb_playlist_new (_("New playlist"), FALSE);
+	rb_ipod_db_add_playlist (priv->ipod_db, ipod_playlist);
+	add_rb_playlist (source, ipod_playlist);
+}
+
+void
+rb_ipod_source_remove_playlist (RBiPodSource *ipod_source,
+				RBSource *source)
+{
+	RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (ipod_source);
+	RBIpodStaticPlaylistSource *playlist_source = RB_IPOD_STATIC_PLAYLIST_SOURCE (source);
+
+	rb_source_delete_thyself (source);
+	rb_ipod_db_remove_playlist (priv->ipod_db, rb_ipod_static_playlist_source_get_itdb_playlist (playlist_source));
+}
+
