Index: shell/rb-shell.c
===================================================================
--- shell/rb-shell.c	(revision 4749)
+++ shell/rb-shell.c	(working copy)
@@ -413,6 +413,7 @@
 	{ "Edit", NULL, N_("_Edit") },
 	{ "View", NULL, N_("_View") },
 	{ "Control", NULL, N_("_Control") },
+	{ "Rating", NULL, N_("_Rating") },
 	{ "Tools", NULL, N_("_Tools") },
 	{ "Help", NULL, N_("_Help") },
 
Index: shell/rb-shell-player.c
===================================================================
--- shell/rb-shell-player.c	(revision 4749)
+++ shell/rb-shell-player.c	(working copy)
@@ -98,6 +98,10 @@
 					   RBShellPlayer *player);
 static void rb_shell_player_cmd_volume_down (GtkAction *action,
 					     RBShellPlayer *player);
+static void rb_shell_player_rating_cb (RBShellPlayer *player,
+                                       double change, double absolute);
+static void rb_shell_player_update_rating (GtkAction *action,
+                                           RBShellPlayer *player);
 static void rb_shell_player_shuffle_changed_cb (GtkAction *action,
 						RBShellPlayer *player);
 static void rb_shell_player_repeat_changed_cb (GtkAction *action,
@@ -253,6 +257,30 @@
 	{ "ControlVolumeDown", NULL, N_("_Decrease Volume"), "<control>Down",
 	  N_("Decrease playback volume"),
 	  G_CALLBACK (rb_shell_player_cmd_volume_down) },
+	{ "RatingUp", NULL, N_("_Increase Rating"), "<control>Right",
+	  N_("Increase the Rating of the song"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "RatingDown", NULL, N_("_Decrease Rating"), "<control>Left",
+	  N_("Decrease the Rating of the song"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "Rating0", NULL, N_("Set _0 Rating"), "<control>0",
+	  N_("Set the song rating to 0"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "Rating1", NULL, N_("Set _1 Rating"), "<control>1",
+	  N_("Set the song rating to 1"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "Rating2", NULL, N_("Set _2 Rating"), "<control>2",
+	  N_("Set the song rating to 2"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "Rating3", NULL, N_("Set _3 Rating"), "<control>3",
+	  N_("Set the song rating to 3"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "Rating4", NULL, N_("Set _4 Rating"), "<control>4",
+	  N_("Set the song rating to 4"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
+	{ "Rating5", NULL, N_("Set _5 Rating"), "<control>5",
+	  N_("Set the song rating to 5"),
+	  G_CALLBACK (rb_shell_player_update_rating) },
 };
 static guint rb_shell_player_n_actions = G_N_ELEMENTS (rb_shell_player_actions);
 
@@ -1811,6 +1839,72 @@
 }
 
 static void
+rb_shell_player_update_rating (GtkAction *action,
+                               RBShellPlayer *player)
+{
+	gchar *name = gtk_action_get_name(action);
+
+	if ( strcmp(name, "RatingDown") == 0) {
+		rb_shell_player_rating_cb(player, -1.0, 0.0);
+	} else if ( strcmp(name, "RatingUp") == 0) {
+		rb_shell_player_rating_cb(player, 1.0, 0.0);
+	} else if ( strcmp(name, "Rating0") == 0) {
+		rb_shell_player_rating_cb(player, 0.0, 0.0);
+	} else if ( strcmp(name, "Rating1") == 0) {
+                rb_shell_player_rating_cb(player, 0.0, 1.0);
+        } else if ( strcmp(name, "Rating2") == 0) {
+                rb_shell_player_rating_cb(player, 0.0, 2.0);
+        } else if ( strcmp(name, "Rating3") == 0) {
+                rb_shell_player_rating_cb(player, 0.0, 3.0);
+        } else if ( strcmp(name, "Rating4") == 0) {
+                rb_shell_player_rating_cb(player, 0.0, 4.0);
+        } else if ( strcmp(name, "Rating5") == 0) {
+                rb_shell_player_rating_cb(player, 0.0, 5.0);
+        } else {
+                rb_debug("Hit a function that isn't for Ratings");
+        }
+}
+
+static void
+rb_shell_player_rating_cb (RBShellPlayer *player, double change, double absolute)
+{
+	RhythmDBEntry *entry;
+	double score;
+
+	entry = rb_shell_player_get_playing_entry (player);
+
+	if (!entry)
+		return;
+
+	/* We're not changing a value already there, we're setting it absolutely */
+	if (change == 0.0) {
+		score = absolute;
+	} else if (change == 0.0 && absolute == 0.0) {
+		/* We're setting a zero rating */
+		score = 0.0;
+	} else {
+		score = rhythmdb_entry_get_double(entry, RHYTHMDB_PROP_RATING);
+		score = score + change;
+	}
+	if (score > 5.0) score = 5.0;
+	if (score < 0.0) score = 0.0;
+        GValue value = {0, };
+
+        g_return_if_fail (score >= 0 && score <= 5);
+
+        g_value_init (&value, G_TYPE_DOUBLE);
+        g_value_set_double (&value, score);
+
+        /* set the new value for the song */
+        rhythmdb_entry_set (player->priv->db,
+                            entry,
+                            RHYTHMDB_PROP_RATING,
+                            &value);
+        g_value_unset (&value);
+        rhythmdb_commit (player->priv->db);
+}
+
+static void
 rb_shell_player_cmd_play (GtkAction *action,
 			  RBShellPlayer *player)
 {
Index: data/ui/rhythmbox-ui.xml
===================================================================
--- data/ui/rhythmbox-ui.xml	(revision 4749)
+++ data/ui/rhythmbox-ui.xml	(working copy)
@@ -74,6 +74,18 @@
       <placeholder name="ToolsOps_5" />
     </menu>
 
+    <menu name="RatingMenu" action="Rating">
+      <menuitem name="RatingUpMenu" action="RatingUp"/>
+      <menuitem name="RatingDownMenu" action="RatingDown"/>
+      <separator/>
+      <menuitem name="Rating0Menu" action="Rating0"/>
+      <menuitem name="Rating1Menu" action="Rating1"/>
+      <menuitem name="Rating2Menu" action="Rating2"/>
+      <menuitem name="Rating3Menu" action="Rating3"/>
+      <menuitem name="Rating4Menu" action="Rating4"/>
+      <menuitem name="Rating5Menu" action="Rating5"/>
+    </menu>
+ 
     <menu name="ControlMenu" action="Control">
       <menuitem name="ControlPlayMenu" action="ControlPlay"/>
       <separator name="ControlSep1"/>
