diff --git a/VDownload.Core/VDownload.Core.Strings/Strings/en-US/HomeDownloadsViewResources.resw b/VDownload.Core/VDownload.Core.Strings/Strings/en-US/HomeDownloadsViewResources.resw index f6b9601..07e88ad 100644 --- a/VDownload.Core/VDownload.Core.Strings/Strings/en-US/HomeDownloadsViewResources.resw +++ b/VDownload.Core/VDownload.Core.Strings/Strings/en-US/HomeDownloadsViewResources.resw @@ -117,6 +117,21 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + No internet connection. Try again later. + + + Error + + + Downloading timeout. Check your internet connection and try again later. + + + FFmpeg exited with error. + + + No FFmpeg executables found. Check path in settings and try again. + Cancelled diff --git a/VDownload.Core/VDownload.Core.Tasks/DownloadTask.cs b/VDownload.Core/VDownload.Core.Tasks/DownloadTask.cs index 05fa933..f19fd9b 100644 --- a/VDownload.Core/VDownload.Core.Tasks/DownloadTask.cs +++ b/VDownload.Core/VDownload.Core.Tasks/DownloadTask.cs @@ -13,6 +13,9 @@ using System.IO; using VDownload.Services.UI.Notifications; using VDownload.Services.UI.StringResources; using System.Collections.Generic; +using System.Net.Http; +using Instances.Exceptions; +using FFMpegCore.Exceptions; namespace VDownload.Core.Tasks { @@ -140,7 +143,11 @@ namespace VDownload.Core.Tasks await _settingsService.Load(); - string tempDirectory = $"{_settingsService.Data.Common.Temp.Directory}\\{_configurationService.Common.Path.Temp.TasksDirectory}\\{Id}"; + string tempDirectory = $"{_settingsService.Data.Common.Temp.Directory}\\{_configurationService.Common.Path.Temp.TasksDirectory}\\{Guid.NewGuid()}"; + if (Directory.Exists(tempDirectory)) + { + Directory.Delete(tempDirectory, true); + } Directory.CreateDirectory(tempDirectory); List content = new List() @@ -180,10 +187,11 @@ namespace VDownload.Core.Tasks .JoinProgressReporter(onProgressProcessing, downloadResult.NewDuration); await ffmpegBuilder.RunAsync(downloadResult.File, outputPath); + StorageFile outputFile = await StorageFile.GetFileFromPathAsync(outputPath); + UpdateStatusWithDispatcher(DownloadTaskStatus.Finalizing); - string destination = $"{DownloadOptions.Directory}\\{DownloadOptions.Filename}.{DownloadOptions.Extension}"; - File.Copy(outputPath, destination, true); + await Finalizing(outputFile); UpdateStatusWithDispatcher(DownloadTaskStatus.EndedSuccessfully); @@ -199,7 +207,26 @@ namespace VDownload.Core.Tasks } catch (Exception ex) { - UpdateErrorWithDispatcher(ex.Message); + string message; + + if (ex is TaskCanceledException || ex is HttpRequestException) + { + message = _stringResourcesService.HomeDownloadsViewResources.Get("ErrorDownloadingTimeout"); + } + else if (ex is InstanceFileNotFoundException) + { + message = _stringResourcesService.HomeDownloadsViewResources.Get("ErrorFFmpegPath"); + } + else if (ex is FFMpegException) + { + message = _stringResourcesService.HomeDownloadsViewResources.Get("ErrorFFmpeg"); + } + else + { + message = ex.Message; + } + + UpdateErrorWithDispatcher(message); UpdateStatusWithDispatcher(DownloadTaskStatus.EndedUnsuccessfully); if (_settingsService.Data.Common.Notifications.OnUnsuccessful) @@ -218,11 +245,19 @@ namespace VDownload.Core.Tasks } } - private void UpdateStatusWithDispatcher(DownloadTaskStatus status) => _dispatcherQueue.TryEnqueue(() => Status = status); + protected async Task Finalizing(StorageFile outputFile) + { + StorageFolder destination = await StorageFolder.GetFolderFromPathAsync(DownloadOptions.Directory); - private void UpdateProgressWithDispatcher(double progress) => _dispatcherQueue.TryEnqueue(() => Progress = progress); + string filename = $"{DownloadOptions.Filename}.{DownloadOptions.Extension}"; + await outputFile.CopyAsync(destination, filename, NameCollisionOption.ReplaceExisting); + } - private void UpdateErrorWithDispatcher(string message) => _dispatcherQueue.TryEnqueue(() => Error = message); + protected void UpdateStatusWithDispatcher(DownloadTaskStatus status) => _dispatcherQueue.TryEnqueue(() => Status = status); + + protected void UpdateProgressWithDispatcher(double progress) => _dispatcherQueue.TryEnqueue(() => Progress = progress); + + protected void UpdateErrorWithDispatcher(string message) => _dispatcherQueue.TryEnqueue(() => Error = message); #endregion } diff --git a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs index cf82579..7d03e7f 100644 --- a/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs +++ b/VDownload.Core/VDownload.Core.ViewModels/Home/HomeDownloadsViewModel.cs @@ -68,6 +68,14 @@ namespace VDownload.Core.ViewModels.Home ]; if (idleStatuses.Contains(task.Status)) { + if (!NetworkHelper.Instance.ConnectionInformation.IsInternetAvailable) + { + string title = _stringResourcesService.HomeDownloadsViewResources.Get("DialogErrorTitle"); + string message = _stringResourcesService.HomeDownloadsViewResources.Get("DialogErrorMessageNoInternetConnection"); + await _dialogsService.ShowOk(title, message); + return; + } + bool continueEnqueue = true; if (NetworkHelper.Instance.ConnectionInformation.IsInternetOnMeteredConnection) { diff --git a/VDownload.Services/VDownload.Services.Utility/VDownload.Services.Utility.FFmpeg/FFmpegBuilder.cs b/VDownload.Services/VDownload.Services.Utility/VDownload.Services.Utility.FFmpeg/FFmpegBuilder.cs index fc635da..33ea457 100644 --- a/VDownload.Services/VDownload.Services.Utility/VDownload.Services.Utility.FFmpeg/FFmpegBuilder.cs +++ b/VDownload.Services/VDownload.Services.Utility/VDownload.Services.Utility.FFmpeg/FFmpegBuilder.cs @@ -40,6 +40,9 @@ namespace VDownload.Services.Utility.FFmpeg protected string _inputFile; protected string _outputFile; + protected string _audioCodec; + protected string _videoCodec; + protected FFOptions _options; #endregion @@ -103,6 +106,10 @@ namespace VDownload.Services.Utility.FFmpeg _inputFile = inputFile; _outputFile = outputFile; + IMediaAnalysis analysis = await FFProbe.AnalyseAsync(_inputFile, _options); + _audioCodec = analysis.AudioStreams.First().CodecName; + _videoCodec = analysis.VideoStreams.First().CodecName; + FFMpegArgumentProcessor ffmpegArguments = FFMpegArguments.FromFileInput(inputFile, true, async (options) => await BuildInputArgumentOptions(options)) .OutputToFile(outputFile, true, async (options) => await BuildOutputArgumentOptions(options)); @@ -154,17 +161,13 @@ namespace VDownload.Services.Utility.FFmpeg private async Task BuildOutputArgumentOptions(FFMpegArgumentOptions options) { - IMediaAnalysis analysis = await FFProbe.AnalyseAsync(_inputFile, _options); - string audioCodec = analysis.AudioStreams.First().CodecName; - string videoCodec = analysis.VideoStreams.First().CodecName; - string extension = Path.GetExtension(_outputFile).Replace(".", string.Empty); Data.Configuration.Models.Muxer muxer = _configurationService.Common.Processing.Muxers.First(x => x.Extension == extension); if (_mediaType != MediaType.OnlyAudio) { IEnumerable availableCodecs = muxer.VideoCodecs; - string selectedCodec = availableCodecs.Contains(videoCodec) ? "copy" : availableCodecs.First(); + string selectedCodec = availableCodecs.Contains(_videoCodec) ? "copy" : availableCodecs.First(); options.WithCustomArgument($"-vcodec {selectedCodec}"); } else @@ -175,7 +178,7 @@ namespace VDownload.Services.Utility.FFmpeg if (_mediaType != MediaType.OnlyVideo) { IEnumerable availableCodecs = muxer.AudioCodecs; - string selectedCodec = availableCodecs.Contains(audioCodec) ? "copy" : availableCodecs.First(); + string selectedCodec = availableCodecs.Contains(_audioCodec) ? "copy" : availableCodecs.First(); options.WithCustomArgument($"-acodec {selectedCodec}"); } else diff --git a/VDownload.Sources/VDownload.Sources.Twitch/VDownload.Sources.Twitch.Models/TwitchVodStream.cs b/VDownload.Sources/VDownload.Sources.Twitch/VDownload.Sources.Twitch.Models/TwitchVodStream.cs index 5c00f2f..2e052c2 100644 --- a/VDownload.Sources/VDownload.Sources.Twitch/VDownload.Sources.Twitch.Models/TwitchVodStream.cs +++ b/VDownload.Sources/VDownload.Sources.Twitch/VDownload.Sources.Twitch.Models/TwitchVodStream.cs @@ -145,15 +145,17 @@ namespace VDownload.Sources.Twitch.Models { token.ThrowIfCancellationRequested(); - using (FileStream inputStream = File.OpenRead(path)) + using (FileStream inputStream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { inputStream.CopyTo(outputStream); } - - if (deleteSource) - { - File.Delete(path); - } + } + } + foreach (string item in sourceFiles) + { + if (deleteSource) + { + File.Delete(item); } } } @@ -184,10 +186,7 @@ namespace VDownload.Sources.Twitch.Models int retriesCount = 0; while (true) { - if (token.IsCancellationRequested) - { - return; - } + token.ThrowIfCancellationRequested(); try { byte[] data = await _httpClient.GetByteArrayAsync(chunk.Url, token); @@ -195,10 +194,6 @@ namespace VDownload.Sources.Twitch.Models onTaskEndSuccessfully.Invoke(); return; } - catch (OperationCanceledException) - { - return; - } catch (Exception ex) when (ex is HttpRequestException || ex is TaskCanceledException) { if (_settingsService.Data.Twitch.Vod.ChunkDownloadingError.Retry && retriesCount < _settingsService.Data.Twitch.Vod.ChunkDownloadingError.RetriesCount)