Index: src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs
===================================================================
--- src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs	(revision 4915)
+++ src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs	(working copy)
@@ -96,15 +96,22 @@
                 new RadioActionEntry ("ShuffleAlbumAction", null,
                     Catalog.GetString ("Shuffle by A_lbum"), null,
                     Catalog.GetString ("Play all songs from an album, then randomly choose another album"),
-                    (int)PlaybackShuffleMode.Album)
+                    (int)PlaybackShuffleMode.Album),
+                    
+                new RadioActionEntry ("ShuffleRatingAction", null,
+                    Catalog.GetString ("Shuffle by _Rating"), null,
+                    Catalog.GetString ("Play songs with a random selection that follows songs' ratings (stars) "),
+                    (int)PlaybackShuffleMode.Rating),
             }, 0, OnActionChanged);
                 
             this["ShuffleOffAction"].IconName = "media-skip-forward";
             this["ShuffleSongAction"].IconName = "media-playlist-shuffle";
             this["ShuffleArtistAction"].IconName = "media-playlist-shuffle";
             this["ShuffleAlbumAction"].IconName = "media-playlist-shuffle";
+            this["ShuffleRatingAction"].IconName = "media-playlist-shuffle";
             this["ShuffleArtistAction"].Sensitive = false;
             this["ShuffleAlbumAction"].Sensitive = false;
+          //  this["ShuffleRatingAction"].Sensitive = false;
 
             Gtk.Action action = this[ConfigIdToActionName (ShuffleMode.Get ())];
             if (action is RadioAction) {
@@ -164,6 +171,7 @@
             yield return (RadioAction)this["ShuffleSongAction"];
             yield return (RadioAction)this["ShuffleArtistAction"];
             yield return (RadioAction)this["ShuffleAlbumAction"];
+            yield return (RadioAction)this["ShuffleRatingAction"];
         }
 
         IEnumerator IEnumerable.GetEnumerator ()
@@ -186,7 +194,7 @@
             "playback", "shuffle_mode",
             "off",
             "Shuffle playback",
-            "Shuffle mode (shuffle_off, shuffle_song, shuffle_artist, shuffle_album)"
+            "Shuffle mode (shuffle_off, shuffle_song, shuffle_artist, shuffle_album, shuffle_rating)"
         );
     }
 }
Index: src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs
===================================================================
--- src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs	(revision 4915)
+++ src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackControllerService.cs	(working copy)
@@ -340,7 +340,7 @@
         
         private TrackInfo QueryTrackRandom (bool restart)
         {
-            return Source.TrackModel.GetRandom (source_set_at, restart);
+            return Source.TrackModel.GetRandom (source_set_at, restart, ShuffleMode);
             //return Source.TrackModel[random.Next (0, Source.TrackModel.Count - 1)];
         }
         
Index: src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackShuffleMode.cs
===================================================================
--- src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackShuffleMode.cs	(revision 4915)
+++ src/Core/Banshee.Services/Banshee.PlaybackController/PlaybackShuffleMode.cs	(working copy)
@@ -35,6 +35,7 @@
         Linear,
         Song,
         Artist,
-        Album
+        Album,
+        Rating
     }
 }
Index: src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs
===================================================================
--- src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs	(revision 4915)
+++ src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackListModel.cs	(working copy)
@@ -43,6 +43,8 @@
 using Banshee.Query;
 using Banshee.Database;
 
+using Banshee.PlaybackController;
+
 namespace Banshee.Collection.Database
 {       
     public class DatabaseTrackListModel : TrackListModel, IExportableModel, 
@@ -338,9 +340,32 @@
 
         private DateTime random_began_at = DateTime.MinValue;
         private DateTime last_random = DateTime.MinValue;
-        private static string random_fragment = "AND (LastPlayedStamp < ? OR LastPlayedStamp IS NULL) AND (LastSkippedStamp < ? OR LastSkippedStamp IS NULL) ORDER BY RANDOM()";
+        private static string random_fragment_rating = @"AND (LastPlayedStamp < ? OR LastPlayedStamp IS NULL) 
+                                                         AND (LastSkippedStamp < ? OR LastSkippedStamp IS NULL) 
+                                                         AND (CoreTracks.Rating == ?) ORDER BY RANDOM()"; 
+       
+        private static string random_fragment = @"AND (LastPlayedStamp < ? OR LastPlayedStamp IS NULL) 
+                                                  AND (LastSkippedStamp < ? OR LastSkippedStamp IS NULL) 
+                                                  ORDER BY RANDOM()";
+       
+        
+        public override TrackInfo GetRandom (DateTime notPlayedSince, bool repeat, PlaybackShuffleMode shuffleMode)
+        {
+            if (shuffleMode == PlaybackShuffleMode.Linear)
+                return GetRandomSong (notPlayedSince, repeat);    
+            else if (shuffleMode == PlaybackShuffleMode.Rating)
+                return GetRandomRating (notPlayedSince, repeat);
+            else //until other random modes gets implemented
+                return GetRandomSong (notPlayedSince, repeat);
+        }
+            
         public override TrackInfo GetRandom (DateTime notPlayedSince, bool repeat)
         {
+            return GetRandomSong (notPlayedSince, repeat);
+        }
+        
+        private TrackInfo GetRandomSong (DateTime notPlayedSince, bool repeat)
+        {
             lock (this) {
                 if (Count == 0)
                     return null;
@@ -358,8 +383,104 @@
                 last_random = DateTime.Now;
                 return track;
             }
+        }
+        private ShuffleRating w_random = new ShuffleRating(6, connection); 
+        
+        private TrackInfo GetRandomRating (DateTime notPlayedSince, bool repeat)
+        {
+            lock (this) {
+                if (Count == 0)
+                    return null;
+
+                if (random_began_at < notPlayedSince)
+                    random_began_at = last_random = notPlayedSince;
+
+                int next_rating = w_random.NextRating;
+                TrackInfo track = cache.GetSingle (random_fragment_rating, random_began_at, random_began_at, next_rating);
+                    
+                if (track == null && repeat) {
+                    random_began_at = last_random;
+                    track = cache.GetSingle (random_fragment_rating, random_began_at, random_began_at, next_rating);
+                }
+                           
+                last_random = DateTime.Now;
+                return track;
+            }
         }
-
+        
+        internal class ShuffleRating
+        {
+            //private static bool loaded = false;    
+            private int classes;
+            private double[] weights;
+            private int[] rating;
+            private Random random;
+            private const int NO_RATING_VALUE = 3; //unrated songs (with rating == 0) are considered like 3 stars songs
+            private readonly BansheeDbConnection connection;
+
+            public ShuffleRating (int classes, BansheeDbConnection connection)
+            {
+                //if (!loaded) {
+                    this.classes = classes;
+                    this.random = new Random ();
+                    this.connection = connection;
+
+                    weights = new double[classes];
+                    rating =  new int[classes];
+                    for (int i = 0; i < classes; i++) {
+                       rating[i]= i;
+                    }
+              
+                    FillWeights ();
+                //}
+                //loaded = true;
+            }
+        
+            private void FillWeights ()
+            {
+                long[] library_banshee = new long[classes];
+                long with_rating = 0;
+                for (int i = 0; i < classes; i++) {
+                    library_banshee[i] = connection.Query<long> ("SELECT COUNT(*) FROM CoreTracks WHERE Rating == ?", i);
+                    with_rating += library_banshee[i];
+                    Log.DebugFormat ("{0} songs with {1} stars", library_banshee[i], i);
+                }
+                // libraryBanshee[i] now contains the number of songs with i stars
+
+                double tot = 0;
+                for (int i = 0; i < classes; i++) {
+                    weights[i] = library_banshee[i] * ((i == 0) ? NO_RATING_VALUE : rating[i]);
+                    tot += weights[i];
+                }
+                for (int i = 0; i < classes; i++) { 
+                    weights[i] /= tot;
+                    Log.DebugFormat ("Songs with {0} stars have a weight of {1}", i, weights[i]);
+                }
+
+                Array.Sort (weights, rating);
+            }
+
+            private int NextRandom ()
+            {
+                double rand = random.NextDouble ();
+                for (int i = 0; i < classes; i++) {
+                    rand -= weights[i];
+                    if (rand < 0) {
+                        Log.DebugFormat ("Selected rating {0}", rating[i]);
+                        return i;
+                    }
+                }
+                // If for some rounding error rand is still >= 0 we simply return
+                // the highest class.
+                Log.DebugFormat ("After...Selected rating {0}", rating[classes-1]);
+                return classes-1;
+            }
+        
+            public int NextRating {
+                get { return rating[NextRandom ()]; }
+            }
+        }
+        
         public override TrackInfo this[int index] {
             get {
                 lock (this) {
Index: src/Core/Banshee.Services/Banshee.Collection/TrackListModel.cs
===================================================================
--- src/Core/Banshee.Services/Banshee.Collection/TrackListModel.cs	(revision 4915)
+++ src/Core/Banshee.Services/Banshee.Collection/TrackListModel.cs	(working copy)
@@ -34,6 +34,7 @@
 using Hyena.Query;
 
 using Banshee.ServiceStack;
+using Banshee.PlaybackController;
 
 namespace Banshee.Collection
 {
@@ -51,6 +52,7 @@
         
         public abstract int IndexOf (TrackInfo track);
 
-        public abstract TrackInfo GetRandom (DateTime notPlayedSince, bool repeat);
+        public abstract TrackInfo GetRandom (DateTime notPlayedSince, bool repeat); 
+        public abstract TrackInfo GetRandom (DateTime notPlayedSince, bool repeat, PlaybackShuffleMode shuffleMode);
     }
-}
+}
\ No newline at end of file
Index: src/Core/Banshee.Services/Banshee.Collection/MemoryTrackListModel.cs
===================================================================
--- src/Core/Banshee.Services/Banshee.Collection/MemoryTrackListModel.cs	(revision 4915)
+++ src/Core/Banshee.Services/Banshee.Collection/MemoryTrackListModel.cs	(working copy)
@@ -30,6 +30,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using Banshee.PlaybackController;
 
 namespace Banshee.Collection
 {
@@ -88,7 +89,12 @@
 
             return this [random.Next (0, Count - 1)];
         }
-
+        
+        public override TrackInfo GetRandom (DateTime notPlayedSince, bool repeat, PlaybackShuffleMode shuffleMode)
+        {
+            return GetRandom (notPlayedSince, repeat);        
+        }
+        
         public override int Count { 
             get { lock (this) { return tracks.Count; } }
         }
