-
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -1752,7 +1752,6 @@ namespace Tommy
|
||||
}
|
||||
else
|
||||
stringBuilder.Append(c);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string[]> Action { get; set; }
|
||||
|
||||
static List<Command> commands;
|
||||
|
||||
public static List<Command> Commands
|
||||
public static void Execute(string id, string[] args)
|
||||
{
|
||||
get
|
||||
switch (id)
|
||||
{
|
||||
if (commands == null)
|
||||
{
|
||||
commands = new List<Command>();
|
||||
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<string[]>)i.CreateDelegate(typeof(Action<string[]>)) };
|
||||
|
||||
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<string>())
|
||||
{
|
||||
@@ -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 { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<string> files = new List<string>();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Native.RECT>(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,9 +385,7 @@ namespace mpvnet
|
||||
mp.commandv("loadfile", file, "append");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RegHelp.RemoveValue(App.RegPath, "ShellFiles");
|
||||
Activate();
|
||||
return;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<string> 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<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
|
||||
|
||||
Reference in New Issue
Block a user