From 7a1de4cf0fc0f2e1d59a60338acde44f4d3397a9 Mon Sep 17 00:00:00 2001 From: Frank Skare Date: Fri, 5 Jul 2019 05:05:37 +0200 Subject: [PATCH] - --- Changelog.md | 4 + mpv.net/DynamicGUI/Tommy.cs | 1 - mpv.net/Misc/Command.cs | 179 +++++++++++---------------------- mpv.net/Misc/Misc.cs | 18 ++-- mpv.net/Misc/Program.cs | 28 ++++-- mpv.net/Native/Native.cs | 15 +++ mpv.net/WPF/ConfWindow.xaml.cs | 2 +- mpv.net/WinForms/MainForm.cs | 31 +++--- mpv.net/mpv/libmpv.cs | 2 +- mpv.net/mpv/mp.cs | 30 ++---- 10 files changed, 128 insertions(+), 182 deletions(-) diff --git a/Changelog.md b/Changelog.md index 8fdf9ad..3aa4a60 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,10 @@ ### - fix for middle mouse button not working +- the config dialog was showing a message about app restart even when no + settings were modified +- when multiple files are selected in Windows File Explorer and enter is + pressed, the files are opened, the order is random however ### 4.5 diff --git a/mpv.net/DynamicGUI/Tommy.cs b/mpv.net/DynamicGUI/Tommy.cs index 82dace7..9af7f11 100644 --- a/mpv.net/DynamicGUI/Tommy.cs +++ b/mpv.net/DynamicGUI/Tommy.cs @@ -1752,7 +1752,6 @@ namespace Tommy } else stringBuilder.Append(c); - break; } } diff --git a/mpv.net/Misc/Command.cs b/mpv.net/Misc/Command.cs index 9c67989..f6df6a0 100644 --- a/mpv.net/Misc/Command.cs +++ b/mpv.net/Misc/Command.cs @@ -1,9 +1,8 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Reflection; +using System.Windows; using System.Windows.Forms; using System.Windows.Interop; @@ -13,42 +12,53 @@ namespace mpvnet { public class Command { - public string Name { get; set; } - public Action Action { get; set; } - - static List commands; - - public static List Commands + public static void Execute(string id, string[] args) { - get + switch (id) { - if (commands == null) - { - commands = new List(); - Type type = typeof(Command); - MethodInfo[] methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public); - - foreach (MethodInfo i in methods) - { - ParameterInfo[] parameters = i.GetParameters(); - - if (parameters == null || - parameters.Length != 1 || - parameters[0].ParameterType != typeof(string[])) - continue; - - Command cmd = new Command() { - Name = i.Name.Replace("_", "-"), - Action = (Action)i.CreateDelegate(typeof(Action)) }; - - commands.Add(cmd); - } - } - return commands; + case "manage-file-associations": ManageFileAssociations(); break; + case "cycle-audio": CycleAudio(); break; + case "load-audio": LoadAudio(); break; + case "load-sub": LoadSubtitle(); break; + case "open-url": OpenURL(); break; + case "execute-mpv-command": ExecuteMpvCommand(); break; + case "show-history": ShowHistory(); break; + case "show-media-search": ShowMediaSearch(); break; + case "show-command-palette": ShowCommandPalette(); break; + case "show-about": ShowAbout(); break; + case "show-conf-editor": ShowConfEditor(); break; + case "show-input-editor": ShowInputEditor(); break; + case "open-conf-folder": Process.Start(mp.ConfFolder); break; + case "open-files": OpenFiles(args); break; + case "shell-execute": Process.Start(args[0]); break; + case "show-info": ShowInfo(); break; + case "add-files-to-playlist": OpenFiles("append"); break; // deprecated 2019 + default: Msg.ShowError($"No command '{id}' found."); break; } } - public static void open_files(string[] args) + public static void InvokeOnMainThread(Action action) => MainForm.Instance.Invoke(action); + + public static void ShowDialog(Type winType) + { + InvokeOnMainThread(new Action(() => { + Window win = Activator.CreateInstance(winType) as Window; + new WindowInteropHelper(win).Owner = MainForm.Instance.Handle; + win.ShowDialog(); + })); + } + + public static void ShowInputEditor() => ShowDialog(typeof(InputWindow)); + + public static void ShowConfEditor() => ShowDialog(typeof(ConfWindow)); + + public static void ShowAbout() => ShowDialog(typeof(AboutWindow)); + + public static void ShowCommandPalette() => ShowDialog(typeof(CommandPaletteWindow)); + + public static void ShowMediaSearch() => ShowDialog(typeof(EverythingWindow)); + + public static void OpenFiles(params string[] args) { bool append = Control.ModifierKeys.HasFlag(Keys.Control); bool loadFolder = true; @@ -59,75 +69,14 @@ namespace mpvnet if (arg == "no-folder") loadFolder = false; } - MainForm.Instance.Invoke(new Action(() => { + InvokeOnMainThread(new Action(() => { using (var d = new OpenFileDialog() { Multiselect = true }) if (d.ShowDialog() == DialogResult.OK) mp.Load(d.FileNames, loadFolder, append); })); } - // deprecated in 2019 - public static void add_files_to_playlist(string[] args) - { - MainForm.Instance.Invoke(new Action(() => { - using (var d = new OpenFileDialog() { Multiselect = true }) - if (d.ShowDialog() == DialogResult.OK) - foreach (string file in d.FileNames) - mp.commandv("loadfile", file, "append"); - })); - } - - public static void open_conf_folder(string[] args) - { - Process.Start(mp.ConfFolder); - } - - public static void show_input_editor(string[] args) - { - MainForm.Instance.Invoke(new Action(() => { - InputWindow w = new InputWindow(); - new WindowInteropHelper(w).Owner = MainForm.Instance.Handle; - w.ShowDialog(); - })); - } - - public static void show_conf_editor(string[] args) - { - MainForm.Instance.Invoke(new Action(() => { - ConfWindow w = new ConfWindow(); - new WindowInteropHelper(w).Owner = MainForm.Instance.Handle; - w.ShowDialog(); - })); - } - - public static void show_about(string[] args) - { - MainForm.Instance.Invoke(new Action(() => { - AboutWindow w = new AboutWindow(); - new WindowInteropHelper(w).Owner = MainForm.Instance.Handle; - w.ShowDialog(); - })); - } - - public static void show_command_palette(string[] args) - { - MainForm.Instance.Invoke(new Action(() => { - var w = new CommandPaletteWindow(); - new WindowInteropHelper(w).Owner = MainForm.Instance.Handle; - w.ShowDialog(); - })); - } - - public static void show_media_search(string[] args) - { - MainForm.Instance.Invoke(new Action(() => { - var w = new EverythingWindow(); - new WindowInteropHelper(w).Owner = MainForm.Instance.Handle; - w.ShowDialog(); - })); - } - - public static void show_history(string[] args) + public static void ShowHistory() { var fp = mp.ConfFolder + "history.txt"; @@ -139,9 +88,7 @@ namespace mpvnet File.WriteAllText(fp, ""); } - public static void shell_execute(string[] args) => Process.Start(args[0]); - - public static void show_info(string[] args) + public static void ShowInfo() { try { @@ -205,9 +152,9 @@ namespace mpvnet } } - public static void execute_mpv_command(string[] args) + public static void ExecuteMpvCommand() { - MainForm.Instance.Invoke(new Action(() => { + InvokeOnMainThread(new Action(() => { string command = VB.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegHelp.GetString(App.RegPath, "RecentExecutedCommand")); if (string.IsNullOrEmpty(command)) return; RegHelp.SetObject(App.RegPath, "RecentExecutedCommand", command); @@ -215,22 +162,22 @@ namespace mpvnet })); } - public static void open_url(string[] args) + public static void OpenURL() { - MainForm.Instance.Invoke(new Action(() => { - string clipboard = Clipboard.GetText(); + InvokeOnMainThread(new Action(() => { + string clipboard = System.Windows.Forms.Clipboard.GetText(); if (string.IsNullOrEmpty(clipboard) || (!clipboard.Contains("://") && !File.Exists(clipboard)) || clipboard.Contains("\n")) { - Msg.ShowError("The clipboard does not contain a valid URL or file, URLs have to contain :// and is not allowed to contain a newline character."); + Msg.ShowError("The clipboard does not contain a valid URL or file, URLs have to contain :// and are not allowed to contain a newline character."); return; } mp.Load(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control)); })); } - public static void load_sub(string[] args) + public static void LoadSubtitle() { - MainForm.Instance.Invoke(new Action(() => { + InvokeOnMainThread(new Action(() => { using (var d = new OpenFileDialog()) { d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false)); @@ -242,9 +189,9 @@ namespace mpvnet })); } - public static void load_audio(string[] args) + public static void LoadAudio() { - MainForm.Instance.Invoke(new Action(() => { + InvokeOnMainThread(new Action(() => { using (var d = new OpenFileDialog()) { d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false)); @@ -257,7 +204,7 @@ namespace mpvnet })); } - public static void cycle_audio(string[] args) + public static void CycleAudio() { string filePath = mp.get_property_string("path", false); if (!File.Exists(filePath)) return; @@ -274,7 +221,7 @@ namespace mpvnet } } - public static void manage_file_associations(string[] args) + public static void ManageFileAssociations() { using (var td = new TaskDialog()) { @@ -283,7 +230,7 @@ namespace mpvnet td.AddCommandLink("Register video file extensions", "video"); td.AddCommandLink("Register audio file extensions", "audio"); - td.AddCommandLink("Unregister file extensions", "unreg"); + td.AddCommandLink("Unregister file extensions", "unreg"); string result = td.Show(); @@ -291,14 +238,10 @@ namespace mpvnet { using (var proc = new Process()) { - proc.StartInfo.FileName = Application.ExecutablePath; + proc.StartInfo.FileName = System.Windows.Forms.Application.ExecutablePath; proc.StartInfo.Arguments = "--reg-file-assoc " + result; proc.StartInfo.Verb = "runas"; - try { - proc.Start(); - } - catch (Exception) - { } + try { proc.Start(); } catch { } } } } diff --git a/mpv.net/Misc/Misc.cs b/mpv.net/Misc/Misc.cs index e95291d..c6e3941 100644 --- a/mpv.net/Misc/Misc.cs +++ b/mpv.net/Misc/Misc.cs @@ -228,6 +228,13 @@ namespace mpvnet return val.ToString(); } + public static int GetInt(string path, string name) + { + object val = GetObject(path, name); + if (val == null || !(val is int)) return 0; + return (int)val; + } + public static object GetObject(string path, string name) { using (RegistryKey rk = GetRootKey(path).OpenSubKey(path.Substring(5))) @@ -393,15 +400,4 @@ namespace mpvnet Math.Abs(screenPos.Y - Control.MousePosition.Y) > 10; } } - - public class SingleProcess - { - public static int Message { get; } = RegisterWindowMessage("mpvnet_IPC"); - - [DllImport("user32.dll", CharSet = CharSet.Unicode)] - static extern int RegisterWindowMessage(string id); - - [DllImport("user32.dll")] - public static extern bool AllowSetForegroundWindow(int dwProcessId); - } } \ No newline at end of file diff --git a/mpv.net/Misc/Program.cs b/mpv.net/Misc/Program.cs index 5381e78..2d94f52 100644 --- a/mpv.net/Misc/Program.cs +++ b/mpv.net/Misc/Program.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; using System.Diagnostics; +using System.Runtime.InteropServices; namespace mpvnet { @@ -31,24 +32,31 @@ namespace mpvnet if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst) { List files = new List(); + files.Add(App.ProcessInstance); foreach (string arg in args) if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") || File.Exists(arg))) files.Add(arg); - if (files.Count > 0) - RegHelp.SetObject(App.RegPath, "ShellFiles", files.ToArray()); + Process[] procs = Process.GetProcessesByName("mpvnet"); - RegHelp.SetObject(App.RegPath, "ProcessInstanceMode", App.ProcessInstance); - - foreach(Process process in Process.GetProcessesByName("mpvnet")) + for (int i = 0; i < 20; i++) { - try { - SingleProcess.AllowSetForegroundWindow(process.Id); - Native.SendMessage(process.MainWindowHandle, SingleProcess.Message, IntPtr.Zero, IntPtr.Zero); - } catch {} + foreach (Process proc in procs) + { + if (proc.MainWindowHandle != IntPtr.Zero) + { + Native.AllowSetForegroundWindow(proc.Id); + var data = new Native.COPYDATASTRUCT(); + data.lpData = string.Join("\n", files.ToArray()); + data.cbData = data.lpData.Length * 2 + 1; + Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data); + mutex.Dispose(); + return; + } + } + Thread.Sleep(50); } - mutex.Dispose(); return; } diff --git a/mpv.net/Native/Native.cs b/mpv.net/Native/Native.cs index 4939619..77c7b02 100644 --- a/mpv.net/Native/Native.cs +++ b/mpv.net/Native/Native.cs @@ -15,9 +15,15 @@ namespace mpvnet [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam); + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + [DllImport("user32.dll")] + public static extern bool AllowSetForegroundWindow(int dwProcessId); + [DllImport("user32.dll")] public static extern void ReleaseCapture(); @@ -70,5 +76,14 @@ namespace mpvnet public int Width => Right - Left; public int Height => Bottom - Top; } + + [StructLayout(LayoutKind.Sequential)] + public struct COPYDATASTRUCT + { + public IntPtr dwData; + public int cbData; + [MarshalAs(UnmanagedType.LPStr)] + public string lpData; + } } } \ No newline at end of file diff --git a/mpv.net/WPF/ConfWindow.xaml.cs b/mpv.net/WPF/ConfWindow.xaml.cs index 4c9b211..5fbe0a2 100644 --- a/mpv.net/WPF/ConfWindow.xaml.cs +++ b/mpv.net/WPF/ConfWindow.xaml.cs @@ -59,7 +59,7 @@ namespace mpvnet if (setting.Name == pair.Key) { setting.Value = pair.Value.Trim('\'', '"'); - setting.StartValue = pair.Value; + setting.StartValue = pair.Value.Trim('\'', '"'); continue; } } diff --git a/mpv.net/WinForms/MainForm.cs b/mpv.net/WinForms/MainForm.cs index a45b80b..4fa83b1 100644 --- a/mpv.net/WinForms/MainForm.cs +++ b/mpv.net/WinForms/MainForm.cs @@ -365,22 +365,17 @@ namespace mpvnet int[] d_corners = { d_w, d_h, -d_w, -d_h }; int[] corners = { rc.Left, rc.Top, rc.Right, rc.Bottom }; int corner = NativeHelp.GetResizeBorder(m.WParam.ToInt32()); - - if (corner >= 0) - corners[corner] -= d_corners[corner]; - + if (corner >= 0) corners[corner] -= d_corners[corner]; Marshal.StructureToPtr(new Native.RECT(corners[0], corners[1], corners[2], corners[3]), m.LParam, false); m.Result = new IntPtr(1); return; - } + case 0x004A: // WM_COPYDATA + var copyData = (Native.COPYDATASTRUCT)m.GetLParam(typeof(Native.COPYDATASTRUCT)); + string[] files = copyData.lpData.Split('\n'); + string mode = files[0]; + files = files.Skip(1).ToArray(); - if (m.Msg == SingleProcess.Message) - { - object filesObject = RegHelp.GetObject(App.RegPath, "ShellFiles"); - - if (filesObject is string[] files) - { - switch (RegHelp.GetString(App.RegPath, "ProcessInstanceMode")) + switch (mode) { case "single": mp.Load(files, true, Control.ModifierKeys.HasFlag(Keys.Control)); @@ -390,11 +385,9 @@ namespace mpvnet mp.commandv("loadfile", file, "append"); break; } - } - RegHelp.RemoveValue(App.RegPath, "ShellFiles"); - Activate(); - return; + Activate(); + return; } base.WndProc(ref m); @@ -481,13 +474,13 @@ namespace mpvnet BuildMenu(); ContextMenuStrip = ContextMenu; IgnoreDpiChanged = false; - CheckUrlInClipboard(); + CheckClipboardForURL(); } protected override void OnActivated(EventArgs e) { base.OnActivated(e); - CheckUrlInClipboard(); + CheckClipboardForURL(); Message m = new Message() { Msg = 0x0202 }; // WM_LBUTTONUP Native.SendMessage(Handle, m.Msg, m.WParam, m.LParam); } @@ -530,7 +523,7 @@ namespace mpvnet CursorHelp.Show(); } - void CheckUrlInClipboard() + void CheckClipboardForURL() { string clipboard = Clipboard.GetText(); diff --git a/mpv.net/mpv/libmpv.cs b/mpv.net/mpv/libmpv.cs index 5e277b7..4369148 100644 --- a/mpv.net/mpv/libmpv.cs +++ b/mpv.net/mpv/libmpv.cs @@ -144,7 +144,7 @@ namespace mpvnet MPV_END_FILE_REASON_REDIRECT = 5 } - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential)] public struct mpv_event_log_message { public string prefix; diff --git a/mpv.net/mpv/mp.cs b/mpv.net/mpv/mp.cs index 7928b5b..6a5fdcd 100644 --- a/mpv.net/mpv/mp.cs +++ b/mpv.net/mpv/mp.cs @@ -274,27 +274,8 @@ namespace mpvnet case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE: var client_messageData = (mpv_event_client_message)Marshal.PtrToStructure(evt.data, typeof(mpv_event_client_message)); string[] args = NativeUtf8StrArray2ManagedStrArray(client_messageData.args, client_messageData.num_args); - if (args.Length > 1 && args[0] == "mpv.net") - { - bool found = false; - - foreach (Command i in Command.Commands) - { - if (args[1] == i.Name) - { - found = true; - i.Action.Invoke(args.Skip(2).ToArray()); - } - } - - if (!found) - { - List names = mpvnet.Command.Commands.Select((item) => item.Name).ToList(); - names.Sort(); - Msg.ShowError($"No command '{args[1]}' found.", $"Available commands are:\n\n{string.Join("\n", names)}\n\nHow to bind these commands can be seen in the [default input bindings and menu definition](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt)."); - } - } + Command.Execute(args[1], args.Skip(2).ToArray()); else if (args.Length > 0) ClientMessage?.Invoke(args); break; @@ -558,11 +539,18 @@ namespace mpvnet } } + static DateTime LastLoad; + public static void Load(string[] files, bool loadFolder, bool append) { if (files is null || files.Length == 0) return; HideLogo(); + if ((DateTime.Now - LastLoad).TotalMilliseconds < 500) + append = true; + + LastLoad = DateTime.Now; + for (int i = 0; i < files.Length; i++) if (App.SubtitleTypes.Contains(Path.GetExtension(files[i]).TrimStart('.').ToLower())) commandv("sub-add", files[i]); @@ -579,7 +567,7 @@ namespace mpvnet public static void LoadFolder() { - Thread.Sleep(50); // user reported race condition + Thread.Sleep(200); // user reported race condition string path = get_property_string("path"); if (!File.Exists(path) || get_property_int("playlist-count") != 1) return; List files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();