diff -Nru --exclude='*svn*' --exclude=Makefile rhythmbox-cleansvn_diffagainst/data/ui/rhythmbox-ui.xml rhythmbox-personalsvn_savehere/data/ui/rhythmbox-ui.xml
--- rhythmbox-cleansvn_diffagainst/data/ui/rhythmbox-ui.xml	2007-12-02 12:45:25.000000000 -0500
+++ rhythmbox-personalsvn_savehere/data/ui/rhythmbox-ui.xml	2007-12-01 13:35:47.000000000 -0500
@@ -222,6 +222,7 @@
     <menuitem name="RenameAutoPlaylistPopup" action="MusicPlaylistRenamePlaylist"/>
     <separator/>
     <menuitem name="QueuePlaylistPopup" action="QueuePlaylist"/>
+    <menuitem name="ShufflePlaylistPopup" action="ShufflePlaylist"/>
     <placeholder name="PlaylistSourcePopupPluginPlaceholder" />
     <separator/>
     <menuitem name="DeletePlaylistPopup" action="MusicPlaylistDeletePlaylist"/>
@@ -234,6 +235,7 @@
     <menuitem name="RenameAutoPlaylistPopup" action="MusicPlaylistRenamePlaylist"/>
     <separator/>
     <menuitem name="QueuePlaylistPopup" action="QueuePlaylist"/>
+    <menuitem name="ShufflePlaylistPopup" action="ShufflePlaylist"/>
     <placeholder name="AutoPlaylistSourcePopupPluginPlaceholder" />
     <separator/>
     <menuitem name="DeleteAutoPlaylistPopup" action="MusicPlaylistDeletePlaylist"/>
diff -Nru --exclude='*svn*' --exclude=Makefile rhythmbox-cleansvn_diffagainst/shell/rb-playlist-manager.c rhythmbox-personalsvn_savehere/shell/rb-playlist-manager.c
--- rhythmbox-cleansvn_diffagainst/shell/rb-playlist-manager.c	2007-12-02 12:45:22.000000000 -0500
+++ rhythmbox-personalsvn_savehere/shell/rb-playlist-manager.c	2007-12-02 12:36:24.000000000 -0500
@@ -74,6 +74,8 @@
 						  RBPlaylistManager *mgr);
 static void rb_playlist_manager_cmd_new_automatic_playlist (GtkAction *action,
 							    RBPlaylistManager *mgr);
+static void rb_playlist_manager_cmd_shuffle_playlist (GtkAction *action,
+						      RBPlaylistManager *mgr);
 static void rb_playlist_manager_cmd_rename_playlist (GtkAction *action,
 						     RBPlaylistManager *mgr);
 static void rb_playlist_manager_cmd_delete_playlist (GtkAction *action,
@@ -154,6 +156,9 @@
 	{ "QueuePlaylist", NULL, N_("_Queue All Tracks"), NULL,
 	  N_("Add all tracks in this playlist to the queue"),
 	  G_CALLBACK (rb_playlist_manager_cmd_queue_playlist) },
+	{ "ShufflePlaylist", NULL, N_("_Shuffle Playlist"), NULL,
+	  N_("Shuffle the tracks in this playlist"),
+	  G_CALLBACK (rb_playlist_manager_cmd_shuffle_playlist) },
 };
 static guint rb_playlist_manager_n_actions = G_N_ELEMENTS (rb_playlist_manager_actions);
 
@@ -362,6 +367,7 @@
 	gboolean can_delete;
 	gboolean can_edit;
 	gboolean can_rename;
+	gboolean can_shuffle;
 	GtkAction *action;
 
 	party_mode = rb_shell_get_party_mode (mgr->priv->shell);
@@ -397,6 +403,11 @@
 	action = gtk_action_group_get_action (mgr->priv->actiongroup,
 					      "MusicPlaylistRenamePlaylist");
 	gtk_action_set_visible (action, can_rename);
+
+	can_shuffle = RB_IS_STATIC_PLAYLIST_SOURCE (mgr->priv->selected_source);
+	action = gtk_action_group_get_action (mgr->priv->actiongroup,
+					      "ShufflePlaylist");
+	gtk_action_set_sensitive (action, can_shuffle);
 }
 
 static void
@@ -1253,6 +1264,69 @@
 	g_object_unref (model);
 }
 
+
+static gboolean
+_count_track_cb (RhythmDBQueryModel *model,
+		 GtkTreePath *path,
+		 GtkTreeIter *iter,
+		 GList **retval)
+{
+	RhythmDBEntry *entry;
+
+	entry = rhythmdb_query_model_iter_to_entry (model, iter);
+	*retval = g_list_append(*retval, entry);
+
+	return FALSE;
+}
+
+typedef struct {
+	RBStaticPlaylistSource *playlist_source;
+	int numtracks;
+} ShuffleTrackData;
+
+static void
+_shuffle_track_cb (RhythmDBEntry *entry,
+		 ShuffleTrackData *passdata) {
+	int new_location;
+
+	new_location = g_random_int_range (0, passdata->numtracks);
+
+	rb_static_playlist_source_move_entry (passdata->playlist_source, entry, 
+						new_location);
+	rhythmdb_entry_unref (entry);
+}
+
+static void
+rb_playlist_manager_cmd_shuffle_playlist (GtkAction *action,
+					RBPlaylistManager *mgr)
+{
+	RhythmDBQueryModel *model;
+	int numtracks = 0;
+	ShuffleTrackData shuffle_track_data;
+	GList *entries;
+
+	g_object_get (mgr->priv->selected_source, "query-model", &model, NULL);
+
+	/* Phase I:  Put the tracks into a list, so I can traverse while I 
+	 * move the entries around. */
+	entries = NULL;
+	gtk_tree_model_foreach (GTK_TREE_MODEL (model),
+				(GtkTreeModelForeachFunc) _count_track_cb,
+				&entries);
+
+	numtracks = g_list_length (entries);
+
+	/* Phase II:  Traverse the list, placing the entries in random places 
+	 * in the playlist. */
+	shuffle_track_data.playlist_source = (RBStaticPlaylistSource *) mgr->priv->selected_source;
+	shuffle_track_data.numtracks = numtracks;
+
+	g_list_foreach (entries, (GFunc)_shuffle_track_cb, &shuffle_track_data);
+
+	g_list_free (entries);
+	g_object_unref (model);
+}
+
 static void
 rb_playlist_manager_cmd_rename_playlist (GtkAction *action,
 					 RBPlaylistManager *mgr)
