Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87e3d9ca3e | ||
|
|
29a0eae3d5 | ||
|
|
01b2492cde | ||
|
|
d2b1ca0c69 | ||
|
|
91b429e6b0 | ||
|
|
fa05e95892 | ||
|
|
701a58a4bf | ||
|
|
387c3f7896 | ||
|
|
eeb0189577 | ||
|
|
de4c2d6d70 | ||
|
|
63ee598ebd | ||
|
|
1bf8e568c5 | ||
|
|
f8f58dba5e | ||
|
|
ebb8ad351a | ||
|
|
0202c34c6f | ||
|
|
c3f2b22ff5 | ||
|
|
c1a03c3e4b | ||
|
|
e041908f04 |
20
Changelog.md
20
Changelog.md
@@ -1,3 +1,23 @@
|
||||
### 4.3
|
||||
|
||||
- there was new bug in file association feature
|
||||
|
||||
### 4.2
|
||||
|
||||
- the help and layout in the config editor was improved
|
||||
- clipboard monitoring for URLs can be disabled in the settings
|
||||
- the context menu has a new feature: Open > Add files to playlist,
|
||||
it appends files to the playlist [(Default binding)](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L33)
|
||||
- a setting was added to force using a single mpv.net process instance
|
||||
|
||||
### 4.1
|
||||
|
||||
- drag & drop support for subtitles was added
|
||||
- libmpv was updated
|
||||
- command line support for stdin and URLs was added
|
||||
- there was a crash happening when the player is
|
||||
minimized in the taskbar
|
||||
|
||||
### 4.0
|
||||
|
||||
- on the start screen the mpv.NET icon is shown instead of the mpv icon,
|
||||
|
||||
16
README.md
16
README.md
@@ -6,11 +6,11 @@ mpv.net is a modern media player for Windows that works just like [mpv](https://
|
||||
|
||||
#### Based on libmpv
|
||||
|
||||
mpv.net is based on libmpv which offers a straightforward C API that was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications.
|
||||
mpv.net is based on libmpv which offers a straightforward C API that was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications. mpv is like vlc not based on DirectShow or Media Foundation.
|
||||
|
||||
#### Command Line Interface
|
||||
|
||||
mpv.net has the CLI of mpv: [CLI switches](https://mpv.io/manual/master/#options).
|
||||
mpv.net has the [CLI of mpv](https://mpv.io/manual/master/#options).
|
||||
|
||||
#### High quality video output
|
||||
|
||||
@@ -46,15 +46,15 @@ Table of contents
|
||||
|
||||
### Features
|
||||
|
||||
- Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu-screenshot))
|
||||
- Searchable config dialog ([Screenshot](#config-editor-screenshot))
|
||||
- Searchable input (key/mouse) binding editor ([Screenshot](#input-editor-screenshot))
|
||||
- Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt))
|
||||
- Searchable config dialog ([Screenshot](#config-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt))
|
||||
- Searchable input (key/mouse) binding editor ([Screenshot](#input-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt))
|
||||
- Searchable command palette to quickly launch commands and look for keys ([Screenshot](#command-palette-screenshot))
|
||||
- Modern UI with dark mode ([Screenshot](#config-editor-screenshot))
|
||||
- Addon/extension API for .NET languages
|
||||
- Scripting API for Python, C#, Lua, JavaScript and PowerShell ([wiki](https://github.com/stax76/mpv.net/wiki/Scripting))
|
||||
- mpv's OSC, IPC and conf files
|
||||
- Support of the same [CLI options](https://mpv.io/manual/master/#options) as mpv
|
||||
- [Command Line Interface](https://mpv.io/manual/master/#options)
|
||||
- DXVA2 video decoding acceleration
|
||||
- OpenGL based video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more
|
||||
- Search feature powered by [Everything](https://www.voidtools.com) to find and play media ([Screenshot](#media-search-screenshot))
|
||||
@@ -139,6 +139,8 @@ if it's missing mpv.net generates it with the following defaults:
|
||||
|
||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt>
|
||||
|
||||
mpv.net supports almost all mpv settings and features, [limitations are listed in the wiki](https://github.com/stax76/mpv.net/wiki/Limitations).
|
||||
|
||||
### Scripting
|
||||
|
||||
[Scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting)
|
||||
@@ -188,6 +190,8 @@ Third party components:
|
||||
|
||||
[Issue tracker to report bugs and request features](https://github.com/stax76/mpv.net/issues)
|
||||
|
||||
[frank.skare.de@gmail.com](mailto:frank.skare.de@gmail.com?Subject=mpv.net%20support)
|
||||
|
||||
### Links
|
||||
|
||||
mpv manual: <https://mpv.io/manual/master/>
|
||||
|
||||
@@ -13,8 +13,8 @@ Public Class CSScriptAddon
|
||||
Sub New()
|
||||
Dim scriptFiles As New List(Of String)
|
||||
|
||||
If Directory.Exists(mp.MpvConfFolder + "scripts") Then
|
||||
scriptFiles.AddRange(Directory.GetFiles(mp.MpvConfFolder + "scripts", "*.cs"))
|
||||
If Directory.Exists(mp.ConfFolder + "scripts") Then
|
||||
scriptFiles.AddRange(Directory.GetFiles(mp.ConfFolder + "scripts", "*.cs"))
|
||||
End If
|
||||
|
||||
If Directory.Exists(Application.StartupPath + "\scripts") Then
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Navigation;
|
||||
|
||||
@@ -102,13 +103,15 @@ namespace DynamicGUI
|
||||
set => _Text = value;
|
||||
}
|
||||
|
||||
public bool IsChecked
|
||||
public bool Checked
|
||||
{
|
||||
get => OptionSetting.Value == Name ;
|
||||
set {
|
||||
if (value)
|
||||
OptionSetting.Value = Name;
|
||||
set { if (value) OptionSetting.Value = Name; }
|
||||
}
|
||||
|
||||
public Visibility Visibility
|
||||
{
|
||||
get => string.IsNullOrEmpty(Help) ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<WrapPanel Orientation="Vertical">
|
||||
<RadioButton x:Name="RadioButton" VerticalContentAlignment="Center" IsChecked="{Binding IsChecked}" GroupName="{Binding OptionSetting.Name}" Content="{Binding Text}" FontSize="16" FontWeight="Normal" VerticalAlignment="Top" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></RadioButton>
|
||||
<TextBox x:Name="ItemHelpTextBox" TextWrapping="WrapWithOverflow" Text="{Binding Help}" Margin="10,0,0,0" BorderThickness="0" IsReadOnly="True" Padding="7,0,0,0" MinHeight="0" Foreground="{Binding Path=Foreground2, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
||||
<RadioButton x:Name="RadioButton" VerticalContentAlignment="Center" IsChecked="{Binding Checked}" GroupName="{Binding OptionSetting.Name}" Content="{Binding Text}" FontSize="16" FontWeight="Normal" VerticalAlignment="Top" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></RadioButton>
|
||||
<TextBox x:Name="ItemHelpTextBox" TextWrapping="WrapWithOverflow" Text="{Binding Help}" Visibility="{Binding Visibility}" Margin="10,0,0,0" BorderThickness="0" IsReadOnly="True" Padding="7,0,0,0" MinHeight="0" Foreground="{Binding Path=Foreground2, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
||||
@@ -12,11 +12,13 @@ namespace DynamicGUI
|
||||
OptionSetting = optionSetting;
|
||||
InitializeComponent();
|
||||
TitleTextBox.Text = optionSetting.Name;
|
||||
if (string.IsNullOrEmpty(optionSetting.Help))
|
||||
HelpTextBox.Visibility = Visibility.Collapsed;
|
||||
HelpTextBox.Text = optionSetting.Help;
|
||||
ItemsControl.ItemsSource = optionSetting.Options;
|
||||
Link.SetURL(optionSetting.HelpURL);
|
||||
if (string.IsNullOrEmpty(optionSetting.HelpURL))
|
||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||
Link.SetURL(optionSetting.HelpURL);
|
||||
}
|
||||
|
||||
private string _SearchableText;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<TextBox x:Name="ValueTextBox" Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="150" HorizontalAlignment="Left" Height="20" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" TextChanged="ValueTextBox_TextChanged"/>
|
||||
<Button x:Name="Button" Height="20" Grid.Column="1" Visibility="{Binding Path=Text, ElementName=StringSettingControl1}" Margin="5,0,0,0" Width="20" Click="Button_Click">...</Button>
|
||||
</Grid>
|
||||
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" Margin="0,0,0,10" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
||||
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||
</TextBlock>
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace mpvnet
|
||||
foreach (string i in Directory.GetDirectories(dir))
|
||||
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
|
||||
|
||||
dir = mp.MpvConfFolder + "\\Addons";
|
||||
dir = mp.ConfFolder + "\\Addons";
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
foreach (string i in Directory.GetDirectories(dir))
|
||||
|
||||
@@ -7,6 +7,8 @@ using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
|
||||
using VB = Microsoft.VisualBasic;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Command
|
||||
@@ -46,13 +48,13 @@ namespace mpvnet
|
||||
MainForm.Instance.Invoke(new Action(() => {
|
||||
using (var d = new OpenFileDialog() { Multiselect = true })
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
mp.LoadFiles(d.FileNames);
|
||||
mp.Load(d.FileNames);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void open_conf_folder(string[] args)
|
||||
{
|
||||
Process.Start(mp.MpvConfFolder);
|
||||
Process.Start(mp.ConfFolder);
|
||||
}
|
||||
|
||||
public static void show_input_editor(string[] args)
|
||||
@@ -102,7 +104,7 @@ namespace mpvnet
|
||||
|
||||
public static void show_history(string[] args)
|
||||
{
|
||||
var fp = mp.MpvConfFolder + "history.txt";
|
||||
var fp = mp.ConfFolder + "history.txt";
|
||||
|
||||
if (File.Exists(fp))
|
||||
Process.Start(fp);
|
||||
@@ -172,17 +174,18 @@ namespace mpvnet
|
||||
mp.commandv("show-text", text, "5000");
|
||||
string FormatTime(double value) => ((int)value).ToString("00");
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
Msg.ShowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void execute_mpv_command(string[] args)
|
||||
{
|
||||
MainForm.Instance.Invoke(new Action(() => {
|
||||
string command = Microsoft.VisualBasic.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegistryHelp.GetString("HKCU\\Software\\" + Application.ProductName, "RecentExecutedCommand"));
|
||||
string command = VB.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegistryHelp.GetString(App.RegPath, "RecentExecutedCommand"));
|
||||
if (string.IsNullOrEmpty(command)) return;
|
||||
RegistryHelp.SetObject("HKCU\\Software\\" + Application.ProductName, "RecentExecutedCommand", command);
|
||||
RegistryHelp.SetObject(App.RegPath, "RecentExecutedCommand", command);
|
||||
mp.command_string(command, false);
|
||||
}));
|
||||
}
|
||||
@@ -190,9 +193,9 @@ namespace mpvnet
|
||||
public static void open_url(string[] args)
|
||||
{
|
||||
MainForm.Instance.Invoke(new Action(() => {
|
||||
string command = Microsoft.VisualBasic.Interaction.InputBox("Enter URL to be opened.");
|
||||
string command = VB.Interaction.InputBox("Enter URL to be opened.");
|
||||
if (string.IsNullOrEmpty(command)) return;
|
||||
mp.LoadFiles(command);
|
||||
mp.Load(command);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -203,7 +206,6 @@ namespace mpvnet
|
||||
{
|
||||
d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false));
|
||||
d.Multiselect = true;
|
||||
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
foreach (string i in d.FileNames)
|
||||
mp.commandv("sub-add", i);
|
||||
@@ -226,6 +228,16 @@ namespace mpvnet
|
||||
}));
|
||||
}
|
||||
|
||||
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 cycle_audio(string[] args)
|
||||
{
|
||||
string filePath = mp.get_property_string("path", false);
|
||||
|
||||
@@ -17,13 +17,82 @@ namespace mpvnet
|
||||
{
|
||||
public class App
|
||||
{
|
||||
public static string[] VideoTypes { get; } = "mkv mp4 mpg avi mov webm vob wmv flv avs 264 h264 asf webm mpeg mpv y4m avc hevc 265 h265 m2v m2ts vpy mts m4v".Split(" ".ToCharArray());
|
||||
public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(" ".ToCharArray());
|
||||
public static string ConfFilePath { get; } = mp.ConfFolder + "\\mpvnet.conf";
|
||||
public static string RegPath { get; } = "HKCU\\Software\\" + Application.ProductName;
|
||||
public static string ClipboardMonitoring { get; set; } = "yes";
|
||||
|
||||
public static string[] VideoTypes { get; } = "mkv mp4 mpg avi mov webm vob wmv flv avs 264 h264 asf webm mpeg mpv y4m avc hevc 265 h265 m2v m2ts vpy mts m4v".Split(' ');
|
||||
public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(' ');
|
||||
public static string[] SubtitleTypes { get; } = "srt ass idx sup ttxt ssa smi".Split(' ');
|
||||
|
||||
public static string DarkMode { get; set; } = "always";
|
||||
public static string ProcessInstance { get; set; } = "single";
|
||||
|
||||
public static bool IsDarkMode {
|
||||
get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
foreach (var i in Conf)
|
||||
ProcessProperty(i.Key, i.Value);
|
||||
}
|
||||
|
||||
static Dictionary<string, string> _Conf;
|
||||
|
||||
public static Dictionary<string, string> Conf {
|
||||
get {
|
||||
string darkMode = MainForm.Instance.MpvNetDarkMode;
|
||||
return (darkMode == "system" && Sys.IsDarkTheme) || darkMode == "always";
|
||||
if (_Conf == null)
|
||||
{
|
||||
_Conf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(ConfFilePath))
|
||||
foreach (string i in File.ReadAllLines(ConfFilePath))
|
||||
if (i.Contains("=") && !i.StartsWith("#"))
|
||||
_Conf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||
}
|
||||
return _Conf;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessProperty(string name, string value)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "clipboard-monitoring": ClipboardMonitoring = value; break;
|
||||
case "process-instance": ProcessInstance = value; break;
|
||||
case "dark-mode": DarkMode = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessCommandLineEarly()
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs().Skip(1);
|
||||
|
||||
foreach (string i in args)
|
||||
{
|
||||
if (i.StartsWith("--"))
|
||||
{
|
||||
if (i.Contains("="))
|
||||
{
|
||||
string left = i.Substring(2, i.IndexOf("=") - 2);
|
||||
string right = i.Substring(left.Length + 3);
|
||||
mp.ProcessProperty(left, right);
|
||||
ProcessProperty(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
string switchName = i.Substring(2);
|
||||
|
||||
switch (switchName)
|
||||
{
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
mp.Fullscreen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,14 +212,18 @@ namespace mpvnet
|
||||
|
||||
public static void RemoveKey(string path)
|
||||
{
|
||||
try {
|
||||
GetRootKey(path).DeleteSubKeyTree(path.Substring(5), false);
|
||||
} catch { }
|
||||
}
|
||||
|
||||
public static void RemoveValue(string path, string name)
|
||||
{
|
||||
try {
|
||||
using (RegistryKey rk = GetRootKey(path).OpenSubKey(path.Substring(5), true))
|
||||
if (!(rk is null))
|
||||
rk.DeleteValue(name, false);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
static RegistryKey GetRootKey(string path)
|
||||
@@ -293,4 +366,15 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
@@ -10,19 +15,47 @@ namespace mpvnet
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
||||
|
||||
if (args.Length == 3 && args[1] == "--reg-file-assoc")
|
||||
if (args.Length == 2 && args[0] == "--reg-file-assoc")
|
||||
{
|
||||
if (args[2] == "audio") FileAssociation.Register(App.AudioTypes);
|
||||
if (args[2] == "video") FileAssociation.Register(App.VideoTypes);
|
||||
if (args[2] == "unreg") FileAssociation.Unregister();
|
||||
if (args[1] == "audio") FileAssociation.Register(App.AudioTypes);
|
||||
if (args[1] == "video") FileAssociation.Register(App.VideoTypes);
|
||||
if (args[1] == "unreg") FileAssociation.Unregister();
|
||||
return;
|
||||
}
|
||||
|
||||
Mutex mutex = new Mutex(true, "mpvnetProcessInstance", out bool isFirst);
|
||||
App.Init();
|
||||
|
||||
if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst)
|
||||
{
|
||||
List<string> files = new List<string>();
|
||||
|
||||
foreach (string arg in args)
|
||||
if (!arg.StartsWith("--") && (File.Exists(arg) || arg == "-" || arg.StartsWith("http")))
|
||||
files.Add(arg);
|
||||
|
||||
if (files.Count > 0)
|
||||
RegistryHelp.SetObject(App.RegPath, "ShellFiles", files.ToArray());
|
||||
|
||||
RegistryHelp.SetObject(App.RegPath, "ProcessInstanceMode", App.ProcessInstance);
|
||||
|
||||
foreach(Process process in Process.GetProcessesByName("mpvnet"))
|
||||
{
|
||||
try {
|
||||
SingleProcess.AllowSetForegroundWindow(process.Id);
|
||||
Native.SendMessage(process.MainWindowHandle, SingleProcess.Message, IntPtr.Zero, IntPtr.Zero);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new MainForm());
|
||||
mutex.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace mpvnet
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
|
||||
private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("mpv.net")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017-2019 stax76")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017-2019 Frank Skare (stax76)")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("4.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("4.0.0.0")]
|
||||
[assembly: AssemblyVersion("4.3.0.0")]
|
||||
[assembly: AssemblyFileVersion("4.3.0.0")]
|
||||
|
||||
107
mpv.net/Properties/Resources.Designer.cs
generated
107
mpv.net/Properties/Resources.Designer.cs
generated
@@ -1,6 +1,24 @@
|
||||
namespace mpvnet.Properties {
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace mpvnet.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
@@ -14,6 +32,9 @@
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
@@ -25,6 +46,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
@@ -35,30 +60,92 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
/// # This file defines the input (keys and mouse) bindings of mpv and mpv.net
|
||||
/// # and it also defines the context menu of mpv.net. mpv.net has an input
|
||||
/// # editor and an config editor as alternative to editing conf text files.
|
||||
/// # The input and config editor can be found in mpv.net's context menu at:
|
||||
///
|
||||
/// # Settings > Show Config Editor
|
||||
/// # Settings > Show Input Editor
|
||||
///
|
||||
/// # The defaults of this file can be found at:
|
||||
///
|
||||
/// # https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt
|
||||
///
|
||||
/// # th [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string inputConf {
|
||||
get {
|
||||
return ResourceManager.GetString("inputConf", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
/// # This file defines the input (keys and mouse) bindings of mpv and mpv.net
|
||||
/// # and it also defines the context menu of mpv.net. mpv.net has an input
|
||||
/// # editor and an config editor as alternatives to editing conf text files.
|
||||
/// # The input and config editor can be found in mpv.net's context menu at:
|
||||
///
|
||||
/// # Settings > Show Config Editor
|
||||
/// # Settings > Show Input Editor
|
||||
///
|
||||
/// # The defaults of this file can be found at:
|
||||
///
|
||||
/// # https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt
|
||||
///
|
||||
/// # t [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string inputConfHeader {
|
||||
get {
|
||||
return ResourceManager.GetString("inputConfHeader", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
///# mpv manual: https://mpv.io/manual/master/
|
||||
///
|
||||
///# mpv.net mpv.conf defaults: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt
|
||||
///
|
||||
///input-ar-delay = 500
|
||||
///input-ar-rate = 20
|
||||
///volume = 50
|
||||
///hwdec = yes
|
||||
///keep-open = yes
|
||||
///keep-open-pause = no
|
||||
///osd-playing-msg = ${filename}
|
||||
///screenshot-directory = ~~desktop/
|
||||
///input-default-bindings = no
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string mpvConf {
|
||||
get {
|
||||
return ResourceManager.GetString("mpvConf", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to [[settings]]
|
||||
///name = "hwdec"
|
||||
///default = "no"
|
||||
///filter = "Video"
|
||||
///helpurl = "https://mpv.io/manual/master/#options-hwdec"
|
||||
///help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
|
||||
///options = [{ name = "no", help = "always use software decoding" },
|
||||
/// { name = "auto", help = "enabl [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string mpvConfToml {
|
||||
get {
|
||||
return ResourceManager.GetString("mpvConfToml", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap mpvnet {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("mpvnet", resourceCulture);
|
||||
@@ -66,6 +153,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to [[settings]]
|
||||
///name = "dark-mode"
|
||||
///default = "always"
|
||||
///filter = "mpv.net"
|
||||
///help = "Enables a dark theme."
|
||||
///options = [{ name = "always" },
|
||||
/// { name = "system" , help = "Available on Windows 10 or higher" },
|
||||
/// { name = "never" }]
|
||||
///
|
||||
///[[settings]]
|
||||
///name = "clipboard-monitoring"
|
||||
///default = "yes"
|
||||
///filter = "mpv.net"
|
||||
///help = "Monitors the clipboard for URLs to play."
|
||||
///options = [{ name = "yes" },
|
||||
/// { name = "no" }].
|
||||
/// </summary>
|
||||
internal static string mpvNetConfToml {
|
||||
get {
|
||||
return ResourceManager.GetString("mpvNetConfToml", resourceCulture);
|
||||
|
||||
@@ -26,11 +26,13 @@
|
||||
|
||||
o script-message mpv.net open-files #menu: Open > Open Files...
|
||||
u script-message mpv.net open-url #menu: Open > Open URL...
|
||||
Ctrl+S script-message mpv.net show-media-search #menu: Open > Show media search...
|
||||
_ ignore #menu: Open > -
|
||||
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
|
||||
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
|
||||
_ ignore #menu: Open > -
|
||||
_ script-message mpv.net add-files-to-playlist #menu: Open > Add files to playlist...
|
||||
Ctrl+S script-message mpv.net show-media-search #menu: Open > Show media search...
|
||||
_ ignore #menu: Open > -
|
||||
_ ignore #menu: Open > Recent
|
||||
|
||||
_ ignore #menu: -
|
||||
@@ -137,7 +139,7 @@
|
||||
F8 show-text ${playlist} 5000 #menu: View > Show Playlist
|
||||
F9 show-text ${track-list} 5000 #menu: View > Show Audio/Video/Subtitle List
|
||||
|
||||
Ctrl+c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
|
||||
c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
|
||||
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor
|
||||
Ctrl+f script-message mpv.net open-conf-folder #menu: Settings > Open Config Folder
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ default = "no"
|
||||
filter = "Video"
|
||||
helpurl = "https://mpv.io/manual/master/#options-hwdec"
|
||||
help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
|
||||
options = [{ name = "no", help = "always use software decoding (Default)" },
|
||||
options = [{ name = "no", help = "always use software decoding" },
|
||||
{ name = "auto", help = "enable best hw decoder (see below)" },
|
||||
{ name = "yes", help = "exactly the same as auto" },
|
||||
{ name = "auto-copy", help = "enable best hw decoder with copy-back (see below)" },
|
||||
@@ -24,7 +24,7 @@ name = "gpu-api"
|
||||
default = "auto"
|
||||
filter = "Video"
|
||||
help = "Controls which type of graphics APIs will be accepted."
|
||||
options = [{ name = "auto", help = "Use any available API (Default)" },
|
||||
options = [{ name = "auto", help = "Use any available API" },
|
||||
{ name = "opengl", help = "Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)" },
|
||||
{ name = "vulkan", help = "Allow only Vulkan (requires a valid/working spirv-compiler)" },
|
||||
{ name = "d3d11", help = "Allow only gpu-context=d3d11" }]
|
||||
@@ -33,8 +33,7 @@ options = [{ name = "auto", help = "Use any available API (Default)" },
|
||||
name = "gpu-context"
|
||||
default = "auto"
|
||||
filter = "Video"
|
||||
help = "The value auto (the default) selects the GPU context. You can also pass help to get a complete list of compiled in backends (sorted by autoprobe order)."
|
||||
options = [{ name = "auto", help = "auto-select (Default)" },
|
||||
options = [{ name = "auto", help = "auto-select" },
|
||||
{ name = "win", help = "Win32/WGL" },
|
||||
{ name = "winvk", help = "VK_KHR_win32_surface" },
|
||||
{ name = "angle", help = "Direct3D11 through the OpenGL ES translation layer ANGLE. This supports almost everything the win backend does (if the ANGLE build is new enough)." },
|
||||
@@ -45,9 +44,9 @@ options = [{ name = "auto", help = "auto-select (Default)" },
|
||||
name = "vo"
|
||||
default = "gpu"
|
||||
filter = "Video"
|
||||
help = "Video output drivers to be used.\n\nFor more information visit:"
|
||||
helpurl = "https://mpv.io/manual/master/#video-output-drivers-vo"
|
||||
help = "Video output drivers to be used. Default = gpu.\n\nFor more information visit:"
|
||||
options = [{ name = "gpu", help = "General purpose, customizable, GPU-accelerated video output driver. It supports extended scaling methods, dithering, color management, custom shaders, HDR, and more. (Default)" },
|
||||
options = [{ name = "gpu", help = "General purpose, customizable, GPU-accelerated video output driver. It supports extended scaling methods, dithering, color management, custom shaders, HDR, and more." },
|
||||
{ name = "direct3d", help = "Video output driver that uses the Direct3D interface" }]
|
||||
|
||||
[[settings]]
|
||||
@@ -70,7 +69,7 @@ name = "scale"
|
||||
default = "bilinear"
|
||||
filter = "Video"
|
||||
help = "The GPU renderer filter function to use when upscaling video. There are some more filters, but most are not as useful. For a complete list, pass help as value, e.g.: mpv --scale=help"
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality). This is the default for compatibility reasons." },
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
|
||||
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
|
||||
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
|
||||
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
|
||||
@@ -84,7 +83,7 @@ name = "cscale"
|
||||
default = "bilinear"
|
||||
filter = "Video"
|
||||
help = "As scale, but for interpolating chroma information. If the image is not subsampled, this option is ignored entirely."
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality). This is the default for compatibility reasons." },
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
|
||||
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
|
||||
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
|
||||
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
|
||||
@@ -98,7 +97,7 @@ name = "dscale"
|
||||
default = "bilinear"
|
||||
filter = "Video"
|
||||
help = "Like scale, but apply these filters on downscaling instead. If this option is unset, the filter implied by scale will be applied."
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality). This is the default for compatibility reasons." },
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
|
||||
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
|
||||
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
|
||||
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
|
||||
@@ -111,7 +110,7 @@ options = [{ name = "bilinear", help = "Bilinear hardware texture filter
|
||||
name = "dither-depth"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
help = "Set dither target depth to N. Default: no. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output."
|
||||
help = "Set dither target depth to N. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output."
|
||||
options = [{ name = "no", help = "Disable any dithering done by mpv." },
|
||||
{ name = "auto", help = "Automatic selection. If output bit depth cannot be detected, 8 bits per component are assumed." },
|
||||
{ name = "8", help = "Dither to 8 bit output." }]
|
||||
@@ -157,7 +156,7 @@ name = "audio-file-auto"
|
||||
default = "no"
|
||||
filter = "Audio"
|
||||
help = "Load additional audio files matching the video filename. The parameter specifies how external audio files are matched."
|
||||
options = [{ name = "no", help = "Don't automatically load external audio files (default)." },
|
||||
options = [{ name = "no", help = "Don't automatically load external audio files." },
|
||||
{ name = "exact", help = "Load the media filename with audio file extension." },
|
||||
{ name = "fuzzy", help = "Load all audio files containing media filename." },
|
||||
{ name = "all", help = "Load all audio files in the current and audio-file-paths directories." }]
|
||||
@@ -174,7 +173,7 @@ default = "exact"
|
||||
filter = "Subtitle"
|
||||
help = "Load additional subtitle files matching the video filename. The parameter specifies how external subtitle files are matched. exact is enabled by default."
|
||||
options = [{ name = "no", help = "Don't automatically load external subtitle files." },
|
||||
{ name = "exact", help = "Load the media filename with subtitle file extension (Default)." },
|
||||
{ name = "exact", help = "Load the media filename with subtitle file extension." },
|
||||
{ name = "fuzzy", help = "Load all subs containing media filename." },
|
||||
{ name = "all", help = "Load all subs in the current and sub-file-paths directories." }]
|
||||
|
||||
@@ -202,7 +201,7 @@ name = "sub-border-color"
|
||||
default = ""
|
||||
type = "color"
|
||||
filter = "Subtitle"
|
||||
help = "See --sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent)."
|
||||
help = "See sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent)."
|
||||
|
||||
[[settings]]
|
||||
name = "sub-back-color"
|
||||
@@ -215,7 +214,7 @@ help = "See sub-color. Color used for sub text background. You can use sub-shado
|
||||
name = "screen"
|
||||
default = ""
|
||||
filter = "Screen"
|
||||
help = "In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on. Default: default"
|
||||
help = "In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on."
|
||||
|
||||
[[settings]]
|
||||
name = "osd-playing-msg"
|
||||
@@ -235,7 +234,7 @@ help = "Specify the OSD font size. See sub-font-size for details. Default: 55"
|
||||
name = "fullscreen"
|
||||
default = "no"
|
||||
filter = "Screen"
|
||||
help = "Start the player in fullscreen mode. Default: no"
|
||||
help = "Start the player in fullscreen mode."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
@@ -257,7 +256,7 @@ help = "Set the initial window size in percent. Please note that this setting is
|
||||
name = "keep-open-pause"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "If set to no, instead of pausing when keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again. Default: yes"
|
||||
help = "If set to no, instead of pausing when keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
@@ -267,7 +266,7 @@ default = "no"
|
||||
filter = "Playback"
|
||||
help = "Do not terminate when playing or seeking beyond the end of the file, and there is not next file to be played (and loop is not used). Instead, pause the player. When trying to seek beyond end of the file, the player will attempt to seek to the last frame.\n\nNormally, this will act like set pause yes on EOF, unless the keep-open-pause=no option is set."
|
||||
options = [{ name = "yes", help = "Don't terminate if the current file is the last playlist entry. Equivalent to keep-open without arguments."},
|
||||
{ name = "no", help = "If the current file ends, go to the next file or terminate. (Default.)" },
|
||||
{ name = "no", help = "If the current file ends, go to the next file or terminate." },
|
||||
{ name = "always", help = "Like yes, but also applies to files before the last playlist entry. This means playback will never automatically advance to the next file."}]
|
||||
|
||||
[[settings]]
|
||||
@@ -303,14 +302,14 @@ filter = "Playback"
|
||||
help = "Select when to use precise seeks that are not limited to keyframes. Such seeks require decoding video from the previous keyframe up to the target position and so can take some time depending on decoding performance. For some video formats, precise seeks are disabled. This option selects the default choice to use for seeks; it is possible to explicitly override that default in the definition of key bindings and in input commands."
|
||||
options = [{ name = "yes", help = "Use precise seeks whenever possible." },
|
||||
{ name = "no", help = "Never use precise seeks." },
|
||||
{ name = "absolute", help = "Use precise seeks if the seek is to an absolute position in the file, such as a chapter seek, but not for relative seeks like the default behavior of arrow keys (default)." },
|
||||
{ name = "absolute", help = "Use precise seeks if the seek is to an absolute position in the file, such as a chapter seek, but not for relative seeks like the default behavior of arrow keys." },
|
||||
{ name = "always", help = "Same as yes (for compatibility)." }]
|
||||
|
||||
[[settings]]
|
||||
name = "track-auto-selection"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "Enable the default track auto-selection (default: yes). Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected."
|
||||
help = "Enable the default track auto-selection. Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
|
||||
@@ -6,3 +6,20 @@ help = "Enables a dark theme."
|
||||
options = [{ name = "always" },
|
||||
{ name = "system" , help = "Available on Windows 10 or higher" },
|
||||
{ name = "never" }]
|
||||
|
||||
[[settings]]
|
||||
name = "clipboard-monitoring"
|
||||
default = "yes"
|
||||
filter = "mpv.net"
|
||||
help = "Monitors the clipboard for URLs to play."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "process-instance"
|
||||
default = "single"
|
||||
filter = "mpv.net"
|
||||
help = "Defines if more then one mpv.net process is allowed."
|
||||
options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" },
|
||||
{ name = "single", help = "Force a single process everytime the shell starts mpv.net" },
|
||||
{ name = "queue", help = "Force a single process and add files to playlist" }]
|
||||
@@ -13,11 +13,11 @@
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="6*" />
|
||||
<ColumnDefinition Width="100" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Controls:SearchTextBoxUserControl HintText="Find a setting" x:Name="SearchControl" Width="250" Margin="0,20,0,10" Grid.ColumnSpan="2" />
|
||||
<ScrollViewer x:Name="MainScrollViewer" VerticalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="1" Margin="0,0,0,10">
|
||||
<Controls:SearchTextBoxUserControl HintText="Find a setting" x:Name="SearchControl" Width="250" Margin="0,20,0,0" Grid.ColumnSpan="2"/>
|
||||
<ScrollViewer x:Name="MainScrollViewer" VerticalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="2" Margin="0,0,0,10">
|
||||
<StackPanel x:Name="MainStackPanel"></StackPanel>
|
||||
</ScrollViewer>
|
||||
<StackPanel Margin="20,0,0,0" Grid.Row="1">
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace mpvnet
|
||||
{
|
||||
public partial class ConfWindow : Window
|
||||
{
|
||||
private List<SettingBase> MpvSettingsDefinitions = Settings.LoadSettings(Properties.Resources.mpvConfToml);
|
||||
private List<SettingBase> MpvNetSettingsDefinitions = Settings.LoadSettings(Properties.Resources.mpvNetConfToml);
|
||||
private List<SettingBase> SettingsDefinitions = Settings.LoadSettings(Properties.Resources.mpvConfToml);
|
||||
private List<SettingBase> NetSettingsDefinitions = Settings.LoadSettings(Properties.Resources.mpvNetConfToml);
|
||||
private Dictionary<string, Dictionary<string, string>> Comments = new Dictionary<string, Dictionary<string, string>>();
|
||||
|
||||
public ObservableCollection<string> FilterStrings { get; } = new ObservableCollection<string>();
|
||||
@@ -26,8 +26,8 @@ namespace mpvnet
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
||||
LoadSettings(MpvSettingsDefinitions, MpvConf);
|
||||
LoadSettings(MpvNetSettingsDefinitions, MpvNetConf);
|
||||
LoadSettings(SettingsDefinitions, Conf);
|
||||
LoadSettings(NetSettingsDefinitions, NetConf);
|
||||
SearchControl.Text = RegistryHelp.GetString(@"HKCU\Software\mpv.net", "config editor search");
|
||||
|
||||
if (App.IsDarkMode)
|
||||
@@ -80,21 +80,21 @@ namespace mpvnet
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> _mpvConf;
|
||||
private Dictionary<string, string> _Conf;
|
||||
|
||||
public Dictionary<string, string> MpvConf {
|
||||
public Dictionary<string, string> Conf {
|
||||
get {
|
||||
if (_mpvConf == null) _mpvConf = LoadConf(mp.MpvConfPath);
|
||||
return _mpvConf;
|
||||
if (_Conf == null) _Conf = LoadConf(mp.ConfPath);
|
||||
return _Conf;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> _mpvNetConf;
|
||||
private Dictionary<string, string> _NetConf;
|
||||
|
||||
public Dictionary<string, string> MpvNetConf {
|
||||
public Dictionary<string, string> NetConf {
|
||||
get {
|
||||
if (_mpvNetConf == null) _mpvNetConf = LoadConf(mp.MpvNetConfPath);
|
||||
return _mpvNetConf;
|
||||
if (_NetConf == null) _NetConf = LoadConf(App.ConfFilePath);
|
||||
return _NetConf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,19 +139,19 @@ namespace mpvnet
|
||||
{
|
||||
bool isDirty = false;
|
||||
|
||||
foreach (SettingBase i in MpvSettingsDefinitions)
|
||||
foreach (SettingBase i in SettingsDefinitions)
|
||||
if (i.StartValue != i.Value)
|
||||
isDirty = true;
|
||||
|
||||
foreach (SettingBase i in MpvNetSettingsDefinitions)
|
||||
foreach (SettingBase i in NetSettingsDefinitions)
|
||||
if (i.StartValue != i.Value)
|
||||
isDirty = true;
|
||||
|
||||
if (!isDirty)
|
||||
return;
|
||||
|
||||
WriteToDisk(mp.MpvConfPath, MpvConf, MpvSettingsDefinitions);
|
||||
WriteToDisk(mp.MpvNetConfPath, MpvNetConf, MpvNetSettingsDefinitions);
|
||||
WriteToDisk(mp.ConfPath, Conf, SettingsDefinitions);
|
||||
WriteToDisk(App.ConfFilePath, NetConf, NetSettingsDefinitions);
|
||||
|
||||
Msg.Show("Changes will be available on next mpv.net startup.");
|
||||
}
|
||||
@@ -228,7 +228,7 @@ namespace mpvnet
|
||||
|
||||
private void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Process.Start(Path.GetDirectoryName(mp.MpvConfPath));
|
||||
Process.Start(Path.GetDirectoryName(mp.ConfPath));
|
||||
}
|
||||
|
||||
private void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace mpvnet
|
||||
void Execute()
|
||||
{
|
||||
if (ListView.SelectedItem != null)
|
||||
mp.LoadFiles(ListView.SelectedItem as string);
|
||||
mp.Load(ListView.SelectedItem as string);
|
||||
Keyboard.Focus(FilterTextBox);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,15 +24,6 @@ namespace mpvnet
|
||||
bool IgnoreDpiChanged = true;
|
||||
List<string> RecentFiles;
|
||||
|
||||
public string MpvNetDarkMode { get; set; } = "always";
|
||||
public bool MpvFullscreen { get; set; }
|
||||
public float MpvAutofit { get; set; } = 0.50f;
|
||||
public int MpvScreen { get; set; } = -1;
|
||||
public string MpvSid { get; set; } = "";
|
||||
public string MpvAid { get; set; } = "";
|
||||
public string MpvVid { get; set; } = "";
|
||||
public int MpvEdition { get; set; }
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -49,25 +40,20 @@ namespace mpvnet
|
||||
MinimumSize = new Size(FontHeight * 16, FontHeight * 9);
|
||||
Text += " " + Application.ProductVersion;
|
||||
|
||||
object recent = RegistryHelp.GetObject("HKCU\\Software\\" + Application.ProductName, "Recent");
|
||||
object recent = RegistryHelp.GetObject(App.RegPath, "Recent");
|
||||
|
||||
if (recent is string[] r)
|
||||
RecentFiles = new List<string>(r);
|
||||
else
|
||||
RecentFiles = new List<string>();
|
||||
|
||||
foreach (var i in mp.mpvConf)
|
||||
ProcessMpvProperty(i.Key, i.Value);
|
||||
var dummy = mp.Conf;
|
||||
App.ProcessCommandLineEarly();
|
||||
|
||||
foreach (var i in mp.mpvNetConf)
|
||||
ProcessMpvNetProperty(i.Key, i.Value);
|
||||
if (mp.Screen == -1) mp.Screen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen);
|
||||
SetScreen(mp.Screen);
|
||||
|
||||
ProcessCommandLineEarly();
|
||||
|
||||
if (MpvScreen == -1) MpvScreen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen);
|
||||
SetScreen(MpvScreen);
|
||||
|
||||
ChangeFullscreen(MpvFullscreen);
|
||||
ChangeFullscreen(mp.Fullscreen);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -94,7 +80,7 @@ namespace mpvnet
|
||||
{
|
||||
MenuItem mi = new MenuItem(track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "vid", track.ID.ToString()); };
|
||||
mi.Checked = MpvVid == track.ID.ToString();
|
||||
mi.Checked = mp.Vid == track.ID.ToString();
|
||||
trackMenuItem.DropDownItems.Add(mi);
|
||||
}
|
||||
|
||||
@@ -105,7 +91,7 @@ namespace mpvnet
|
||||
{
|
||||
MenuItem mi = new MenuItem(track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "aid", track.ID.ToString()); };
|
||||
mi.Checked = MpvAid == track.ID.ToString();
|
||||
mi.Checked = mp.Aid == track.ID.ToString();
|
||||
trackMenuItem.DropDownItems.Add(mi);
|
||||
}
|
||||
|
||||
@@ -116,7 +102,7 @@ namespace mpvnet
|
||||
{
|
||||
MenuItem mi = new MenuItem(track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "sid", track.ID.ToString()); };
|
||||
mi.Checked = MpvSid == track.ID.ToString();
|
||||
mi.Checked = mp.Sid == track.ID.ToString();
|
||||
trackMenuItem.DropDownItems.Add(mi);
|
||||
}
|
||||
|
||||
@@ -124,7 +110,7 @@ namespace mpvnet
|
||||
{
|
||||
MenuItem mi = new MenuItem("S: No subtitles");
|
||||
mi.Action = () => { mp.commandv("set", "sid", "no"); };
|
||||
mi.Checked = MpvSid == "no";
|
||||
mi.Checked = mp.Sid == "no";
|
||||
trackMenuItem.DropDownItems.Add(mi);
|
||||
}
|
||||
|
||||
@@ -135,7 +121,7 @@ namespace mpvnet
|
||||
{
|
||||
MenuItem mi = new MenuItem(track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "edition", track.ID.ToString()); };
|
||||
mi.Checked = MpvEdition == track.ID;
|
||||
mi.Checked = mp.Edition == track.ID;
|
||||
trackMenuItem.DropDownItems.Add(mi);
|
||||
}
|
||||
}
|
||||
@@ -166,7 +152,7 @@ namespace mpvnet
|
||||
recent.DropDownItems.Clear();
|
||||
|
||||
foreach (string path in RecentFiles)
|
||||
MenuItem.Add(recent.DropDownItems, path, () => mp.LoadFiles(path));
|
||||
MenuItem.Add(recent.DropDownItems, path, () => mp.Load(path));
|
||||
|
||||
recent.DropDownItems.Add(new ToolStripSeparator());
|
||||
MenuItem mi = new MenuItem("Clear List");
|
||||
@@ -215,7 +201,7 @@ namespace mpvnet
|
||||
{
|
||||
if (IsFullscreen || mp.VideoSize.Width == 0) return;
|
||||
Screen screen = Screen.FromControl(this);
|
||||
int height = Convert.ToInt32(screen.Bounds.Height * MpvAutofit);
|
||||
int height = Convert.ToInt32(screen.Bounds.Height * mp.Autofit);
|
||||
int width = Convert.ToInt32(height * mp.VideoSize.Width / (double)mp.VideoSize.Height);
|
||||
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
|
||||
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
|
||||
@@ -230,7 +216,7 @@ namespace mpvnet
|
||||
if (IsFullscreen || mp.VideoSize.Width == 0) return;
|
||||
Screen screen = Screen.FromControl(this);
|
||||
int height = ClientSize.Height;
|
||||
if (height > screen.Bounds.Height * 0.9) height = Convert.ToInt32(screen.Bounds.Height * MpvAutofit);
|
||||
if (height > screen.Bounds.Height * 0.9) height = Convert.ToInt32(screen.Bounds.Height * mp.Autofit);
|
||||
int width = Convert.ToInt32(height * mp.VideoSize.Width / (double)mp.VideoSize.Height);
|
||||
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
|
||||
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
|
||||
@@ -244,66 +230,6 @@ namespace mpvnet
|
||||
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, left, top, rect.Width, rect.Height, 4 /* SWP_NOZORDER */);
|
||||
}
|
||||
|
||||
protected void ProcessCommandLineEarly()
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs().Skip(1);
|
||||
|
||||
foreach (string i in args)
|
||||
{
|
||||
if (i.StartsWith("--"))
|
||||
{
|
||||
if (i.Contains("="))
|
||||
{
|
||||
string left = i.Substring(2, i.IndexOf("=") - 2);
|
||||
string right = i.Substring(left.Length + 3);
|
||||
ProcessMpvProperty(left, right);
|
||||
ProcessMpvNetProperty(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
string switchName = i.Substring(2);
|
||||
|
||||
switch (switchName)
|
||||
{
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
MpvFullscreen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessMpvProperty(string name, string value)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "autofit":
|
||||
if (value.Length == 3 && value.EndsWith("%"))
|
||||
if (int.TryParse(value.Substring(0, 2), out int result))
|
||||
MpvAutofit = result / 100f;
|
||||
break;
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
MpvFullscreen = value == "yes";
|
||||
break;
|
||||
case "screen":
|
||||
MpvScreen = Convert.ToInt32(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessMpvNetProperty(string name, string value)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "dark-mode":
|
||||
MpvNetDarkMode = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildMenu()
|
||||
{
|
||||
string content = File.ReadAllText(mp.InputConfPath);
|
||||
@@ -414,12 +340,17 @@ namespace mpvnet
|
||||
case 0x0104: // WM_SYSKEYDOWN
|
||||
case 0x0105: // WM_SYSKEYUP
|
||||
case 0x020A: // WM_MOUSEWHEEL
|
||||
if (mp.MpvWindowHandle != IntPtr.Zero)
|
||||
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
if (mp.WindowHandle != IntPtr.Zero)
|
||||
Native.SendMessage(mp.WindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
break;
|
||||
case 0x0200: // WM_MOUSEMOVE
|
||||
Point pos = PointToClient(Cursor.Position);
|
||||
mp.command_string($"mouse {pos.X} {pos.Y}");
|
||||
if (CursorHelp.IsPosDifferent(LastCursorPosChanged)) CursorHelp.Show();
|
||||
break;
|
||||
case 0x319: // WM_APPCOMMAND
|
||||
if (mp.MpvWindowHandle != IntPtr.Zero)
|
||||
Native.PostMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
if (mp.WindowHandle != IntPtr.Zero)
|
||||
Native.PostMessage(mp.WindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
break;
|
||||
case 0x203: // Native.WM.LBUTTONDBLCLK
|
||||
if (!IsMouseInOSC())
|
||||
@@ -449,6 +380,30 @@ namespace mpvnet
|
||||
m.Result = new IntPtr(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.Msg == SingleProcess.Message)
|
||||
{
|
||||
object filesObject = RegistryHelp.GetObject(App.RegPath, "ShellFiles");
|
||||
|
||||
if (filesObject is string[] files)
|
||||
{
|
||||
switch (RegistryHelp.GetString(App.RegPath, "ProcessInstanceMode"))
|
||||
{
|
||||
case "single":
|
||||
mp.Load(files);
|
||||
break;
|
||||
case "queue":
|
||||
foreach (string file in files)
|
||||
mp.commandv("loadfile", file, "append");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RegistryHelp.RemoveValue(App.RegPath, "ShellFiles");
|
||||
Activate();
|
||||
return;
|
||||
}
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
@@ -463,9 +418,9 @@ namespace mpvnet
|
||||
{
|
||||
base.OnDragDrop(e);
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
mp.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[]);
|
||||
mp.Load(e.Data.GetData(DataFormats.FileDrop) as String[]);
|
||||
if (e.Data.GetDataPresent(DataFormats.Text))
|
||||
mp.LoadFiles(e.Data.GetData(DataFormats.Text).ToString());
|
||||
mp.Load(e.Data.GetData(DataFormats.Text).ToString());
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
@@ -485,15 +440,6 @@ namespace mpvnet
|
||||
mp.commandv("quit");
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
mp.command_string($"mouse {e.X} {e.Y}");
|
||||
|
||||
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
|
||||
CursorHelp.Show();
|
||||
}
|
||||
|
||||
bool IsMouseInOSC() => PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
|
||||
|
||||
void Timer_Tick(object sender, EventArgs e)
|
||||
@@ -529,26 +475,25 @@ namespace mpvnet
|
||||
|
||||
void mpPropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value));
|
||||
|
||||
void mpPropChangeAid(string value) => MpvAid = value;
|
||||
void mpPropChangeAid(string value) => mp.Aid = value;
|
||||
|
||||
void mpPropChangeSid(string value) => MpvSid = value;
|
||||
void mpPropChangeSid(string value) => mp.Sid = value;
|
||||
|
||||
void mpPropChangeVid(string value) => MpvVid = value;
|
||||
void mpPropChangeVid(string value) => mp.Vid = value;
|
||||
|
||||
void mpPropChangeEdition(int value) => MpvEdition = value;
|
||||
void mpPropChangeEdition(int value) => mp.Edition = value;
|
||||
|
||||
protected override void OnShown(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
if ((MpvNetDarkMode == "system" && Sys.IsDarkTheme) || MpvNetDarkMode == "always")
|
||||
ToolStripRendererEx.ColorTheme = Color.Black;
|
||||
if (App.IsDarkMode) ToolStripRendererEx.ColorTheme = Color.Black;
|
||||
ContextMenu = new ContextMenuStripEx(components);
|
||||
ContextMenu.Opened += ContextMenu_Opened;
|
||||
ContextMenu.Opening += ContextMenu_Opening;
|
||||
BuildMenu();
|
||||
ContextMenuStrip = ContextMenu;
|
||||
IgnoreDpiChanged = false;
|
||||
CheckURL();
|
||||
CheckURLinClipboard();
|
||||
}
|
||||
|
||||
protected override void OnResize(EventArgs e)
|
||||
@@ -560,7 +505,7 @@ namespace mpvnet
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
base.OnFormClosed(e);
|
||||
RegistryHelp.SetObject("HKCU\\Software\\" + Application.ProductName, "Recent", RecentFiles.ToArray());
|
||||
RegistryHelp.SetObject(App.RegPath, "Recent", RecentFiles.ToArray());
|
||||
mp.commandv("quit");
|
||||
mp.AutoResetEvent.WaitOne(3000);
|
||||
}
|
||||
@@ -574,19 +519,20 @@ namespace mpvnet
|
||||
protected override void OnActivated(EventArgs e)
|
||||
{
|
||||
base.OnActivated(e);
|
||||
CheckURL();
|
||||
CheckURLinClipboard();
|
||||
}
|
||||
|
||||
void CheckURL()
|
||||
void CheckURLinClipboard()
|
||||
{
|
||||
if (App.ClipboardMonitoring != "yes") return;
|
||||
string clipboard = Clipboard.GetText();
|
||||
|
||||
if (clipboard.StartsWith("http") && RegistryHelp.GetString("HKCU\\Software\\" + Application.ProductName, "LastURL") != clipboard && Visible)
|
||||
if (clipboard.StartsWith("http") && RegistryHelp.GetString(App.RegPath, "LastURL") != clipboard && Visible)
|
||||
{
|
||||
RegistryHelp.SetObject("HKCU\\Software\\" + Application.ProductName, "LastURL", clipboard);
|
||||
RegistryHelp.SetObject(App.RegPath, "LastURL", clipboard);
|
||||
|
||||
if (Msg.ShowQuestion("Play URL?", clipboard) == MsgResult.OK)
|
||||
mp.LoadFiles(clipboard);
|
||||
mp.Load(clipboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ namespace mpvnet
|
||||
public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW
|
||||
public static event Action Hook; // MPV_EVENT_HOOK
|
||||
|
||||
public static IntPtr MpvHandle { get; set; }
|
||||
public static IntPtr MpvWindowHandle { get; set; }
|
||||
public static IntPtr Handle { get; set; }
|
||||
public static IntPtr WindowHandle { get; set; }
|
||||
public static Addon Addon { get; set; }
|
||||
public static bool IsLogoVisible { set; get; }
|
||||
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<bool>>>();
|
||||
@@ -65,15 +65,22 @@ namespace mpvnet
|
||||
public static List<MediaTrack> MediaTracks { get; set; } = new List<MediaTrack>();
|
||||
public static List<KeyValuePair<string, double>> Chapters { get; set; } = new List<KeyValuePair<string, double>>();
|
||||
|
||||
public static string InputConfPath { get; } = MpvConfFolder + "\\input.conf";
|
||||
public static string MpvConfPath { get; } = MpvConfFolder + "\\mpv.conf";
|
||||
public static string MpvNetConfPath { get; } = MpvConfFolder + "\\mpvnet.conf";
|
||||
public static string InputConfPath { get; } = ConfFolder + "\\input.conf";
|
||||
public static string ConfPath { get; } = ConfFolder + "\\mpv.conf";
|
||||
|
||||
static string _MpvConfFolder;
|
||||
public static bool Fullscreen { get; set; }
|
||||
public static float Autofit { get; set; } = 0.50f;
|
||||
public static int Screen { get; set; } = -1;
|
||||
public static string Sid { get; set; } = "";
|
||||
public static string Aid { get; set; } = "";
|
||||
public static string Vid { get; set; } = "";
|
||||
public static int Edition { get; set; }
|
||||
|
||||
public static string MpvConfFolder {
|
||||
static string _ConfFolder;
|
||||
|
||||
public static string ConfFolder {
|
||||
get {
|
||||
if (_MpvConfFolder == null)
|
||||
if (_ConfFolder == null)
|
||||
{
|
||||
string portableFolder = Application.StartupPath + "\\portable_config\\";
|
||||
string appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
|
||||
@@ -91,75 +98,61 @@ namespace mpvnet
|
||||
td.AddCommandLink("portable", portableFolder, portableFolder);
|
||||
td.AddCommandLink("startup", startupFolder, startupFolder);
|
||||
td.AllowCancel = false;
|
||||
_MpvConfFolder = td.Show();
|
||||
_ConfFolder = td.Show();
|
||||
}
|
||||
}
|
||||
else if (Directory.Exists(portableFolder))
|
||||
_MpvConfFolder = portableFolder;
|
||||
_ConfFolder = portableFolder;
|
||||
else if (Directory.Exists(appdataFolder))
|
||||
_MpvConfFolder = appdataFolder;
|
||||
_ConfFolder = appdataFolder;
|
||||
else if (File.Exists(Application.StartupPath + "\\mpv.conf"))
|
||||
_MpvConfFolder = Application.StartupPath + "\\";
|
||||
_ConfFolder = Application.StartupPath + "\\";
|
||||
|
||||
if (string.IsNullOrEmpty(_MpvConfFolder)) _MpvConfFolder = appdataFolder;
|
||||
if (!Directory.Exists(_MpvConfFolder)) Directory.CreateDirectory(_MpvConfFolder);
|
||||
if (string.IsNullOrEmpty(_ConfFolder)) _ConfFolder = appdataFolder;
|
||||
if (!Directory.Exists(_ConfFolder)) Directory.CreateDirectory(_ConfFolder);
|
||||
|
||||
if (!File.Exists(_MpvConfFolder + "\\input.conf"))
|
||||
File.WriteAllText(_MpvConfFolder + "\\input.conf", Properties.Resources.inputConf);
|
||||
if (!File.Exists(_ConfFolder + "\\input.conf"))
|
||||
File.WriteAllText(_ConfFolder + "\\input.conf", Properties.Resources.inputConf);
|
||||
|
||||
if (!File.Exists(_MpvConfFolder + "\\mpv.conf"))
|
||||
File.WriteAllText(_MpvConfFolder + "\\mpv.conf", Properties.Resources.mpvConf);
|
||||
if (!File.Exists(_ConfFolder + "\\mpv.conf"))
|
||||
File.WriteAllText(_ConfFolder + "\\mpv.conf", Properties.Resources.mpvConf);
|
||||
}
|
||||
return _MpvConfFolder;
|
||||
return _ConfFolder;
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, string> _mpvConf;
|
||||
static Dictionary<string, string> _Conf;
|
||||
|
||||
public static Dictionary<string, string> mpvConf {
|
||||
public static Dictionary<string, string> Conf {
|
||||
get {
|
||||
if (_mpvConf == null)
|
||||
if (_Conf == null)
|
||||
{
|
||||
_mpvConf = new Dictionary<string, string>();
|
||||
_Conf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(MpvConfPath))
|
||||
foreach (var i in File.ReadAllLines(MpvConfPath))
|
||||
if (File.Exists(ConfPath))
|
||||
foreach (var i in File.ReadAllLines(ConfPath))
|
||||
if (i.Contains("=") && ! i.StartsWith("#"))
|
||||
_mpvConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||
}
|
||||
return _mpvConf;
|
||||
}
|
||||
}
|
||||
_Conf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||
|
||||
static Dictionary<string, string> _mpvNetConf;
|
||||
|
||||
public static Dictionary<string, string> mpvNetConf {
|
||||
get {
|
||||
if (_mpvNetConf == null)
|
||||
{
|
||||
_mpvNetConf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(MpvNetConfPath))
|
||||
foreach (string i in File.ReadAllLines(MpvNetConfPath))
|
||||
if (i.Contains("=") && !i.StartsWith("#"))
|
||||
_mpvNetConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||
foreach (var i in Conf)
|
||||
ProcessProperty(i.Key, i.Value);
|
||||
}
|
||||
return _mpvNetConf;
|
||||
return _Conf;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
string dummy = MpvConfFolder;
|
||||
string dummy = ConfFolder;
|
||||
LoadLibrary("mpv-1.dll");
|
||||
MpvHandle = mpv_create();
|
||||
Handle = mpv_create();
|
||||
set_property_string("input-default-bindings", "yes");
|
||||
set_property_string("osc", "yes");
|
||||
set_property_string("config", "yes");
|
||||
set_property_string("wid", MainForm.Hwnd.ToString());
|
||||
set_property_string("force-window", "yes");
|
||||
set_property_string("input-media-keys", "yes");
|
||||
mpv_initialize(MpvHandle);
|
||||
mpv_initialize(Handle);
|
||||
ShowLogo();
|
||||
ProcessCommandLine();
|
||||
Task.Run(() => { LoadScripts(); });
|
||||
@@ -184,8 +177,8 @@ namespace mpvnet
|
||||
if (Path.GetExtension(scriptPath) == ".ps1")
|
||||
PowerShellScript.Init(scriptPath);
|
||||
|
||||
if (Directory.Exists(mp.MpvConfFolder + "Scripts"))
|
||||
foreach (var scriptPath in Directory.GetFiles(mp.MpvConfFolder + "Scripts"))
|
||||
if (Directory.Exists(mp.ConfFolder + "Scripts"))
|
||||
foreach (var scriptPath in Directory.GetFiles(mp.ConfFolder + "Scripts"))
|
||||
if (Path.GetExtension(scriptPath) == ".py")
|
||||
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
|
||||
else if (Path.GetExtension(scriptPath) == ".ps1")
|
||||
@@ -196,11 +189,14 @@ namespace mpvnet
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
IntPtr ptr = mpv_wait_event(MpvHandle, -1);
|
||||
IntPtr ptr = mpv_wait_event(Handle, -1);
|
||||
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event));
|
||||
|
||||
if (MpvWindowHandle == IntPtr.Zero)
|
||||
MpvWindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
|
||||
if (WindowHandle == IntPtr.Zero)
|
||||
{
|
||||
WindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
|
||||
//Native.EnableWindow(WindowHandle, true);
|
||||
}
|
||||
|
||||
//Debug.WriteLine(evt.event_id.ToString());
|
||||
|
||||
@@ -405,11 +401,11 @@ namespace mpvnet
|
||||
|
||||
public static void commandv(params string[] args)
|
||||
{
|
||||
if (MpvHandle == IntPtr.Zero)
|
||||
if (Handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
IntPtr mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out IntPtr[] byteArrayPointers);
|
||||
int err = mpv_command(MpvHandle, mainPtr);
|
||||
int err = mpv_command(Handle, mainPtr);
|
||||
|
||||
if (err < 0)
|
||||
throw new Exception($"{(mpv_error)err}");
|
||||
@@ -422,10 +418,10 @@ namespace mpvnet
|
||||
|
||||
public static void command_string(string command, bool throwException = false)
|
||||
{
|
||||
if (MpvHandle == IntPtr.Zero)
|
||||
if (Handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
int err = mpv_command_string(MpvHandle, command);
|
||||
int err = mpv_command_string(Handle, command);
|
||||
|
||||
if (err < 0 && throwException)
|
||||
throw new Exception($"{(mpv_error)err}\r\n\r\n" + command);
|
||||
@@ -434,7 +430,7 @@ namespace mpvnet
|
||||
public static void set_property_string(string name, string value, bool throwOnException = false)
|
||||
{
|
||||
byte[] bytes = GetUtf8Bytes(value);
|
||||
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
|
||||
int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -444,7 +440,7 @@ namespace mpvnet
|
||||
{
|
||||
try
|
||||
{
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
|
||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -463,7 +459,7 @@ namespace mpvnet
|
||||
|
||||
public static int get_property_int(string name, bool throwOnException = false)
|
||||
{
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
|
||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -474,7 +470,7 @@ namespace mpvnet
|
||||
public static double get_property_number(string name, bool throwOnException = false)
|
||||
{
|
||||
double val = 0;
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
|
||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -484,7 +480,7 @@ namespace mpvnet
|
||||
|
||||
public static bool get_property_bool(string name, bool throwOnException = false)
|
||||
{
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_FLAG, out IntPtr lpBuffer);
|
||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_FLAG, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -495,7 +491,7 @@ namespace mpvnet
|
||||
public static void set_property_int(string name, int value, bool throwOnException = false)
|
||||
{
|
||||
Int64 val = value;
|
||||
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
|
||||
int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -503,7 +499,7 @@ namespace mpvnet
|
||||
|
||||
public static void observe_property_int(string name, Action<int> action)
|
||||
{
|
||||
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_INT64);
|
||||
int err = mpv_observe_property(Handle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_INT64);
|
||||
|
||||
if (err < 0)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -513,7 +509,7 @@ namespace mpvnet
|
||||
|
||||
public static void observe_property_bool(string name, Action<bool> action)
|
||||
{
|
||||
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
|
||||
int err = mpv_observe_property(Handle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
|
||||
|
||||
if (err < 0)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -523,7 +519,7 @@ namespace mpvnet
|
||||
|
||||
public static void observe_property_string(string name, Action<string> action)
|
||||
{
|
||||
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_STRING);
|
||||
int err = mpv_observe_property(Handle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_STRING);
|
||||
|
||||
if (err < 0)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
@@ -537,10 +533,16 @@ namespace mpvnet
|
||||
List<string> files = new List<string>();
|
||||
|
||||
foreach (string i in args)
|
||||
if (!i.StartsWith("--") && File.Exists(i))
|
||||
{
|
||||
if (!i.StartsWith("--") && (File.Exists(i) || i == "-" || i.StartsWith("http")))
|
||||
{
|
||||
files.Add(i);
|
||||
if (i.StartsWith("http"))
|
||||
RegistryHelp.SetObject(App.RegPath, "LastURL", i);
|
||||
}
|
||||
}
|
||||
|
||||
mp.LoadFiles(files.ToArray());
|
||||
mp.Load(files.ToArray());
|
||||
|
||||
foreach (string i in args)
|
||||
{
|
||||
@@ -558,10 +560,26 @@ namespace mpvnet
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadFiles(params string[] files)
|
||||
public static void Load(params string[] files)
|
||||
{
|
||||
if (files is null || files.Length == 0) return;
|
||||
HideLogo();
|
||||
List<string> fileList = files.ToList();
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
string ext = Path.GetExtension(file).TrimStart('.').ToLower();
|
||||
|
||||
if (App.SubtitleTypes.Contains(ext))
|
||||
{
|
||||
mp.commandv("sub-add", file);
|
||||
fileList.Remove(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (fileList.Count == 0) return;
|
||||
files = fileList.ToArray();
|
||||
|
||||
int count = mp.get_property_int("playlist-count");
|
||||
|
||||
foreach (string file in files)
|
||||
@@ -643,7 +661,7 @@ namespace mpvnet
|
||||
|
||||
if (File.Exists(LastHistoryPath) && totalMinutes > 1)
|
||||
{
|
||||
string historyFilepath = mp.MpvConfFolder + "history.txt";
|
||||
string historyFilepath = mp.ConfFolder + "history.txt";
|
||||
|
||||
File.AppendAllText(historyFilepath, DateTime.Now.ToString().Substring(0, 16) +
|
||||
" " + totalMinutes.ToString().PadLeft(3) + " " +
|
||||
@@ -658,6 +676,7 @@ namespace mpvnet
|
||||
{
|
||||
if (MainForm.Instance is null) return;
|
||||
Rectangle cr = MainForm.Instance.ClientRectangle;
|
||||
if (cr.Width == 0 || cr.Height == 0) return;
|
||||
|
||||
using (Bitmap b = new Bitmap(cr.Width, cr.Height))
|
||||
{
|
||||
@@ -676,6 +695,25 @@ namespace mpvnet
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessProperty(string name, string value)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "autofit":
|
||||
if (value.Length == 3 && value.EndsWith("%"))
|
||||
if (int.TryParse(value.Substring(0, 2), out int result))
|
||||
mp.Autofit = result / 100f;
|
||||
break;
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
mp.Fullscreen = value == "yes";
|
||||
break;
|
||||
case "screen":
|
||||
mp.Screen = Convert.ToInt32(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadMetaData()
|
||||
{
|
||||
lock (MediaTracks)
|
||||
|
||||
Reference in New Issue
Block a user