Index: lib/rb-preferences.h
===================================================================
--- lib/rb-preferences.h	(revision 5499)
+++ lib/rb-preferences.h	(working copy)
@@ -76,6 +76,15 @@
 #define CONF_PLAYER_TRANSITION_TIME 	CONF_PREFIX "/player/transition_time"
 #define CONF_PLAYER_NETWORK_BUFFER_SIZE	CONF_PREFIX "/player/network_buffer_size"
 
+#define CONF_RANDOM_DIR			CONF_PREFIX "/random"
+#define CONF_RANDOM_RATING_BIAS		CONF_PREFIX "/random/rating_bias"
+#define CONF_RANDOM_AGE_BIAS		CONF_PREFIX "/random/age_bias"
+#define CONF_RANDOM_VERY_RECENT_BIAS    CONF_PREFIX "/random/very_recent_bias"
+#define CONF_RANDOM_VERY_RECENT_PERIOD	CONF_PREFIX "/random/very_recent_period"
+#define CONF_RANDOM_SHUFFLE_BEHAVIOUR	CONF_PREFIX "/random/shuffle_behaviour"
+/* These are the indexes of the radio buttons - is there a safer way? */
+#define CONF_RANDOM_SHUFFLE_BEHAVIOUR_INDEX_SHUFFLE 0
+#define CONF_RANDOM_SHUFFLE_BEHAVIOUR_INDEX_RANDOM 1
 G_END_DECLS
 
 #endif /* __RB_PREFERENCES_H */
Index: shell/rb-shell-preferences.c
===================================================================
--- shell/rb-shell-preferences.c	(revision 5499)
+++ shell/rb-shell-preferences.c	(working copy)
@@ -72,6 +72,17 @@
 static void update_playback_prefs_sensitivity (RBShellPreferences *preferences);
 #endif
 
+void rb_shell_preferences_random_shuffle_behaviour_activated_cb (GtkWidget *widget,
+						      RBShellPreferences *shell_preferences);
+static void rb_shell_preferences_random_rating_bias_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences);
+static void rb_shell_preferences_random_age_bias_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences);
+static void rb_shell_preferences_very_recent_play_bias_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences);
+static void rb_shell_preferences_very_recent_play_period_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences);
+
 enum
 {
 	PROP_0,
@@ -103,6 +114,13 @@
 	GtkWidget *network_buffer_size;
 #endif
 
+        /* Random settings pane */
+	GSList *shuffle_button_behaviour_group;
+	GtkWidget *random_rating_bias;
+	GtkWidget *random_age_bias;
+	GtkWidget *random_veryrecentplay_bias;
+	GtkWidget *random_veryrecentplay_period;
+
 	GSList *browser_views_group;
 
 	GtkWidget *toolbar_style_menu;
@@ -285,11 +303,63 @@
 				  gtk_label_new (_("Playback")));
 	g_object_unref (xml);
 #endif
-
 	eel_gconf_notification_add (CONF_PLAYER_DIR,
 				    (GConfClientNotifyFunc) rb_shell_preferences_ui_pref_changed,
 				    shell_preferences);
 
+        /* random playback preferences */
+        xml = rb_glade_xml_new ("random-prefs.glade",
+                                "random_table",
+                                shell_preferences);
+	rb_glade_boldify_label (xml, "shuffle_behaviour_label");
+	rb_glade_boldify_label (xml, "rating_bias_label");
+	rb_glade_boldify_label (xml, "age_bias_label");
+	rb_glade_boldify_label (xml, "veryrecentplay_bias_label");
+	rb_glade_boldify_label (xml, "veryrecentplay_period_label");
+
+	tmp = glade_xml_get_widget (xml, "shuffle_button_radio_shuffle");
+	shell_preferences->priv->shuffle_button_behaviour_group =
+		g_slist_reverse (g_slist_copy (gtk_radio_button_get_group
+					       (GTK_RADIO_BUTTON (tmp))));
+
+	shell_preferences->priv->random_rating_bias =
+		glade_xml_get_widget (xml, "rating_bias_scale");
+	g_signal_connect_object (shell_preferences->priv->random_rating_bias,
+				 "value-changed",
+				 G_CALLBACK (rb_shell_preferences_random_rating_bias_changed_cb),
+				 shell_preferences, 0);
+
+	shell_preferences->priv->random_age_bias =
+		glade_xml_get_widget (xml, "age_bias_scale");
+	g_signal_connect_object (shell_preferences->priv->random_age_bias,
+				 "value-changed",
+				 G_CALLBACK (rb_shell_preferences_random_age_bias_changed_cb),
+				 shell_preferences, 0);
+
+	shell_preferences->priv->random_veryrecentplay_bias =
+		glade_xml_get_widget (xml, "veryrecentplay_bias_scale");
+	g_signal_connect_object (shell_preferences->priv->random_veryrecentplay_bias,
+				 "value-changed",
+				 G_CALLBACK (rb_shell_preferences_very_recent_play_bias_changed_cb),
+				 shell_preferences, 0);
+
+	shell_preferences->priv->random_veryrecentplay_period =
+		glade_xml_get_widget (xml, "veryrecentplay_period_scale");
+	g_signal_connect_object (shell_preferences->priv->random_veryrecentplay_period,
+				 "value-changed",
+				 G_CALLBACK (rb_shell_preferences_very_recent_play_period_changed_cb),
+				 shell_preferences, 0);
+
+
+	gtk_notebook_append_page (GTK_NOTEBOOK (shell_preferences->priv->notebook),
+				  glade_xml_get_widget (xml, "random_table"),
+				  gtk_label_new (_("Random")));
+	g_object_unref (xml);
+	eel_gconf_notification_add (CONF_RANDOM_DIR,
+				    (GConfClientNotifyFunc) rb_shell_preferences_ui_pref_changed,
+				    shell_preferences);
+
+
 	rb_shell_preferences_sync (shell_preferences);
 }
 
@@ -477,7 +547,8 @@
 {
 	char *columns;
 	GSList  *l;
-	gint view, i;
+	gint view, i, behaviour;
+        gdouble d;
 
 	shell_preferences->priv->loading = TRUE;
 
@@ -565,6 +636,22 @@
 	}
 #endif
 
+        /* random behaviour pane */
+        d = eel_gconf_get_float (CONF_RANDOM_RATING_BIAS);
+        gtk_range_set_value (GTK_RANGE (shell_preferences->priv->random_rating_bias), d);
+        d = eel_gconf_get_float (CONF_RANDOM_AGE_BIAS);
+        gtk_range_set_value (GTK_RANGE (shell_preferences->priv->random_age_bias), d);
+        d = eel_gconf_get_float (CONF_RANDOM_VERY_RECENT_BIAS);
+        gtk_range_set_value (GTK_RANGE (shell_preferences->priv->random_veryrecentplay_bias), d);
+        d = eel_gconf_get_float (CONF_RANDOM_VERY_RECENT_PERIOD);
+        gtk_range_set_value (GTK_RANGE (shell_preferences->priv->random_veryrecentplay_period), d);
+
+	behaviour = eel_gconf_get_integer (CONF_RANDOM_SHUFFLE_BEHAVIOUR);
+	for (l = shell_preferences->priv->shuffle_button_behaviour_group, i = 0; l != NULL; l = g_slist_next (l), i++)
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (l->data), (i == behaviour));
+
+        /* Do something to get these prefs into the actual random code! */
+
 	shell_preferences->priv->loading = FALSE;
 }
 
@@ -652,3 +739,58 @@
 }
 
 #endif
+
+void
+rb_shell_preferences_random_shuffle_behaviour_activated_cb (GtkWidget *widget,
+						 RBShellPreferences *shell_preferences)
+{
+	int index;
+
+	if (shell_preferences->priv->loading)
+		return;
+
+	index = g_slist_index (shell_preferences->priv->shuffle_button_behaviour_group, widget);
+
+	eel_gconf_set_integer (CONF_RANDOM_SHUFFLE_BEHAVIOUR, index);
+}
+
+static void
+rb_shell_preferences_random_rating_bias_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences)
+{
+	gdouble v;
+
+	v = gtk_range_get_value (range);
+	eel_gconf_set_float (CONF_RANDOM_RATING_BIAS, (float)v);
+}
+
+static void
+rb_shell_preferences_random_age_bias_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences)
+{
+	gdouble v;
+
+	v = gtk_range_get_value (range);
+	eel_gconf_set_float (CONF_RANDOM_AGE_BIAS, (float)v);
+}
+
+static void
+rb_shell_preferences_very_recent_play_bias_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences)
+{
+	gdouble v;
+
+	v = gtk_range_get_value (range);
+	eel_gconf_set_float (CONF_RANDOM_VERY_RECENT_BIAS, (float)v);
+}
+
+static void
+rb_shell_preferences_very_recent_play_period_changed_cb (GtkRange *range,
+							 RBShellPreferences *preferences)
+{
+	gdouble v;
+
+	v = gtk_range_get_value (range);
+	eel_gconf_set_float (CONF_RANDOM_VERY_RECENT_PERIOD, (float)v);
+}
+
Index: shell/rb-play-order-random-by-age-and-rating.c
===================================================================
--- shell/rb-play-order-random-by-age-and-rating.c	(revision 5499)
+++ shell/rb-play-order-random-by-age-and-rating.c	(working copy)
@@ -22,6 +22,8 @@
 #include "config.h"
 
 #include "rb-play-order-random-by-age-and-rating.h"
+#include "eel-gconf-extensions.h"
+#include "rb-preferences.h"
 
 #include "rhythmdb.h"
 #include <time.h>
@@ -58,8 +60,49 @@
 }
 
 static void
+rb_random_play_order_by_age_and_rating_fromeel (RBRandomPlayOrderByAgeAndRating *porder)
+{
+        porder->rating_bias = eel_gconf_get_float (CONF_RANDOM_RATING_BIAS);
+        porder->age_bias = eel_gconf_get_float (CONF_RANDOM_AGE_BIAS);
+        porder->very_recent_bias = eel_gconf_get_float (CONF_RANDOM_VERY_RECENT_BIAS);
+
+	/* This is used as a divisor so it mustn't be 0 and it doesn't make sense for it to be less than 1 */
+	if (porder->very_recent_bias < 1.0)
+		porder->very_recent_bias = 1.0;
+
+	/* Users setting is in days, seconds is more useful for us here */
+        porder->very_recent_period = eel_gconf_get_float (CONF_RANDOM_VERY_RECENT_PERIOD) * 60*60*24;
+}
+
+static void
+rb_random_play_order_by_age_and_rating_prefchange_cb (GConfClient *client,
+                         guint cnxn_id,
+                         GConfEntry *entry,
+                         RBRandomPlayOrderByAgeAndRating *porder)
+{
+	rb_random_play_order_by_age_and_rating_fromeel (porder);
+}
+
+static void
 rb_random_play_order_by_age_and_rating_init (RBRandomPlayOrderByAgeAndRating *porder)
 {
+	/* treblig: Not sure if the etiquette is to do this here or do it elsewhere in the shell
+	and pass it in? */
+	rb_random_play_order_by_age_and_rating_fromeel(porder);
+
+	/* Need to clean these out in a destructor */
+		eel_gconf_notification_add (CONF_RANDOM_RATING_BIAS,
+               	                             (GConfClientNotifyFunc) rb_random_play_order_by_age_and_rating_prefchange_cb,
+               	                             porder);
+		eel_gconf_notification_add (CONF_RANDOM_AGE_BIAS,
+               	                             (GConfClientNotifyFunc) rb_random_play_order_by_age_and_rating_prefchange_cb,
+               	                             porder);
+		eel_gconf_notification_add (CONF_RANDOM_VERY_RECENT_BIAS,
+               	                             (GConfClientNotifyFunc) rb_random_play_order_by_age_and_rating_prefchange_cb,
+               	                             porder);
+		eel_gconf_notification_add (CONF_RANDOM_VERY_RECENT_PERIOD,
+               	                             (GConfClientNotifyFunc) rb_random_play_order_by_age_and_rating_prefchange_cb,
+               	                             porder);
 }
 
 static double
@@ -69,7 +112,11 @@
 	gulong last_play;
 	gulong seconds_since_last_play;
 	gdouble rating;
+	double log_seconds_since_last_play;
+	double result;
 
+	RBRandomPlayOrderByAgeAndRating *us=RB_RANDOM_PLAY_ORDER_BY_AGE_AND_RATING (rorder);
+
 	/* This finds the log of the number of seconds since the last play.
 	 * It handles never played automatically, since now-0 is a valid
 	 * argument to log(). */
@@ -86,5 +133,26 @@
 	if (rating < 0.01)
 		rating = 2.5;
 
-	return log (seconds_since_last_play) * (rating + 1.0);
+	log_seconds_since_last_play=log (seconds_since_last_play);
+
+	/* Apply biases */
+	rating = (rating + 1.0) * us->rating_bias;
+	log_seconds_since_last_play *= us->age_bias;
+
+	/* The biases can be 0, which leaves the danger of killing the whole weight
+	   This doesn't feel the right answer though ? */
+	if (rating < 0.01)
+		rating = 0.01;
+	if (log_seconds_since_last_play < 0.01)
+		log_seconds_since_last_play = 0.01;
+
+
+	result = log_seconds_since_last_play * rating;
+
+	/* Now apply the very recent penalty - if it has been played within a set time then we scale
+	   the weight down again */
+	if (seconds_since_last_play < us->very_recent_period)
+		result = result / us->very_recent_bias;
+
+	return result;
 }
Index: shell/rb-play-order-random-by-age-and-rating.h
===================================================================
--- shell/rb-play-order-random-by-age-and-rating.h	(revision 5499)
+++ shell/rb-play-order-random-by-age-and-rating.h	(working copy)
@@ -38,6 +38,11 @@
 typedef struct
 {
 	RBRandomPlayOrder parent;
+
+	gdouble rating_bias;
+	gdouble age_bias;
+	gdouble very_recent_bias;
+	gdouble very_recent_period;
 } RBRandomPlayOrderByAgeAndRating;
 
 typedef struct
Index: shell/rb-play-order-random-by-age.c
===================================================================
--- shell/rb-play-order-random-by-age.c	(revision 5499)
+++ shell/rb-play-order-random-by-age.c	(working copy)
@@ -1,81 +0,0 @@
-/*
- *  arch-tag: Implementation of random play order weighted by the time since last play
- *
- *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
- *
- *  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 "rb-play-order-random-by-age.h"
-
-#include "rhythmdb.h"
-#include <time.h>
-#include <math.h>
-
-static void rb_random_play_order_by_age_class_init (RBRandomPlayOrderByAgeClass *klass);
-
-static double rb_random_by_age_get_entry_weight (RBRandomPlayOrder *rorder,
-						 RhythmDB *db, RhythmDBEntry *entry);
-
-G_DEFINE_TYPE (RBRandomPlayOrderByAge, rb_random_play_order_by_age, RB_TYPE_RANDOM_PLAY_ORDER)
-
-static void
-rb_random_play_order_by_age_class_init (RBRandomPlayOrderByAgeClass *klass)
-{
-	RBRandomPlayOrderClass *rorder;
-
-	rorder = RB_RANDOM_PLAY_ORDER_CLASS (klass);
-	rorder->get_entry_weight = rb_random_by_age_get_entry_weight;
-}
-
-RBPlayOrder *
-rb_random_play_order_by_age_new (RBShellPlayer *player)
-{
-	RBRandomPlayOrderByAge *rorder;
-
-	rorder = g_object_new (RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE,
-			"player", player,
-			NULL);
-
-	return RB_PLAY_ORDER (rorder);
-}
-
-static void
-rb_random_play_order_by_age_init (RBRandomPlayOrderByAge *porder)
-{
-}
-
-static double
-rb_random_by_age_get_entry_weight (RBRandomPlayOrder *rorder, RhythmDB *db, RhythmDBEntry *entry)
-{
-	time_t now;
-	gulong last_play;
-	gulong seconds_since_last_play;
-
-	/* This returns the log of the number of seconds since the last play.
-	 * It handles never played automatically, since now-0 is a valid
-	 * argument to log(). */
-
-	time (&now);
-	last_play = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_PLAYED);
-	seconds_since_last_play = now - last_play;
-	/* The lowest weight should be 0. */
-	if (seconds_since_last_play < 1)
-		seconds_since_last_play = 1;
-	return log (seconds_since_last_play);
-}
Index: shell/rb-shell-player.c
===================================================================
--- shell/rb-shell-player.c	(revision 5499)
+++ shell/rb-shell-player.c	(working copy)
@@ -67,9 +67,6 @@
 #include "rb-play-order-linear.h"
 #include "rb-play-order-linear-loop.h"
 #include "rb-play-order-shuffle.h"
-#include "rb-play-order-random-equal-weights.h"
-#include "rb-play-order-random-by-age.h"
-#include "rb-play-order-random-by-rating.h"
 #include "rb-play-order-random-by-age-and-rating.h"
 #include "rb-play-order-queue.h"
 
@@ -157,6 +154,8 @@
 							GConfEntry *entry, RBShellPlayer *player);
 static void gconf_network_buffer_size_changed (GConfClient *client, guint cnxn_id,
 					       GConfEntry *entry, RBShellPlayer *player);
+static void gconf_shuffle_button_behaviour_changed (GConfClient *client, guint cnxn_id,
+						    GConfEntry *entry, RBShellPlayer *player);
 static void rb_shell_player_playing_changed_cb (RBShellPlayer *player,
 						GParamSpec *arg1,
 						gpointer user_data);
@@ -231,6 +230,7 @@
 
 	RBPlayOrder *play_order;
 	RBPlayOrder *queue_play_order;
+	gint shuffle_button_behaviour; /* as per CONF_RANDOM_SHUFFLE_BEHAVIOUR_INDEX_* */
 
 	GQueue *playlist_urls;
 
@@ -242,6 +242,7 @@
 	guint gconf_track_transition_time_id;
 	guint gconf_track_transition_album_check_id;
 	guint gconf_network_buffer_size_id;
+	guint gconf_shuffle_button_behaviour_id;
 
 	gboolean mute;
 	float volume;
@@ -811,12 +812,6 @@
 					RB_TYPE_LINEAR_PLAY_ORDER_LOOP, FALSE);
 	rb_shell_player_add_play_order (player, "shuffle", N_("Shuffle"),
 					RB_TYPE_SHUFFLE_PLAY_ORDER, FALSE);
-	rb_shell_player_add_play_order (player, "random-equal-weights", N_("Random with equal weights"),
-					RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS, FALSE);
-	rb_shell_player_add_play_order (player, "random-by-age", N_("Random by time since last play"),
-					RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE, FALSE);
-	rb_shell_player_add_play_order (player, "random-by-rating", N_("Random by rating"),
-					RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING, FALSE);
 	rb_shell_player_add_play_order (player, "random-by-age-and-rating", N_("Random by time since last play and rating"),
 					RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE_AND_RATING, FALSE);
 	rb_shell_player_add_play_order (player, "queue", N_("Linear, removing entries once played"),
@@ -876,6 +871,11 @@
 					    player);
 
 	player->priv->volume = eel_gconf_get_float (CONF_STATE_VOLUME);
+	player->priv->shuffle_button_behaviour = eel_gconf_get_integer (CONF_RANDOM_SHUFFLE_BEHAVIOUR);
+	player->priv->gconf_shuffle_button_behaviour_id =
+		eel_gconf_notification_add (CONF_RANDOM_SHUFFLE_BEHAVIOUR,
+					    (GConfClientNotifyFunc)gconf_shuffle_button_behaviour_changed,
+					    player);
 
 	player->priv->track_transition_time = (int)(eel_gconf_get_float (CONF_PLAYER_TRANSITION_TIME));
 	player->priv->track_transition_album_check = eel_gconf_get_boolean (CONF_PLAYER_TRANSITION_ALBUM_CHECK);
@@ -1614,13 +1614,30 @@
 	g_free (old_val);
 }
 
+static const char*
+rb_shell_player_get_order_from_flags (RBShellPlayer *player,
+				      gboolean shuffle,
+				      gboolean repeat)
+{
+	/* This behaviour isn't right yet - I don't think we should special case this,
+	   I think we should just kill off the shuffle && repeat  combo so that shuffle
+	   being true always does what the pref says */
+	if (shuffle  && !repeat) {
+		if (player->priv->shuffle_button_behaviour == CONF_RANDOM_SHUFFLE_BEHAVIOUR_INDEX_SHUFFLE)
+			return "shuffle";
+		else
+			return "random-by-age-and-rating";
+	}
+	
+	return state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
+}
+
 void
 rb_shell_player_set_playback_state (RBShellPlayer *player,
 				    gboolean shuffle,
 				    gboolean repeat)
 {
-	const char *neworder = state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
-	rb_shell_player_set_play_order (player, neworder);
+	rb_shell_player_set_play_order (player, rb_shell_player_get_order_from_flags(player, shuffle, repeat));
 }
 
 static void
@@ -2293,7 +2310,7 @@
 	rb_shell_player_get_playback_state (player, &shuffle, &repeat);
 
 	shuffle = !shuffle;
-	neworder = state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
+	neworder = rb_shell_player_get_order_from_flags(player, shuffle, repeat);
 	rb_shell_player_set_play_order (player, neworder);
 }
 
@@ -2312,7 +2329,7 @@
 	rb_shell_player_get_playback_state (player, &shuffle, &repeat);
 
 	repeat = !repeat;
-	neworder = state_to_play_order[shuffle ? 1 : 0][repeat ? 1 : 0];
+	neworder = rb_shell_player_get_order_from_flags(player, shuffle, repeat);
 	rb_shell_player_set_play_order (player, neworder);
 }
 
@@ -3418,6 +3435,14 @@
 }
 
 static void
+gconf_shuffle_button_behaviour_changed (GConfClient *client, guint cnxn_id,
+				        GConfEntry *entry, RBShellPlayer *player)
+{
+	/* Should we actually sync the play button now? */
+	player->priv->shuffle_button_behaviour = eel_gconf_get_integer (CONF_RANDOM_SHUFFLE_BEHAVIOUR);
+}
+
+static void
 gconf_network_buffer_size_changed (GConfClient *client,
 				   guint cnxn_id,
 				   GConfEntry *entry,
Index: shell/rb-play-order-random-by-age.h
===================================================================
--- shell/rb-play-order-random-by-age.h	(revision 5499)
+++ shell/rb-play-order-random-by-age.h	(working copy)
@@ -1,54 +0,0 @@
-/*
- *  arch-tag: Header for random play order weighted by the time since last play
- *
- *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
- *
- *  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_PLAY_ORDER_RANDOM_BY_AGE_H
-#define __RB_PLAY_ORDER_RANDOM_BY_AGE_H
-
-#include "rb-play-order-random.h"
-
-#include "rb-shell-player.h"
-
-G_BEGIN_DECLS
-
-#define RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE         (rb_random_play_order_by_age_get_type ())
-#define RB_RANDOM_PLAY_ORDER_BY_AGE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE, RBRandomPlayOrderByAge))
-#define RB_RANDOM_PLAY_ORDER_BY_AGE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE, RBRandomPlayOrderByAgeClass))
-#define RB_IS_RANDOM_PLAY_ORDER_BY_AGE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE))
-#define RB_IS_RANDOM_PLAY_ORDER_BY_AGE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE))
-#define RB_RANDOM_PLAY_ORDER_BY_AGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_RANDOM_PLAY_ORDER_BY_AGE, RBRandomPlayOrderByAgeClass))
-
-typedef struct
-{
-	RBRandomPlayOrder parent;
-} RBRandomPlayOrderByAge;
-
-typedef struct
-{
-	RBRandomPlayOrderClass parent_class;
-} RBRandomPlayOrderByAgeClass;
-
-GType					rb_random_play_order_by_age_get_type	(void);
-
-RBPlayOrder *				rb_random_play_order_by_age_new		(RBShellPlayer *player);
-
-G_END_DECLS
-
-#endif /* __RB_PLAY_ORDER_RANDOM_BY_AGE_H */
Index: shell/rb-play-order-random-equal-weights.c
===================================================================
--- shell/rb-play-order-random-equal-weights.c	(revision 5499)
+++ shell/rb-play-order-random-equal-weights.c	(working copy)
@@ -1,65 +0,0 @@
-/*
- *  arch-tag: Implementation of random navigation method with equal weights for each song
- *
- *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
- *
- *  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 "rb-play-order-random-equal-weights.h"
-
-static void rb_random_play_order_equal_weights_class_init (RBRandomPlayOrderEqualWeightsClass *klass);
-
-static double rb_random_equal_weights_get_entry_weight (RBRandomPlayOrder *rorder,
-							RhythmDB *db, RhythmDBEntry *entry);
-
-G_DEFINE_TYPE (RBRandomPlayOrderEqualWeights,
-	       rb_random_play_order_equal_weights,
-	       RB_TYPE_RANDOM_PLAY_ORDER)
-
-static void
-rb_random_play_order_equal_weights_class_init (RBRandomPlayOrderEqualWeightsClass *klass)
-{
-	RBRandomPlayOrderClass *rorder;
-
-	rorder = RB_RANDOM_PLAY_ORDER_CLASS (klass);
-	rorder->get_entry_weight = rb_random_equal_weights_get_entry_weight;
-}
-
-RBPlayOrder *
-rb_random_play_order_equal_weights_new (RBShellPlayer *player)
-{
-	RBRandomPlayOrderEqualWeights *rorder;
-
-	rorder = g_object_new (RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS,
-			"player", player,
-			NULL);
-
-	return RB_PLAY_ORDER (rorder);
-}
-
-static void
-rb_random_play_order_equal_weights_init (RBRandomPlayOrderEqualWeights *porder)
-{
-}
-
-static double
-rb_random_equal_weights_get_entry_weight (RBRandomPlayOrder *rorder, RhythmDB *db, RhythmDBEntry *entry)
-{
-	return 1.0;
-}
Index: shell/rb-play-order-random-equal-weights.h
===================================================================
--- shell/rb-play-order-random-equal-weights.h	(revision 5499)
+++ shell/rb-play-order-random-equal-weights.h	(working copy)
@@ -1,54 +0,0 @@
-/*
- *  arch-tag: Header for random navigation method with equal weights for each song
- *
- *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
- *
- *  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_PLAY_ORDER_RANDOM_EQUAL_WEIGHTS_H
-#define __RB_PLAY_ORDER_RANDOM_EQUAL_WEIGHTS_H
-
-#include "rb-play-order-random.h"
-
-#include "rb-shell-player.h"
-
-G_BEGIN_DECLS
-
-#define RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS         (rb_random_play_order_equal_weights_get_type ())
-#define RB_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS, RBRandomPlayOrderEqualWeights))
-#define RB_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS, RBRandomPlayOrderEqualWeightsClass))
-#define RB_IS_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS))
-#define RB_IS_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS))
-#define RB_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_RANDOM_PLAY_ORDER_EQUAL_WEIGHTS, RBRandomPlayOrderEqualWeightsClass))
-
-typedef struct
-{
-	RBRandomPlayOrder parent;
-} RBRandomPlayOrderEqualWeights;
-
-typedef struct
-{
-	RBRandomPlayOrderClass parent_class;
-} RBRandomPlayOrderEqualWeightsClass;
-
-GType					rb_random_play_order_equal_weights_get_type	(void);
-
-RBPlayOrder *				rb_random_play_order_equal_weights_new		(RBShellPlayer *player);
-
-G_END_DECLS
-
-#endif /* __RB_PLAY_ORDER_RANDOM_EQUAL_WEIGHTS_H */
Index: shell/rb-play-order-random-by-rating.c
===================================================================
--- shell/rb-play-order-random-by-rating.c	(revision 5499)
+++ shell/rb-play-order-random-by-rating.c	(working copy)
@@ -1,73 +0,0 @@
-/*
- *  arch-tag: Implementation of random play order weighted by rating
- *
- *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
- *
- *  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 "rb-play-order-random-by-rating.h"
-
-#include "rhythmdb.h"
-#include <time.h>
-#include <math.h>
-
-static void rb_random_play_order_by_rating_class_init (RBRandomPlayOrderByRatingClass *klass);
-
-static double rb_random_by_rating_get_entry_weight (RBRandomPlayOrder *rorder,
-						 RhythmDB *db, RhythmDBEntry *entry);
-
-G_DEFINE_TYPE (RBRandomPlayOrderByRating, rb_random_play_order_by_rating, RB_TYPE_RANDOM_PLAY_ORDER)
-
-static void
-rb_random_play_order_by_rating_class_init (RBRandomPlayOrderByRatingClass *klass)
-{
-	RBRandomPlayOrderClass *rorder;
-
-	rorder = RB_RANDOM_PLAY_ORDER_CLASS (klass);
-	rorder->get_entry_weight = rb_random_by_rating_get_entry_weight;
-}
-
-RBPlayOrder *
-rb_random_play_order_by_rating_new (RBShellPlayer *player)
-{
-	RBRandomPlayOrderByRating *rorder;
-
-	rorder = g_object_new (RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING,
-			"player", player,
-			NULL);
-
-	return RB_PLAY_ORDER (rorder);
-}
-
-static void
-rb_random_play_order_by_rating_init (RBRandomPlayOrderByRating *porder)
-{
-}
-
-static double
-rb_random_by_rating_get_entry_weight (RBRandomPlayOrder *rorder, RhythmDB *db, RhythmDBEntry *entry)
-{
-	double rating;
-
-	rating = rhythmdb_entry_get_double (entry, RHYTHMDB_PROP_RATING);
-	if (rating < 0.01)
-		rating = 2.5;
-
-	return rating;
-}
Index: shell/Makefile.am
===================================================================
--- shell/Makefile.am	(revision 5499)
+++ shell/Makefile.am	(working copy)
@@ -80,14 +80,8 @@
 	rb-play-order-shuffle.h				\
 	rb-play-order-random.c				\
 	rb-play-order-random.h				\
-	rb-play-order-random-equal-weights.c		\
-	rb-play-order-random-equal-weights.h		\
-	rb-play-order-random-by-age.c			\
-	rb-play-order-random-by-age.h			\
 	rb-play-order-random-by-age-and-rating.c	\
 	rb-play-order-random-by-age-and-rating.h	\
-	rb-play-order-random-by-rating.c		\
-	rb-play-order-random-by-rating.h		\
 	rb-tray-icon.c					\
 	rb-tray-icon.h					\
 	rb-missing-plugins.c				\
Index: shell/rb-play-order-random-by-rating.h
===================================================================
--- shell/rb-play-order-random-by-rating.h	(revision 5499)
+++ shell/rb-play-order-random-by-rating.h	(working copy)
@@ -1,54 +0,0 @@
-/*
- *  arch-tag: Header for random play order weighted by rating
- *
- *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
- *
- *  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_PLAY_ORDER_RANDOM_BY_RATING_H
-#define __RB_PLAY_ORDER_RANDOM_BY_RATING_H
-
-#include "rb-play-order-random.h"
-
-#include "rb-shell-player.h"
-
-G_BEGIN_DECLS
-
-#define RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING         (rb_random_play_order_by_rating_get_type ())
-#define RB_RANDOM_PLAY_ORDER_BY_RATING(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING, RBRandomPlayOrderByRating))
-#define RB_RANDOM_PLAY_ORDER_BY_RATING_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING, RBRandomPlayOrderByRatingClass))
-#define RB_IS_RANDOM_PLAY_ORDER_BY_RATING(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING))
-#define RB_IS_RANDOM_PLAY_ORDER_BY_RATING_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING))
-#define RB_RANDOM_PLAY_ORDER_BY_RATING_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_RANDOM_PLAY_ORDER_BY_RATING, RBRandomPlayOrderByRatingClass))
-
-typedef struct
-{
-	RBRandomPlayOrder parent;
-} RBRandomPlayOrderByRating;
-
-typedef struct
-{
-	RBRandomPlayOrderClass parent_class;
-} RBRandomPlayOrderByRatingClass;
-
-GType					rb_random_play_order_by_rating_get_type	(void);
-
-RBPlayOrder *				rb_random_play_order_by_rating_new		(RBShellPlayer *player);
-
-G_END_DECLS
-
-#endif /* __RB_PLAY_ORDER_RANDOM_BY_RATING_H */
Index: shell/rb-play-order-random.c
===================================================================
--- shell/rb-play-order-random.c	(revision 5499)
+++ shell/rb-play-order-random.c	(working copy)
@@ -34,11 +34,10 @@
 
 #include <string.h>
 
-#include "rb-play-order-random-by-age.h"
-
 #include "rb-debug.h"
 #include "rhythmdb.h"
 #include "rb-history.h"
+#include "rb-play-order-random.h"
 
 static void rb_random_play_order_class_init (RBRandomPlayOrderClass *klass);
 static void rb_random_play_order_init (RBRandomPlayOrder *rorder);
Index: data/rhythmbox.schemas
===================================================================
--- data/rhythmbox.schemas	(revision 5499)
+++ data/rhythmbox.schemas	(working copy)
@@ -282,8 +282,8 @@
         <locale name="C">
 	<short>Order to play songs in</short>
 	<long>Value identifies the order songs are played in. Legal values are:
-	"linear", "shuffle", "random-equal-weights", "random-by-age",
-	"random-by-rating".</long>
+	"linear", "shuffle",
+	"random-by-age-and-rating". </long>
         </locale>
       </schema>
       <schema>
@@ -734,6 +734,50 @@
         </locale>
       </schema>
       <schema>
+        <key>/schemas/apps/rhythmbx/random/rating_bias</key>
+        <applyto>/apps/rhythmbox/rating_bias</applyto>
+        <owner>rhythmbox</owner>
+        <type>float</type>
+        <default>1.0</default>
+        <locale name="C">
+	<short>How much influence your ratings have on random playback.</short>
+	<long>The higher this value the more influence your ratings have on random playback.  Unrated entries are equivalent to a rating of 2.5.  Setting this value to 0 causes the random playback to ignore your ratings.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbx/random/age_bias</key>
+        <applyto>/apps/rhythmbox/age_bias</applyto>
+        <owner>rhythmbox</owner>
+        <type>float</type>
+        <default>1.0</default>
+        <locale name="C">
+	<short>Increases the chance that songs that haven't been played for a while are played in random playback.</short>
+	<long>The higher this value the more influence the time since the track was last played has on random playback. Setting this value to 0 causes the random playback to ignore when the track was last played.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbx/random/very_recent_bias</key>
+        <applyto>/apps/rhythmbox/very_recent_bias</applyto>
+        <owner>rhythmbox</owner>
+        <type>float</type>
+        <default>4.0</default>
+        <locale name="C">
+	<short>The higher this value the less likely very recently played tracks will be played in random playback.</short>
+	<long>Tracks that have been played very recently (as defined by very_recent_period) are penalised by having their probability divided by this penalty.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbx/random/very_recent_period</key>
+        <applyto>/apps/rhythmbox/very_recent_period</applyto>
+        <owner>rhythmbox</owner>
+        <type>float</type>
+        <default>2.0</default>
+        <locale name="C">
+	<short>The time (in days) that is classified as 'very recent'.</short>
+	<long>The time (in days) for which 'very_recent_bias' is applied.  This shouldn't be too large otherwise it could include most of your tracks which would make the penalty pointless.</long>
+        </locale>
+      </schema>
+      <schema>
         <key>/schemas/apps/rhythmbox/plugins/no_user_plugins</key>
         <applyto>/apps/rhythmbox/plugins/no_user_plugins</applyto>
         <owner>rhythmbox</owner>
Index: data/glade/random-prefs.glade
===================================================================
--- data/glade/random-prefs.glade	(revision 0)
+++ data/glade/random-prefs.glade	(revision 0)
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.0 on Sun Dec 30 16:21:54 2007 -->
+<glade-interface>
+  <widget class="GtkWindow" id="preferences">
+    <property name="visible">True</property>
+    <property name="resizable">False</property>
+    <child>
+      <widget class="GtkTable" id="random_table">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="border_width">12</property>
+        <property name="n_rows">5</property>
+        <property name="n_columns">2</property>
+        <property name="homogeneous">True</property>
+        <child>
+          <widget class="GtkLabel" id="veryrecentplay_period_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Very recent period (days):</property>
+            <property name="justify">GTK_JUSTIFY_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHScale" id="veryrecentplay_period_scale">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="adjustment">0 0 100 1 10 10</property>
+            <property name="value_pos">GTK_POS_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">4</property>
+            <property name="bottom_attach">5</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHScale" id="veryrecentplay_bias_scale">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="adjustment">1 1 100 1 10 10</property>
+            <property name="value_pos">GTK_POS_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHScale" id="age_bias_scale">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="adjustment">0 0 100 1 10 10</property>
+            <property name="value_pos">GTK_POS_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHScale" id="rating_bias_scale">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="adjustment">0 0 100 1 10 10</property>
+            <property name="value_pos">GTK_POS_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="veryrecentplay_bias_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Bias against very recent play:</property>
+            <property name="justify">GTK_JUSTIFY_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="age_bias_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Bias for 'age':</property>
+            <property name="justify">GTK_JUSTIFY_RIGHT</property>
+          </widget>
+          <packing>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="rating_bias_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Bias towards rating:</property>
+            <property name="single_line_mode">True</property>
+          </widget>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="shuffle_behaviour_label">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">Behaviour of Shuffle button:</property>
+            <property name="justify">GTK_JUSTIFY_RIGHT</property>
+          </widget>
+        </child>
+        <child>
+          <widget class="GtkHButtonBox" id="shuffle_behaviour_box">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <child>
+              <widget class="GtkRadioButton" id="shuffle_button_radio_shuffle">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Shuffle</property>
+                <property name="response_id">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+                <signal name="toggled" handler="rb_shell_preferences_random_shuffle_behaviour_activated_cb"/>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkRadioButton" id="shuffle_button_radio_random">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label" translatable="yes">Random</property>
+                <property name="response_id">0</property>
+                <property name="draw_indicator">True</property>
+                <property name="group">shuffle_button_radio_shuffle</property>
+                <signal name="toggled" handler="rb_shell_preferences_random_shuffle_behaviour_activated_cb"/>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
Index: data/glade/Makefile.am
===================================================================
--- data/glade/Makefile.am	(revision 5499)
+++ data/glade/Makefile.am	(working copy)
@@ -12,6 +12,7 @@
 		plugins.glade			\
 		playlist-save.glade		\
 		playback-prefs.glade		\
+		random-prefs.glade		\
 		uri-new.glade
 
 gladedir = $(pkgdatadir)/glade
