I like it move it move it

This commit is contained in:
Oleksandr Bezdieniezhnykh
2024-05-18 17:51:38 +03:00
parent de77c9236f
commit dd0ece36f2
33 changed files with 0 additions and 0 deletions
+265
View File
@@ -0,0 +1,265 @@
using System.Collections.ObjectModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows;
using Azaion.Annotator.DTO;
using Azaion.Annotator.Extensions;
using LibVLCSharp.Shared;
using MediatR;
using Microsoft.WindowsAPICodePack.Dialogs;
using Point = System.Windows.Point;
using Size = System.Windows.Size;
namespace Azaion.Annotator;
public partial class MainWindow
{
private readonly LibVLC _libVLC;
private readonly MediaPlayer _mediaPlayer;
private readonly IMediator _mediator;
private readonly FormState _formState;
private readonly Config _config;
private readonly HelpWindow _helpWindow;
private readonly TimeSpan _annotationTime = TimeSpan.FromSeconds(1);
public ObservableCollection<AnnotationClass> AnnotationClasses { get; set; }
private bool _suspendLayout;
public Dictionary<string, List<AnnotationInfo>> Annotations { get; set; } = new();
public bool ShowHelpOnStart { get; set; }
public MainWindow(LibVLC libVLC, MediaPlayer mediaPlayer,
IMediator mediator,
FormState formState,
Config config,
HelpWindow helpWindow)
{
InitializeComponent();
_libVLC = libVLC;
_mediaPlayer = mediaPlayer;
_mediator = mediator;
_formState = formState;
_config = config;
_helpWindow = helpWindow;
VideoView.Loaded += VideoView_Loaded;
Closed += OnFormClosed;
}
private void VideoView_Loaded(object sender, RoutedEventArgs e)
{
Core.Initialize();
InitControls();
_suspendLayout = true;
Left = _config.WindowLocation.X;
Top = _config.WindowLocation.Y;
Width = _config.WindowSize.Width;
Height = _config.WindowSize.Height;
_suspendLayout = false;
ReloadFiles();
if (_config.AnnotationClasses.Count == 0)
_config.AnnotationClasses.Add(new AnnotationClass(0));
AnnotationClasses = new ObservableCollection<AnnotationClass>(_config.AnnotationClasses);
LvClasses.ItemsSource = AnnotationClasses;
LvClasses.SelectedIndex = 0;
if (LvFiles.Items.IsEmpty)
BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.Initial]);
ShowHelpOnStart = _config.ShowHelpOnStart;
if (ShowHelpOnStart)
_helpWindow.Show();
}
public void BlinkHelp(string helpText, int times = 3)
{
_ = Task.Run(async () =>
{
for (int i = 0; i < times; i++)
{
Dispatcher.Invoke(() => StatusHelp.Text = helpText);
await Task.Delay(200);
Dispatcher.Invoke(() => StatusHelp.Text = "");
await Task.Delay(200);
}
Dispatcher.Invoke(() => StatusHelp.Text = helpText);
});
}
private void InitControls()
{
VideoView.MediaPlayer = _mediaPlayer;
_mediaPlayer.Playing += (sender, args) =>
{
uint vw = 0, vh = 0;
_mediaPlayer.Size(0, ref vw, ref vh);
_formState.CurrentVideoSize = new Size(vw, vh);
_formState.CurrentVideoLength = TimeSpan.FromMilliseconds(_mediaPlayer.Length);
};
LvFiles.MouseDoubleClick += async (_, _) => await _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Play));
LvClasses.SelectionChanged += (_, _) =>
{
var selectedClass = (AnnotationClass)LvClasses.SelectedItem;
Editor.CurrentAnnClass = selectedClass;
_mediator.Publish(new AnnClassSelectedEvent(selectedClass));
};
_mediaPlayer.PositionChanged += (o, args) =>
{
Dispatcher.Invoke(() => videoSlider.Value = _mediaPlayer.Position * videoSlider.Maximum);
Dispatcher.Invoke(() => StatusClock.Text = $"{TimeSpan.FromMilliseconds(_mediaPlayer.Time):mm\\:ss} / {_formState.CurrentVideoLength:mm\\:ss}");
var curTime = _formState.GetTimeName(TimeSpan.FromMilliseconds(_mediaPlayer.Time));
if (!Annotations.TryGetValue(curTime, out var annotationInfos))
return;
var annotations = annotationInfos.Select(info =>
{
var annClass = _config.AnnotationClasses[info.ClassNumber];
var annInfo = info.ToCanvasCoordinates(Editor.RenderSize, _formState.CurrentVideoSize);
var annotation = Dispatcher.Invoke(() => Editor.CreateAnnotation(annClass, annInfo));
return annotation;
}).ToList();
//remove annotations: either in 1 sec, either earlier if there is next annotation in a dictionary
var strs = curTime.Split("_");
var timeStr = strs.LastOrDefault();
var ts = TimeSpan.FromMilliseconds(int.Parse(timeStr)*100);
var timeSpanRemove = Enumerable.Range(1, ((int)_annotationTime.TotalMilliseconds / 100) - 1)
.Select(x =>
{
var time = TimeSpan.FromMilliseconds(x * 100);
var fName = _formState.GetTimeName(ts.Add(time));
return Annotations.ContainsKey(fName) ? time : (TimeSpan?)null;
}).FirstOrDefault(x => x != null) ?? _annotationTime;
_ = Task.Run(async () =>
{
await Task.Delay(timeSpanRemove);
Dispatcher.Invoke(() => Editor.RemoveAnnotations(annotations));
});
};
videoSlider.ValueChanged += (value, newValue) =>
_mediaPlayer.Position = (float)(newValue / videoSlider.Maximum);
videoSlider.KeyDown += (sender, args) => _mediator.Publish(new KeyEvent(sender, args));
SizeChanged += (sender, args) =>
{
if (!_suspendLayout)
_config.WindowSize = args.NewSize;
};
LocationChanged += (_, _) =>
{
if (!_suspendLayout)
_config.WindowLocation = new Point(Left, Top);
};
Editor.FormState = _formState;
Editor.Mediator = _mediator;
}
public void LoadExistingAnnotations()
{
var dirInfo = new DirectoryInfo(_config.LabelsDirectory);
if (!dirInfo.Exists)
return;
var files = dirInfo.GetFiles($"{_formState.VideoName}_*");
Annotations = files.ToDictionary(f => Path.GetFileNameWithoutExtension(f.Name), f =>
{
var str = File.ReadAllText(f.FullName);
return str.Split(Environment.NewLine).Select(AnnotationInfo.Parse)
.Where(x => x != null)
.ToList();
})!;
}
private void ReloadFiles()
{
var dir = new DirectoryInfo(_config.VideosDirectory);
if (!dir.Exists)
return;
var files = dir.GetFiles("mp4", "mov").Select(x =>
{
_mediaPlayer.Media = new Media(_libVLC, x.FullName);
return new VideoFileInfo
{
Name = x.Name,
Path = x.FullName,
Duration = TimeSpan.FromMilliseconds(_mediaPlayer.Media.Duration)
};
}).ToList();
LvFiles.ItemsSource = new ObservableCollection<VideoFileInfo>(files);
TbFolder.Text = _config.VideosDirectory;
BlinkHelp(files.Count == 0
? HelpTexts.HelpTextsDict[HelpTextEnum.Initial]
: HelpTexts.HelpTextsDict[HelpTextEnum.PlayVideo]);
}
private void OnFormClosed(object? sender, EventArgs e)
{
_mediaPlayer.Stop();
_mediaPlayer.Dispose();
_libVLC.Dispose();
_config.AnnotationClasses = AnnotationClasses.ToList();
_config.Save();
Application.Current.Shutdown();
}
// private void AddClassBtnClick(object sender, RoutedEventArgs e)
// {
// LvClasses.IsReadOnly = false;
// AnnotationClasses.Add(new AnnotationClass(AnnotationClasses.Count));
// LvClasses.SelectedIndex = AnnotationClasses.Count - 1;
// }
private void OpenFolderItemClick(object sender, RoutedEventArgs e) => OpenFolder();
private void OpenFolderButtonClick(object sender, RoutedEventArgs e) => OpenFolder();
private void OpenFolder()
{
var dlg = new CommonOpenFileDialog
{
Title = "Open Video folder",
IsFolderPicker = true,
InitialDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
};
if (dlg.ShowDialog() != CommonFileDialogResult.Ok)
return;
_config.VideosDirectory = dlg.FileName;
ReloadFiles();
}
private void PlayClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Play));
private void PauseClick(object sender, RoutedEventArgs e)=> _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Pause));
private void StopClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Stop));
private void PreviousFrameClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.PreviousFrame));
private void NextFrameClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.NextFrame));
private void SaveAnnotationsClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.SaveAnnotations));
private void RemoveSelectedClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.RemoveSelectedAnns));
private void RemoveAllClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.RemoveAllAnns));
private void OpenHelpWindowClick(object sender, RoutedEventArgs e)
{
_helpWindow.Show();
_helpWindow.Activate();
}
}