コード例 #1
0
        /// <summary>
        /// Download media
        /// </summary>
        /// <param name="media">Media file <see cref="IMediaFile"/></param>
        /// <param name="type">Media type <see cref="MediaType"/></param>
        /// <param name="uploadLimit">Upload limit</param>
        /// <param name="downloadLimit">Download limit</param>
        /// <param name="downloadProgress">Download progress</param>
        /// <param name="bandwidthRate">Download rate</param>
        /// <param name="nbSeeds">Number of seeders</param>
        /// <param name="nbPeers">Number of peers</param>
        /// <param name="handle"><see cref="torrent_handle"/></param>
        /// <param name="session"><see cref="session"/></param>
        /// <param name="buffered">Action to execute when media has been buffered</param>
        /// <param name="cancelled">Action to execute when media download has been cancelled</param>
        /// <param name="cts"><see cref="CancellationTokenSource"/></param>
        /// <returns><see cref="Task"/></returns>
        private async Task HandleDownload(T media, MediaType type, int uploadLimit, int downloadLimit,
                                          IProgress <double> downloadProgress,
                                          IProgress <BandwidthRate> bandwidthRate, IProgress <int> nbSeeds, IProgress <int> nbPeers, torrent_handle handle,
                                          session session, Action buffered, Action cancelled, CancellationTokenSource cts)
        {
            handle.set_upload_limit(uploadLimit * 1024);
            handle.set_download_limit(downloadLimit * 1024);
            handle.set_sequential_download(true);
            var alreadyBuffered = false;
            var bandwidth       = new Progress <BandwidthRate>();
            var prog            = new Progress <double>();

            while (!cts.IsCancellationRequested)
            {
                using (var status = handle.status())
                {
                    var progress = status.progress * 100d;
                    var downRate = Math.Round(status.download_rate / 1024d, 0);
                    var upRate   = Math.Round(status.upload_rate / 1024d, 0);

                    nbSeeds.Report(status.num_seeds);
                    nbPeers.Report(status.num_peers);
                    downloadProgress.Report(progress);
                    bandwidthRate.Report(new BandwidthRate
                    {
                        DownloadRate = downRate,
                        UploadRate   = upRate
                    });

                    ((IProgress <double>)prog).Report(progress);
                    ((IProgress <BandwidthRate>)bandwidth).Report(new BandwidthRate
                    {
                        DownloadRate = downRate,
                        UploadRate   = upRate
                    });

                    handle.flush_cache();
                    if (handle.need_save_resume_data())
                    {
                        handle.save_resume_data(1);
                    }

                    double minimumBuffering;
                    switch (type)
                    {
                    case MediaType.Movie:
                        minimumBuffering = Constants.MinimumMovieBuffering;
                        break;

                    case MediaType.Show:
                        minimumBuffering = Constants.MinimumShowBuffering;
                        break;

                    case MediaType.Unkown:
                        minimumBuffering = Constants.MinimumMovieBuffering;
                        break;

                    default:
                        minimumBuffering = Constants.MinimumMovieBuffering;
                        break;
                    }

                    if (progress >= minimumBuffering && !alreadyBuffered)
                    {
                        buffered.Invoke();
                        foreach (
                            var filePath in
                            Directory
                            .GetFiles(status.save_path, "*.*",
                                      SearchOption.AllDirectories)
                            .Where(s => s.Contains(handle.torrent_file().name()) &&
                                   (s.EndsWith(".mp4") || s.EndsWith(".mkv") ||
                                    s.EndsWith(".mov") || s.EndsWith(".avi")))
                            )
                        {
                            alreadyBuffered = true;
                            media.FilePath  = filePath;
                            BroadcastMediaBuffered(media, prog, bandwidth);

                            break;
                        }

                        if (!alreadyBuffered)
                        {
                            session.remove_torrent(handle, 0);
                            if (type == MediaType.Unkown)
                            {
                                Messenger.Default.Send(
                                    new UnhandledExceptionMessage(
                                        new PopcornException(
                                            "There is no media file in the torrent you dropped in the UI.")));
                            }
                            else
                            {
                                Messenger.Default.Send(
                                    new UnhandledExceptionMessage(
                                        new PopcornException("There is no media file in the torrent.")));
                            }

                            break;
                        }
                    }

                    if (status.is_finished)
                    {
                        session.remove_torrent(handle, 0);
                        break;
                    }

                    try
                    {
                        await Task.Delay(1000, cts.Token);
                    }
                    catch (TaskCanceledException)
                    {
                        cancelled.Invoke();
                        break;
                    }
                }
            }
        }
コード例 #2
0
ファイル: DownloadService.cs プロジェクト: punker76/Popcorn
        /// <summary>
        /// Download media
        /// </summary>
        /// <param name="media">Media file <see cref="IMediaFile"/></param>
        /// <param name="savePath">Save path of the media</param>
        /// <param name="type">Media type <see cref="MediaType"/></param>
        /// <param name="uploadLimit">Upload limit</param>
        /// <param name="downloadLimit">Download limit</param>
        /// <param name="downloadProgress">Download progress</param>
        /// <param name="bandwidthRate">Download rate</param>
        /// <param name="nbSeeds">Number of seeders</param>
        /// <param name="nbPeers">Number of peers</param>
        /// <param name="handle"><see cref="torrent_handle"/></param>
        /// <param name="session"><see cref="session"/></param>
        /// <param name="buffered">Action to execute when media has been buffered</param>
        /// <param name="cancelled">Action to execute when media download has been cancelled</param>
        /// <param name="cts"><see cref="CancellationTokenSource"/></param>
        /// <returns><see cref="Task"/></returns>
        private async Task HandleDownload(T media, string savePath, MediaType type, int uploadLimit, int downloadLimit,
                                          IProgress <double> downloadProgress, IProgress <BandwidthRate> bandwidthRate, IProgress <int> nbSeeds,
                                          IProgress <int> nbPeers,
                                          torrent_handle handle,
                                          session session, Action buffered, Action cancelled, CancellationTokenSource cts)
        {
            handle.set_upload_limit(uploadLimit * 1024);
            handle.set_download_limit(downloadLimit * 1024);
            handle.set_sequential_download(true);
            var alreadyBuffered = false;
            var bandwidth       = new Progress <BandwidthRate>();
            var prog            = new Progress <double>();
            var playingProgress = new Progress <double>();
            var sw = new Stopwatch();

            sw.Start();
            var  mediaIndex = -1;
            long maxSize    = 0;
            var  filePath   = string.Empty;

            while (!cts.IsCancellationRequested)
            {
                using (var status = handle.status())
                {
                    var progress = 0d;
                    if (status.has_metadata)
                    {
                        var numFiles = handle.torrent_file().files().num_files();
                        var totalSizeExceptIgnoredFiles = handle.torrent_file().total_size();
                        handle.flush_cache();
                        if (mediaIndex == -1 || string.IsNullOrEmpty(filePath))
                        {
                            for (var i = 0; i < numFiles; i++)
                            {
                                var currentSize = handle.torrent_file().files().file_size(i);
                                if (currentSize > maxSize)
                                {
                                    maxSize    = currentSize;
                                    mediaIndex = i;
                                }
                            }

                            for (var i = 0; i < numFiles; i++)
                            {
                                if (i != mediaIndex)
                                {
                                    handle.file_priority(i, 0);
                                    totalSizeExceptIgnoredFiles -= handle.torrent_file().files().file_size(i);
                                }
                            }

                            filePath = handle.torrent_file().files().file_path(mediaIndex, savePath);
                        }

                        var fileProgressInBytes = handle.file_progress(1)[mediaIndex];
                        progress = (double)fileProgressInBytes / (double)totalSizeExceptIgnoredFiles * 100d;
                        var downRate = Math.Round(status.download_rate / 1024d, 0);
                        var upRate   = Math.Round(status.upload_rate / 1024d, 0);
                        nbSeeds.Report(status.num_seeds);
                        nbPeers.Report(status.num_peers);
                        downloadProgress.Report(progress);
                        var eta = sw.GetEta(fileProgressInBytes, totalSizeExceptIgnoredFiles);
                        bandwidthRate.Report(new BandwidthRate
                        {
                            DownloadRate = downRate,
                            UploadRate   = upRate,
                            ETA          = eta
                        });

                        ((IProgress <double>)prog).Report(progress);
                        ((IProgress <BandwidthRate>)bandwidth).Report(new BandwidthRate
                        {
                            DownloadRate = downRate,
                            UploadRate   = upRate,
                            ETA          = eta
                        });
                    }

                    double minimumBuffering;
                    switch (type)
                    {
                    case MediaType.Show:
                        minimumBuffering = Constants.MinimumShowBuffering;
                        break;

                    default:
                        minimumBuffering = Constants.MinimumMovieBuffering;
                        break;
                    }

                    if (mediaIndex != -1 && progress >= minimumBuffering && !alreadyBuffered)
                    {
                        buffered.Invoke();
                        if (!string.IsNullOrEmpty(filePath))
                        {
                            alreadyBuffered = true;
                            media.FilePath  = filePath;
                            BroadcastMediaBuffered(media, prog, bandwidth, playingProgress);
                        }

                        if (!alreadyBuffered)
                        {
                            session.remove_torrent(handle, 0);
                            if (type == MediaType.Unkown)
                            {
                                Messenger.Default.Send(
                                    new UnhandledExceptionMessage(
                                        new PopcornException(
                                            LocalizationProviderHelper.GetLocalizedValue <string>(
                                                "NoMediaInDroppedTorrent"))));
                            }
                            else
                            {
                                Messenger.Default.Send(
                                    new UnhandledExceptionMessage(
                                        new PopcornException(
                                            LocalizationProviderHelper.GetLocalizedValue <string>("NoMediaInTorrent"))));
                            }

                            break;
                        }
                    }

                    try
                    {
                        await Task.Delay(1000, cts.Token);
                    }
                    catch (Exception ex) when(ex is TaskCanceledException || ex is ObjectDisposedException)
                    {
                        cancelled.Invoke();
                        sw.Stop();
                        try
                        {
                            session.remove_torrent(handle, 1);
                        }
                        catch (Exception)
                        {
                            // ignored
                        }

                        break;
                    }
                }
            }
        }