commit 39ecbb7e9cfa2b0a81aba6f1c4d6befeb24b34b7
Author: Christophe Fergeau <teuf@grincheux.(none)>
Date:   Sat Apr 7 00:25:42 2007 +0200

    Properly save rating changes to the iPod

diff --git a/plugins/ipod/rb-ipod-source.c b/plugins/ipod/rb-ipod-source.c
index 92caf86..a49a385 100644
--- a/plugins/ipod/rb-ipod-source.c
+++ b/plugins/ipod/rb-ipod-source.c
@@ -405,6 +405,7 @@ create_ipod_song_from_entry (RhythmDBEntry *entry, const char *mimetype)
 	track->time_played = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_PLAYED);
 	track->time_played = itdb_time_host_to_mac (track->time_played);
 	track->rating = rhythmdb_entry_get_double (entry, RHYTHMDB_PROP_RATING);
+	track->rating *= ITDB_RATING_STEP;
 	track->app_rating = track->rating;
 	track->playcount = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_PLAY_COUNT);
 
@@ -537,7 +538,7 @@ add_ipod_song_to_db (RBiPodSource *source, RhythmDB *db, Itdb_Track *song)
 	if (song->rating != 0) {
 		GValue value = {0, };
 		g_value_init (&value, G_TYPE_DOUBLE);
-		g_value_set_double (&value, song->rating/20.0);
+		g_value_set_double (&value, song->rating/ITDB_RATING_STEP);
 		rhythmdb_entry_set (RHYTHMDB (db), entry,
 					       RHYTHMDB_PROP_RATING,
 					       &value);
@@ -587,6 +588,60 @@ get_db_for_source (RBiPodSource *source)
 	return db;
 }
 
+
+static void
+rb_ipod_source_entry_changed_cb (RhythmDB *db,
+				 RhythmDBEntry *entry,
+				 GSList *changes,
+				 RBiPodSource *source)
+{
+	GSList *t;
+
+	/* Ignore entries which are not iPod entries */
+	RhythmDBEntryType entry_type;
+	RhythmDBEntryType ipod_entry_type;
+
+	entry_type = rhythmdb_entry_get_pointer (entry, RHYTHMDB_PROP_TYPE);
+	g_object_get (G_OBJECT (source),
+		      "entry-type", &ipod_entry_type,
+		      NULL);
+	g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE, ipod_entry_type);
+	/* ipod_entry_type can no longer be dereferenced, but its value 
+	 * hasn't been changed, so this comparison is valid
+	 */
+	if (entry_type != ipod_entry_type) {
+		return; 
+	};
+
+
+	/* If the rating was changed, update it on the iPod */
+	for (t = changes; t; t = t->next) {
+		RhythmDBEntryChange *change = t->data;
+		switch (change->prop) {
+		case RHYTHMDB_PROP_RATING: {
+			RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+			Itdb_Track *track;
+			double old_rating;
+			double new_rating;
+
+			old_rating = g_value_get_double (&change->old);
+			new_rating = g_value_get_double (&change->new);
+			if (old_rating != new_rating) {
+				track = g_hash_table_lookup (priv->entry_map, 
+							     entry);
+				track->rating = new_rating * ITDB_RATING_STEP;
+				track->app_rating = track->rating;
+
+				itdb_schedule_save (source);
+			}
+			break;
+		}
+		default:
+			break;
+		}
+	}
+}
+
 static gboolean
 load_ipod_db_idle_cb (RBiPodSource *source)
 {
@@ -605,6 +660,10 @@ load_ipod_db_idle_cb (RBiPodSource *source)
 
 	load_ipod_playlists (source);
 
+	g_signal_connect_object(G_OBJECT(db), "entry-changed", 
+				G_CALLBACK (rb_ipod_source_entry_changed_cb),
+				source, 0);
+
 	g_object_unref (db);
 
 	GDK_THREADS_LEAVE ();
@@ -647,7 +706,6 @@ rb_ipod_load_songs (RBiPodSource *source)
 		}
 		priv->load_idle_id = g_idle_add ((GSourceFunc)load_ipod_db_idle_cb, source);
 	}
-
 	g_object_unref (volume);
 }
 
