private async Task <bool> DownloadCollectionAsync(EnqueuedCollection collection, SavePlaylistSetting savePlaylistSetting) { var tracksCollectionLength = collection.MediaCollection.Tracks.Count; var tracksQueue = new Queue <Track>(collection.MediaCollection.Tracks); var trackFiles = new List <TrackFile>(collection.MediaCollection.Tracks.Count); TrackDownloadEventArgs gEventArgs = null; while (tracksQueue.Count > 0) { var eventArgs = gEventArgs = new TrackDownloadEventArgs { CurrentItemIndex = (tracksCollectionLength - tracksQueue.Count) - 1, PercentCompleted = 0M, State = DownloadState.PreProcess, TotalItems = tracksCollectionLength, TrackFile = null }; var currentItem = tracksQueue.Dequeue(); OnTrackDequeued(eventArgs); try { if (!currentItem.IsDownloadable) { continue; } OnTrackDownloadProgress(eventArgs); if (currentItem.Album?.CoverPicture != null) { // Download album artwork if it's not cached var albumSmid = currentItem.Album.GetSmid(collection.Service.Info.Name).ToString(); if (!ImageCache.Instance.HasItem(albumSmid)) { eventArgs.State = DownloadState.DownloadingAlbumArtwork; OnTrackDownloadProgress(eventArgs); try { await ImageCache.Instance.AddByDownload(albumSmid, currentItem.Album.CoverPicture); } catch (Exception ex) { ImageCache.Instance.AddNull(albumSmid); Log.WriteException(Level.Warning, Tag, ex, "Exception occurred when download album artwork:"); } } } // Get the TrackFile eventArgs.TrackFile = await collection.Service.GetDownloadableTrackAsync(currentItem); var downloader = collection.Service.GetDownloader(eventArgs.TrackFile); downloader.Progress += (sender, args) => { eventArgs.Update(args); OnTrackDownloadProgress(eventArgs); }; downloader.Done += (sender, args) => { eventArgs.State = DownloadState.PostProcess; OnTrackDownloadProgress(eventArgs); }; // Generate the path var path = collection.GetPath(eventArgs.TrackFile); var tempPath = path; if (useTempFile) { tempPath += "-temp"; } EnsureParentDirectories(tempPath); eventArgs.State = DownloadState.Downloading; // Begin download await downloader.DownloadAsyncTask(eventArgs.TrackFile, tempPath); trackFiles.Add(eventArgs.TrackFile); // Attempt to dispose the downloader, since the most probable case will be that it will // implement IDisposable if it uses sockets var disposableDownloader = downloader as IDisposable; disposableDownloader?.Dispose(); // Write the tag eventArgs.State = DownloadState.WritingTags; OnTrackDownloadProgress(eventArgs); var setting = Program.DefaultSettings.Settings.AlbumArtworkSaveFormat; if (Program.DefaultSettings.Settings.IgnoreSaveArtworkWithPlaylist && collection.Type == MediaType.Playlist) { setting = AlbumArtworkSaveFormat.DontSave; } TrackTagger.Write(collection.Service.Info.Name, currentItem, eventArgs.TrackFile, setting, tempPath); // Rename to proper path if (useTempFile) { if (File.Exists(path)) { File.Delete(path); } File.Move(tempPath, path); } } catch (Exception ex) { var exEventArgs = new ExceptionEventArgs { CurrentState = eventArgs, Exception = ex }; OnException(exEventArgs); switch (exEventArgs.SkipTo) { case ExceptionSkip.Item: continue; case ExceptionSkip.Collection: case ExceptionSkip.Fail: skip = exEventArgs.SkipTo; return(false); default: throw new ArgumentOutOfRangeException(); } } // Raise the completed event even if an error occurred OnTrackDownloadCompleted(eventArgs); } // Write playlist if possible try { var writer = new PlaylistWriter(collection, trackFiles); switch (savePlaylistSetting) { case SavePlaylistSetting.DontSave: break; case SavePlaylistSetting.M3U: writer.WriteM3U8(); break; case SavePlaylistSetting.PLS: writer.WritePLS(); break; default: throw new ArgumentOutOfRangeException(nameof(savePlaylistSetting), savePlaylistSetting, null); } } catch (Exception ex) { var exEventArgs = new ExceptionEventArgs { CurrentState = gEventArgs, Exception = ex }; OnException(exEventArgs); switch (exEventArgs.SkipTo) { case ExceptionSkip.Item: break; case ExceptionSkip.Collection: case ExceptionSkip.Fail: skip = exEventArgs.SkipTo; return(false); default: throw new ArgumentOutOfRangeException(); } } return(true); }
private async Task <bool> DownloadCollectionAsync(EnqueuedCollection collection) { var tracksCollectionLength = collection.MediaCollection.Tracks.Count; var tracksQueue = new Queue <Track>(collection.MediaCollection.Tracks); while (tracksQueue.Count > 0) { var currentItem = tracksQueue.Dequeue(); var eventArgs = new TrackDownloadEventArgs { CurrentItemIndex = (tracksCollectionLength - tracksQueue.Count) - 1, PercentCompleted = 0M, State = DownloadState.PreProcess, TotalItems = tracksCollectionLength, TrackFile = null }; OnTrackDequeued(eventArgs); try { if (!currentItem.IsDownloadable) { continue; } OnTrackDownloadProgress(eventArgs); // Download album artwork if it's not cached if (currentItem.Album != null && !AlbumArtCache.Instance.HasItem(currentItem.Album.CoverUri.ToString())) { eventArgs.State = DownloadState.DownloadingAlbumArtwork; OnTrackDownloadProgress(eventArgs); await AlbumArtCache.Instance.AddByDownload(currentItem.Album.CoverUri.ToString()); } eventArgs.TrackFile = await collection.Service.GetDownloadableTrackAsync(currentItem); var downloader = collection.Service.GetDownloader(eventArgs.TrackFile); downloader.Progress += (sender, args) => { eventArgs.Update(args); OnTrackDownloadProgress(eventArgs); }; downloader.Done += (sender, args) => { eventArgs.State = DownloadState.PostProcess; OnTrackDownloadProgress(eventArgs); }; var path = eventArgs.TrackFile.GetPath(collection.PathFormat); EnsureParentDirectories(path); eventArgs.State = DownloadState.Downloading; await downloader.DownloadAsyncTask(eventArgs.TrackFile, path); // Attempt to dispose the downloader, since the most probable case will be that it will // implement IDisposable if it uses sockets var disposableDownloader = downloader as IDisposable; disposableDownloader?.Dispose(); // Write the tag eventArgs.State = DownloadState.WritingTags; OnTrackDownloadProgress(eventArgs); TrackTagger.Write(path, currentItem); OnTrackDownloadCompleted(eventArgs); } catch (Exception ex) { #if DEBUG throw ex; #else var exEventArgs = new ExceptionEventArgs { CurrentState = eventArgs, Exception = ex }; OnException(exEventArgs); switch (exEventArgs.SkipTo) { case ExceptionSkip.Item: continue; case ExceptionSkip.Collection: case ExceptionSkip.Fail: skip = exEventArgs.SkipTo; return(false); default: throw new ArgumentOutOfRangeException(); } #endif } } return(true); }
private async Task <bool> DownloadCollectionAsync(EnqueuedCollection collection) { var tracksCollectionLength = collection.MediaCollection.Tracks.Count; var tracksQueue = new Queue <Track>(collection.MediaCollection.Tracks); while (tracksQueue.Count > 0) { var currentItem = tracksQueue.Dequeue(); var eventArgs = new TrackDownloadEventArgs { CurrentItemIndex = (tracksCollectionLength - tracksQueue.Count) - 1, PercentCompleted = 0M, State = DownloadState.PreProcess, TotalItems = tracksCollectionLength, TrackFile = null }; OnTrackDequeued(eventArgs); try { if (!currentItem.IsDownloadable) { continue; } OnTrackDownloadProgress(eventArgs); if (currentItem.Album?.CoverPicture != null) { // Download album artwork if it's not cached var albumSmid = currentItem.Album.GetSmid(collection.Service.Info.Name).ToString(); if (!ImageCache.Instance.HasItem(albumSmid)) { eventArgs.State = DownloadState.DownloadingAlbumArtwork; OnTrackDownloadProgress(eventArgs); try { await ImageCache.Instance.AddByDownload(albumSmid, currentItem.Album.CoverPicture); } catch (Exception ex) { ImageCache.Instance.AddNull(albumSmid); Log.WriteException(Level.Warning, Tag, ex, "Exception occurred when download album artwork:"); } } } eventArgs.TrackFile = await collection.Service.GetDownloadableTrackAsync(currentItem); var downloader = collection.Service.GetDownloader(eventArgs.TrackFile); downloader.Progress += (sender, args) => { eventArgs.Update(args); OnTrackDownloadProgress(eventArgs); }; downloader.Done += (sender, args) => { eventArgs.State = DownloadState.PostProcess; OnTrackDownloadProgress(eventArgs); }; var formatter = new StringObjectFormatter { Globals = { { "ServiceName", collection.Service.Info.Name } } }; var playlistCollection = collection.MediaCollection as Playlist; if (playlistCollection != null) { formatter.Globals.Add("PlaylistName", playlistCollection.Title); } var path = eventArgs.TrackFile.GetPath(collection.PathFormat, formatter); var tempPath = path; if (useTempFile) { tempPath += "-temp"; } EnsureParentDirectories(tempPath); eventArgs.State = DownloadState.Downloading; await downloader.DownloadAsyncTask(eventArgs.TrackFile, tempPath); // Attempt to dispose the downloader, since the most probable case will be that it will // implement IDisposable if it uses sockets var disposableDownloader = downloader as IDisposable; disposableDownloader?.Dispose(); // Write the tag eventArgs.State = DownloadState.WritingTags; OnTrackDownloadProgress(eventArgs); TrackTagger.Write(collection.Service.Info.Name, currentItem, eventArgs.TrackFile, Program.DefaultSettings.Settings.AlbumArtworkSaveFormat, tempPath); // Rename to proper path if (useTempFile) { if (File.Exists(path)) { File.Delete(path); } File.Move(tempPath, path); } } catch (Exception ex) { var exEventArgs = new ExceptionEventArgs { CurrentState = eventArgs, Exception = ex }; OnException(exEventArgs); switch (exEventArgs.SkipTo) { case ExceptionSkip.Item: continue; case ExceptionSkip.Collection: case ExceptionSkip.Fail: skip = exEventArgs.SkipTo; return(false); default: throw new ArgumentOutOfRangeException(); } } // Raise the completed event even if an error occurred OnTrackDownloadCompleted(eventArgs); } return(true); }