mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-21 16:12:01 +00:00
Video processing implemented.
This commit is contained in:
parent
9cdf611ec8
commit
af363ebb9a
@ -8,7 +8,9 @@ namespace Splitter_UI;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
private readonly ServiceProvider _provider;
|
||||
private readonly ServiceProvider _provider = null!;
|
||||
|
||||
public App() { }
|
||||
|
||||
public App(ServiceProvider provider)
|
||||
{
|
||||
|
||||
15
Splitter-UI/Converters/BoolInvertConverter.cs
Normal file
15
Splitter-UI/Converters/BoolInvertConverter.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Splitter_UI.Converters;
|
||||
|
||||
public sealed class BoolInvertConverter : IValueConverter
|
||||
{
|
||||
public static readonly BoolInvertConverter Instance = new();
|
||||
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
=> value is bool b ? !b : value;
|
||||
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
=> value is bool b ? !b : value;
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Media;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Splitter_UI.Converters;
|
||||
|
||||
@ -30,6 +30,7 @@ internal sealed class Program
|
||||
services.AddTransient<PreviewPaneViewModel>();
|
||||
services.AddTransient<InspectorPaneViewModel>();
|
||||
services.AddSingleton<StatusBarViewModel>();
|
||||
services.AddSingleton<ProgressViewModel>();
|
||||
services.AddSingleton<LogPaneViewModel>(logPaveVM);
|
||||
services.AddSingleton<ILogService>(logPaveVM);
|
||||
|
||||
@ -48,6 +49,7 @@ internal sealed class Program
|
||||
};
|
||||
});
|
||||
services.AddSingleton<ILogger, GlobalLogger>();
|
||||
services.AddSingleton<IJobProcessor, JobProcessor>();
|
||||
|
||||
// Domain services (your pipeline)
|
||||
services.AddTransient<IFileProbeService, FileProbeService>();
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
namespace Splitter_UI.Services;
|
||||
|
||||
internal class GlobalLogger(ILogService _logService, StatusBarViewModel _statusBar) : ILogger
|
||||
internal class GlobalLogger(ILogService _logService, StatusBarViewModel _statusBar, ProgressViewModel _progress) : ILogger
|
||||
{
|
||||
public void ClearProgress(string name, int progressLine)
|
||||
{
|
||||
if (progressLine == 0)
|
||||
_statusBar.Percent = 0;
|
||||
else
|
||||
_progress.ClearProgress(name, progressLine-1);
|
||||
}
|
||||
public void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed)
|
||||
{
|
||||
if (progressLine == 0)
|
||||
_statusBar.Percent = progress;
|
||||
else
|
||||
_progress.DrawProgress(name, progressLine - 1, progress, eta, speed);
|
||||
}
|
||||
|
||||
public void Log(string prefix, ConsoleColor color, string msg)
|
||||
|
||||
@ -39,4 +39,21 @@ public partial class FileListViewModel : ObservableObject
|
||||
|
||||
Selected = Files.LastOrDefault();
|
||||
}
|
||||
|
||||
internal void DeleteSelected()
|
||||
{
|
||||
if (SelectedFiles.Any())
|
||||
{
|
||||
var toDelete = SelectedFiles.ToList();
|
||||
foreach (var item in toDelete)
|
||||
Files.Remove(item);
|
||||
}
|
||||
else if ( Selected != null)
|
||||
{
|
||||
var sel = Selected;
|
||||
Files.Remove(sel);
|
||||
}
|
||||
|
||||
Selected = Files.LastOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,13 @@ public partial class InspectorPaneViewModel : ObservableObject
|
||||
"face", "body", "none"
|
||||
];
|
||||
|
||||
[RelayCommand]
|
||||
private void TransformAll()
|
||||
{
|
||||
_ = _main.Start();
|
||||
}
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private void ApplyOverrides()
|
||||
{
|
||||
@ -43,12 +50,16 @@ public partial class InspectorPaneViewModel : ObservableObject
|
||||
public IRelayCommand RotateLeftCommand { get; }
|
||||
public IRelayCommand RotateRightCommand { get; }
|
||||
|
||||
private MainViewModel _main = null!;
|
||||
|
||||
public InspectorPaneViewModel()
|
||||
{
|
||||
RotateLeftCommand = new RelayCommand(() => AdjustRotation(-90));
|
||||
RotateRightCommand = new RelayCommand(() => AdjustRotation(+90));
|
||||
}
|
||||
|
||||
public void SetMain(MainViewModel main) => _main = main;
|
||||
|
||||
private void AdjustRotation(int delta)
|
||||
{
|
||||
if ( Selected == null)
|
||||
|
||||
@ -11,7 +11,9 @@ namespace Splitter_UI.ViewModels;
|
||||
public partial class JobViewModel : ObservableObject
|
||||
{
|
||||
private SingleJob Job { get; }
|
||||
|
||||
|
||||
public SingleJob GetJob() => Job;
|
||||
|
||||
[ObservableProperty] private VideoInfo? _probe;
|
||||
[ObservableProperty] private PreviewData? _preview = new(null, [], null, new(0.5f, 0.5f));
|
||||
[ObservableProperty] private Bitmap? _thumbnail;
|
||||
@ -366,4 +368,5 @@ public partial class JobViewModel : ObservableObject
|
||||
{
|
||||
Task.Run(CreatePreview);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Splitter_UI.ViewModels;
|
||||
|
||||
@ -9,41 +9,74 @@ public partial class MainViewModel : ViewModelBase
|
||||
public InspectorPaneViewModel Inspector { get; }
|
||||
public StatusBarViewModel StatusBar { get; }
|
||||
public LogPaneViewModel LogPane { get; }
|
||||
public ProgressViewModel Progress { get; }
|
||||
private IJobProcessor _processor = null!;
|
||||
|
||||
[ObservableProperty] private bool _transformMode = false;
|
||||
private ILogger _logger;
|
||||
|
||||
public MainViewModel(
|
||||
IFileJobFactory fileJobFactory,
|
||||
IAutoDecisionService autoDecisionService,
|
||||
FileListViewModel fileListVM,
|
||||
PreviewPaneViewModel ppVM,
|
||||
InspectorPaneViewModel iVM,
|
||||
LogPaneViewModel lpVM,
|
||||
StatusBarViewModel sbVM
|
||||
StatusBarViewModel sbVM,
|
||||
ProgressViewModel pVM,
|
||||
IJobProcessor processor,
|
||||
ILogger logger
|
||||
)
|
||||
{
|
||||
FileList = new FileListViewModel(fileJobFactory, autoDecisionService);
|
||||
Preview = ppVM;
|
||||
Inspector = iVM;
|
||||
LogPane = lpVM;
|
||||
StatusBar = sbVM;
|
||||
// Wire selection → preview + inspector
|
||||
FileList = fileListVM;
|
||||
Preview = ppVM;
|
||||
Inspector = iVM;
|
||||
LogPane = lpVM;
|
||||
StatusBar = sbVM;
|
||||
Progress = pVM;
|
||||
_processor = processor;
|
||||
_logger = logger;
|
||||
|
||||
// Wire selection -> preview + inspector
|
||||
FileList.SelectedFileChanged += file =>
|
||||
{
|
||||
Preview.Selected = file;
|
||||
Inspector.Selected = file;
|
||||
};
|
||||
|
||||
Inspector.SetMain(this);
|
||||
Inspector.Files = FileList.Files;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Start()
|
||||
public async Task Start()
|
||||
{
|
||||
StatusBar.StatusText = "Processing…";
|
||||
// call IProcessingService here
|
||||
try
|
||||
{
|
||||
StatusBar.StatusText = "Processing…";
|
||||
StatusBar.Percent = 0;
|
||||
TransformMode = true;
|
||||
|
||||
var files = FileList.Files.ToList();
|
||||
var jobs = new List<SingleTask>();
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
var fileJobs = await _processor.GenerateJobs(file.GetJob(), false);
|
||||
jobs.AddRange(fileJobs);
|
||||
}
|
||||
|
||||
await _processor.ProcessJobs(jobs, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exception
|
||||
StatusBar.StatusText = "Error occurred…";
|
||||
_logger.LogError($"Error: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
StatusBar.StatusText = "Ready…";
|
||||
StatusBar.Percent = 0;
|
||||
TransformMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Stop()
|
||||
{
|
||||
StatusBar.StatusText = "Stopped";
|
||||
}
|
||||
}
|
||||
|
||||
43
Splitter-UI/ViewModels/ProgressViewModel.cs
Normal file
43
Splitter-UI/ViewModels/ProgressViewModel.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Splitter_UI.ViewModels;
|
||||
|
||||
public record ProgressInfo(string Name, int ProgressLine, double Progress, TimeSpan Eta, double Speed);
|
||||
|
||||
public partial class ProgressViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty] private int _numberOfProcesses = 0;
|
||||
public ObservableCollection<ProgressInfo> Processes { get; } = [];
|
||||
|
||||
private Lock _lock = new();
|
||||
public void ClearProgress(string name, int progressLine)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (progressLine < 0 || progressLine > Processes.Count)
|
||||
return;
|
||||
|
||||
NumberOfProcesses -= 1;
|
||||
Processes[progressLine] = new ProgressInfo("", progressLine, 0, TimeSpan.Zero, 0);
|
||||
}
|
||||
}
|
||||
public void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (progressLine < 0)
|
||||
return;
|
||||
|
||||
while (Processes.Count <= progressLine)
|
||||
{
|
||||
Processes.Add(new ProgressInfo("", Processes.Count, 0, TimeSpan.Zero, 0));
|
||||
}
|
||||
|
||||
if (Processes[progressLine].Name == "")
|
||||
NumberOfProcesses += 1;
|
||||
Processes[progressLine] = new ProgressInfo(name, progressLine, progress, eta, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,4 @@ public partial class StatusBarViewModel : ObservableObject
|
||||
[ObservableProperty]
|
||||
private double _percent;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _threadInfo = "Threads: 0/0";
|
||||
}
|
||||
|
||||
@ -5,7 +5,9 @@
|
||||
xmlns:views="clr-namespace:Splitter_UI.Views"
|
||||
xmlns:conv="clr-namespace:Splitter_UI.Converters"
|
||||
x:Class="Splitter_UI.Views.FileListView"
|
||||
x:DataType="vm:FileListViewModel">
|
||||
x:DataType="vm:FileListViewModel"
|
||||
KeyDown="OnKeyDown"
|
||||
Focusable="True">
|
||||
|
||||
<UserControl.Resources>
|
||||
<conv:ZeroToBoolConverter x:Key="ZeroToBoolConverter"/>
|
||||
|
||||
@ -21,6 +21,14 @@ public partial class FileListView : UserControl
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Delete)
|
||||
{
|
||||
if (DataContext is FileListViewModel vm)
|
||||
vm.DeleteSelected();
|
||||
}
|
||||
}
|
||||
private void OnDragEnter(object? sender, DragEventArgs e)
|
||||
{
|
||||
IsDragActive = true;
|
||||
|
||||
@ -147,10 +147,21 @@ x:DataType="vm:InspectorPaneViewModel">
|
||||
<TextBox Text="{Binding Selected.PassthroughText}" Width="260"/>
|
||||
</StackPanel>
|
||||
|
||||
<Button Content="Apply to Selected"
|
||||
Command="{Binding ApplyOverridesCommand}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,10,0,0"/>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
Spacing="8"
|
||||
Margin="0,10,0,0">
|
||||
|
||||
<Button Content="Apply to Selected"
|
||||
Command="{Binding ApplyOverridesCommand}"/>
|
||||
|
||||
<Button Content="Transform all"
|
||||
Background="#AA0000"
|
||||
Foreground="White"
|
||||
Command="{Binding TransformAllCommand}"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@ -3,12 +3,18 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:views="clr-namespace:Splitter_UI.Views"
|
||||
xmlns:vm="clr-namespace:Splitter_UI.ViewModels"
|
||||
xmlns:conv="clr-namespace:Splitter_UI.Converters"
|
||||
x:Class="Splitter_UI.Views.MainWindow"
|
||||
x:DataType="vm:MainViewModel"
|
||||
x:Name="Root"
|
||||
Width="1400"
|
||||
Height="950"
|
||||
Title="Splitter UI">
|
||||
|
||||
<Window.Resources>
|
||||
<conv:BoolInvertConverter x:Key="BoolInvertConverter"/>
|
||||
</Window.Resources>
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Status Bar -->
|
||||
@ -19,21 +25,28 @@
|
||||
<views:LogPane DockPanel.Dock="Bottom" Height="150"
|
||||
DataContext="{Binding LogPane}" />
|
||||
|
||||
<!-- Main Content -->
|
||||
<Grid ColumnDefinitions="2*,3*,430">
|
||||
<Grid>
|
||||
<!-- Main Content -->
|
||||
<Grid ColumnDefinitions="2*,3*,430" IsVisible="{Binding TransformMode, Converter={StaticResource BoolInvertConverter}}">
|
||||
|
||||
<!-- File List -->
|
||||
<views:FileListView Grid.Column="0"
|
||||
DataContext="{Binding FileList}" />
|
||||
<!-- File List -->
|
||||
<views:FileListView Grid.Column="0"
|
||||
DataContext="{Binding FileList}" />
|
||||
|
||||
<!-- Preview -->
|
||||
<views:PreviewPane Grid.Column="1"
|
||||
DataContext="{Binding Preview}" />
|
||||
<!-- Preview -->
|
||||
<views:PreviewPane Grid.Column="1"
|
||||
DataContext="{Binding Preview}" />
|
||||
|
||||
<!-- Inspector -->
|
||||
<views:InspectorPane Grid.Column="2"
|
||||
DataContext="{Binding Inspector}" />
|
||||
<!-- Inspector -->
|
||||
<views:InspectorPane Grid.Column="2"
|
||||
DataContext="{Binding Inspector}" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- Progress view (replaces entire grid) -->
|
||||
<views:ProgressView
|
||||
DataContext="{Binding Progress}"
|
||||
IsVisible="{Binding #Root.DataContext.TransformMode}"/>
|
||||
</Grid>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
50
Splitter-UI/Views/ProgressView.axaml
Normal file
50
Splitter-UI/Views/ProgressView.axaml
Normal file
@ -0,0 +1,50 @@
|
||||
<UserControl
|
||||
x:Class="Splitter_UI.Views.ProgressView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:Splitter_UI.ViewModels"
|
||||
x:DataType="vm:ProgressViewModel">
|
||||
|
||||
<Border Background="#111" Padding="8">
|
||||
<ItemsControl ItemsSource="{Binding Processes}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:ProgressInfo">
|
||||
<Grid ColumnDefinitions="2*,3*,Auto,Auto"
|
||||
Margin="0,2">
|
||||
|
||||
<!-- Name -->
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding Name}"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"/>
|
||||
|
||||
<!-- Progress bar -->
|
||||
<ProgressBar Grid.Column="1"
|
||||
Height="12"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
Value="{Binding Progress}"
|
||||
Margin="8,0"/>
|
||||
|
||||
<!-- ETA -->
|
||||
<TextBlock Grid.Column="2"
|
||||
Width="70"
|
||||
Text="{Binding Eta, StringFormat={}{0:hh\\:mm\\:ss}}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0"
|
||||
FontSize="12"/>
|
||||
|
||||
<!-- Speed -->
|
||||
<TextBlock Grid.Column="3"
|
||||
Width="70"
|
||||
Text="{Binding Speed, StringFormat={}{0:0.00}}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0"
|
||||
FontSize="12"/>
|
||||
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</UserControl>
|
||||
12
Splitter-UI/Views/ProgressView.axaml.cs
Normal file
12
Splitter-UI/Views/ProgressView.axaml.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Splitter_UI.Views;
|
||||
|
||||
public partial class ProgressView : UserControl
|
||||
{
|
||||
public ProgressView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,13 +12,13 @@
|
||||
Text="{Binding StatusText}" />
|
||||
|
||||
<ProgressBar Grid.Column="1"
|
||||
Width="200" Height="16"
|
||||
Width="200"
|
||||
Height="16"
|
||||
Minimum="0"
|
||||
Maximum="1"
|
||||
VerticalAlignment="Center"
|
||||
Value="{Binding Percent}" />
|
||||
|
||||
<TextBlock Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding ThreadInfo}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user