=== added file 'b/data/ui/ipod-ui.xml'
--- /dev/null	
+++ b/data/ui/ipod-ui.xml	
@@ -0,0 +1,6 @@
+<ui>
+  <popup name="iPodSourcePopup">
+    <menuitem name="iPodSrcPopupRename" action="iPodSourceRename"/>
+    <menuitem name="iPodSrcPopupEject" action="RemovableSourceEject"/>
+  </popup>
+</ui>
\ No newline at end of file

=== modified file 'a/data/ui/Makefile.am'
--- a/data/ui/Makefile.am	
+++ b/data/ui/Makefile.am	
@@ -1,7 +1,7 @@
 ## arch-tag: Automake rules for XML user interface definition stuff
 
 uixmldir = $(pkgdatadir)
-uixml_DATA = rhythmbox-ui.xml
+uixml_DATA = rhythmbox-ui.xml ipod-ui.xml
 
-EXTRA_DIST = rhythmbox-ui.xml
+EXTRA_DIST = rhythmbox-ui.xml ipod-ui.xml
 

=== modified file 'a/lib/rb-util.c'
--- a/lib/rb-util.c	
+++ b/lib/rb-util.c	
@@ -278,8 +278,12 @@
 	GtkWidget *menu;
 
 	menu = gtk_ui_manager_get_widget (uimanager, path);
+	if (menu == NULL) {
+		g_warning ("Couldn't get menu widget for %s", path);
+	} else {
 	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, 
 			gtk_get_current_event_time ());
+	}
 }
 
 static GList *

=== modified file 'a/sources/rb-ipod-source.c'
--- a/sources/rb-ipod-source.c	
+++ b/sources/rb-ipod-source.c	
@@ -30,12 +30,15 @@
 #include <libhal.h>
 #include <dbus/dbus.h>
 #endif
+#include <libgnomevfs/gnome-vfs-utils.h>
 #include <libgnomevfs/gnome-vfs-volume.h>
 #include <libgnomevfs/gnome-vfs-volume-monitor.h>
 #include <gpod/itdb.h>
 #include "eel-gconf-extensions.h"
 #include "rb-ipod-source.h"
 #include "rb-debug.h"
+#include "rb-file-helpers.h"
+#include "rb-removable-media-manager.h"
 #include "rb-static-playlist-source.h"
 #include "rb-util.h"
 #include "rhythmdb.h"
@@ -49,10 +52,13 @@
 static void rb_ipod_source_dispose (GObject *object);
 
 static gboolean impl_show_popup (RBSource *source);
+
 static void rb_ipod_load_songs (RBiPodSource *source);
 static gchar *rb_ipod_get_mount_path (GnomeVFSVolume *volume);
 static void impl_delete_thyself (RBSource *source);
-
+static GList* impl_get_ui_actions (RBSource *source);
+static void rb_ipod_source_cmd_rename (GtkAction *action,
+				       RBiPodSource *source);
 #ifdef HAVE_HAL
 static gboolean hal_udi_is_ipod (const char *udi);
 #endif
@@ -61,7 +67,16 @@
 {
 	Itdb_iTunesDB *ipod_db;
 	gchar *ipod_mount_path;
+	GtkActionGroup *action_group;	
 } RBiPodSourcePrivate;
+
+
+static GtkActionEntry rb_ipod_source_actions [] =
+{
+	{ "iPodSourceRename", NULL, N_("_Rename"), NULL,
+	  N_("Rename iPod"),
+	  G_CALLBACK (rb_ipod_source_cmd_rename) }
+};
 
 
 G_DEFINE_TYPE (RBiPodSource, rb_ipod_source, RB_TYPE_REMOVABLE_MEDIA_SOURCE)
@@ -79,14 +94,41 @@
 
 	source_class->impl_show_popup = impl_show_popup;
 	source_class->impl_delete_thyself = impl_delete_thyself;
+	source_class->impl_can_rename = (RBSourceFeatureFunc) rb_true_function;
+	source_class->impl_get_ui_actions = impl_get_ui_actions;
 
 	g_type_class_add_private (klass, sizeof (RBiPodSourcePrivate));
+}
+
+static void
+rb_ipod_source_set_ipod_name (RBiPodSource *source, const char *name)
+{
+	Itdb_Playlist *mpl;
+	RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+
+	mpl = itdb_playlist_mpl (priv->ipod_db);
+	rb_debug ("Renaming iPod from %s to %s", mpl->name, name);
+	g_free (mpl->name);
+	mpl->name = g_strdup (name);
+	itdb_write (priv->ipod_db, NULL);
+}
+
+static void
+rb_ipod_source_name_changed_cb (RBiPodSource *source, GParamSpec *spec, 
+				gpointer data)
+{
+	char *name;
+
+	g_object_get (RB_SOURCE (source), "name", &name, NULL);
+	rb_ipod_source_set_ipod_name (source, name);
+	g_free (name);
 }
 
 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 *
@@ -95,13 +137,29 @@
 {
 	RBiPodSource *source;
 	RBEntryView *songs;
+	RBiPodSourcePrivate *priv;
+	GtkUIManager *uimanager;
 
 	source = RB_IPOD_SOURCE (G_OBJECT_CLASS (rb_ipod_source_parent_class)->
 			constructor (type, n_construct_properties, construct_properties));
-
+	priv = IPOD_SOURCE_GET_PRIVATE (source);
 	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);
+
+	priv->action_group = _rb_source_register_action_group (RB_SOURCE (source),
+							       "iPodActions",
+							       rb_ipod_source_actions,
+							       G_N_ELEMENTS (rb_ipod_source_actions),
+							       source);
+
+	/* FIXME: shouldn't it be done only once for the class instead of 
+	 * being done for every RBiPodSource object created?
+	 */
+	g_object_get (G_OBJECT (source), "ui-manager", &uimanager, NULL);
+	gtk_ui_manager_add_ui_from_file (uimanager,
+					 rb_file ("ipod-ui.xml"), NULL);
+	g_object_unref (G_OBJECT (uimanager));
 
 	rb_ipod_load_songs (source);
 
@@ -421,6 +479,12 @@
 
  	priv->ipod_db = itdb_parse (priv->ipod_mount_path, NULL);
 	if (priv->ipod_db != NULL) {
+		/* FIXME: we could set a different icon depending on the iPod
+		 * model
+		 */
+		g_object_set (RB_SOURCE (source), 
+			      "name", itdb_playlist_mpl (priv->ipod_db)->name, 
+			      NULL);
 		g_idle_add ((GSourceFunc)load_ipod_db_idle_cb, source);
 	}
 }
@@ -592,6 +656,17 @@
 
 #endif
 
+static GList*
+impl_get_ui_actions (RBSource *source)
+{
+	GList *actions = NULL;
+ 
+	actions = g_list_prepend (actions, "RemovableSourceEject");
+ 
+	return actions;
+}
+
+
 static gboolean
 impl_show_popup (RBSource *source)
 {
@@ -609,3 +684,31 @@
 
 	RB_SOURCE_CLASS (rb_ipod_source_parent_class)->impl_delete_thyself (source);
 }
+
+static void 
+rb_ipod_source_cmd_rename (GtkAction *action,
+			   RBiPodSource *source)
+{
+	RBShell *shell;
+	RBRemovableMediaManager *manager;
+	RBSourceList *sourcelist;
+
+	/* FIXME: this is pretty ugly, the sourcelist should automatically add
+	 * a "rename" menu item for sources that have can_rename == TRUE.
+	 * This is a bit trickier to handle though, since playlists want 
+	 * to make rename sensitive/unsensitive instead of showing/hiding it
+	 */
+	g_object_get (G_OBJECT (source), "shell", &shell, NULL);
+	g_object_get (G_OBJECT (shell), 
+		      "removable-media-manager", &manager, 
+		      NULL);
+	g_object_get (G_OBJECT (manager), "sourcelist", &sourcelist, NULL);
+	g_object_unref (G_OBJECT (manager));
+	g_object_unref (G_OBJECT (shell));
+	
+	rb_sourcelist_edit_source_name (sourcelist, RB_SOURCE (source)); 
+	/* Once editing is done, notify::name will be fired on the source, and
+	 * we'll catch that in our rename callback
+	 */
+	g_object_unref (sourcelist);
+}

