Example #1
0
        /// <summary>
        /// Adds one or more tracks to an existing playlist in the catalog.
        /// </summary>

        private void AddTracksToPlaylist()
        {
            PersistentID playlistPID = controller.GetPersistentID(action.PlaylistOID);

            if (!playlistPID.IsEmpty)
            {
                PersistentIDCollection trackPIDs = new PersistentIDCollection();

                ObjectIDCollection trackOIDs = action.TrackOIDs;
                foreach (ObjectID trackOID in trackOIDs)
                {
                    PersistentID trackPID = controller.GetPersistentID(trackOID);
                    if (!trackPID.IsEmpty)
                    {
                        trackPID.TransientID = trackOID.TrackID;
                        trackPIDs.Add(trackPID);
                    }
                }

                if (trackPIDs.Count > 0)
                {
                    catalog.AddTracksToPlaylist(trackPIDs, playlistPID);
                }
            }
        }
Example #2
0
        //========================================================================================
        // Methods
        //========================================================================================

        /// <summary>
        /// Execute the scanner.
        /// </summary>

        public override void Execute()
        {
            if (!NetworkStatus.IsAvailable)
            {
                Logger.WriteLine(base.name, "Information scanner skipped, network not available");
                return;
            }

            Logger.WriteLine(base.name, String.Format(
                                 "Information scanner beginning for {0} tracks on '{1}'/'{2}'",
                                 pids.Count, pids.Artist, pids.Album));

            ScanTracks(pids);

            libraryPlaylist = null;
            pids.Clear();
            pids = null;

            if (base.isActive)
            {
                Logger.WriteLine(base.name, "Information scanner completed");
            }
            else
            {
                Logger.WriteLine(base.name, "Information scanner cancelled");
            }
        }
Example #3
0
        /// <summary>
        /// Export the specified tracks to a given directory using the specified encoder.
        /// </summary>
        /// <param name="tracks"></param>
        /// <param name="encoder"></param>
        /// <param name="location"></param>
        /// <param name="createSubdir"></param>

        public void Export(
            PersistentIDCollection list, Encoder encoder,
            string playlistFormat, string location, bool createSubdirectories)
        {
            lock (sync)
            {
                disabled.Add(Resx.I_ScanDuplicates);
                disabled.Add(Resx.I_ScanFileWatch);
                disabled.Add(Resx.I_ScanMaintenance);
            }

            string pathFormat = null;

            if (createSubdirectories)
            {
                pathFormat = PathHelper.GetPathFormat(ExportScanner.DefaultPathFormat);
            }

            IScanner scanner = new ExportScanner(
                controller, catalog, list, encoder, playlistFormat, location, pathFormat, false);

            scanner.Completed = (Action) delegate
            {
                lock (sync)
                {
                    disabled.Remove(Resx.I_ScanDuplicates);
                    disabled.Remove(Resx.I_ScanFileWatch);
                    disabled.Remove(Resx.I_ScanMaintenance);
                }
            };

            AddScanner(scanner, ExportScannerPriority);
        }
Example #4
0
        /// <summary>
        /// Fix missing and incorrect information for all tracks in the current album.
        /// </summary>

        public void FixInformation(PersistentIDCollection list)
        {
            if (IsScannerAllowed(Resx.I_ScanInformation) && NetworkStatus.IsAvailable)
            {
                var scanner = new InformationScanner(controller, catalog, list);
                AddScanner(scanner, FixInformationScannerPriority);
            }
        }
Example #5
0
        /// <summary>
        /// Retrieves a list of all tracks found in the given playlist.
        /// </summary>
        /// <param name="playlistID">The unique PersistentID of the playlist to examine.</param>
        /// <returns></returns>
        /// <remarks>
        /// iTunes allows users to create multiple playlists with the same name.  So we
        /// must use the PersistentID of the playlist instead of its canonical name.
        /// </remarks>

        public override PersistentIDCollection FindTracksByPlaylist(PersistentID playlistID)
        {
            if (!isReady)
            {
                return(new PersistentIDCollection());
            }

            // find the <plist><dict><key>Playlists</key><array> root node
            var playlistRoot =
                from node in root
                .Element(ns + "dict")
                .Elements(ns + "key")
                where node.Value == "Playlists"
                select node.NextNode;

            // find the parent <array><dict> node of the named playlist
            // <array><dict><key>Name</key><string>Library</string>
            var playlistNodes =
                from node in ((XElement)playlistRoot.Single())
                .Elements(ns + "dict")
                .Elements(ns + "key")
                where node.Value == "Playlist Persistent ID" &&
                ((XElement)node.NextNode).Value == (string)playlistID
                select node.Parent;

            // collect all Track ID values from this playlist
            var trackIDs =
                from node in ((XElement)playlistNodes.Single())
                .Elements(ns + "array")
                .Elements(ns + "dict")
                .Elements(ns + "key")
                where node.Value == "Track ID"
                select node.NextNode;

            // find the <plist><dict><key>Tracks</key><dict> root node
            var trackRoot =
                from node in root
                .Element(ns + "dict")
                .Elements(ns + "key")
                where node.Value == "Tracks"
                select node.NextNode;

            // join tracks on trackID to extract the persistent IDs
            var tracks =
                from node in
                (from node in ((XElement)trackRoot.Single()).Elements(ns + "key")
                 join id in trackIDs on((XElement)node).Value equals((XElement)id).Value
                 select((XElement)node.NextNode)
                ).Elements(ns + "key")
                where ((XElement)node).Value == "Persistent ID"
                select PersistentID.Parse(((XElement)node.NextNode).Value);

            PersistentIDCollection list = new PersistentIDCollection(tracks.ToList <PersistentID>());

            return(list);
        }
Example #6
0
        /// <summary>
        /// Export the specified tracks to a given USB MP3 player, synchronizing the
        /// contents of the specified location.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="location"></param>
        /// <param name="pathFormat"></param>

        public void Export(PersistentIDCollection list, string location, string pathFormat)
        {
            if (disabled.Contains(Resx.I_ScanExport))
            {
                return;
            }

            Encoder mp3Encoder = null;

            foreach (Encoder encoder in controller.Encoders)
            {
                // skip the Null encoder that's automatically added to controller.Encoders
                if (!encoder.IsEmpty)
                {
                    if (encoder.Format.Equals("MP3"))
                    {
                        mp3Encoder = encoder;
                    }
                }
            }

            if (mp3Encoder != null)
            {
                lock (sync)
                {
                    disabled.Add(Resx.I_ScanDuplicates);
                    disabled.Add(Resx.I_ScanFileWatch);
                    disabled.Add(Resx.I_ScanMaintenance);
                }

                IScanner scanner = new ExportScanner(
                    controller, catalog, list,
                    mp3Encoder,
                    PlaylistProviderFactory.NoFormat,
                    location, pathFormat, true);

                scanner.Completed = (Action) delegate
                {
                    Encoder mp3 = mp3Encoder;
                    lock (sync)
                    {
                        disabled.Remove(Resx.I_ScanDuplicates);
                        disabled.Remove(Resx.I_ScanFileWatch);
                        disabled.Remove(Resx.I_ScanMaintenance);
                    }
                    mp3 = null;
                };

                AddScanner(scanner, ExportScannerPriority);
            }

            // [foo] dispose this reference but do not release underlying instance passed to Librarian
            //mp3Encoder.Dispose(false);
        }
Example #7
0
        //========================================================================================
        // Constructor
        //========================================================================================

        /// <summary>
        /// Initialize a new instance of this scanner with the specified iTunes interface.
        /// </summary>
        /// <param name="itunes"></param>
        /// <param name="catalog"></param>

        public InformationScanner(
            Controller controller, ICatalog catalog, PersistentIDCollection pids)
            : base(Resx.I_ScanInformation, controller, catalog)
        {
            this.libraryPlaylist = controller.LibraryPlaylist;

            base.description = Resx.ScanInformation;
            base.tooltip     = String.Format("{0}/{1}", (pids.Album ?? "?"), (pids.Artist ?? "?"));

            this.pids = pids;
        }
Example #8
0
        /// <summary>
        /// Scan all tracks in the given playlist.
        /// </summary>
        /// <param name="list"></param>

        private void ScanTracks(PersistentIDCollection pids)
        {
            // Artwork must be applied to every track in an album.
            // Although we may apply artwork to the CurrentTrack, it will not show up in the
            // iTunes artwork viewer until context is moved to another track and then the user
            // selects or plays that first track again.

            foreach (PersistentID persistentID in pids)
            {
                if (!base.isActive)
                {
                    Logger.WriteLine(base.name, "Artwork scanner cancelled while scanning");
                    break;
                }

                using (Track track = libraryPlaylist.GetTrack(persistentID))
                {
                    if ((track != null) && (track.Kind == TrackKind.File))
                    {
                        string album  = track.Album;
                        string artist = track.Artist;

                        string key = track.MakeKey();
                        if (String.IsNullOrEmpty(track.Artwork))
                        {
                            Logger.WriteLine(base.name, "Fetching album artwork for " + key);

                            try
                            {
                                if (ScannerBase.isLive)
                                {
                                    track.Artwork = GetArtworkPath(artist, album);
                                }
                            }
                            catch (Exception exc)
                            {
                                Logger.WriteLine(base.name,
                                                 String.Format("Error fetching artwork {0}, {1}, {2}",
                                                               artist, track.Name, album), exc);
                            }
                        }
                        else
                        {
                            Logger.WriteLine(base.name, "Album already has artwork " + key);
                        }
                    }
                }

                count++;
                base.ProgressPercentage = (int)((double)count / (double)total * 100.0);
            }
        }
Example #9
0
        /// <summary>
        /// Get a lits of iTunes Tracks given a list of track IDs.
        /// </summary>
        /// <param name="trackIDs"></param>
        /// <returns></returns>

        protected TrackCollection GetTracks(PersistentIDCollection persistentIDs)
        {
            TrackCollection tracks = new TrackCollection();

            foreach (PersistentID persistentID in persistentIDs)
            {
                Track track = controller.LibraryPlaylist.GetTrack(persistentID);
                if (track != null)
                {
                    tracks.Add(track);
                }
            }

            return(tracks);
        }
Example #10
0
        /// <summary>
        /// Scan all tracks in the given playlist.
        /// </summary>
        /// <param name="list"></param>

        private void ScanTracks(PersistentIDCollection pids)
        {
            var tagger = new Tagger();
            int total  = pids.Count;
            int count  = 0;

            foreach (PersistentID persistentID in pids)
            {
                if (!base.isActive)
                {
                    Logger.WriteLine(base.name, "Information scanner cancelled while scanning");
                    break;
                }

                using (Track track = libraryPlaylist.GetTrack(persistentID))
                {
                    if ((track != null) && (track.Kind == TrackKind.File))
                    {
                        Logger.WriteLine(base.name, String.Format(
                                             "Fetching tag information for '{0}' ({1})",
                                             track.MakeKey(), track.UniqueID));

                        try
                        {
                            // store into a temporary TrackFile so we can decide which
                            // properties to update...

                            var buffer = new TrackFile(track);
                            tagger.RetrieveTags(buffer);

                            Reconcile(track, buffer);
                        }
                        catch (Exception exc)
                        {
                            Logger.WriteLine(base.name,
                                             String.Format("Error fetching information {0}, {1}, {2}",
                                                           track.Artist, track.Name, track.Album), exc);
                        }
                    }
                }

                count++;
                base.ProgressPercentage = (int)((double)count / (double)total * 100.0);
            }

            tagger = null;
        }
Example #11
0
        /// <summary>
        /// Scan all tracks in the given playlist.
        /// </summary>
        /// <param name="list"></param>

        private void ScanTracks(PersistentIDCollection pids)
        {
            foreach (PersistentID persistentID in pids)
            {
                if (base.isActive)
                {
                    using (Track track = libraryPlaylist.GetTrack(persistentID))
                    {
                        if ((track != null) && (track.Kind == TrackKind.File))
                        {
                            //Logger.WriteLine(base.name, "ScanTrying " + track.MakeKey());

                            if (String.IsNullOrEmpty(track.Location) || !File.Exists(track.Location))
                            {
                                Logger.WriteLine(base.name,
                                                 "Deleting phantom track " + track.MakeKey());

                                try
                                {
                                    if (ScannerBase.isLive)
                                    {
                                        // deletes library entry but not physical media file
                                        track.Delete();
                                    }
                                }
                                catch (Exception exc)
                                {
                                    Logger.WriteLine(base.name,
                                                     String.Format("Error deleting phantom {0}, {1}, {2}",
                                                                   track.Artist, track.Name, track.Album), exc);
                                }
                            }
                        }
                    }

                    count++;
                    base.ProgressPercentage = (int)((double)count / (double)total * 100.0);
                }
                else
                {
                    Logger.WriteLine(base.name, "Phantom scanner cancelled while scanning");
                    break;
                }
            }
        }
Example #12
0
        /// <summary>
        /// Removes a playlist from the catalog.
        /// </summary>

        private void RemovePlaylist()
        {
            PersistentIDCollection playlistPIDs = new PersistentIDCollection();

            foreach (Playlist playlist in controller.Playlists.Values)
            {
                if (playlist != null)
                {
                    playlistPIDs.Add(playlist.PersistentID);
                    playlist.Dispose();
                }
            }

            if (playlistPIDs.Count > 0)
            {
                catalog.RefreshPlaylists(playlistPIDs);
            }
        }
Example #13
0
        /// <summary>
        /// Retrieves a list of all tracks by the specivied artist on the named album.
        /// </summary>
        /// <param name="album">The name of the album.</param>
        /// <param name="artist">The name of the artist.</param>
        /// <returns></returns>

        public override PersistentIDCollection FindTracksByAlbum(string album, string artist)
        {
            if (!isReady)
            {
                return(new PersistentIDCollection());
            }

            album  = album.Trim().ToLower();
            artist = artist.Trim().ToLower();

            // find the <plist><dict><key>Tracks</key><dict> root node
            var trackRoot =
                from node in root
                .Element(ns + "dict")
                .Elements(ns + "key")
                where node.Value == "Tracks"
                select node.NextNode;

            // Tracks/dict is the container for all tracks where each is a key/dict pair
            // collect all dict elements related to specified album

            var albumTracks =
                from node in
                (from node in ((XElement)trackRoot.Single())
                 .Elements(ns + "dict")
                 .Elements(ns + "key")
                 where node.Value == "Album" &&
                 ((XElement)node.NextNode).Value.Trim().ToLower() == album
                 select node.Parent
                ).Elements(ns + "key")
                where node.Value == "Artist" &&
                ((XElement)node.NextNode).Value.Trim().ToLower() == artist
                select node.Parent;

            // collect all persistent IDs from these dict elements
            var tracks =
                from node in albumTracks.Elements(ns + "key")
                where node.Value == "Persistent ID"
                select PersistentID.Parse(((XElement)node.NextNode).Value);

            PersistentIDCollection list = new PersistentIDCollection(tracks.ToList <PersistentID>());

            return(list);
        }
Example #14
0
        //========================================================================================
        // Constructor
        //========================================================================================

        /// <summary>
        /// Initialize a new instance of this scanner.
        /// </summary>
        /// <param name="controller">The iTunesAppClass to use.</param>
        /// <param name="catalog"></param>
        /// <param name="exportPIDs">
        /// The list of persistent track IDs.  When exporting multiple playlists, this list
        /// should include all tracks from all playlists where each track indicates its own
        /// source playlist.  This allows comprehensive/overall feedback for UI progress bars.
        /// </param>
        /// <param name="encoder">The encoder to use to convert tracks.</param>
        /// <param name="playlistFormat">
        /// The playlist output format or PlaylistProviderFactory.NoFormat for no playlist file.
        /// </param>
        /// <param name="location">
        /// The target root directory path to which all entries will be copied or converted.
        /// </param>
        /// <param name="pathFormat">
        /// The path format string as specified in FolderFormts.xml or null for title only.
        /// </param>
        /// <param name="isSynchronized">
        /// True if target location should be synchronized, removing entries in the target
        /// location that are not included in the exportPIDs collection.
        /// </param>

        public ExportScanner(
            Controller controller, ICatalog catalog, PersistentIDCollection exportPIDs,
            Encoder encoder, string playlistFormat, string location, string pathFormat,
            bool isSynchronized)
            : base(Resx.I_ScanExport, controller, catalog)
        {
            base.description = isSynchronized ? Resx.ScanSynchronize : Resx.ScanExport;
            base.tooltip     = String.Format(Resx.ExportingCount, exportPIDs.Count);

            this.exportPIDs           = exportPIDs;
            this.encoder              = encoder;
            this.expectedType         = (encoder == null ? String.Empty : encoder.ExpectedType);
            this.playlistFormat       = playlistFormat;
            this.playlistName         = exportPIDs.Name;
            this.location             = location;
            this.createSubdirectories = (pathFormat != null);
            this.pathFormat           = pathFormat ?? PathHelper.GetPathFormat(FlatPathFormat);
            this.isSynchronized       = isSynchronized;

            this.exports = null;
            this.writer  = null;
        }
Example #15
0
        /// <summary>
        /// Verifies playlists in the catalog against a list of known existing playlists.
        /// </summary>
        /// <param name="playlistPIDs">
        /// A collection of existing playlist persistent IDs; any playlist not referenced
        /// in the list will be removed from the catalog.
        /// </param>

        public abstract void RefreshPlaylists(PersistentIDCollection playlistPIDs);
Example #16
0
        /// <summary>
        /// Adds one or more tracks to the specified playlist.
        /// </summary>
        /// <param name="playlistPID"></param>
        /// <param name="trackPIDs"></param>

        public abstract void AddTracksToPlaylist(
            PersistentIDCollection trackPIDs, PersistentID playlistPID);
Example #17
0
        /// <summary>
        /// Verifies playlists in the catalog against a list of known existing playlists.
        /// </summary>
        /// <param name="playlistPIDs">
        /// A collection of existing playlist persistent IDs; any playlist not referenced
        /// in the list will be removed from the catalog.
        /// </param>

        public override void RefreshPlaylists(PersistentIDCollection playlistPIDs)
        {
        }
Example #18
0
        /// <summary>
        /// Adds a track entry to the specified playlist.
        /// </summary>
        /// <param name="playlistPID"></param>
        /// <param name="trackPIDs"></param>

        public override void AddTracksToPlaylist(
            PersistentIDCollection trackPIDs, PersistentID playlistPID)
        {
        }