Files
annotations/Azaion.Annotator/PlayerControlHandler.cs
T
2024-05-19 00:02:59 +03:00

148 lines
5.5 KiB
C#

using System.IO;
using System.Windows.Input;
using Azaion.Annotator.DTO;
using LibVLCSharp.Shared;
using MediatR;
namespace Azaion.Annotator;
public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWindow mainWindow, FormState formState, Config config) :
INotificationHandler<KeyEvent>,
INotificationHandler<AnnClassSelectedEvent>,
INotificationHandler<PlaybackControlEvent>
{
private const int STEP = 20;
private const int LARGE_STEP = 5000;
private static readonly string[] CatchSenders = ["ForegroundWindow", "ScrollViewer", "VideoView"];
private readonly Dictionary<Key, PlaybackControlEnum> KeysControlEnumDict = new()
{
{ Key.Space, PlaybackControlEnum.Pause },
{ Key.Left, PlaybackControlEnum.PreviousFrame },
{ Key.Right, PlaybackControlEnum.NextFrame },
{ Key.Enter, PlaybackControlEnum.SaveAnnotations },
{ Key.Delete, PlaybackControlEnum.RemoveSelectedAnns },
{ Key.X, PlaybackControlEnum.RemoveAllAnns }
};
public async Task Handle(AnnClassSelectedEvent notification, CancellationToken cancellationToken)
{
SelectClass(notification.AnnotationClass);
await Task.CompletedTask;
}
private void SelectClass(AnnotationClass annClass)
{
mainWindow.Editor.CurrentAnnClass = annClass;
foreach (var ann in mainWindow.Editor.CurrentAnns.Where(x => x.IsSelected))
ann.AnnotationClass = annClass;
mainWindow.LvClasses.SelectedIndex = annClass.Id;
}
public async Task Handle(KeyEvent notification, CancellationToken cancellationToken)
{
if (!CatchSenders.Contains(notification.Sender.GetType().Name))
return;
var key = notification.Args.Key;
var keyNumber = (int?)null;
if ((int)key >= (int)Key.D1 && (int)key <= (int)Key.D9)
keyNumber = key - Key.D1;
if ((int)key >= (int)Key.NumPad1 && (int)key <= (int)Key.NumPad9)
keyNumber = key - Key.NumPad1;
if (keyNumber.HasValue)
SelectClass(mainWindow.AnnotationClasses[keyNumber.Value]);
if (KeysControlEnumDict.TryGetValue(key, out var value))
await ControlPlayback(value);
}
public async Task Handle(PlaybackControlEvent notification, CancellationToken cancellationToken)
{
await ControlPlayback(notification.PlaybackControl);
mainWindow.VideoView.Focus();
}
private async Task ControlPlayback(PlaybackControlEnum controlEnum)
{
var isCtrlPressed = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
var step = isCtrlPressed ? LARGE_STEP : STEP;
switch (controlEnum)
{
case PlaybackControlEnum.Play:
Play();
break;
case PlaybackControlEnum.Pause:
mediaPlayer.Pause();
if (!mediaPlayer.IsPlaying)
mainWindow.BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.AnnotationHelp]);
break;
case PlaybackControlEnum.Stop:
mediaPlayer.Stop();
break;
case PlaybackControlEnum.PreviousFrame:
mediaPlayer.SetPause(true);
mediaPlayer.Time -= step;
break;
case PlaybackControlEnum.NextFrame:
mediaPlayer.SetPause(true);
mediaPlayer.Time += step;
break;
case PlaybackControlEnum.SaveAnnotations:
await SaveAnnotations();
break;
case PlaybackControlEnum.RemoveSelectedAnns:
mainWindow.Editor.RemoveSelectedAnns();
break;
case PlaybackControlEnum.RemoveAllAnns:
mainWindow.Editor.RemoveAllAnns();
break;
case PlaybackControlEnum.None:
break;
default:
throw new ArgumentOutOfRangeException(nameof(controlEnum), controlEnum, null);
}
}
private void Play()
{
if (mainWindow.LvFiles.SelectedItem == null)
return;
var fileInfo = (VideoFileInfo)mainWindow.LvFiles.SelectedItem;
formState.CurrentFile = fileInfo.Name;
mainWindow.LoadExistingAnnotations();
mediaPlayer.Stop();
mediaPlayer.Play(new Media(libVLC, fileInfo.Path));
mainWindow.BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.PauseForAnnotations]);
}
private async Task SaveAnnotations()
{
if (string.IsNullOrEmpty(formState.CurrentFile))
return;
var fName = formState.GetTimeName(TimeSpan.FromMilliseconds(mediaPlayer.Time));
var currentAnns = mainWindow.Editor.CurrentAnns
.Select(x => x.Info.ToLabelCoordinates(mainWindow.Editor.RenderSize, formState.CurrentVideoSize))
.ToList();
var labels = string.Join(Environment.NewLine, currentAnns.Select(x => x.ToString()));
if (!Directory.Exists(config.LabelsDirectory))
Directory.CreateDirectory(config.LabelsDirectory);
if (!Directory.Exists(config.ImagesDirectory))
Directory.CreateDirectory(config.ImagesDirectory);
await File.WriteAllTextAsync($"{config.LabelsDirectory}/{fName}.txt", labels);
mediaPlayer.TakeSnapshot(0, $"{config.ImagesDirectory}/{fName}.jpg", 0, 0);
mainWindow.Annotations[fName] = currentAnns;
mainWindow.Editor.RemoveAllAnns();
mediaPlayer.Play();
}
}