JD2022-TU1/main/tools/modules/JD.VideoPlayer.WPF/View/VideoPlayerControl.xaml.cs

225 lines
7 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using ActiproSoftware.Windows.Controls.Docking;
using JD.Asset.Types.Map;
using JD.Interfaces.Player;
using JD.VideoPlayer.WPF.Actions;
using JD.VideoPlayer.WPF.Settings;
using JetBrains.Annotations;
using PleoNET;
using Plume.Interfaces.WPF.Modules;
using Plume.Interfaces.WPF.Window;
namespace JD.VideoPlayer.WPF.View
{
/// <summary>
/// Interaction logic for VideoPlayerControl.xaml
/// </summary>
public partial class VideoPlayerControl : UserControl, INotifyPropertyChanged
{
private IVideoProvider _videoProvider;
private readonly IWindowManager _windowManager;
private PleoVideoClip _videoClip;
private double _aspectRatio;
private readonly VideoPlayerSettings _settings;
private bool _showDebugInformations;
private TimeSpan _currentTime;
private static readonly Dictionary<string, bool> _hasAlphaCache = new Dictionary<string, bool>();
public VideoPlayerControl(IWpfModuleContext context)
{
InitializeComponent();
_windowManager = context.WindowManager;
VideoControl = new PleoControl();
WindowsFormsHost.Child = VideoControl;
_windowManager.ActiveWindowChanged += WindowManagerOnActiveWindowChanged;
_settings = context.SettingsManager.Get<VideoPlayerSettings>();
if (_settings != null)
{
_settings.PropertyChanged += OnSettingsPropertyChanged;
}
var aspectRatioButton = context.ToolBarManager.CreatePopupButton(context.ActionManager.Actions.OfType<AspectRatioAction>());
aspectRatioButton.ShowTextInToolBar = true;
ToolBar.Items.Add(aspectRatioButton);
var debugButton = context.ToolBarManager.CreateButton(context.ActionManager.Get<ShowDebugInformationsAction>());
ToolBar.Items.Add(debugButton);
UpdateSettings();
}
private void OnSettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
{
UpdateSettings();
}
private void UpdateSettings()
{
AspectRatio = _settings.AspectRatio == Settings.AspectRatio.Original ? 1.777 : 1;
ShowDebugInformations = _settings.ShowDebugInformations;
}
public double AspectRatio
{
get => _aspectRatio;
set
{
_aspectRatio = value;
OnPropertyChanged();
}
}
public bool ShowDebugInformations
{
get => _showDebugInformations;
set
{
_showDebugInformations = value;
OnPropertyChanged();
}
}
public PleoControl VideoControl { get; }
public PleoVideoClip VideoClip
{
get => _videoClip;
private set
{
if (null != _videoClip)
{
VideoControl.UnbindVideoClip();
_videoClip.Stop();
_videoClip.Dispose();
}
_videoClip = value;
VideoControl.BindVideoClip(value);
_videoClip?.Play();
}
}
public IVideoProvider VideoProvider
{
get
{
return _videoProvider;
}
set
{
if (_videoProvider != value)
{
if (null != _videoProvider)
{
_videoProvider.PropertyChanged += VideoProviderOnPropertyChanged;
}
_videoProvider = value;
if (null != _videoProvider)
{
_videoProvider.PropertyChanged += VideoProviderOnPropertyChanged;
VideoClip = LoadVideoClip(_videoProvider.VideoFileUri.OriginalString);
}
}
}
}
private void VideoProviderOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(IVideoProvider.VideoCurrentTime))
{
VideoClip.UpdateTime(VideoProvider.VideoCurrentTime.TotalSeconds);
CurrentTime = VideoProvider.VideoCurrentTime;
VideoControl.Invalidate();
VideoControl.Update();
}
}
protected bool HasNoClip => VideoClip == null;
public TimeSpan CurrentTime
{
get => _currentTime;
set
{
_currentTime = value;
OnPropertyChanged();
}
}
private void WindowManagerOnActiveWindowChanged(object sender, DockingWindow e)
{
var videoPlayerProvider = _windowManager.GetActiveWindowContent<IVideoProvider>();
if (videoPlayerProvider != null)
{
VideoProvider = videoPlayerProvider;
}
}
public Bitmap Snapshot()
{
if (HasNoClip)
{
return null;
}
VideoControl.Update();
return VideoControl.Snapshot();
}
protected PleoVideoClip LoadVideoClip(string videoFile)
{
if (!string.IsNullOrEmpty(videoFile))
{
var map = Map.FromPath(videoFile);
bool hasAlpha;
if (_hasAlphaCache.ContainsKey(videoFile))
{
hasAlpha = _hasAlphaCache[videoFile];
}
else
{
hasAlpha = ComputeAlpha(map, videoFile);
_hasAlphaCache.Add(videoFile, hasAlpha);
}
return new PleoVideoClip(videoFile, 0, 0, _externTimeSource: true, _hasAlpha: hasAlpha);
}
return null;
}
private bool ComputeAlpha(Map map, string videoFile)
{
if (map == null)
{
return false;
}
if (videoFile.Contains("thumbnail"))
{
// Edition video has alpha.
return true;
}
if (videoFile.Contains("_alpha") && File.Exists(map.VideoCoachAlphaIsc))
{
return File.ReadAllText(map.VideoCoachAlphaIsc).Contains("video_alpha_output_main");
}
return File.Exists(map.VideoCoachIsc) && File.ReadAllText(map.VideoCoachIsc).Contains("video_alpha_output_main");
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}