[Banshee-List] 2 ways sync with Ratings & Playlist content



Hello,
   I listen a lot music on my Android phone and my music database in on
banshee (ubuntu).

I was interested in setting ratings and add tracks in playlist on my android
and then synchronize with banshee. Unfortunately this is not an existing
feature. Therefore, i have decided to add it on banshee. Below the
modifications i have done. 

If anyone is interested in this feature, let me know.
Christian.

Assumption:
. Rating is always taken from Android device (if you choose to synchronise
ratings). If you have done a modification on a track rating both on banshee
and android, the track rating on external device will be used.
. Rating synchronisation is done based on the synchronisation playlist
chosen by user.
. New Tracks from android playlist are added to banshee playlist. No delete
done.

Tests:
. Done with Android with PlayerPro (with rating system set to  windows media
player) and Playlist backup applications,
. Synchronisation system shall work with other kind of source. To be tested.


Modifications:
src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs:
  1/ Launching Rating synchronisation. Mainly in
sync.Dap.UpdateStatAllTracks(sync_src, sync.Dap.DbId);
  2/ New function dedicated to Import Playlist content to Hard Drive
(InjectPlayList)

src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs:
  1/ New functions to import Ratings from a source. Track list is the source
chosen by user (UpdateStatTrack, UpdateStatAllTracks)

src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs:
  1/ New functions to launch Playlist content import for each library to be
synchronized (LaunchInjectPlayList)
  2/ Launching  LaunchInjectPlayList before Playlist deletion
  3/ Show options to user to import or not

src/Core/Banshee.Core/Banshee.Streaming/StreamRatingTagger.cs:
  1/ Modification of the prefered author for POPM Management to enable
Rating import



src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
After:                sync.Dap.AddAllTracks (to_add);
Added:
                // CHR: Launching Rating import
                if (sync.importRating)
                        sync.Dap.UpdateStatAllTracks(sync_src,
sync.Dap.DbId);
                else
                        Log.Debug ("CHR: User asked No rating import.");
                // End CHR


Add the following function:
        // CHR: Before Puting new playlist on target, we search if target
has already this playlist
        // if yes, we put the additionnal content on HD
        public void InjectPlayList()
        {


            IList<AbstractPlaylistSource> playlists = GetSyncPlaylists ();

                var src = SyncSource;
                int? syncID = -1;
                if (src is PlaylistSource) {
                     syncID = (src as PlaylistSource).DbId;
                } else if (src is SmartPlaylistSource) {
                    syncID=(src as SmartPlaylistSource).DbId;
                }

            foreach (AbstractPlaylistSource from in playlists) {
                // Synchronize only Playlist and not SmartPlayList
                if ((from is SmartPlaylistSource ) || (from.DbId == syncID))
{
                        Log.Debug ("CHR: Skip '" +from.Name+"' playlist. ");
                    continue;
                }

                String clauseWhere = String.Format (@"WHERE PrimarySourceID
= {3}
AND MetadataHash IN (select metadatahash from CoreTracks b,
CorePlayListEntries e, CorePlayLists f where b.TrackID = e.TrackID and
e.PlayListID = f.PlayListID and f.Name= '{1}' and f.PrimarySourceID= {2} )
AND MetadataHash  NOT IN (select metadatahash from CoreTracks b,
CorePlayListEntries e where b.TrackID = e.TrackID and e.PlayListID = {0} )",
                    from.DbId, from.Name, sync.Dap.DbId,
from.PrimarySourceId);

                long nbinject=  ServiceManager.DbConnection.Query<long>
(@"SELECT count(TrackID) FROM CoreTracks "+ clauseWhere);

                if ((nbinject > 0) && (from.CanDeleteTracks))
                {
                        Log.InformationFormat ("CHR: Add '" + nbinject + "'
track(s) in playlist '"+from.Name+"'");
                        String Sql = String.Format (
                               @"INSERT INTO CorePlaylistEntries
(PlaylistID, TrackID)
                                    SELECT {0}, TrackID FROM CoreTracks ",
from.DbId );

                        ServiceManager.DbConnection.Execute (Sql +
clauseWhere);
                        // from.UpdateCounts();
                        from.Reload ();
                        // InvalidateCaches ();

                }
                else
                        Log.Debug ("CHR: No modification for playlist
'"+from.Name+"'");
               Log.Debug ("CHR: Synchro PlayList ending ");

                // Fin CHR


            }
        }


In src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
Add:
       // CHR: Copie le rating depuis une source feed vers une playlist. La
copie de la playlist dans etre presente dans le feed
        public void UpdateStatAllTracks (AbstractPlaylistSource target, long
src_DbId )
        {
            Log.DebugFormat ("CHR UpdateStatAllTracks: Deb");
/*
            if (target.PrimarySource != this) {
                Log.WarningFormat ("Cannot delete all tracks from {0} via
primary source {1}", target, this);
                return;
            }
*/

            if ((target.Count < 1) || (src_DbId < 1))
                return;

            var list = CachedList<DatabaseTrackInfo>.CreateFromModel
(target.DatabaseTrackModel);
            ThreadAssist.SpawnFromMain (delegate {
                UpdateStatTrackList (list, src_DbId);
            });

        Log.DebugFormat ("CHR UpdateStatAllTracks: Fin");
        }

Add:
       // CHR
        protected virtual void UpdateStatTrackList
(CachedList<DatabaseTrackInfo> list, long srcID)
        {
            Log.DebugFormat ("CHR UpdateStatAllTracks : debut");

            is_updating = true;
            UpdateTrackJob.Total += (int) list.Count;

            //
            foreach (DatabaseTrackInfo track in list) {
                if (track == null) {
                    UpdateTrackJob.Completed++;
                    continue;
                }

                try {
                    UpdateTrackJob.Status = String.Format ("{0} - {1}",
track.ArtistName, track.TrackTitle);
                    if (!UpdateStatTrack (track, srcID)) {
                    }
                } catch (Exception e) {
                    Log.Exception (e);
                    ErrorSource.AddMessage (e.Message, track.Uri.ToString
());
                }

                UpdateTrackJob.Completed++;

            }

            is_updating = false;

            if (UpdateTrackJob.Total == UpdateTrackJob.Completed) {
                update_track_job.Finish ();
                update_track_job = null;
            }

        }
        protected virtual bool DeleteTrack (DatabaseTrackInfo track)
        {
            if (!track.Uri.IsLocalPath)
                throw new Exception ("Cannot delete a non-local resource: "
+ track.Uri.Scheme);

            try {
                Banshee.IO.Utilities.DeleteFileTrimmingParentDirectories
(track.Uri);
            } catch (System.IO.FileNotFoundException) {
            } catch (System.IO.DirectoryNotFoundException) {
            }

            return true;
        }

Add:
        protected virtual bool UpdateStatTrack (DatabaseTrackInfo track,
long srcID)
        {
            Log.DebugFormat ("CHR UpdateStatTrack : debut "+
track.Uri.Scheme+" SrcFeedId:'"+srcID+"'" );
            int ratingfound=0;

            if (!track.Uri.IsLocalPath)
                throw new Exception ("Cannot update a non-local resource: "
+ track.Uri.Scheme);

            try {
                     Log.DebugFormat ("CHR UpdateStatTrack : Need to find "+
track.MetadataHash );

                     ratingfound =  ServiceManager.DbConnection.Query<int>
("SELECT rating FROM CoreTracks WHERE MetadataHash = ? AND PrimarySourceId =
?", track.MetadataHash, srcID);


                    if (track.Rating != ratingfound)
                    {
                            track.Rating = ratingfound;
                            track.Save ();
                    }

            } catch (System.IO.FileNotFoundException) {
            } catch (System.IO.DirectoryNotFoundException) {
            }

            Log.DebugFormat ("CHR UpdateStatTrack : fin "+ track.Uri.Scheme
);
            return true;
        }

In src/Dap/Banshee.Dap/Banshee.Dap/DapSync.cs:
Add:
// CHR
        private SchemaEntry<bool> import_Rating;
        private SchemaPreference<bool> import_Rating_pref;
        private SchemaEntry<bool> import_PlaylistContent;
        private SchemaPreference<bool> import_PlaylistContent_pref;


        public bool importPlaylistContent {
            get { return import_PlaylistContent.Get (); }
        }

        public bool importRating {
            get { return import_Rating.Get (); }
        }

In BuildPreferences(), add:
            import_Rating = dap.CreateSchema<bool> (conf_ns,
"import_Rating", true,
                Catalog.GetString ("Import Ratings during synchronisation"),
                Catalog.GetString ("After Track add/delete on your device,
Import Track ratings from device.")
            );
            import_PlaylistContent = dap.CreateSchema<bool> (conf_ns,
"import_PlaylistContent", true,
                Catalog.GetString ("Import Playlist content"),
                Catalog.GetString ("Add Tracks in playlist added on your
device playlist.")
            );
            import_Rating_pref = sync_prefs.Add (import_Rating);
            import_Rating_pref.ValueChanged += Onimport_RatingChanged;

            import_PlaylistContent_pref = sync_prefs.Add
(import_PlaylistContent);
            import_PlaylistContent_pref.ValueChanged +=
Onimport_PlaylistContentChanged;

Add 
// CHR
        private void Onimport_RatingChanged (Root preference)
        {
                Log.Debug ("CHR: Onimport_RatingChanged, import_Rating='" +
import_Rating + "', import_Rating_pref='" + import_Rating_pref + "',
importRating='" + importRating + "'");
        }

        private void Onimport_PlaylistContentChanged (Root preference)
        {
                Log.Debug ("CHR: Onimport_PlaylistContentChanged,
Onimport_PlaylistContent='"+ import_PlaylistContent +"',
import_PlaylistContent_pref='" + import_PlaylistContent_pref + "',
importPlaylistContent='" + importPlaylistContent + "'");
        }

// Ending CHR

        internal void LaunchInjectPlayList ()
        {
            foreach (DapLibrarySync library_sync in library_syncs) {
                library_sync.InjectPlayList ();
            }

            OnUpdated ();
        }

In RateLimitedSync() , change
            if (sync_playlists) {
                dap.RemovePlaylists ();
            }
with
            if (sync_playlists) {
// Ajout CHR
                if (importPlaylistContent)
                        LaunchInjectPlayList();
                else
                        Log.Debug ("CHR: User asked No playlist content
import.");
// fin CHR

                dap.RemovePlaylists ();
            }

In src/Core/Banshee.Core/Banshee.Streaming/StreamRatingTagger.cs,  change
POPM_known_creator_list with
        private static string[] POPM_known_creator_list = {
            "quodlibet lists sacredchao net",// Quod Libet (their default)
            "Windows Media Player 9 Series",// WMP/Vista
            "no email",// MediaMonkey
            POPM_our_creator_name,// This item must be first
            "mcored gmail com" // iTSfv
        };






--
View this message in context: 
http://banshee-media-player.2283330.n4.nabble.com/2-ways-sync-with-Ratings-Playlist-content-tp4651037.html
Sent from the Banshee Media Player mailing list archive at Nabble.com.


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