예제 #1
0
        /// <summary>
        /// Private method that contains the actual logic for adding a download
        /// </summary>
        /// <param name="item"></param>
        private void InternalAddDownload(IDownloadItem item)
        {
            // Check dirs
            if (!Directory.Exists(Config.Instance.GetInProgressDownloadsFolder()))
            {
                Directory.CreateDirectory(Config.Instance.GetInProgressDownloadsFolder());
            }
            if (!Directory.Exists(Config.Instance.GetCompleteDownloadsFolder()))
            {
                Directory.CreateDirectory(Config.Instance.GetCompleteDownloadsFolder());
            }

            // Create and store downloader
            IDownloader dl = DownloaderFactory.CreateFrom(item.DownloadUri);

            dl.SetItem(item);

            // Register events
            dl.DownloadProgressChanged += IDownloader_DownloadProgressChanged;
            dl.DownloadStatusChanged   += IDownloader_DownloadStatusChanged;

            downloads[dl.CurrentDownloadItem] = dl;
            // Fire event
            DownloadAdded?.Invoke(this, new DownloadEventArgs(dl.CurrentDownloadItem));

            UpdateActiveDownloads();
            SaveDownloads();
        }
 /// <summary>
 /// Runs all enabled post processors against a <code>DownloadItem</code>, assuming the item has completed
 /// </summary>
 /// <param name="item"></param>
 public void Run(IDownloadItem item)
 {
     foreach (var pp in PostProcessors.Where(pp => pp.Enabled || pp.Mandatory).OrderBy(pp => pp.Priority))
     {
         pp.Run(item);
     }
 }
예제 #3
0
        public static void StartQueue(string url = null)
        {
            if (url != null)
            {
                _queueUrl = url;
            }

            if (_queueUrl == null)
            {
                throw new Exception("DownloadManager:下载队列没有设置Url");
            }

            int num = LoaderMaxCount - _currentLoaderCount;

            for (int i = 0; i < num; i++)
            {
                if (_queue.Count == 0)
                {
                    break;
                }

                IDownloadItem item = _queue.Dequeue();

                DownloadItem downloadItem = new DownloadItem(_queueUrl + item.Path, item.Md5, item.Size,
                                                             AssetLoader.ExternalHotfixPath + "/" + item.Path);
                downloadItem.Start(OnQueueItemProgress, OnQueueItemError, OnQueueItemLoaded, null);

                _currentLoaderCount++;
            }
        }
        /// <summary>
        /// Given that download items are presently made as a generic DownloadItem from the API POST, this method
        /// will take that and parse the soulseek data from the DownloadUri
        /// </summary>
        /// <param name="item">Any download item with a fake soulseek-like Uri</param>
        /// <returns>The parsed download information</returns>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="item"/>does not contain a valid faked soulseek uri</exception>
        public static SoulseekDownloadItem ParseFrom(IDownloadItem item)
        {
            if (item is SoulseekDownloadItem ssItem)
            {
                return(ssItem);
            }

            return(FakeSoulseekUriBuilder.DeconstructFrom(item));
        }
예제 #5
0
        /// <summary>
        /// Adds a download at the end of the queue.
        /// </summary>
        /// <param name="downloadItem">The download to add.</param>
        public void AddDownload(IDownloadItem downloadItem)
        {
            if (_downloadQueue.Any(p => p.RssItem.Guid == downloadItem.RssItem.Guid))
            {
                return;
            }

            _downloadQueue.AddLast(downloadItem);
            RaiseDownloadAdded(new DownloadAddedEventArgs(downloadItem));
        }
예제 #6
0
        public async Task StartDownload(string url)
        {
            IDownloadItem item = await downloadItemFactory(url);

            Downloads.Add(item);
            await item.Start();

            if (Downloads.Count > 0)
            {
                IsCancelAllEnabled = true;
            }
        }
예제 #7
0
        /// <summary>
        /// Send a download request to the Cache Server. Listen to the DownloadComplete event to read the results.
        /// </summary>
        /// <param name="downloadItem">The IDownloadItem that specifies which file to download</param>
        public void QueueDownload(IDownloadItem downloadItem)
        {
            m_stream.Write(Encoding.ASCII.GetBytes(CmdGet + (char)downloadItem.Type), 0, 2);
            m_stream.Write(downloadItem.Id.guid, 0, GuidLen);
            m_stream.Write(downloadItem.Id.hash, 0, HashLen);
            m_downloadQueue.Enqueue(downloadItem);

            if (m_downloadQueue.Count == 1)
            {
                ReadNextDownloadResult();
            }
        }
예제 #8
0
        /// <summary>
        /// Downloads a file asynchronously.
        /// </summary>
        /// <param name="address">The address of the resource to download.</param>
        /// <param name="filename">The name of the local file that is to receive the data.</param>
        /// <param name="downloadItem">The download item.</param>
        /// <param name="token">The token for cancelling the operation.</param>
        /// <returns>Returns a Task.</returns>
        private Task <object> DownloadFileAsync(
            string address,
            string filename,
            IDownloadItem downloadItem,
            CancellationToken token)
        {
            var tcs       = new TaskCompletionSource <object>();
            var webClient = _composer.GetExportedValue <IWebDownloader>();

            token.Register(webClient.CancelAsync);

            webClient.DownloadFileCompleted += (obj, args) =>
            {
                if (args.Cancelled)
                {
                    tcs.TrySetCanceled();
                    downloadItem.DownloadState = DownloadState.Stopped;
                    return;
                }

                if (args.Error != null)
                {
                    tcs.TrySetException(args.Error);
                    downloadItem.DownloadState = DownloadState.Error;
                    return;
                }

                tcs.TrySetResult(null);
                downloadItem.DownloadState = DownloadState.Finished;
            };

            webClient.DownloadProgressChanged += (obj, args) =>
            {
                downloadItem.ProgressPercentage  = args.ProgressPercentage;
                downloadItem.BytesReceived       = args.BytesReceived;
                downloadItem.TotalBytesToReceive = args.TotalBytesToReceive;
            };

            try
            {
                webClient.DownloadFileAsync(new Uri(address), filename);
                downloadItem.DownloadState = DownloadState.Downloading;
            }
            catch (UriFormatException ex)
            {
                tcs.TrySetException(ex);
            }

            return(tcs.Task);
        }
예제 #9
0
        public static DownloadItem Load(IDownloadItem downloadItem, string localPath, Action <DownloadItem> onComplete,
                                        Action <DownloadItem> onError, Action <float> onProgress, Action <DownloadItem> onCancel = null)
        {
            _onComplete = onComplete;
            _onProgress = onProgress;
            _onError    = onError;
            _onCancel   = onCancel;

            DownloadItem item = new DownloadItem(downloadItem.Path, downloadItem.Md5, downloadItem.Size, localPath,
                                                 downloadItem.FileType);

            item.Start(OnProgress, OnError, OnLoaded, OnCancel);

            return(item);
        }
예제 #10
0
        /// <summary>
        /// Gets the download address.
        /// </summary>
        /// <param name="downloadItem">The download item.</param>
        /// <returns>Returns the URI of the download item.</returns>
        private string GetDownloadAddress(IDownloadItem downloadItem)
        {
            var media = new MediaContent {
                FileSize = 0
            };

            foreach (var mediaContent in downloadItem.RssItem.MediaGroup)
            {
                if (mediaContent.FileSize > media.FileSize)
                {
                    media = mediaContent;
                }
            }

            return(media.Url);
        }
        /// <summary>
        /// Does the opposite of BuildFrom - it takes a faked uri and creates a downloadable item.
        /// This also copies all of the other properties from the IDownloadItem into the new SoulseekDownloadItem
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public static SoulseekDownloadItem DeconstructFrom(IDownloadItem item)
        {
            // Do the thing we're here for
            var newItem = DeconstructFrom(item.DownloadUri);

            // Copy all the other properties
            newItem.CompletedFilename   = item.CompletedFilename;
            newItem.Content             = item.Content;
            newItem.DownloadingFilename = item.DownloadingFilename;
            newItem.DownloadUri         = item.DownloadUri;
            newItem.Id       = item.Id;
            newItem.Progress = item.Progress;

            // Return the newly created item
            return(newItem);
        }
예제 #12
0
        public void SetItem(IDownloadItem item)
        {
            // I keep making this mistake - the ParseFrom method can return a new IDownloadItem, so then referencing `item` after
            // that references the old one, and so setting the values on that doesn't help anything...
            CurrentSSDownloadItem = SoulseekDownloadItem.ParseFrom(item);
            CurrentSSDownloadItem.DownloadingFilename = HttpUtility.UrlDecode(CurrentSSDownloadItem.DownloadUri.Segments.Last());
            CurrentSSDownloadItem.CompletedFilename   = CurrentSSDownloadItem.DownloadingFilename;

            CurrentSSDownloadItem.Progress = new DownloadProgress
            {
                BytesTotal      = 0,
                BytesDownloaded = 0,
                Status          = DownloadStatus.Pending
            };

            DownloadStatusChanged?.Invoke(this, new DownloadEventArgs(CurrentDownloadItem));
        }
예제 #13
0
        protected virtual void SetItem(IDownloadItem item, Uri actualDownloadUri)
        {
            CurrentDownloadItem      = item;
            item.DownloadingFilename = HttpUtility.UrlDecode(actualDownloadUri.Segments.Last());
            item.CompletedFilename   = item.DownloadingFilename;

            downloader = new PausableEventedDownloader(actualDownloadUri, item.GetDownloadingPath());
            downloader.ProgressChanged          += Downloader_ProgressChanged;
            downloader.StatusChanged            += Downloader_StatusChanged;
            downloader.ReceivedResponseFilename += Downloader_ReceivedResponseFilename;
            item.Progress = new DownloadProgress
            {
                BytesTotal      = 0,
                BytesDownloaded = 0,
                Status          = DownloadStatus.Pending
            };

            // Now it's ready, invoke the handler to get download manager to start (or update)
            DownloadStatusChanged?.Invoke(this, new DownloadEventArgs(CurrentDownloadItem));
        }
예제 #14
0
 public void Cancel(IDownloadItem item) => downloads[item].Cancel();
 /// <summary>
 /// Initializes a new instance of the <see cref="DownloadAddedEventArgs"/> class.
 /// </summary>
 /// <param name="downloadItem">The added download.</param>
 public DownloadAddedEventArgs(IDownloadItem downloadItem)
 {
     DownloadItem = downloadItem;
 }
예제 #16
0
 public void Run(IDownloadItem item)
 {
     File.Move(item.GetDownloadingPath(), item.GetCompletedPath());
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DownloadAddedEventArgs"/> class.
 /// </summary>
 /// <param name="downloadItem">The added download.</param>
 public DownloadAddedEventArgs(IDownloadItem downloadItem)
 {
     DownloadItem = downloadItem;
 }
        /// <summary>
        /// Gets the download address.
        /// </summary>
        /// <param name="downloadItem">The download item.</param>
        /// <returns>Returns the URI of the download item.</returns>
        private string GetDownloadAddress(IDownloadItem downloadItem)
        {
            var media = new MediaContent { FileSize = 0 };
            foreach (var mediaContent in downloadItem.RssItem.MediaGroup)
            {
                if (mediaContent.FileSize > media.FileSize)
                {
                    media = mediaContent;
                }
            }

            return media.Url;
        }
        /// <summary>
        /// Downloads a file asynchronously.
        /// </summary>
        /// <param name="address">The address of the resource to download.</param>
        /// <param name="filename">The name of the local file that is to receive the data.</param>
        /// <param name="downloadItem">The download item.</param>
        /// <param name="token">The token for cancelling the operation.</param>
        /// <returns>Returns a Task.</returns>
        private Task<object> DownloadFileAsync(
            string address,
            string filename,
            IDownloadItem downloadItem,
            CancellationToken token)
        {
            var tcs = new TaskCompletionSource<object>();
            var webClient = _composer.GetExportedValue<IWebDownloader>();

            token.Register(webClient.CancelAsync);

            webClient.DownloadFileCompleted += (obj, args) =>
            {
                if (args.Cancelled)
                {
                    tcs.TrySetCanceled();
                    downloadItem.DownloadState = DownloadState.Stopped;
                    return;
                }

                if (args.Error != null)
                {
                    tcs.TrySetException(args.Error);
                    downloadItem.DownloadState = DownloadState.Error;
                    return;
                }

                tcs.TrySetResult(null);
                downloadItem.DownloadState = DownloadState.Finished;
            };

            webClient.DownloadProgressChanged += (obj, args) =>
            {
                downloadItem.ProgressPercentage = args.ProgressPercentage;
                downloadItem.BytesReceived = args.BytesReceived;
                downloadItem.TotalBytesToReceive = args.TotalBytesToReceive;
            };

            try
            {
                webClient.DownloadFileAsync(new Uri(address), filename);
                downloadItem.DownloadState = DownloadState.Downloading;
            }
            catch (UriFormatException ex)
            {
                tcs.TrySetException(ex);
            }

            return tcs.Task;
        }
        /// <summary>
        /// Adds a download at the end of the queue.
        /// </summary>
        /// <param name="downloadItem">The download to add.</param>
        public void AddDownload(IDownloadItem downloadItem)
        {
            if (_downloadQueue.Any(p => p.RssItem.Guid == downloadItem.RssItem.Guid))
            {
                return;
            }

            _downloadQueue.AddLast(downloadItem);
            RaiseDownloadAdded(new DownloadAddedEventArgs(downloadItem));
        }
예제 #21
0
 public virtual void SetItem(IDownloadItem item) => SetItem(item, item.DownloadUri);
예제 #22
0
 public void Resume(IDownloadItem item) => GetExistingDownload(item).Resume();
예제 #23
0
 public void Pause(IDownloadItem item) => GetExistingDownload(item).Pause();
예제 #24
0
 public DownloadProgress GetProgress(IDownloadItem item) => GetExistingDownload(item).CurrentDownloadItem.Progress;
예제 #25
0
 public async override void SetItem(IDownloadItem item) => base.SetItem(item, await GetActualDownloadUri(item.DownloadUri));
예제 #26
0
 /// <summary>
 /// Removes a <see cref="DownloadItem"/> on the main thread.
 /// </summary>
 /// <param name="downloadItem">The download to remove.</param>
 private void RemoveDownloadItemOnMainThread(IDownloadItem downloadItem)
 {
     _mainThreadDispatcher.Invoke(new CollectionInitializerDelegate(p => _downloads.Remove(p)), downloadItem);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DownloadRemovedEventArgs"/> class.
 /// </summary>
 /// <param name="downloadItem">The download that has been removed.</param>
 public DownloadRemovedEventArgs(IDownloadItem downloadItem)
 {
     DownloadItem = downloadItem;
 }
예제 #28
0
 public DownloadEventArgs(IDownloadItem item) => Target = item;
 /// <summary>
 /// Removes a <see cref="DownloadItem"/> on the main thread.
 /// </summary>
 /// <param name="downloadItem">The download to remove.</param>
 private void RemoveDownloadItemOnMainThread(IDownloadItem downloadItem)
 {
     _mainThreadDispatcher.Invoke(new CollectionInitializerDelegate(p => _downloads.Remove(p)), downloadItem);
 }
예제 #30
0
 /// <summary>
 /// Returns the downloader for a specified download item if it exists, otherwise it throws an exception
 /// </summary>
 /// <param name="item"></param>
 /// <returns></returns>
 private IDownloader GetExistingDownload(IDownloadItem item) => DownloadQueue.Contains(item) ? downloads[item] : throw new KeyNotFoundException();
 /// <summary>
 /// Initializes a new instance of the <see cref="DownloadRemovedEventArgs"/> class.
 /// </summary>
 /// <param name="downloadItem">The download that has been removed.</param>
 public DownloadRemovedEventArgs(IDownloadItem downloadItem)
 {
     DownloadItem = downloadItem;
 }
예제 #32
0
 public void Enqueue(IDownloadItem item) => InternalAddDownload(item);