Example #1
0
        public void Setup()
        {
            _artist = new Artist
            {
                Name            = "Alien Ant Farm",
                Monitored       = true,
                ForeignArtistId = "this is a fake id",
                Id       = 1,
                Metadata = new ArtistMetadata {
                    Id = 1
                }
            };

            _albumRepo   = Mocker.Resolve <AlbumRepository>();
            _releaseRepo = Mocker.Resolve <ReleaseRepository>();

            _release = Builder <AlbumRelease>
                       .CreateNew()
                       .With(e => e.Id = 0)
                       .With(e => e.ForeignReleaseId = "e00e40a3-5ed5-4ed3-9c22-0a8ff4119bdf")
                       .With(e => e.Monitored        = true)
                       .Build();

            _album = new Album
            {
                Title            = "ANThology",
                ForeignAlbumId   = "1",
                CleanTitle       = "anthology",
                Artist           = _artist,
                ArtistMetadataId = _artist.ArtistMetadataId,
                AlbumType        = "",
                AlbumReleases    = new List <AlbumRelease> {
                    _release
                },
            };

            _albumRepo.Insert(_album);
            _release.AlbumId = _album.Id;
            _releaseRepo.Insert(_release);
            _albumRepo.Update(_album);

            _albumSpecial = new Album
            {
                Title            = "+",
                ForeignAlbumId   = "2",
                CleanTitle       = "",
                Artist           = _artist,
                ArtistMetadataId = _artist.ArtistMetadataId,
                AlbumType        = "",
                AlbumReleases    = new List <AlbumRelease>
                {
                    new AlbumRelease
                    {
                        ForeignReleaseId = "fake id"
                    }
                }
            };

            _albumRepo.Insert(_albumSpecial);
        }
Example #2
0
        public static AlbumReleaseResource ToResource(this AlbumRelease model)
        {
            if (model == null)
            {
                return(null);
            }

            return(new AlbumReleaseResource
            {
                Id = model.Id,
                AlbumId = model.AlbumId,
                ForeignReleaseId = model.ForeignReleaseId,
                Title = model.Title,
                Status = model.Status,
                Duration = model.Duration,
                TrackCount = model.TrackCount,
                Media = model.Media.ToResource(),
                Disambiguation = model.Disambiguation,
                Country = model.Country,
                Label = model.Label,
                Monitored = model.Monitored,
                Format = string.Join(", ",
                                     model.Media.OrderBy(x => x.Number)
                                     .GroupBy(x => x.Format)
                                     .Select(g => MediaFormatHelper(g.Key, g.Count()))
                                     .ToList())
            });
        }
Example #3
0
        public void Setup()
        {
            _artist = Builder <Artist> .CreateNew()
                      .With(a => a.ArtistMetadataId = 10)
                      .BuildNew();

            Db.Insert(_artist);

            _album = Builder <Album> .CreateNew()
                     .With(e => e.ReleaseDate      = DateTime.Today.AddDays(-5))
                     .With(e => e.ArtistMetadataId = 10)
                     .BuildNew();

            Db.Insert(_album);

            _release = Builder <AlbumRelease> .CreateNew()
                       .With(e => e.AlbumId   = _album.Id)
                       .With(e => e.Monitored = true)
                       .BuildNew();

            Db.Insert(_release);

            _track = Builder <Track> .CreateNew()
                     .With(e => e.TrackFileId    = 0)
                     .With(e => e.Artist         = _artist)
                     .With(e => e.AlbumReleaseId = _release.Id)
                     .BuildNew();

            _trackFile = Builder <TrackFile> .CreateNew()
                         .With(e => e.Artist  = _artist)
                         .With(e => e.Album   = _album)
                         .With(e => e.Quality = new QualityModel(Quality.MP3_256))
                         .BuildNew();
        }
Example #4
0
        public virtual bool Equals(AlbumRelease another)
        {
            if (another == null)
                return IsEmpty;

            return (Equals(CatNum, another.CatNum) && Equals(ReleaseDate, another.ReleaseDate) && Equals(EventName, another.EventName));
        }
Example #5
0
        private LocalTrack GivenLocalTrack(Track track, AlbumRelease release)
        {
            var fileInfo = Builder <ParsedTrackInfo>
                           .CreateNew()
                           .With(x => x.Title          = track.Title)
                           .With(x => x.CleanTitle     = track.Title.CleanTrackTitle())
                           .With(x => x.AlbumTitle     = release.Title)
                           .With(x => x.Disambiguation = release.Disambiguation)
                           .With(x => x.ReleaseMBId    = release.ForeignReleaseId)
                           .With(x => x.ArtistTitle    = track.ArtistMetadata.Value.Name)
                           .With(x => x.TrackNumbers   = new[] { track.AbsoluteTrackNumber })
                           .With(x => x.DiscCount      = release.Media.Count)
                           .With(x => x.DiscNumber     = track.MediumNumber)
                           .With(x => x.RecordingMBId  = track.ForeignRecordingId)
                           .With(x => x.Country        = IsoCountries.Find("US"))
                           .With(x => x.Label          = release.Label.First())
                           .With(x => x.Year           = (uint)(release.Album.Value.ReleaseDate?.Year ?? 0))
                           .Build();

            var localTrack = Builder <LocalTrack>
                             .CreateNew()
                             .With(x => x.FileTrackInfo = fileInfo)
                             .Build();

            return(localTrack);
        }
        public void Setup()
        {
            _release = Builder <AlbumRelease>
                       .CreateNew()
                       .With(s => s.Media = new List <Medium> {
                new Medium {
                    Number = 1
                }
            })
                       .With(s => s.ForeignReleaseId = "xxx-xxx-xxx-xxx")
                       .With(s => s.Monitored        = true)
                       .With(s => s.TrackCount       = 10)
                       .Build();

            _metadata = Builder <ArtistMetadata> .CreateNew().Build();

            _tracks = Builder <Track>
                      .CreateListOfSize(10)
                      .All()
                      .With(x => x.AlbumReleaseId   = _release.Id)
                      .With(x => x.ArtistMetadata   = _metadata)
                      .With(x => x.ArtistMetadataId = _metadata.Id)
                      .BuildList();

            Mocker.GetMock <ITrackService>()
            .Setup(s => s.GetTracksForRefresh(_release.Id, It.IsAny <IEnumerable <string> >()))
            .Returns(_tracks);
        }
Example #7
0
        public AlbumReleaseContract(AlbumRelease release, ContentLanguagePreference languagePreference)
        {
            ParamIs.NotNull(() => release);

            CatNum       = release.CatNum;
            ReleaseDate  = (release.ReleaseDate != null ? new OptionalDateTimeContract(release.ReleaseDate) : null);
            ReleaseEvent = release.ReleaseEvent != null ? new ReleaseEventForApiContract(release.ReleaseEvent, languagePreference, ReleaseEventOptionalFields.None, null, false) : null;
        }
Example #8
0
        public AlbumReleaseContract(AlbumRelease release)
        {
            ParamIs.NotNull(() => release);

            CatNum      = release.CatNum;
            ReleaseDate = (release.ReleaseDate != null ? new OptionalDateTimeContract(release.ReleaseDate) : null);
            EventName   = release.EventName;
        }
Example #9
0
        public AlbumReleaseContract(AlbumRelease release)
        {
            ParamIs.NotNull(() => release);

            CatNum       = release.CatNum;
            ReleaseDate  = (release.ReleaseDate != null ? new OptionalDateTimeContract(release.ReleaseDate) : null);
            ReleaseEvent = release.ReleaseEvent != null ? new ReleaseEventForApiContract(release.ReleaseEvent, ReleaseEventOptionalFields.None) : null;
        }
Example #10
0
        public void Setup()
        {
            _release = Builder <AlbumRelease> .CreateNew().Build();

            _allTracks = Builder <Track> .CreateListOfSize(20)
                         .All()
                         .BuildList();
        }
Example #11
0
        public virtual bool Equals(AlbumRelease another)
        {
            if (another == null)
            {
                return(IsEmpty);
            }

            return(Equals(CatNum, another.CatNum) && Equals(ReleaseDate, another.ReleaseDate) && Equals(EventName, another.EventName));
        }
Example #12
0
        private List <LocalTrack> GivenLocalTracks(List <Track> tracks, AlbumRelease release)
        {
            var output = new List <LocalTrack>();

            foreach (var track in tracks)
            {
                output.Add(GivenLocalTrack(track, release));
            }
            return(output);
        }
Example #13
0
        private List <LocalTrack> GivenLocalTracks(List <Track> tracks, AlbumRelease release)
        {
            var output = Builder <LocalTrack>
                         .CreateListOfSize(tracks.Count)
                         .Build()
                         .ToList();

            for (int i = 0; i < tracks.Count; i++)
            {
                output[i].FileTrackInfo = GivenParsedTrackInfo(tracks[i], release);
            }

            return(output);
        }
Example #14
0
        public ArchivedAlbumReleaseContract(AlbumRelease release)
        {
            ParamIs.NotNull(() => release);

            CatNum      = release.CatNum;
            ReleaseDate = (release.ReleaseDate != null ? new OptionalDateTimeContract(release.ReleaseDate) : null);

            if (ReleaseDate != null)
            {
                ReleaseDate.Formatted = string.Empty;
            }

            EventName = release.EventName;
        }
        public ArchivedAlbumReleaseContract(AlbumRelease release)
        {
            ParamIs.NotNull(() => release);

            CatNum      = release.CatNum;
            ReleaseDate = (release.ReleaseDate != null ? new OptionalDateTimeContract(release.ReleaseDate) : null);

            if (ReleaseDate != null)
            {
                ReleaseDate.Formatted = string.Empty;
            }

            ReleaseEvent = ObjectRefContract.Create(release.ReleaseEvent);
        }
Example #16
0
        public AlbumImportedEvent(Artist artist, Album album, AlbumRelease release, List <TrackFile> importedTracks, List <TrackFile> oldFiles, bool newDownload, DownloadClientItem downloadClientItem)
        {
            Artist         = artist;
            Album          = album;
            AlbumRelease   = release;
            ImportedTracks = importedTracks;
            OldFiles       = oldFiles;
            NewDownload    = newDownload;

            if (downloadClientItem != null)
            {
                DownloadClient = downloadClientItem.DownloadClientInfo.Name;
                DownloadId     = downloadClientItem.DownloadId;
            }
        }
 private ParsedTrackInfo GivenParsedTrackInfo(Track track, AlbumRelease release)
 {
     return(Builder <ParsedTrackInfo>
            .CreateNew()
            .With(x => x.Title = track.Title)
            .With(x => x.AlbumTitle = release.Title)
            .With(x => x.Disambiguation = release.Disambiguation)
            .With(x => x.ReleaseMBId = release.ForeignReleaseId)
            .With(x => x.ArtistTitle = track.ArtistMetadata.Value.Name)
            .With(x => x.TrackNumbers = new[] { track.AbsoluteTrackNumber })
            .With(x => x.RecordingMBId = track.ForeignRecordingId)
            .With(x => x.Country = IsoCountries.Find("US"))
            .With(x => x.Label = release.Label.First())
            .With(x => x.Year = (uint)release.Album.Value.ReleaseDate.Value.Year)
            .Build());
 }
Example #18
0
        private static AlbumRelease MapRelease(ReleaseResource resource, Dictionary <string, ArtistMetadata> artistDict)
        {
            AlbumRelease release = new AlbumRelease();

            release.ForeignReleaseId     = resource.Id;
            release.OldForeignReleaseIds = resource.OldIds;
            release.Title          = resource.Title;
            release.Status         = resource.Status;
            release.Label          = resource.Label;
            release.Disambiguation = resource.Disambiguation;
            release.Country        = resource.Country;
            release.ReleaseDate    = resource.ReleaseDate;

            // Get the complete set of media/tracks returned by the API, adding missing media if necessary
            var allMedia  = resource.Media.Select(MapMedium).ToList();
            var allTracks = resource.Tracks.Select(x => MapTrack(x, artistDict));

            if (!allMedia.Any())
            {
                foreach (int n in allTracks.Select(x => x.MediumNumber).Distinct())
                {
                    allMedia.Add(new Medium {
                        Name = "Unknown", Number = n, Format = "Unknown"
                    });
                }
            }

            // Skip non-audio media
            var audioMediaNumbers = allMedia.Where(x => !nonAudioMedia.Contains(x.Format)).Select(x => x.Number);

            // Get tracks on the audio media and omit any that are skipped
            release.Tracks     = allTracks.Where(x => audioMediaNumbers.Contains(x.MediumNumber) && !skippedTracks.Contains(x.Title)).ToList();
            release.TrackCount = release.Tracks.Value.Count;

            // Only include the media that contain the tracks we have selected
            var usedMediaNumbers = release.Tracks.Value.Select(track => track.MediumNumber);

            release.Media = allMedia.Where(medium => usedMediaNumbers.Contains(medium.Number)).ToList();

            release.Duration = release.Tracks.Value.Sum(x => x.Duration);

            return(release);
        }
Example #19
0
        public void Setup()
        {
            _artist = Builder <Artist>
                      .CreateNew()
                      .With(s => s.Name = "Alien Ant Farm")
                      .Build();

            _album = Builder <Album>
                     .CreateNew()
                     .With(s => s.Title = "Anthology")
                     .Build();

            _release = Builder <AlbumRelease>
                       .CreateNew()
                       .With(s => s.Media = new List <Medium> {
                new Medium {
                    Number = 1
                }
            })
                       .Build();

            _track = Builder <Track> .CreateNew()
                     .With(e => e.Title = "City Sushi")
                     .With(e => e.AbsoluteTrackNumber = 6)
                     .With(e => e.AlbumRelease        = _release)
                     .Build();

            _trackFile = new TrackFile {
                Quality = new QualityModel(Quality.MP3_320), ReleaseGroup = "GamearrTest"
            };

            _namingConfig = NamingConfig.Default;
            _namingConfig.RenameTracks = true;

            Mocker.GetMock <INamingConfigService>()
            .Setup(c => c.GetConfig()).Returns(_namingConfig);

            Mocker.GetMock <IQualityDefinitionService>()
            .Setup(v => v.Get(Moq.It.IsAny <Quality>()))
            .Returns <Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
        }
Example #20
0
        public void Setup()
        {
            _artist = Builder <Artist>
                      .CreateNew()
                      .With(s => s.Name = "Avenged Sevenfold")
                      .Build();

            _album = Builder <Album>
                     .CreateNew()
                     .With(s => s.Title = "Hail to the King")
                     .Build();

            _release = Builder <AlbumRelease>
                       .CreateNew()
                       .With(s => s.Media = new List <Medium> {
                new Medium {
                    Number = 1
                }
            })
                       .Build();

            _track = Builder <Track> .CreateNew()
                     .With(e => e.Title = "Doing Time")
                     .With(e => e.AbsoluteTrackNumber = 3)
                     .With(e => e.AlbumRelease        = _release)
                     .Build();

            _trackFile = new TrackFile {
                Quality = new QualityModel(Quality.MP3_256), ReleaseGroup = "LidarrTest"
            };

            _namingConfig = NamingConfig.Default;
            _namingConfig.RenameTracks = true;

            Mocker.GetMock <INamingConfigService>()
            .Setup(c => c.GetConfig()).Returns(_namingConfig);

            Mocker.GetMock <IQualityDefinitionService>()
            .Setup(v => v.Get(Moq.It.IsAny <Quality>()))
            .Returns <Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
        }
Example #21
0
        public List <CandidateAlbumRelease> GetCandidatesFromTags(LocalAlbumRelease localAlbumRelease, Artist artist, Album album, AlbumRelease release, bool includeExisting)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();

            // Generally artist, album and release are null.  But if they're not then limit candidates appropriately.
            // We've tried to make sure that tracks are all for a single release.

            List <CandidateAlbumRelease> candidateReleases;

            // if we have a release ID, use that
            AlbumRelease tagMbidRelease = null;
            List <CandidateAlbumRelease> tagCandidate = null;

            var releaseIds = localAlbumRelease.LocalTracks.Select(x => x.FileTrackInfo.ReleaseMBId).Distinct().ToList();

            if (releaseIds.Count == 1 && releaseIds[0].IsNotNullOrWhiteSpace())
            {
                _logger.Debug("Selecting release from consensus ForeignReleaseId [{0}]", releaseIds[0]);
                tagMbidRelease = _releaseService.GetReleaseByForeignReleaseId(releaseIds[0], true);

                if (tagMbidRelease != null)
                {
                    tagCandidate = GetCandidatesByRelease(new List <AlbumRelease> {
                        tagMbidRelease
                    }, includeExisting);
                }
            }

            if (release != null)
            {
                // this case overrides the release picked up from the file tags
                _logger.Debug("Release {0} [{1} tracks] was forced", release, release.TrackCount);
                candidateReleases = GetCandidatesByRelease(new List <AlbumRelease> {
                    release
                }, includeExisting);
            }
            else if (album != null)
            {
                // use the release from file tags if it exists and agrees with the specified album
                if (tagMbidRelease?.AlbumId == album.Id)
                {
                    candidateReleases = tagCandidate;
                }
                else
                {
                    candidateReleases = GetCandidatesByAlbum(localAlbumRelease, album, includeExisting);
                }
            }
            else if (artist != null)
            {
                // use the release from file tags if it exists and agrees with the specified album
                if (tagMbidRelease?.Album.Value.ArtistMetadataId == artist.ArtistMetadataId)
                {
                    candidateReleases = tagCandidate;
                }
                else
                {
                    candidateReleases = GetCandidatesByArtist(localAlbumRelease, artist, includeExisting);
                }
            }
            else
            {
                if (tagMbidRelease != null)
                {
                    candidateReleases = tagCandidate;
                }
                else
                {
                    candidateReleases = GetCandidates(localAlbumRelease, includeExisting);
                }
            }

            watch.Stop();
            _logger.Debug($"Getting candidates from tags for {localAlbumRelease.LocalTracks.Count} tracks took {watch.ElapsedMilliseconds}ms");

            // if we haven't got any candidates then try fingerprinting
            return(candidateReleases);
        }
Example #22
0
        public List <ImportDecision <LocalTrack> > GetImportDecisions(List <IFileInfo> musicFiles, Artist artist, Album album, AlbumRelease albumRelease, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter, bool newDownload, bool singleRelease, bool includeExisting)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            var files = filter != FilterFilesType.None && (artist != null) ? _mediaFileService.FilterUnchangedFiles(musicFiles, artist, filter) : musicFiles;

            var localTracks = new List <LocalTrack>();
            var decisions   = new List <ImportDecision <LocalTrack> >();

            _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count);

            if (!files.Any())
            {
                return(decisions);
            }

            ParsedAlbumInfo downloadClientItemInfo = null;

            if (downloadClientItem != null)
            {
                downloadClientItemInfo = Parser.Parser.ParseAlbumTitle(downloadClientItem.Title);
            }

            foreach (var file in files)
            {
                var localTrack = new LocalTrack
                {
                    Artist = artist,
                    Album  = album,
                    DownloadClientAlbumInfo = downloadClientItemInfo,
                    FolderTrackInfo         = folderInfo,
                    Path           = file.FullName,
                    Size           = file.Length,
                    Modified       = file.LastWriteTimeUtc,
                    FileTrackInfo  = _audioTagService.ReadTags(file.FullName),
                    ExistingFile   = !newDownload,
                    AdditionalFile = false
                };

                try
                {
                    // TODO fix otherfiles?
                    _augmentingService.Augment(localTrack, true);
                    localTracks.Add(localTrack);
                }
                catch (AugmentingFailedException)
                {
                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unable to parse file")));
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Couldn't import file. {0}", localTrack.Path);

                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unexpected error processing file")));
                }
            }

            _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms");

            var releases = _identificationService.Identify(localTracks, artist, album, albumRelease, newDownload, singleRelease, includeExisting);

            foreach (var release in releases)
            {
                release.NewDownload = newDownload;
                var releaseDecision = GetDecision(release);

                foreach (var localTrack in release.LocalTracks)
                {
                    if (releaseDecision.Approved)
                    {
                        decisions.AddIfNotNull(GetDecision(localTrack));
                    }
                    else
                    {
                        decisions.Add(new ImportDecision <LocalTrack>(localTrack, releaseDecision.Rejections.ToArray()));
                    }
                }
            }

            return(decisions);
        }
Example #23
0
 public CandidateAlbumRelease(AlbumRelease release)
 {
     AlbumRelease   = release;
     ExistingTracks = new List <TrackFile>();
 }
Example #24
0
        public FileNameSampleService(IBuildFileNames buildFileNames)
        {
            _buildFileNames = buildFileNames;

            _standardArtist = new Artist
            {
                Metadata = new ArtistMetadata
                {
                    Name           = "The Artist Name",
                    Disambiguation = "US Rock Band"
                }
            };

            _standardAlbum = new Album
            {
                Title          = "The Album Title",
                ReleaseDate    = System.DateTime.Today,
                AlbumType      = "Album",
                Disambiguation = "The Best Album",
            };

            _singleRelease = new AlbumRelease
            {
                Album = _standardAlbum,
                Media = new List <Medium>
                {
                    new Medium
                    {
                        Name   = "CD 1: First Years",
                        Format = "CD",
                        Number = 1
                    }
                },
                Monitored = true
            };

            _multiRelease = new AlbumRelease
            {
                Album = _standardAlbum,
                Media = new List <Medium>
                {
                    new Medium
                    {
                        Name   = "CD 1: First Years",
                        Format = "CD",
                        Number = 1
                    },
                    new Medium
                    {
                        Name   = "CD 2: Second Best",
                        Format = "CD",
                        Number = 2
                    }
                },
                Monitored = true
            };

            _track1 = new Track
            {
                AlbumRelease        = _singleRelease,
                AbsoluteTrackNumber = 3,
                MediumNumber        = 1,

                Title = "Track Title (1)",
            };

            _singleTrack = new List <Track> {
                _track1
            };

            var mediaInfo = new MediaInfoModel()
            {
                AudioFormat     = "Flac Audio",
                AudioChannels   = 2,
                AudioBitrate    = 875,
                AudioBits       = 24,
                AudioSampleRate = 44100
            };

            _singleTrackFile = new TrackFile
            {
                Quality      = new QualityModel(Quality.MP3_256, new Revision(2)),
                Path         = "/music/Artist.Name.Album.Name.TrackNum.Track.Title.MP3256.mp3",
                SceneName    = "Artist.Name.Album.Name.TrackNum.Track.Title.MP3256",
                ReleaseGroup = "RlsGrp",
                MediaInfo    = mediaInfo
            };

            _preferredWords = new List <string>
            {
                "iNTERNAL"
            };
        }
Example #25
0
        public List <LocalAlbumRelease> Identify(List <LocalTrack> localTracks, Artist artist, Album album, AlbumRelease release, bool newDownload, bool singleRelease, bool includeExisting)
        {
            // 1 group localTracks so that we think they represent a single release
            // 2 get candidates given specified artist, album and release.  Candidates can include extra files already on disk.
            // 3 find best candidate
            // 4 If best candidate worse than threshold, try fingerprinting

            var watch = System.Diagnostics.Stopwatch.StartNew();

            _logger.Debug("Starting track identification");
            LogTestCaseOutput(localTracks, artist, album, release, newDownload, singleRelease);

            List <LocalAlbumRelease> releases = null;

            if (singleRelease)
            {
                releases = new List <LocalAlbumRelease> {
                    new LocalAlbumRelease(localTracks)
                };
            }
            else
            {
                releases = _trackGroupingService.GroupTracks(localTracks);
            }

            _logger.Debug($"Sorted {localTracks.Count} tracks into {releases.Count} releases in {watch.ElapsedMilliseconds}ms");

            foreach (var localRelease in releases)
            {
                try
                {
                    _augmentingService.Augment(localRelease);
                }
                catch (AugmentingFailedException)
                {
                    _logger.Warn($"Augmentation failed for {localRelease}");
                }
                IdentifyRelease(localRelease, artist, album, release, newDownload, includeExisting);
            }

            watch.Stop();

            _logger.Debug($"Track identification for {localTracks.Count} tracks took {watch.ElapsedMilliseconds}ms");

            return(releases);
        }
Example #26
0
        private void IdentifyRelease(LocalAlbumRelease localAlbumRelease, Artist artist, Album album, AlbumRelease release, bool newDownload, bool includeExisting)
        {
            var  watch         = System.Diagnostics.Stopwatch.StartNew();
            bool fingerprinted = false;

            var candidateReleases = GetCandidatesFromTags(localAlbumRelease, artist, album, release, includeExisting);

            if (candidateReleases.Count == 0 && FingerprintingAllowed(newDownload))
            {
                _logger.Debug("No candidates found, fingerprinting");
                _fingerprintingService.Lookup(localAlbumRelease.LocalTracks, 0.5);
                fingerprinted     = true;
                candidateReleases = GetCandidatesFromFingerprint(localAlbumRelease, artist, album, release, includeExisting);
            }

            if (candidateReleases.Count == 0)
            {
                // can't find any candidates even after fingerprinting
                return;
            }

            _logger.Debug($"Got {candidateReleases.Count} candidates for {localAlbumRelease.LocalTracks.Count} tracks in {watch.ElapsedMilliseconds}ms");

            var allTracks = _trackService.GetTracksByReleases(candidateReleases.Select(x => x.AlbumRelease.Id).ToList());

            // convert all the TrackFiles that represent extra files to List<LocalTrack>
            var allLocalTracks = ToLocalTrack(candidateReleases
                                              .SelectMany(x => x.ExistingTracks)
                                              .DistinctBy(x => x.Path), localAlbumRelease);

            _logger.Debug($"Retrieved {allTracks.Count} possible tracks in {watch.ElapsedMilliseconds}ms");

            GetBestRelease(localAlbumRelease, candidateReleases, allTracks, allLocalTracks);

            // If result isn't great and we haven't fingerprinted, try that
            // Note that this can improve the match even if we try the same candidates
            if (!fingerprinted && FingerprintingAllowed(newDownload) && ShouldFingerprint(localAlbumRelease))
            {
                _logger.Debug($"Match not good enough, fingerprinting");
                _fingerprintingService.Lookup(localAlbumRelease.LocalTracks, 0.5);

                // Only include extra possible candidates if neither album nor release are specified
                // Will generally be specified as part of manual import
                if (album == null && release == null)
                {
                    var extraCandidates = GetCandidatesFromFingerprint(localAlbumRelease, artist, album, release, includeExisting);
                    var newCandidates   = extraCandidates.ExceptBy(x => x.AlbumRelease.Id, candidateReleases, y => y.AlbumRelease.Id, EqualityComparer <int> .Default);
                    candidateReleases.AddRange(newCandidates);
                    allTracks.AddRange(_trackService.GetTracksByReleases(newCandidates.Select(x => x.AlbumRelease.Id).ToList()));
                    allLocalTracks.AddRange(ToLocalTrack(newCandidates
                                                         .SelectMany(x => x.ExistingTracks)
                                                         .DistinctBy(x => x.Path)
                                                         .ExceptBy(x => x.Path, allLocalTracks, x => x.Path, PathEqualityComparer.Instance),
                                                         localAlbumRelease));
                }

                // fingerprint all the local files in candidates we might be matching against
                _fingerprintingService.Lookup(allLocalTracks, 0.5);

                GetBestRelease(localAlbumRelease, candidateReleases, allTracks, allLocalTracks);
            }

            _logger.Debug($"Best release found in {watch.ElapsedMilliseconds}ms");

            localAlbumRelease.PopulateMatch();

            _logger.Debug($"IdentifyRelease done in {watch.ElapsedMilliseconds}ms");
        }
        public void Setup()
        {
            _albumpass1 = new Mock <IImportDecisionEngineSpecification <LocalAlbumRelease> >();
            _albumpass2 = new Mock <IImportDecisionEngineSpecification <LocalAlbumRelease> >();
            _albumpass3 = new Mock <IImportDecisionEngineSpecification <LocalAlbumRelease> >();

            _albumfail1 = new Mock <IImportDecisionEngineSpecification <LocalAlbumRelease> >();
            _albumfail2 = new Mock <IImportDecisionEngineSpecification <LocalAlbumRelease> >();
            _albumfail3 = new Mock <IImportDecisionEngineSpecification <LocalAlbumRelease> >();


            _pass1 = new Mock <IImportDecisionEngineSpecification <LocalTrack> >();
            _pass2 = new Mock <IImportDecisionEngineSpecification <LocalTrack> >();
            _pass3 = new Mock <IImportDecisionEngineSpecification <LocalTrack> >();

            _fail1 = new Mock <IImportDecisionEngineSpecification <LocalTrack> >();
            _fail2 = new Mock <IImportDecisionEngineSpecification <LocalTrack> >();
            _fail3 = new Mock <IImportDecisionEngineSpecification <LocalTrack> >();

            _albumpass1.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalAlbumRelease>())).Returns(Decision.Accept());
            _albumpass2.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalAlbumRelease>())).Returns(Decision.Accept());
            _albumpass3.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalAlbumRelease>())).Returns(Decision.Accept());

            _albumfail1.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalAlbumRelease>())).Returns(Decision.Reject("_albumfail1"));
            _albumfail2.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalAlbumRelease>())).Returns(Decision.Reject("_albumfail2"));
            _albumfail3.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalAlbumRelease>())).Returns(Decision.Reject("_albumfail3"));

            _pass1.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalTrack>())).Returns(Decision.Accept());
            _pass2.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalTrack>())).Returns(Decision.Accept());
            _pass3.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalTrack>())).Returns(Decision.Accept());

            _fail1.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalTrack>())).Returns(Decision.Reject("_fail1"));
            _fail2.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalTrack>())).Returns(Decision.Reject("_fail2"));
            _fail3.Setup(c => c.IsSatisfiedBy(It.IsAny <LocalTrack>())).Returns(Decision.Reject("_fail3"));

            _artist = Builder <Artist> .CreateNew()
                      .With(e => e.QualityProfile = new QualityProfile {
                Items = Qualities.QualityFixture.GetDefaultQualities()
            })
                      .Build();

            _albumRelease = Builder <AlbumRelease> .CreateNew()
                            .Build();

            _quality = new QualityModel(Quality.MP3_256);

            _localTrack = new LocalTrack
            {
                Artist  = _artist,
                Quality = _quality,
                Tracks  = new List <Track> {
                    new Track()
                },
                Path = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi".AsOsAgnostic()
            };

            GivenAudioFiles(new List <string> {
                @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi".AsOsAgnostic()
            });

            Mocker.GetMock <IIdentificationService>()
            .Setup(s => s.Identify(It.IsAny <List <LocalTrack> >(), It.IsAny <Artist>(), It.IsAny <Album>(), It.IsAny <AlbumRelease>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns((List <LocalTrack> tracks, Artist artist, Album album, AlbumRelease release, bool newDownload, bool singleRelease, bool includeExisting) => {
                var ret          = new LocalAlbumRelease(tracks);
                ret.AlbumRelease = _albumRelease;
                return(new List <LocalAlbumRelease> {
                    ret
                });
            });

            Mocker.GetMock <IMediaFileService>()
            .Setup(c => c.FilterUnchangedFiles(It.IsAny <List <IFileInfo> >(), It.IsAny <Artist>(), It.IsAny <FilterFilesType>()))
            .Returns((List <IFileInfo> files, Artist artist, FilterFilesType filter) => files);

            GivenSpecifications(_albumpass1);
        }
Example #28
0
        public void Setup()
        {
            _artist = Builder <Artist>
                      .CreateNew()
                      .With(s => s.Name     = "Linkin Park")
                      .With(s => s.Metadata = new ArtistMetadata {
                Disambiguation = "US Rock Band",
                Name           = "Linkin Park"
            })
                      .Build();

            _medium = Builder <Medium>
                      .CreateNew()
                      .With(m => m.Number = 3)
                      .Build();

            _release = Builder <AlbumRelease>
                       .CreateNew()
                       .With(s => s.Media = new List <Medium> {
                _medium
            })
                       .With(s => s.Monitored = true)
                       .Build();

            _album = Builder <Album>
                     .CreateNew()
                     .With(s => s.Title          = "Hybrid Theory")
                     .With(s => s.AlbumType      = "Album")
                     .With(s => s.Disambiguation = "The Best Album")
                     .Build();


            _namingConfig = NamingConfig.Default;
            _namingConfig.RenameTracks = true;


            Mocker.GetMock <INamingConfigService>()
            .Setup(c => c.GetConfig()).Returns(_namingConfig);

            _track1 = Builder <Track> .CreateNew()
                      .With(e => e.Title = "City Sushi")
                      .With(e => e.AbsoluteTrackNumber = 6)
                      .With(e => e.AlbumRelease        = _release)
                      .With(e => e.MediumNumber        = _medium.Number)
                      .Build();

            _trackFile = Builder <TrackFile> .CreateNew()
                         .With(e => e.Quality      = new QualityModel(Quality.MP3_256))
                         .With(e => e.ReleaseGroup = "LidarrTest")
                         .With(e => e.MediaInfo    = new Parser.Model.MediaInfoModel {
                AudioBitrate    = 320,
                AudioBits       = 16,
                AudioChannels   = 2,
                AudioFormat     = "Flac Audio",
                AudioSampleRate = 44100
            }).Build();

            Mocker.GetMock <IQualityDefinitionService>()
            .Setup(v => v.Get(Moq.It.IsAny <Quality>()))
            .Returns <Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
        }
Example #29
0
        public List <CandidateAlbumRelease> GetCandidatesFromFingerprint(LocalAlbumRelease localAlbumRelease, Artist artist, Album album, AlbumRelease release, bool includeExisting)
        {
            var recordingIds = localAlbumRelease.LocalTracks.Where(x => x.AcoustIdResults != null).SelectMany(x => x.AcoustIdResults).ToList();
            var allReleases  = _releaseService.GetReleasesByRecordingIds(recordingIds);

            // make sure releases are consistent with those selected by the user
            if (release != null)
            {
                allReleases = allReleases.Where(x => x.Id == release.Id).ToList();
            }
            else if (album != null)
            {
                allReleases = allReleases.Where(x => x.AlbumId == album.Id).ToList();
            }
            else if (artist != null)
            {
                allReleases = allReleases.Where(x => x.Album.Value.ArtistMetadataId == artist.ArtistMetadataId).ToList();
            }

            return(GetCandidatesByRelease(allReleases.Select(x => new {
                Release = x,
                TrackCount = x.TrackCount,
                CommonProportion = x.Tracks.Value.Select(y => y.ForeignRecordingId).Intersect(recordingIds).Count() / localAlbumRelease.TrackCount
            })
                                          .Where(x => x.CommonProportion > 0.6)
                                          .ToList()
                                          .OrderBy(x => Math.Abs(x.TrackCount - localAlbumRelease.TrackCount))
                                          .ThenByDescending(x => x.CommonProportion)
                                          .Select(x => x.Release)
                                          .Take(10)
                                          .ToList(), includeExisting));
        }
Example #30
0
        public Distance AlbumReleaseDistance(List <LocalTrack> localTracks, AlbumRelease release, TrackMapping mapping)
        {
            var dist = new Distance();

            if (!VariousArtistIds.Contains(release.Album.Value.ArtistMetadata.Value.ForeignArtistId))
            {
                var artist = MostCommon(localTracks.Select(x => x.FileTrackInfo.ArtistTitle)) ?? "";
                dist.AddString("artist", artist, release.Album.Value.ArtistMetadata.Value.Name);
                _logger.Trace("artist: {0} vs {1}; {2}", artist, release.Album.Value.ArtistMetadata.Value.Name, dist.NormalizedDistance());
            }

            var title = MostCommon(localTracks.Select(x => x.FileTrackInfo.AlbumTitle)) ?? "";

            // Use the album title since the differences in release titles can cause confusion and
            // aren't always correct in the tags
            dist.AddString("album", title, release.Album.Value.Title);
            _logger.Trace("album: {0} vs {1}; {2}", title, release.Title, dist.NormalizedDistance());

            // Number of discs, either as tagged or the max disc number seen
            var discCount = MostCommon(localTracks.Select(x => x.FileTrackInfo.DiscCount));

            discCount = discCount != 0 ? discCount : localTracks.Max(x => x.FileTrackInfo.DiscNumber);
            if (discCount > 0)
            {
                dist.AddNumber("media_count", discCount, release.Media.Count);
                _logger.Trace("media_count: {0} vs {1}; {2}", discCount, release.Media.Count, dist.NormalizedDistance());
            }

            // Media format
            if (release.Media.Select(x => x.Format).Contains("Unknown"))
            {
                dist.Add("media_format", 1.0);
            }

            // Year
            var localYear = MostCommon(localTracks.Select(x => x.FileTrackInfo.Year));

            if (localYear > 0 && (release.Album.Value.ReleaseDate.HasValue || release.ReleaseDate.HasValue))
            {
                var albumYear   = release.Album.Value.ReleaseDate?.Year ?? 0;
                var releaseYear = release.ReleaseDate?.Year ?? 0;
                if (localYear == albumYear || localYear == releaseYear)
                {
                    dist.Add("year", 0.0);
                }
                else
                {
                    var remoteYear = albumYear > 0 ? albumYear : releaseYear;
                    var diff       = Math.Abs(localYear - remoteYear);
                    var diff_max   = Math.Abs(DateTime.Now.Year - remoteYear);
                    dist.AddRatio("year", diff, diff_max);
                }
                _logger.Trace($"year: {localYear} vs {release.Album.Value.ReleaseDate?.Year} or {release.ReleaseDate?.Year}; {dist.NormalizedDistance()}");
            }

            // If we parsed a country from the files use that, otherwise use our preference
            var country = MostCommon(localTracks.Select(x => x.FileTrackInfo.Country));

            if (release.Country.Count > 0)
            {
                if (country != null)
                {
                    dist.AddEquality("country", country.Name, release.Country);
                    _logger.Trace("country: {0} vs {1}; {2}", country.Name, string.Join(", ", release.Country), dist.NormalizedDistance());
                }
                else if (preferredCountries.Count > 0)
                {
                    dist.AddPriority("country", release.Country, preferredCountries.Select(x => x.Name).ToList());
                    _logger.Trace("country priority: {0} vs {1}; {2}", string.Join(", ", preferredCountries.Select(x => x.Name)), string.Join(", ", release.Country), dist.NormalizedDistance());
                }
            }
            else
            {
                // full penalty if MusicBrainz release is missing a country
                dist.Add("country", 1.0);
            }

            var label = MostCommon(localTracks.Select(x => x.FileTrackInfo.Label));

            if (label.IsNotNullOrWhiteSpace())
            {
                dist.AddEquality("label", label, release.Label);
                _logger.Trace("label: {0} vs {1}; {2}", label, string.Join(", ", release.Label), dist.NormalizedDistance());
            }

            var disambig = MostCommon(localTracks.Select(x => x.FileTrackInfo.Disambiguation));

            if (disambig.IsNotNullOrWhiteSpace())
            {
                dist.AddString("album_disambiguation", disambig, release.Disambiguation);
                _logger.Trace("album_disambiguation: {0} vs {1}; {2}", disambig, release.Disambiguation, dist.NormalizedDistance());
            }

            var mbAlbumId = MostCommon(localTracks.Select(x => x.FileTrackInfo.ReleaseMBId));

            if (mbAlbumId.IsNotNullOrWhiteSpace())
            {
                dist.AddBool("album_id", mbAlbumId != release.ForeignReleaseId && !release.OldForeignReleaseIds.Contains(mbAlbumId));
                _logger.Trace("album_id: {0} vs {1} or {2}; {3}", mbAlbumId, release.ForeignReleaseId, string.Join(", ", release.OldForeignReleaseIds), dist.NormalizedDistance());
            }

            // tracks
            foreach (var pair in mapping.Mapping)
            {
                dist.Add("tracks", pair.Value.Item2.NormalizedDistance());
            }
            _logger.Trace("after trackMapping: {0}", dist.NormalizedDistance());

            // missing tracks
            foreach (var track in mapping.MBExtra.Take(localTracks.Count))
            {
                dist.Add("missing_tracks", 1.0);
            }
            _logger.Trace("after missing tracks: {0}", dist.NormalizedDistance());

            // unmatched tracks
            foreach (var track in mapping.LocalExtra.Take(localTracks.Count))
            {
                dist.Add("unmatched_tracks", 1.0);
            }
            _logger.Trace("after unmatched tracks: {0}", dist.NormalizedDistance());

            return(dist);
        }
Example #31
0
        private void LogTestCaseOutput(List <LocalTrack> localTracks, Artist artist, Album album, AlbumRelease release, bool newDownload, bool singleRelease)
        {
            var trackData = localTracks.Select(x => new BasicLocalTrack {
                Path          = x.Path,
                FileTrackInfo = x.FileTrackInfo
            });
            var options = new IdTestCase {
                ExpectedMusicBrainzReleaseIds = new List <string> {
                    "expected-id-1", "expected-id-2", "..."
                },
                LibraryArtists = new List <ArtistTestCase> {
                    new ArtistTestCase {
                        Artist          = artist?.Metadata.Value.ForeignArtistId ?? "expected-artist-id (dev: don't forget to add metadata profile)",
                        MetadataProfile = artist?.MetadataProfile.Value
                    }
                },
                Artist        = artist?.Metadata.Value.ForeignArtistId,
                Album         = album?.ForeignAlbumId,
                Release       = release?.ForeignReleaseId,
                NewDownload   = newDownload,
                SingleRelease = singleRelease,
                Tracks        = trackData.ToList()
            };

            var SerializerSettings = Json.GetSerializerSettings();

            SerializerSettings.Formatting = Formatting.None;

            var output = JsonConvert.SerializeObject(options, SerializerSettings);

            _logger.Debug($"*** IdentificationService TestCaseGenerator ***\n{output}");
        }