[banshee] Metadata: Split WriteRatingsAndPlayCount into two options



commit f2fcfefe796512b0e571932a370bf133dd4546e3
Author: Kevin Anthony <kevin s anthony gmail com>
Date:   Thu Sep 22 19:11:40 2011 +0100

    Metadata: Split WriteRatingsAndPlayCount into two options
    
    The configuration for embedding Ratings and Playcounts
    into files was not separated before. In certain
    situation this is not desirable because you may want
    to make the files change to propagate the Rating to
    other computers, in case you share your media collection
    somehow, but propagating the tracks everytime they
    play is too expensive. Fixes bgo#602159.

 .../Banshee.Streaming/StreamRatingTagger.cs        |  105 ++++++++++++++-----
 .../Banshee.Core/Banshee.Streaming/StreamTagger.cs |    9 +-
 .../DatabaseTrackInfo.cs                           |   12 ++-
 .../Banshee.Library/LibrarySchema.cs               |   11 ++-
 .../Banshee.Metadata/SaveTrackMetadataJob.cs       |    7 +-
 .../Banshee.Metadata/SaveTrackMetadataService.cs   |   28 ++++--
 .../Banshee.Metadata/Tests/TaglibReadWriteTests.cs |    2 +-
 .../Banshee.Preferences/PreferenceService.cs       |    3 +-
 .../Banshee.Dap.MassStorage/MassStorageSource.cs   |    5 +-
 9 files changed, 129 insertions(+), 53 deletions(-)
---
diff --git a/src/Core/Banshee.Core/Banshee.Streaming/StreamRatingTagger.cs b/src/Core/Banshee.Core/Banshee.Streaming/StreamRatingTagger.cs
index 714e4ff..bf39046 100644
--- a/src/Core/Banshee.Core/Banshee.Streaming/StreamRatingTagger.cs
+++ b/src/Core/Banshee.Core/Banshee.Streaming/StreamRatingTagger.cs
@@ -34,7 +34,7 @@ using Banshee.Collection;
 
 namespace Banshee.Streaming
 {
-    internal static class ID3v2RatingTagger
+    internal static class ID3v2Tagger
     {
         // What we call ourselves in POPM tags.
         private static string POPM_our_creator_name = "Banshee";
@@ -115,8 +115,7 @@ namespace Banshee.Streaming
         // Overwrites all POPM frames with the new rating and playcount.
         // If no *known-compatible* frames are found, a new "Banshee"-authored
         // frame is also created to store this information.
-        public static void StoreRatingAndPlayCount (int rating, int playcount,
-                                                    TagLib.File to_file)
+        public static void StoreRating (int rating, TagLib.File to_file)
         {
             TagLib.Id3v2.Tag id3v2tag = GetTag (to_file);
             if (id3v2tag == null) {
@@ -132,10 +131,8 @@ namespace Banshee.Streaming
                 }
 
                 popm.Rating = BansheeToPopm (rating);
-                popm.PlayCount = (ulong)playcount;
-                Hyena.Log.DebugFormat ("Exporting ID3v2 Rating={0}({1}) and Playcount={2}({3}) to File \"{4}\" as Creator \"{5}\"",
+                Hyena.Log.DebugFormat ("Exporting ID3v2 Rating={0}({1}) to File \"{2}\" as Creator \"{3}\"",
                                        rating, popm.Rating,
-                                       playcount, popm.PlayCount,
                                        to_file.Name, popm.User);
             }
 
@@ -145,13 +142,43 @@ namespace Banshee.Streaming
                                                                                             POPM_our_creator_name,
                                                                                             true);
                 popm.Rating = BansheeToPopm (rating);
-                popm.PlayCount = (ulong)playcount;
-                Hyena.Log.DebugFormat ("Exporting ID3v2 Rating={0}({1}) and Playcount={2}({3}) to File \"{4}\" as Creator \"{5}\"",
+                Hyena.Log.DebugFormat ("Exporting ID3v2 Rating={0}({1}) to File \"{2}\" as Creator \"{3}\"",
                                        rating, popm.Rating,
-                                       playcount, popm.PlayCount,
                                        to_file.Name, POPM_our_creator_name);
             }
         }
+        public static void StorePlayCount (int playcount, TagLib.File to_file)
+        {
+            TagLib.Id3v2.Tag id3v2tag = GetTag (to_file);
+            if (id3v2tag == null) {
+                return;
+            }
+
+            bool known_frames_found = false;
+            foreach (TagLib.Id3v2.PopularimeterFrame popm in
+                     id3v2tag.GetFrames<TagLib.Id3v2.PopularimeterFrame> ()) {
+                if (System.Array.IndexOf (POPM_known_creator_list, popm.User) >= 0) {
+                    // Found a known-good POPM frame, don't need to create a "Banshee" frame.
+                    known_frames_found = true;
+                }
+
+                popm.PlayCount = (ulong)playcount;
+                Hyena.Log.DebugFormat ("Exporting ID3v2 Playcount={0}({1}) to File \"{2}\" as Creator \"{3}\"",
+                                       playcount, popm.PlayCount,
+                                       to_file.Name, popm.User);
+            }
+
+            if (!known_frames_found) {
+                // No known-good frames found, create a new POPM frame (with creator string "Banshee")
+                TagLib.Id3v2.PopularimeterFrame popm = TagLib.Id3v2.PopularimeterFrame.Get (id3v2tag,
+                                                                                            POPM_our_creator_name,
+                                                                                            true);
+                popm.PlayCount = (ulong)playcount;
+                Hyena.Log.DebugFormat ("Exporting ID3v2 Playcount={0}({1}) to File \"{2}\" as Creator \"{3}\"",
+                                       playcount, popm.PlayCount,
+                                       to_file.Name, popm.User);
+            }
+        }
 
         // Scans the file for *known-compatible* POPM frames, with priority given to
         // frames at the top of the known creator list.
@@ -183,7 +210,7 @@ namespace Banshee.Streaming
     // Applicable for Vorbis, Speex, and many (most?) FLAC files
     // Follows the naming standard established by the Quod Libet team
     // See: http://code.google.com/p/quodlibet/wiki/Specs_VorbisComments
-    internal static class OggRatingTagger
+    internal static class OggTagger
     {
         // What we call ourselves in rating/playcount tags.
         private static string ogg_our_creator_name = "BANSHEE";
@@ -308,8 +335,7 @@ namespace Banshee.Streaming
 
         // Scans the file for ogg rating/playcount tags as defined by the Quod Libet standard
         // All applicable tags are overwritten with the new values, regardless of tag author
-        public static void StoreRatingAndPlayCount (int rating, int playcount,
-                                                    TagLib.File to_file)
+        public static void StoreRating (int rating, TagLib.File to_file)
         {
             TagLib.Ogg.XiphComment xiphtag = GetTag (to_file);
             if (xiphtag == null) {
@@ -317,23 +343,17 @@ namespace Banshee.Streaming
             }
 
             ArrayList rating_fieldnames = new ArrayList ();
-            ArrayList playcount_fieldnames = new ArrayList ();
 
-            // Collect list of rating and playcount tags to be updated:
+            // Collect list of rating tags to be updated:
             foreach (string fieldname in xiphtag) {
                 if (fieldname.ToUpper ().StartsWith (rating_prefix)) {
                     rating_fieldnames.Add (fieldname);
-                } else if (fieldname.ToUpper ().StartsWith (playcount_prefix)) {
-                    playcount_fieldnames.Add (fieldname);
                 }
             }
-            // Add "BANSHEE" tags if no rating/playcount tags were found:
+            // Add "BANSHEE" tags if no rating tags were found:
             if (rating_fieldnames.Count == 0) {
                 rating_fieldnames.Add (rating_prefix+ogg_our_creator_name);
             }
-            if (playcount_fieldnames.Count == 0) {
-                playcount_fieldnames.Add (playcount_prefix+ogg_our_creator_name);
-            }
 
             string ogg_rating = BansheeToOgg (rating);
             foreach (string ratingname in rating_fieldnames) {
@@ -343,6 +363,28 @@ namespace Banshee.Streaming
                                        to_file.Name,
                                        ratingname.Substring (rating_prefix.Length));
             }
+        }
+
+        public static void StorePlayCount (int playcount, TagLib.File to_file)
+        {
+            TagLib.Ogg.XiphComment xiphtag = GetTag (to_file);
+            if (xiphtag == null) {
+                return;
+            }
+
+            ArrayList playcount_fieldnames = new ArrayList ();
+
+            // Collect list of  playcount tags to be updated:
+            foreach (string fieldname in xiphtag) {
+                if (fieldname.ToUpper ().StartsWith (playcount_prefix)) {
+                    playcount_fieldnames.Add (fieldname);
+                }
+            }
+            // Add "BANSHEE" tags if no playcount tags were found:
+            if (playcount_fieldnames.Count == 0) {
+                playcount_fieldnames.Add (playcount_prefix+ogg_our_creator_name);
+            }
+
             string ogg_playcount = playcount.ToString ();
             foreach (string playcountname in playcount_fieldnames) {
                 xiphtag.SetField (playcountname, ogg_playcount);
@@ -360,25 +402,32 @@ namespace Banshee.Streaming
                                                   ref int rating, ref int playcount)
         {
             if ((from_file.Tag.TagTypes & TagLib.TagTypes.Id3v2) != 0) {
-                ID3v2RatingTagger.GetRatingAndPlayCount (from_file,
+                ID3v2Tagger.GetRatingAndPlayCount (from_file,
                                                          ref rating, ref playcount);
             }
             if ((from_file.Tag.TagTypes & TagLib.TagTypes.Xiph) != 0) {
-                OggRatingTagger.GetRatingAndPlayCount (from_file,
+                OggTagger.GetRatingAndPlayCount (from_file,
                                                        ref rating, ref playcount);
             }
         }
 
-        public static void StoreRatingAndPlayCount (int rating, int playcount,
-                                                    TagLib.File to_file)
+        public static void StoreRating (int rating, TagLib.File to_file)
+        {
+            if ((to_file.Tag.TagTypes & TagLib.TagTypes.Id3v2) != 0) {
+                ID3v2Tagger.StoreRating (rating, to_file);
+            }
+            if ((to_file.Tag.TagTypes & TagLib.TagTypes.Xiph) != 0) {
+                OggTagger.StoreRating (rating, to_file);
+            }
+        }
+
+        public static void StorePlayCount (int playcount, TagLib.File to_file)
         {
             if ((to_file.Tag.TagTypes & TagLib.TagTypes.Id3v2) != 0) {
-                ID3v2RatingTagger.StoreRatingAndPlayCount (rating, playcount,
-                                                           to_file);
+                ID3v2Tagger.StorePlayCount (playcount, to_file);
             }
             if ((to_file.Tag.TagTypes & TagLib.TagTypes.Xiph) != 0) {
-                OggRatingTagger.StoreRatingAndPlayCount (rating, playcount,
-                                                         to_file);
+                OggTagger.StorePlayCount (playcount, to_file);
             }
         }
     }
diff --git a/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs b/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
index f74b0b7..493b6a5 100644
--- a/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
+++ b/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
@@ -282,7 +282,7 @@ namespace Banshee.Streaming
             } catch {}
         }
 
-        public static bool SaveToFile (TrackInfo track, bool write_metadata, bool write_rating_and_play_count)
+        public static bool SaveToFile (TrackInfo track, bool write_metadata, bool write_rating, bool write_play_count)
         {
             // Note: this should be kept in sync with the metadata read in StreamTagger.cs
             TagLib.File file = ProcessUri (track.Uri);
@@ -321,9 +321,12 @@ namespace Banshee.Streaming
                 SaveIsCompilation (file, track.IsCompilation);
             }
 
-            if (write_rating_and_play_count) {
+            if (write_rating) {
                 // FIXME move StreamRatingTagger to taglib#
-                StreamRatingTagger.StoreRatingAndPlayCount (track.Rating, track.PlayCount, file);
+                StreamRatingTagger.StoreRating (track.Rating, file);
+            }
+            if (write_play_count){
+                StreamRatingTagger.StorePlayCount (track.PlayCount,file);
             }
 
             file.Save ();
diff --git a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
index 37686a9..231e8e5 100644
--- a/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs
@@ -89,15 +89,19 @@ namespace Banshee.Collection.Database
                 BansheeQuery.RatingField
             };
             Action<Root> handler = delegate {
-                if (SaveTrackMetadataService.WriteRatingsAndPlayCountsEnabled.Value) {
-                    transient_fields.Remove (BansheeQuery.PlayCountField);
+                if (SaveTrackMetadataService.WriteRatingsEnabled.Value) {
                     transient_fields.Remove (BansheeQuery.RatingField);
                 } else {
-                    transient_fields.Add (BansheeQuery.PlayCountField);
                     transient_fields.Add (BansheeQuery.RatingField);
                 }
+                if (SaveTrackMetadataService.WritePlayCountsEnabled.Value) {
+                    transient_fields.Remove (BansheeQuery.PlayCountField);
+                } else {
+                    transient_fields.Add (BansheeQuery.PlayCountField);
+                }
             };
-            SaveTrackMetadataService.WriteRatingsAndPlayCountsEnabled.ValueChanged += handler;
+            SaveTrackMetadataService.WritePlayCountsEnabled.ValueChanged += handler;
+            SaveTrackMetadataService.WriteRatingsEnabled.ValueChanged += handler;
             handler (null);
         }
 
diff --git a/src/Core/Banshee.Services/Banshee.Library/LibrarySchema.cs b/src/Core/Banshee.Services/Banshee.Library/LibrarySchema.cs
index 687ce85..55909c7 100644
--- a/src/Core/Banshee.Services/Banshee.Library/LibrarySchema.cs
+++ b/src/Core/Banshee.Services/Banshee.Library/LibrarySchema.cs
@@ -79,11 +79,18 @@ namespace Banshee.Configuration.Schema
             "If enabled, metadata (tags) will be written back to audio files when using the track metadata editor."
         );
 
-        public static readonly SchemaEntry<bool> WriteRatingsAndPlayCounts = new SchemaEntry<bool>(
+        public static readonly SchemaEntry<bool> WriteRatings = new SchemaEntry<bool>(
             "library", "write_rating",
             false,
             "Store ratings within supported files",
-            "If enabled, rating and playcount metadata will be written back to audio files."
+            "If enabled, rating metadata will be written back to audio files."
+        );
+
+        public static readonly SchemaEntry<bool> WritePlayCounts = new SchemaEntry<bool>(
+            "library", "write_count",
+            false,
+            "Store playcount within supported files",
+            "If enabled, playcount metadata will be written back to audio files."
         );
 
         public static readonly SchemaEntry<bool> SortByAlbumYear = new SchemaEntry<bool>(
diff --git a/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs b/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs
index fefe51d..029b800 100644
--- a/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs
+++ b/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataJob.cs
@@ -72,7 +72,8 @@ namespace Banshee.Metadata
         }
 
         public bool WriteMetadataEnabled { get; set; }
-        public bool WriteRatingsAndPlayCountsEnabled { get; set; }
+        public bool WriteRatingsEnabled { get; set; }
+        public bool WritePlayCountsEnabled { get; set; }
         public bool RenameEnabled { get; set; }
 
         private HyenaSqliteCommand update_synced_at;
@@ -90,9 +91,9 @@ namespace Banshee.Metadata
             bool wrote = false;
             bool renamed = false;
             try {
-                if (WriteMetadataEnabled || WriteRatingsAndPlayCountsEnabled) {
+                if (WriteMetadataEnabled || WriteRatingsEnabled || WritePlayCountsEnabled) {
                     Hyena.Log.DebugFormat ("Saving metadata for {0}", track);
-                    wrote = StreamTagger.SaveToFile (track, WriteMetadataEnabled, WriteRatingsAndPlayCountsEnabled);
+                    wrote = StreamTagger.SaveToFile (track, WriteMetadataEnabled, WriteRatingsEnabled, WritePlayCountsEnabled);
                 }
 
                 // Rename tracks only from the Music Library
diff --git a/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataService.cs b/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataService.cs
index 5604073..5b32ffa 100644
--- a/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataService.cs
+++ b/src/Core/Banshee.Services/Banshee.Metadata/SaveTrackMetadataService.cs
@@ -50,10 +50,17 @@ namespace Banshee.Metadata
                 Catalog.GetString ("Save tags and other metadata inside supported media files")
         );
 
-        public static SchemaPreference<bool> WriteRatingsAndPlayCountsEnabled = new SchemaPreference<bool> (
-                LibrarySchema.WriteRatingsAndPlayCounts,
-                Catalog.GetString ("Write _ratings and play counts to files"),
-                Catalog.GetString ("Enable this option to save rating and playcount metadata inside supported audio files"));
+        public static SchemaPreference<bool> WriteRatingsEnabled = new SchemaPreference<bool> (
+                LibrarySchema.WriteRatings,
+                Catalog.GetString ("Write _ratings to files"),
+                Catalog.GetString ("Enable this option to save rating metadata inside supported audio files")
+        );
+
+        public static SchemaPreference<bool> WritePlayCountsEnabled = new SchemaPreference<bool> (
+                LibrarySchema.WritePlayCounts,
+                Catalog.GetString ("Write play counts to files"),
+                Catalog.GetString ("Enable this option to save playcount metadata inside supported audio files")
+        );
 
         public static SchemaPreference<bool> RenameEnabled = new SchemaPreference<bool> (
                 LibrarySchema.MoveOnInfoSave,
@@ -73,7 +80,8 @@ namespace Banshee.Metadata
         {
             Banshee.ServiceStack.Application.RunTimeout (10000, delegate {
                 WriteMetadataEnabled.ValueChanged += OnEnabledChanged;
-                WriteRatingsAndPlayCountsEnabled.ValueChanged += OnEnabledChanged;
+                WriteRatingsEnabled.ValueChanged += OnEnabledChanged;
+                WritePlayCountsEnabled.ValueChanged += OnEnabledChanged;
                 RenameEnabled.ValueChanged += OnEnabledChanged;
 
                 foreach (var source in ServiceManager.SourceManager.Sources) {
@@ -127,18 +135,20 @@ namespace Banshee.Metadata
 
         private void Save ()
         {
-            if (!(WriteMetadataEnabled.Value || WriteRatingsAndPlayCountsEnabled.Value || RenameEnabled.Value))
+            if (!(WriteMetadataEnabled.Value || WriteRatingsEnabled.Value || WritePlayCountsEnabled.Value || RenameEnabled.Value))
                 return;
 
             lock (sync) {
                 if (job != null) {
                     job.WriteMetadataEnabled = WriteMetadataEnabled.Value;
-                    job.WriteRatingsAndPlayCountsEnabled = WriteRatingsAndPlayCountsEnabled.Value;
+                    job.WriteRatingsEnabled = WriteRatingsEnabled.Value;
+                    job.WritePlayCountsEnabled = WritePlayCountsEnabled.Value;
                     job.RenameEnabled = RenameEnabled.Value;
                 } else {
                     var new_job = new SaveTrackMetadataJob () {
                         WriteMetadataEnabled = WriteMetadataEnabled.Value,
-                        WriteRatingsAndPlayCountsEnabled = WriteRatingsAndPlayCountsEnabled.Value,
+                        WriteRatingsEnabled = WriteRatingsEnabled.Value,
+                        WritePlayCountsEnabled = WritePlayCountsEnabled.Value,
                         RenameEnabled = RenameEnabled.Value
                     };
                     new_job.Finished += delegate { lock (sync) { job = null; } };
@@ -155,7 +165,7 @@ namespace Banshee.Metadata
 
         private void OnEnabledChanged (Root pref)
         {
-            if (WriteMetadataEnabled.Value || WriteRatingsAndPlayCountsEnabled.Value || RenameEnabled.Value) {
+            if (WriteMetadataEnabled.Value || WriteRatingsEnabled.Value || WritePlayCountsEnabled.Value || RenameEnabled.Value) {
                 Save ();
             } else {
                 if (job != null) {
diff --git a/src/Core/Banshee.Services/Banshee.Metadata/Tests/TaglibReadWriteTests.cs b/src/Core/Banshee.Services/Banshee.Metadata/Tests/TaglibReadWriteTests.cs
index 6e12520..ee2b306 100644
--- a/src/Core/Banshee.Services/Banshee.Metadata/Tests/TaglibReadWriteTests.cs
+++ b/src/Core/Banshee.Services/Banshee.Metadata/Tests/TaglibReadWriteTests.cs
@@ -185,7 +185,7 @@ namespace Banshee.Metadata
             change (track);
 
             // Save changes
-            bool saved = StreamTagger.SaveToFile (track, true, true);
+            bool saved = StreamTagger.SaveToFile (track, true, true, true);
             Assert.IsTrue (saved);
 
             // Read changes
diff --git a/src/Core/Banshee.Services/Banshee.Preferences/PreferenceService.cs b/src/Core/Banshee.Services/Banshee.Preferences/PreferenceService.cs
index 8ed6391..8d61651 100644
--- a/src/Core/Banshee.Services/Banshee.Preferences/PreferenceService.cs
+++ b/src/Core/Banshee.Services/Banshee.Preferences/PreferenceService.cs
@@ -58,7 +58,8 @@ namespace Banshee.Preferences
                 Catalog.GetString ("Co_py files to media folders when importing")));
 
             policies.Add (Banshee.Metadata.SaveTrackMetadataService.WriteMetadataEnabled);
-            policies.Add (Banshee.Metadata.SaveTrackMetadataService.WriteRatingsAndPlayCountsEnabled);
+            policies.Add (Banshee.Metadata.SaveTrackMetadataService.WriteRatingsEnabled);
+            policies.Add (Banshee.Metadata.SaveTrackMetadataService.WritePlayCountsEnabled);
             policies.Add (Banshee.Metadata.SaveTrackMetadataService.RenameEnabled);
 
             // Misc section
diff --git a/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs b/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
index 880dbf1..1dc3324 100644
--- a/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
+++ b/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
@@ -515,8 +515,9 @@ namespace Banshee.Dap.MassStorage
                 if (track.LastSyncedStamp >= Hyena.DateTimeUtil.ToDateTime (track.FileModifiedStamp)) {
                     Log.DebugFormat ("Copying Metadata to File Since Sync time >= Updated Time");
                     bool write_metadata = Metadata.SaveTrackMetadataService.WriteMetadataEnabled.Value;
-                    bool write_ratings_and_playcounts = Metadata.SaveTrackMetadataService.WriteRatingsAndPlayCountsEnabled.Value;
-                    Banshee.Streaming.StreamTagger.SaveToFile (copied_track, write_metadata, write_ratings_and_playcounts);
+                    bool write_ratings = Metadata.SaveTrackMetadataService.WriteRatingsEnabled.Value;
+                    bool write_playcounts = Metadata.SaveTrackMetadataService.WritePlayCountsEnabled.Value;
+                    Banshee.Streaming.StreamTagger.SaveToFile (copied_track, write_metadata, write_ratings, write_playcounts);
                 }
 
                 copied_track.Save (false);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]