예제 #1
0
        public async Task RequestCache(NicoVideoCacheRequest req)
        {
            var requests = await GetCacheRequest(req.RawVideoId);

            var already = requests.FirstOrDefault(x => x.RawVideoId == req.RawVideoId && x.Quality == req.Quality);

            if (already != null)
            {
                req.RequestAt = already.RequestAt;
            }
            else
            {
                using (var releaser2 = await _CacheRequestProcessingLock.LockAsync())
                {
                    // 画質指定が無い場合はデフォルトのキャッシュ画質を選択
                    if (req.Quality == NicoVideoQuality.Unknown)
                    {
                        req.Quality = _HohoemaApp.UserSettings.CacheSettings.DefaultCacheQuality;
                    }

                    _CacheDownloadPendingVideos.Add(req);

                    Requested?.Invoke(this, req);
                    VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                    {
                        CacheState = NicoVideoCacheState.Pending,
                        Request    = req
                    });
                }
            }

            await SaveDownloadRequestItems();
        }
예제 #2
0
        public async Task <bool> CancelCacheRequest(string rawVideoId, NicoVideoQuality quality)
        {
            bool removed = false;
            var  items   = await GetCacheRequest(rawVideoId);

            var item = items.FirstOrDefault(x => x.Quality == quality);

            if (item != null)
            {
                switch (item.ToCacheState())
                {
                case NicoVideoCacheState.Pending:
                    using (var releaser2 = await _CacheRequestProcessingLock.LockAsync())
                    {
                        var removeTarget = _CacheDownloadPendingVideos.FirstOrDefault(x => x.RawVideoId == rawVideoId && x.Quality == quality);
                        removed = _CacheDownloadPendingVideos.Remove(removeTarget);
                        await SaveDownloadRequestItems();
                    }
                    break;

                case NicoVideoCacheState.Downloading:
                    var canceledReq = await CancelDownload(rawVideoId, quality);

                    await Task.Delay(500);

                    using (var releaser2 = await _CacheRequestProcessingLock.LockAsync())
                    {
                        var removeTarget = _CacheDownloadPendingVideos.FirstOrDefault(x => x.RawVideoId == rawVideoId && x.Quality == quality);
                        removed = _CacheDownloadPendingVideos.Remove(removeTarget);
                        await SaveDownloadRequestItems();
                    }
                    removed = canceledReq != null;
                    break;

                case NicoVideoCacheState.Cached:
                    removed = await DeleteCachedVideo(rawVideoId, quality);

                    break;

                default:
                    break;
                }
            }

            if (removed)
            {
                RequestCanceled?.Invoke(this, item);
                VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                {
                    CacheState = NicoVideoCacheState.NotCacheRequested,
                    Request    = item
                });

                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #3
0
        private async Task <NicoVideoCacheRequest> CancelDownload(string videoId, NicoVideoQuality quality)
        {
            NicoVideoCacheProgress progress = null;

            using (var releaser2 = await _CacheRequestProcessingLock.LockAsync())
            {
                progress = _DownloadOperations.FirstOrDefault(x => x.RawVideoId == videoId && x.Quality == quality);
            }

            if (progress == null)
            {
                return(null);
            }


            await RemoveDownloadOperation(progress);

            VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
            {
                Request    = progress,
                CacheState = NicoVideoCacheState.NotCacheRequested
            });

            return(progress);
        }
예제 #4
0
        public async Task <int> DeleteCachedVideo(string videoId)
        {
            int deletedCount = 0;

            if (_CacheVideos.TryRemove(videoId, out var cachedItems))
            {
                foreach (var target in cachedItems)
                {
                    var result = await target.Delete();

                    if (cachedItems.Count == 0)
                    {
                        _CacheVideos.TryRemove(videoId, out var list);
                        break;
                    }

                    RequestCanceled?.Invoke(this, target);
                    VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                    {
                        CacheState = NicoVideoCacheState.NotCacheRequested,
                        Request    = target
                    });

                    if (result)
                    {
                        deletedCount++;
                    }
                }
            }

            return(deletedCount);
        }
예제 #5
0
        private async void VideoDownloadManager_DownloadCompleted(object sender, NicoVideoCacheRequest request, string filePath)
        {
            var nicoVideo = await GetNicoVideoAsync(request.RawVideoId);

            var div = nicoVideo.GetDividedQualityNicoVideo(request.Quality);

            await div.RestoreCache(filePath);

            VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.Cached);
        }
예제 #6
0
        private async Task RetrieveCacheCompletedVideos()
        {
            var videoFolder = await _HohoemaApp.GetVideoCacheFolder();

            if (videoFolder != null)
            {
                var files = await videoFolder.GetFilesAsync();

                foreach (var file in files)
                {
                    if (file.FileType != ".mp4")
                    {
                        continue;
                    }

                    // ファイル名の最後方にある[]の中身の文字列を取得
                    // (動画タイトルに[]が含まれる可能性に配慮)
                    var match   = NicoVideoIdRegex.Match(file.Name);
                    var id      = match.Value;
                    var quality = NicoVideoQualityFileNameHelper.NicoVideoQualityFromFileNameExtention(file.Name);
                    var info    = new NicoVideoCacheRequest()
                    {
                        RawVideoId = id,
                        Quality    = quality,
                    };

                    if (string.IsNullOrEmpty(id))
                    {
                        continue;
                    }

                    var nicoVideo = await GetNicoVideoAsync(info.RawVideoId, false);

                    var div = nicoVideo.GetDividedQualityNicoVideo(quality);

                    await nicoVideo.RestoreCache(quality, file.Path);

                    await CacheRequested(info);

                    VideoCacheStateChanged?.Invoke(this, info, NicoVideoCacheState.Cached);

                    Debug.Write(".");
                }
            }
        }
예제 #7
0
        public async Task <bool> DeleteCachedVideo(string videoId, NicoVideoQuality quality)
        {
            using (var releaser = await _CacheRequestProcessingLock.LockAsync())
            {
                if (_CacheVideos.TryGetValue(videoId, out var cachedItems))
                {
                    var removeCached = cachedItems.FirstOrDefault(x => x.RawVideoId == videoId && x.Quality == quality);
                    if (removeCached != null)
                    {
                        var result = await removeCached.Delete();

                        if (result)
                        {
                            cachedItems.Remove(removeCached);
                        }

                        if (cachedItems.Count == 0)
                        {
                            _CacheVideos.TryRemove(videoId, out var list);
                        }

                        RequestCanceled?.Invoke(this, removeCached);
                        VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                        {
                            CacheState = NicoVideoCacheState.NotCacheRequested,
                            Request    = removeCached
                        });


                        return(result);
                    }
                }

                return(false);
            }
        }
예제 #8
0
        // 次のキャッシュダウンロードを試行
        // ダウンロード用の本数
        private async Task TryNextCacheRequestedVideoDownload()
        {
            if (State != CacheManagerState.Running)
            {
                return;
            }

            NicoVideoCacheRequest nextDownloadItem = null;

            using (var releaser = await _CacheRequestProcessingLock.LockAsync())
            {
                while (CanAddDownloadLine)
                {
                    if (_DownloadOperations.Count == 0)
                    {
                        nextDownloadItem = _CacheDownloadPendingVideos
                                           .FirstOrDefault();
                    }

                    if (nextDownloadItem == null)
                    {
                        break;
                    }

                    if (_DownloadOperations.Any(x => x.RawVideoId == nextDownloadItem.RawVideoId && x.Quality == nextDownloadItem.Quality))
                    {
                        _CacheDownloadPendingVideos.Remove(nextDownloadItem);
                        break;
                    }

                    Debug.WriteLine($"キャッシュ準備を開始: {nextDownloadItem.RawVideoId} {nextDownloadItem.Quality}");

                    // 動画ダウンロードURLを取得
                    var nicoVideo = new NicoVideo(nextDownloadItem.RawVideoId, _HohoemaApp.ContentProvider, _HohoemaApp.NiconicoContext, _HohoemaApp.CacheManager);
                    var videoInfo = await _HohoemaApp.ContentProvider.GetNicoVideoInfo(nextDownloadItem.RawVideoId);

                    // DownloadSessionを保持して、再生完了時にDisposeさせる必要がある
                    var downloadSession = await nicoVideo.CreateVideoStreamingSession(nextDownloadItem.Quality, forceDownload : true);

                    var uri = await downloadSession.GetDownloadUrlAndSetupDonwloadSession();

                    var downloader = new BackgroundDownloader()
                    {
                        TransferGroup = _NicoCacheVideoBGTransferGroup
                    };

                    downloader.SuccessToastNotification = MakeSuccessToastNotification(videoInfo);
                    downloader.FailureToastNotification = MakeFailureToastNotification(videoInfo);

                    // 保存先ファイルの確保
                    var filename = VideoCacheManager.MakeCacheVideoFileName(
                        videoInfo.Title,
                        nextDownloadItem.RawVideoId,
                        videoInfo.MovieType,
                        downloadSession.Quality
                        );

                    var videoFolder = await _HohoemaApp.GetVideoCacheFolder();

                    var videoFile = await videoFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);

                    // ダウンロード操作を作成
                    var operation = downloader.CreateDownload(uri, videoFile);

                    var progress = new NicoVideoCacheProgress(nextDownloadItem, operation, downloadSession);
                    await AddDownloadOperation(progress);


                    Debug.WriteLine($"キャッシュ準備完了: {nextDownloadItem.RawVideoId} {nextDownloadItem.Quality}");


                    // ダウンロードを開始

                    /*
                     * if (Helpers.ApiContractHelper.IsFallCreatorsUpdateAvailable)
                     * {
                     *  operation.IsRandomAccessRequired = true;
                     * }
                     */

                    var action = operation.StartAsync();
                    action.Progress = OnDownloadProgress;
                    var task = action.AsTask();
                    TaskIdToCacheProgress.Add(task.Id, progress);
                    var _ = task.ContinueWith(OnDownloadCompleted);



                    VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                    {
                        CacheState = NicoVideoCacheState.Downloading,
                        Request    = progress
                    });

                    Debug.WriteLine($"キャッシュ開始: {nextDownloadItem.RawVideoId} {nextDownloadItem.Quality}");

                    SendUpdatableToastWithProgress(videoInfo.Title, nextDownloadItem);


                    // DL作業を作成できたらDL待ちリストから削除
                    _CacheDownloadPendingVideos.Remove(nextDownloadItem);

                    await SaveDownloadRequestItems();
                }
            }
        }
예제 #9
0
        private async Task RetrieveCacheCompletedVideos()
        {
            var videoFolder = await _HohoemaApp.GetVideoCacheFolder();

            if (videoFolder != null)
            {
                var files = await videoFolder.GetFilesAsync();

                foreach (var file in files)
                {
                    if (!(file.FileType == ".mp4" || file.FileType == ".flv"))
                    {
                        continue;
                    }

                    // ファイル名の最後方にある[]の中身の文字列を取得
                    // (動画タイトルに[]が含まれる可能性に配慮)
                    var match = NicoVideoIdRegex.Match(file.Name);
                    var id    = match.Groups[1]?.Value;
                    NicoVideoQuality quality = NicoVideoQuality.Unknown;
                    if (string.IsNullOrEmpty(id))
                    {
                        // 外部キャッシュとして取得可能かをチェック
                        match = ExternalCachedNicoVideoIdRegex.Match(file.Name);

                        if (match.Groups.Count > 0)
                        {
                            id = match.Groups[match.Groups.Count - 1].Value;
                        }

                        // 動画IDを抽出不可だった場合はスキップ
                        if (string.IsNullOrEmpty(id))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        quality = VideoCacheManager.GetQualityFromFileName(file.Name);
                    }

                    var info = new NicoVideoCacheInfo()
                    {
                        RawVideoId = id,
                        Quality    = quality,
                        FilePath   = file.Path,
                        RequestAt  = file.DateCreated.DateTime
                    };


                    _CacheVideos.AddOrUpdate(info.RawVideoId,
                                             (x) =>
                    {
                        return(new List <NicoVideoCacheInfo>()
                        {
                            info
                        });
                    },
                                             (x, y) =>
                    {
                        var tempinfo = y.FirstOrDefault(z => z.Quality == info.Quality);
                        if (tempinfo == null)
                        {
                            y.Add(info);
                        }
                        else
                        {
                            tempinfo.RequestAt = info.RequestAt;
                            tempinfo.FilePath  = info.FilePath;
                        }
                        return(y);
                    });

                    VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                    {
                        Request    = info,
                        CacheState = NicoVideoCacheState.Cached
                    });

                    Debug.Write(".");
                }
            }
        }
예제 #10
0
        // ダウンロード完了
        private async Task OnDownloadCompleted(Task <DownloadOperation> prevTask)
        {
            // 進捗付きトースト表示を削除
            RemoveProgressToast();

            var progress = TaskIdToCacheProgress[prevTask.Id];

            await RemoveDownloadOperation(progress);

            TaskIdToCacheProgress.Remove(prevTask.Id);

            if (prevTask.IsFaulted)
            {
                Debug.WriteLine("キャッシュ失敗");


                VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                {
                    Request = new NicoVideoCacheRequest()
                    {
                        RawVideoId           = progress.RawVideoId,
                        RequestAt            = progress.RequestAt,
                        Quality              = progress.Quality,
                        IsRequireForceUpdate = progress.IsRequireForceUpdate
                    },
                    CacheState = NicoVideoCacheState.Pending
                });

                return;
            }

            Debug.WriteLine("キャッシュ完了");

            if (prevTask.Result != null)
            {
                var op = progress.DownloadOperation;

                if (op.Progress.Status == BackgroundTransferStatus.Completed)
                {
                    if (op.Progress.TotalBytesToReceive == op.Progress.BytesReceived)
                    {
                        Debug.WriteLine("キャッシュ済み: " + op.ResultFile.Name);
                        var cacheInfo = new NicoVideoCacheInfo(progress, op.ResultFile.Path);

                        _CacheVideos.AddOrUpdate(cacheInfo.RawVideoId,
                                                 (x) =>
                        {
                            return(new List <NicoVideoCacheInfo>()
                            {
                                cacheInfo
                            });
                        },
                                                 (x, y) =>
                        {
                            var tempinfo = y.FirstOrDefault(z => z.Quality == cacheInfo.Quality);
                            if (tempinfo == null)
                            {
                                y.Add(cacheInfo);
                            }
                            else
                            {
                                tempinfo.RequestAt = cacheInfo.RequestAt;
                                tempinfo.FilePath  = cacheInfo.FilePath;
                            }
                            return(y);
                        });

                        VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                        {
                            Request    = progress,
                            CacheState = NicoVideoCacheState.Cached
                        });
                    }
                    else
                    {
                        Debug.WriteLine("キャッシュキャンセル: " + op.ResultFile.Name);

                        VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                        {
                            Request = new NicoVideoCacheRequest()
                            {
                                RawVideoId           = progress.RawVideoId,
                                RequestAt            = progress.RequestAt,
                                Quality              = progress.Quality,
                                IsRequireForceUpdate = progress.IsRequireForceUpdate
                            },
                            CacheState = NicoVideoCacheState.Pending
                        });
                    }
                }
                else
                {
                    Debug.WriteLine($"キャッシュ失敗: {op.ResultFile.Name} (再ダウンロードします)");
                    VideoCacheStateChanged?.Invoke(this, new VideoCacheStateChangedEventArgs()
                    {
                        Request = new NicoVideoCacheRequest()
                        {
                            RawVideoId           = progress.RawVideoId,
                            RequestAt            = progress.RequestAt,
                            Quality              = progress.Quality,
                            IsRequireForceUpdate = progress.IsRequireForceUpdate
                        },
                        CacheState = NicoVideoCacheState.Pending
                    });
                }
            }
        }
예제 #11
0
 private void VideoDownloadManager_DownloadCanceled(object sender, NicoVideoCacheRequest request)
 {
     VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.Pending);
 }
예제 #12
0
 private void VideoDownloadManager_DownloadStarted(object sender, NicoVideoCacheRequest request, DownloadOperation op)
 {
     VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.Downloading);
 }
예제 #13
0
        private async void VideoDownloadManager_RequestCanceled(object sender, NicoVideoCacheRequest request)
        {
            VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.NotCacheRequested);

            await CacheRequestCanceled(request);
        }