This commit is contained in:
Frank Skare
2019-07-05 05:05:37 +02:00
parent caf0bee161
commit 7a1de4cf0f
10 changed files with 128 additions and 182 deletions

View File

@@ -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

View File

@@ -1752,7 +1752,6 @@ namespace Tommy
}
else
stringBuilder.Append(c);
break;
}
}

View File

@@ -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>())
{
@@ -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 { }
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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,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();

View File

@@ -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;

View File

@@ -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();