rhythmbox r5747 - in trunk: . plugins/ipod



Author: teuf
Date: Sat Jun 14 16:20:53 2008
New Revision: 5747
URL: http://svn.gnome.org/viewvc/rhythmbox?rev=5747&view=rev

Log:
Playlist creation/deletion/renaming on the ipod, fixes bug #451265


Added:
   trunk/plugins/ipod/rb-ipod-static-playlist-source.c
   trunk/plugins/ipod/rb-ipod-static-playlist-source.h
Modified:
   trunk/ChangeLog
   trunk/plugins/ipod/Makefile.am
   trunk/plugins/ipod/ipod-ui.xml
   trunk/plugins/ipod/rb-ipod-db.c
   trunk/plugins/ipod/rb-ipod-db.h
   trunk/plugins/ipod/rb-ipod-plugin.c
   trunk/plugins/ipod/rb-ipod-source.c
   trunk/plugins/ipod/rb-ipod-source.h

Modified: trunk/plugins/ipod/Makefile.am
==============================================================================
--- trunk/plugins/ipod/Makefile.am	(original)
+++ trunk/plugins/ipod/Makefile.am	Sat Jun 14 16:20:53 2008
@@ -4,9 +4,11 @@
 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 = 					\

Modified: trunk/plugins/ipod/ipod-ui.xml
==============================================================================
--- trunk/plugins/ipod/ipod-ui.xml	(original)
+++ trunk/plugins/ipod/ipod-ui.xml	Sat Jun 14 16:20:53 2008
@@ -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>

Modified: trunk/plugins/ipod/rb-ipod-db.c
==============================================================================
--- trunk/plugins/ipod/rb-ipod-db.c	(original)
+++ trunk/plugins/ipod/rb-ipod-db.c	Sat Jun 14 16:20:53 2008
@@ -79,11 +79,16 @@
 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,
@@ -115,7 +120,8 @@
 
 #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);
 
@@ -205,8 +211,10 @@
 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
@@ -236,7 +244,8 @@
 	};
 };
 
-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:
@@ -249,7 +258,13 @@
 		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 */
@@ -264,7 +279,8 @@
 	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);
@@ -315,7 +331,8 @@
 }
 
 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)
 {
 	g_return_if_fail (track != NULL);
@@ -339,6 +356,24 @@
 }
 
 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);
@@ -369,8 +404,10 @@
 }
 
 
-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);
 
@@ -381,7 +418,8 @@
 	}
 }
 
-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);
 
@@ -392,7 +430,8 @@
 	}
 }
 
-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);
 
@@ -403,7 +442,33 @@
 	}
 }
 
-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);
 
@@ -414,7 +479,8 @@
 	}
 }
 
-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);
 
@@ -425,7 +491,8 @@
 	}
 }
 
-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);
@@ -437,9 +504,10 @@
 	}	
 }
 
-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);
 
@@ -499,11 +567,17 @@
 			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");
@@ -523,8 +597,9 @@
 	}
 }
 
-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);
@@ -537,8 +612,9 @@
 	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);
@@ -551,21 +627,55 @@
 	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);
@@ -578,9 +688,10 @@
 	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);
@@ -594,9 +705,10 @@
 	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);
@@ -610,9 +722,10 @@
 	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);
@@ -640,7 +753,8 @@
 	return path;
 }
 
-static gboolean rb_ipod_db_load (RbIpodDb *ipod_db, GnomeVFSVolume *volume)
+static gboolean
+rb_ipod_db_load (RbIpodDb *ipod_db, GnomeVFSVolume *volume)
 {
 	char *mount_path;
 	const Itdb_IpodInfo *info;
@@ -667,7 +781,8 @@
         return TRUE;
 }
 
-RbIpodDb *rb_ipod_db_new (GnomeVFSVolume *volume)
+RbIpodDb *
+rb_ipod_db_new (GnomeVFSVolume *volume)
 {
 	RbIpodDb *db;
         gboolean success;
@@ -709,7 +824,8 @@
 	return FALSE;
 }
 
-static gpointer saving_thread (RbIpodDb *ipod_db)
+static gpointer
+saving_thread (RbIpodDb *ipod_db)
 {
 	RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
 
@@ -757,28 +873,32 @@
 	}
 }
 
-GList *rb_ipod_db_get_playlists (RbIpodDb *ipod_db)
+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) {
@@ -787,3 +907,4 @@
 
 	return priv->itdb->device;
 }
+

Modified: trunk/plugins/ipod/rb-ipod-db.h
==============================================================================
--- trunk/plugins/ipod/rb-ipod-db.h	(original)
+++ trunk/plugins/ipod/rb-ipod-db.h	Sat Jun 14 16:20:53 2008
@@ -63,6 +63,8 @@
 			       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, 

Modified: trunk/plugins/ipod/rb-ipod-plugin.c
==============================================================================
--- trunk/plugins/ipod/rb-ipod-plugin.c	(original)
+++ trunk/plugins/ipod/rb-ipod-plugin.c	Sat Jun 14 16:20:53 2008
@@ -41,6 +41,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"
@@ -85,6 +86,12 @@
 				    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)
 
@@ -93,7 +100,16 @@
 {
 	{ "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) },
 };
 
 
@@ -109,7 +125,8 @@
 	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
@@ -255,3 +272,76 @@
 	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);
+}
+

Modified: trunk/plugins/ipod/rb-ipod-source.c
==============================================================================
--- trunk/plugins/ipod/rb-ipod-source.c	(original)
+++ trunk/plugins/ipod/rb-ipod-source.c	Sat Jun 14 16:20:53 2008
@@ -51,7 +51,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"
@@ -114,7 +114,7 @@
 	GHashTable *entry_map;
 
 	gboolean needs_shuffle_db;
-	RBStaticPlaylistSource *podcast_pl;
+	RBIpodStaticPlaylistSource *podcast_pl;
 
 	guint load_idle_id;
 
@@ -206,6 +206,7 @@
 
 	source = RB_IPOD_SOURCE (G_OBJECT_CLASS (rb_ipod_source_parent_class)->
 			constructor (type, n_construct_properties, construct_properties));
+
 	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);
@@ -338,16 +339,16 @@
 			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);
 }
@@ -356,9 +357,9 @@
 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;
@@ -377,7 +378,7 @@
 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;
@@ -388,11 +389,11 @@
 			  "entry-type", &entry_type,
 			  NULL);
 
-	playlist_source = rb_static_playlist_source_new (shell,
-							 playlist->name,
-							 NULL,
-							 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) {
@@ -421,13 +422,9 @@
 			          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);
 }
 
@@ -445,8 +442,7 @@
 		playlist = (Itdb_Playlist *)it->data;
 		if (itdb_playlist_is_mpl (playlist)) {
 			continue;
-		}
-		if (playlist->is_spl) {
+		} else if (playlist->is_spl) {
 			continue;
 		}
 
@@ -1349,7 +1345,7 @@
 
 	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);
 }
 
@@ -1679,3 +1675,27 @@
 }
 
 #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));
+}
+

Modified: trunk/plugins/ipod/rb-ipod-source.h
==============================================================================
--- trunk/plugins/ipod/rb-ipod-source.h	(original)
+++ trunk/plugins/ipod/rb-ipod-source.h	Sat Jun 14 16:20:53 2008
@@ -30,6 +30,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"
@@ -59,6 +61,10 @@
 
 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 */

Added: trunk/plugins/ipod/rb-ipod-static-playlist-source.c
==============================================================================
--- (empty file)
+++ trunk/plugins/ipod/rb-ipod-static-playlist-source.c	Sat Jun 14 16:20:53 2008
@@ -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);
+}
+

Added: trunk/plugins/ipod/rb-ipod-static-playlist-source.h
==============================================================================
--- (empty file)
+++ trunk/plugins/ipod/rb-ipod-static-playlist-source.h	Sat Jun 14 16:20:53 2008
@@ -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 */



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