Beispiel #1
0
        public static TrackInfo Path2TrackInfo(string path, string artworkPrefix)
        {
            var ti = new TrackInfo();

            try
            {
                var fmd = new FileMetadata(path);
                var fi  = new FileInformation(path);

                ti.Path        = path;
                ti.FileName    = fi.NameWithoutExtension;
                ti.MimeType    = fmd.MimeType;
                ti.FileSize    = fi.SizeInBytes;
                ti.BitRate     = fmd.BitRate;
                ti.SampleRate  = fmd.SampleRate;
                ti.TrackTitle  = MetadataUtils.SanitizeTag(fmd.Title.Value);
                ti.TrackNumber = MetadataUtils.SafeConvertToLong(fmd.TrackNumber.Value);
                ti.TrackCount  = MetadataUtils.SafeConvertToLong(fmd.TrackCount.Value);
                ti.DiscNumber  = MetadataUtils.SafeConvertToLong(fmd.DiscNumber.Value);
                ti.DiscCount   = MetadataUtils.SafeConvertToLong(fmd.DiscCount.Value);
                ti.Duration    = Convert.ToInt64(fmd.Duration.TotalMilliseconds);
                ti.Year        = MetadataUtils.SafeConvertToLong(fmd.Year.Value);

                ti.ArtistName = GetFirstArtist(fmd);

                ti.GenreName = GetFirstGenre(fmd);

                ti.AlbumTitle  = string.IsNullOrWhiteSpace(fmd.Album.Value) ? Defaults.UnknownAlbumString : MetadataUtils.SanitizeTag(fmd.Album.Value);
                ti.AlbumArtist = GetFirstAlbumArtist(fmd);

                var dummyAlbum = new Album
                {
                    AlbumTitle  = ti.AlbumTitle,
                    AlbumArtist = ti.AlbumArtist
                };

                IndexerUtils.UpdateAlbumYear(dummyAlbum, MetadataUtils.SafeConvertToLong(fmd.Year.Value));

                IndexerUtils.CacheArtwork(dummyAlbum, ti.Path);
            }
            catch (Exception ex)
            {
                LogClient.Instance.Logger.Error("Error while creating TrackInfo from file '{0}'. Exception: {1}", path, ex.Message);

                // Make sure the file can be opened by creating a TrackInfo with some default values
                ti = new TrackInfo();

                ti.Path     = path;
                ti.FileName = System.IO.Path.GetFileNameWithoutExtension(path);

                ti.ArtistName = Defaults.UnknownArtistString;

                ti.GenreName = Defaults.UnknownGenreString;

                ti.AlbumTitle  = Defaults.UnknownAlbumString;
                ti.AlbumArtist = Defaults.UnknownAlbumArtistString;
            }

            return(ti);
        }
Beispiel #2
0
        private async Task <long> UpdateTracksAsync()
        {
            long numberUpdatedTracks = 0;

            await Task.Run(() =>
            {
                try
                {
                    using (var conn = this.factory.GetConnection())
                    {
                        conn.BeginTransaction();

                        // Ignore Tracks which are in an unreachable folder
                        List <Track> tracksToProcess = conn.Table <Track>().Select((t) => t).Where((t) => !this.unreachableFolderIDs.Contains(t.FolderID)).ToList();

                        long currentValue = 0;
                        long totalValue   = tracksToProcess.Count;

                        foreach (Track dbTrack in tracksToProcess)
                        {
                            try
                            {
                                if (IndexerUtils.IsTrackOutdated(dbTrack))
                                {
                                    if (this.ProcessTrack(dbTrack, conn))
                                    {
                                        conn.Update(dbTrack);
                                        numberUpdatedTracks += 1;
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                LogClient.Instance.Logger.Error("There was a problem while updating Track with path='{0}'. Exception: {1}", dbTrack.Path, ex.Message);
                            }

                            currentValue += 1;

                            // Report progress if at least 1 track is updated
                            if (numberUpdatedTracks > 0)
                            {
                                this.eventArgs.IndexingAction  = IndexingAction.UpdateTracks;
                                this.eventArgs.ProgressCurrent = currentValue;
                                this.eventArgs.ProgressTotal   = totalValue;
                                this.eventArgs.ProgressPercent = IndexerUtils.CalculatePercent(currentValue, totalValue);
                                this.IndexingStatusChanged(this.eventArgs);
                            }
                        }

                        conn.Commit();
                    }
                }
                catch (Exception ex)
                {
                    LogClient.Instance.Logger.Error("There was a problem while updating Tracks. Exception: {0}", ex.Message);
                }
            });

            return(numberUpdatedTracks);
        }
Beispiel #3
0
        public static void SplitMetadata(string path, ref Track track, ref Album album, ref Artist artist, ref Genre genre)
        {
            if (!string.IsNullOrEmpty(path))
            {
                var fmd = new FileMetadata(path);
                var fi  = new FileInformation(path);

                // Track information
                track.Path        = path;
                track.FileName    = fi.NameWithoutExtension;
                track.Duration    = Convert.ToInt64(fmd.Duration.TotalMilliseconds);
                track.MimeType    = fmd.MimeType;
                track.BitRate     = fmd.BitRate;
                track.SampleRate  = fmd.SampleRate;
                track.TrackTitle  = MetadataUtils.SanitizeTag(fmd.Title.Value);
                track.TrackNumber = MetadataUtils.SafeConvertToLong(fmd.TrackNumber.Value);
                track.TrackCount  = MetadataUtils.SafeConvertToLong(fmd.TrackCount.Value);
                track.DiscNumber  = MetadataUtils.SafeConvertToLong(fmd.DiscNumber.Value);
                track.DiscCount   = MetadataUtils.SafeConvertToLong(fmd.DiscCount.Value);
                track.Year        = MetadataUtils.SafeConvertToLong(fmd.Year.Value);
                track.Rating      = fmd.Rating.Value;

                // Before proceeding, get the available artists
                string albumArtist = GetFirstAlbumArtist(fmd);
                string trackArtist = GetFirstArtist(fmd); // will be used for the album if no album artist is found

                // Album information
                album.AlbumTitle  = string.IsNullOrWhiteSpace(fmd.Album.Value) ? Defaults.UnknownAlbumString : MetadataUtils.SanitizeTag(fmd.Album.Value);
                album.AlbumArtist = (albumArtist == Defaults.UnknownAlbumArtistString ? trackArtist : albumArtist);
                album.DateAdded   = FileOperations.GetDateCreated(path);

                IndexerUtils.UpdateAlbumYear(album, MetadataUtils.SafeConvertToLong(fmd.Year.Value));

                // Artist information
                artist.ArtistName = trackArtist;

                // Genre information
                genre.GenreName = GetFirstGenre(fmd);

                // Metadata hash
                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                sb.Append(album.AlbumTitle);
                sb.Append(artist.ArtistName);
                sb.Append(genre.GenreName);
                sb.Append(track.TrackTitle);
                sb.Append(track.TrackNumber);
                sb.Append(track.Year);
                track.MetaDataHash = CryptographyUtils.MD5Hash(sb.ToString());

                // File information
                track.FileSize         = fi.SizeInBytes;
                track.DateFileModified = fi.DateModifiedTicks;
                track.DateLastSynced   = DateTime.Now.Ticks;
            }
        }
Beispiel #4
0
        private async Task <long> AddArtworkAsync(bool quickArtworkIndexing = true)
        {
            long numberUpdated = 0;

            await Task.Run(() =>
            {
                using (SQLiteConnection conn = this.factory.GetConnection())
                {
                    conn.BeginTransaction();

                    foreach (Album alb in conn.Table <Album>())
                    {
                        try
                        {
                            // Only update artwork if QuickArtworkIndexing is enabled AND there
                            // is no ArtworkID set, OR when QuickArtworkIndexing is disabled.
                            if ((quickArtworkIndexing & string.IsNullOrEmpty(alb.ArtworkID)) | !quickArtworkIndexing)
                            {
                                Track trk = this.GetLastModifiedTrack(alb);

                                if (IndexerUtils.CacheArtwork(alb, trk.Path))
                                {
                                    conn.Update(alb);
                                    numberUpdated += 1;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            LogClient.Instance.Logger.Error("There was a problem while updating the cover art for Album {0}/{1}. Exception: {2}", alb.AlbumTitle, alb.AlbumArtist, ex.Message);
                        }

                        // Report progress if at least 1 album is added
                        if (numberUpdated > 0)
                        {
                            this.eventArgs.IndexingAction  = IndexingAction.UpdateArtwork;
                            this.eventArgs.ProgressPercent = 0;
                            this.IndexingStatusChanged(this.eventArgs);
                        }
                    }

                    conn.Commit();
                }
            });

            return(numberUpdated);
        }
Beispiel #5
0
        private async Task <long> AddTracksAsync()
        {
            long numberAddedTracks = 0;

            await Task.Run(() =>
            {
                try
                {
                    long currentValue = 0;
                    long totalValue   = this.newDiskPaths.Count;

                    long saveItemCount    = IndexerUtils.CalculateSaveItemCount(this.newDiskPaths.Count);
                    long unsavedItemCount = 0;

                    using (var conn = this.factory.GetConnection())
                    {
                        conn.BeginTransaction();

                        foreach (Tuple <long, string, long> newDiskPath in this.newDiskPaths)
                        {
                            Track diskTrack = new Track
                            {
                                FolderID  = newDiskPath.Item1,
                                Path      = newDiskPath.Item2,
                                DateAdded = DateTime.Now.Ticks
                            };

                            try
                            {
                                if (this.ProcessTrack(diskTrack, conn))
                                {
                                    conn.Insert(diskTrack);
                                    numberAddedTracks += 1;
                                    unsavedItemCount  += 1;
                                }

                                // Intermediate save to the database if 20% is reached
                                if (unsavedItemCount == saveItemCount)
                                {
                                    unsavedItemCount = 0;
                                    conn.Commit(); // Intermediate save
                                    conn.BeginTransaction();
                                }
                            }
                            catch (Exception ex)
                            {
                                LogClient.Error("There was a problem while updating Track with path='{0}'. Exception: {1}", diskTrack.Path, ex.Message);
                            }

                            currentValue += 1;

                            // Report progress if at least 1 track is updated
                            if (numberAddedTracks > 0)
                            {
                                this.eventArgs.IndexingAction  = IndexingAction.AddTracks;
                                this.eventArgs.ProgressCurrent = currentValue;
                                this.eventArgs.ProgressTotal   = totalValue;
                                this.eventArgs.ProgressPercent = IndexerUtils.CalculatePercent(currentValue, totalValue);
                                this.IndexingStatusChanged(this.eventArgs);
                            }
                        }

                        conn.Commit(); // Final save
                    }
                }
                catch (Exception ex)
                {
                    LogClient.Error("There was a problem while adding Tracks. Exception: {0}", ex.Message);
                }
            });

            return(numberAddedTracks);
        }
Beispiel #6
0
        private bool ProcessTrack(Track track, SQLiteConnection conn)
        {
            bool processingSuccessful = false;

            var newAlbum  = new Album();
            var newArtist = new Artist();
            var newGenre  = new Genre();

            try
            {
                IndexerUtils.SplitMetadata(track.Path, ref track, ref newAlbum, ref newArtist, ref newGenre);
                processingSuccessful = true;
            }
            catch (Exception ex)
            {
                processingSuccessful = false;
                LogClient.Instance.Logger.Error("Error while retrieving tag information for file {0}. File not added to the database. Exception: {1}", track.Path, ex.Message);
            }

            if (processingSuccessful)
            {
                // Check if such Artist already exists in the database
                if (!this.cache.GetCachedArtist(ref newArtist))
                {
                    // If not, add it.
                    conn.Insert(newArtist);
                }

                // Check if such Genre already exists in the database
                if (!this.cache.GetCachedGenre(ref newGenre))
                {
                    // If not, add it.
                    conn.Insert(newGenre);
                }

                // Check if such Album already exists in the database
                if (!this.cache.GetCachedAlbum(ref newAlbum))
                {
                    // If Not, add it.
                    conn.Insert(newAlbum);
                }
                else
                {
                    // Make sure the Year of the existing album is updated
                    // TODO: can we prevent a database query here?

                    Album dbAlbum = conn.Table <Album>().Where((a) => a.AlbumID.Equals(newAlbum.AlbumID)).FirstOrDefault();

                    if (dbAlbum != null)
                    {
                        dbAlbum.Year = newAlbum.Year;
                        conn.Update(dbAlbum);
                    }
                }

                track.AlbumID  = newAlbum.AlbumID;
                track.ArtistID = newArtist.ArtistID;
                track.GenreID  = newGenre.GenreID;
            }

            return(processingSuccessful);
        }
Beispiel #7
0
        private async Task <long> AddArtworkAsync()
        {
            long numberUpdated = 0;

            await Task.Run(async() =>
            {
                using (SQLiteConnection conn = this.factory.GetConnection())
                {
                    conn.BeginTransaction();

                    foreach (Album alb in conn.Table <Album>())
                    {
                        try
                        {
                            Track trk = this.GetLastModifiedTrack(alb);

                            alb.ArtworkID = await this.cacheService.CacheArtworkAsync(IndexerUtils.GetArtwork(alb, trk.Path));

                            if (!string.IsNullOrEmpty(alb.ArtworkID))
                            {
                                alb.DateLastSynced = DateTime.Now.Ticks;
                                conn.Update(alb);
                                numberUpdated += 1;
                            }
                        }
                        catch (Exception ex)
                        {
                            LogClient.Error("There was a problem while updating the cover art for Album {0}/{1}. Exception: {2}", alb.AlbumTitle, alb.AlbumArtist, ex.Message);
                        }

                        // Report progress if at least 1 album is added
                        if (numberUpdated > 0)
                        {
                            this.eventArgs.IndexingAction  = IndexingAction.UpdateArtwork;
                            this.eventArgs.ProgressPercent = 0;
                            this.IndexingStatusChanged(this.eventArgs);
                        }
                    }

                    conn.Commit();
                }
            });

            return(numberUpdated);
        }
Beispiel #8
0
        private async void AddArtworkInBackgroundAsync()
        {
            LogClient.Info("+++ STARTED ADDING ARTWORK IN THE BACKGROUND +++");
            this.canIndexArtwork   = true;
            this.isIndexingArtwork = true;

            long     numberAdded = 0;
            DateTime startTime   = DateTime.Now;

            await Task.Run(async() =>
            {
                using (SQLiteConnection conn = this.factory.GetConnection())
                {
                    try
                    {
                        conn.BeginTransaction();

                        List <Album> albumsToCheck = conn.Table <Album>().ToList().Where(a => string.IsNullOrEmpty(a.ArtworkID)).ToList();
                        List <long> albumIds       = new List <long>();

                        List <Album> albumsToIndex = conn.Table <Album>().ToList().Where(a => a.NeedsIndexing == 1).ToList();

                        foreach (Album alb in albumsToIndex)
                        {
                            if (!this.canIndexArtwork)
                            {
                                try
                                {
                                    LogClient.Info("+++ ABORTED ADDING ARTWORK IN THE BACKGROUND. Time required: {0} ms +++", Convert.ToInt64(DateTime.Now.Subtract(startTime).TotalMilliseconds));
                                    conn.Commit(); // Makes sure we commit what we already processed
                                    this.AlbumArtworkAdded(this, new AlbumArtworkAddedEventArgs()
                                    {
                                        AlbumIds = albumIds
                                    });                                                                                     // Update UI
                                }
                                catch (Exception ex)
                                {
                                    LogClient.Error("Failed to commit changes while aborting adding artwork in background. Exception: {0}", ex.Message);
                                }

                                this.isIndexingArtwork = false;

                                return;
                            }

                            try
                            {
                                Track trk = this.GetLastModifiedTrack(alb);

                                alb.ArtworkID = await this.cacheService.CacheArtworkAsync(IndexerUtils.GetArtwork(alb, trk.Path));

                                if (!string.IsNullOrEmpty(alb.ArtworkID))
                                {
                                    albumIds.Add(alb.AlbumID);
                                    alb.DateLastSynced = DateTime.Now.Ticks;
                                    conn.Update(alb);
                                    numberAdded += 1;

                                    if (albumIds.Count >= 20)
                                    {
                                        conn.Commit();
                                        List <long> eventAlbumIds = new List <long>(albumIds);
                                        albumIds.Clear();
                                        this.AlbumArtworkAdded(this, new AlbumArtworkAddedEventArgs()
                                        {
                                            AlbumIds = eventAlbumIds
                                        });                                                                                          // Update UI
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                LogClient.Error("There was a problem while updating the cover art for Album {0}/{1}. Exception: {2}", alb.AlbumTitle, alb.AlbumArtist, ex.Message);
                            }

                            try
                            {
                                alb.NeedsIndexing = 0;
                                conn.Update(alb);
                            }
                            catch (Exception ex)
                            {
                                LogClient.Error("There was a problem while updating the cover art for Album {0}/{1}. Exception: {2}", alb.AlbumTitle, alb.AlbumArtist, ex.Message);
                            }
                        }

                        try
                        {
                            conn.Commit();
                            this.AlbumArtworkAdded(this, new AlbumArtworkAddedEventArgs()
                            {
                                AlbumIds = albumIds
                            });                                                                                     // Update UI
                        }
                        catch (Exception ex)
                        {
                            LogClient.Error("Failed to commit changes while finishing adding artwork in background. Exception: {0}", ex.Message);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogClient.Error("Unexpected error occurred while updating artwork in the background. Exception: {0}", ex.Message);
                    }
                }
            });

            this.isIndexingArtwork = false;
            LogClient.Error("+++ FINISHED ADDING ARTWORK IN THE BACKGROUND. Time required: {0} ms +++", Convert.ToInt64(DateTime.Now.Subtract(startTime).TotalMilliseconds));
        }
Beispiel #9
0
        private async Task <long> AddTracksAsync()
        {
            long numberAddedTracks = 0;

            var args = new IndexingStatusEventArgs()
            {
                IndexingAction  = IndexingAction.AddTracks,
                ProgressPercent = 0
            };

            await Task.Run(() =>
            {
                try
                {
                    long currentValue = 0;
                    long totalValue   = this.newDiskPaths.Count;

                    long saveItemCount    = IndexerUtils.CalculateSaveItemCount(totalValue);
                    long unsavedItemCount = 0;
                    int lastPercent       = 0;

                    using (var conn = this.factory.GetConnection())
                    {
                        conn.BeginTransaction();

                        foreach (FolderPathInfo newDiskPath in this.newDiskPaths)
                        {
                            Track diskTrack = Track.CreateDefault(newDiskPath.Path);

                            try
                            {
                                this.ProcessTrack(diskTrack, conn);

                                if (!this.cache.HasCachedTrack(ref diskTrack))
                                {
                                    conn.Insert(diskTrack);
                                    this.cache.AddTrack(diskTrack);
                                    numberAddedTracks += 1;
                                    unsavedItemCount  += 1;
                                }

                                conn.Insert(new FolderTrack(newDiskPath.FolderId, diskTrack.TrackID));

                                // Intermediate save to the database if 20% is reached
                                if (unsavedItemCount == saveItemCount)
                                {
                                    unsavedItemCount = 0;
                                    conn.Commit(); // Intermediate save
                                    conn.BeginTransaction();
                                }
                            }
                            catch (Exception ex)
                            {
                                LogClient.Error("There was a problem while adding Track with path='{0}'. Exception: {1}", diskTrack.Path, ex.Message);
                            }

                            currentValue += 1;

                            int percent = IndexerUtils.CalculatePercent(currentValue, totalValue);

                            // Report progress if at least 1 track is added OR when the progress
                            // interval has been exceeded OR the maximum has been reached.
                            bool mustReportProgress = numberAddedTracks == 1 || percent >= lastPercent + 5 || percent == 100;

                            if (mustReportProgress)
                            {
                                lastPercent          = percent;
                                args.ProgressCurrent = numberAddedTracks;
                                args.ProgressPercent = percent;
                                this.IndexingStatusChanged(args);
                            }
                        }

                        conn.Commit(); // Final save
                    }
                }
                catch (Exception ex)
                {
                    LogClient.Error("There was a problem while adding Tracks. Exception: {0}", ex.Message);
                }
            });

            return(numberAddedTracks);
        }
Beispiel #10
0
        private async Task <long> UpdateTracksAsync()
        {
            long numberUpdatedTracks = 0;

            var args = new IndexingStatusEventArgs()
            {
                IndexingAction  = IndexingAction.UpdateTracks,
                ProgressPercent = 0
            };

            await Task.Run(() =>
            {
                try
                {
                    using (var conn = this.factory.GetConnection())
                    {
                        conn.BeginTransaction();

                        List <Track> alltracks = conn.Table <Track>().Select((t) => t).ToList();

                        long currentValue = 0;
                        long totalValue   = alltracks.Count;
                        int lastPercent   = 0;

                        foreach (Track dbTrack in alltracks)
                        {
                            try
                            {
                                if (IndexerUtils.IsTrackOutdated(dbTrack) | dbTrack.NeedsIndexing == 1)
                                {
                                    this.ProcessTrack(dbTrack, conn);
                                    conn.Update(dbTrack);
                                    numberUpdatedTracks += 1;
                                }
                            }
                            catch (Exception ex)
                            {
                                LogClient.Error("There was a problem while updating Track with path='{0}'. Exception: {1}", dbTrack.Path, ex.Message);
                            }

                            currentValue += 1;

                            int percent = IndexerUtils.CalculatePercent(currentValue, totalValue);

                            // Report progress if at least 1 track is updated OR when the progress
                            // interval has been exceeded OR the maximum has been reached.
                            bool mustReportProgress = numberUpdatedTracks == 1 || percent >= lastPercent + 5 || percent == 100;

                            if (mustReportProgress)
                            {
                                lastPercent          = percent;
                                args.ProgressPercent = percent;
                                this.IndexingStatusChanged(args);
                            }
                        }

                        conn.Commit();
                    }
                }
                catch (Exception ex)
                {
                    LogClient.Error("There was a problem while updating Tracks. Exception: {0}", ex.Message);
                }
            });

            return(numberUpdatedTracks);
        }
Beispiel #11
0
        private async Task <string> GetArtworkFromFile(Album album)
        {
            Track trk = this.GetLastModifiedTrack(album);

            return(await this.cacheService.CacheArtworkAsync(IndexerUtils.GetArtwork(album, trk.Path)));
        }