From 078e8046bda7ae2c16aa8f30f798f90ac9d37732 Mon Sep 17 00:00:00 2001 From: Frank Skare Date: Thu, 5 Sep 2019 06:20:44 +0200 Subject: [PATCH] added taskbar-progress implementation --- Changelog.md | 1 + mpv.net/Native/Native.cs | 3 ++ mpv.net/Native/Taskbar.cs | 53 ++++++++++++++++++++++++++ mpv.net/Resources/inputConf.txt | 3 +- mpv.net/Resources/mpvConfToml.txt | 8 ++++ mpv.net/WinForms/MainForm.Designer.cs | 18 ++++++--- mpv.net/WinForms/MainForm.cs | 54 +++++++++++++++++++++++---- mpv.net/WinForms/MainForm.resx | 5 ++- mpv.net/mpv.net.csproj | 1 + mpv.net/mpv/mp.cs | 9 +++-- 10 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 mpv.net/Native/Taskbar.cs diff --git a/Changelog.md b/Changelog.md index f6ff4f4..1919b98 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,6 @@ ### +- added taskbar-progress implementation - added new setting to start with maximized window - long file names work now even if not enabled by the OS - fixed history being written even when history file wasn't created prior diff --git a/mpv.net/Native/Native.cs b/mpv.net/Native/Native.cs index fb2ffaa..d2fc349 100644 --- a/mpv.net/Native/Native.cs +++ b/mpv.net/Native/Native.cs @@ -27,6 +27,9 @@ namespace mpvnet [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern int RegisterWindowMessage(string id); + [DllImport("user32.dll")] public static extern bool AllowSetForegroundWindow(int dwProcessId); diff --git a/mpv.net/Native/Taskbar.cs b/mpv.net/Native/Taskbar.cs new file mode 100644 index 0000000..499d361 --- /dev/null +++ b/mpv.net/Native/Taskbar.cs @@ -0,0 +1,53 @@ +using System; +using System.Runtime.InteropServices; + +public class Taskbar +{ + private ITaskbarList3 Instance = (ITaskbarList3)new TaskBarCommunication(); + + public IntPtr Handle { get; set; } + + public Taskbar(IntPtr handle) => Handle = handle; + + [ComImportAttribute] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")] + private interface ITaskbarList3 + { + // ITaskbarList + [PreserveSig] void HrInit(); + [PreserveSig] void AddTab(IntPtr hwnd); + [PreserveSig] void DeleteTab(IntPtr hwnd); + [PreserveSig] void ActivateTab(IntPtr hwnd); + [PreserveSig] void SetActiveAlt(IntPtr hwnd); + // ITaskbarList2 + [PreserveSig] void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen); + // ITaskbarList3 + [PreserveSig] void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal); + [PreserveSig] void SetProgressState(IntPtr hwnd, TaskbarStates state); + } + + [ComImportAttribute] + [ClassInterfaceAttribute(ClassInterfaceType.None)] + [GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")] + private class TaskBarCommunication { } + + public void SetState(TaskbarStates taskbarState) + { + Instance.SetProgressState(Handle, taskbarState); + } + + public void SetValue(double progressValue, double progressMax) + { + Instance.SetProgressValue(Handle, (UInt64)progressValue, (UInt64)progressMax); + } +} + +public enum TaskbarStates +{ + NoProgress = 0, + Indeterminate = 0x1, + Normal = 0x2, + Error = 0x4, + Paused = 0x8 +} \ No newline at end of file diff --git a/mpv.net/Resources/inputConf.txt b/mpv.net/Resources/inputConf.txt index 9d90267..59f928a 100644 --- a/mpv.net/Resources/inputConf.txt +++ b/mpv.net/Resources/inputConf.txt @@ -196,5 +196,4 @@ Ctrl+Wheel_Up no-osd seek 7 Ctrl+Wheel_Down no-osd seek -7 MBTN_Left_DBL cycle fullscreen - KP_Enter cycle fullscreen - MBTN_Left ignore \ No newline at end of file + KP_Enter cycle fullscreen \ No newline at end of file diff --git a/mpv.net/Resources/mpvConfToml.txt b/mpv.net/Resources/mpvConfToml.txt index befaa6d..8115db6 100644 --- a/mpv.net/Resources/mpvConfToml.txt +++ b/mpv.net/Resources/mpvConfToml.txt @@ -325,6 +325,14 @@ name = "screenshot-png-filter" filter = "Screen" help = "<0-5> Set the filter applied prior to PNG compression. 0 is none, 1 is 'sub', 2 is 'up', 3 is 'average', 4 is 'Paeth', and 5 is 'mixed'. This affects the level of compression that can be achieved. For most images, 'mixed' achieves the best compression ratio, hence it is the default." +[[settings]] +name = "taskbar-progress" +default = "yes" +filter = "Playback" +help = "Show progress in taskbar." +options = [{ name = "yes" }, + { name = "no" }] + [[settings]] name = "keep-open-pause" default = "yes" diff --git a/mpv.net/WinForms/MainForm.Designer.cs b/mpv.net/WinForms/MainForm.Designer.cs index 42b40cf..1813545 100644 --- a/mpv.net/WinForms/MainForm.Designer.cs +++ b/mpv.net/WinForms/MainForm.Designer.cs @@ -30,14 +30,19 @@ { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); - this.Timer = new System.Windows.Forms.Timer(this.components); + this.CursorTimer = new System.Windows.Forms.Timer(this.components); + this.ProgressTimer = new System.Windows.Forms.Timer(this.components); this.SuspendLayout(); // - // Timer + // CursorTimer // - this.Timer.Enabled = true; - this.Timer.Interval = 1000; - this.Timer.Tick += new System.EventHandler(this.Timer_Tick); + this.CursorTimer.Enabled = true; + this.CursorTimer.Interval = 1000; + this.CursorTimer.Tick += new System.EventHandler(this.CursorTimer_Tick); + // + // ProgressTimer + // + this.ProgressTimer.Tick += new System.EventHandler(this.ProgressTimer_Tick); // // MainForm // @@ -57,6 +62,7 @@ #endregion - private System.Windows.Forms.Timer Timer; + private System.Windows.Forms.Timer CursorTimer; + private System.Windows.Forms.Timer ProgressTimer; } } \ No newline at end of file diff --git a/mpv.net/WinForms/MainForm.cs b/mpv.net/WinForms/MainForm.cs index 3f8c3e9..049bd9b 100644 --- a/mpv.net/WinForms/MainForm.cs +++ b/mpv.net/WinForms/MainForm.cs @@ -16,12 +16,12 @@ namespace mpvnet { public static MainForm Instance { get; set; } public static IntPtr Hwnd { get; set; } - public new ContextMenuStripEx ContextMenu { get; set; } - Point LastCursorPosChanged; int LastCursorChangedTickCount; + int TaskbarButtonCreatedMessage; bool WasShown; + Taskbar Taskbar; List RecentFiles; public MainForm() @@ -38,7 +38,9 @@ namespace mpvnet mp.VideoSizeChanged += VideoSizeChanged; mp.FileLoaded += FileLoaded; mp.Idle += Idle; + mp.Seek += () => UpdateProgressBar(); + mp.observe_property_bool("pause", PropChangePause); mp.observe_property_bool("fullscreen", PropChangeFullscreen); mp.observe_property_bool("ontop", PropChangeOnTop); mp.observe_property_bool("border", PropChangeBorder); @@ -46,14 +48,15 @@ namespace mpvnet mp.observe_property_string("aid", PropChangeAid); mp.observe_property_string("vid", PropChangeVid); mp.observe_property_int("edition", PropChangeEdition); - + if (mp.GPUAPI != "vulkan") mp.ProcessCommandLine(false); AppDomain.CurrentDomain.UnhandledException += (sender, e) => Msg.ShowError(e.ExceptionObject.ToString()); Application.ThreadException += (sender, e) => Msg.ShowException(e.Exception); Msg.SupportURL = "https://github.com/stax76/mpv.net#support"; Text = "mpv.net " + Application.ProductVersion; - + TaskbarButtonCreatedMessage = Native.RegisterWindowMessage("TaskbarButtonCreated"); + object recent = RegHelp.GetObject(App.RegPath, "Recent"); if (recent is string[] r) @@ -94,14 +97,17 @@ namespace mpvnet public MenuItem FindMenuItem(string text) => FindMenuItem(text, ContextMenu.Items); - void Idle() => BeginInvoke(new Action(() => Text = "mpv.net " + Application.ProductVersion)); + void Shutdown() => BeginInvoke(new Action(() => Close())); + + void Idle() + { + BeginInvoke(new Action(() => Text = "mpv.net " + Application.ProductVersion)); + } void CM_Popup(object sender, EventArgs e) => CursorHelp.Show(); void VideoSizeChanged() => BeginInvoke(new Action(() => SetFormPosAndSize())); - void Shutdown() => BeginInvoke(new Action(() => Close())); - void PropChangeFullscreen(bool value) => BeginInvoke(new Action(() => CycleFullscreen(value))); void ContextMenu_Opened(object sender, EventArgs e) => CursorHelp.Show(); @@ -372,6 +378,7 @@ namespace mpvnet private void FileLoaded() { string path = mp.get_property_string("path"); + BeginInvoke(new Action(() => { if (path.Contains("://")) Text = path + " - mpv.net " + Application.ProductVersion; @@ -379,7 +386,13 @@ namespace mpvnet Text = path.FileName() + " - mpv.net " + Application.ProductVersion; else Text = "mpv.net " + Application.ProductVersion; + + double duration = mp.get_property_number("duration"); + ProgressTimer.Interval = (int)(mp.Duration.TotalMilliseconds / 99); + if (ProgressTimer.Interval < 100) ProgressTimer.Interval = 100; + if (ProgressTimer.Interval > 999) ProgressTimer.Interval = 999; })); + if (RecentFiles.Contains(path)) RecentFiles.Remove(path); RecentFiles.Insert(0, path); while (RecentFiles.Count > App.RecentCount) RecentFiles.RemoveAt(App.RecentCount); @@ -473,10 +486,16 @@ namespace mpvnet return; } + if (m.Msg == TaskbarButtonCreatedMessage) + { + Taskbar = new Taskbar(Handle); + ProgressTimer.Start(); + } + base.WndProc(ref m); } - void Timer_Tick(object sender, EventArgs e) + void CursorTimer_Tick(object sender, EventArgs e) { if (CursorHelp.IsPosDifferent(LastCursorPosChanged)) { @@ -490,6 +509,14 @@ namespace mpvnet CursorHelp.Hide(); } + private void ProgressTimer_Tick(object sender, EventArgs e) => UpdateProgressBar(); + + void UpdateProgressBar() + { + if (mp.TaskbarProgress) + Taskbar.SetValue(mp.get_property_number("time-pos"), mp.Duration.TotalSeconds); + } + void PropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value)); void PropChangeAid(string value) => mp.Aid = value; @@ -514,6 +541,17 @@ namespace mpvnet })); } + void PropChangePause(bool enabled) + { + if (Taskbar != null) + { + if (enabled) + Taskbar.SetState(TaskbarStates.Paused); + else + Taskbar.SetState(TaskbarStates.Normal); + } + } + protected override void OnLoad(EventArgs e) { base.OnLoad(e); diff --git a/mpv.net/WinForms/MainForm.resx b/mpv.net/WinForms/MainForm.resx index 5a9fa4c..0cd1870 100644 --- a/mpv.net/WinForms/MainForm.resx +++ b/mpv.net/WinForms/MainForm.resx @@ -117,9 +117,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 30, 12 + + 321, 12 + diff --git a/mpv.net/mpv.net.csproj b/mpv.net/mpv.net.csproj index b961ad6..761376d 100644 --- a/mpv.net/mpv.net.csproj +++ b/mpv.net/mpv.net.csproj @@ -153,6 +153,7 @@ + Component diff --git a/mpv.net/mpv/mp.cs b/mpv.net/mpv/mp.cs index 128d0a1..e2a929f 100644 --- a/mpv.net/mpv/mp.cs +++ b/mpv.net/mpv/mp.cs @@ -61,12 +61,12 @@ namespace mpvnet public static List>> StringPropChangeActions { get; set; } = new List>>(); public static List MediaTracks { get; set; } = new List(); public static List> Chapters { get; set; } = new List>(); - public static IntPtr Handle { get; set; } public static IntPtr WindowHandle { get; set; } public static Extension Extension { get; set; } public static List PythonScripts { get; set; } = new List(); public static Size VideoSize { get; set; } + public static TimeSpan Duration; public static AutoResetEvent ShutdownAutoResetEvent { get; set; } = new AutoResetEvent(false); public static AutoResetEvent VideoSizeAutoResetEvent { get; set; } = new AutoResetEvent(false); @@ -81,7 +81,8 @@ namespace mpvnet public static bool IsQuitNeeded { set; get; } = true; public static bool Fullscreen { get; set; } public static bool Border { get; set; } = true; - + public static bool TaskbarProgress { get; set; } = true; + public static int Screen { get; set; } = -1; public static int Edition { get; set; } @@ -136,6 +137,7 @@ namespace mpvnet case "fs": case "fullscreen": Fullscreen = value == "yes"; break; case "border": Border = value == "yes"; break; + case "taskbar-progress": TaskbarProgress = value == "yes"; break; case "screen": Screen = Convert.ToInt32(value); break; case "gpu-api": GPUAPI = value; break; } @@ -317,7 +319,7 @@ namespace mpvnet break; case mpv_event_id.MPV_EVENT_FILE_LOADED: HideLogo(); - FileLoaded?.Invoke(); + Duration = TimeSpan.FromSeconds(get_property_number("duration")); Size vidSize = new Size(get_property_int("width"), get_property_int("height")); if (vidSize.Width == 0 || vidSize.Height == 0) vidSize = new Size(1, 1); @@ -329,6 +331,7 @@ namespace mpvnet VideoSizeAutoResetEvent.Set(); Task.Run(new Action(() => ReadMetaData())); WriteHistory(get_property_string("path")); + FileLoaded?.Invoke(); break; case mpv_event_id.MPV_EVENT_TRACKS_CHANGED: TracksChanged?.Invoke();