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(); }
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); } }
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); }
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); }
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); }
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("."); } } }
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); } }
// 次のキャッシュダウンロードを試行 // ダウンロード用の本数 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(); } } }
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("."); } } }
// ダウンロード完了 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 }); } } }
private void VideoDownloadManager_DownloadCanceled(object sender, NicoVideoCacheRequest request) { VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.Pending); }
private void VideoDownloadManager_DownloadStarted(object sender, NicoVideoCacheRequest request, DownloadOperation op) { VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.Downloading); }
private async void VideoDownloadManager_RequestCanceled(object sender, NicoVideoCacheRequest request) { VideoCacheStateChanged?.Invoke(this, request, NicoVideoCacheState.NotCacheRequested); await CacheRequestCanceled(request); }