diff --git a/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs b/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
index 7c3bf20..a655910 100644
--- a/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
+++ b/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
@@ -56,7 +56,7 @@ namespace Banshee.Database
         // NOTE: Whenever there is a change in ANY of the database schema,
         //       this version MUST be incremented and a migration method
         //       MUST be supplied to match the new version number
-        protected const int CURRENT_VERSION = 33;
+        protected const int CURRENT_VERSION = 34;
         protected const int CURRENT_METADATA_VERSION = 6;
         
 #region Migration Driver
@@ -778,6 +778,22 @@ namespace Banshee.Database
 
 #endregion
 
+#region Version 34
+
+        [DatabaseVersion (34)]
+        private bool Migrate_34 ()
+        {
+            try {
+                CreateTableLastSyncedRatings ();
+            } catch (Exception e) {
+                Hyena.Log.Exception (e);
+            }
+            return true;
+        }
+        
+#endregion
+        
+
 #pragma warning restore 0169
         
 #region Fresh database setup
@@ -984,6 +1000,22 @@ namespace Banshee.Database
             // This index slows down queries were we shove data into the CoreCache.
             // Since we do that frequently, not using it.
             //Execute("CREATE INDEX CoreCacheModelId      ON CoreCache(ModelID)");
+
+            try {
+                CreateTableLastSyncedRatings ();
+            } catch { }
+        }
+
+        private void CreateTableLastSyncedRatings () {
+            // if the LastModifiedTime field in the iPod gave us the real date on which the rating was modified, we wouldn't need this table
+            Execute(@"
+                CREATE TABLE LastSyncedRatings (
+                  DapID               TEXT,
+                  MetadataHash        TEXT,
+                  Rating              INTEGER NOT NULL,
+                  PRIMARY KEY (DapID, MetadataHash)
+                )
+            ");
         }
         
 #endregion
diff --git a/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs b/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
index 11ff809..3bb4f52 100644
--- a/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
+++ b/src/Core/Banshee.Services/Banshee.Playlist/AbstractPlaylistSource.cs
@@ -212,5 +212,56 @@ namespace Banshee.Playlist
 
         protected abstract void Create ();
         protected abstract void Update ();
+
+        protected void UpdateTrackInParent (DatabaseTrackInfo track)
+        {
+            ServiceManager.DbConnection.Execute (new HyenaSqliteCommand (
+                "UPDATE CoreTracks SET Rating = ? WHERE MetadataHash = ? AND PrimarySourceId = ?",
+                track.Rating,
+                track.MetadataHash,
+                primary_source_id
+            ));
+            OnTracksChanged (BansheeQuery.RatingField);
+        }
+
+        public virtual List<DatabaseTrackInfo> UpdateTracks (CachedList<DatabaseTrackInfo> dest, PrimarySource dap)
+        {
+            List<DatabaseTrackInfo> to_update_externally = new List<DatabaseTrackInfo> ();
+            foreach (DatabaseTrackInfo track in dest) {
+                int local_rating =
+                    ServiceManager.DbConnection.Query<int> ("SELECT Rating FROM CoreTracks WHERE MetadataHash = ? AND PrimarySourceId = ?",
+                                                            track.MetadataHash, primary_source_id);
+                if (local_rating == track.Rating) {
+                    continue;
+                }
+                
+                if (track.Rating > 0 && local_rating == 0) {
+                    UpdateTrackInParent (track);
+                } else if (local_rating > 0 && track.Rating == 0) {
+                    track.Rating = local_rating;
+                    track.Save ();
+                    to_update_externally.Add (track);
+                } else {
+                    int last_rating_synced =
+                        ServiceManager.DbConnection.Query<int> ("SELECT Rating FROM LastSyncedRatings WHERE MetadataHash = ? AND DapId = ?",
+                                                                track.MetadataHash, dap.UniqueId);
+                    if (track.Rating == last_rating_synced) {
+                        track.Rating = local_rating;
+                        track.Save ();
+                        to_update_externally.Add (track);
+                    } else if (local_rating == last_rating_synced) {
+                        UpdateTrackInParent (track);
+                    } else {
+                        string uri = ServiceManager.DbConnection.Query<string> ("SELECT Uri FROM CoreTracks WHERE MetadataHash = ? AND PrimarySourceId = ?",
+                                                                                track.MetadataHash, primary_source_id);
+                        dap.ErrorSource.AddMessage (Catalog.GetString ("The track's rating was set differently on the device and on Banshee"), uri);
+                    }
+                }
+            }
+            
+
+            return to_update_externally;
+        }
+
     }
 }
diff --git a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
index f19049f..241e3d0 100644
--- a/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
+++ b/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
@@ -545,6 +545,38 @@ namespace Banshee.Sources
             throw new Exception ("PrimarySource DeleteTrack method not implemented");
         }
 
+        protected virtual bool UpdateTrack (DatabaseTrackInfo track)
+        {
+            throw new Exception ("PrimarySource UpdateTrack method not implemented");
+        }
+
+        protected void UpdateTrackRatingRecord (DatabaseTrackInfo track, bool commit)
+        {
+            if (commit)
+                UpdateTrack (track);
+            UpdateTrackRatingRecord (track);
+        }
+
+        protected virtual void UpdateTrackRatingRecord (DatabaseTrackInfo track)
+        {
+            throw new Exception ("PrimarySource UpdateTrack method not implemented");
+        }
+
+        public void UpdateTracks (SmartPlaylistSource main_source, SmartPlaylistSource to_update)
+        {
+            DatabaseTrackListModel model = (to_update as ITrackModelSource).TrackModel as DatabaseTrackListModel;
+            CachedList<DatabaseTrackInfo> dest_cached_list = CachedList<DatabaseTrackInfo>.CreateFromModel (model);
+            List<DatabaseTrackInfo> tracks = main_source.UpdateTracks (dest_cached_list, this);
+            foreach (var track in tracks) {
+                UpdateTrackRatingRecord (track, true);
+            }
+            foreach (var track in dest_cached_list) {
+                if (!tracks.Contains (track)) {
+                    UpdateTrackRatingRecord (track);
+                }
+            }
+        }
+
         public override bool AcceptsInputFromSource (Source source)
         {
             return base.AcceptsInputFromSource (source) && source.Parent != this
diff --git a/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs b/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs
index 797c053..fb9bf91 100644
--- a/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs
+++ b/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs
@@ -417,6 +417,7 @@ namespace Banshee.Dap.Ipod
         
         private Queue<IpodTrackInfo> tracks_to_add = new Queue<IpodTrackInfo> ();
         private Queue<IpodTrackInfo> tracks_to_remove = new Queue<IpodTrackInfo> ();
+        private Queue<IpodTrackInfo> tracks_to_update = new Queue<IpodTrackInfo> ();
         
         private uint sync_timeout_id = 0;
         private object sync_timeout_mutex = new object ();
@@ -442,6 +443,7 @@ namespace Banshee.Dap.Ipod
         protected override bool DeleteTrack (DatabaseTrackInfo track)
         {
             lock (sync_mutex) {
+                DeleteTrackRatingRecord (track);
                 if (!tracks_map.ContainsKey (track.TrackId)) {
                     return true;
                 }
@@ -454,6 +456,23 @@ namespace Banshee.Dap.Ipod
                 return true;
             }
         }
+
+        protected override bool UpdateTrack (DatabaseTrackInfo track)
+        {
+            lock (sync_mutex) {
+                if (!tracks_map.ContainsKey (track.TrackId)) {
+                    return false;
+                }
+                
+                IpodTrackInfo ipod_track = tracks_map[track.TrackId];
+                if (ipod_track != null) {
+                    tracks_to_update.Enqueue (ipod_track);
+                    ipod_track.Rating = track.Rating;
+                }
+                
+                return true;
+            }
+        }
         
         protected override void AddTrackToDevice (DatabaseTrackInfo track, SafeUri fromUri)
         {
@@ -466,6 +485,7 @@ namespace Banshee.Dap.Ipod
                 ipod_track.Uri = fromUri;
                 ipod_track.PrimarySource = this;
                 ipod_track.Save (false);
+                UpdateTrackRatingRecord (track);
             
                 tracks_to_add.Enqueue (ipod_track);
             }
@@ -567,7 +587,14 @@ namespace Banshee.Dap.Ipod
                 }
             }
 
-            // TODO sync updated metadata to changed tracks
+            // TODO sync all updated metadata to changed tracks
+            while (tracks_to_update.Count > 0) {
+                IpodTrackInfo track = null;
+                lock (sync_mutex) {
+                    track = tracks_to_update.Dequeue ();
+                }
+                track.CommitToIpod (ipod_device);
+            }
             
             while (tracks_to_remove.Count > 0) {
                 IpodTrackInfo track = null;
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
index a3ab143..a2146d4 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
@@ -53,7 +53,7 @@ namespace Banshee.Dap
         private SchemaEntry<bool> enabled, sync_entire_library;
         private SchemaEntry<string[]> playlist_ids;
         private SchemaPreference<bool> enabled_pref;
-        private SmartPlaylistSource sync_src, to_add, to_remove;
+        private SmartPlaylistSource sync_src, to_add, to_remove, to_update;
         private Section library_prefs_section;
         
         #region Public Properties
@@ -112,6 +112,9 @@ namespace Banshee.Dap
             if (to_remove != null)
                 to_remove.Unmap ();
 
+            if (to_update != null)
+                to_update.Unmap ();
+
             if (sync_src != null)
                 sync_src.Unmap ();
         }
@@ -154,17 +157,23 @@ namespace Banshee.Dap
                 "MetadataHash NOT IN (SELECT MetadataHash FROM CoreTracks WHERE PrimarySourceId = {0})", sync.Dap.DbId
             ));
 
+            var rel_condition = @"MetadataHash {0} IN (SELECT MetadataHash FROM CoreTracks, CoreSmartPlaylistEntries 
+                                  WHERE CoreSmartPlaylistEntries.SmartPlaylistID = {1}
+                                    AND CoreTracks.TrackID = CoreSmartPlaylistEntries.TrackID)";
+
             // Any items on the device that aren't in the sync lists need to be removed
             to_remove = new SmartPlaylistSource ("to_remove", sync.Dap);
             to_remove.IsTemporary = true;
             to_remove.Save ();
             to_remove.AddCondition (library.AttributesCondition);
-            to_remove.AddCondition (String.Format (
-                @"MetadataHash NOT IN (SELECT MetadataHash FROM CoreTracks, CoreSmartPlaylistEntries 
-                    WHERE CoreSmartPlaylistEntries.SmartPlaylistID = {0} AND
-                        CoreTracks.TrackID = CoreSmartPlaylistEntries.TrackID)",
-                sync_src.DbId
-            ));
+            to_remove.AddCondition (String.Format (rel_condition, "NOT", sync_src.DbId));
+
+            // Items that are already on the device and also in our library
+            to_update = new SmartPlaylistSource ("to_update", sync.Dap);
+            to_update.IsTemporary = true;
+            to_update.Save ();
+            to_update.AddCondition (library.AttributesCondition);
+            to_update.AddCondition (String.Format (rel_condition, String.Empty, sync_src.DbId));
         }
         
         internal void CalculateSync ()
@@ -185,17 +194,27 @@ namespace Banshee.Dap
             sync_src.RefreshAndReload ();
             to_add.RefreshAndReload ();
             to_remove.RefreshAndReload ();
+            to_update.RefreshAndReload ();
             enabled_pref.Name = String.Format ("{0} ({1})",
                 enabled.ShortDescription,
-                String.Format (Catalog.GetString ("{0} to add, {1} to remove"), to_add.Count, to_remove.Count));
+                String.Format (Catalog.GetString ("{0} to add, {1} to remove, {2} to update"),
+                               to_add.Count, to_remove.Count, to_update.Count));
         }
 
         public override string ToString ()
         {
-            return String.Format ("Sync calculated for {1}: to add: {0} items, remove {2} items; sync_src.cacheid = {5}, to_add.cacheid = {3}, to_remove.cacheid = {4}", to_add.Count, library.Name, to_remove.Count,
-                                  to_add.DatabaseTrackModel.CacheId, to_remove.DatabaseTrackModel.CacheId, sync_src.DatabaseTrackModel.CacheId);
+            return String.Format (
+                "Sync calculated for {0}: to add: {1} items, remove {2} items, update {3} items;" + 
+                " sync_src.cacheid = {3}, to_add.cacheid = {4}, to_remove.cacheid = {5}, to_update.cacheid = {6}",
+                library.Name, to_add.Count, to_remove.Count, to_update.Count, sync_src.DatabaseTrackModel.CacheId,
+                to_add.DatabaseTrackModel.CacheId, to_remove.DatabaseTrackModel.CacheId, to_update.DatabaseTrackModel.CacheId);
         }
-        
+
+        internal void SyncMetadata ()
+        {
+            sync.Dap.UpdateTracks (sync_src, to_update);
+        }
+
         internal void Sync ()
         {
             if (Enabled) {
@@ -205,6 +224,7 @@ namespace Banshee.Dap
 
                 sync.Dap.DeleteAllTracks (to_remove);
                 sync.Dap.AddAllTracks (to_add);
+                SyncMetadata ();
 
                 if (library.SupportsPlaylists && sync.Dap.SupportsPlaylists) {
                     // Now create the playlists, taking snapshots of smart playlists and saving them
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
index 886787a..bcf817c 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
@@ -276,6 +276,8 @@ namespace Banshee.Dap
                 sync.CalculateSync ();
                 if (sync.AutoSync) {
                     sync.Sync ();
+                } else {
+                    sync.SyncMetadata ();
                 }
             } catch (Exception e) {
                 Log.Exception (e);
@@ -404,6 +406,22 @@ namespace Banshee.Dap
             ErrorSource.AddMessage (Catalog.GetString ("Error converting file"), track.Uri.ToString ());
             IncrementAddedTracks ();
         }
+
+        protected override void UpdateTrackRatingRecord (DatabaseTrackInfo track)
+        {
+            ServiceManager.DbConnection.BeginTransaction ();
+            DeleteTrackRatingRecord (track);
+            if (track.Rating > 0)
+                ServiceManager.DbConnection.Execute ("INSERT INTO LastSyncedRatings(Rating,MetadataHash,DapId) VALUES (?, ?, ?)",
+                                                     track.Rating, track.MetadataHash, UniqueId);
+            ServiceManager.DbConnection.CommitTransaction ();
+        }
+
+        protected void DeleteTrackRatingRecord (DatabaseTrackInfo track)
+        {
+            ServiceManager.DbConnection.Execute ("DELETE FROM LastSyncedRatings WHERE MetadataHash = ? AND DapId = ?",
+                                                 track.MetadataHash, UniqueId);
+        }
         
 #endregion
 
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
index 2293e79..e86e25d 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs
@@ -193,6 +193,14 @@ namespace Banshee.Dap
             }
         }
 
+        public void SyncMetadata ()
+        {
+            foreach (DapLibrarySync lib_sync in library_syncs) {
+                lib_sync.CalculateSync ();
+                lib_sync.SyncMetadata ();
+            }
+        }
+
         private void OnLibraryChanged (Source sender, TrackEventArgs args)
         {
             if (!Enabled) {
@@ -205,6 +213,7 @@ namespace Banshee.Dap
                         Sync ();
                     } else {
                         lib_sync.CalculateSync ();
+                        lib_sync.SyncMetadata ();
                         OnUpdated ();
                     }
                     break;
