Compare commits

...

7 Commits
1.0.0.0 ... 1.1

Author SHA1 Message Date
Frank Skare
c075f4982b 1.1 2019-03-14 05:22:39 +01:00
Frank Skare
303355ce63 1.2 2019-03-14 05:19:57 +01:00
Frank Skare
a392c2c6da - 2019-03-13 22:22:51 +01:00
Frank Skare
72d6f44e47 - 2019-03-12 01:21:31 +01:00
Frank Skare
2e695e43bf 1.0.0.0 2019-03-11 22:05:30 +01:00
Frank Skare
207c2fc685 1.0.0.0 2019-03-11 21:59:26 +01:00
Frank Skare
3939dc7924 1.0.0.0 2019-03-11 21:33:37 +01:00
24 changed files with 396 additions and 138 deletions

View File

@@ -11,7 +11,7 @@ Public Class CSScriptAddon
Implements IAddon Implements IAddon
Sub New() Sub New()
Dim scriptDir = mpv.mpvConfFolderPath + "scripts" Dim scriptDir = mp.mpvConfFolderPath + "scripts"
If Not Directory.Exists(scriptDir) Then Return If Not Directory.Exists(scriptDir) Then Return
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs") Dim csFiles = Directory.GetFiles(scriptDir, "*.cs")
If csFiles.Count = 0 Then Return If csFiles.Count = 0 Then Return

View File

@@ -52,11 +52,6 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>.\CSScriptLibrary.dll</HintPath> <HintPath>.\CSScriptLibrary.dll</HintPath>
</Reference> </Reference>
<Reference Include="mpvnet, Version=0.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\mpv.net\bin\Debug\mpvnet.exe</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
@@ -117,5 +112,12 @@
<ItemGroup> <ItemGroup>
<Content Include="CSScriptLibrary.dll" /> <Content Include="CSScriptLibrary.dll" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project> </Project>

View File

@@ -8,11 +8,11 @@ Imports System.Runtime.InteropServices
' Review the values of the assembly attributes ' Review the values of the assembly attributes
<Assembly: AssemblyTitle("PowerShellAddon")> <Assembly: AssemblyTitle("CSScriptAddon")>
<Assembly: AssemblyDescription("")> <Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")> <Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("PowerShellAddon")> <Assembly: AssemblyProduct("CSScriptAddon")>
<Assembly: AssemblyCopyright("Copyright © 2017")> <Assembly: AssemblyCopyright("Copyright © 2019")>
<Assembly: AssemblyTrademark("")> <Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)> <Assembly: ComVisible(False)>

View File

@@ -8,12 +8,12 @@ mpv manual: https://mpv.io/manual/master/
### Features ### Features
- mpv's OSC, IPC, Lua/JS, conf files and more
- Customizable context menu defined in the same file as the keybindings - Customizable context menu defined in the same file as the keybindings
- Addons support for using .NET languages - Addons support for using .NET languages
- C# scripts implemented with CS-Script - C# scripts implemented with CS-Script
- mpv's OSC, IPC, Lua/JS, conf files and more
![](https://github.com/stax76/mpv.net/blob/master/mpv.net/screenshot.jpg) ![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshot.png)
### Context Menu ### Context Menu
@@ -50,6 +50,11 @@ class Script
### Changes ### Changes
### 1.1
- 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
### 1.0 ### 1.0
- much more feature packed context menu - much more feature packed context menu

View File

@@ -14,8 +14,8 @@ namespace RatingAddon
public RatingAddon() public RatingAddon()
{ {
mpv.ClientMessage += mpv_ClientMessage; mp.ClientMessage += mpv_ClientMessage;
mpv.Shutdown += mpv_Shutdown; mp.Shutdown += mpv_Shutdown;
} }
private void mpv_Shutdown() private void mpv_Shutdown()
@@ -51,8 +51,8 @@ namespace RatingAddon
if (args?.Length != 2 || args[0] != "rate-file" || ! int.TryParse(args[1], out rating)) if (args?.Length != 2 || args[0] != "rate-file" || ! int.TryParse(args[1], out rating))
return; return;
Dic[mpv.GetStringProp("path")] = rating; Dic[mp.GetStringProp("path")] = rating;
mpv.Command("show-text", $"Rating: {rating}"); mp.Command("show-text", $"Rating: {rating}");
} }
} }
} }

View File

@@ -67,10 +67,6 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="mpvnet">
<HintPath>..\mpv.net\bin\Debug\mpvnet.exe</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@@ -85,5 +81,12 @@
<Compile Include="RatingAddon.cs" /> <Compile Include="RatingAddon.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@@ -1,31 +0,0 @@
// when seeking displays position and
// duration like so: 00:00 / 120:00
// this is different from MPC which
// uses 00:00:00 / 02:00: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);

View File

@@ -4,10 +4,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 15.0.26730.8 VisualStudioVersion = 15.0.26730.8
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpv.net", "mpv.net\mpv.net.csproj", "{1751F378-8EDF-4B62-BE6D-304C7C287089}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpv.net", "mpv.net\mpv.net.csproj", "{1751F378-8EDF-4B62-BE6D-304C7C287089}"
ProjectSection(ProjectDependencies) = postProject
{55C88710-539D-4402-84C8-31694841C731} = {55C88710-539D-4402-84C8-31694841C731}
{71808A87-8B1C-4DF8-957C-D79C3B164CCA} = {71808A87-8B1C-4DF8-957C-D79C3B164CCA}
EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingAddon", "RatingAddon\RatingAddon.csproj", "{55C88710-539D-4402-84C8-31694841C731}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingAddon", "RatingAddon\RatingAddon.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
EndProject EndProject

View File

@@ -28,7 +28,7 @@ namespace mpvnet
foreach (string i in Directory.GetDirectories(dir)) foreach (string i in Directory.GetDirectories(dir))
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll")); catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
dir = mpv.mpvConfFolderPath + "\\Addons"; dir = mp.mpvConfFolderPath + "\\Addons";
if (Directory.Exists(dir)) if (Directory.Exists(dir))
foreach (string i in Directory.GetDirectories(dir)) foreach (string i in Directory.GetDirectories(dir))

View File

@@ -50,41 +50,41 @@ namespace mpvnet
d.Filter = Misc.GetFilter(Misc.FileTypes); d.Filter = Misc.GetFilter(Misc.FileTypes);
if (d.ShowDialog() == DialogResult.OK) if (d.ShowDialog() == DialogResult.OK)
mpv.LoadFiles(d.FileNames); mp.LoadFiles(d.FileNames);
} }
})); }));
} }
public static void open_config_folder(string[] args) public static void open_config_folder(string[] args)
{ {
Process.Start(mpv.mpvConfFolderPath); Process.Start(mp.mpvConfFolderPath);
} }
public static void show_keys(string[] args) public static void show_keys(string[] args)
{ {
Process.Start(mpv.InputConfPath); Process.Start(mp.InputConfPath);
} }
private static void CreateMpvConf() private static void CreateMpvConf()
{ {
if (!File.Exists(mpv.mpvConfPath)) if (!File.Exists(mp.mpvConfPath))
{ {
if (!Directory.Exists(mpv.mpvConfFolderPath)) if (!Directory.Exists(mp.mpvConfFolderPath))
Directory.CreateDirectory(mpv.mpvConfFolderPath); Directory.CreateDirectory(mp.mpvConfFolderPath);
File.WriteAllText(mpv.mpvConfPath, "# https://mpv.io/manual/master/#configuration-files"); File.WriteAllText(mp.mpvConfPath, "# https://mpv.io/manual/master/#configuration-files");
} }
} }
public static void show_prefs(string[] args) public static void show_prefs(string[] args)
{ {
CreateMpvConf(); CreateMpvConf();
Process.Start(mpv.mpvConfPath); Process.Start(mp.mpvConfPath);
} }
public static void history(string[] args) public static void history(string[] args)
{ {
var fp = mpv.mpvConfFolderPath + "history.txt"; var fp = mp.mpvConfFolderPath + "history.txt";
if (File.Exists(fp)) if (File.Exists(fp))
Process.Start(fp); Process.Start(fp);
@@ -103,7 +103,7 @@ namespace mpvnet
CreateMpvConf(); CreateMpvConf();
bool changed = false; bool changed = false;
string fp = mpv.mpvConfPath; string fp = mp.mpvConfPath;
var confLines = File.ReadAllLines(fp); var confLines = File.ReadAllLines(fp);
for (int i = 0; i < confLines.Length; i++) for (int i = 0; i < confLines.Length; i++)
@@ -130,21 +130,21 @@ namespace mpvnet
public static void show_info(string[] args) public static void show_info(string[] args)
{ {
var fi = new FileInfo(mpv.GetStringProp("path")); var fi = new FileInfo(mp.GetStringProp("path"));
using (var mi = new MediaInfo(fi.FullName)) using (var mi = new MediaInfo(fi.FullName))
{ {
var w = mi.GetInfo(MediaInfoStreamKind.Video, "Width"); var w = mi.GetInfo(MediaInfoStreamKind.Video, "Width");
var h = mi.GetInfo(MediaInfoStreamKind.Video, "Height"); var h = mi.GetInfo(MediaInfoStreamKind.Video, "Height");
var pos = TimeSpan.FromSeconds(mpv.GetIntProp("time-pos")); var pos = TimeSpan.FromSeconds(mp.GetIntProp("time-pos"));
var dur = TimeSpan.FromSeconds(mpv.GetIntProp("duration")); var dur = TimeSpan.FromSeconds(mp.GetIntProp("duration"));
string mibr = mi.GetInfo(MediaInfoStreamKind.Video, "BitRate"); string mibr = mi.GetInfo(MediaInfoStreamKind.Video, "BitRate");
if (mibr == "") if (mibr == "")
mibr = "0"; mibr = "0";
var br = Convert.ToInt32(mibr) / 1000.0 / 1000.0; var br = Convert.ToInt32(mibr) / 1000.0 / 1000.0;
var vf = mpv.GetStringProp("video-format").ToUpper(); var vf = mp.GetStringProp("video-format").ToUpper();
var fn = fi.Name; var fn = fi.Name;
if (fn.Length > 60) if (fn.Length > 60)
@@ -158,7 +158,7 @@ namespace mpvnet
((int)(fi.Length / 1024 / 1024)).ToString() + ((int)(fi.Length / 1024 / 1024)).ToString() +
$" MB - {w} x {h}\n{vf} - {br.ToString("f1")} Mb/s" + "\n" + fn; $" MB - {w} x {h}\n{vf} - {br.ToString("f1")} Mb/s" + "\n" + fn;
mpv.Command("show-text", info, "5000"); mp.Command("show-text", info, "5000");
string FormatTime(double value) => ((int)(Math.Floor(value))).ToString("00"); string FormatTime(double value) => ((int)(Math.Floor(value))).ToString("00");
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -30,7 +30,7 @@ namespace mpvnet
SetFormPosSize(); SetFormPosSize();
Instance = this; Instance = this;
Hwnd = Handle; Hwnd = Handle;
ChangeFullscreen((mpv.mpvConv.ContainsKey("fullscreen") && mpv.mpvConv["fullscreen"] == "yes") || (mpv.mpvConv.ContainsKey("fs") && mpv.mpvConv["fs"] == "yes")); ChangeFullscreen((mp.mpvConv.ContainsKey("fullscreen") && mp.mpvConv["fullscreen"] == "yes") || (mp.mpvConv.ContainsKey("fs") && mp.mpvConv["fs"] == "yes"));
CMS = new ContextMenuStripEx(components); CMS = new ContextMenuStripEx(components);
CMS.Opened += CMS_Opened; CMS.Opened += CMS_Opened;
ContextMenuStrip = CMS; ContextMenuStrip = CMS;
@@ -44,15 +44,15 @@ namespace mpvnet
public void BuildMenu() public void BuildMenu()
{ {
if (!File.Exists(mpv.InputConfPath)) if (!File.Exists(mp.InputConfPath))
{ {
if (!Directory.Exists(mpv.mpvConfFolderPath)) if (!Directory.Exists(mp.mpvConfFolderPath))
Directory.CreateDirectory(mpv.mpvConfFolderPath); Directory.CreateDirectory(mp.mpvConfFolderPath);
File.WriteAllText(mpv.InputConfPath, Properties.Resources.input_conf); File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf);
} }
foreach (var i in File.ReadAllText(mpv.InputConfPath).SplitLinesNoEmpty()) foreach (var i in File.ReadAllText(mp.InputConfPath).SplitLinesNoEmpty())
{ {
if (!i.Contains("#menu:")) if (!i.Contains("#menu:"))
continue; continue;
@@ -73,7 +73,7 @@ namespace mpvnet
var menuItem = CMS.Add(path, () => { var menuItem = CMS.Add(path, () => {
try try
{ {
mpv.CommandString(cmd, false); mp.CommandString(cmd, false);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -95,9 +95,9 @@ namespace mpvnet
private void mpv_PlaybackRestart() private void mpv_PlaybackRestart()
{ {
var fn = mpv.GetStringProp("filename"); var fn = mp.GetStringProp("filename");
BeginInvoke(new Action(() => { Text = fn + " - mpv.net " + Application.ProductVersion; })); BeginInvoke(new Action(() => { Text = fn + " - mpv.net " + Application.ProductVersion; }));
var fp = mpv.mpvConfFolderPath + "history.txt"; var fp = mp.mpvConfFolderPath + "history.txt";
if (LastHistory != fn && File.Exists(fp)) if (LastHistory != fn && File.Exists(fp))
{ {
@@ -166,19 +166,19 @@ namespace mpvnet
case 0x0100: // WM_KEYDOWN case 0x0100: // WM_KEYDOWN
case 0x0101: // WM_KEYUP case 0x0101: // WM_KEYUP
case 0x020A: // WM_MOUSEWHEEL case 0x020A: // WM_MOUSEWHEEL
if (mpv.MpvWindowHandle != IntPtr.Zero) if (mp.MpvWindowHandle != IntPtr.Zero)
Native.SendMessage(mpv.MpvWindowHandle, m.Msg, m.WParam, m.LParam); Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break; break;
case 0x203: // Native.WM.LBUTTONDBLCLK case 0x203: // Native.WM.LBUTTONDBLCLK
if (!IsMouseInOSC()) if (!IsMouseInOSC())
mpv.CommandString("cycle fullscreen"); mp.CommandString("cycle fullscreen");
break; break;
case 0x0214: // WM_SIZING case 0x0214: // WM_SIZING
var rc = Marshal.PtrToStructure<Native.RECT>(m.LParam); var rc = Marshal.PtrToStructure<Native.RECT>(m.LParam);
var r = rc; var r = rc;
NativeHelp.SubtractWindowBorders(Handle, ref r); NativeHelp.SubtractWindowBorders(Handle, ref r);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top; int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
float aspect = mpv.VideoSize.Width / (float)mpv.VideoSize.Height; float aspect = mp.VideoSize.Width / (float)mp.VideoSize.Height;
int d_w = (int)(c_h * aspect - c_w); int d_w = (int)(c_h * aspect - c_w);
int d_h = (int)(c_w / aspect - c_h); int d_h = (int)(c_w / aspect - c_h);
int[] d_corners = { d_w, d_h, -d_w, -d_h }; int[] d_corners = { d_w, d_h, -d_w, -d_h };
@@ -198,10 +198,10 @@ namespace mpvnet
void SetFormPosSize() void SetFormPosSize()
{ {
if (IsFullscreen || mpv.VideoSize.Width == 0) return; if (IsFullscreen || mp.VideoSize.Width == 0) return;
var wa = Screen.GetWorkingArea(this); var wa = Screen.GetWorkingArea(this);
int h = (int)(wa.Height * 0.6); int h = (int)(wa.Height * 0.6);
int w = (int)(h * mpv.VideoSize.Width / (float)mpv.VideoSize.Height); int w = (int)(h * mp.VideoSize.Width / (float)mp.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2); Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var r = new Native.RECT(new Rectangle(0, 0, w, h)); var r = new Native.RECT(new Rectangle(0, 0, w, h));
NativeHelp.AddWindowBorders(Handle, ref r); NativeHelp.AddWindowBorders(Handle, ref r);
@@ -227,7 +227,7 @@ namespace mpvnet
base.OnDragDrop(e); base.OnDragDrop(e);
if (e.Data.GetDataPresent(DataFormats.FileDrop)) if (e.Data.GetDataPresent(DataFormats.FileDrop))
mpv.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[]); mp.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[]);
} }
protected override void OnMouseDown(MouseEventArgs e) protected override void OnMouseDown(MouseEventArgs e)
@@ -249,7 +249,7 @@ namespace mpvnet
var p2 = PointToScreen(e.Location); var p2 = PointToScreen(e.Location);
if (Math.Abs(p1.X - p2.X) < 10 && Math.Abs(p1.Y - p2.Y) < 10) if (Math.Abs(p1.X - p2.X) < 10 && Math.Abs(p1.Y - p2.Y) < 10)
mpv.Command("quit"); mp.Command("quit");
} }
protected override void OnMouseMove(MouseEventArgs e) protected override void OnMouseMove(MouseEventArgs e)
@@ -257,7 +257,7 @@ namespace mpvnet
base.OnMouseMove(e); base.OnMouseMove(e);
// send mouse command to make OSC show // send mouse command to make OSC show
mpv.CommandString($"mouse {e.X} {e.Y}"); mp.CommandString($"mouse {e.X} {e.Y}");
if (CursorHelp.IsPosDifferent(LastCursorPosChanged)) if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
CursorHelp.Show(); CursorHelp.Show();
@@ -267,7 +267,7 @@ namespace mpvnet
{ {
base.OnFormClosed(e); base.OnFormClosed(e);
IsCloseRequired = false; IsCloseRequired = false;
mpv.Command("quit"); mp.Command("quit");
} }
bool IsMouseInOSC() bool IsMouseInOSC()
@@ -292,11 +292,11 @@ namespace mpvnet
private void MainForm_Load(object sender, EventArgs ea) private void MainForm_Load(object sender, EventArgs ea)
{ {
mpv.Init(); mp.Init();
mpv.ObserveBoolProp("fullscreen", MpvChangeFullscreen); mp.ObserveBoolProp("fullscreen", MpvChangeFullscreen);
mpv.AfterShutdown += Mpv_AfterShutdown; mp.Shutdown += Mpv_AfterShutdown;
mpv.VideoSizeChanged += Mpv_VideoSizeChanged; mp.VideoSizeChanged += Mpv_VideoSizeChanged;
mpv.PlaybackRestart += mpv_PlaybackRestart; mp.PlaybackRestart += mpv_PlaybackRestart;
} }
} }
} }

View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.1.0.0")]

33
mpv.net/PyScript.cs Normal file
View File

@@ -0,0 +1,33 @@
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());
}
}
}
}

View File

@@ -113,8 +113,8 @@
L cycle-values loop-file "inf" "no" #menu: Shift+L ; Tools > Toggle Infinite Looping 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 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 Ctrl+H cycle-values hwdec "auto" "no" #menu: Ctrl+H ; Tools > Cycle Hardware Decoding
F8 show_text ${playlist} #menu: F8 ; Tools > Show Playlist F8 show-text ${playlist} 5000 #menu: F8 ; Tools > Show Playlist
F9 show_text ${track-list} #menu: F9 ; Tools > Show Audio/Video/Subtitle List 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://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/mpv-player/mpv/blob/master/etc/input.conf #menu: _ ; Tools > Web > Show mpv default keys

View File

@@ -29,6 +29,9 @@ namespace mpvnet
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [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, ref 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);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref byte[] data); public static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref byte[] data);
@@ -102,7 +105,8 @@ namespace mpvnet
MPV_EVENT_PLAYBACK_RESTART = 21, MPV_EVENT_PLAYBACK_RESTART = 21,
MPV_EVENT_PROPERTY_CHANGE = 22, MPV_EVENT_PROPERTY_CHANGE = 22,
MPV_EVENT_CHAPTER_CHANGE = 23, MPV_EVENT_CHAPTER_CHANGE = 23,
MPV_EVENT_QUEUE_OVERFLOW = 24 MPV_EVENT_QUEUE_OVERFLOW = 24,
MPV_EVENT_HOOK = 25
} }
public enum mpv_format public enum mpv_format
@@ -131,7 +135,16 @@ namespace mpvnet
MPV_LOG_LEVEL_TRACE = 70, MPV_LOG_LEVEL_TRACE = 70,
} }
[StructLayout(LayoutKind.Sequential)] public enum mpv_end_file_reason
{
MPV_END_FILE_REASON_EOF = 0,
MPV_END_FILE_REASON_STOP = 2,
MPV_END_FILE_REASON_QUIT = 3,
MPV_END_FILE_REASON_ERROR = 4,
MPV_END_FILE_REASON_REDIRECT = 5
}
[StructLayout(LayoutKind.Sequential)]
public struct mpv_event_log_message public struct mpv_event_log_message
{ {
public string prefix; public string prefix;
@@ -159,9 +172,16 @@ namespace mpvnet
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct mpv_event_property public struct mpv_event_property
{ {
[MarshalAs(UnmanagedType.LPUTF8Str)] public string name; public string name;
public mpv_format format; public mpv_format format;
public IntPtr data; public IntPtr data;
} }
[StructLayout(LayoutKind.Sequential)]
public struct mpv_event_end_file
{
public int reason;
public int error;
}
} }
} }

View File

@@ -4,34 +4,63 @@ using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms;
using static mpvnet.libmpv; using static mpvnet.libmpv;
using static mpvnet.Native; using static mpvnet.Native;
using static mpvnet.StaticUsing; using static mpvnet.StaticUsing;
using PyRT = IronPython.Runtime;
namespace mpvnet namespace mpvnet
{ {
public delegate void MpvBoolPropChangeHandler(string propName, bool value); public delegate void MpvBoolPropChangeHandler(string propName, bool value);
public class mpv public class mp
{ {
public static event Action<string[]> ClientMessage;
public static event Action Shutdown;
public static event Action AfterShutdown;
public static event Action PlaybackRestart;
public static event Action VideoSizeChanged; public static event Action VideoSizeChanged;
// Lua/JS evens libmpv events
// MPV_EVENT_NONE
public static event Action Shutdown; // shutdown MPV_EVENT_SHUTDOWN
public static event Action LogMessage; // log-message MPV_EVENT_LOG_MESSAGE
public static event Action GetPropertyReply; // get-property-reply MPV_EVENT_GET_PROPERTY_REPLY
public static event Action SetPropertyReply; // set-property-reply MPV_EVENT_SET_PROPERTY_REPLY
public static event Action CommandReply; // command-reply MPV_EVENT_COMMAND_REPLY
public static event Action StartFile; // start-file MPV_EVENT_START_FILE
public static event Action<EndFileEventMode> EndFile; // end-file MPV_EVENT_END_FILE
public static event Action FileLoaded; // file-loaded MPV_EVENT_FILE_LOADED
public static event Action TracksChanged; // MPV_EVENT_TRACKS_CHANGED
public static event Action TrackSwitched; // MPV_EVENT_TRACK_SWITCHED
public static event Action Idle; // idle MPV_EVENT_IDLE
public static event Action Pause; // MPV_EVENT_PAUSE
public static event Action Unpause; // MPV_EVENT_UNPAUSE
public static event Action Tick; // tick MPV_EVENT_TICK
public static event Action ScriptInputDispatch; // MPV_EVENT_SCRIPT_INPUT_DISPATCH
public static event Action<string[]> ClientMessage; // client-message MPV_EVENT_CLIENT_MESSAGE
public static event Action VideoReconfig; // video-reconfig MPV_EVENT_VIDEO_RECONFIG
public static event Action AudioReconfig; // audio-reconfig MPV_EVENT_AUDIO_RECONFIG
public static event Action MetadataUpdate; // MPV_EVENT_METADATA_UPDATE
public static event Action Seek; // seek MPV_EVENT_SEEK
public static event Action PlaybackRestart; // playback-restart MPV_EVENT_PLAYBACK_RESTART
// MPV_EVENT_PROPERTY_CHANGE
public static event Action ChapterChange; // MPV_EVENT_CHAPTER_CHANGE
public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW
public static event Action Hook; // MPV_EVENT_HOOK
public static IntPtr MpvHandle; public static IntPtr MpvHandle;
public static IntPtr MpvWindowHandle; public static IntPtr MpvWindowHandle;
public static Addon Addon; public static Addon Addon;
public static List<Action<bool>> BoolPropChangeActions = new List<Action<bool>>(); public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions = new List<KeyValuePair<string, Action<bool>>>();
public static Size VideoSize = new Size(1920, 1080); public static Size VideoSize = new Size(1920, 1080);
public static string mpvConfFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\"; 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 InputConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
public static string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf"; public static string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
public static List<PyScript> PyScripts { get; } = new List<PyScript>();
private static Dictionary<string, string> _mpvConv; private static Dictionary<string, string> _mpvConv;
@@ -76,17 +105,35 @@ namespace mpvnet
SetStringProp("force-window", "yes"); SetStringProp("force-window", "yes");
mpv_initialize(MpvHandle); mpv_initialize(MpvHandle);
ProcessCommandLine(); ProcessCommandLine();
Task.Run(() => { LoadScripts(); });
Task.Run(() => { Addon = new Addon(); }); Task.Run(() => { Addon = new Addon(); });
Task.Run(() => { EventLoop(); }); Task.Run(() => { EventLoop(); });
} }
public static void LoadScripts()
{
string[] jsLua = { ".lua", ".js" };
string[] startupScripts = Directory.GetFiles(Application.StartupPath + "\\Scripts");
foreach (var scriptPath in startupScripts)
if (jsLua.Contains(Path.GetExtension(scriptPath).ToLower()))
mp.Command("load-script", $"{scriptPath}");
foreach (var scriptPath in startupScripts)
if (Path.GetExtension(scriptPath) == ".py")
PyScripts.Add(new PyScript(File.ReadAllText(scriptPath)));
foreach(var scriptPath in Directory.GetFiles(mp.mpvConfFolderPath + "scripts", "*.py"))
PyScripts.Add(new PyScript(File.ReadAllText(scriptPath)));
}
public static void EventLoop() public static void EventLoop()
{ {
while (true) while (true)
{ {
IntPtr ptr = mpv_wait_event(MpvHandle, -1); IntPtr ptr = mpv_wait_event(MpvHandle, -1);
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event)); mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event));
Debug.WriteLine(evt.event_id); //Debug.WriteLine(evt.event_id);
if (MpvWindowHandle == IntPtr.Zero) if (MpvWindowHandle == IntPtr.Zero)
MpvWindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null); MpvWindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
@@ -95,22 +142,50 @@ namespace mpvnet
{ {
case mpv_event_id.MPV_EVENT_SHUTDOWN: case mpv_event_id.MPV_EVENT_SHUTDOWN:
Shutdown?.Invoke(); Shutdown?.Invoke();
AfterShutdown?.Invoke();
return; return;
case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
LogMessage?.Invoke();
break;
case mpv_event_id.MPV_EVENT_GET_PROPERTY_REPLY:
GetPropertyReply?.Invoke();
break;
case mpv_event_id.MPV_EVENT_SET_PROPERTY_REPLY:
SetPropertyReply?.Invoke();
break;
case mpv_event_id.MPV_EVENT_COMMAND_REPLY:
CommandReply?.Invoke();
break;
case mpv_event_id.MPV_EVENT_START_FILE:
StartFile?.Invoke();
break;
case mpv_event_id.MPV_EVENT_END_FILE:
var end_fileData = (mpv_event_end_file)Marshal.PtrToStructure(evt.data, typeof(mpv_event_end_file));
EndFile?.Invoke((EndFileEventMode)end_fileData.reason);
break;
case mpv_event_id.MPV_EVENT_FILE_LOADED: case mpv_event_id.MPV_EVENT_FILE_LOADED:
FileLoaded?.Invoke();
LoadFolder(); LoadFolder();
break; break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART: case mpv_event_id.MPV_EVENT_TRACKS_CHANGED:
PlaybackRestart?.Invoke(); TracksChanged?.Invoke();
break;
Size s = new Size(GetIntProp("dwidth", false), GetIntProp("dheight", false)); case mpv_event_id.MPV_EVENT_TRACK_SWITCHED:
TrackSwitched?.Invoke();
if (VideoSize != s && s != Size.Empty) break;
{ case mpv_event_id.MPV_EVENT_IDLE:
VideoSize = s; Idle?.Invoke();
VideoSizeChanged?.Invoke(); break;
} case mpv_event_id.MPV_EVENT_PAUSE:
Pause?.Invoke();
break;
case mpv_event_id.MPV_EVENT_UNPAUSE:
Unpause?.Invoke();
break;
case mpv_event_id.MPV_EVENT_TICK:
Tick?.Invoke();
break;
case mpv_event_id.MPV_EVENT_SCRIPT_INPUT_DISPATCH:
ScriptInputDispatch?.Invoke();
break; break;
case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE: case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE:
if (ClientMessage != null) if (ClientMessage != null)
@@ -129,22 +204,122 @@ namespace mpvnet
{ {
MsgError(ex.GetType().Name + "\r\n\r\n" + ex.ToString()); MsgError(ex.GetType().Name + "\r\n\r\n" + ex.ToString());
} }
ClientMessage?.Invoke(args); ClientMessage?.Invoke(args);
} }
break;
case mpv_event_id.MPV_EVENT_VIDEO_RECONFIG:
VideoReconfig?.Invoke();
break;
case mpv_event_id.MPV_EVENT_AUDIO_RECONFIG:
AudioReconfig?.Invoke();
break;
case mpv_event_id.MPV_EVENT_METADATA_UPDATE:
MetadataUpdate?.Invoke();
break;
case mpv_event_id.MPV_EVENT_SEEK:
Seek?.Invoke();
break; break;
case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE: case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE:
var eventData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property)); var event_propertyData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property));
if (eventData.format == mpv_format.MPV_FORMAT_FLAG) if (event_propertyData.format == mpv_format.MPV_FORMAT_FLAG)
foreach (var action in BoolPropChangeActions) foreach (var i in BoolPropChangeActions)
action.Invoke(Marshal.PtrToStructure<int>(eventData.data) == 1); if (i.Key== event_propertyData.name)
i.Value.Invoke(Marshal.PtrToStructure<int>(event_propertyData.data) == 1);
break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke();
Size s = new Size(GetIntProp("dwidth", false), GetIntProp("dheight", false));
if (VideoSize != s && s != Size.Empty)
{
VideoSize = s;
VideoSizeChanged?.Invoke();
}
break;
case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE:
ChapterChange?.Invoke();
break;
case mpv_event_id.MPV_EVENT_QUEUE_OVERFLOW:
QueueOverflow?.Invoke();
break;
case mpv_event_id.MPV_EVENT_HOOK:
Hook?.Invoke();
break; break;
} }
} }
} }
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>();
public static void register_event(string name, PyRT.PythonFunction pyFunc)
{
foreach (var eventInfo in typeof(mp).GetEvents())
{
if (eventInfo.Name.ToLower() == name.Replace("-", ""))
{
EventObject eventObject = new EventObject();
EventObjects.Add(eventObject);
eventObject.PythonFunction = pyFunc;
MethodInfo mi;
if (eventInfo.EventHandlerType == typeof(Action))
{
mi = eventObject.GetType().GetMethod(nameof(EventObject.Invoke));
}
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
{
mi = eventObject.GetType().GetMethod(nameof(EventObject.InvokeEndFileEventMode));
}
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
{
mi = eventObject.GetType().GetMethod(nameof(EventObject.InvokeStrings));
}
else
throw new Exception();
eventObject.EventInfo = eventInfo;
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
eventObject.Delegate = handler;
eventInfo.AddEventHandler(eventObject, handler);
}
}
}
public static void unregister_event(PyRT.PythonFunction pyFunc)
{
foreach (var eventObjects in EventObjects)
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) public static void Command(params string[] args)
{ {
if (MpvHandle == IntPtr.Zero) if (MpvHandle == IntPtr.Zero)
@@ -208,6 +383,22 @@ namespace mpvnet
return lpBuffer.ToInt32(); return lpBuffer.ToInt32();
} }
public static double get_property_number(string name)
{
return GetDoubleProp(name);
}
public static double GetDoubleProp(string name, bool throwException = true)
{
double val = 0;
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
if (err < 0 && throwException)
throw new Exception($"{name}: {(mpv_error)err}");
else
return val;
}
public static void SetIntProp(string name, int value) public static void SetIntProp(string name, int value)
{ {
Int64 val = value; Int64 val = value;
@@ -219,16 +410,20 @@ namespace mpvnet
public static void ObserveBoolProp(string name, Action<bool> action) public static void ObserveBoolProp(string name, Action<bool> action)
{ {
BoolPropChangeActions.Add(action);
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG); int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
if (err < 0) if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}"); throw new Exception($"{name}: {(mpv_error)err}");
else
BoolPropChangeActions.Add(new KeyValuePair<string, Action<bool>>(name, action));
} }
public static void UnobserveBoolProp(string name, Action<bool> action) public static void UnobserveBoolProp(string name, Action<bool> action)
{ {
BoolPropChangeActions.Remove(action); foreach (var i in BoolPropChangeActions.ToArray())
if (i.Value == action)
BoolPropChangeActions.Remove(i);
int err = mpv_unobserve_property(MpvHandle, (ulong)action.GetHashCode()); int err = mpv_unobserve_property(MpvHandle, (ulong)action.GetHashCode());
if (err < 0) if (err < 0)
@@ -241,9 +436,9 @@ namespace mpvnet
foreach (string i in args) foreach (string i in args)
if (!i.StartsWith("--") && File.Exists(i)) if (!i.StartsWith("--") && File.Exists(i))
mpv.Command("loadfile", i, "append"); mp.Command("loadfile", i, "append");
mpv.SetStringProp("playlist-pos", "0", false); mp.SetStringProp("playlist-pos", "0", false);
foreach (string i in args) foreach (string i in args)
{ {
@@ -253,27 +448,27 @@ namespace mpvnet
{ {
string left = i.Substring(2, i.IndexOf("=") - 2); string left = i.Substring(2, i.IndexOf("=") - 2);
string right = i.Substring(left.Length + 3); string right = i.Substring(left.Length + 3);
mpv.SetStringProp(left, right); mp.SetStringProp(left, right);
} }
else else
mpv.SetStringProp(i.Substring(2), "yes"); mp.SetStringProp(i.Substring(2), "yes");
} }
} }
} }
public static void LoadFiles(string[] files) public static void LoadFiles(string[] files)
{ {
int count = mpv.GetIntProp("playlist-count"); int count = mp.GetIntProp("playlist-count");
foreach (string file in files) foreach (string file in files)
mpv.Command("loadfile", file, "append"); mp.Command("loadfile", file, "append");
mpv.SetIntProp("playlist-pos", count); mp.SetIntProp("playlist-pos", count);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
mpv.Command("playlist-remove", "0"); mp.Command("playlist-remove", "0");
mpv.LoadFolder(); mp.LoadFolder();
} }
private static bool WasFolderLoaded; private static bool WasFolderLoaded;
@@ -344,4 +539,14 @@ namespace mpvnet
public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0"); public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
} }
public enum EndFileEventMode
{
Eof,
Stop,
Quit,
Error,
Redirect,
Unknown
}
} }

View File

@@ -94,6 +94,29 @@
<ApplicationManifest>app.manifest</ApplicationManifest> <ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="IKVM.Reflection, Version=7.2.4630.5, Culture=neutral, PublicKeyToken=13235d27fcbfff58, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\IKVM.Reflection.dll</HintPath>
</Reference>
<Reference Include="IronPython, Version=2.7.9.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\IronPython.dll</HintPath>
</Reference>
<Reference Include="IronPython.Modules, Version=2.7.9.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\IronPython.Modules.dll</HintPath>
</Reference>
<Reference Include="IronPythonAddon">
<HintPath>IronPython\IronPythonAddon.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Dynamic, Version=1.2.2.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\Microsoft.Dynamic.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Scripting, Version=1.2.2.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\Microsoft.Scripting.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@@ -109,6 +132,7 @@
<Compile Include="Menu.cs"> <Compile Include="Menu.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="PyScript.cs" />
<Compile Include="StringExtensions.cs" /> <Compile Include="StringExtensions.cs" />
<Compile Include="libmpv.cs" /> <Compile Include="libmpv.cs" />
<Compile Include="MainForm.cs"> <Compile Include="MainForm.cs">
@@ -118,7 +142,7 @@
<DependentUpon>MainForm.cs</DependentUpon> <DependentUpon>MainForm.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Misc.cs" /> <Compile Include="Misc.cs" />
<Compile Include="mpv.cs" /> <Compile Include="mp.cs" />
<Compile Include="Command.cs" /> <Compile Include="Command.cs" />
<Compile Include="Native.cs" /> <Compile Include="Native.cs" />
<Compile Include="NativeHelp.cs" /> <Compile Include="NativeHelp.cs" />
@@ -127,6 +151,7 @@
<Compile Include="UI.cs" /> <Compile Include="UI.cs" />
<EmbeddedResource Include="MainForm.resx"> <EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon> <DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB