/// <summary> /// Get [CacheObject] for the specified [TrackFile] of type [CacheType] /// with a limit age /// </summary> /// <returns>The first found object, Null if not found</returns> public CacheObject Get(TrackFile file, CacheType type, TimeSpan maxAge) { CacheObject obj = Get(file, type); if (obj?.IsValid(maxAge) ?? false) { return(obj); } return(null); }
public void Setup() { Mocker.Resolve <UpgradableSpecification>(); _firstFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 1)), DateAdded = DateTime.Now }; _secondFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 1)), DateAdded = DateTime.Now }; var singleAlbumList = new List <Album> { new Album { }, new Album { } }; var doubleAlbumList = new List <Album> { new Album { }, new Album { }, new Album { } }; var fakeArtist = Builder <Artist> .CreateNew() .With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.FLAC.Id }) .Build(); Mocker.GetMock <IMediaFileService>() .Setup(c => c.GetFilesByAlbum(It.IsAny <int>())) .Returns(new List <TrackFile> { _firstFile, _secondFile }); _parseResultMulti = new RemoteAlbum { Artist = fakeArtist, ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) }, Albums = doubleAlbumList }; _parseResultSingle = new RemoteAlbum { Artist = fakeArtist, ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) }, Albums = singleAlbumList }; }
public override string GetFilenameAfterMove(Artist artist, TrackFile trackFile, MetadataFile metadataFile) { var trackFilePath = trackFile.Path; if (metadataFile.Type == MetadataType.TrackMetadata) { return(GetTrackMetadataFilename(trackFilePath)); } _logger.Debug("Unknown track file metadata: {0}", metadataFile.RelativePath); return(Path.Combine(artist.Path, metadataFile.RelativePath)); }
public async Task DownloadAsync(MediaItem item) { foreach (var track in item.Media.Tracks) { try { e.TrackFile = await MediaService.GetDownloadableTrackAsync(track); e.PercentCompleted = 0; e.Status = TrackStatus.PreProcess; OnTrackDownloadStarted(e); Context.CreatePath(e.TrackFile); Context.TrackFiles.Add(e.TrackFile); if (TrackFile.Exists(e.TrackFile) || !e.TrackFile.Track.IsDownloadable) { e.Status = TrackStatus.DownloadSkipped; OnTrackDownloadCompleted(e); continue; } e.Status = TrackStatus.DownloadingArtwork; OnTrackDownloadProgressChanged(e); await DownloadArtworkAsync(e.TrackFile); e.Status = TrackStatus.DownloadingTrack; var progress = new Progress <ProgressInfo>(info => { e.PercentCompleted = info.PercentCompleted; OnTrackDownloadProgressChanged(e); }); await MediaService.GetDownloader().DownloadAsync(e.TrackFile, progress); e.Status = TrackStatus.DownloadCompleted; OnTrackDownloadCompleted(e); } catch (OperationCanceledException ope) { Log.Error(ope, "{Service}: Track download stopped {Track}", MediaService.Name, track.Title); e.Status = TrackStatus.DownloadFailed; OnTrackDownloadCompleted(e); return; } catch (Exception ex) { Log.Error(ex, "{Service}: Track download failed.", MediaService.Name); e.Status = TrackStatus.DownloadFailed; OnTrackDownloadCompleted(e); } } }
public static void Write(string serviceName, Track completedTrack, TrackFile trackFile, AlbumArtworkSaveFormat saveFormat, string path) { // Get album artwork from cache ImageCacheEntry albumArtwork = null; var smid = completedTrack.Album.GetSmid(serviceName).ToString(); if (ImageCache.Instance.HasItem(smid)) { albumArtwork = ImageCache.Instance.Get(smid); } // Write track tags var track = completedTrack; using (var file = File.Create(new File.LocalFileAbstraction(path), trackFile.FileType.MimeType, ReadStyle.Average)) { file.Tag.Title = track.Title; file.Tag.Performers = new[] { track.Artist.Name }; if (track.Album.Artist != null) { file.Tag.AlbumArtists = new[] { track.Album.Artist.Name }; } file.Tag.Genres = new[] { track.Genre }; file.Tag.Album = track.Album.Title; file.Tag.Track = (uint)track.TrackNumber; file.Tag.TrackCount = (uint)(track.Album.GetNumberOfTracksOnDisc(track.DiscNumber) ?? 0); file.Tag.Disc = (uint)track.DiscNumber; file.Tag.DiscCount = (uint)(track.Album.GetTotalDiscs() ?? 0); file.Tag.Year = (uint)track.Year; file.Tag.Copyright = CopyrightText; file.Tag.Comment = CopyrightText; if (albumArtwork != null) { file.Tag.Pictures = new IPicture[] { new TagLib.Picture(new ByteVector(albumArtwork.Data)) }; } file.Save(); } // Write album artwork to file if requested if (albumArtwork == null) { return; } string parentDirectory; if (saveFormat != AlbumArtworkSaveFormat.DontSave && (parentDirectory = Path.GetDirectoryName(path)) != null) { WriteArtworkFile(parentDirectory, saveFormat, track, albumArtwork); } }
private MetadataFile ProcessTrackMetadata(IMetadata consumer, Artist artist, TrackFile trackFile, List <MetadataFile> existingMetadataFiles) { var trackMetadata = consumer.TrackMetadata(artist, trackFile); if (trackMetadata == null) { return(null); } var fullPath = Path.Combine(artist.Path, trackMetadata.RelativePath); _otherExtraFileRenamer.RenameOtherExtraFile(artist, fullPath); var existingMetadata = GetMetadataFile(artist, existingMetadataFiles, c => c.Type == MetadataType.TrackMetadata && c.TrackFileId == trackFile.Id); if (existingMetadata != null) { var existingFullPath = Path.Combine(artist.Path, existingMetadata.RelativePath); if (fullPath.PathNotEquals(existingFullPath)) { _diskTransferService.TransferFile(existingFullPath, fullPath, TransferMode.Move); existingMetadata.RelativePath = trackMetadata.RelativePath; } } var hash = trackMetadata.Contents.SHA256Hash(); var metadata = existingMetadata ?? new MetadataFile { ArtistId = artist.Id, AlbumId = trackFile.AlbumId, TrackFileId = trackFile.Id, Consumer = consumer.GetType().Name, Type = MetadataType.TrackMetadata, RelativePath = trackMetadata.RelativePath, Extension = Path.GetExtension(fullPath) }; if (hash == metadata.Hash) { return(null); } _logger.Debug("Writing Track Metadata to: {0}", fullPath); SaveMetadataFile(fullPath, trackMetadata.Contents); metadata.Hash = hash; return(metadata); }
private void OnSelectionChange(object sender, SelectionChangedEventArgs e) { TrackFile file = listView_FileList.SelectedItem as TrackFile; if (file == null) { return; } txt_title.Text = file.Title; txt_artist.Text = file.Artist; txt_album.Text = file.Album; }
public TrackImportedEvent(LocalTrack trackInfo, TrackFile importedTrack, List <TrackFile> oldFiles, bool newDownload, DownloadClientItem downloadClientItem) { TrackInfo = trackInfo; ImportedTrack = importedTrack; OldFiles = oldFiles; NewDownload = newDownload; if (downloadClientItem != null) { DownloadClient = downloadClientItem.DownloadClientInfo.Name; DownloadId = downloadClientItem.DownloadId; } }
/// <summary> /// Updates current source of genres, moods and themes with a new one /// </summary> /// <param name="source"></param> private void UpdateTagContainer(TrackFile source) { PluginSettings.LocalSettings.Genres.AddRange(source.Genres); PluginSettings.LocalSettings.Genres = PluginSettings.LocalSettings.Genres.Distinct().ToList(); PluginSettings.LocalSettings.Moods.AddRange(source.Moods); PluginSettings.LocalSettings.Moods = PluginSettings.LocalSettings.Moods.Distinct().ToList(); PluginSettings.LocalSettings.Themes.AddRange(source.Themes); PluginSettings.LocalSettings.Themes = PluginSettings.LocalSettings.Themes.Distinct().ToList(); PluginSettings.LocalSettings.Save(); }
public void RetrieveEmbeddedTags() { ITrackBasics track = new TrackFile( @"C:\Users\cohns\Music\iTunes\iTunes Media\Music\Adele\Rolling In the Deep - Single\01 Rolling In The Deep.mp3"); Tagger.ReadFileTags(track); Tagger tagger = new Tagger(); tagger.RetrieveTags(track); Assert.IsNotNull(track.UniqueID); Assert.IsNotNull(track.ArtistURL); Assert.AreNotEqual(0, track.Year); }
public override ExtraFile Import(Artist artist, TrackFile trackFile, string path, string extension, bool readOnly) { if (LyricFileExtensions.Extensions.Contains(Path.GetExtension(path))) { var suffix = GetSuffix(1, false); var subtitleFile = ImportFile(artist, trackFile, path, readOnly, extension, suffix); _lyricFileService.Upsert(subtitleFile); return(subtitleFile); } return(null); }
public void Setup() { var singleAlbumList = new List <Album> { new Album { Id = FIRST_ALBUM_ID, Title = "Some Album" } }; _artist = Builder <Artist> .CreateNew() .Build(); _firstFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now }; _mp3 = new QualityModel(Quality.MP3_320, new Revision(version: 1)); _flac = new QualityModel(Quality.FLAC, new Revision(version: 1)); _remoteAlbum = new RemoteAlbum { Artist = _artist, ParsedAlbumInfo = new ParsedAlbumInfo { Quality = _mp3 }, Albums = singleAlbumList, Release = Builder <ReleaseInfo> .CreateNew() .Build() }; _history = new List <History.History>(); Mocker.GetMock <IConfigService>() .SetupGet(s => s.EnableCompletedDownloadHandling) .Returns(true); Mocker.GetMock <IHistoryService>() .Setup(s => s.GetByAlbum(It.IsAny <int>(), null)) .Returns(_history); Mocker.GetMock <IMediaFileService>() .Setup(c => c.GetFilesByAlbum(It.IsAny <int>())) .Returns(new List <TrackFile> { _firstFile }); }
public static ISearchResult GetBestResult( this IEnumerable <ISearchResult> enumList, TrackFile file, int tolerance) { IEnumerable <ISearchResult> results = enumList .Where(x => x.Diference(file.Artist) <= tolerance) .OrderBy(x => x.Diference(file.Artist)); if (results.FirstOrDefault()?.ResultType == SearchResultType.Album) { results = results .Where(x => x.Diference(file.Album, "Title") < tolerance) .OrderBy(x => (x.Diference(file.Album, "Title") + x.Diference(file.Artist)) / 2); } return(results.FirstOrDefault()); }
/// <summary> /// Add GMT values to existing values /// </summary> /// <param name="file"></param> /// <param name="media"></param> /// <returns></returns> public static TrackFile AddGmtMedia(this TrackFile file, IGmtMedia media) { if (media == null) { return(file); } file.Genres.AddRange(media.Genres); file.Moods.AddRange(media.Moods); file.Themes.AddRange(media.Themes); file.Genres = file.Genres.Select(x => x.Trim()).Distinct().ToList(); file.Moods = file.Moods.Select(x => x.Trim()).Distinct().ToList(); file.Themes = file.Themes.Select(x => x.Trim()).Distinct().ToList(); return(file); }
/// <summary> /// Add GMT tags according to bot options /// </summary> /// <param name="file"></param> /// <param name="media"></param> /// <param name="setOptions"></param> /// <returns></returns> public static TrackFile SetGmtMedia(this TrackFile file, IGmtMedia media, GmtBotOptions setOptions) { switch (setOptions.FillTagsMode) { case 1: //If empty return(file.SetGmtMediaIfEmpty(media)); case 2: //Add to existing ones return(file.AddGmtMedia(media)); case 3: // Replace all return(file.ForceSetGmt(media)); default: // Test mode or invalid options return unchanged data return(file); } }
private async Task <IGmtMedia> GetTagsFromWebAsync(TrackFile file, SearchResultType tagType) { //Load tags from web IGmtMedia tags = await GetTags(file, tagType); //save it to cache if (tagType == SearchResultType.Album) { Cache.Set(new CacheObject(file.GetAlbumCacheId(), tags)); } else { Cache.Set(new CacheObject(file.GetArtistCacheId(), tags)); } return(tags); }
public void ImportExtraFiles(LocalTrack localTrack, TrackFile trackFile, bool isReadOnly) { if (!_configService.ImportExtraFiles) { return; } var sourcePath = localTrack.Path; var sourceFolder = _diskProvider.GetParentFolder(sourcePath); var sourceFileName = Path.GetFileNameWithoutExtension(sourcePath); var files = _diskProvider.GetFiles(sourceFolder, SearchOption.TopDirectoryOnly); var wantedExtensions = _configService.ExtraFileExtensions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(e => e.Trim(' ', '.')) .ToList(); var matchingFilenames = files.Where(f => Path.GetFileNameWithoutExtension(f).StartsWith(sourceFileName, StringComparison.InvariantCultureIgnoreCase)); foreach (var matchingFilename in matchingFilenames) { var matchingExtension = wantedExtensions.FirstOrDefault(e => matchingFilename.EndsWith(e)); if (matchingExtension == null) { continue; } try { foreach (var extraFileManager in _extraFileManagers) { var extension = Path.GetExtension(matchingFilename); var extraFile = extraFileManager.Import(localTrack.Artist, trackFile, matchingFilename, extension, isReadOnly); if (extraFile != null) { break; } } } catch (Exception ex) { _logger.Warn(ex, "Failed to import extra file: {0}", matchingFilename); } } }
public void ShouldConstructFromAnMp3File() { var track = new TrackFile("./data/mp3/music/Various Artists/Quest - Foxtrot Z/13 - Premium Standard - A Wink & A Smile.mp3"); Assert.Equal("A Wink & A Smile", track.Title); Assert.Equal(new string[] { "Premium Standard" }, track.ArtistNames); Assert.Equal("Quest - Foxtrot Z", track.AlbumTitle); Assert.Equal(new string[] { "Various Artists" }, track.AlbumArtistNames); Assert.Equal(7, track.Comments.Count); Assert.Equal("NoAuto", track.MediaMonkey.Custom1); Assert.Equal("FOX", track.MediaMonkey.Custom2); Assert.Equal("Quest", track.MediaMonkey.Custom3); Assert.Equal("Social", track.MediaMonkey.Custom4); Assert.Equal("Any", track.MediaMonkey.Custom5); Assert.Equal("Seasonal", track.MediaMonkey.Occasion); ; }
public void Setup() { _artist = Builder <Artist> .CreateNew() .With(s => s.Path = Path.Combine(RootFolder, "Artist Name")) .Build(); _trackFile = Builder <TrackFile> .CreateNew() .With(f => f.Path = "/Artist Name - Track01") .Build(); Mocker.GetMock <IDiskProvider>() .Setup(s => s.GetParentFolder(_artist.Path)) .Returns(RootFolder); Mocker.GetMock <IDiskProvider>() .Setup(s => s.GetParentFolder(_trackFile.Path)) .Returns(_artist.Path); }
public void Constructor_GivenFileWithExtension_ShouldReturnValue() { // Arrange. const string validFilename = "someFile.MP3"; var fileSystem = Substitute.For <IFileSystem>(); fileSystem.File.Exists(validFilename).Returns(true); fileSystem.Path.GetExtension(Arg.Any <string>()).Returns("MP3"); var filePropertyRetriever = Substitute.For <IFileExtendedPropertyRetriever>(); // Act. var testObject = new TrackFile(validFilename, fileSystem, filePropertyRetriever); // Assert. Assert.AreEqual("mp3", testObject.FileExtension); }
public async Task DownloadAsyncTask(TrackFile track, string destination) { var tidalTrack = (TidalTrackFile)track; // This is the way to do it as a stream. However this is also really slow. // var request = WebRequest.CreateHttp(tidalTrack.DownloadUri); // request.Method = "GET"; // var response = (HttpWebResponse) await request.GetResponseAsync(); // using ( // var cryptoStream = TidalDecryptor.CreateDecryptionStream(tidalTrack.FileKey, // response.GetResponseStream())) // { // using (var destFile = File.OpenWrite(destination)) // { // var eventArgs = new DownloadEventArgs {State = DownloadState.Downloading}; // int bytesRead, bytesReadTotal = 0; // var buffer = new byte[TidalDecryptor.BlockSize]; // while ((bytesRead = await cryptoStream.ReadAsync(buffer, 0, TidalDecryptor.BlockSize)) > 0) // { // bytesReadTotal += bytesRead; // await destFile.WriteAsync(buffer, 0, bytesRead); // eventArgs.PercentCompleted = (decimal)bytesReadTotal / response.ContentLength; // Progress?.Invoke(this, eventArgs); // } // } // } // Done?.Invoke(this, EventArgs.Empty); var data = await mClient.DownloadDataTaskAsync(tidalTrack.DownloadUri); Progress?.Invoke(this, new DownloadEventArgs { PercentCompleted = 1m, State = DownloadState.PostProcess }); using (var inputStream = new MemoryStream(data)) { using ( var cryptoStream = TidalDecryptor.CreateDecryptionStream(tidalTrack.FileKey, inputStream)) { using (var destFile = File.OpenWrite(destination)) { await cryptoStream.CopyToAsync(destFile, TidalDecryptor.BlockSize); } } } Done?.Invoke(this, EventArgs.Empty); }
public void Constructor_GivenFileWithArtistAttrib_ShouldReturnValueForArtist() { // Arrange. const string validFilename = "someFile.txt"; var fileSystem = Substitute.For <IFileSystem>(); fileSystem.File.Exists(validFilename).Returns(true); var filePropertyRetriever = Substitute.For <IFileExtendedPropertyRetriever>(); filePropertyRetriever.GetPropertyValue("System.Music.Artist").Returns("SomeArtist"); // Act. var testObject = new TrackFile(validFilename, fileSystem, filePropertyRetriever); // Assert. Assert.AreEqual("SomeArtist", testObject.Artist); }
private async Task DownloadArtworkAsync(TrackFile trackFile) { var media = trackFile.Track.Album; if (!ImageCache.Instance.HasImage(media)) // Download artwork if it's not cached { try { var img = await MediaService.GetMediaCoverAsync(media.Cover.Id); ImageCache.Instance.AddEntry(img); } catch (Exception ex) { ImageCache.Instance.AddNull(media); Log.Warning(ex, "{Service}: Exception occurred when download album artwork.", MediaService.Name); } } }
public static TrackFileResource ToResource(this TrackFile model) { if (model == null) { return(null); } return(new TrackFileResource { Id = model.Id, AlbumId = model.AlbumId, Path = model.Path, Size = model.Size, DateAdded = model.DateAdded, Quality = model.Quality, QualityWeight = QualityWeight(model.Quality), MediaInfo = model.MediaInfo.ToResource() }); }
/// <summary> /// Replace properties with GMT values /// </summary> /// <param name="file"></param> /// <param name="media"></param> /// <returns></returns> public static TrackFile ForceSetGmt(this TrackFile file, IGmtMedia media) { if (media?.Genres?.Count > 0) { file.Genres = media.Genres.Select(x => x.Trim()).Distinct().ToList(); } if (media?.Moods?.Count > 0) { file.Moods = media.Moods.Select(x => x.Trim()).Distinct().ToList(); } if (media?.Themes?.Count > 0) { file.Themes = media.Themes.Select(x => x.Trim()).Distinct().ToList(); } return(file); }
public override MetadataFileResult TrackMetadata(Artist artist, TrackFile trackFile) { if (!Settings.TrackMetadata) { return(null); } _logger.Debug("Generating Track Metadata for: {0}", trackFile.Path); var xmlResult = string.Empty; foreach (var track in trackFile.Tracks.Value) { var sb = new StringBuilder(); var xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; xws.Indent = false; using (var xw = XmlWriter.Create(sb, xws)) { var doc = new XDocument(); var details = new XElement("details"); details.Add(new XElement("id", artist.Id)); details.Add(new XElement("title", string.Format("{0} - {1} - {2}", artist.Name, track.TrackNumber, track.Title))); details.Add(new XElement("artist_name", artist.Metadata.Value.Name)); details.Add(new XElement("track_name", track.Title)); details.Add(new XElement("track_number", track.AbsoluteTrackNumber.ToString("00"))); details.Add(new XElement("member", string.Join(" / ", artist.Metadata.Value.Members.ConvertAll(c => c.Name + " - " + c.Instrument)))); doc.Add(details); doc.Save(xw); xmlResult += doc.ToString(); xmlResult += Environment.NewLine; } } var filename = GetTrackMetadataFilename(artist.Path.GetRelativePath(trackFile.Path)); return(new MetadataFileResult(filename, xmlResult.Trim(Environment.NewLine.ToCharArray()))); }
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 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 static TrackFileResource ToResource(this TrackFile model, NzbDrone.Core.Music.Artist artist, IUpgradableSpecification upgradableSpecification) { if (model == null) { return(null); } return(new TrackFileResource { Id = model.Id, ArtistId = artist.Id, AlbumId = model.AlbumId, Path = model.Path, Size = model.Size, DateAdded = model.DateAdded, Quality = model.Quality, QualityWeight = QualityWeight(model.Quality), MediaInfo = model.MediaInfo.ToResource(), QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(artist.QualityProfile.Value, model.Quality) }); }
/// <summary> /// Add values of IGmtMedia if properties are empty /// </summary> /// <param name="file"></param> /// <param name="media"></param> /// <returns></returns> public static TrackFile SetGmtMediaIfEmpty(this TrackFile file, IGmtMedia media) { if (media == null) { return(file); } if (file.Genres.Count == 0) { file.Genres = media.Genres.Select(x => x.Trim()).ToList(); } if (file.Moods.Count == 0) { file.Moods = media.Moods.Select(x => x.Trim()).ToList(); } if (file.Themes.Count == 0) { file.Themes = media.Themes.Select(x => x.Trim()).ToList(); } return(file); }