diff --git a/Splitter-UI/Services/AutoDecisionService.cs b/Splitter-UI/Services/AutoDecisionService.cs index aed8196..c7c3e64 100644 --- a/Splitter-UI/Services/AutoDecisionService.cs +++ b/Splitter-UI/Services/AutoDecisionService.cs @@ -2,12 +2,12 @@ public sealed class AutoDecisionService(IThumbnailService _thumbnails, IFileProbeService _fileProbe, ILogger _log) : IAutoDecisionService { - public void ApplyAutoDecisions(JobViewModel job) + public void ApplyAutoDecisions(JobViewModel job, CancellationToken token) { - Task.Run(() => Detect(job)); + Task.Run(() => Detect(job, token)); } - private async Task Detect(JobViewModel job) + private async Task Detect(JobViewModel job, CancellationToken token) { try { @@ -16,7 +16,7 @@ public sealed class AutoDecisionService(IThumbnailService _thumbnails, IFileProb job.Mask = "[NAME]_seg[NN].[EXT]"; job.OutputFolder = Path.Combine(Path.GetDirectoryName(job.InputFile)!, "splitter"); - job.Probe = await _fileProbe.ProbeAsync(job.InputFile); + job.Probe = await _fileProbe.ProbeAsync(job.InputFile, token); job.Thumbnail = await _thumbnails.CreateThumbnailAsync(job.InputFile, job.Probe, rotateDegree: job.Rotate); if (job.Probe.Width > job.Probe.Height) @@ -29,7 +29,7 @@ public sealed class AutoDecisionService(IThumbnailService _thumbnails, IFileProb else { var sampler = new VideoRotationSampler(null); - job.Rotate = await sampler.DetectRotationAsync(job.InputFile, job.Probe.Duration); + job.Rotate = await sampler.DetectRotationAsync(job.InputFile, job.Probe.Duration, token); job.Detect = job.Rotate == 0 ? null : "body"; } diff --git a/Splitter-UI/Services/FileProbeService.cs b/Splitter-UI/Services/FileProbeService.cs index 13cb2d5..25980ba 100644 --- a/Splitter-UI/Services/FileProbeService.cs +++ b/Splitter-UI/Services/FileProbeService.cs @@ -2,9 +2,9 @@ public sealed class FileProbeService : IFileProbeService { - public async Task ProbeAsync(string inputFile) + public async Task ProbeAsync(string inputFile, CancellationToken token) { - var res = await Task.Run(() => ProbeVideo.Probe(inputFile, false)); + var res = await Task.Run(() => ProbeVideo.Probe(inputFile, false, token), token); return res; } } diff --git a/Splitter-UI/Services/IAutoDecisionService.cs b/Splitter-UI/Services/IAutoDecisionService.cs index 5793c2c..c760066 100644 --- a/Splitter-UI/Services/IAutoDecisionService.cs +++ b/Splitter-UI/Services/IAutoDecisionService.cs @@ -2,5 +2,5 @@ public interface IAutoDecisionService { - void ApplyAutoDecisions(JobViewModel job); + void ApplyAutoDecisions(JobViewModel job, CancellationToken token); } diff --git a/Splitter-UI/Services/IFileProbeService.cs b/Splitter-UI/Services/IFileProbeService.cs index 8e60265..eee2cf1 100644 --- a/Splitter-UI/Services/IFileProbeService.cs +++ b/Splitter-UI/Services/IFileProbeService.cs @@ -2,5 +2,5 @@ public interface IFileProbeService { - Task ProbeAsync(string inputFile); + Task ProbeAsync(string inputFile, CancellationToken token); } diff --git a/Splitter-UI/ViewModels/FileListViewModel.cs b/Splitter-UI/ViewModels/FileListViewModel.cs index 3fa2a55..abc51b1 100644 --- a/Splitter-UI/ViewModels/FileListViewModel.cs +++ b/Splitter-UI/ViewModels/FileListViewModel.cs @@ -34,7 +34,7 @@ public partial class FileListViewModel : ObservableObject var job = new SingleJob { InputFile = path }; var vm = _factory.Create(job); Files.Add(vm); - _autoDecisionService.ApplyAutoDecisions(vm); + _autoDecisionService.ApplyAutoDecisions(vm, CancellationToken.None); } Selected = Files.LastOrDefault(); diff --git a/Splitter-UI/ViewModels/MainViewModel.cs b/Splitter-UI/ViewModels/MainViewModel.cs index f80db4f..d5463e7 100644 --- a/Splitter-UI/ViewModels/MainViewModel.cs +++ b/Splitter-UI/ViewModels/MainViewModel.cs @@ -15,6 +15,8 @@ public partial class MainViewModel : ViewModelBase [ObservableProperty] private bool _transformMode = false; private ILogger _logger; + private CancellationTokenSource? _cancellationTokenSource; + public MainViewModel( FileListViewModel fileListVM, PreviewPaneViewModel ppVM, @@ -42,12 +44,19 @@ public partial class MainViewModel : ViewModelBase Inspector.Selected = file; }; + Progress.SetMain(this); Inspector.SetMain(this); Inspector.Files = FileList.Files; } + public void Cancel() + { + _cancellationTokenSource?.Cancel(); + } + public async Task Start() { + _cancellationTokenSource = new CancellationTokenSource(); try { StatusBar.StatusText = "Processing…"; @@ -59,23 +68,26 @@ public partial class MainViewModel : ViewModelBase foreach (var file in files) { - var fileJobs = await _processor.GenerateJobs(file.GetJob(), false); + var fileJobs = await _processor.GenerateJobs(file.GetJob(), false, _cancellationTokenSource.Token); jobs.AddRange(fileJobs); } - await _processor.ProcessJobs(jobs, false); + await _processor.ProcessJobs(jobs, false, _cancellationTokenSource.Token); } catch (Exception ex) { // Handle exception StatusBar.StatusText = "Error occurred…"; _logger.LogError($"Error: {ex.Message}"); + _cancellationTokenSource.Cancel(); } finally { StatusBar.StatusText = "Ready…"; StatusBar.Percent = 0; TransformMode = false; + + _cancellationTokenSource?.Dispose(); } } diff --git a/Splitter-UI/ViewModels/ProgressViewModel.cs b/Splitter-UI/ViewModels/ProgressViewModel.cs index 5c96263..85dc8a3 100644 --- a/Splitter-UI/ViewModels/ProgressViewModel.cs +++ b/Splitter-UI/ViewModels/ProgressViewModel.cs @@ -1,5 +1,7 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Splitter_UI.Views; namespace Splitter_UI.ViewModels; @@ -11,6 +13,20 @@ public partial class ProgressViewModel : ObservableObject public ObservableCollection Processes { get; } = []; private Lock _lock = new(); + + private MainViewModel _mainModel = null!; + + [RelayCommand] + private void Cancel() + { + _mainModel.Cancel(); + } + + public void SetMain(MainViewModel mainModel) + { + _mainModel = mainModel; + } + public void ClearProgress(string name, int progressLine) { lock (_lock) diff --git a/Splitter-UI/Views/ProgressView.axaml b/Splitter-UI/Views/ProgressView.axaml index c443a74..4843ae9 100644 --- a/Splitter-UI/Views/ProgressView.axaml +++ b/Splitter-UI/Views/ProgressView.axaml @@ -5,20 +5,20 @@ xmlns:vm="clr-namespace:Splitter_UI.ViewModels" x:DataType="vm:ProgressViewModel"> - - + + + + - - - - - + + + + +