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); }
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()) }); }
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(); }
public virtual bool Equals(AlbumRelease another) { if (another == null) return IsEmpty; return (Equals(CatNum, another.CatNum) && Equals(ReleaseDate, another.ReleaseDate) && Equals(EventName, another.EventName)); }
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); }
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; }
public AlbumReleaseContract(AlbumRelease release) { ParamIs.NotNull(() => release); CatNum = release.CatNum; ReleaseDate = (release.ReleaseDate != null ? new OptionalDateTimeContract(release.ReleaseDate) : null); EventName = release.EventName; }
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; }
public void Setup() { _release = Builder <AlbumRelease> .CreateNew().Build(); _allTracks = Builder <Track> .CreateListOfSize(20) .All() .BuildList(); }
public virtual bool Equals(AlbumRelease another) { if (another == null) { return(IsEmpty); } return(Equals(CatNum, another.CatNum) && Equals(ReleaseDate, another.ReleaseDate) && Equals(EventName, another.EventName)); }
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); }
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); }
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); }
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()); }
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); }
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)); }
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)); }
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); }
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); }
public CandidateAlbumRelease(AlbumRelease release) { AlbumRelease = release; ExistingTracks = new List <TrackFile>(); }
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" }; }
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); }
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); }
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)); }
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)); }
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); }
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}"); }