Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fa4418e1f | ||
|
|
c89bbe319d | ||
|
|
08089b0fc7 | ||
|
|
4116aeb65a | ||
|
|
bfeb041d08 | ||
|
|
2dca7eb599 | ||
|
|
87213f9610 | ||
|
|
8a6f00bdf2 | ||
|
|
448add600b | ||
|
|
6669a42dcd | ||
|
|
3df26a4b90 | ||
|
|
3ccb80f359 | ||
|
|
636e36583d | ||
|
|
d7617bda6d | ||
|
|
12f1d70969 | ||
|
|
f7b908a5c4 | ||
|
|
1080d0afd7 | ||
|
|
77ba7f105c | ||
|
|
07b6d4379e | ||
|
|
8a6659b1bf | ||
|
|
e7d41ff626 | ||
|
|
f2c526348d | ||
|
|
b4d2a7e86d | ||
|
|
98f8e7090a | ||
|
|
aeb5958be6 | ||
|
|
1d16861b0b | ||
|
|
4366c47a09 | ||
|
|
fc3dd45b72 | ||
|
|
66cf3a9b2f | ||
|
|
a9c2150c47 | ||
|
|
b77bbd5aec | ||
|
|
92b58873e2 | ||
|
|
c8214b2d94 | ||
|
|
f77defecfd | ||
|
|
6fec4bada7 | ||
|
|
c508761c36 | ||
|
|
3fd1285ad8 | ||
|
|
91a67c29a7 | ||
|
|
c8ce0b6dfc |
@@ -1,8 +1,8 @@
|
||||
Imports System.ComponentModel.Composition
|
||||
Imports System.IO
|
||||
Imports System.Windows.Forms
|
||||
|
||||
Imports mpvnet
|
||||
Imports mpvnet.StaticUsing
|
||||
|
||||
Imports CSScriptLibrary
|
||||
|
||||
@@ -13,7 +13,8 @@ Public Class CSScriptAddon
|
||||
Sub New()
|
||||
Dim scriptDir = mp.mpvConfFolderPath + "scripts"
|
||||
If Not Directory.Exists(scriptDir) Then Return
|
||||
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs")
|
||||
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList
|
||||
csFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\Scripts", "*.cs"))
|
||||
If csFiles.Count = 0 Then Return
|
||||
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom
|
||||
|
||||
@@ -21,7 +22,7 @@ Public Class CSScriptAddon
|
||||
Try
|
||||
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(i))
|
||||
Catch ex As Exception
|
||||
MsgError(ex.ToString)
|
||||
MainForm.Instance.ShowMsgBox(ex.ToString(), MessageBoxIcon.Error)
|
||||
End Try
|
||||
Next
|
||||
End Sub
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<OutputPath>..\mpv.net\bin\Debug\Addons\CSScriptAddon\</OutputPath>
|
||||
<OutputPath>..\mpv.net\bin\Addons\CSScriptAddon\</OutputPath>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
|
||||
@@ -29,7 +29,7 @@
|
||||
<DefineDebug>false</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<OutputPath>..\mpv.net\bin\Addons\CSScriptAddon\</OutputPath>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
|
||||
@@ -55,6 +55,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
||||
109
README.md
109
README.md
@@ -1,86 +1,79 @@
|
||||
# mpv.net
|
||||
|
||||
mpv.net is a libmpv based media player for Windows, it looks and works like mpv, even shares the settings and therefore the mpv documentation applies.
|
||||
mpv.net is a libmpv based media player for Windows, it looks and works like mpv and also shares the same settings as mpv and therefore the mpv documentation applies.
|
||||
|
||||
mpv and mpv.net have a learning curve and are only suitable for experienced users.
|
||||
mpv and mpv.net have a learning curve.
|
||||
|
||||
mpv manual: https://mpv.io/manual/master/
|
||||
mpv manual: <https://mpv.io/manual/master/>
|
||||
|
||||
Table of contents
|
||||
-----------------
|
||||
|
||||
- [Features](#features)
|
||||
- [Screenshots](#screenshots)
|
||||
- [Context Menu](#context-menu)
|
||||
- [Settings](#settings)
|
||||
- [Scripting](#scripting)
|
||||
- [Support](#support)
|
||||
- [Changelog](#changelog)
|
||||
|
||||
### Features
|
||||
|
||||
- Customizable context menu defined in the same file as the keybindings
|
||||
- Addons support for using .NET languages
|
||||
- C# scripts implemented with CS-Script
|
||||
- mpv's OSC, IPC, Lua/JS, conf files and more
|
||||
- Addon API for .NET languages
|
||||
- Scripting API for Python, C#, Lua, JavaScript and PowerShell
|
||||
- mpv's OSC, IPC, conf files and more
|
||||
|
||||

|
||||
### Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Context Menu
|
||||
|
||||
The context menu can be customized via input.conf file located at:
|
||||
|
||||
C:\Users\Frank\AppData\Roaming\mpv\input.conf
|
||||
|
||||
if it misses mpv.net generates it with the following defaults:
|
||||
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input_conf.txt
|
||||
|
||||
### C# Scripting
|
||||
|
||||
A simple C# script located at: C:\Users\Frank\AppData\Roaming\mpv\scripts\test.cs
|
||||
|
||||
```
|
||||
using mpvnet;
|
||||
|
||||
class Script
|
||||
{
|
||||
public Script()
|
||||
{
|
||||
var fs = mpv.GetStringProp("fullscreen");
|
||||
mpv.Command("show-text", "fullscreen: " + fs);
|
||||
mpv.ObserveBoolProp("fullscreen", FullscreenChange);
|
||||
}
|
||||
|
||||
void FullscreenChange(bool val)
|
||||
{
|
||||
mpv.Command("show-text", "fullscreen: " + val.ToString());
|
||||
}
|
||||
}
|
||||
C:\Users\username\AppData\Roaming\mpv\input.conf
|
||||
```
|
||||
if it's missing mpv.net generates it with the following defaults:
|
||||
|
||||
### Changes
|
||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt>
|
||||
|
||||
### 1.1
|
||||
### Settings
|
||||
|
||||
- added support for Python scripting via IronPython
|
||||
- show tracks and show playlist didn't work because the duration wasn't defined in the key bindings
|
||||
mpv.net shares the settings with mpv, settings can be edited in a settings dialog or in a config file called mpv.conf located at:
|
||||
```
|
||||
C:\Users\user\AppData\Roaming\mpv\mpv.conf
|
||||
```
|
||||
if it's missing mpv.net generates it with the following defaults:
|
||||
|
||||
### 1.0
|
||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt>
|
||||
|
||||
- much more feature packed context menu
|
||||
### Scripting
|
||||
|
||||
### 0.2.5
|
||||
Scripting is supported for Python, C#, Lua, JavaScript and PowerShell
|
||||
|
||||
- mpv lib updated to 2019-02-24
|
||||
- UI glitch fixed the appeared when started in fullscreen mode
|
||||
- fixed default video output mode which caused video playback to fail
|
||||
https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lua,-PowerShell)
|
||||
|
||||
### 0.2.4
|
||||
### Support
|
||||
|
||||
- changed minimum runtime to .NET 4.7.2
|
||||
- fixed mpv.net not working with new mpv lib
|
||||
- the track name in the title bar was sometimes wrong
|
||||
- mpv lib updated to 2018-12-16
|
||||
- quit-watch-later added to context menu (Shift+Q) to exit and resume at the last position
|
||||
- ab loop added to menu
|
||||
- added the possibility to modify mpv.conf settings using the context menu
|
||||
- added link to the manual and default keys to the menu
|
||||
<https://forum.doom9.org/showthread.php?t=174841>
|
||||
|
||||
### 0.2.2
|
||||
<https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows>
|
||||
|
||||
- history feature added
|
||||
- mpv lib updated
|
||||
<https://github.com/stax76/mpv.net/issues>
|
||||
|
||||
### 0.2.1
|
||||
### Changelog
|
||||
|
||||
- right-click in fullscreen in the right-left corner closes the app
|
||||
### 2.0 (2019-03-28)
|
||||
|
||||
- setting track-auto-selection added to settings editor (<https://mpv.io/manual/master/#options-track-auto-selection>)
|
||||
- setting loop-playlist added to settings editor (<https://mpv.io/manual/master/#options-loop-playlist>)
|
||||
- setting audio-file-auto added to settings editor (<https://mpv.io/manual/master/#options-audio-file-auto>)
|
||||
- setting video-sync added to settings editor (<https://mpv.io/manual/master/#options-video-sync>)
|
||||
- command execute-mpv-command added to menu: Tools > Enter a mpv command for execution
|
||||
- added youtube-dl.exe, please note this will only work when a certain Visual C++ runtime is installed
|
||||
- added drag & drop support to drag & drop a youtube URL on mpv.net
|
||||
- added support to open a youtube URL from command line
|
||||
- added support for opening a URL from the menu: Open > Open URL
|
||||
@@ -51,8 +51,8 @@ namespace RatingAddon
|
||||
if (args?.Length != 2 || args[0] != "rate-file" || ! int.TryParse(args[1], out rating))
|
||||
return;
|
||||
|
||||
Dic[mp.GetStringProp("path")] = rating;
|
||||
mp.Command("show-text", $"Rating: {rating}");
|
||||
Dic[mp.get_property_string("path")] = rating;
|
||||
mp.commandv("show-text", $"Rating: {rating}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\Debug\Addons\RatingAddon\</OutputPath>
|
||||
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
@@ -25,7 +25,7 @@
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\Release\</OutputPath>
|
||||
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
||||
@@ -5,8 +5,6 @@ using System.ComponentModel.Composition.Hosting;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using static mpvnet.StaticUsing;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Addon
|
||||
@@ -42,7 +40,7 @@ namespace mpvnet
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MsgError(e.ToString());
|
||||
MainForm.Instance.ShowMsgBox(e.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using static mpvnet.StaticUsing;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Command
|
||||
@@ -22,21 +21,20 @@ namespace mpvnet
|
||||
if (commands == null)
|
||||
{
|
||||
commands = new List<Command>();
|
||||
var type = typeof(Command);
|
||||
var methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
|
||||
Type type = typeof(Command);
|
||||
MethodInfo[] methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
|
||||
|
||||
foreach (var i in methods)
|
||||
{
|
||||
var parameters = i.GetParameters();
|
||||
ParameterInfo[] parameters = i.GetParameters();
|
||||
|
||||
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(string[]))
|
||||
continue;
|
||||
|
||||
var cmd = new Command() { Name = i.Name.Replace("_","-"), Action = (Action<string[]>)i.CreateDelegate(typeof(Action<string[]>)) };
|
||||
Command cmd = new Command() { Name = i.Name.Replace("_","-"), Action = (Action<string[]>)i.CreateDelegate(typeof(Action<string[]>)) };
|
||||
commands.Add(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
@@ -60,26 +58,14 @@ namespace mpvnet
|
||||
Process.Start(mp.mpvConfFolderPath);
|
||||
}
|
||||
|
||||
public static void show_keys(string[] args)
|
||||
public static void show_input_editor(string[] args)
|
||||
{
|
||||
Process.Start(mp.InputConfPath);
|
||||
Process.Start(Application.StartupPath + "\\mpvInputEdit.exe");
|
||||
}
|
||||
|
||||
private static void CreateMpvConf()
|
||||
public static void show_conf_editor(string[] args)
|
||||
{
|
||||
if (!File.Exists(mp.mpvConfPath))
|
||||
{
|
||||
if (!Directory.Exists(mp.mpvConfFolderPath))
|
||||
Directory.CreateDirectory(mp.mpvConfFolderPath);
|
||||
|
||||
File.WriteAllText(mp.mpvConfPath, "# https://mpv.io/manual/master/#configuration-files");
|
||||
}
|
||||
}
|
||||
|
||||
public static void show_prefs(string[] args)
|
||||
{
|
||||
CreateMpvConf();
|
||||
Process.Start(mp.mpvConfPath);
|
||||
Process.Start(Application.StartupPath + "\\mpvConfEdit.exe");
|
||||
}
|
||||
|
||||
public static void history(string[] args)
|
||||
@@ -89,7 +75,7 @@ namespace mpvnet
|
||||
if (File.Exists(fp))
|
||||
Process.Start(fp);
|
||||
else
|
||||
if (MsgQuestion("Create history.txt file in config folder?\r\n\r\nmpv.net will write the date, time and filename of opened files to it.") == DialogResult.OK)
|
||||
if (MainForm.Instance.ShowMsgBox("Create history.txt file in config folder?\n\nmpv.net will write the date, time and filename of opened files to it.", MessageBoxIcon.Question) == DialogResult.OK)
|
||||
File.WriteAllText(fp, "");
|
||||
}
|
||||
|
||||
@@ -100,68 +86,106 @@ namespace mpvnet
|
||||
|
||||
public static void set_setting(string[] args)
|
||||
{
|
||||
CreateMpvConf();
|
||||
|
||||
bool changed = false;
|
||||
string fp = mp.mpvConfPath;
|
||||
var confLines = File.ReadAllLines(fp);
|
||||
var lines = File.ReadAllLines(mp.mpvConfPath);
|
||||
|
||||
for (int i = 0; i < confLines.Length; i++)
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
if (confLines[i].Left("=").Trim() == args[0])
|
||||
if (lines[i].Contains("=") &&
|
||||
lines[i].Substring(0, lines[i].IndexOf("=")).Trim("# ".ToCharArray()) == args[0])
|
||||
{
|
||||
confLines[i] = args[0] + "=" + args[1];
|
||||
lines[i] = args[0] + " = " + args[1];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
File.WriteAllText(fp, String.Join(Environment.NewLine, confLines));
|
||||
}
|
||||
File.WriteAllText(mp.mpvConfPath, String.Join(Environment.NewLine, lines));
|
||||
else
|
||||
{
|
||||
File.WriteAllText(fp,
|
||||
File.ReadAllText(fp) + Environment.NewLine + args[0] + "=" + args[1]);
|
||||
}
|
||||
File.WriteAllText(mp.mpvConfPath, File.ReadAllText(mp.mpvConfPath) + Environment.NewLine + args[0] + " = " + args[1]);
|
||||
|
||||
MsgInfo("Please restart mpv.net");
|
||||
MainForm.Instance.ShowMsgBox("Please restart mpv.net", MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
public static void show_info(string[] args)
|
||||
{
|
||||
var fi = new FileInfo(mp.GetStringProp("path"));
|
||||
|
||||
using (var mi = new MediaInfo(fi.FullName))
|
||||
try
|
||||
{
|
||||
var w = mi.GetInfo(MediaInfoStreamKind.Video, "Width");
|
||||
var h = mi.GetInfo(MediaInfoStreamKind.Video, "Height");
|
||||
var pos = TimeSpan.FromSeconds(mp.GetIntProp("time-pos"));
|
||||
var dur = TimeSpan.FromSeconds(mp.GetIntProp("duration"));
|
||||
string mibr = mi.GetInfo(MediaInfoStreamKind.Video, "BitRate");
|
||||
var fileInfo = new FileInfo(mp.get_property_string("path"));
|
||||
|
||||
if (mibr == "")
|
||||
mibr = "0";
|
||||
using (var mediaInfo = new MediaInfo(fileInfo.FullName))
|
||||
{
|
||||
string width = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "Width");
|
||||
|
||||
var br = Convert.ToInt32(mibr) / 1000.0 / 1000.0;
|
||||
var vf = mp.GetStringProp("video-format").ToUpper();
|
||||
var fn = fi.Name;
|
||||
if (width == "")
|
||||
{
|
||||
string performer = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Performer");
|
||||
string title = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Title");
|
||||
string album = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Album");
|
||||
string genre = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Genre");
|
||||
string date = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Recorded_Date");
|
||||
string duration = mediaInfo.GetInfo(MediaInfoStreamKind.Audio, "Duration/String");
|
||||
|
||||
if (fn.Length > 60)
|
||||
fn = fn.Insert(59, "\r\n");
|
||||
string text = "";
|
||||
|
||||
var info =
|
||||
FormatTime(pos.TotalMinutes) + ":" +
|
||||
FormatTime(pos.Seconds) + " / " +
|
||||
FormatTime(dur.TotalMinutes) + ":" +
|
||||
FormatTime(dur.Seconds) + "\n" +
|
||||
((int)(fi.Length / 1024 / 1024)).ToString() +
|
||||
$" MB - {w} x {h}\n{vf} - {br.ToString("f1")} Mb/s" + "\n" + fn;
|
||||
if (performer != "") text += "Artist: " + performer + "\n";
|
||||
if (title != "") text += "Title: " + title + "\n";
|
||||
if (album != "") text += "Album: " + album + "\n";
|
||||
if (genre != "") text += "Genre: " + genre + "\n";
|
||||
if (date != "") text += "Year: " + date + "\n";
|
||||
if (duration != "") text += "Length: " + duration + "\n";
|
||||
|
||||
mp.Command("show-text", info, "5000");
|
||||
mp.commandv("show-text", text, "5000");
|
||||
}
|
||||
else
|
||||
{
|
||||
string height = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "Height");
|
||||
TimeSpan position = TimeSpan.FromSeconds(mp.get_property_number("time-pos"));
|
||||
TimeSpan duration = TimeSpan.FromSeconds(mp.get_property_number("duration"));
|
||||
string bitrate = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "BitRate");
|
||||
|
||||
string FormatTime(double value) => ((int)(Math.Floor(value))).ToString("00");
|
||||
if (bitrate == "")
|
||||
bitrate = "0";
|
||||
|
||||
var bitrate2 = Convert.ToDouble(bitrate) / 1000.0 / 1000.0;
|
||||
var videoCodec = mp.get_property_string("video-format").ToUpper();
|
||||
var filename = fileInfo.Name;
|
||||
|
||||
var text =
|
||||
FormatTime(position.TotalMinutes) + ":" +
|
||||
FormatTime(position.Seconds) + " / " +
|
||||
FormatTime(duration.TotalMinutes) + ":" +
|
||||
FormatTime(duration.Seconds) + "\n" +
|
||||
Convert.ToInt32(fileInfo.Length / 1024 / 1024).ToString() +
|
||||
$" MB - {width} x {height}\n{videoCodec} - {bitrate2.ToString("f1")} Mb/s" + "\n" + filename;
|
||||
|
||||
mp.commandv("show-text", text, "5000");
|
||||
}
|
||||
|
||||
string FormatTime(double value) => ((int)value).ToString("00");
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
if (string.IsNullOrEmpty(command)) return;
|
||||
mp.command_string(command, false);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void open_url(string[] args)
|
||||
{
|
||||
MainForm.Instance.Invoke(new Action(() => {
|
||||
string command = Microsoft.VisualBasic.Interaction.InputBox("Enter URL to be opened.");
|
||||
if (string.IsNullOrEmpty(command)) return;
|
||||
mp.LoadURL(command);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static string Join(this IEnumerable<string> instance, string delimiter, bool removeEmpty = false)
|
||||
{
|
||||
if (instance == null)
|
||||
return null;
|
||||
|
||||
bool containsEmpty = false;
|
||||
|
||||
foreach (var i in instance)
|
||||
{
|
||||
if (string.IsNullOrEmpty(i))
|
||||
{
|
||||
containsEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (containsEmpty && removeEmpty)
|
||||
instance = instance.Where(arg => !string.IsNullOrEmpty(arg));
|
||||
|
||||
return string.Join(delimiter, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
mpv.net/MainForm.Designer.cs
generated
7
mpv.net/MainForm.Designer.cs
generated
@@ -42,17 +42,16 @@
|
||||
// MainForm
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 25F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.BackColor = System.Drawing.Color.Black;
|
||||
this.ClientSize = new System.Drawing.Size(1553, 1000);
|
||||
this.ClientSize = new System.Drawing.Size(1012, 615);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.Name = "MainForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "mpv.net";
|
||||
this.Load += new System.EventHandler(this.MainForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using static mpvnet.StaticUsing;
|
||||
using System.Linq;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
@@ -16,7 +15,7 @@ namespace mpvnet
|
||||
|
||||
private Point LastCursorPosChanged;
|
||||
private int LastCursorChangedTickCount;
|
||||
private bool IsCloseRequired = true;
|
||||
private bool IgnoreDpiChanged = true;
|
||||
|
||||
public ContextMenuStripEx CMS;
|
||||
|
||||
@@ -27,57 +26,136 @@ namespace mpvnet
|
||||
try
|
||||
{
|
||||
Application.ThreadException += Application_ThreadException;
|
||||
SetFormPosSize();
|
||||
Instance = this;
|
||||
Hwnd = Handle;
|
||||
ChangeFullscreen((mp.mpvConv.ContainsKey("fullscreen") && mp.mpvConv["fullscreen"] == "yes") || (mp.mpvConv.ContainsKey("fs") && mp.mpvConv["fs"] == "yes"));
|
||||
CMS = new ContextMenuStripEx(components);
|
||||
CMS.Opened += CMS_Opened;
|
||||
ContextMenuStrip = CMS;
|
||||
BuildMenu();
|
||||
Text += " " + Application.ProductVersion;
|
||||
|
||||
if (mp.mpvConf.ContainsKey("screen"))
|
||||
SetScreen(Convert.ToInt32(mp.mpvConf["screen"]));
|
||||
else
|
||||
SetScreen(Screen.PrimaryScreen);
|
||||
|
||||
ChangeFullscreen((mp.mpvConf.ContainsKey("fullscreen") && mp.mpvConf["fullscreen"] == "yes") ||
|
||||
(mp.mpvConf.ContainsKey("fs") && mp.mpvConf["fs"] == "yes"));
|
||||
|
||||
ProcessCommandLineEarly();
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception e)
|
||||
{
|
||||
HandleException(ex);
|
||||
MainForm.Instance.ShowMsgBox(e.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetScreen(int targetIndex)
|
||||
{
|
||||
Screen[] screens = Screen.AllScreens;
|
||||
if (targetIndex < 0 || targetIndex > screens.Length - 1) return;
|
||||
SetScreen(screens[Array.IndexOf(screens, screens[targetIndex])]);
|
||||
}
|
||||
|
||||
protected void SetScreen(Screen screen)
|
||||
{
|
||||
Rectangle target = screen.Bounds;
|
||||
Left = target.X + Convert.ToInt32((target.Width - Width) / 2.0);
|
||||
Top = target.Y + Convert.ToInt32((target.Height - Height) / 2.0);
|
||||
SetStartFormPositionAndSize();
|
||||
}
|
||||
|
||||
void SetStartFormPositionAndSize()
|
||||
{
|
||||
if (IsFullscreen || mp.VideoSize.Width == 0) return;
|
||||
Screen screen = Screen.FromControl(this);
|
||||
int height = Convert.ToInt32(screen.Bounds.Height * 0.6);
|
||||
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));
|
||||
NativeHelp.AddWindowBorders(Handle, ref rect);
|
||||
int left = middlePos.X - rect.Width / 2;
|
||||
int top = middlePos.Y - rect.Height / 2;
|
||||
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, left, top, rect.Width, rect.Height, 4 /* SWP_NOZORDER */);
|
||||
}
|
||||
|
||||
void SetFormPositionAndSizeKeepHeight()
|
||||
{
|
||||
if (IsFullscreen || mp.VideoSize.Width == 0) return;
|
||||
Screen screen = Screen.FromControl(this);
|
||||
int height = ClientSize.Height;
|
||||
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));
|
||||
NativeHelp.AddWindowBorders(Handle, ref rect);
|
||||
int left = middlePos.X - rect.Width / 2;
|
||||
int top = middlePos.Y - rect.Height / 2;
|
||||
Screen[] screens = Screen.AllScreens;
|
||||
|
||||
if (left < screens[0].Bounds.Left)
|
||||
left = screens[0].Bounds.Left;
|
||||
|
||||
int maxLeft = screens[0].Bounds.Left + screens.Select((sc) => sc.Bounds.Width).Sum() - rect.Width - SystemInformation.CaptionHeight;
|
||||
|
||||
if (left > maxLeft)
|
||||
left = maxLeft;
|
||||
|
||||
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);
|
||||
|
||||
if (left == "screen")
|
||||
SetScreen(Convert.ToInt32(right));
|
||||
|
||||
ChangeFullscreen((left == "fs" || left == "fullscreen") && right == "yes");
|
||||
}
|
||||
else
|
||||
{
|
||||
string switchName = i.Substring(2);
|
||||
|
||||
switch (switchName)
|
||||
{
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
ChangeFullscreen(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildMenu()
|
||||
{
|
||||
if (!File.Exists(mp.InputConfPath))
|
||||
foreach (var i in File.ReadAllText(mp.InputConfPath).Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (!Directory.Exists(mp.mpvConfFolderPath))
|
||||
Directory.CreateDirectory(mp.mpvConfFolderPath);
|
||||
|
||||
File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf);
|
||||
}
|
||||
|
||||
foreach (var i in File.ReadAllText(mp.InputConfPath).SplitLinesNoEmpty())
|
||||
{
|
||||
if (!i.Contains("#menu:"))
|
||||
continue;
|
||||
|
||||
var left = i.Left("#menu:").Trim();
|
||||
|
||||
if (left.StartsWith("#"))
|
||||
continue;
|
||||
|
||||
var cmd = left.Right(" ").Trim();
|
||||
var menu = i.Right("#menu:").Trim();
|
||||
var key = menu.Left(";").Trim();
|
||||
var path = menu.Right(";").Trim();
|
||||
|
||||
if (path == "" || cmd == "")
|
||||
continue;
|
||||
if (!i.Contains("#menu:")) continue;
|
||||
var left = i.Substring(0, i.IndexOf("#menu:")).Trim();
|
||||
if (left.StartsWith("#")) continue;
|
||||
var cmd = left.Substring(left.IndexOf(" ") + 1).Trim();
|
||||
var menu = i.Substring(i.IndexOf("#menu:") + "#menu:".Length).Trim();
|
||||
var key = left.Substring(0, left.IndexOf(" "));
|
||||
if (key == "_") key = "";
|
||||
if (menu.Contains(";")) key = menu.Substring(0, menu.IndexOf(";")).Trim();
|
||||
var path = menu.Substring(menu.IndexOf(";") + 1).Trim().Replace("&", "&&");
|
||||
if (path == "" || cmd == "") continue;
|
||||
|
||||
var menuItem = CMS.Add(path, () => {
|
||||
try
|
||||
{
|
||||
mp.CommandString(cmd, false);
|
||||
mp.command_string(cmd);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MsgError(e.ToString());
|
||||
MainForm.Instance.ShowMsgBox(e.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -93,19 +171,25 @@ namespace mpvnet
|
||||
|
||||
private string LastHistory;
|
||||
|
||||
private void mpv_PlaybackRestart()
|
||||
private void mp_PlaybackRestart()
|
||||
{
|
||||
var fn = mp.GetStringProp("filename");
|
||||
BeginInvoke(new Action(() => { Text = fn + " - mpv.net " + Application.ProductVersion; }));
|
||||
var fp = mp.mpvConfFolderPath + "history.txt";
|
||||
var filename = mp.get_property_string("filename");
|
||||
BeginInvoke(new Action(() => { Text = filename + " - mpv.net " + Application.ProductVersion; }));
|
||||
var historyFilepath = mp.mpvConfFolderPath + "history.txt";
|
||||
|
||||
if (LastHistory != fn && File.Exists(fp))
|
||||
if (LastHistory != filename && File.Exists(historyFilepath))
|
||||
{
|
||||
File.AppendAllText(fp, DateTime.Now.ToString() + " " + Path.GetFileNameWithoutExtension(fn) + "\r\n");
|
||||
LastHistory = fn;
|
||||
File.AppendAllText(historyFilepath, DateTime.Now.ToString() + " " +
|
||||
Path.GetFileNameWithoutExtension(filename) + "\r\n");
|
||||
LastHistory = filename;
|
||||
}
|
||||
}
|
||||
|
||||
private void Mp_Idle()
|
||||
{
|
||||
BeginInvoke(new Action(() => { Text = "mpv.net " + Application.ProductVersion; }));
|
||||
}
|
||||
|
||||
private void CM_Popup(object sender, EventArgs e)
|
||||
{
|
||||
CursorHelp.Show();
|
||||
@@ -113,31 +197,22 @@ namespace mpvnet
|
||||
|
||||
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
HandleException(e.Exception);
|
||||
ShowMsgBox(e.Exception.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
void HandleException(Exception e)
|
||||
private void mp_VideoSizeChanged()
|
||||
{
|
||||
MsgError(e.ToString());
|
||||
BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight()));
|
||||
}
|
||||
|
||||
private void Mpv_VideoSizeChanged()
|
||||
private void mp_Shutdown()
|
||||
{
|
||||
BeginInvoke(new Action(() => SetFormPosSize()));
|
||||
BeginInvoke(new Action(() => Close()));
|
||||
}
|
||||
|
||||
private void Mpv_AfterShutdown()
|
||||
{
|
||||
if (IsCloseRequired)
|
||||
Invoke(new Action(() => Close()));
|
||||
}
|
||||
public bool IsFullscreen => WindowState == FormWindowState.Maximized;
|
||||
|
||||
public bool IsFullscreen
|
||||
{
|
||||
get => WindowState == FormWindowState.Maximized;
|
||||
}
|
||||
|
||||
void MpvChangeFullscreen(bool value)
|
||||
void mp_ChangeFullscreen(bool value)
|
||||
{
|
||||
BeginInvoke(new Action(() => ChangeFullscreen(value)));
|
||||
}
|
||||
@@ -146,14 +221,17 @@ namespace mpvnet
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.None;
|
||||
WindowState = FormWindowState.Maximized;
|
||||
if (FormBorderStyle != FormBorderStyle.None)
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.None;
|
||||
WindowState = FormWindowState.Maximized;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = FormWindowState.Normal;
|
||||
FormBorderStyle = FormBorderStyle.Sizable;
|
||||
SetFormPosSize();
|
||||
SetFormPositionAndSizeKeepHeight();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,9 +247,26 @@ namespace mpvnet
|
||||
if (mp.MpvWindowHandle != IntPtr.Zero)
|
||||
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
break;
|
||||
case 0x319: // WM_APPCOMMAND
|
||||
if (mp.MpvWindowHandle != IntPtr.Zero)
|
||||
Native.PostMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
break;
|
||||
case 0x0104: // WM_SYSKEYDOWN:
|
||||
if (mp.MpvWindowHandle != IntPtr.Zero)
|
||||
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
break;
|
||||
case 0x0105: // WM_SYSKEYUP:
|
||||
if (mp.MpvWindowHandle != IntPtr.Zero)
|
||||
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
|
||||
break;
|
||||
case 0x203: // Native.WM.LBUTTONDBLCLK
|
||||
if (!IsMouseInOSC())
|
||||
mp.CommandString("cycle fullscreen");
|
||||
mp.command_string("cycle fullscreen");
|
||||
break;
|
||||
case 0x02E0: // WM_DPICHANGED
|
||||
if (IgnoreDpiChanged) break;
|
||||
var r2 = Marshal.PtrToStructure<Native.RECT>(m.LParam);
|
||||
Native.SetWindowPos(Handle, IntPtr.Zero, r2.Left, r2.Top, r2.Width, r2.Height, 0);
|
||||
break;
|
||||
case 0x0214: // WM_SIZING
|
||||
var rc = Marshal.PtrToStructure<Native.RECT>(m.LParam);
|
||||
@@ -179,8 +274,8 @@ namespace mpvnet
|
||||
NativeHelp.SubtractWindowBorders(Handle, ref r);
|
||||
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
|
||||
float aspect = mp.VideoSize.Width / (float)mp.VideoSize.Height;
|
||||
int d_w = (int)(c_h * aspect - c_w);
|
||||
int d_h = (int)(c_w / aspect - c_h);
|
||||
int d_w = Convert.ToInt32(c_h * aspect - c_w);
|
||||
int d_h = Convert.ToInt32(c_w / aspect - c_h);
|
||||
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());
|
||||
@@ -196,45 +291,27 @@ namespace mpvnet
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
void SetFormPosSize()
|
||||
{
|
||||
if (IsFullscreen || mp.VideoSize.Width == 0) return;
|
||||
var wa = Screen.GetWorkingArea(this);
|
||||
int h = (int)(wa.Height * 0.6);
|
||||
int w = (int)(h * mp.VideoSize.Width / (float)mp.VideoSize.Height);
|
||||
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
|
||||
var r = new Native.RECT(new Rectangle(0, 0, w, h));
|
||||
NativeHelp.AddWindowBorders(Handle, ref r);
|
||||
int l = middlePos.X - r.Width / 2;
|
||||
int t = middlePos.Y - r.Height / 2;
|
||||
if (l < 0) l = 0;
|
||||
if (t < 0) t = 0;
|
||||
if (l + r.Width > wa.Width ) l = wa.Width - r.Width;
|
||||
if (t + r.Height > wa.Height ) t = wa.Height - r.Height;
|
||||
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, l, t, r.Width, r.Height, 4 /* SWP_NOZORDER */);
|
||||
}
|
||||
|
||||
protected override void OnDragEnter(DragEventArgs e)
|
||||
{
|
||||
base.OnDragEnter(e);
|
||||
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop) || e.Data.GetDataPresent(DataFormats.Text))
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
}
|
||||
|
||||
protected override void OnDragDrop(DragEventArgs e)
|
||||
{
|
||||
base.OnDragDrop(e);
|
||||
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
mp.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[]);
|
||||
if (e.Data.GetDataPresent(DataFormats.Text))
|
||||
mp.LoadURL(e.Data.GetData(DataFormats.Text).ToString());
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
|
||||
// window-dragging
|
||||
if (WindowState == FormWindowState.Normal &&
|
||||
e.Button == MouseButtons.Left &&
|
||||
e.Y < ClientSize.Height * 0.9)
|
||||
@@ -249,27 +326,18 @@ namespace mpvnet
|
||||
var p2 = PointToScreen(e.Location);
|
||||
|
||||
if (Math.Abs(p1.X - p2.X) < 10 && Math.Abs(p1.Y - p2.Y) < 10)
|
||||
mp.Command("quit");
|
||||
mp.commandv("quit");
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
|
||||
// send mouse command to make OSC show
|
||||
mp.CommandString($"mouse {e.X} {e.Y}");
|
||||
mp.command_string($"mouse {e.X} {e.Y}");
|
||||
|
||||
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
|
||||
CursorHelp.Show();
|
||||
}
|
||||
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
base.OnFormClosed(e);
|
||||
IsCloseRequired = false;
|
||||
mp.Command("quit");
|
||||
}
|
||||
|
||||
bool IsMouseInOSC()
|
||||
{
|
||||
return PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
|
||||
@@ -290,13 +358,49 @@ namespace mpvnet
|
||||
}
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs ea)
|
||||
public DialogResult ShowMsgBox(string message, MessageBoxIcon icon)
|
||||
{
|
||||
var buttons = MessageBoxButtons.OK;
|
||||
if (icon == MessageBoxIcon.Question) buttons = MessageBoxButtons.OKCancel;
|
||||
|
||||
var fn = new Func<DialogResult>(() => MessageBox.Show(
|
||||
message, Application.ProductName, buttons, MessageBoxIcon.Information));
|
||||
|
||||
return (DialogResult)Invoke(fn);
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
mp.Init();
|
||||
mp.ObserveBoolProp("fullscreen", MpvChangeFullscreen);
|
||||
mp.Shutdown += Mpv_AfterShutdown;
|
||||
mp.VideoSizeChanged += Mpv_VideoSizeChanged;
|
||||
mp.PlaybackRestart += mpv_PlaybackRestart;
|
||||
mp.observe_property_bool("fullscreen", mp_ChangeFullscreen);
|
||||
mp.Shutdown += mp_Shutdown;
|
||||
mp.VideoSizeChanged += mp_VideoSizeChanged;
|
||||
mp.PlaybackRestart += mp_PlaybackRestart;
|
||||
mp.Idle += Mp_Idle;
|
||||
}
|
||||
|
||||
protected override void OnShown(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
CMS = new ContextMenuStripEx(components);
|
||||
CMS.Opened += CMS_Opened;
|
||||
ContextMenuStrip = CMS;
|
||||
BuildMenu();
|
||||
IgnoreDpiChanged = false;
|
||||
}
|
||||
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
base.OnFormClosed(e);
|
||||
mp.commandv("quit");
|
||||
mp.AutoResetEvent.WaitOne(3000);
|
||||
}
|
||||
|
||||
protected override void OnLostFocus(EventArgs e)
|
||||
{
|
||||
base.OnLostFocus(e);
|
||||
CursorHelp.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,8 +214,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
||||
|
||||
if (e.Item is ToolStripMenuItem && !(e.Item.Owner is MenuStrip))
|
||||
{
|
||||
var r = e.TextRectangle;
|
||||
|
||||
Rectangle rect = e.TextRectangle;
|
||||
var dropDown = e.ToolStrip as ToolStripDropDownMenu;
|
||||
|
||||
if (dropDown == null || dropDown.ShowImageMargin || dropDown.ShowCheckMargin)
|
||||
@@ -223,7 +222,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
||||
else
|
||||
TextOffset = Convert.ToInt32(e.Item.Height * 0.2);
|
||||
|
||||
e.TextRectangle = new Rectangle(TextOffset, Convert.ToInt32((e.Item.Height - r.Height) / 2.0), r.Width, r.Height);
|
||||
e.TextRectangle = new Rectangle(TextOffset, Convert.ToInt32((e.Item.Height - rect.Height) / 2.0), rect.Width, rect.Height);
|
||||
}
|
||||
|
||||
base.OnRenderItemText(e);
|
||||
@@ -279,31 +278,22 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
||||
|
||||
public void DrawButton(ToolStripItemRenderEventArgs e)
|
||||
{
|
||||
var g = e.Graphics;
|
||||
var r = new Rectangle(Point.Empty, e.Item.Size);
|
||||
var r2 = new Rectangle(r.X, r.Y, r.Width - 1, r.Height - 1);
|
||||
var gx = e.Graphics;
|
||||
var rect = new Rectangle(Point.Empty, e.Item.Size);
|
||||
var rect2 = new Rectangle(rect.X, rect.Y, rect.Width - 1, rect.Height - 1);
|
||||
|
||||
using (Pen pen = new Pen(ColorBorder))
|
||||
{
|
||||
g.DrawRectangle(pen, r2);
|
||||
}
|
||||
|
||||
r2.Inflate(-1, -1);
|
||||
gx.DrawRectangle(pen, rect2);
|
||||
|
||||
rect2.Inflate(-1, -1);
|
||||
var tsb = e.Item as ToolStripButton;
|
||||
|
||||
if (!(tsb == null) && tsb.Checked)
|
||||
{
|
||||
if (tsb != null && tsb.Checked)
|
||||
using (SolidBrush brush = new SolidBrush(ColorChecked))
|
||||
{
|
||||
g.FillRectangle(brush, r2);
|
||||
}
|
||||
}
|
||||
gx.FillRectangle(brush, rect2);
|
||||
else
|
||||
using (SolidBrush brush = new SolidBrush(ColorBottom))
|
||||
{
|
||||
g.FillRectangle(brush, r2);
|
||||
}
|
||||
gx.FillRectangle(brush, rect2);
|
||||
}
|
||||
|
||||
protected override void OnRenderDropDownButtonBackground(ToolStripItemRenderEventArgs e)
|
||||
@@ -332,7 +322,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
||||
|
||||
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
|
||||
{
|
||||
var x = Convert.ToInt32(e.ImageRectangle.Height * 0.2);
|
||||
int x = Convert.ToInt32(e.ImageRectangle.Height * 0.2);
|
||||
e.Graphics.DrawImage(e.Image, new Point(x, x));
|
||||
}
|
||||
|
||||
@@ -341,28 +331,21 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
||||
if (e.Item.IsOnDropDown)
|
||||
{
|
||||
e.Graphics.Clear(ColorBackground);
|
||||
var right = e.Item.Width - Convert.ToInt32(TextOffset / 5.0);
|
||||
var top = e.Item.Height / 2;
|
||||
int right = e.Item.Width - Convert.ToInt32(TextOffset / 5.0);
|
||||
int top = e.Item.Height / 2;
|
||||
top -= 1;
|
||||
var b = e.Item.Bounds;
|
||||
|
||||
using (Pen p = new Pen(Color.Gray))
|
||||
{
|
||||
e.Graphics.DrawLine(p, new Point(TextOffset, top), new Point(right, top));
|
||||
}
|
||||
}
|
||||
else if (e.Vertical)
|
||||
{
|
||||
var b = e.Item.Bounds;
|
||||
|
||||
var bounds = e.Item.Bounds;
|
||||
using (Pen p = new Pen(SystemColors.ControlDarkDark))
|
||||
{
|
||||
e.Graphics.DrawLine(p,
|
||||
Convert.ToInt32(b.Width / 2.0),
|
||||
Convert.ToInt32(b.Height * 0.15),
|
||||
Convert.ToInt32(b.Width / 2.0),
|
||||
Convert.ToInt32(b.Height * 0.85));
|
||||
}
|
||||
Convert.ToInt32(bounds.Width / 2.0),
|
||||
Convert.ToInt32(bounds.Height * 0.15),
|
||||
Convert.ToInt32(bounds.Width / 2.0),
|
||||
Convert.ToInt32(bounds.Height * 0.85));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -383,21 +366,24 @@ public struct HSLColor
|
||||
|
||||
private double hue;
|
||||
|
||||
public int Hue {
|
||||
public int Hue
|
||||
{
|
||||
get => System.Convert.ToInt32(hue * 240);
|
||||
set => hue = CheckRange(value / 240.0);
|
||||
}
|
||||
|
||||
private double saturation;
|
||||
|
||||
public int Saturation {
|
||||
public int Saturation
|
||||
{
|
||||
get => System.Convert.ToInt32(saturation * 240);
|
||||
set => saturation = CheckRange(value / 240.0);
|
||||
}
|
||||
|
||||
private double luminosity;
|
||||
|
||||
public int Luminosity {
|
||||
public int Luminosity
|
||||
{
|
||||
get => System.Convert.ToInt32(luminosity * 240);
|
||||
set => luminosity = CheckRange(value / 240.0);
|
||||
}
|
||||
@@ -408,7 +394,6 @@ public struct HSLColor
|
||||
value = 0;
|
||||
else if (value > 1)
|
||||
value = 1;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -438,9 +423,8 @@ public struct HSLColor
|
||||
}
|
||||
else
|
||||
{
|
||||
var temp2 = GetTemp2(this);
|
||||
var temp1 = 2.0 * luminosity - temp2;
|
||||
|
||||
double temp2 = GetTemp2(this);
|
||||
double temp1 = 2.0 * luminosity - temp2;
|
||||
r = GetColorComponent(temp1, temp2, hue + 1.0 / 3.0);
|
||||
g = GetColorComponent(temp1, temp2, hue);
|
||||
b = GetColorComponent(temp1, temp2, hue - 1.0 / 3.0);
|
||||
@@ -473,7 +457,6 @@ public struct HSLColor
|
||||
temp3 += 1;
|
||||
else if (temp3 > 1)
|
||||
temp3 -= 1;
|
||||
|
||||
return temp3;
|
||||
}
|
||||
|
||||
@@ -500,7 +483,7 @@ public struct HSLColor
|
||||
|
||||
public void SetRGB(int red, int green, int blue)
|
||||
{
|
||||
var hc = HSLColor.Convert(Color.FromArgb(red, green, blue));
|
||||
HSLColor hc = HSLColor.Convert(Color.FromArgb(red, green, blue));
|
||||
hue = hc.hue;
|
||||
saturation = hc.saturation;
|
||||
luminosity = hc.luminosity;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
@@ -9,10 +10,8 @@ namespace mpvnet
|
||||
{
|
||||
public static readonly string[] FileTypes = "264 265 3gp aac ac3 avc avi avs bmp divx dts dtshd dtshr dtsma eac3 evo flac flv h264 h265 hevc hvc jpg jpeg m2t m2ts m2v m4a m4v mka mkv mlp mov mp2 mp3 mp4 mpa mpeg mpg mpv mts ogg ogm opus pcm png pva raw rmvb thd thd+ac3 true-hd truehd ts vdr vob vpy w64 wav webm wmv y4m".Split(' ');
|
||||
|
||||
public static string GetFilter(IEnumerable<string> values)
|
||||
{
|
||||
return "*." + values.Join(";*.") + "|*." + values.Join(";*.") + "|All Files|*.*";
|
||||
}
|
||||
public static string GetFilter(IEnumerable<string> values) => "*." +
|
||||
String.Join(";*.", values) + "|*." + String.Join(";*.", values) + "|All Files|*.*";
|
||||
}
|
||||
|
||||
public class StringLogicalComparer : IComparer, IComparer<string>
|
||||
@@ -26,21 +25,13 @@ namespace mpvnet
|
||||
int IComparer<string>.Compare(string x, string y) => IComparerOfString_Compare(x, y);
|
||||
}
|
||||
|
||||
public class StaticUsing
|
||||
public class OSVersion
|
||||
{
|
||||
public static void MsgInfo(string message)
|
||||
{
|
||||
MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
public static float Windows7 { get; } = 6.1f;
|
||||
public static float Windows8 { get; } = 6.2f;
|
||||
public static float Windows81 { get; } = 6.3f;
|
||||
public static float Windows10 { get; } = 10f;
|
||||
|
||||
public static void MsgError(string message)
|
||||
{
|
||||
MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
public static DialogResult MsgQuestion(string message)
|
||||
{
|
||||
return MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
|
||||
}
|
||||
public static float Current => Environment.OSVersion.Version.Major + Environment.OSVersion.Version.Minor / 10f;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
@@ -54,25 +56,10 @@ namespace mpvnet
|
||||
Bottom = bottom;
|
||||
}
|
||||
|
||||
public Rectangle ToRectangle()
|
||||
{
|
||||
return Rectangle.FromLTRB(Left, Top, Right, Bottom);
|
||||
}
|
||||
|
||||
public Size Size
|
||||
{
|
||||
get => new Size(Right - Left, Bottom - Top);
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get => Right - Left;
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get => Bottom - Top;
|
||||
}
|
||||
public Rectangle ToRectangle() { return Rectangle.FromLTRB(Left, Top, Right, Bottom); }
|
||||
public Size Size => new Size(Right - Left, Bottom - Top);
|
||||
public int Width => Right - Left;
|
||||
public int Height => Bottom - Top;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,4 +35,4 @@ namespace mpvnet
|
||||
Native.AdjustWindowRect(ref rc, (uint)Native.GetWindowLongPtrW(hwnd, -16 /* GWL_STYLE */), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
128
mpv.net/PowerShellScript.cs
Normal file
128
mpv.net/PowerShellScript.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class PowerShellScript
|
||||
{
|
||||
public static object Execute(string code, string[] parameters)
|
||||
{
|
||||
using (Runspace runspace = RunspaceFactory.CreateRunspace())
|
||||
{
|
||||
runspace.ApartmentState = ApartmentState.STA;
|
||||
runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
|
||||
runspace.Open();
|
||||
|
||||
using (Pipeline pipeline = runspace.CreatePipeline())
|
||||
{
|
||||
pipeline.Commands.AddScript(
|
||||
@"Using namespace mpvnet;
|
||||
Using namespace System;
|
||||
[System.Reflection.Assembly]::LoadWithPartialName(""mpvnet"")");
|
||||
|
||||
pipeline.Commands.AddScript(code);
|
||||
|
||||
try
|
||||
{
|
||||
var ret = pipeline.Invoke(parameters);
|
||||
|
||||
if (ret.Count > 0)
|
||||
return ret[0];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Pipeline pipeline2 = runspace.CreatePipeline())
|
||||
{
|
||||
pipeline2.Commands.AddScript("$PSVersionTable.PSVersion.Major * 10 +" +
|
||||
"$PSVersionTable.PSVersion.Minor");
|
||||
|
||||
if (Convert.ToInt32(pipeline2.Invoke()[0].ToString()) < 51)
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
MainForm.Instance.ShowMsgBox("PowerShell Setup Problem\n\nEnsure you have at least PowerShell 5.1 installed.", MessageBoxIcon.Error);
|
||||
return null;
|
||||
}
|
||||
MainForm.Instance.ShowMsgBox(ex.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Init(string filePath)
|
||||
{
|
||||
foreach (var eventInfo in typeof(mp).GetEvents())
|
||||
{
|
||||
if (eventInfo.Name.ToLower() ==
|
||||
Path.GetFileNameWithoutExtension(filePath).ToLower().Replace("-", ""))
|
||||
{
|
||||
PowerShellEventObject eventObject = new PowerShellEventObject();
|
||||
MethodInfo mi;
|
||||
eventObject.FilePath = filePath;
|
||||
|
||||
if (eventInfo.EventHandlerType == typeof(Action))
|
||||
{
|
||||
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.Invoke));
|
||||
}
|
||||
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
|
||||
{
|
||||
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.InvokeEndFileEventMode));
|
||||
}
|
||||
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
|
||||
{
|
||||
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.InvokeStrings));
|
||||
}
|
||||
else
|
||||
throw new Exception();
|
||||
|
||||
eventObject.EventInfo = eventInfo;
|
||||
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
|
||||
eventObject.Delegate = handler;
|
||||
eventInfo.AddEventHandler(eventObject, handler);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
PowerShellScript.Execute(File.ReadAllText(filePath), new string[] {});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class PowerShellEventObject
|
||||
{
|
||||
public EventInfo EventInfo { get; set; }
|
||||
public Delegate Delegate { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
Task.Run(() => { PowerShellScript.Execute(File.ReadAllText(FilePath), new string[] { }); });
|
||||
}
|
||||
|
||||
public void InvokeEndFileEventMode(EndFileEventMode arg)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
PowerShellScript.Execute(File.ReadAllText(FilePath), new string[] { arg.ToString() });
|
||||
});
|
||||
}
|
||||
|
||||
public void InvokeStrings(string[] args)
|
||||
{
|
||||
Task.Run(() => {
|
||||
PowerShellScript.Execute(File.ReadAllText(FilePath), args);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("mpv.net")]
|
||||
[assembly: AssemblyDescription("mpv/libmpv based player with pure mpv experience")]
|
||||
[assembly: AssemblyDescription("libmpv based player with pure mpv experience")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("mpv.net")]
|
||||
@@ -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("1.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||
[assembly: AssemblyVersion("2.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.1.0.0")]
|
||||
|
||||
31
mpv.net/Properties/Resources.Designer.cs
generated
31
mpv.net/Properties/Resources.Designer.cs
generated
@@ -19,7 +19,7 @@ namespace mpvnet.Properties {
|
||||
// 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", "15.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
@@ -61,11 +61,38 @@ namespace mpvnet.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to # mpv.net key bindings, mouse bindings and context menu configuration
|
||||
///
|
||||
/// o script-message mpv.net open-files #menu: O ; Open Files...
|
||||
/// _ ignore #menu: _ ; -
|
||||
/// Space cycle pause #menu: Space, Enter ; Play/Pause
|
||||
/// Enter cycle pause
|
||||
/// s stop #menu: S ; Stop
|
||||
/// _ ignore #menu: _ ; -
|
||||
/// f cycle fullscreen #menu: F ; Toggle Fullscreen
|
||||
/// [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string input_conf {
|
||||
get {
|
||||
return ResourceManager.GetString("input_conf", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to input-ar-delay = 500
|
||||
///input-ar-rate = 20
|
||||
///volume = 50
|
||||
///hwdec = yes
|
||||
///vo = direct3d
|
||||
///keep-open = yes
|
||||
///keep-open-pause = no
|
||||
///osd-playing-msg = '${filename}'
|
||||
///screenshot-directory = ~~desktop/.
|
||||
/// </summary>
|
||||
internal static string mpv_conf {
|
||||
get {
|
||||
return ResourceManager.GetString("mpv_conf", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,9 @@
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="input_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\input_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
<value>..\Resources\input.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="mpv_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\mpv.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
|
||||
using IronPython.Hosting;
|
||||
using Microsoft.Scripting.Hosting;
|
||||
|
||||
using static mpvnet.StaticUsing;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class PyScript
|
||||
{
|
||||
ScriptEngine engine;
|
||||
ScriptScope scope;
|
||||
|
||||
public PyScript(string code)
|
||||
{
|
||||
try
|
||||
{
|
||||
engine = Python.CreateEngine();
|
||||
scope = engine.CreateScope();
|
||||
scope.ImportModule("clr");
|
||||
engine.Execute("import clr", scope);
|
||||
engine.Execute("clr.AddReference(\"mpvnet\")", scope);
|
||||
engine.Execute("from mpvnet import *", scope);
|
||||
engine.Execute(code, scope);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MsgError(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
mpv.net/PythonScript.cs
Normal file
56
mpv.net/PythonScript.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using IronPython.Hosting;
|
||||
using Microsoft.Scripting.Hosting;
|
||||
|
||||
using PyRT = IronPython.Runtime;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class PythonScript
|
||||
{
|
||||
ScriptEngine engine;
|
||||
ScriptScope scope;
|
||||
|
||||
public PythonScript(string code)
|
||||
{
|
||||
try
|
||||
{
|
||||
engine = Python.CreateEngine();
|
||||
scope = engine.CreateScope();
|
||||
scope.ImportModule("clr");
|
||||
engine.Execute("import clr", scope);
|
||||
engine.Execute("clr.AddReference(\"mpvnet\")", scope);
|
||||
engine.Execute("from mpvnet import *", scope);
|
||||
engine.Execute(code, scope);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MainForm.Instance.ShowMsgBox(ex.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PythonEventObject
|
||||
{
|
||||
public PyRT.PythonFunction PythonFunction { get; set; }
|
||||
public EventInfo EventInfo { get; set; }
|
||||
public Delegate Delegate { get; set; }
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
PyRT.Operations.PythonCalls.Call(PythonFunction);
|
||||
}
|
||||
|
||||
public void InvokeEndFileEventMode(EndFileEventMode arg)
|
||||
{
|
||||
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
|
||||
}
|
||||
|
||||
public void InvokeStrings(string[] arg)
|
||||
{
|
||||
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
|
||||
}
|
||||
}
|
||||
}
|
||||
124
mpv.net/Resources/input.conf.txt
Normal file
124
mpv.net/Resources/input.conf.txt
Normal file
@@ -0,0 +1,124 @@
|
||||
o script-message mpv.net open-files #menu: Open > Open Files...
|
||||
u script-message mpv.net open-url #menu: Open > Open URL...
|
||||
_ ignore #menu: -
|
||||
Space cycle pause #menu: Play/Pause
|
||||
s stop #menu: Stop
|
||||
_ ignore #menu: -
|
||||
f cycle fullscreen #menu: Toggle Fullscreen
|
||||
|
||||
F11 playlist-prev #menu: Navigate > Previous
|
||||
F12 playlist-next #menu: Navigate > Next
|
||||
_ ignore #menu: Navigate > -
|
||||
PGUP add chapter 1 #menu: Navigate > Next Chapter
|
||||
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
|
||||
|
||||
. frame-step #menu: Seek > Next Frame
|
||||
, frame-back-step #menu: Seek > Previous Frame
|
||||
_ ignore #menu: Seek > -
|
||||
Right no-osd seek 7 #menu: Seek > 7 sec forward
|
||||
Left no-osd seek -7 #menu: Seek > 7 sec backward
|
||||
_ ignore #menu: Seek > -
|
||||
Up no-osd seek 40 #menu: Seek > 40 sec forward
|
||||
Down no-osd seek -40 #menu: Seek > 40 sec backward
|
||||
_ ignore #menu: Seek > -
|
||||
Ctrl+Right no-osd seek 300 #menu: Seek > 5 min forward
|
||||
Ctrl+Left no-osd seek -300 #menu: Seek > 5 min backward
|
||||
Ctrl++ add video-zoom 0.1 #menu: Pan & Scan > Increase Size
|
||||
Ctrl+- add video-zoom -0.1 #menu: Pan & Scan > Decrease Size
|
||||
_ ignore #menu: Pan & Scan > -
|
||||
Ctrl+KP4 add video-pan-x -0.01 #menu: Pan & Scan > Move Left
|
||||
Ctrl+KP6 add video-pan-x 0.01 #menu: Pan & Scan > Move Right
|
||||
_ ignore #menu: Pan & Scan > -
|
||||
Ctrl+KP8 add video-pan-y -0.01 #menu: Pan & Scan > Move Up
|
||||
Ctrl+KP2 add video-pan-y 0.01 #menu: Pan & Scan > Move Down
|
||||
_ ignore #menu: Pan & Scan > -
|
||||
w add panscan -0.1 #menu: Pan & Scan > Decrease Height
|
||||
W add panscan +0.1 #menu: Pan & Scan > Increase Height
|
||||
_ ignore #menu: Pan & Scan > -
|
||||
Ctrl+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 #menu: Pan & Scan > Reset
|
||||
Ctrl+1 add contrast -1 #menu: Video > Decrease Contrast
|
||||
Ctrl+2 add contrast 1 #menu: Video > Increase Contrast
|
||||
_ ignore #menu: Video > -
|
||||
Ctrl+3 add brightness -1 #menu: Video > Decrease Brightness
|
||||
Ctrl+4 add brightness 1 #menu: Video > Increase Brightness
|
||||
_ ignore #menu: Video > -
|
||||
Ctrl+5 add gamma -1 #menu: Video > Decrease Gamma
|
||||
Ctrl+6 add gamma 1 #menu: Video > Increase Gamma
|
||||
_ ignore #menu: Video > -
|
||||
Ctrl+7 add saturation -1 #menu: Video > Decrease Saturation
|
||||
Ctrl+8 add saturation 1 #menu: Video > Increase Saturation
|
||||
_ ignore #menu: Video > -
|
||||
Ctrl+s async screenshot #menu: Video > Take Screenshot
|
||||
d cycle deinterlace #menu: Video > Toggle Deinterlace
|
||||
a cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" #menu: Video > Cycle Aspect Ratio
|
||||
KP7 cycle audio #menu: Audio > Cycle/Next
|
||||
_ ignore #menu: Audio > -
|
||||
KP6 add audio-delay 0.100 #menu: Audio > Delay +0.1
|
||||
KP9 add audio-delay -0.100 #menu: Audio > Delay -0.1
|
||||
KP8 cycle sub #menu: Subtitle > Cycle/Next
|
||||
v cycle sub-visibility #menu: Subtitle > Toggle Visibility
|
||||
_ ignore #menu: Subtitle > -
|
||||
z add sub-delay -0.1 #menu: Subtitle > Delay -0.1
|
||||
Z add sub-delay +0.1 #menu: Subtitle > Delay +0.1
|
||||
_ ignore #menu: Subtitle > -
|
||||
r add sub-pos -1 #menu: Subtitle > Move Up
|
||||
R add sub-pos +1 #menu: Subtitle > Move Down
|
||||
_ ignore #menu: Subtitle > -
|
||||
_ add sub-scale -0.1 #menu: Subtitle > Decrease Subtitle Font Size
|
||||
_ add sub-scale +0.1 #menu: Subtitle > Increase Subtitle Font Size
|
||||
+ add volume 10 #menu: Volume > Up
|
||||
- add volume -10 #menu: Volume > Down
|
||||
_ ignore #menu: Volume > -
|
||||
m cycle mute #menu: Volume > Mute
|
||||
[ multiply speed 0.9 #menu: Speed > -10%
|
||||
] multiply speed 1.1 #menu: Speed > +10%
|
||||
_ ignore #menu: Speed > -
|
||||
{ multiply speed 0.5 #menu: Speed > Half
|
||||
} multiply speed 2.0 #menu: Speed > Double
|
||||
_ ignore #menu: Speed > -
|
||||
BS set speed 1 #menu: Speed > Reset
|
||||
KP0 script-message rate-file 0 #menu: Addons > Rating > 0stars
|
||||
KP1 script-message rate-file 1 #menu: Addons > Rating > 1stars
|
||||
KP2 script-message rate-file 2 #menu: Addons > Rating > 2stars
|
||||
KP3 script-message rate-file 3 #menu: Addons > Rating > 3stars
|
||||
KP4 script-message rate-file 4 #menu: Addons > Rating > 4stars
|
||||
KP5 script-message rate-file 5 #menu: Addons > Rating > 5stars
|
||||
_ script-message mpv.net set-setting hwdec yes #menu: Settings > Hardware Decoding > Enable
|
||||
_ script-message mpv.net set-setting hwdec no #menu: Settings > Hardware Decoding > Disable
|
||||
e 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
|
||||
c script-message mpv.net open-config-folder #menu: Settings > Open Config Folder
|
||||
i script-message mpv.net show-info #menu: Tools > Info
|
||||
t script-binding stats/display-stats #menu: Tools > Show Statistics
|
||||
T script-binding stats/display-stats-toggle #menu: Tools > Toggle Statistics
|
||||
_ ignore #menu: Tools > -
|
||||
h script-message mpv.net history #menu: Tools > Show History
|
||||
l ab-loop #menu: Tools > Set/clear A-B loop points
|
||||
L cycle-values loop-file "inf" "no" #menu: Tools > Toggle Infinite Looping
|
||||
Del script-binding osc/visibility #menu: Tools > Toggle OSC Visibility
|
||||
Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Cycle Hardware Decoding
|
||||
F8 show-text ${playlist} 5000 #menu: Tools > Show Playlist
|
||||
F9 show-text ${track-list} 5000 #menu: Tools > Show Audio/Video/Subtitle List
|
||||
_ script-message mpv.net execute-mpv-command #menu: Tools > Execute mpv command...
|
||||
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Show mpv manual
|
||||
_ script-message mpv.net shell-execute https://github.com/mpv-player/mpv/blob/master/etc/input.conf #menu: Help > Show mpv default keys
|
||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt #menu: Help > Show mpv.net default keys
|
||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpvnet #menu: Help > Show mpv.net web site
|
||||
_ ignore #menu: -
|
||||
Esc quit #menu: Exit
|
||||
Q quit-watch-later #menu: Exit Watch Later
|
||||
> playlist-next
|
||||
< playlist-prev
|
||||
Enter cycle pause
|
||||
Power quit
|
||||
Play cycle pause
|
||||
Pause cycle pause
|
||||
PlayPause cycle pause
|
||||
Stop quit
|
||||
Forward seek 60
|
||||
Rewind seek -60
|
||||
Mute cycle mute
|
||||
Volume_Up add volume 10
|
||||
Volume_Down add volume -10
|
||||
Wheel_Up add volume 10
|
||||
Wheel_Down add volume -10
|
||||
@@ -1,140 +0,0 @@
|
||||
# mpv.net key bindings, mouse bindings and context menu configuration
|
||||
|
||||
o script-message mpv.net open-files #menu: O ; Open Files...
|
||||
_ ignore #menu: _ ; -
|
||||
Space cycle pause #menu: Space, Enter ; Play/Pause
|
||||
Enter cycle pause
|
||||
s stop #menu: S ; Stop
|
||||
_ ignore #menu: _ ; -
|
||||
f cycle fullscreen #menu: F ; Toggle Fullscreen
|
||||
|
||||
F11 playlist-prev #menu: F11 ; Navigate > Previous
|
||||
F12 playlist-next #menu: F12 ; Navigate > Next
|
||||
_ ignore #menu: _ ; Navigate > -
|
||||
PGUP add chapter 1 #menu: Page Up ; Navigate > Next Chapter
|
||||
PGDWN add chapter -1 #menu: Page Down ; Navigate > Previous Chapter
|
||||
|
||||
. frame-step #menu: . ; Seek > Next Frame
|
||||
, frame-back-step #menu: , ; Seek > Previous Frame
|
||||
_ ignore #menu: _ ; Seek > -
|
||||
Right no-osd seek 7 #menu: Right ; Seek > 7 sec forward
|
||||
Left no-osd seek -7 #menu: Left ; Seek > 7 sec backward
|
||||
_ ignore #menu: _ ; Seek > -
|
||||
Up no-osd seek 40 #menu: Up ; Seek > 40 sec forward
|
||||
Down no-osd seek -40 #menu: Down ; Seek > 40 sec backward
|
||||
_ ignore #menu: _ ; Seek > -
|
||||
Ctrl+Right no-osd seek 300 #menu: Ctrl+Right ; Seek > 5 min forward
|
||||
Ctrl+Left no-osd seek -300 #menu: Ctrl+Left ; Seek > 5 min backward
|
||||
|
||||
Ctrl++ add video-zoom 0.1 #menu: Ctrl++ ; Pan && Scan > Increase Size
|
||||
Ctrl+- add video-zoom -0.1 #menu: Ctrl+- ; Pan && Scan > Decrease Size
|
||||
_ ignore #menu: _ ; Pan && Scan > -
|
||||
Shift+Left add video-pan-x -0.01 #menu: Shift+Left ; Pan && Scan > Move Left
|
||||
Shift+Right add video-pan-x 0.01 #menu: Shift+Right ; Pan && Scan > Move Right
|
||||
_ ignore #menu: _ ; Pan && Scan > -
|
||||
Shift+Up add video-pan-y -0.01 #menu: Shift+Up ; Pan && Scan > Move Up
|
||||
Shift+Down add video-pan-y 0.01 #menu: Shift+Down ; Pan && Scan > Move Down
|
||||
_ ignore #menu: _ ; Pan && Scan > -
|
||||
w add panscan -0.1 #menu: W ; Pan && Scan > Decrease Height
|
||||
W add panscan +0.1 #menu: Shift+W ; Pan && Scan > Increase Height
|
||||
_ ignore #menu: _ ; Pan && Scan > -
|
||||
Shift+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 #menu: Alt+Backspace ; Pan && Scan > Reset
|
||||
|
||||
Ctrl+1 add contrast -1 #menu: Ctrl+1 ; Video > Decrease Contrast
|
||||
Ctrl+2 add contrast 1 #menu: Ctrl+2 ; Video > Increase Contrast
|
||||
_ ignore #menu: _ ; Video > -
|
||||
Ctrl+3 add brightness -1 #menu: Ctrl+3 ; Video > Decrease Brightness
|
||||
Ctrl+4 add brightness 1 #menu: Ctrl+4 ; Video > Increase Brightness
|
||||
_ ignore #menu: _ ; Video > -
|
||||
Ctrl+5 add gamma -1 #menu: Ctrl+5 ; Video > Decrease Gamma
|
||||
Ctrl+6 add gamma 1 #menu: Ctrl+6 ; Video > Increase Gamma
|
||||
_ ignore #menu: _ ; Video > -
|
||||
Ctrl+7 add saturation -1 #menu: Ctrl+7 ; Video > Decrease Saturation
|
||||
Ctrl+8 add saturation 1 #menu: Ctrl+8 ; Video > Increase Saturation
|
||||
_ ignore #menu: _ ; Video > -
|
||||
Ctrl+S async screenshot #menu: Ctrl+S ; Video > Take Screenshot
|
||||
Ctrl+Shift+S screenshot each-frame #menu: Ctrl+Shift+S ; Video > Take Screenshots All Frames
|
||||
_ ignore #menu: _ ; Video > -
|
||||
d cycle deinterlace #menu: D ; Video > Toggle Deinterlace
|
||||
a cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" #menu: A ; Video > Cycle Aspect Ratio
|
||||
|
||||
KP7 cycle audio #menu: Keypad 7 ; Audio > Cycle/Next
|
||||
_ ignore #menu: _ ; Audio > -
|
||||
KP6 add audio-delay 0.100 #menu: Keypad 6 ; Audio > Delay +0.1
|
||||
KP9 add audio-delay -0.100 #menu: Keypad 9 ; Audio > Delay -0.1
|
||||
|
||||
KP8 cycle sub #menu: Keypad 8 ; Subtitle > Cycle/Next
|
||||
v cycle sub-visibility #menu: V ; Subtitle > Toggle Visibility
|
||||
_ ignore #menu: _ ; Subtitle > -
|
||||
z add sub-delay -0.1 #menu: Z ; Subtitle > Delay -0.1
|
||||
Z add sub-delay +0.1 #menu: Shift+Z ; Subtitle > Delay +0.1
|
||||
_ ignore #menu: _ ; Subtitle > -
|
||||
r add sub-pos -1 #menu: R ; Subtitle > Move Up
|
||||
R add sub-pos +1 #menu: Shift+R ; Subtitle > Move Down
|
||||
_ ignore #menu: _ ; Subtitle > -
|
||||
_ add sub-scale -0.1 #menu: _ ; Subtitle > Decrease Subtitle Font Size
|
||||
_ add sub-scale +0.1 #menu: _ ; Subtitle > Increase Subtitle Font Size
|
||||
_ ignore #menu: _ ; Subtitle > -
|
||||
|
||||
+ add volume 10 #menu: + ; Volume > Up
|
||||
- add volume -10 #menu: - ; Volume > Down
|
||||
WHEEL_UP add volume 10
|
||||
WHEEL_DOWN add volume -10
|
||||
_ ignore #menu: _ ; Volume > -
|
||||
m cycle mute #menu: M ; Volume > Mute
|
||||
|
||||
[ multiply speed 0.9 #menu: [ ; Speed > -10%
|
||||
] multiply speed 1.1 #menu: ] ; Speed > +10%
|
||||
_ ignore #menu: _ ; Speed > -
|
||||
{ multiply speed 0.5 #menu: { ; Speed > Half
|
||||
} multiply speed 2.0 #menu: } ; Speed > Double
|
||||
_ ignore #menu: _ ; Speed > -
|
||||
BS set speed 1 #menu: Backspace ; Speed > Reset
|
||||
|
||||
KP0 script-message rate-file 0 #menu: Keypad 0 ; Addons > Rating > 0stars
|
||||
KP1 script-message rate-file 1 #menu: Keypad 1 ; Addons > Rating > 1stars
|
||||
KP2 script-message rate-file 2 #menu: Keypad 2 ; Addons > Rating > 2stars
|
||||
KP3 script-message rate-file 3 #menu: Keypad 3 ; Addons > Rating > 3stars
|
||||
KP4 script-message rate-file 4 #menu: Keypad 4 ; Addons > Rating > 4stars
|
||||
KP5 script-message rate-file 5 #menu: Keypad 5 ; Addons > Rating > 5stars
|
||||
|
||||
_ script-message mpv.net set-setting hwdec yes #menu: _ ; Settings > Hardware Decoding > Enable
|
||||
_ script-message mpv.net set-setting hwdec no #menu: _ ; Settings > Hardware Decoding > Disable
|
||||
p script-message mpv.net show-prefs #menu: P ; Settings > Show Preferences
|
||||
k script-message mpv.net show-keys #menu: K ; Settings > Show Keys
|
||||
c script-message mpv.net open-config-folder #menu: C ; Settings > Open Config Folder
|
||||
|
||||
i show-progress ; script-message mpv.net show-info #menu: I ; Tools | Info
|
||||
t script-binding stats/display-stats #menu: T ; Tools > Show Statistics
|
||||
T script-binding stats/display-stats-toggle #menu: Shift+T ; Tools > Toggle Statistics
|
||||
_ ignore #menu: _ ; Tools > -
|
||||
h script-message mpv.net history #menu: H ; Tools > Show History
|
||||
l ab-loop #menu: L ; Tools > Set/clear A-B loop points
|
||||
L cycle-values loop-file "inf" "no" #menu: Shift+L ; Tools > Toggle Infinite Looping
|
||||
DEL script-binding osc/visibility #menu: Delete ; Tools > Toggle OSC Visibility
|
||||
Ctrl+H cycle-values hwdec "auto" "no" #menu: Ctrl+H ; Tools > Cycle Hardware Decoding
|
||||
F8 show-text ${playlist} 5000 #menu: F8 ; Tools > Show Playlist
|
||||
F9 show-text ${track-list} 5000 #menu: F9 ; Tools > Show Audio/Video/Subtitle List
|
||||
|
||||
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: _ ; Tools > Web > Show mpv manual
|
||||
_ script-message mpv.net shell-execute https://github.com/mpv-player/mpv/blob/master/etc/input.conf #menu: _ ; Tools > Web > Show mpv default keys
|
||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpvnet #menu: _ ; Tools > Web > Show mpv.net web site
|
||||
_ ignore #menu: _ ; -
|
||||
Esc quit #menu: Escape ; Exit
|
||||
Q quit-watch-later #menu: Shift+Q ; Exit Watch Later
|
||||
|
||||
> playlist-next
|
||||
< playlist-prev
|
||||
|
||||
POWER quit
|
||||
PLAY cycle pause
|
||||
PAUSE cycle pause
|
||||
PLAYPAUSE cycle pause
|
||||
STOP quit
|
||||
FORWARD seek 60
|
||||
REWIND seek -60
|
||||
VOLUME_UP add volume 2
|
||||
VOLUME_DOWN add volume -2
|
||||
MUTE cycle mute
|
||||
CLOSE_WIN quit
|
||||
CLOSE_WIN {encode} quit 4
|
||||
13
mpv.net/Resources/mpv.conf.txt
Normal file
13
mpv.net/Resources/mpv.conf.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
# mpv manual: https://mpv.io/manual/master/
|
||||
# mpv.net mpv.conf defaults: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt
|
||||
|
||||
input-ar-delay = 500
|
||||
input-ar-rate = 20
|
||||
volume = 50
|
||||
hwdec = yes
|
||||
vo = direct3d
|
||||
keep-open = yes
|
||||
keep-open-pause = no
|
||||
osd-playing-msg = ${filename}
|
||||
screenshot-directory = ~~desktop/
|
||||
input-default-bindings = no
|
||||
@@ -1,120 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static string ExtFull(this string filepath)
|
||||
{
|
||||
return Ext(filepath, true);
|
||||
}
|
||||
|
||||
public static string Ext(this string filepath)
|
||||
{
|
||||
return Ext(filepath, false);
|
||||
}
|
||||
|
||||
public static string Ext(this string filepath, bool dot)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filepath))
|
||||
return "";
|
||||
|
||||
var chars = filepath.ToCharArray();
|
||||
|
||||
for (var x = filepath.Length - 1; x >= 0; x += -1)
|
||||
{
|
||||
if (chars[x] == Path.DirectorySeparatorChar)
|
||||
return "";
|
||||
|
||||
if (chars[x] == '.')
|
||||
return filepath.Substring(x + (dot ? 0 : 1)).ToLower();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string Left(this string value, int index)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value) || index < 0)
|
||||
return "";
|
||||
|
||||
if (index > value.Length)
|
||||
return value;
|
||||
|
||||
return value.Substring(0, index);
|
||||
}
|
||||
|
||||
public static string Left(this string value, string start)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
|
||||
return "";
|
||||
|
||||
if (!value.Contains(start))
|
||||
return "";
|
||||
|
||||
return value.Substring(0, value.IndexOf(start));
|
||||
}
|
||||
|
||||
public static string LeftLast(this string value, string start)
|
||||
{
|
||||
if (!value.Contains(start))
|
||||
return "";
|
||||
|
||||
return value.Substring(0, value.LastIndexOf(start));
|
||||
}
|
||||
|
||||
public static string Right(this string value, string start)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
|
||||
return "";
|
||||
|
||||
if (!value.Contains(start))
|
||||
return "";
|
||||
|
||||
return value.Substring(value.IndexOf(start) + start.Length);
|
||||
}
|
||||
|
||||
public static string RightLast(this string value, string start)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
|
||||
return "";
|
||||
|
||||
if (!value.Contains(start))
|
||||
return "";
|
||||
|
||||
return value.Substring(value.LastIndexOf(start) + start.Length);
|
||||
}
|
||||
|
||||
public static string[] SplitNoEmpty(this string value, params string[] delimiters)
|
||||
{
|
||||
return value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public static string[] SplitKeepEmpty(this string value, params string[] delimiters)
|
||||
{
|
||||
return value.Split(delimiters, StringSplitOptions.None);
|
||||
}
|
||||
|
||||
public static string[] SplitNoEmptyAndWhiteSpace(this string value, params string[] delimiters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return null;
|
||||
|
||||
var a = SplitNoEmpty(value, delimiters);
|
||||
|
||||
for (var i = 0; i <= a.Length - 1; i++)
|
||||
a[i] = a[i].Trim();
|
||||
|
||||
var l = a.ToList();
|
||||
|
||||
while (l.Contains(""))
|
||||
l.Remove("");
|
||||
|
||||
return l.ToArray();
|
||||
}
|
||||
|
||||
public static string[] SplitLinesNoEmpty(this string value)
|
||||
{
|
||||
return SplitNoEmpty(value, Environment.NewLine);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,9 @@
|
||||
</compatibility>
|
||||
<application>
|
||||
<windowsSettings>
|
||||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<dependency>
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace mpvnet
|
||||
public static extern int mpv_set_option_string(IntPtr mpvHandle, byte[] name, byte[] value);
|
||||
|
||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref IntPtr data);
|
||||
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, out IntPtr data);
|
||||
|
||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data);
|
||||
|
||||
208
mpv.net/mp.cs
208
mpv.net/mp.cs
@@ -7,12 +7,12 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using static mpvnet.libmpv;
|
||||
using static mpvnet.Native;
|
||||
using static mpvnet.StaticUsing;
|
||||
|
||||
using PyRT = IronPython.Runtime;
|
||||
|
||||
@@ -60,49 +60,45 @@ namespace mpvnet
|
||||
public static string mpvConfFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
|
||||
public static string InputConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
|
||||
public static string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
|
||||
public static List<PyScript> PyScripts { get; } = new List<PyScript>();
|
||||
public static List<PythonScript> PythonScripts => new List<PythonScript>();
|
||||
public static AutoResetEvent AutoResetEvent = new AutoResetEvent(false);
|
||||
|
||||
private static Dictionary<string, string> _mpvConv;
|
||||
private static Dictionary<string, string> _mpvConf;
|
||||
|
||||
public static Dictionary<string, string> mpvConv {
|
||||
public static Dictionary<string, string> mpvConf {
|
||||
get {
|
||||
if (_mpvConv == null)
|
||||
if (_mpvConf == null)
|
||||
{
|
||||
_mpvConv = new Dictionary<string, string>();
|
||||
_mpvConf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(mpvConfPath))
|
||||
{
|
||||
foreach (var i in File.ReadAllLines(mpvConfPath))
|
||||
{
|
||||
if (i.Contains("=") && ! i.StartsWith("#"))
|
||||
{
|
||||
_mpvConv[i.Left("=").Trim()] = i.Right("=").Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
_mpvConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||
}
|
||||
return _mpvConv;
|
||||
return _mpvConf;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (!Directory.Exists(mp.mpvConfFolderPath))
|
||||
Directory.CreateDirectory(mp.mpvConfFolderPath);
|
||||
|
||||
if (!File.Exists(mp.mpvConfPath))
|
||||
File.WriteAllText(mp.mpvConfPath, Properties.Resources.mpv_conf);
|
||||
|
||||
if (!File.Exists(mp.InputConfPath))
|
||||
File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf);
|
||||
|
||||
LoadLibrary("mpv-1.dll");
|
||||
MpvHandle = mpv_create();
|
||||
SetIntProp("input-ar-delay", 500);
|
||||
SetIntProp("input-ar-rate", 20);
|
||||
SetIntProp("volume", 50);
|
||||
SetStringProp("hwdec", "yes");
|
||||
SetStringProp("vo", "direct3d");
|
||||
SetStringProp("input-default-bindings", "yes");
|
||||
SetStringProp("osd-playing-msg", "'${filename}'");
|
||||
SetStringProp("screenshot-directory", "~~desktop/");
|
||||
SetStringProp("keep-open", "yes");
|
||||
SetStringProp("keep-open-pause", "no");
|
||||
SetStringProp("osc", "yes");
|
||||
SetStringProp("config", "yes");
|
||||
SetStringProp("wid", MainForm.Hwnd.ToString());
|
||||
SetStringProp("force-window", "yes");
|
||||
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);
|
||||
ProcessCommandLine();
|
||||
Task.Run(() => { LoadScripts(); });
|
||||
@@ -117,14 +113,21 @@ namespace mpvnet
|
||||
|
||||
foreach (var scriptPath in startupScripts)
|
||||
if (jsLua.Contains(Path.GetExtension(scriptPath).ToLower()))
|
||||
mp.Command("load-script", $"{scriptPath}");
|
||||
mp.commandv("load-script", $"{scriptPath}");
|
||||
|
||||
foreach (var scriptPath in startupScripts)
|
||||
if (Path.GetExtension(scriptPath) == ".py")
|
||||
PyScripts.Add(new PyScript(File.ReadAllText(scriptPath)));
|
||||
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
|
||||
|
||||
foreach(var scriptPath in Directory.GetFiles(mp.mpvConfFolderPath + "scripts", "*.py"))
|
||||
PyScripts.Add(new PyScript(File.ReadAllText(scriptPath)));
|
||||
foreach (var scriptPath in startupScripts)
|
||||
if (Path.GetExtension(scriptPath) == ".ps1")
|
||||
PowerShellScript.Init(scriptPath);
|
||||
|
||||
foreach (var scriptPath in Directory.GetFiles(mp.mpvConfFolderPath + "Scripts"))
|
||||
if (Path.GetExtension(scriptPath) == ".py")
|
||||
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
|
||||
else if (Path.GetExtension(scriptPath) == ".ps1")
|
||||
PowerShellScript.Init(scriptPath);
|
||||
}
|
||||
|
||||
public static void EventLoop()
|
||||
@@ -133,15 +136,17 @@ namespace mpvnet
|
||||
{
|
||||
IntPtr ptr = mpv_wait_event(MpvHandle, -1);
|
||||
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event));
|
||||
//Debug.WriteLine(evt.event_id);
|
||||
|
||||
if (MpvWindowHandle == IntPtr.Zero)
|
||||
MpvWindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
|
||||
|
||||
//Debug.WriteLine(evt.event_id.ToString());
|
||||
|
||||
switch (evt.event_id)
|
||||
{
|
||||
case mpv_event_id.MPV_EVENT_SHUTDOWN:
|
||||
Shutdown?.Invoke();
|
||||
AutoResetEvent.Set();
|
||||
return;
|
||||
case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
|
||||
LogMessage?.Invoke();
|
||||
@@ -202,7 +207,7 @@ namespace mpvnet
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MsgError(ex.GetType().Name + "\r\n\r\n" + ex.ToString());
|
||||
MainForm.Instance.ShowMsgBox(ex.GetType().Name + "\n\n" + ex.ToString(), MessageBoxIcon.Error);
|
||||
}
|
||||
ClientMessage?.Invoke(args);
|
||||
}
|
||||
@@ -229,7 +234,7 @@ namespace mpvnet
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
|
||||
PlaybackRestart?.Invoke();
|
||||
Size s = new Size(GetIntProp("dwidth", false), GetIntProp("dheight", false));
|
||||
Size s = new Size(get_property_int("dwidth"), get_property_int("dheight"));
|
||||
|
||||
if (VideoSize != s && s != Size.Empty)
|
||||
{
|
||||
@@ -250,29 +255,7 @@ namespace mpvnet
|
||||
}
|
||||
}
|
||||
|
||||
public class EventObject
|
||||
{
|
||||
public PyRT.PythonFunction PythonFunction { get; set; }
|
||||
public EventInfo EventInfo { get; set; }
|
||||
public Delegate Delegate { get; set; }
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
PyRT.Operations.PythonCalls.Call(PythonFunction);
|
||||
}
|
||||
|
||||
public void InvokeEndFileEventMode(EndFileEventMode arg)
|
||||
{
|
||||
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
|
||||
}
|
||||
|
||||
public void InvokeStrings(string[] arg)
|
||||
{
|
||||
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
|
||||
}
|
||||
}
|
||||
|
||||
private static List<EventObject> EventObjects = new List<EventObject>();
|
||||
private static List<PythonEventObject> PythonEventObjects = new List<PythonEventObject>();
|
||||
|
||||
public static void register_event(string name, PyRT.PythonFunction pyFunc)
|
||||
{
|
||||
@@ -280,22 +263,22 @@ namespace mpvnet
|
||||
{
|
||||
if (eventInfo.Name.ToLower() == name.Replace("-", ""))
|
||||
{
|
||||
EventObject eventObject = new EventObject();
|
||||
EventObjects.Add(eventObject);
|
||||
PythonEventObject eventObject = new PythonEventObject();
|
||||
PythonEventObjects.Add(eventObject);
|
||||
eventObject.PythonFunction = pyFunc;
|
||||
MethodInfo mi;
|
||||
|
||||
if (eventInfo.EventHandlerType == typeof(Action))
|
||||
{
|
||||
mi = eventObject.GetType().GetMethod(nameof(EventObject.Invoke));
|
||||
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.Invoke));
|
||||
}
|
||||
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
|
||||
{
|
||||
mi = eventObject.GetType().GetMethod(nameof(EventObject.InvokeEndFileEventMode));
|
||||
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.InvokeEndFileEventMode));
|
||||
}
|
||||
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
|
||||
{
|
||||
mi = eventObject.GetType().GetMethod(nameof(EventObject.InvokeStrings));
|
||||
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.InvokeStrings));
|
||||
}
|
||||
else
|
||||
throw new Exception();
|
||||
@@ -304,29 +287,24 @@ namespace mpvnet
|
||||
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
|
||||
eventObject.Delegate = handler;
|
||||
eventInfo.AddEventHandler(eventObject, handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void unregister_event(PyRT.PythonFunction pyFunc)
|
||||
{
|
||||
foreach (var eventObjects in EventObjects)
|
||||
foreach (var eventObjects in PythonEventObjects)
|
||||
if (eventObjects.PythonFunction == pyFunc)
|
||||
eventObjects.EventInfo.RemoveEventHandler(eventObjects, eventObjects.Delegate);
|
||||
}
|
||||
|
||||
public static void commandv(params string[] args)
|
||||
{
|
||||
Command(args);
|
||||
}
|
||||
|
||||
public static void Command(params string[] args)
|
||||
{
|
||||
if (MpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
IntPtr[] byteArrayPointers;
|
||||
var mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out byteArrayPointers);
|
||||
IntPtr mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out IntPtr[] byteArrayPointers);
|
||||
int err = mpv_command(MpvHandle, mainPtr);
|
||||
|
||||
if (err < 0)
|
||||
@@ -338,7 +316,7 @@ namespace mpvnet
|
||||
Marshal.FreeHGlobal(mainPtr);
|
||||
}
|
||||
|
||||
public static void CommandString(string command, bool throwException = true)
|
||||
public static void command_string(string command, bool throwException = false)
|
||||
{
|
||||
if (MpvHandle == IntPtr.Zero)
|
||||
return;
|
||||
@@ -349,21 +327,20 @@ namespace mpvnet
|
||||
throw new Exception($"{(mpv_error)err}\r\n\r\n" + command);
|
||||
}
|
||||
|
||||
public static void SetStringProp(string name, string value, bool throwException = true)
|
||||
public static void set_property_string(string name, string value, bool throwOnException = false)
|
||||
{
|
||||
var bytes = GetUtf8Bytes(value);
|
||||
byte[] bytes = GetUtf8Bytes(value);
|
||||
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
|
||||
|
||||
if (err < 0 && throwException)
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
}
|
||||
|
||||
public static string GetStringProp(string name)
|
||||
public static string get_property_string(string name, bool throwOnException = false)
|
||||
{
|
||||
var lpBuffer = IntPtr.Zero;
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref lpBuffer);
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0)
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
|
||||
var ret = StringFromNativeUtf8(lpBuffer);
|
||||
@@ -372,43 +349,47 @@ namespace mpvnet
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int GetIntProp(string name, bool throwException = true)
|
||||
public static int get_property_int(string name, bool throwOnException = false)
|
||||
{
|
||||
var lpBuffer = IntPtr.Zero;
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref lpBuffer);
|
||||
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0 && throwException)
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
else
|
||||
return lpBuffer.ToInt32();
|
||||
}
|
||||
|
||||
public static double get_property_number(string name)
|
||||
{
|
||||
return GetDoubleProp(name);
|
||||
}
|
||||
|
||||
public static double GetDoubleProp(string name, bool throwException = true)
|
||||
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);
|
||||
|
||||
if (err < 0 && throwException)
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
public static void SetIntProp(string name, int value)
|
||||
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);
|
||||
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
else
|
||||
return lpBuffer.ToInt32() == 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (err < 0)
|
||||
if (err < 0 && throwOnException)
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
}
|
||||
|
||||
public static void ObserveBoolProp(string name, Action<bool> action)
|
||||
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);
|
||||
|
||||
@@ -418,7 +399,7 @@ namespace mpvnet
|
||||
BoolPropChangeActions.Add(new KeyValuePair<string, Action<bool>>(name, action));
|
||||
}
|
||||
|
||||
public static void UnobserveBoolProp(string name, Action<bool> action)
|
||||
public static void unobserve_property_bool(string name, Action<bool> action)
|
||||
{
|
||||
foreach (var i in BoolPropChangeActions.ToArray())
|
||||
if (i.Value == action)
|
||||
@@ -430,15 +411,17 @@ namespace mpvnet
|
||||
throw new Exception($"{name}: {(mpv_error)err}");
|
||||
}
|
||||
|
||||
public static void ProcessCommandLine()
|
||||
protected static void ProcessCommandLine()
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs().Skip(1);
|
||||
|
||||
foreach (string i in args)
|
||||
if (!i.StartsWith("--") && File.Exists(i))
|
||||
mp.Command("loadfile", i, "append");
|
||||
mp.commandv("loadfile", i, "append");
|
||||
else if (!i.StartsWith("--") && i.StartsWith("http"))
|
||||
mp.LoadURL(i);
|
||||
|
||||
mp.SetStringProp("playlist-pos", "0", false);
|
||||
mp.set_property_string("playlist-pos", "0");
|
||||
|
||||
foreach (string i in args)
|
||||
{
|
||||
@@ -448,25 +431,34 @@ namespace mpvnet
|
||||
{
|
||||
string left = i.Substring(2, i.IndexOf("=") - 2);
|
||||
string right = i.Substring(left.Length + 3);
|
||||
mp.SetStringProp(left, right);
|
||||
mp.set_property_string(left, right);
|
||||
}
|
||||
else
|
||||
mp.SetStringProp(i.Substring(2), "yes");
|
||||
mp.set_property_string(i.Substring(2), "yes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadURL(string url)
|
||||
{
|
||||
int count = mp.get_property_int("playlist-count");
|
||||
mp.commandv("loadfile", url, "append");
|
||||
mp.set_property_int("playlist-pos", count);
|
||||
for (int i = 0; i < count; i++)
|
||||
mp.commandv("playlist-remove", "0");
|
||||
}
|
||||
|
||||
public static void LoadFiles(string[] files)
|
||||
{
|
||||
int count = mp.GetIntProp("playlist-count");
|
||||
int count = mp.get_property_int("playlist-count");
|
||||
|
||||
foreach (string file in files)
|
||||
mp.Command("loadfile", file, "append");
|
||||
mp.commandv("loadfile", file, "append");
|
||||
|
||||
mp.SetIntProp("playlist-pos", count);
|
||||
mp.set_property_int("playlist-pos", count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
mp.Command("playlist-remove", "0");
|
||||
mp.commandv("playlist-remove", "0");
|
||||
|
||||
mp.LoadFolder();
|
||||
}
|
||||
@@ -478,21 +470,21 @@ namespace mpvnet
|
||||
if (WasFolderLoaded)
|
||||
return;
|
||||
|
||||
if (GetIntProp("playlist-count") == 1)
|
||||
if (get_property_int("playlist-count") == 1)
|
||||
{
|
||||
string[] types = "264 265 3gp aac ac3 avc avi avs bmp divx dts dtshd dtshr dtsma eac3 evo flac flv h264 h265 hevc hvc jpg jpeg m2t m2ts m2v m4a m4v mka mkv mlp mov mp2 mp3 mp4 mpa mpeg mpg mpv mts ogg ogm opus pcm png pva raw rmvb thd thd+ac3 true-hd truehd ts vdr vob vpy w64 wav webm wmv y4m".Split(' ');
|
||||
string path = GetStringProp("path");
|
||||
string path = get_property_string("path");
|
||||
List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
|
||||
files = files.Where((file) => types.Contains(file.Ext())).ToList();
|
||||
files = files.Where((file) => types.Contains(Path.GetExtension(file).TrimStart(".".ToCharArray()).ToLower())).ToList();
|
||||
files.Sort(new StringLogicalComparer());
|
||||
int index = files.IndexOf(path);
|
||||
files.Remove(path);
|
||||
|
||||
foreach (string i in files)
|
||||
Command("loadfile", i, "append");
|
||||
commandv("loadfile", i, "append");
|
||||
|
||||
if (index > 0)
|
||||
Command("playlist-move", "0", (index + 1).ToString());
|
||||
commandv("playlist-move", "0", (index + 1).ToString());
|
||||
}
|
||||
|
||||
WasFolderLoaded = true;
|
||||
|
||||
@@ -19,17 +19,18 @@
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
@@ -117,23 +118,31 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>IronPython\Microsoft.Scripting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Addon.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="MediaInfo.cs" />
|
||||
<Compile Include="Menu.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PyScript.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PowerShellScript.cs" />
|
||||
<Compile Include="PythonScript.cs" />
|
||||
<Compile Include="libmpv.cs" />
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
@@ -148,6 +157,7 @@
|
||||
<Compile Include="NativeHelp.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="trash.cs" />
|
||||
<Compile Include="UI.cs" />
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
@@ -155,15 +165,11 @@
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
@@ -173,6 +179,7 @@
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Content Include="Resources\mpv.conf.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
@@ -180,7 +187,7 @@
|
||||
<ItemGroup>
|
||||
<Content Include="mpv.ico" />
|
||||
<Content Include="screenshot.jpg" />
|
||||
<None Include="Resources\input_conf.txt" />
|
||||
<Content Include="Resources\input.conf.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
||||
4
mpv.net/packages.config
Normal file
4
mpv.net/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.PowerShell.5.ReferenceAssemblies" version="1.1.0" targetFramework="net472" />
|
||||
</packages>
|
||||
22
mpv.net/trash.cs
Normal file
22
mpv.net/trash.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
//public static string GetAssociatedApplication(string ext)
|
||||
//{
|
||||
// uint returnValue = 0U;
|
||||
// // ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE
|
||||
// if (1 == Native.AssocQueryString(0x40, 2, ext, null, null, ref returnValue))
|
||||
// {
|
||||
// if (returnValue > 0)
|
||||
// {
|
||||
// StringBuilder sb = new StringBuilder(Convert.ToInt32(returnValue));
|
||||
// // ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE
|
||||
// if (0 == Native.AssocQueryString(0x40, 2, ext, null, sb, ref returnValue))
|
||||
// {
|
||||
// var ret = sb.ToString();
|
||||
// if (File.Exists(ret)) return ret;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return "";
|
||||
//}
|
||||
|
||||
//[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
//public static extern uint AssocQueryString(uint flags, uint str, string pszAssoc, string pszExtra, StringBuilder pszOut, ref uint pcchOut);
|
||||
6
mpvConfEdit/App.config
Normal file
6
mpvConfEdit/App.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
30
mpvConfEdit/App.xaml
Normal file
30
mpvConfEdit/App.xaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<Application x:Class="DynamicGUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:DynamicGUI"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
|
||||
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsFocused" Value="true">
|
||||
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static SystemParameters.WindowGlassBrush}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
8
mpvConfEdit/App.xaml.cs
Normal file
8
mpvConfEdit/App.xaml.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
136
mpvConfEdit/DynamicGUI/DynamicGUI.cs
Normal file
136
mpvConfEdit/DynamicGUI/DynamicGUI.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Navigation;
|
||||
using Tommy;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
public static List<SettingBase> LoadSettings(string filepath)
|
||||
{
|
||||
TomlTable table;
|
||||
using (StreamReader reader = new StreamReader(File.OpenRead(filepath)))
|
||||
table = TOML.Parse(reader);
|
||||
List<SettingBase> settingsList = new List<SettingBase>();
|
||||
|
||||
foreach (TomlTable setting in table["settings"])
|
||||
{
|
||||
SettingBase baseSetting = null;
|
||||
|
||||
if (setting.HasKey("options"))
|
||||
{
|
||||
OptionSetting optionSetting = new OptionSetting();
|
||||
baseSetting = optionSetting;
|
||||
optionSetting.Default = setting["default"];
|
||||
optionSetting.Value = optionSetting.Default;
|
||||
|
||||
foreach (TomlTable option in setting["options"])
|
||||
{
|
||||
var opt = new OptionSettingOption();
|
||||
opt.Name = option["name"];
|
||||
if (option.HasKey("help"))
|
||||
opt.Help = option["help"];
|
||||
if (option.HasKey("text"))
|
||||
opt.Text = option["text"];
|
||||
else if (opt.Name == optionSetting.Default)
|
||||
opt.Text = opt.Name + " (Default)";
|
||||
opt.OptionSetting = optionSetting;
|
||||
optionSetting.Options.Add(opt);
|
||||
}
|
||||
}
|
||||
else if (setting["default"].IsString)
|
||||
{
|
||||
StringSetting stringSetting = new StringSetting();
|
||||
baseSetting = stringSetting;
|
||||
stringSetting.Default = setting["default"];
|
||||
if (setting.HasKey("folder")) stringSetting.IsFolder = true;
|
||||
}
|
||||
|
||||
baseSetting.Name = setting["name"];
|
||||
baseSetting.Filter = setting["filter"];
|
||||
if (setting.HasKey("help")) baseSetting.Help = setting["help"];
|
||||
if (setting.HasKey("helpurl")) baseSetting.HelpURL = setting["helpurl"];
|
||||
if (setting.HasKey("alias")) baseSetting.Alias = setting["alias"];
|
||||
if (setting.HasKey("width")) baseSetting.Width = setting["width"];
|
||||
settingsList.Add(baseSetting);
|
||||
}
|
||||
return settingsList;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SettingBase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public string Help { get; set; }
|
||||
public string HelpURL { get; set; }
|
||||
public string Filter { get; set; }
|
||||
public int Width { get; set; }
|
||||
}
|
||||
|
||||
public class StringSetting : SettingBase
|
||||
{
|
||||
public string Default { get; set; }
|
||||
public string Value { get; set; }
|
||||
public bool IsFolder { get; set; }
|
||||
}
|
||||
|
||||
public class OptionSetting : SettingBase
|
||||
{
|
||||
public string Default { get; set; }
|
||||
public string Value { get; set; }
|
||||
public List<OptionSettingOption> Options = new List<OptionSettingOption>();
|
||||
}
|
||||
|
||||
public class OptionSettingOption
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Help { get; set; }
|
||||
|
||||
public OptionSetting OptionSetting { get; set; }
|
||||
|
||||
private string _Text;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => string.IsNullOrEmpty(_Text) ? Name : _Text;
|
||||
set => _Text = value;
|
||||
}
|
||||
|
||||
public bool IsChecked
|
||||
{
|
||||
get => OptionSetting.Value == Name ;
|
||||
set {
|
||||
if (value)
|
||||
OptionSetting.Value = Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ISettingControl
|
||||
{
|
||||
bool Contains(string searchString);
|
||||
SettingBase SettingBase { get; }
|
||||
}
|
||||
|
||||
public class HyperlinkEx : Hyperlink
|
||||
{
|
||||
private void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
Process.Start(e.Uri.AbsoluteUri);
|
||||
}
|
||||
|
||||
public void SetURL(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) return;
|
||||
NavigateUri = new Uri(url);
|
||||
RequestNavigate += HyperLinkEx_RequestNavigate;
|
||||
Inlines.Clear();
|
||||
Inlines.Add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
mpvConfEdit/DynamicGUI/OptionSettingControl.xaml
Normal file
28
mpvConfEdit/DynamicGUI/OptionSettingControl.xaml
Normal file
@@ -0,0 +1,28 @@
|
||||
<UserControl x:Name="OptionSettingControl1" x:Class="DynamicGUI.OptionSettingControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:DynamicGUI"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Margin="20,0">
|
||||
<StackPanel>
|
||||
<TextBox x:Name="TitleTextBox" FontSize="24" Margin="0,10" BorderThickness="0" IsReadOnly="True" Foreground="{x:Static SystemParameters.WindowGlassBrush}"></TextBox>
|
||||
<ItemsControl x:Name="ItemsControl">
|
||||
<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"></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"></TextBox>
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Margin="0,10,0,0"></TextBox>
|
||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
41
mpvConfEdit/DynamicGUI/OptionSettingControl.xaml.cs
Normal file
41
mpvConfEdit/DynamicGUI/OptionSettingControl.xaml.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public partial class OptionSettingControl : UserControl, ISettingControl
|
||||
{
|
||||
private OptionSetting OptionSetting;
|
||||
|
||||
public OptionSettingControl(OptionSetting optionSetting)
|
||||
{
|
||||
OptionSetting = optionSetting;
|
||||
InitializeComponent();
|
||||
TitleTextBox.Text = optionSetting.Name;
|
||||
HelpTextBox.Text = optionSetting.Help;
|
||||
ItemsControl.ItemsSource = optionSetting.Options;
|
||||
Link.SetURL(optionSetting.HelpURL);
|
||||
|
||||
if (string.IsNullOrEmpty(optionSetting.HelpURL))
|
||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private string _SearchableText;
|
||||
|
||||
public string SearchableText {
|
||||
get {
|
||||
if (_SearchableText is null)
|
||||
{
|
||||
_SearchableText = TitleTextBox.Text + HelpTextBox.Text;
|
||||
foreach (var i in OptionSetting.Options)
|
||||
_SearchableText += i.Text + i.Help + i.Name;
|
||||
_SearchableText = _SearchableText.ToLower();
|
||||
}
|
||||
return _SearchableText;
|
||||
}
|
||||
}
|
||||
|
||||
public SettingBase SettingBase => OptionSetting;
|
||||
public bool Contains(string searchString) => SearchableText.Contains(searchString.ToLower());
|
||||
}
|
||||
}
|
||||
27
mpvConfEdit/DynamicGUI/StringSettingControl.xaml
Normal file
27
mpvConfEdit/DynamicGUI/StringSettingControl.xaml
Normal file
@@ -0,0 +1,27 @@
|
||||
<UserControl x:Name="StringSettingControl1" x:Class="DynamicGUI.StringSettingControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:DynamicGUI"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800" >
|
||||
<Grid Margin="20,0">
|
||||
<StackPanel>
|
||||
<TextBox x:Name="TitleTextBox" FontSize="24" Margin="0,10" BorderThickness="0" IsReadOnly="True" Foreground="{x:Static SystemParameters.WindowGlassBrush}"></TextBox>
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox x:Name="ValueTextBox" Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="150" HorizontalAlignment="Left" Height="20"/>
|
||||
<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"></TextBox>
|
||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
58
mpvConfEdit/DynamicGUI/StringSettingControl.xaml.cs
Normal file
58
mpvConfEdit/DynamicGUI/StringSettingControl.xaml.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public partial class StringSettingControl : UserControl, ISettingControl
|
||||
{
|
||||
private StringSetting StringSetting;
|
||||
|
||||
public StringSettingControl(StringSetting stringSetting)
|
||||
{
|
||||
StringSetting = stringSetting;
|
||||
InitializeComponent();
|
||||
TitleTextBox.Text = stringSetting.Name;
|
||||
HelpTextBox.Text = stringSetting.Help;
|
||||
ValueTextBox.Text = stringSetting.Value;
|
||||
if (stringSetting.Width > 0)
|
||||
ValueTextBox.Width = stringSetting.Width;
|
||||
if (!StringSetting.IsFolder)
|
||||
Button.Visibility = Visibility.Hidden;
|
||||
Link.SetURL(StringSetting.HelpURL);
|
||||
|
||||
if (string.IsNullOrEmpty(stringSetting.HelpURL))
|
||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private string _SearchableText;
|
||||
|
||||
public string SearchableText {
|
||||
get {
|
||||
if (_SearchableText is null)
|
||||
_SearchableText = (TitleTextBox.Text + HelpTextBox.Text +ValueTextBox.Text).ToLower();
|
||||
|
||||
return _SearchableText;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(string searchString) => SearchableText.Contains(searchString.ToLower());
|
||||
public SettingBase SettingBase => StringSetting;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => StringSetting.Value;
|
||||
set => StringSetting.Value = value;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
using (var d = new System.Windows.Forms.FolderBrowserDialog())
|
||||
{
|
||||
d.Description = "Choose a folder.";
|
||||
d.SelectedPath = ValueTextBox.Text;
|
||||
if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||
ValueTextBox.Text = d.SelectedPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1824
mpvConfEdit/DynamicGUI/Tommy.cs
Normal file
1824
mpvConfEdit/DynamicGUI/Tommy.cs
Normal file
File diff suppressed because it is too large
Load Diff
36
mpvConfEdit/MainWindow.xaml
Normal file
36
mpvConfEdit/MainWindow.xaml
Normal file
@@ -0,0 +1,36 @@
|
||||
<Window xmlns:Controls="clr-namespace:Controls" x:Name="MainWindow1" x:Class="mpvConfEdit.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Height="500" Width="700" Loaded="MainWindow1_Loaded">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="4*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="10*" />
|
||||
<ColumnDefinition Width="60*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Controls:SearchTextBoxUserControl x:Name="SearchControl" Width="300" Margin="0,0,0,10" Grid.ColumnSpan="2" />
|
||||
<ScrollViewer x:Name="MainScrollViewer" VerticalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="1">
|
||||
<StackPanel x:Name="MainStackPanel"></StackPanel>
|
||||
</ScrollViewer>
|
||||
<StackPanel Margin="20,0,0,0" Grid.Row="1">
|
||||
<ListBox x:Name="FilterListBox" ItemsSource="{Binding FilterStrings}" BorderThickness="0" SelectionChanged="ListBox_SelectionChanged" Foreground="{x:Static SystemParameters.WindowGlassBrush}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding}" FontSize="16" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<TextBlock x:Name="OpenSettingsTextBlock" Margin="0,30,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static SystemParameters.WindowGlassBrush}" MouseUp="OpenSettingsTextBlock_MouseUp">Open settings folder</TextBlock>
|
||||
<TextBlock x:Name="ShowManualTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static SystemParameters.WindowGlassBrush}" MouseUp="ShowManualTextBlock_MouseUp">Show mpv manual</TextBlock>
|
||||
<TextBlock x:Name="SupportTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static SystemParameters.WindowGlassBrush}" MouseUp="SupportTextBlock_MouseUp">Show support forum</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
214
mpvConfEdit/MainWindow.xaml.cs
Normal file
214
mpvConfEdit/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
using DynamicGUI;
|
||||
|
||||
namespace mpvConfEdit
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
|
||||
private List<SettingBase> DynamicSettings = Settings.LoadSettings(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\mpvConfEdit.toml");
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
Title = (Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0] as AssemblyProductAttribute).Product + " " + Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
||||
|
||||
foreach (var setting in DynamicSettings)
|
||||
{
|
||||
if (!FilterStrings.Contains(setting.Filter))
|
||||
FilterStrings.Add(setting.Filter);
|
||||
foreach (var pair in mpvConf)
|
||||
{
|
||||
if (setting.Name == pair.Key || setting.Alias == pair.Key)
|
||||
switch (setting)
|
||||
{
|
||||
case StringSetting s:
|
||||
s.Value = pair.Value;
|
||||
continue;
|
||||
case OptionSetting s:
|
||||
s.Value = pair.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (setting)
|
||||
{
|
||||
case StringSetting s:
|
||||
MainStackPanel.Children.Add(new StringSettingControl(s));
|
||||
break;
|
||||
case OptionSetting s:
|
||||
MainStackPanel.Children.Add(new OptionSettingControl(s));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> _mpvConf;
|
||||
|
||||
public Dictionary<string, string> mpvConf {
|
||||
get {
|
||||
if (_mpvConf == null)
|
||||
{
|
||||
_mpvConf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(mpvConfPath))
|
||||
foreach (var i in File.ReadAllLines(mpvConfPath))
|
||||
if (i.Contains("=") && !i.Trim().StartsWith("#"))
|
||||
{
|
||||
int pos = i.IndexOf("=");
|
||||
_mpvConf[i.Substring(0, pos).Trim()] = i.Substring(pos + 1).Trim();
|
||||
}
|
||||
}
|
||||
return _mpvConf;
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<string> FilterStrings { get; } = new ObservableCollection<string>();
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
base.OnClosed(e);
|
||||
|
||||
foreach (var mpvSetting in DynamicSettings)
|
||||
{
|
||||
switch (mpvSetting)
|
||||
{
|
||||
case StringSetting s:
|
||||
if ((s.Value ?? "") != s.Default)
|
||||
mpvConf[s.Name] = s.Value;
|
||||
else
|
||||
mpvConf.Remove(s.Name);
|
||||
break;
|
||||
case OptionSetting s:
|
||||
if ((s.Value ?? "") != s.Default)
|
||||
mpvConf[s.Name] = s.Value;
|
||||
else
|
||||
mpvConf.Remove(s.Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!File.Exists(mpvConfPath))
|
||||
File.WriteAllText(mpvConfPath, "");
|
||||
|
||||
List<string> lines = File.ReadAllLines(mpvConfPath).ToList();
|
||||
|
||||
foreach (var mpvSetting in DynamicSettings)
|
||||
{
|
||||
foreach (var line in lines.ToArray())
|
||||
{
|
||||
string test = line.Replace("#", "").Replace(" ", "");
|
||||
if (test.StartsWith(mpvSetting.Alias + "="))
|
||||
{
|
||||
lines.Remove(line);
|
||||
foreach (var pair in mpvConf.ToArray())
|
||||
if (test.StartsWith(pair.Key + "="))
|
||||
mpvConf.Remove(pair.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in mpvConf)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (int i = 0; i < lines.Count; i++)
|
||||
{
|
||||
if (lines[i].Contains("=") &&
|
||||
lines[i].Substring(0, lines[i].IndexOf("=")).Trim("# ".ToCharArray()) == pair.Key)
|
||||
{
|
||||
lines[i] = pair.Key + " = " + pair.Value;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
lines.Add(pair.Key + " = " + pair.Value);
|
||||
}
|
||||
|
||||
foreach (var mpvSetting in DynamicSettings)
|
||||
{
|
||||
foreach (var line in lines.ToArray())
|
||||
{
|
||||
string test = line.Replace("#", "").Replace(" ", "");
|
||||
|
||||
if (test.StartsWith(mpvSetting.Name + "=") && !mpvConf.ContainsKey(mpvSetting.Name))
|
||||
lines.Remove(line);
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(mpvConfPath, String.Join(Environment.NewLine, lines));
|
||||
|
||||
foreach (Process process in Process.GetProcesses())
|
||||
if (process.ProcessName == "mpvnet")
|
||||
MessageBox.Show("Restart mpv.net in order to apply changed settings.", Title, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
else if (process.ProcessName == "mpv")
|
||||
MessageBox.Show("Restart mpv in order to apply changed settings.", Title, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
string activeFilter = "";
|
||||
|
||||
foreach (var i in FilterStrings)
|
||||
if (SearchControl.Text == i + ":")
|
||||
activeFilter = i;
|
||||
|
||||
if (activeFilter == "")
|
||||
{
|
||||
foreach (UIElement i in MainStackPanel.Children)
|
||||
if ((i as ISettingControl).Contains(SearchControl.Text))
|
||||
i.Visibility = Visibility.Visible;
|
||||
else
|
||||
i.Visibility = Visibility.Collapsed;
|
||||
|
||||
FilterListBox.SelectedItem = null;
|
||||
}
|
||||
else
|
||||
foreach (UIElement i in MainStackPanel.Children)
|
||||
if ((i as ISettingControl).SettingBase.Filter == activeFilter)
|
||||
i.Visibility = Visibility.Visible;
|
||||
else
|
||||
i.Visibility = Visibility.Collapsed;
|
||||
|
||||
MainScrollViewer.ScrollToTop();
|
||||
}
|
||||
|
||||
private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Keyboard.Focus(SearchControl.SearchTextBox);
|
||||
}
|
||||
|
||||
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.AddedItems.Count > 0)
|
||||
SearchControl.Text = e.AddedItems[0].ToString() + ":";
|
||||
}
|
||||
|
||||
private void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Process.Start(Path.GetDirectoryName(mpvConfPath));
|
||||
}
|
||||
|
||||
private void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Process.Start("https://mpv.io/manual/master/");
|
||||
}
|
||||
|
||||
private void SupportTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
Process.Start("https://github.com/stax76/mpv.net#Support");
|
||||
}
|
||||
}
|
||||
}
|
||||
55
mpvConfEdit/Properties/AssemblyInfo.cs
Normal file
55
mpvConfEdit/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("mpv(.net) conf edit")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("mpv(.net) conf edit")]
|
||||
[assembly: AssemblyCopyright("Copyright © stax76")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// 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("1.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||
63
mpvConfEdit/Properties/Resources.Designer.cs
generated
Normal file
63
mpvConfEdit/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <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 mpvConfEdit.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()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
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 {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvConfEdit.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
mpvConfEdit/Properties/Resources.resx
Normal file
117
mpvConfEdit/Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
26
mpvConfEdit/Properties/Settings.Designer.cs
generated
Normal file
26
mpvConfEdit/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <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 mpvConfEdit.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
mpvConfEdit/Properties/Settings.settings
Normal file
7
mpvConfEdit/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
13
mpvConfEdit/SearchTextBoxUserControl.xaml
Normal file
13
mpvConfEdit/SearchTextBoxUserControl.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="Controls.SearchTextBoxUserControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="SearchTextBoxUserControl1" Background="White">
|
||||
<TextBlock x:Name="SearchTextBlock" Margin="5,2" Text="Find a setting" Foreground="LightSteelBlue" VerticalAlignment="Center" />
|
||||
<TextBox Name="SearchTextBox" Height="25" Padding="1,2,0,0" BorderThickness="2" Background="Transparent" TextChanged="SearchTextBox_TextChanged" />
|
||||
<Button x:Name="SearchClearButton" Background="Transparent" HorizontalAlignment="Right" Margin="2,0,4,0" FontSize="5" Width="17" Height="17" Visibility="Hidden" Click="SearchClearButton_Click">╳</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
32
mpvConfEdit/SearchTextBoxUserControl.xaml.cs
Normal file
32
mpvConfEdit/SearchTextBoxUserControl.xaml.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Controls
|
||||
{
|
||||
public partial class SearchTextBoxUserControl : UserControl
|
||||
{
|
||||
public SearchTextBoxUserControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string Text { get => SearchTextBox.Text; set => SearchTextBox.Text = value; }
|
||||
|
||||
private void SearchClearButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SearchTextBox.Text = "";
|
||||
Keyboard.Focus(SearchTextBox);
|
||||
}
|
||||
|
||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
SearchTextBlock.Text = SearchTextBox.Text == "" ? "Find a setting" : "";
|
||||
|
||||
if (SearchTextBox.Text == "")
|
||||
SearchClearButton.Visibility = Visibility.Hidden;
|
||||
else
|
||||
SearchClearButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
mpvConfEdit/mpv.ico
Normal file
BIN
mpvConfEdit/mpv.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 264 KiB |
140
mpvConfEdit/mpvConfEdit.csproj
Normal file
140
mpvConfEdit/mpvConfEdit.csproj
Normal file
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C4FEAA45-001D-4DC8-8BFA-621527326D09}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>mpvConfEdit</RootNamespace>
|
||||
<AssemblyName>mpvConfEdit</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<NullableReferenceTypes>true</NullableReferenceTypes>
|
||||
<NullableContextOptions>enable</NullableContextOptions>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>mpv.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="DynamicGUI\DynamicGUI.cs" />
|
||||
<Compile Include="DynamicGUI\OptionSettingControl.xaml.cs">
|
||||
<DependentUpon>OptionSettingControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="DynamicGUI\StringSettingControl.xaml.cs">
|
||||
<DependentUpon>StringSettingControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="DynamicGUI\Tommy.cs" />
|
||||
<Compile Include="SearchTextBoxUserControl.xaml.cs">
|
||||
<DependentUpon>SearchTextBoxUserControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="DynamicGUI\OptionSettingControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="DynamicGUI\StringSettingControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="SearchTextBoxUserControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="mpvConfEdit.toml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="mpv.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
25
mpvConfEdit/mpvConfEdit.sln
Normal file
25
mpvConfEdit/mpvConfEdit.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28714.193
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpvConfEdit", "mpvConfEdit.csproj", "{C4FEAA45-001D-4DC8-8BFA-621527326D09}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {959F2890-E1FC-47A2-856C-A42F8C955D15}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
181
mpvConfEdit/mpvConfEdit.toml
Normal file
181
mpvConfEdit/mpvConfEdit.toml
Normal file
@@ -0,0 +1,181 @@
|
||||
[[settings]]
|
||||
name = "hwdec"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
helpurl = "https://mpv.io/manual/master/#options-hwdec"
|
||||
help = "--hwdec=<mode> 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)" },
|
||||
{ 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)" },
|
||||
{ name = "dxva2", help = "requires --vo=gpu with --gpu-context=d3d11, --gpu-context=angle or --gpu-context=dxinterop (Windows only)" },
|
||||
{ name = "dxva2-copy", help = "copies video back to system RAM (Windows only)" },
|
||||
{ name = "d3d11va", help = "requires --vo=gpu with --gpu-context=d3d11 or --gpu-context=angle (Windows 8+ only)" },
|
||||
{ name = "d3d11va-copy", help = "copies video back to system RAM (Windows 8+ only)" },
|
||||
{ name = "cuda", help = "requires --vo=gpu (Any platform CUDA is available)" },
|
||||
{ name = "cuda-copy", help = "copies video back to system RAM (Any platform CUDA is available)" },
|
||||
{ name = "nvdec", help = "requires --vo=gpu (Any platform CUDA is available)" },
|
||||
{ name = "nvdec-copy", help = "copies video back to system RAM (Any platform CUDA is available)" },
|
||||
{ name = "crystalhd", help = "copies video back to system RAM (Any platform supported by hardware)" },
|
||||
{ name = "rkmpp", help = "requires --vo=gpu (some RockChip devices only)" }]
|
||||
|
||||
[[settings]]
|
||||
name = "vo"
|
||||
default = "gpu"
|
||||
filter = "Video"
|
||||
helpurl = "https://mpv.io/manual/master/#video-output-drivers-vo"
|
||||
help = "--gpu=<mode> 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)" },
|
||||
{ name = "direct3d", help = "Video output driver that uses the Direct3D interface" }]
|
||||
|
||||
[[settings]]
|
||||
name = "volume"
|
||||
default = "100"
|
||||
filter = "Audio"
|
||||
help = "--volume=<integer> Set the startup volume. 0 means silence, 100 means no volume reduction or amplification. Negative values can be passed for compatibility, but are treated as 0. Since mpv 0.18.1, this always controls the internal mixer (aka \"softvol\"). Default: 100"
|
||||
|
||||
[[settings]]
|
||||
name = "slang"
|
||||
default = ""
|
||||
filter = "Subtitle"
|
||||
help = "--slang=<languagecode[,languagecode,...]> Specify a priority list of subtitle languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two letter language codes, Matroska uses ISO 639-2 three letter language codes while OGM uses a free-form identifier. See also --sid."
|
||||
|
||||
[[settings]]
|
||||
name = "screen"
|
||||
default = ""
|
||||
filter = "Screen"
|
||||
help = "--screen=<default|0-32> 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."
|
||||
|
||||
[[settings]]
|
||||
name = "osd-playing-msg"
|
||||
default = ""
|
||||
width = 300
|
||||
filter = "Screen"
|
||||
help = "--osd-playing-msg=<value> Show a message on OSD when playback starts. The string is expanded for properties, e.g. --osd-playing-msg='file: ${filename}' will show the message file: followed by a space and the currently played filename.\n\nFor more information visit:"
|
||||
helpurl = "https://mpv.io/manual/master/#property-expansion"
|
||||
|
||||
[[settings]]
|
||||
name = "fullscreen"
|
||||
alias = "fs"
|
||||
default = "no"
|
||||
filter = "Screen"
|
||||
help = "--fullscreen=<yes|no>, fs=<yes|no> Start the player in fullscreen mode. Default: no."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "keep-open-pause"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "--keep-open-pause=<yes|no> 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."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "keep-open"
|
||||
default = "no"
|
||||
filter = "Playback"
|
||||
help = "--keep-open=<yes|no|always> 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 = "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]]
|
||||
name = "loop-file"
|
||||
alias = "loop"
|
||||
default = ""
|
||||
filter = "Playback"
|
||||
help = "--loop-file=<N|inf|no>, loop=<N|inf|no> Loop a single file N times. inf means forever, no means normal playback. For compatibility, --loop-file and --loop-file=yes are also accepted, and are the same as --loop-file=inf.\n\nThe difference to --loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file.\n\n--loop is an alias for this option."
|
||||
|
||||
[[settings]]
|
||||
name = "save-position-on-quit"
|
||||
default = "no"
|
||||
filter = "Playback"
|
||||
help = "--save-position-on-quit=<yes|no> Always save the current playback position on quit. When this file is played again later, the player will seek to the old playback position on start. This does not happen if playback of a file is stopped in any other way than quitting. For example, going to the next file in the playlist will not save the position, and start playback at beginning the next time the file is played.\n\nThis behavior is disabled by default, but is always available when quitting the player with Shift+Q."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-directory"
|
||||
default = ""
|
||||
width = 500
|
||||
folder = true
|
||||
filter = "Screen"
|
||||
help = "--screenshot-directory=<value> Store screenshots in this directory. This path is joined with the filename generated by --screenshot-template. If the template filename is already absolute, the directory is ignored.\n\nIf the directory does not exist, it is created on the first screenshot. If it is not a directory, an error is generated when trying to write a screenshot.\n\nThis option is not set by default, and thus will write screenshots to the directory from which mpv was started. In pseudo-gui mode (see PSEUDO GUI MODE), this is set to the desktop."
|
||||
|
||||
[[settings]]
|
||||
name = "input-ar-delay"
|
||||
default = ""
|
||||
filter = "Input"
|
||||
help = "--input-ar-delay=<integer> Delay in milliseconds before we start to autorepeat a key (0 to disable)."
|
||||
|
||||
[[settings]]
|
||||
name = "input-ar-rate"
|
||||
default = ""
|
||||
filter = "Input"
|
||||
help = "--input-ar-rate=<integer> Number of key presses to generate per second on autorepeat."
|
||||
|
||||
[[settings]]
|
||||
name = "alang"
|
||||
default = ""
|
||||
filter = "Audio"
|
||||
help = "--alang=<languagecode[,languagecode,...]> Specify a priority list of audio languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two-letter language codes, Matroska, MPEG-TS and NUT use ISO 639-2 three-letter language codes, while OGM uses a free-form identifier. See also --aid.\n\nExamples\n\nmpv dvd://1 --alang=hu,en chooses the Hungarian language track on a DVD and falls back on English if Hungarian is not available.\n\nmpv --alang=jpn example.mkv plays a Matroska file with Japanese audio."
|
||||
|
||||
[[settings]]
|
||||
name = "hr-seek"
|
||||
default = "absolute"
|
||||
filter = "Playback"
|
||||
help = "--hr-seek=<no|absolute|yes> 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 = "always", help = "Same as yes (for compatibility)." }]
|
||||
|
||||
[[settings]]
|
||||
name = "track-auto-selection"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "--track-auto-selection=<yes|no> 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."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "loop-playlist"
|
||||
default = ""
|
||||
filter = "Playback"
|
||||
help = "--loop-playlist=<N|inf|force|no>, --loop-playlist Loops playback N times. A value of 1 plays it one time (default), 2 two times, etc. inf means forever. no is the same as 1 and disables looping. If several files are specified on command line, the entire playlist is looped. --loop-playlist is the same as --loop-playlist=inf.\n\nThe force mode is like inf, but does not skip playlist entries which have been marked as failing. This means the player might waste CPU time trying to loop a file that doesn't exist. But it might be useful for playing webradios under very bad network conditions."
|
||||
|
||||
[[settings]]
|
||||
name = "video-sync"
|
||||
default = "audio"
|
||||
filter = "Video"
|
||||
help = "--video-sync=<audio|...> How the player synchronizes audio and video.\n\nFor more information visit:"
|
||||
helpurl = "https://mpv.io/manual/master/#options-video-sync"
|
||||
options = [{ name = "audio" },
|
||||
{ name = "display-resample" },
|
||||
{ name = "display-resample-vdrop" },
|
||||
{ name = "display-resample-desync" },
|
||||
{ name = "display-vdrop" },
|
||||
{ name = "display-adrop" },
|
||||
{ name = "display-desync" },
|
||||
{ name = "desync" }]
|
||||
|
||||
[[settings]]
|
||||
name = "audio-file-auto"
|
||||
default = "no"
|
||||
filter = "Audio"
|
||||
help = "--audio-file-auto=<no|exact|fuzzy|all>, --no-audio-file-auto 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)." },
|
||||
{ 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." }]
|
||||
|
||||
[[settings]]
|
||||
name = "sub-auto"
|
||||
default = "exact"
|
||||
filter = "Subtitle"
|
||||
help = "--sub-auto=<no|exact|fuzzy|all>, --no-sub-auto 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 = "fuzzy", help = "Load all subs containing media filename." },
|
||||
{ name = "all", help = "Load all subs in the current and --sub-file-paths directories." }]
|
||||
6
mpvInputEdit/App.config
Normal file
6
mpvInputEdit/App.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
||||
42
mpvInputEdit/App.xaml
Normal file
42
mpvInputEdit/App.xaml
Normal file
@@ -0,0 +1,42 @@
|
||||
<Application x:Class="mpvInputEdit.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:mpvInputEdit"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
|
||||
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsFocused" Value="true">
|
||||
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static SystemParameters.WindowGlassBrush}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="DataGrid_Font_Centering"
|
||||
TargetType="{x:Type DataGridCell}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type DataGridCell}">
|
||||
<Grid Background="{TemplateBinding Background}">
|
||||
<ContentPresenter VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
56
mpvInputEdit/App.xaml.cs
Normal file
56
mpvInputEdit/App.xaml.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
|
||||
namespace mpvInputEdit
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
public static string InputConfPath { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
|
||||
|
||||
private static ObservableCollection<InputItem> _InputItems;
|
||||
|
||||
public static ObservableCollection<InputItem> InputItems
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_InputItems is null)
|
||||
{
|
||||
_InputItems = new ObservableCollection<InputItem>();
|
||||
|
||||
if (File.Exists(InputConfPath))
|
||||
{
|
||||
foreach (string line in File.ReadAllLines(InputConfPath))
|
||||
{
|
||||
string l = line.Trim();
|
||||
if (l.StartsWith("#")) continue;
|
||||
if (!l.Contains(" ")) continue;
|
||||
InputItem item = new InputItem();
|
||||
item.Key = l.Substring(0, l.IndexOf(" "));
|
||||
if (item.Key == "") continue;
|
||||
l = l.Substring(l.IndexOf(" ") + 1);
|
||||
|
||||
if (l.Contains("#menu:"))
|
||||
{
|
||||
item.Menu = l.Substring(l.IndexOf("#menu:") + 6).Trim();
|
||||
l = l.Substring(0, l.IndexOf("#menu:"));
|
||||
|
||||
if (item.Menu.Contains(";"))
|
||||
item.Menu = item.Menu.Substring(item.Menu.IndexOf(";") + 1).Trim();
|
||||
}
|
||||
|
||||
item.Command = l.Trim();
|
||||
if (item.Command == "")
|
||||
continue;
|
||||
if (item.Command.ToLower() == "ignore")
|
||||
item.Command = "";
|
||||
_InputItems.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _InputItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
mpvInputEdit/InputWindow.xaml
Normal file
24
mpvInputEdit/InputWindow.xaml
Normal file
@@ -0,0 +1,24 @@
|
||||
<Window x:Class="mpvInputEdit.InputWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Title="Learn Input" Height="200" Width="400" WindowStartupLocation="CenterOwner"
|
||||
ResizeMode="NoResize" Loaded="Window_Loaded" Background="Black" MouseWheel="Window_MouseWheel">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="40" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label x:Name="MenuLabel" Grid.ColumnSpan="2" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16"></Label>
|
||||
<Label x:Name="KeyLabel" Grid.Row="1" Grid.ColumnSpan="2" Foreground="White" VerticalAlignment="Top" HorizontalAlignment="Center" FontSize="16"></Label>
|
||||
<Button x:Name="ConfirmButton" Grid.Row="2" Click="ConfirmButton_Click">Confirm</Button>
|
||||
<Button x:Name="ClearButton" Grid.Row="2" Click="ClearButton_Click" Grid.Column="1">Clear</Button>
|
||||
</Grid>
|
||||
</Window>
|
||||
296
mpvInputEdit/InputWindow.xaml.cs
Normal file
296
mpvInputEdit/InputWindow.xaml.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using WF = System.Windows.Forms;
|
||||
|
||||
namespace mpvInputEdit
|
||||
{
|
||||
public partial class InputWindow : Window
|
||||
{
|
||||
string InputString = "";
|
||||
public InputItem InputItem { get; set; }
|
||||
public string NewKey { get; set; } = "";
|
||||
|
||||
public InputWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
WF.Message m = new WF.Message();
|
||||
m.HWnd = hwnd;
|
||||
m.Msg = msg;
|
||||
m.WParam = wParam;
|
||||
m.LParam = lParam;
|
||||
ProcessKeyEventArgs(ref m);
|
||||
return m.Result;
|
||||
}
|
||||
|
||||
void OnKeyUp(WF.KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == WF.Keys.None) return;
|
||||
char c = Convert.ToChar(e.KeyCode);
|
||||
string text = InputString;
|
||||
|
||||
if (e.KeyCode == WF.Keys.ControlKey || e.KeyCode == WF.Keys.ShiftKey ||
|
||||
e.KeyCode == WF.Keys.Menu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (text == "")
|
||||
{
|
||||
text = e.KeyCode.ToString();
|
||||
if (text.Length == 1)
|
||||
text = text.ToLowerInvariant();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 13; i++)
|
||||
if ("D" + i.ToString() == text)
|
||||
text = text.Substring(1);
|
||||
|
||||
//Debug.WriteLine((int)c);
|
||||
//Debug.WriteLine(e.KeyCode.ToString());
|
||||
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
case WF.Keys.NumPad0:
|
||||
case WF.Keys.NumPad1:
|
||||
case WF.Keys.NumPad2:
|
||||
case WF.Keys.NumPad3:
|
||||
case WF.Keys.NumPad4:
|
||||
case WF.Keys.NumPad5:
|
||||
case WF.Keys.NumPad6:
|
||||
case WF.Keys.NumPad7:
|
||||
case WF.Keys.NumPad8:
|
||||
case WF.Keys.NumPad9:
|
||||
text = "KP" + e.KeyCode.ToString()[6].ToString(); break;
|
||||
case WF.Keys.Space:
|
||||
text = "Space"; break;
|
||||
case WF.Keys.Enter:
|
||||
text = "Enter"; break;
|
||||
case WF.Keys.Tab:
|
||||
text = "Tab"; break;
|
||||
case WF.Keys.Back:
|
||||
text = "BS"; break;
|
||||
case WF.Keys.Delete:
|
||||
text = "Del"; break;
|
||||
case WF.Keys.Insert:
|
||||
text = "Ins"; break;
|
||||
case WF.Keys.Home:
|
||||
text = "Home"; break;
|
||||
case WF.Keys.End:
|
||||
text = "End"; break;
|
||||
case WF.Keys.PageUp:
|
||||
text = "PGUP"; break;
|
||||
case WF.Keys.PageDown:
|
||||
text = "PGDWN"; break;
|
||||
case WF.Keys.Escape:
|
||||
text = "Esc"; break;
|
||||
case WF.Keys.PrintScreen:
|
||||
text = "Print"; break;
|
||||
case WF.Keys.Right:
|
||||
text = "Right"; break;
|
||||
case WF.Keys.Left:
|
||||
text = "Left"; break;
|
||||
case WF.Keys.Up:
|
||||
text = "Up"; break;
|
||||
case WF.Keys.Down:
|
||||
text = "Down"; break;
|
||||
case WF.Keys.Play:
|
||||
text = "Play"; break;
|
||||
case WF.Keys.Pause:
|
||||
text = "Pause"; break;
|
||||
case WF.Keys.MediaPlayPause:
|
||||
text = "PlayPause"; break;
|
||||
case WF.Keys.MediaStop:
|
||||
text = "Stop"; break;
|
||||
case WF.Keys.MediaNextTrack:
|
||||
text = "Next"; break;
|
||||
case WF.Keys.MediaPreviousTrack:
|
||||
text = "Prev"; break;
|
||||
case WF.Keys.VolumeUp:
|
||||
text = "Volume_Up"; break;
|
||||
case WF.Keys.VolumeDown:
|
||||
text = "Volume_Down"; break;
|
||||
case WF.Keys.VolumeMute:
|
||||
text = "Mute"; break;
|
||||
case WF.Keys.BrowserHome:
|
||||
text = "Homepage"; break;
|
||||
case WF.Keys.LaunchMail:
|
||||
text = "Mail"; break;
|
||||
case WF.Keys.BrowserFavorites:
|
||||
text = "Favorites"; break;
|
||||
case WF.Keys.BrowserSearch:
|
||||
text = "Search"; break;
|
||||
case WF.Keys.Sleep:
|
||||
text = "Sleep"; break;
|
||||
case WF.Keys.Cancel:
|
||||
text = "Cancel"; break;
|
||||
}
|
||||
|
||||
if (text == "#")
|
||||
text = "Sharp";
|
||||
|
||||
bool isAlt = GetKeyState(18) < (short)0;
|
||||
bool isShift = GetKeyState(16) < (short)0;
|
||||
bool isCtrl = GetKeyState(17) < (short)0;
|
||||
|
||||
if (!(isAlt && isCtrl && !isShift) && !(isShift && !isAlt && !isCtrl && !int.TryParse(text.Replace("F", ""), out int value)))
|
||||
{
|
||||
if (isAlt) text = "Alt+" + text;
|
||||
if (isShift) text = "Shift+" + text;
|
||||
if (isCtrl) text = "Ctrl+" + text;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
SetKey(text);
|
||||
}
|
||||
|
||||
void SetKey(string key)
|
||||
{
|
||||
NewKey = key;
|
||||
MenuLabel.Content = InputItem.Menu;
|
||||
KeyLabel.Content = key;
|
||||
}
|
||||
|
||||
void OnKeyPress(WF.KeyPressEventArgs e)
|
||||
{
|
||||
if (char.IsControl(e.KeyChar))
|
||||
InputString = "";
|
||||
else
|
||||
InputString = e.KeyChar.ToString();
|
||||
}
|
||||
|
||||
public static WF.Keys ModifierKeys {
|
||||
get {
|
||||
WF.Keys keys = WF.Keys.None;
|
||||
if (GetKeyState(17) < (short)0)
|
||||
keys |= WF.Keys.Control;
|
||||
if (GetKeyState(16) < (short)0)
|
||||
keys |= WF.Keys.Shift;
|
||||
if (GetKeyState(18) < (short)0)
|
||||
keys |= WF.Keys.Alt;
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessKeyEventArgs(ref WF.Message m)
|
||||
{
|
||||
int WM_CHAR = 258, WM_SYSCHAR = 262, /*WM_KEYDOWN = 256, WM_SYSKEYDOWN = 260,*/
|
||||
WM_KEYUP = 0x0101, WM_SYSKEYUP = 0x0105, WM_APPCOMMAND = 0x0319;
|
||||
|
||||
IntPtr newWParam = IntPtr.Zero;
|
||||
WF.KeyEventArgs ke = null;
|
||||
WF.KeyPressEventArgs kpe = null;
|
||||
|
||||
if (m.Msg == WM_CHAR || m.Msg == WM_SYSCHAR)
|
||||
{
|
||||
kpe = new WF.KeyPressEventArgs(unchecked((char)(long)m.WParam));
|
||||
OnKeyPress(kpe);
|
||||
newWParam = (IntPtr)kpe.KeyChar;
|
||||
}
|
||||
else
|
||||
{
|
||||
ke = new WF.KeyEventArgs((WF.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys);
|
||||
|
||||
//if (m.Msg == WM_KEYDOWN || m.Msg == WM_SYSKEYDOWN)
|
||||
// OnKeyDown(ke);
|
||||
|
||||
if (m.Msg == WM_KEYUP || m.Msg == WM_SYSKEYUP)
|
||||
OnKeyUp(ke);
|
||||
|
||||
if (m.Msg == WM_APPCOMMAND)
|
||||
{
|
||||
switch ((AppCommand)m.LParam.ToInt32())
|
||||
{
|
||||
case AppCommand.MEDIA_CHANNEL_DOWN:
|
||||
SetKey("CHANNEL_DOWN");
|
||||
break;
|
||||
case AppCommand.MEDIA_CHANNEL_UP:
|
||||
SetKey("CHANNEL_UP");
|
||||
break;
|
||||
case AppCommand.MEDIA_FAST_FORWARD:
|
||||
SetKey("FORWARD");
|
||||
break;
|
||||
case AppCommand.MEDIA_NEXTTRACK:
|
||||
SetKey("NEXT");
|
||||
break;
|
||||
case AppCommand.MEDIA_PAUSE:
|
||||
SetKey("PAUSE");
|
||||
break;
|
||||
case AppCommand.MEDIA_PLAY:
|
||||
SetKey("PLAY");
|
||||
break;
|
||||
case AppCommand.MEDIA_PLAY_PAUSE:
|
||||
SetKey("PLAYPAUSE");
|
||||
break;
|
||||
case AppCommand.MEDIA_PREVIOUSTRACK:
|
||||
SetKey("PREV");
|
||||
break;
|
||||
case AppCommand.MEDIA_RECORD:
|
||||
SetKey("RECORD");
|
||||
break;
|
||||
case AppCommand.MEDIA_REWIND:
|
||||
SetKey("REWIND");
|
||||
break;
|
||||
case AppCommand.MEDIA_STOP:
|
||||
SetKey("STOP");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kpe != null)
|
||||
m.WParam = newWParam;
|
||||
}
|
||||
|
||||
internal enum AppCommand
|
||||
{
|
||||
MEDIA_CHANNEL_DOWN = 52,
|
||||
MEDIA_CHANNEL_UP = 51,
|
||||
MEDIA_FAST_FORWARD = 49,
|
||||
MEDIA_NEXTTRACK = 11,
|
||||
MEDIA_PAUSE = 47,
|
||||
MEDIA_PLAY = 46,
|
||||
MEDIA_PLAY_PAUSE = 14,
|
||||
MEDIA_PREVIOUSTRACK = 12,
|
||||
MEDIA_RECORD = 48,
|
||||
MEDIA_REWIND = 50,
|
||||
MEDIA_STOP = 13
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern short GetKeyState(int keyCode);
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
||||
source.AddHook(new HwndSourceHook(WndProc));
|
||||
SetKey(InputItem.Key);
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
InputItem.Key = NewKey;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ClearButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
InputItem.Key = "_";
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
if (e.Delta > 0)
|
||||
SetKey("WHEEL_UP");
|
||||
else
|
||||
SetKey("WHEEL_DOWN");
|
||||
}
|
||||
}
|
||||
}
|
||||
30
mpvInputEdit/MainWindow.xaml
Normal file
30
mpvInputEdit/MainWindow.xaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<Window xmlns:Controls="clr-namespace:Controls" x:Class="mpvInputEdit.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="500" Width="750" FontSize="13" Loaded="Window_Loaded" Closed="Window_Closed">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="60" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Controls:SearchTextBoxUserControl x:Name="SearchControl" Width="300" Margin="0,0,0,10" Grid.ColumnSpan="2" />
|
||||
<DataGrid Grid.Row="1" x:Name="DataGrid" AutoGenerateColumns="False" CellStyle="{StaticResource DataGrid_Font_Centering}" CommandManager.PreviewCanExecute="Grid_PreviewCanExecute">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Context Menu" Binding="{Binding Menu}"/>
|
||||
<DataGridTemplateColumn Header="Input">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Button MinHeight="20" Click="ButtonClick">
|
||||
<TextBlock Text="{Binding Key}"></TextBlock>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTextColumn Header="Command" Binding="{Binding Command}" MaxWidth="330" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</Window>
|
||||
119
mpvInputEdit/MainWindow.xaml.cs
Normal file
119
mpvInputEdit/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace mpvInputEdit
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
ICollectionView CollectionView;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Title = (Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0] as AssemblyProductAttribute).Product + " " + Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
||||
DataGrid.SelectionMode = DataGridSelectionMode.Single;
|
||||
CollectionViewSource collectionViewSource = new CollectionViewSource() { Source = App.InputItems };
|
||||
CollectionView = collectionViewSource.View;
|
||||
var yourCostumFilter = new Predicate<object>(item => Filter((InputItem)item));
|
||||
CollectionView.Filter = yourCostumFilter;
|
||||
DataGrid.ItemsSource = CollectionView;
|
||||
}
|
||||
|
||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
CollectionView.Refresh();
|
||||
}
|
||||
|
||||
bool Filter(InputItem item)
|
||||
{
|
||||
string searchText = SearchControl.SearchTextBox.Text.ToLowerInvariant();
|
||||
|
||||
if (searchText == "")
|
||||
return true;
|
||||
|
||||
if (item.Command.ToLower().Contains(searchText) ||
|
||||
item.Menu.ToLower().Contains(searchText) ||
|
||||
item.Key.ToLower().Contains(searchText))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
InputItem item = ((Button)e.Source).DataContext as InputItem;
|
||||
if (item is null) return;
|
||||
InputWindow w = new InputWindow();
|
||||
w.Owner = this;
|
||||
w.InputItem = item;
|
||||
w.ShowDialog();
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Keyboard.Focus(SearchControl.SearchTextBox);
|
||||
}
|
||||
|
||||
private void Grid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
|
||||
{
|
||||
DataGrid grid = (DataGrid)sender;
|
||||
|
||||
if (e.Command == DataGrid.DeleteCommand)
|
||||
{
|
||||
if (MessageBox.Show($"Would you like to delete the selected item?\n\n{(grid.SelectedItem as InputItem).Menu}",
|
||||
"Confirm Delete", MessageBoxButton.OKCancel) != MessageBoxResult.OK)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Closed(object sender, EventArgs e)
|
||||
{
|
||||
if (MessageBox.Show("Would you like to save changes?", "Confirm Save", MessageBoxButton.OKCancel) != MessageBoxResult.OK)
|
||||
return;
|
||||
|
||||
var backupDir = Path.GetDirectoryName(App.InputConfPath) + "\\backup\\";
|
||||
|
||||
if (!Directory.Exists(backupDir))
|
||||
Directory.CreateDirectory(backupDir);
|
||||
|
||||
File.Copy(App.InputConfPath, backupDir + "input conf " + DateTime.Now.ToString("yyyy-MM-dd HH-mm") + ".conf");
|
||||
|
||||
string text = "";
|
||||
|
||||
foreach (InputItem item in App.InputItems)
|
||||
{
|
||||
string line = " " + item.Key.PadRight(14);
|
||||
|
||||
if (item.Command.Trim() == "")
|
||||
line += " ignore";
|
||||
else
|
||||
line += " " + item.Command.Trim();
|
||||
|
||||
if (item.Menu.Trim() != "")
|
||||
line = line.PadRight(40) + " #menu: " + item.Menu;
|
||||
|
||||
text += line + "\r\n";
|
||||
}
|
||||
|
||||
File.WriteAllText(App.InputConfPath, text);
|
||||
|
||||
foreach (Process process in Process.GetProcesses())
|
||||
if (process.ProcessName == "mpvnet")
|
||||
MessageBox.Show("Restart mpv.net in order to apply changed input bindings.", Title, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
else if (process.ProcessName == "mpv")
|
||||
MessageBox.Show("Restart mpv in order to apply changed input bindings.", Title, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
mpvInputEdit/Properties/AssemblyInfo.cs
Normal file
55
mpvInputEdit/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("mpv(.net) input edit")]
|
||||
[assembly: AssemblyDescription("mpv(.net) key bindings editor")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("mpv input edit")]
|
||||
[assembly: AssemblyCopyright("Copyright © stax76")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// 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("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
66
mpvInputEdit/Properties/Resources.Designer.cs
generated
Normal file
66
mpvInputEdit/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <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 mpvInputEdit.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <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", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
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 {
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvInputEdit.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
mpvInputEdit/Properties/Resources.resx
Normal file
117
mpvInputEdit/Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
28
mpvInputEdit/Properties/Settings.Designer.cs
generated
Normal file
28
mpvInputEdit/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <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 mpvInputEdit.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
mpvInputEdit/Properties/Settings.settings
Normal file
7
mpvInputEdit/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
13
mpvInputEdit/SearchTextBoxUserControl.xaml
Normal file
13
mpvInputEdit/SearchTextBoxUserControl.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="Controls.SearchTextBoxUserControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid x:Name="SearchTextBoxUserControl1" Background="White">
|
||||
<TextBlock x:Name="SearchTextBlock" Margin="5,2" Text="Search" Foreground="LightSteelBlue" VerticalAlignment="Center" />
|
||||
<TextBox Name="SearchTextBox" Height="25" Padding="1,2,0,0" BorderThickness="2" Background="Transparent" TextChanged="SearchTextBox_TextChanged" />
|
||||
<Button x:Name="SearchClearButton" Background="Transparent" HorizontalAlignment="Right" Margin="2,0,4,0" FontSize="5" Width="17" Height="17" Visibility="Hidden" Click="SearchClearButton_Click">╳</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
32
mpvInputEdit/SearchTextBoxUserControl.xaml.cs
Normal file
32
mpvInputEdit/SearchTextBoxUserControl.xaml.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Controls
|
||||
{
|
||||
public partial class SearchTextBoxUserControl : UserControl
|
||||
{
|
||||
public SearchTextBoxUserControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string Text { get => SearchTextBox.Text; set => SearchTextBox.Text = value; }
|
||||
|
||||
private void SearchClearButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SearchTextBox.Text = "";
|
||||
Keyboard.Focus(SearchTextBox);
|
||||
}
|
||||
|
||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
SearchTextBlock.Text = SearchTextBox.Text == "" ? "Search" : "";
|
||||
|
||||
if (SearchTextBox.Text == "")
|
||||
SearchClearButton.Visibility = Visibility.Hidden;
|
||||
else
|
||||
SearchClearButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
mpvInputEdit/misc.cs
Normal file
30
mpvInputEdit/misc.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace mpvInputEdit
|
||||
{
|
||||
public class InputItem : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public string Menu { get; set; } = "";
|
||||
public string Command { get; set; } = "";
|
||||
|
||||
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
private string _Key = "";
|
||||
|
||||
public string Key {
|
||||
get {
|
||||
return _Key;
|
||||
}
|
||||
set {
|
||||
_Key = value;
|
||||
NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
mpvInputEdit/mpv.ico
Normal file
BIN
mpvInputEdit/mpv.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 264 KiB |
121
mpvInputEdit/mpvInputEdit.csproj
Normal file
121
mpvInputEdit/mpvInputEdit.csproj
Normal file
@@ -0,0 +1,121 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{635F8308-9F79-4BCC-B839-75FCEF8588AE}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>mpvInputEdit</RootNamespace>
|
||||
<AssemblyName>mpvInputEdit</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>mpv.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="SearchTextBoxUserControl.xaml.cs">
|
||||
<DependentUpon>SearchTextBoxUserControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="InputWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="InputWindow.xaml.cs">
|
||||
<DependentUpon>InputWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="SearchTextBoxUserControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="misc.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="mpv.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
25
mpvInputEdit/mpvInputEdit.sln
Normal file
25
mpvInputEdit/mpvInputEdit.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28721.148
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpvInputEdit", "mpvInputEdit.csproj", "{635F8308-9F79-4BCC-B839-75FCEF8588AE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{635F8308-9F79-4BCC-B839-75FCEF8588AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{635F8308-9F79-4BCC-B839-75FCEF8588AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{635F8308-9F79-4BCC-B839-75FCEF8588AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{635F8308-9F79-4BCC-B839-75FCEF8588AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {492E8273-D465-496D-BA18-DC8CEC9EAD70}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,12 +1,10 @@
|
||||
$scriptDir = Split-Path -Path $PSCommandPath -Parent
|
||||
$exePath = $scriptDir + "\mpv.net\bin\Debug\mpvnet.exe"
|
||||
$exePath = $scriptDir + "\mpv.net\bin\mpvnet.exe"
|
||||
$version = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath).FileVersion
|
||||
$desktopDir = [Environment]::GetFolderPath("Desktop")
|
||||
$targetDir = $desktopDir + "\mpv.net-" + $version
|
||||
if (Test-Path $targetDir) { rd $targetDir -recurse }
|
||||
Copy-Item $scriptDir\mpv.net\bin\Debug $targetDir -recurse
|
||||
$addonDir = $targetDir + "\Addons"
|
||||
Remove-Item $addonDir -Recurse -Include *mpvnet.exe, *mpvnet.exe.config, *mpvnet.pdb
|
||||
Copy-Item $scriptDir\mpv.net\bin $targetDir -Recurse -Exclude System.Management.Automation.xml -Force
|
||||
Copy-Item $scriptDir\README.md $targetDir\README.md -Force
|
||||
$7zPath = "C:\Program Files\7-Zip\7z.exe"
|
||||
$args = "a -t7z -mx9 $targetDir.7z -r $targetDir\*"
|
||||
Start-Process -FilePath $7zPath -ArgumentList $args
|
||||
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB |
BIN
screenshots/mpvInputEdit.png
Normal file
BIN
screenshots/mpvInputEdit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
BIN
screenshots/mpvSettingsEditor.png
Normal file
BIN
screenshots/mpvSettingsEditor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
BIN
screenshots/screenshot.png
Normal file
BIN
screenshots/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
16
scripts/fullscreen.cs
Normal file
16
scripts/fullscreen.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using mpvnet;
|
||||
|
||||
class Script
|
||||
{
|
||||
public Script()
|
||||
{
|
||||
var fs = mp.get_property_string("fullscreen");
|
||||
mp.commandv("show-text", "fullscreen: " + fs);
|
||||
mp.observe_property_bool("fullscreen", FullscreenChange);
|
||||
}
|
||||
|
||||
void FullscreenChange(bool val)
|
||||
{
|
||||
mp.commandv("show-text", "fullscreen: " + val.ToString());
|
||||
}
|
||||
}
|
||||
31
scripts/seek-show-position.js
Normal file
31
scripts/seek-show-position.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// when seeking displays position and
|
||||
// duration like so: 70:00 / 80:00
|
||||
// which is different from mpv which
|
||||
// uses 01:10:00 / 01:20:00
|
||||
|
||||
function add_zero(val)
|
||||
{
|
||||
val = Math.round(val);
|
||||
return val > 9 ? "" + val : "0" + val;
|
||||
}
|
||||
|
||||
function format(val)
|
||||
{
|
||||
var sec = Math.round(val);
|
||||
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
|
||||
pos_min_floor = Math.floor(sec / 60);
|
||||
sec_rest = sec - pos_min_floor * 60;
|
||||
return add_zero(pos_min_floor) + ":" + add_zero(sec_rest);
|
||||
}
|
||||
|
||||
function on_seek(_)
|
||||
{
|
||||
mp.commandv("show-text",
|
||||
format(mp.get_property_number("time-pos")) + " / " +
|
||||
format(mp.get_property_number("duration")));
|
||||
}
|
||||
|
||||
mp.register_event("seek", on_seek);
|
||||
2
scripts/seek.ps1
Normal file
2
scripts/seek.ps1
Normal file
@@ -0,0 +1,2 @@
|
||||
$position = [mp]::get_property_number("time-pos");
|
||||
[mp]::commandv("show-text", $position.ToString() + " seconds")
|
||||
67
wiki/scripting.md
Normal file
67
wiki/scripting.md
Normal file
@@ -0,0 +1,67 @@
|
||||
Here is a list of scripts that users of mpv(.net) have published, adding functionality that is not part of the core mpv(.net) player. Anyone can add their own script by editing this wiki. Scripts are usually placed in C:\Users\user\AppData\Roaming\mpv\scripts
|
||||
|
||||
### C#
|
||||
|
||||
```
|
||||
using mpvnet;
|
||||
|
||||
class Script
|
||||
{
|
||||
public Script()
|
||||
{
|
||||
var fs = mp.get_property_string("fullscreen");
|
||||
mp.commandv("show-text", "fullscreen: " + fs);
|
||||
mp.observe_property_bool("fullscreen", FullscreenChange);
|
||||
}
|
||||
|
||||
void FullscreenChange(bool val)
|
||||
{
|
||||
mp.commandv("show-text", "fullscreen: " + val.ToString());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
```
|
||||
# when seeking displays position and
|
||||
# duration like so: 70:00 / 80:00
|
||||
# which is different from mpv which
|
||||
# uses 01:10:00 / 01:20:00
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def seek():
|
||||
pos = mp.get_property_number("time-pos")
|
||||
dur = mp.get_property_number("duration")
|
||||
|
||||
if pos > dur:
|
||||
pos = dur
|
||||
|
||||
mp.commandv('show-text', format(pos) + " / " + format(dur))
|
||||
|
||||
def format(f):
|
||||
sec = round(f)
|
||||
|
||||
if sec < 0:
|
||||
sec = 0
|
||||
|
||||
pos_min_floor = math.floor(sec / 60)
|
||||
sec_rest = sec - pos_min_floor * 60
|
||||
return add_zero(pos_min_floor) + ":" + add_zero(sec_rest)
|
||||
|
||||
def add_zero(val):
|
||||
val = round(val)
|
||||
return "" + str(int(val)) if (val > 9) else "0" + str(int(val))
|
||||
|
||||
mp.register_event("seek", seek) # or use: mp.Seek += seek
|
||||
```
|
||||
|
||||
### PowerShell
|
||||
|
||||
```
|
||||
$position = [mp]::get_property_number("time-pos");
|
||||
[mp]::commandv("show-text", $position.ToString() + " seconds")
|
||||
```
|
||||
Please note that PowerShell don't allow assigning to events and mpv.net uses as workaround a matching script filename, a list of available events can be found in the mpv manual or in the file mp.cs in the mpv.net source code.
|
||||
Reference in New Issue
Block a user