5.4.5.1 Beta

This commit is contained in:
Frank Skare
2020-05-03 11:10:56 +02:00
parent e1bd44cd00
commit 28045ad33e
46 changed files with 1090 additions and 829 deletions

View File

@@ -1,8 +1,26 @@
5.4.4.7 Beta (not yet released)
5.4.5.2 Beta (not yet released)
============
-
5.4.5.1 Beta
============
- extensions no longer need to end with *Extension.dll but rather
the file name and the directory name must be identical
- text encoding exception fix
- the PowerShell script host is more feature complete, easier to use
and more efficient, there were however many PowerShell and C# breaking
changes requrired to make the core more robust and efficient
- Python 2 script host removed, Python 3 support is planned for summer
5.4.5.0
=======
stable release, no changes since the last beta
5.4.4.6 Beta

View File

@@ -341,7 +341,7 @@ The PowerShell scripting host is like extensions not initialized before media fi
mpv.net does not define scripting interfaces but instead exposed its complete internals, there are no compatibility guaranties.
[Example Scripts](scripts/examples)
[Example Scripts](scripts)
#### C#
@@ -358,16 +358,16 @@ Script code can be written within a C# [extension](#extensions), that way full c
The C# scripting host is like [extensions](#extensions) not initialized before media files are loaded.
[Example Scripts](scripts/examples)
[Example Scripts](scripts)
Extensions
----------
Extensions are located in the config folder and the filename must end with 'Extension.dll':
Extensions are located in a subfolder _extensions_ in the config folder and the filename must have the same name as the directory:
```Text
<config folder>\Extensions\ExampleExtension\ExampleExtension.dll
<config folder>\extensions\ExampleExtension\ExampleExtension.dll
```
mpv.net does not define extension interfaces but instead exposed its complete internals, there are no compatibility guaranties.

View File

@@ -7,7 +7,6 @@ $include = @(
'*.iss',
'*.js',
'*.lua',
'*.md',
'*.ps1',
'*.resx',
'*.sln',

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.IO;
using mpvnet;
using static mpvnet.Core;
namespace RatingExtension // the assembly name must end with 'Extension'
{
@@ -19,8 +20,8 @@ namespace RatingExtension // the assembly name must end with 'Extension'
public RatingExtension() // plugin initialization
{
mp.ClientMessage += ClientMessage; //handles keys defined in input.conf
mp.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN
core.ClientMessage += ClientMessage; //handles keys defined in input.conf
core.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN
}
// handles MPV_EVENT_SHUTDOWN
@@ -53,10 +54,10 @@ namespace RatingExtension // the assembly name must end with 'Extension'
if (int.TryParse(args[1], out int rating))
{
string path = mp.get_property_string("path");
string path = core.get_property_string("path");
if (!File.Exists(path)) return;
Dic[path] = rating;
mp.commandv("show-text", $"Rating: {rating}");
core.commandv("show-text", $"Rating: {rating}");
}
else if (args[1] == "about")
Msg.Show("Rating Extension", "This extension writes a rating to the filename of rated videos when mpv.net shuts down.\n\nThe input.conf defaults contain key bindings for this extension to set ratings.");

View File

@@ -13,6 +13,7 @@ using System.IO;
using mpvnet;
using CSScriptLibrary;
using static mpvnet.Core;
// the file name of extensions must end with 'Extension'
namespace ScriptingExtension
@@ -27,8 +28,8 @@ namespace ScriptingExtension
//Script = new Script();
List<string> files = new List<string>();
if (Directory.Exists(mp.ConfigFolder + "scripts-cs"))
files.AddRange(Directory.GetFiles(mp.ConfigFolder + "scripts-cs", "*.cs"));
if (Directory.Exists(core.ConfigFolder + "scripts-cs"))
files.AddRange(Directory.GetFiles(core.ConfigFolder + "scripts-cs", "*.cs"));
if (Directory.Exists(Folder.Startup + "scripts"))
foreach (string path in Directory.GetFiles(Folder.Startup + "scripts", "*.cs"))

View File

@@ -2,12 +2,13 @@
using System.IO;
using mpvnet;
using static mpvnet.Core;
class Script
{
public Script()
{
mp.Shutdown += Shutdown;
core.Shutdown += Shutdown;
}
void Shutdown()

Binary file not shown.

View File

@@ -8,6 +8,7 @@ using System.Windows.Forms;
using UI;
using static libmpv;
using static mpvnet.Core;
using System.Threading.Tasks;
@@ -21,7 +22,7 @@ namespace mpvnet
public static string[] SubtitleTypes { get; } = { "srt", "ass", "idx", "sup", "ttxt", "ssa", "smi" };
public static string RegPath { get; } = @"HKCU\Software\" + Application.ProductName;
public static string ConfPath { get => mp.ConfigFolder + "mpvnet.conf"; }
public static string ConfPath { get => core.ConfigFolder + "mpvnet.conf"; }
public static string ProcessInstance { get; set; } = "single";
public static string DarkMode { get; set; } = "always";
public static string DarkTheme { get; set; } = "dark";
@@ -49,8 +50,8 @@ namespace mpvnet
public static void Init()
{
string dummy = mp.ConfigFolder;
var dummy2 = mp.Conf;
string dummy = core.ConfigFolder;
var dummy2 = core.Conf;
foreach (var i in Conf)
ProcessProperty(i.Key, i.Value, true);
@@ -59,7 +60,7 @@ namespace mpvnet
{
try
{
string filePath = mp.ConfigFolder + "mpvnet-debug.log";
string filePath = core.ConfigFolder + "mpvnet-debug.log";
if (File.Exists(filePath))
File.Delete(filePath);
@@ -78,17 +79,17 @@ namespace mpvnet
string themeContent = null;
if (File.Exists(mp.ConfigFolder + "theme.conf"))
themeContent = File.ReadAllText(mp.ConfigFolder + "theme.conf");
if (File.Exists(core.ConfigFolder + "theme.conf"))
themeContent = File.ReadAllText(core.ConfigFolder + "theme.conf");
Theme.Init(
themeContent,
Properties.Resources.theme,
IsDarkMode ? DarkTheme : LightTheme);
mp.Shutdown += Shutdown;
mp.Initialized += Initialized;
mp.LogMessage += ShowFatalError;
core.Shutdown += Shutdown;
core.Initialized += Initialized;
core.LogMessage += ShowFatalError;
}
static void ShowFatalError(mpv_log_level level, string msg)
@@ -103,6 +104,7 @@ namespace mpvnet
try
{
action.Invoke();
Debug.WriteLine(Environment.TickCount);
}
catch (Exception e)
{
@@ -116,25 +118,36 @@ namespace mpvnet
if (obj is Exception e)
{
if (App.IsStartedFromTerminal)
ConsoleHelp.WriteError(e.ToString(), "mpv.net");
ConsoleHelp.WriteError(e.ToString());
else
Msg.ShowException(e);
}
else
{
if (App.IsStartedFromTerminal)
ConsoleHelp.WriteError(obj.ToString(), "mpv.net");
ConsoleHelp.WriteError(obj.ToString());
else
Msg.ShowError(obj.ToString());
}
}
public static void ShowError(string title, string msg)
{
if (App.IsStartedFromTerminal)
{
ConsoleHelp.WriteError(title);
ConsoleHelp.WriteError(msg);
}
else
Msg.ShowError(title, msg);
}
static void Initialized()
{
if (RememberVolume)
{
mp.set_property_int("volume", RegistryHelp.GetInt(App.RegPath, "Volume", 70));
mp.set_property_string("mute", RegistryHelp.GetString(App.RegPath, "Mute", "no"));
core.set_property_int("volume", RegistryHelp.GetInt(App.RegPath, "Volume", 70));
core.set_property_string("mute", RegistryHelp.GetString(App.RegPath, "Mute", "no"));
}
}
@@ -142,8 +155,8 @@ namespace mpvnet
{
if (RememberVolume)
{
RegistryHelp.SetValue(App.RegPath, "Volume", mp.get_property_int("volume"));
RegistryHelp.SetValue(App.RegPath, "Mute", mp.get_property_string("mute"));
RegistryHelp.SetValue(App.RegPath, "Volume", core.get_property_int("volume"));
RegistryHelp.SetValue(App.RegPath, "Mute", core.get_property_string("mute"));
}
}
@@ -184,7 +197,7 @@ namespace mpvnet
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
default:
if (writeError)
ConsoleHelp.WriteError($"unknown mpvnet.conf property: {name}", "mpv.net");
ConsoleHelp.WriteError($"unknown mpvnet.conf property: {name}");
return false;
}
}

View File

@@ -8,13 +8,13 @@ using System.Windows.Forms;
using System.Windows.Interop;
using VB = Microsoft.VisualBasic;
using ScriptHost;
using static NewLine;
using static mpvnet.Core;
namespace mpvnet
{
public class Command
public class Commands
{
public static void Execute(string id, string[] args)
{
@@ -36,7 +36,7 @@ namespace mpvnet
case "show-about": ShowDialog(typeof(AboutWindow)); break;
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
case "show-input-editor": ShowDialog(typeof(InputWindow)); break;
case "open-conf-folder": Process.Start(mp.ConfigFolder); break;
case "open-conf-folder": Process.Start(core.ConfigFolder); break;
case "shell-execute": Process.Start(args[0]); break;
case "show-info": ShowInfo(); break;
case "playlist-first": PlaylistFirst(); break;
@@ -49,7 +49,7 @@ namespace mpvnet
}
}
public static void InvokeOnMainThread(Action action) => MainForm.Instance.Invoke(action);
public static void InvokeOnMainThread(Action action) => MainForm.Instance.BeginInvoke(action);
public static void ShowDialog(Type winType)
{
@@ -74,7 +74,7 @@ namespace mpvnet
InvokeOnMainThread(new Action(() => {
using (var d = new OpenFileDialog() { Multiselect = true })
if (d.ShowDialog() == DialogResult.OK)
mp.LoadFiles(d.FileNames, loadFolder, append);
core.LoadFiles(d.FileNames, loadFolder, append);
}));
}
@@ -90,13 +90,13 @@ namespace mpvnet
{
if (Directory.Exists(d.SelectedPath + "\\BDMV"))
{
mp.set_property_string("bluray-device", d.SelectedPath);
mp.LoadFiles(new[] { @"bd://" }, false, false);
core.set_property_string("bluray-device", d.SelectedPath);
core.LoadFiles(new[] { @"bd://" }, false, false);
}
else
{
mp.set_property_string("dvd-device", d.SelectedPath);
mp.LoadFiles(new[] { @"dvd://" }, false, false);
core.set_property_string("dvd-device", d.SelectedPath);
core.LoadFiles(new[] { @"dvd://" }, false, false);
}
}
}
@@ -105,31 +105,31 @@ namespace mpvnet
public static void PlaylistFirst()
{
int pos = mp.get_property_int("playlist-pos");
int pos = core.get_property_int("playlist-pos");
if (pos != 0)
mp.set_property_int("playlist-pos", 0);
core.set_property_int("playlist-pos", 0);
}
public static void PlaylistLast()
{
int pos = mp.get_property_int("playlist-pos");
int count = mp.get_property_int("playlist-count");
int pos = core.get_property_int("playlist-pos");
int count = core.get_property_int("playlist-count");
if (pos < count - 1)
mp.set_property_int("playlist-pos", count - 1);
core.set_property_int("playlist-pos", count - 1);
}
public static void ShowHistory()
{
if (File.Exists(mp.ConfigFolder + "history.txt"))
Process.Start(mp.ConfigFolder + "history.txt");
if (File.Exists(core.ConfigFolder + "history.txt"))
Process.Start(core.ConfigFolder + "history.txt");
else
{
if (Msg.ShowQuestion("Create history.txt file in config folder?",
"mpv.net will write the date, time and filename of opened files to it.") == MsgResult.OK)
File.WriteAllText(mp.ConfigFolder + "history.txt", "");
File.WriteAllText(core.ConfigFolder + "history.txt", "");
}
}
@@ -139,13 +139,13 @@ namespace mpvnet
{
string performer, title, album, genre, date, duration, text = "";
long fileSize = 0;
string path = mp.get_property_string("path");
string path = core.get_property_string("path");
if (path.Contains("://"))
path = mp.get_property_string("media-title");
path = core.get_property_string("media-title");
int width = mp.get_property_int("video-params/w");
int height = mp.get_property_int("video-params/h");
int width = core.get_property_int("video-params/w");
int height = core.get_property_int("video-params/h");
if (File.Exists(path))
{
@@ -171,7 +171,7 @@ namespace mpvnet
text += "Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n";
text += "Type: " + path.ShortExt().ToUpper();
mp.commandv("show-text", text, "5000");
core.commandv("show-text", text, "5000");
return;
}
}
@@ -185,16 +185,16 @@ namespace mpvnet
"Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n" +
"Type: " + path.ShortExt().ToUpper();
mp.commandv("show-text", text, "5000");
core.commandv("show-text", text, "5000");
return;
}
}
}
TimeSpan position = TimeSpan.FromSeconds(mp.get_property_number("time-pos"));
TimeSpan duration2 = TimeSpan.FromSeconds(mp.get_property_number("duration"));
string videoFormat = mp.get_property_string("video-format").ToUpper();
string audioCodec = mp.get_property_string("audio-codec-name").ToUpper();
TimeSpan position = TimeSpan.FromSeconds(core.get_property_number("time-pos"));
TimeSpan duration2 = TimeSpan.FromSeconds(core.get_property_number("duration"));
string videoFormat = core.get_property_string("video-format").ToUpper();
string audioCodec = core.get_property_string("audio-codec-name").ToUpper();
text = path.FileName() + "\n" +
FormatTime(position.TotalMinutes) + ":" +
@@ -208,12 +208,12 @@ namespace mpvnet
text += $"{videoFormat}\n{audioCodec}";
mp.commandv("show-text", text, "5000");
core.commandv("show-text", text, "5000");
string FormatTime(double value) => ((int)value).ToString("00");
}
catch (Exception e)
{
Msg.ShowException(e);
App.ShowException(e);
}
}
@@ -221,9 +221,12 @@ namespace mpvnet
{
InvokeOnMainThread(new Action(() => {
string command = VB.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegistryHelp.GetString(App.RegPath, "RecentExecutedCommand"));
if (string.IsNullOrEmpty(command)) return;
if (string.IsNullOrEmpty(command))
return;
RegistryHelp.SetValue(App.RegPath, "RecentExecutedCommand", command);
mp.command(command, false);
core.command(command, false);
}));
}
@@ -231,12 +234,14 @@ namespace mpvnet
{
InvokeOnMainThread(new Action(() => {
string clipboard = System.Windows.Forms.Clipboard.GetText();
if (string.IsNullOrEmpty(clipboard) || (!clipboard.Contains("://") && !File.Exists(clipboard)) || clipboard.Contains("\n"))
{
Msg.ShowError("The clipboard does not contain a valid URL or file, URLs have to contain :// and are not allowed to contain a newline character.");
App.ShowError("No URL found", "The clipboard does not contain a valid URL or file.");
return;
}
mp.LoadFiles(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control));
core.LoadFiles(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control));
}));
}
@@ -245,7 +250,7 @@ namespace mpvnet
InvokeOnMainThread(new Action(() => {
using (var d = new OpenFileDialog())
{
string path = mp.get_property_string("path");
string path = core.get_property_string("path");
if (File.Exists(path))
d.InitialDirectory = Path.GetDirectoryName(path);
@@ -254,7 +259,7 @@ namespace mpvnet
if (d.ShowDialog() == DialogResult.OK)
foreach (string filename in d.FileNames)
mp.commandv("sub-add", filename);
core.commandv("sub-add", filename);
}
}));
}
@@ -264,40 +269,40 @@ namespace mpvnet
InvokeOnMainThread(new Action(() => {
using (var d = new OpenFileDialog())
{
string path = mp.get_property_string("path");
string path = core.get_property_string("path");
if (File.Exists(path))
d.InitialDirectory = Path.GetDirectoryName(path);
d.Multiselect = true;
if (d.ShowDialog() == DialogResult.OK)
foreach (string i in d.FileNames)
mp.commandv("audio-add", i);
core.commandv("audio-add", i);
}
}));
}
public static void CycleAudio()
{
string path = mp.get_property_string("path");
string path = core.get_property_string("path");
if (!File.Exists(path))
return;
using (MediaInfo mi = new MediaInfo(path))
{
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] audTracks = core.MediaTracks.Where(track => track.Type == "a").ToArray();
if (audTracks.Length < 2)
return;
int aid = mp.get_property_int("aid");
int aid = core.get_property_int("aid");
aid += 1;
if (aid > audTracks.Length)
aid = 1;
mp.commandv("set", "aid", aid.ToString());
mp.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
core.commandv("set", "aid", aid.ToString());
core.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
}
}
@@ -317,7 +322,7 @@ namespace mpvnet
''
}";
string json = mp.get_property_string("profile-list");
string json = core.get_property_string("profile-list");
string file = Path.GetTempPath() + @"\mpv profile-list.txt";
File.WriteAllText(file, BR + PowerShell.InvokeAndReturnString(code, "json", json));
Process.Start(file);
@@ -344,7 +349,7 @@ namespace mpvnet
}
}";
string json = mp.get_property_string("command-list");
string json = core.get_property_string("command-list");
string file = Path.GetTempPath() + @"\mpv command-list.txt";
File.WriteAllText(file, PowerShell.InvokeAndReturnString(code, "json", json) + BR);
Process.Start(file);
@@ -353,7 +358,7 @@ namespace mpvnet
static void ShowProperties()
{
string file = Path.GetTempPath() + @"\mpv property-list.txt";
var props = mp.get_property_string("property-list").Split(',').OrderBy(prop => prop);
var props = core.get_property_string("property-list").Split(',').OrderBy(prop => prop);
File.WriteAllText(file, BR + string.Join(BR, props) + BR);
Process.Start(file);
}

View File

@@ -1,10 +1,13 @@
using System;

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using static mpvnet.Core;
namespace mpvnet
{
public class Extension
@@ -25,20 +28,23 @@ namespace mpvnet
{
string[] knownExtensions = { "RatingExtension", "ScriptingExtension" };
foreach (string path in Directory.GetDirectories(dir))
foreach (string extDir in Directory.GetDirectories(dir))
{
if (knownExtensions.Contains(Path.GetFileName(path)))
catalog.Catalogs.Add(new DirectoryCatalog(path, "*Extension.dll"));
if (knownExtensions.Contains(Path.GetFileName(extDir)))
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
else
Msg.ShowError("Failed to load extension", path + "\n\nOnly extensions that ship with mpv.net are allowed in <startup>\\extensions\n\nUser extensions have to use <config folder>\\extensions\n\nNever copy or install a new mpv.net version over a old mpv.net version.");
ConsoleHelp.WriteError("Failed to load extension:\n\n" + extDir +
"\n\nOnly extensions that ship with mpv.net are allowed in <startup>\\extensions" +
"\n\nUser extensions have to use <config folder>\\extensions" +
"\n\nNever copy or install a new mpv.net version over a old mpv.net version.");
}
}
dir = mp.ConfigFolder + "extensions";
dir = core.ConfigFolder + "extensions";
if (Directory.Exists(dir))
foreach (string i in Directory.GetDirectories(dir))
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Extension.dll"));
foreach (string extDir in Directory.GetDirectories(dir))
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
if (catalog.Catalogs.Count > 0)
{
@@ -48,7 +54,7 @@ namespace mpvnet
}
catch (Exception ex)
{
Msg.ShowException(ex);
App.ShowException(ex);
}
}
}
@@ -56,4 +62,4 @@ namespace mpvnet
public interface IExtension
{
}
}
}

View File

@@ -6,7 +6,10 @@ public static class ConsoleHelp
{
public static int Padding { get; set; }
public static void WriteError(object obj, string module = null) => Write(obj, module, ConsoleColor.Red, false);
public static void WriteError(object obj, string module = "mpv.net")
{
Write(obj, module, ConsoleColor.Red, false);
}
public static void Write(object obj, string module = "mpv.net")
{

View File

@@ -14,6 +14,8 @@ using System.Windows.Forms;
using Microsoft.Win32;
using static mpvnet.Core;
namespace mpvnet
{
public class Sys
@@ -186,7 +188,7 @@ namespace mpvnet
public static ObservableCollection<CommandItem> Items {
get {
if (_Items is null)
_Items = GetItems(File.ReadAllText(mp.InputConfPath));
_Items = GetItems(File.ReadAllText(core.InputConfPath));
return _Items;
}

244
mpv.net/Misc/PowerShell.cs Normal file
View File

@@ -0,0 +1,244 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Threading.Tasks;
using static mpvnet.Core;
using static NewLine;
namespace mpvnet
{
public class PowerShell
{
public Runspace Runspace { get; set; }
public Pipeline Pipeline { get; set; }
public string Module { get; set; }
public bool Print { get; set; }
public List<string> Scripts { get; } = new List<string>();
public List<KeyValuePair<string, object>> Variables = new List<KeyValuePair<string, object>>();
public string[] Parameters { get; }
public event Action<string, object[]> Event;
public event Action<string, object> PropertyChanged;
public List<KeyValuePair<string, ScriptBlock>> EventHandlers = new List<KeyValuePair<string, ScriptBlock>>();
public List<KeyValuePair<string, ScriptBlock>> PropChangedHandlers = new List<KeyValuePair<string, ScriptBlock>>();
public static List<PowerShell> Instances { get; } = new List<PowerShell>();
public object Invoke() => Invoke(null, null);
public object Invoke(string variable, object obj)
{
try
{
Runspace = RunspaceFactory.CreateRunspace();
Runspace.ApartmentState = ApartmentState.STA;
Runspace.Open();
Pipeline = Runspace.CreatePipeline();
foreach (string script in Scripts)
Pipeline.Commands.AddScript(script);
if (Parameters != null)
foreach (string param in Parameters)
foreach (Command command in Pipeline.Commands)
command.Parameters.Add(null, param);
Runspace.SessionStateProxy.SetVariable("mp", this);
foreach (var i in Variables)
Runspace.SessionStateProxy.SetVariable(i.Key, i.Value);
if (!string.IsNullOrEmpty(variable))
Runspace.SessionStateProxy.SetVariable(variable, obj);
if (Print)
{
Pipeline.Output.DataReady += Output_DataReady;
Pipeline.Error.DataReady += Error_DataReady;
}
return Pipeline.Invoke();
}
catch (RuntimeException e)
{
string message = e.Message + BR + BR + e.ErrorRecord.ScriptStackTrace.Replace(
" <ScriptBlock>, <No file>", "") + BR + BR + Module + BR;
throw new PowerShellException(message);
}
catch (Exception e)
{
throw e;
}
}
public static string InvokeAndReturnString(string code, string varName, object varValue)
{
PowerShell ps = new PowerShell() { Print = false };
ps.Scripts.Add(code);
string ret = string.Join(Environment.NewLine, (ps.Invoke(varName, varValue)
as IEnumerable<object>).Select(item => item.ToString())).ToString();
ps.Runspace.Dispose();
return ret;
}
public void Output_DataReady(object sender, EventArgs e)
{
var output = sender as PipelineReader<PSObject>;
while (output.Count > 0)
ConsoleHelp.Write(output.Read(), Module);
}
public void Error_DataReady(object sender, EventArgs e)
{
var output = sender as PipelineReader<Object>;
while (output.Count > 0)
ConsoleHelp.WriteError(output.Read(), Module);
}
public void RedirectStreams(PSEventJob job)
{
if (Print)
{
job.Output.DataAdded += Output_DataAdded;
job.Error.DataAdded += Error_DataAdded;
}
}
public void commandv(params string[] args) => core.commandv(args);
public void command(string command) => core.command(command);
public bool get_property_bool(string name) => core.get_property_bool(name);
public void set_property_bool(string name, bool value) => core.set_property_bool(name, value);
public int get_property_int(string name) => core.get_property_int(name);
public void set_property_int(string name, int value) => core.set_property_int(name, value);
public double get_property_number(string name) => core.get_property_number(name);
public void set_property_number(string name, double value) => core.set_property_number(name, value);
public string get_property_string(string name) => core.get_property_string(name);
public void set_property_string(string name, string value) => core.set_property_string(name, value);
public void observe_property(string name, string type, ScriptBlock sb)
{
PropChangedHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
switch (type)
{
case "bool": case "boolean":
core.observe_property_bool(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
break;
case "string":
core.observe_property_string(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
break;
case "int": case "integer":
core.observe_property_int(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
break;
case "float": case "double":
core.observe_property_double(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
break;
case "nil": case "none": case "native":
core.observe_property(name, () => Task.Run(() => PropertyChanged.Invoke(name, null)));
break;
default:
App.ShowError("Invalid Type", "Valid types are: bool or boolean, string, int or integer, float or double, nil or none or native");
break;
}
}
public void register_event(string name, ScriptBlock sb)
{
EventHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
switch (name)
{
case "log-message":
core.LogMessageAsync += (level, msg) => Event.Invoke("log-message", new object[] { level, msg });
break;
case "end-file":
core.EndFileAsync += (reason) => Event.Invoke("end-file", new object[] { reason });
break;
case "client-message":
core.ClientMessageAsync += (args) => Event.Invoke("client-message", args);
break;
case "shutdown":
core.Shutdown += () => Event.Invoke("shutdown", null);
break;
case "get-property-reply":
core.GetPropertyReplyAsync += () => Event.Invoke("get-property-reply", null);
break;
case "set-property-reply":
core.SetPropertyReplyAsync += () => Event.Invoke("set-property-reply", null);
break;
case "command-reply":
core.CommandReplyAsync += () => Event.Invoke("command-reply", null);
break;
case "start-file":
core.StartFileAsync += () => Event.Invoke("start-file", null);
break;
case "file-loaded":
core.FileLoadedAsync += () => Event.Invoke("file-loaded", null);
break;
case "idle":
core.IdleAsync += () => Event.Invoke("idle", null);
break;
case "video-reconfig":
core.VideoReconfigAsync += () => Event.Invoke("video-reconfig", null);
break;
case "audio-reconfig":
core.AudioReconfigAsync += () => Event.Invoke("audio-reconfig", null);
break;
case "seek":
core.SeekAsync += () => Event.Invoke("seek", null);
break;
case "playback-restart":
core.PlaybackRestartAsync += () => Event.Invoke("playback-restart", null);
break;
}
}
void Output_DataAdded(object sender, DataAddedEventArgs e)
{
var output = sender as PSDataCollection<PSObject>;
ConsoleHelp.Write(output[e.Index], Module);
}
void Error_DataAdded(object sender, DataAddedEventArgs e)
{
var error = sender as PSDataCollection<ErrorRecord>;
ConsoleHelp.WriteError(error[e.Index], Module);
}
}
public class PowerShellException : Exception
{
public PowerShellException(string message) : base(message)
{
}
}
}

View File

@@ -6,6 +6,8 @@ using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
using static mpvnet.Core;
namespace mpvnet
{
static class Program
@@ -21,7 +23,7 @@ namespace mpvnet
if (App.IsStartedFromTerminal)
WinAPI.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
if (mp.ConfigFolder == "")
if (core.ConfigFolder == "")
return;
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
@@ -95,4 +97,4 @@ namespace mpvnet
}
}
}
}
}

View File

@@ -45,7 +45,7 @@ namespace UI
if (!theme.Dictionary.ContainsKey(key))
{
isKeyMissing = true;
ConsoleHelp.WriteError($"Theme '{activeTheme}' misses '{key}'", "mpv.net");
ConsoleHelp.WriteError($"Theme '{activeTheme}' misses '{key}'");
break;
}
}

View File

@@ -6,6 +6,8 @@ using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using static mpvnet.Core;
namespace mpvnet
{
class UpdateCheck
@@ -61,7 +63,7 @@ namespace mpvnet
proc.Start();
}
mp.command("quit");
core.command("quit");
}
RegistryHelp.SetValue(RegistryHelp.ApplicationKey, "UpdateCheckVersion", onlineVersion.ToString());
@@ -74,4 +76,4 @@ namespace mpvnet
}
}
}
}
}

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
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.4.5.0")]
[assembly: AssemblyFileVersion("5.4.5.0")]
[assembly: AssemblyVersion("5.4.5.1")]
[assembly: AssemblyFileVersion("5.4.5.1")]

View File

@@ -1,61 +0,0 @@

using System;
using System.IO;
using System.Reflection;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
using IronPython.Runtime;
using IronPython.Runtime.Operations;
namespace mpvnet
{
public class PythonScript
{
ScriptEngine engine;
ScriptScope scope;
public PythonScript(string scriptPath)
{
try
{
engine = Python.CreateEngine();
scope = engine.CreateScope();
scope.ImportModule("clr");
engine.Execute("import clr", scope);
engine.Execute("clr.AddReference(\"mpvnet\")", scope);
engine.Execute("import mpvnet", scope);
engine.Execute("from mpvnet import *", scope);
engine.Execute(File.ReadAllText(scriptPath), scope);
}
catch (Exception ex)
{
if (ex is SyntaxErrorException e)
Msg.ShowError(e.GetType().Name,$"{e.Line}, {e.Column}: " + e.Message + "\n\n" + Path.GetFileName(scriptPath));
else
Msg.ShowError(ex.GetType().Name, ex.Message + "\n\n" + Path.GetFileName(scriptPath));
}
}
}
public class PythonEventObject
{
public PythonFunction PythonFunction { get; set; }
public EventInfo EventInfo { get; set; }
public Delegate Delegate { get; set; }
public void Invoke() => PythonCalls.Call(PythonFunction);
public void InvokeEndFileEventMode(EndFileEventMode arg)
{
PythonCalls.Call(PythonFunction, new[] { arg });
}
public void InvokeStrings(string[] arg)
{
PythonCalls.Call(PythonFunction, new[] { arg });
}
}
}

View File

@@ -1,123 +0,0 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;
namespace ScriptHost
{
public class PowerShell
{
public Runspace Runspace { get; set; }
public Pipeline Pipeline { get; set; }
public string Module { get; set; }
public bool Print { get; set; }
public List<string> Scripts { get; } = new List<string>();
public string[] Parameters { get; }
public static List<PowerShell> Instances { get; } = new List<PowerShell>();
string NL = Environment.NewLine;
public object Invoke() => Invoke(null, null);
public object Invoke(string variable, object obj)
{
try
{
Runspace = RunspaceFactory.CreateRunspace();
Runspace.ApartmentState = ApartmentState.STA;
Runspace.Open();
Pipeline = Runspace.CreatePipeline();
foreach (string script in Scripts)
Pipeline.Commands.AddScript(script);
if (Parameters != null)
foreach (string param in Parameters)
foreach (Command command in Pipeline.Commands)
command.Parameters.Add(null, param);
Runspace.SessionStateProxy.SetVariable("ScriptHost", this);
if (!string.IsNullOrEmpty(variable))
Runspace.SessionStateProxy.SetVariable(variable, obj);
if (Print)
{
Pipeline.Output.DataReady += Output_DataReady;
Pipeline.Error.DataReady += Error_DataReady;
}
return Pipeline.Invoke();
}
catch (RuntimeException e)
{
string message = e.Message + NL + NL + e.ErrorRecord.ScriptStackTrace.Replace(
" <ScriptBlock>, <No file>", "") + NL + NL + Module + NL;
throw new PowerShellException(message);
}
catch (Exception e)
{
throw e;
}
}
public static string InvokeAndReturnString(string code, string varName, object varValue)
{
PowerShell ps = new PowerShell() { Print = false };
ps.Scripts.Add(code);
string ret = string.Join(Environment.NewLine, (ps.Invoke(varName, varValue)
as IEnumerable<object>).Select(item => item.ToString())).ToString();
ps.Runspace.Dispose();
return ret;
}
public void Output_DataReady(object sender, EventArgs e)
{
var output = sender as PipelineReader<PSObject>;
while (output.Count > 0)
ConsoleHelp.Write(output.Read(), Module);
}
public void Error_DataReady(object sender, EventArgs e)
{
var output = sender as PipelineReader<Object>;
while (output.Count > 0)
ConsoleHelp.WriteError(output.Read(), Module);
}
public void RedirectEventJobStreams(PSEventJob job)
{
if (Print)
{
job.Output.DataAdded += Output_DataAdded;
job.Error.DataAdded += Error_DataAdded;
}
}
void Output_DataAdded(object sender, DataAddedEventArgs e)
{
var output = sender as PSDataCollection<PSObject>;
ConsoleHelp.Write(output[e.Index], Module);
}
void Error_DataAdded(object sender, DataAddedEventArgs e)
{
var error = sender as PSDataCollection<ErrorRecord>;
ConsoleHelp.WriteError(error[e.Index], Module);
}
}
public class PowerShellException : Exception
{
public PowerShellException(string message) : base(message)
{
}
}
}

View File

@@ -1,7 +1,10 @@
using System.IO;

using System.IO;
using System.Windows;
using System.Windows.Input;
using static mpvnet.Core;
namespace mpvnet
{
public partial class AboutWindow : Window
@@ -10,7 +13,7 @@ namespace mpvnet
{
InitializeComponent();
Version.Text = $"mpv.net Version {System.Windows.Forms.Application.ProductVersion} ({File.GetLastWriteTime(System.Windows.Forms.Application.ExecutablePath).ToShortDateString()})";
mpvVersion.Text = $"{mp.get_property_string("mpv-version")} ({File.GetLastWriteTime(Folder.Startup + "mpv-1.dll").ToShortDateString()})";
mpvVersion.Text = $"{core.get_property_string("mpv-version")} ({File.GetLastWriteTime(Folder.Startup + "mpv-1.dll").ToShortDateString()})";
}
protected override void OnPreviewKeyDown(KeyEventArgs e) => Close();

View File

@@ -6,6 +6,8 @@ using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interop;
using static mpvnet.Core;
namespace mpvnet
{
public partial class CommandPaletteWindow : Window
@@ -106,7 +108,7 @@ namespace mpvnet
{
CommandItem item = ListView.SelectedItem as CommandItem;
Close();
mp.command(item.Command);
core.command(item.Command);
}
}

View File

@@ -11,6 +11,7 @@ using System.Windows.Controls;
using System.Windows.Input;
using DynamicGUI;
using static mpvnet.Core;
namespace mpvnet
{
@@ -26,7 +27,7 @@ namespace mpvnet
InitializeComponent();
DataContext = this;
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
LoadConf(mp.ConfPath);
LoadConf(core.ConfPath);
LoadConf(App.ConfPath);
LoadSettings();
InitialContent = GetCompareString();
@@ -74,7 +75,7 @@ namespace mpvnet
if (InitialContent == GetCompareString())
return;
File.WriteAllText(mp.ConfPath, GetContent("mpv"));
File.WriteAllText(core.ConfPath, GetContent("mpv"));
File.WriteAllText(App.ConfPath, GetContent("mpvnet"));
Msg.Show("Changes will be available on next mpv.net startup.");
}
@@ -293,7 +294,7 @@ namespace mpvnet
void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
Process.Start(Path.GetDirectoryName(mp.ConfPath));
Process.Start(Path.GetDirectoryName(core.ConfPath));
}
void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
@@ -319,4 +320,4 @@ namespace mpvnet
Close();
}
}
}
}

View File

@@ -10,6 +10,8 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using static mpvnet.Core;
namespace mpvnet
{
public partial class EverythingWindow : Window
@@ -103,7 +105,7 @@ namespace mpvnet
void Execute()
{
if (ListView.SelectedItem != null)
mp.LoadFiles(new[] { ListView.SelectedItem as string }, true, Keyboard.Modifiers == ModifierKeys.Control);
core.LoadFiles(new[] { ListView.SelectedItem as string }, true, Keyboard.Modifiers == ModifierKeys.Control);
Keyboard.Focus(FilterTextBox);
}

View File

@@ -8,6 +8,8 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using static mpvnet.Core;
namespace mpvnet
{
public partial class InputWindow : Window
@@ -123,7 +125,7 @@ namespace mpvnet
void Window_Closed(object sender, EventArgs e)
{
if (InitialInputConfContent == GetInputConfContent()) return;
File.WriteAllText(mp.InputConfPath, GetInputConfContent());
File.WriteAllText(core.InputConfPath, GetInputConfContent());
Msg.Show("Changes will be available on next mpv.net startup.");
}

View File

@@ -6,6 +6,7 @@ using System.Windows.Input;
using System.Windows.Interop;
using WinForms = System.Windows.Forms;
using static mpvnet.Core;
namespace mpvnet
{
@@ -183,7 +184,7 @@ namespace mpvnet
OnKeyUp(new WinForms.KeyEventArgs((WinForms.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys));
else if (m.Msg == WM_APPCOMMAND)
{
if (!mp.get_property_bool("input-media-keys"))
if (!core.get_property_bool("input-media-keys"))
return;
var value = (AppCommand)(m.LParam.ToInt64() >> 16 & ~0xf000);

View File

@@ -12,7 +12,7 @@ using System.Diagnostics;
using System.Threading.Tasks;
using UI;
using ScriptHost;
using static mpvnet.Core;
namespace mpvnet
{
@@ -47,30 +47,30 @@ namespace mpvnet
Instance = this;
Hwnd = Handle;
ConsoleHelp.Padding = 60;
mp.Init();
core.Init();
mp.Shutdown += Shutdown;
mp.VideoSizeChanged += VideoSizeChanged;
mp.FileLoaded += FileLoaded;
mp.Idle += Idle;
mp.Seek += () => UpdateProgressBar();
core.Shutdown += Shutdown;
core.VideoSizeChanged += VideoSizeChanged;
core.FileLoaded += FileLoaded;
core.Idle += Idle;
core.Seek += () => UpdateProgressBar();
mp.observe_property("window-maximized", PropChangeWindowMaximized);
mp.observe_property("window-minimized", PropChangeWindowMinimized);
mp.observe_property_bool("pause", PropChangePause);
mp.observe_property_bool("fullscreen", PropChangeFullscreen);
mp.observe_property_bool("ontop", PropChangeOnTop);
mp.observe_property_bool("border", PropChangeBorder);
core.observe_property("window-maximized", PropChangeWindowMaximized);
core.observe_property("window-minimized", PropChangeWindowMinimized);
core.observe_property_bool("pause", PropChangePause);
core.observe_property_bool("fullscreen", PropChangeFullscreen);
core.observe_property_bool("ontop", PropChangeOnTop);
core.observe_property_bool("border", PropChangeBorder);
mp.observe_property_string("sid", PropChangeSid);
mp.observe_property_string("aid", PropChangeAid);
mp.observe_property_string("vid", PropChangeVid);
core.observe_property_string("sid", PropChangeSid);
core.observe_property_string("aid", PropChangeAid);
core.observe_property_string("vid", PropChangeVid);
mp.observe_property_int("edition", PropChangeEdition);
mp.observe_property_double("window-scale", PropChangeWindowScale);
core.observe_property_int("edition", PropChangeEdition);
core.observe_property_double("window-scale", PropChangeWindowScale);
if (mp.GPUAPI != "vulkan")
mp.ProcessCommandLine(false);
if (core.GPUAPI != "vulkan")
core.ProcessCommandLine(false);
AppDomain.CurrentDomain.UnhandledException += (sender, e) => App.ShowException(e.ExceptionObject);
Application.ThreadException += (sender, e) => App.ShowException(e.Exception);
@@ -82,10 +82,10 @@ namespace mpvnet
ContextMenu.Opened += ContextMenu_Opened;
ContextMenu.Opening += ContextMenu_Opening;
if (mp.Screen == -1)
mp.Screen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen);
if (core.Screen == -1)
core.Screen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen);
int targetIndex = mp.Screen;
int targetIndex = core.Screen;
Screen[] screens = Screen.AllScreens;
if (targetIndex < 0)
@@ -99,7 +99,7 @@ namespace mpvnet
Left = target.X + (target.Width - Width) / 2;
Top = target.Y + (target.Height - Height) / 2;
if (!mp.Border)
if (!core.Border)
FormBorderStyle = FormBorderStyle.None;
int posX = RegistryHelp.GetInt(App.RegPath, "PosX");
@@ -111,13 +111,13 @@ namespace mpvnet
Top = posY - Height / 2;
}
if (mp.WindowMaximized)
if (core.WindowMaximized)
{
SetFormPosAndSize(1, true);
WindowState = FormWindowState.Maximized;
}
if (mp.WindowMinimized)
if (core.WindowMinimized)
{
SetFormPosAndSize(1, true);
WindowState = FormWindowState.Minimized;
@@ -163,7 +163,7 @@ namespace mpvnet
void ContextMenu_Opening(object sender, CancelEventArgs e)
{
lock (mp.MediaTracks)
lock (core.MediaTracks)
{
MenuItem trackMenuItem = FindMenuItem("Track");
@@ -171,16 +171,16 @@ namespace mpvnet
{
trackMenuItem.DropDownItems.Clear();
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] subTracks = mp.MediaTracks.Where(track => track.Type == "s").ToArray();
MediaTrack[] vidTracks = mp.MediaTracks.Where(track => track.Type == "v").ToArray();
MediaTrack[] ediTracks = mp.MediaTracks.Where(track => track.Type == "e").ToArray();
MediaTrack[] audTracks = core.MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] subTracks = core.MediaTracks.Where(track => track.Type == "s").ToArray();
MediaTrack[] vidTracks = core.MediaTracks.Where(track => track.Type == "v").ToArray();
MediaTrack[] ediTracks = core.MediaTracks.Where(track => track.Type == "e").ToArray();
foreach (MediaTrack track in vidTracks)
{
MenuItem mi = new MenuItem(track.Text);
mi.Action = () => mp.commandv("set", "vid", track.ID.ToString());
mi.Checked = mp.Vid == track.ID.ToString();
mi.Action = () => core.commandv("set", "vid", track.ID.ToString());
mi.Checked = core.Vid == track.ID.ToString();
trackMenuItem.DropDownItems.Add(mi);
}
@@ -190,8 +190,8 @@ namespace mpvnet
foreach (MediaTrack track in audTracks)
{
MenuItem mi = new MenuItem(track.Text);
mi.Action = () => mp.commandv("set", "aid", track.ID.ToString());
mi.Checked = mp.Aid == track.ID.ToString();
mi.Action = () => core.commandv("set", "aid", track.ID.ToString());
mi.Checked = core.Aid == track.ID.ToString();
trackMenuItem.DropDownItems.Add(mi);
}
@@ -201,16 +201,16 @@ namespace mpvnet
foreach (MediaTrack track in subTracks)
{
MenuItem mi = new MenuItem(track.Text);
mi.Action = () => mp.commandv("set", "sid", track.ID.ToString());
mi.Checked = mp.Sid == track.ID.ToString();
mi.Action = () => core.commandv("set", "sid", track.ID.ToString());
mi.Checked = core.Sid == track.ID.ToString();
trackMenuItem.DropDownItems.Add(mi);
}
if (subTracks.Length > 0)
{
MenuItem mi = new MenuItem("S: No subtitles");
mi.Action = () => mp.commandv("set", "sid", "no");
mi.Checked = mp.Sid == "no";
mi.Action = () => core.commandv("set", "sid", "no");
mi.Checked = core.Sid == "no";
trackMenuItem.DropDownItems.Add(mi);
}
@@ -220,14 +220,14 @@ namespace mpvnet
foreach (MediaTrack track in ediTracks)
{
MenuItem mi = new MenuItem(track.Text);
mi.Action = () => mp.commandv("set", "edition", track.ID.ToString());
mi.Checked = mp.Edition == track.ID;
mi.Action = () => core.commandv("set", "edition", track.ID.ToString());
mi.Checked = core.Edition == track.ID;
trackMenuItem.DropDownItems.Add(mi);
}
}
}
lock (mp.Chapters)
lock (core.Chapters)
{
MenuItem chaptersMenuItem = FindMenuItem("Chapters");
@@ -235,11 +235,11 @@ namespace mpvnet
{
chaptersMenuItem.DropDownItems.Clear();
foreach (var i in mp.Chapters)
foreach (var i in core.Chapters)
{
MenuItem mi = new MenuItem(i.Key);
mi.ShortcutKeyDisplayString = TimeSpan.FromSeconds(i.Value).ToString().Substring(0, 8) + " ";
mi.Action = () => mp.commandv("seek", i.Value.ToString(CultureInfo.InvariantCulture), "absolute");
mi.Action = () => core.commandv("seek", i.Value.ToString(CultureInfo.InvariantCulture), "absolute");
chaptersMenuItem.DropDownItems.Add(mi);
}
}
@@ -252,7 +252,7 @@ namespace mpvnet
recent.DropDownItems.Clear();
foreach (string path in RecentFiles)
MenuItem.Add(recent.DropDownItems, path, () => mp.LoadFiles(new[] { path }, true, Control.ModifierKeys.HasFlag(Keys.Control)));
MenuItem.Add(recent.DropDownItems, path, () => core.LoadFiles(new[] { path }, true, Control.ModifierKeys.HasFlag(Keys.Control)));
recent.DropDownItems.Add(new ToolStripSeparator());
MenuItem mi = new MenuItem("Clear List");
@@ -287,7 +287,7 @@ namespace mpvnet
if (WindowState != FormWindowState.Normal)
return;
if (mp.Fullscreen)
if (core.Fullscreen)
{
CycleFullscreen(true);
return;
@@ -295,17 +295,17 @@ namespace mpvnet
}
Screen screen = Screen.FromControl(this);
int autoFitHeight = Convert.ToInt32(screen.WorkingArea.Height * mp.Autofit);
int autoFitHeight = Convert.ToInt32(screen.WorkingArea.Height * core.Autofit);
if (mp.VideoSize.Height == 0 || mp.VideoSize.Width == 0 ||
mp.VideoSize.Width / (float)mp.VideoSize.Height < App.MinimumAspectRatio)
if (core.VideoSize.Height == 0 || core.VideoSize.Width == 0 ||
core.VideoSize.Width / (float)core.VideoSize.Height < App.MinimumAspectRatio)
mp.VideoSize = new Size((int)(autoFitHeight * (16 / 9.0)), autoFitHeight);
core.VideoSize = new Size((int)(autoFitHeight * (16 / 9.0)), autoFitHeight);
Size videoSize = mp.VideoSize;
Size videoSize = core.VideoSize;
int height = videoSize.Height;
if (mp.WasInitialSizeSet || scale != 1)
if (core.WasInitialSizeSet || scale != 1)
height = ClientSize.Height;
else
{
@@ -317,7 +317,7 @@ namespace mpvnet
if (App.StartSize != "video")
height = autoFitHeight;
mp.WasInitialSizeSet = true;
core.WasInitialSizeSet = true;
}
height = Convert.ToInt32(height * scale);
@@ -325,15 +325,15 @@ namespace mpvnet
int maxHeight = screen.WorkingArea.Height - (Height - ClientSize.Height);
int maxWidth = screen.WorkingArea.Width - (Width - ClientSize.Width);
if (height < maxHeight * mp.AutofitSmaller)
if (height < maxHeight * core.AutofitSmaller)
{
height = Convert.ToInt32(maxHeight * mp.AutofitSmaller);
height = Convert.ToInt32(maxHeight * core.AutofitSmaller);
width = Convert.ToInt32(height * videoSize.Width / (double)videoSize.Height);
}
if (height > maxHeight * mp.AutofitLarger)
if (height > maxHeight * core.AutofitLarger)
{
height = Convert.ToInt32(maxHeight * mp.AutofitLarger);
height = Convert.ToInt32(maxHeight * core.AutofitLarger);
width = Convert.ToInt32(height * videoSize.Width / (double)videoSize.Height);
}
@@ -374,7 +374,7 @@ namespace mpvnet
public void CycleFullscreen(bool enabled)
{
LastCycleFullscreen = Environment.TickCount;
mp.Fullscreen = enabled;
core.Fullscreen = enabled;
if (enabled)
{
@@ -401,7 +401,7 @@ namespace mpvnet
else
WindowState = FormWindowState.Normal;
if (mp.Border)
if (core.Border)
FormBorderStyle = FormBorderStyle.Sizable;
else
FormBorderStyle = FormBorderStyle.None;
@@ -414,7 +414,7 @@ namespace mpvnet
public void BuildMenu()
{
string content = File.ReadAllText(mp.InputConfPath);
string content = File.ReadAllText(core.InputConfPath);
var items = CommandItem.GetItems(content);
if (!content.Contains("#menu:"))
@@ -438,7 +438,7 @@ namespace mpvnet
MenuItem menuItem = ContextMenu.Add(path, () => {
try {
mp.command(item.Command);
core.command(item.Command);
} catch (Exception ex) {
Msg.ShowException(ex);
}
@@ -451,19 +451,24 @@ namespace mpvnet
void FileLoaded()
{
string path = mp.get_property_string("path");
string path = core.get_property_string("path");
BeginInvoke(new Action(() => {
if (path.Contains("://"))
Text = mp.get_property_string("media-title") + " - mpv.net " + Application.ProductVersion;
Text = core.get_property_string("media-title") + " - mpv.net " + Application.ProductVersion;
else if (path.Contains(":\\") || path.StartsWith("\\\\"))
Text = path.FileName() + " - mpv.net " + Application.ProductVersion;
else
Text = "mpv.net " + Application.ProductVersion;
int interval = (int)(mp.Duration.TotalMilliseconds / 100);
if (interval < 100) interval = 100;
if (interval > 1000) interval = 1000;
int interval = (int)(core.Duration.TotalMilliseconds / 100);
if (interval < 100)
interval = 100;
if (interval > 1000)
interval = 1000;
ProgressTimer.Interval = interval;
UpdateProgressBar();
}));
@@ -510,19 +515,17 @@ namespace mpvnet
case 0x20A: // WM_MOUSEWHEEL
case 0x100: // WM_KEYDOWN
case 0x101: // WM_KEYUP
case 0x102: // WM_CHAR
case 0x104: // WM_SYSKEYDOWN
case 0x105: // WM_SYSKEYUP
case 0x106: // WM_SYSCHAR
case 0x319: // WM_APPCOMMAND
if (mp.WindowHandle != IntPtr.Zero)
m.Result = WinAPI.SendMessage(mp.WindowHandle, m.Msg, m.WParam, m.LParam);
if (core.WindowHandle != IntPtr.Zero)
m.Result = WinAPI.SendMessage(core.WindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x0200: // WM_MOUSEMOVE
if (Environment.TickCount - LastCycleFullscreen > 500)
{
Point pos = PointToClient(Cursor.Position);
mp.command($"mouse {pos.X} {pos.Y}");
core.command($"mouse {pos.X} {pos.Y}");
}
if (CursorHelp.IsPosDifferent(LastCursorPosition))
@@ -530,12 +533,12 @@ namespace mpvnet
break;
case 0x2a3: // WM_MOUSELEAVE
//osc won't auto hide after mouse left window in borderless mode
mp.command($"mouse {ClientSize.Width / 2} {ClientSize.Height / 3}");
core.command($"mouse {ClientSize.Width / 2} {ClientSize.Height / 3}");
break;
case 0x203: // WM_LBUTTONDBLCLK
{
Point pos = PointToClient(Cursor.Position);
mp.command($"mouse {pos.X} {pos.Y} 0 double");
core.command($"mouse {pos.X} {pos.Y} 0 double");
}
break;
case 0x02E0: // WM_DPICHANGED
@@ -553,7 +556,7 @@ namespace mpvnet
var r = rc;
NativeHelp.SubtractWindowBorders(Handle, ref r);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
Size s = mp.VideoSize;
Size s = core.VideoSize;
if (s == Size.Empty)
s = new Size(16, 9);
@@ -582,11 +585,11 @@ namespace mpvnet
switch (mode)
{
case "single":
mp.LoadFiles(files, true, Control.ModifierKeys.HasFlag(Keys.Control));
core.LoadFiles(files, true, Control.ModifierKeys.HasFlag(Keys.Control));
break;
case "queue":
foreach (string file in files)
mp.commandv("loadfile", file, "append");
core.commandv("loadfile", file, "append");
break;
}
@@ -595,7 +598,7 @@ namespace mpvnet
return;
}
if (m.Msg == TaskbarButtonCreatedMessage && mp.TaskbarProgress)
if (m.Msg == TaskbarButtonCreatedMessage && core.TaskbarProgress)
{
Taskbar = new Taskbar(Handle);
ProgressTimer.Start();
@@ -622,26 +625,26 @@ namespace mpvnet
void UpdateProgressBar()
{
if (mp.TaskbarProgress && Taskbar != null)
Taskbar.SetValue(mp.get_property_number("time-pos"), mp.Duration.TotalSeconds);
if (core.TaskbarProgress && Taskbar != null)
Taskbar.SetValue(core.get_property_number("time-pos"), core.Duration.TotalSeconds);
}
void PropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value));
void PropChangeAid(string value) => mp.Aid = value;
void PropChangeAid(string value) => core.Aid = value;
void PropChangeSid(string value) => mp.Sid = value;
void PropChangeSid(string value) => core.Sid = value;
void PropChangeVid(string value) => mp.Vid = value;
void PropChangeVid(string value) => core.Vid = value;
void PropChangeEdition(int value) => mp.Edition = value;
void PropChangeEdition(int value) => core.Edition = value;
void PropChangeWindowScale(double value)
{
if (value != 1)
{
BeginInvoke(new Action(() => SetFormPosAndSize(value)));
mp.command("no-osd set window-scale 1");
core.command("no-osd set window-scale 1");
}
}
@@ -652,11 +655,11 @@ namespace mpvnet
BeginInvoke(new Action(() =>
{
mp.WindowMaximized = mp.get_property_bool("window-maximized");
core.WindowMaximized = core.get_property_bool("window-maximized");
if (mp.WindowMaximized && WindowState != FormWindowState.Maximized)
if (core.WindowMaximized && WindowState != FormWindowState.Maximized)
WindowState = FormWindowState.Maximized;
else if (!mp.WindowMaximized && WindowState == FormWindowState.Maximized)
else if (!core.WindowMaximized && WindowState == FormWindowState.Maximized)
WindowState = FormWindowState.Normal;
}));
}
@@ -668,25 +671,25 @@ namespace mpvnet
BeginInvoke(new Action(() =>
{
mp.WindowMinimized = mp.get_property_bool("window-minimized");
core.WindowMinimized = core.get_property_bool("window-minimized");
if (mp.WindowMinimized && WindowState != FormWindowState.Minimized)
if (core.WindowMinimized && WindowState != FormWindowState.Minimized)
WindowState = FormWindowState.Minimized;
else if (!mp.WindowMinimized && WindowState == FormWindowState.Minimized)
else if (!core.WindowMinimized && WindowState == FormWindowState.Minimized)
WindowState = FormWindowState.Normal;
}));
}
void PropChangeBorder(bool enabled) {
mp.Border = enabled;
core.Border = enabled;
BeginInvoke(new Action(() => {
if (!IsFullscreen)
{
if (mp.Border && FormBorderStyle == FormBorderStyle.None)
if (core.Border && FormBorderStyle == FormBorderStyle.None)
FormBorderStyle = FormBorderStyle.Sizable;
if (!mp.Border && FormBorderStyle == FormBorderStyle.Sizable)
if (!core.Border && FormBorderStyle == FormBorderStyle.Sizable)
FormBorderStyle = FormBorderStyle.None;
}
}));
@@ -694,7 +697,7 @@ namespace mpvnet
void PropChangePause(bool enabled)
{
if (Taskbar != null && mp.TaskbarProgress)
if (Taskbar != null && core.TaskbarProgress)
{
if (enabled)
Taskbar.SetState(TaskbarStates.Paused);
@@ -707,8 +710,8 @@ namespace mpvnet
{
base.OnLoad(e);
if (mp.GPUAPI != "vulkan")
mp.VideoSizeAutoResetEvent.WaitOne(App.StartThreshold);
if (core.GPUAPI != "vulkan")
core.VideoSizeAutoResetEvent.WaitOne(App.StartThreshold);
LastCycleFullscreen = Environment.TickCount;
SetFormPosAndSize();
@@ -718,8 +721,8 @@ namespace mpvnet
{
base.OnShown(e);
if (mp.GPUAPI == "vulkan")
mp.ProcessCommandLine(false);
if (core.GPUAPI == "vulkan")
core.ProcessCommandLine(false);
ToolStripRendererEx.ForegroundColor = Theme.Current.GetWinFormsColor("menu-foreground");
ToolStripRendererEx.BackgroundColor = Theme.Current.GetWinFormsColor("menu-background");
@@ -733,7 +736,7 @@ namespace mpvnet
System.Windows.Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
Cursor.Position = new Point(Cursor.Position.X + 1, Cursor.Position.Y);
UpdateCheck.DailyCheck();
mp.LoadScripts();
core.LoadScripts();
Task.Run(() => App.Extension = new Extension());
ShownTickCount = Environment.TickCount;
}
@@ -749,8 +752,8 @@ namespace mpvnet
{
base.OnResize(e);
if (mp.IsLogoVisible)
mp.ShowLogo();
if (core.IsLogoVisible)
core.ShowLogo();
if (FormBorderStyle != FormBorderStyle.None)
{
@@ -764,16 +767,16 @@ namespace mpvnet
{
if (WindowState == FormWindowState.Minimized)
{
mp.set_property_string("window-minimized", "yes");
core.set_property_string("window-minimized", "yes");
}
else if (WindowState == FormWindowState.Normal)
{
mp.set_property_string("window-maximized", "no");
mp.set_property_string("window-minimized", "no");
core.set_property_string("window-maximized", "no");
core.set_property_string("window-minimized", "no");
}
else if (WindowState == FormWindowState.Maximized)
{
mp.set_property_string("window-maximized", "yes");
core.set_property_string("window-maximized", "yes");
}
}
}
@@ -784,10 +787,10 @@ namespace mpvnet
SaveWindowProperties();
RegistryHelp.SetValue(App.RegPath, "Recent", RecentFiles.ToArray());
if (mp.IsQuitNeeded)
mp.commandv("quit");
if (core.IsQuitNeeded)
core.commandv("quit");
if (!mp.ShutdownAutoResetEvent.WaitOne(10000))
if (!core.ShutdownAutoResetEvent.WaitOne(10000))
Msg.ShowError("Shutdown thread failed to complete within 10 seconds.");
try { // PowerShell 5.1 might not be available
@@ -809,7 +812,7 @@ namespace mpvnet
}
if (Width - e.Location.X < 10 && e.Location.Y < 10)
mp.commandv("quit");
core.commandv("quit");
}
protected override void OnDragEnter(DragEventArgs e)
@@ -825,10 +828,10 @@ namespace mpvnet
base.OnDragDrop(e);
if (e.Data.GetDataPresent(DataFormats.FileDrop))
mp.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[], true, Control.ModifierKeys.HasFlag(Keys.Control));
core.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[], true, Control.ModifierKeys.HasFlag(Keys.Control));
if (e.Data.GetDataPresent(DataFormats.Text))
mp.LoadFiles(new[] { e.Data.GetData(DataFormats.Text).ToString() }, true, Control.ModifierKeys.HasFlag(Keys.Control));
core.LoadFiles(new[] { e.Data.GetData(DataFormats.Text).ToString() }, true, Control.ModifierKeys.HasFlag(Keys.Control));
}
protected override void OnLostFocus(EventArgs e)
@@ -839,8 +842,10 @@ namespace mpvnet
protected override void OnKeyDown(KeyEventArgs e)
{
e.SuppressKeyPress = true; // prevent beep using alt key
if (Control.ModifierKeys == Keys.Alt)
e.SuppressKeyPress = true; // prevent beep using alt key
base.OnKeyDown(e);
}
}
}
}

View File

@@ -76,29 +76,6 @@
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
</PropertyGroup>
<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="Microsoft.VisualBasic" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
@@ -156,7 +133,7 @@
<Compile Include="Misc\UpdateCheck.cs" />
<Compile Include="Misc\RegistryHelp.cs" />
<Compile Include="Misc\Theme.cs" />
<Compile Include="Scripting\PowerShell.cs" />
<Compile Include="Misc\PowerShell.cs" />
<Compile Include="WPF\SearchTextBoxUserControl.xaml.cs">
<DependentUpon>SearchTextBoxUserControl.xaml</DependentUpon>
</Compile>
@@ -179,7 +156,6 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Scripting\IronPython.cs" />
<Compile Include="mpv\libmpv.cs" />
<Compile Include="WinForms\MainForm.cs">
<SubType>Form</SubType>
@@ -188,8 +164,8 @@
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Misc\Misc.cs" />
<Compile Include="mpv\mp.cs" />
<Compile Include="Misc\Command.cs" />
<Compile Include="mpv\Core.cs" />
<Compile Include="Misc\Commands.cs" />
<Compile Include="Native\Native.cs" />
<Compile Include="Native\NativeHelp.cs" />
<Compile Include="Misc\Program.cs" />

File diff suppressed because it is too large Load Diff

View File

@@ -44,6 +44,9 @@ public class libmpv
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref Int64 data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_observe_property(IntPtr mpvHandle, UInt64 reply_userdata, [MarshalAs(UnmanagedType.LPUTF8Str)] string name, mpv_format format);
@@ -149,9 +152,9 @@ public class libmpv
[StructLayout(LayoutKind.Sequential)]
public struct mpv_event_log_message
{
public string prefix;
public string level;
public string text;
public IntPtr prefix;
public IntPtr level;
public IntPtr text;
public mpv_log_level log_level;
}

View File

@@ -8,9 +8,11 @@ using System.Linq;
class Script
{
MainForm MainForm;
Core core;
public Script()
{
core = Core.core;
MainForm = mpvnet.MainForm.Instance;
MainForm.ContextMenu.Opening += ContextMenu_Opening;
}
@@ -24,13 +26,13 @@ class Script
return;
menuItem.DropDownItems.Clear();
var editionTracks = mp.MediaTracks.Where(track => track.Type == "e");
var editionTracks = core.MediaTracks.Where(track => track.Type == "e");
foreach (MediaTrack track in editionTracks)
{
MenuItem mi = new MenuItem(track.Text);
mi.Action = () => { mp.commandv("set", "edition", track.ID.ToString()); };
mi.Checked = mp.Edition == track.ID;
mi.Action = () => { core.commandv("set", "edition", track.ID.ToString()); };
mi.Checked = core.Edition == track.ID;
menuItem.DropDownItems.Add(mi);
}
}

View File

@@ -11,9 +11,10 @@ class Script
{
string content = "ctrl+w script-message my-message-1 my-argument-1";
string sectionName = Assembly.GetExecutingAssembly().GetName().Name;
mp.commandv("define-section", sectionName, content, "force");
mp.commandv("enable-section", sectionName);
mp.ClientMessage += ClientMessage;
Core core = Core.core;
core.commandv("define-section", sectionName, content, "force");
core.commandv("enable-section", sectionName);
core.ClientMessage += ClientMessage;
}
void ClientMessage(string[] args)

View File

@@ -6,13 +6,16 @@ using mpvnet;
class Script
{
Core core;
public Script()
{
mp.observe_property_bool("fullscreen", FullscreenChange);
core = Core.core;
core.observe_property_bool("fullscreen", FullscreenChange);
}
void FullscreenChange(bool value)
{
mp.commandv("show-text", "fullscreen: " + value);
core.commandv("show-text", "fullscreen: " + value);
}
}

View File

@@ -9,12 +9,14 @@ using mpvnet;
class Script
{
MainForm Form;
Core core;
bool WasPlaying;
bool WasPaused;
public Script()
{
core = Core.core;
Form = MainForm.Instance;
Form.Resize += Form_Resize;
}
@@ -23,11 +25,11 @@ class Script
{
if (Form.WindowState == FormWindowState.Minimized)
{
WasPlaying = !mp.get_property_bool("pause");
WasPlaying = !core.get_property_bool("pause");
if (WasPlaying)
{
mp.set_property_bool("pause", true, true);
core.set_property_bool("pause", true, true);
WasPaused = true;
}
}
@@ -35,7 +37,7 @@ class Script
{
if (WasPaused)
{
mp.set_property_bool("pause", false, true);
core.set_property_bool("pause", false, true);
WasPaused = false;
}
}

View File

@@ -1,4 +0,0 @@
// This script shows a message box using the Msg class of mpv.net.
[Msg]::Show("Hello World")

View File

@@ -1,25 +0,0 @@
# Shows the Open File dialog to open a file without loading its folder into the playlist.
# In input.conf add: <key> script-message load-without-folder
$job = Register-ObjectEvent -InputObject ([mpvnet.mp]) -EventName ClientMessage -Action {
# exit if message does not equal 'load-without-folder'
if ($args.Length -ne 1 -or $args[0] -ne 'load-without-folder')
{
exit
}
$dialog = New-Object Windows.Forms.OpenFileDialog
if ($dialog.ShowDialog() -ne "OK") {
$dialog.Dispose()
exit
}
[mp]::Load($dialog.FileNames, $false, $false);
$dialog.Dispose()
}
$ScriptHost.RedirectEventJobStreams($job)

View File

@@ -1,8 +0,0 @@
# Display position in window title bar when seeking
$job = Register-ObjectEvent -InputObject ([mpvnet.mp]) -EventName Seek -Action {
[MainForm]::Instance.Text = [mp]::get_property_number("time-pos")
}
$ScriptHost.RedirectEventJobStreams($job)

View File

@@ -3,7 +3,6 @@
function showPlaylist()
{
// set font size
mp.set_property_number("osd-font-size", 40);

View File

@@ -8,18 +8,16 @@
local did_minimize = false
mp.observe_property("window-minimized", "bool", function(name, value)
local pause = mp.get_property_bool("pause")
local pause = mp.get_property_native("pause")
if value == true then
if pause == false then
mp.set_property_bool("pause", true)
mp.set_property_native("pause", true)
did_minimize = true
end
elseif value == false then
if did_minimize and (pause == true) then
mp.set_property_bool("pause", false)
mp.set_property_native("pause", false)
end
did_minimize = false
end
end)

View File

@@ -0,0 +1,20 @@
# Shows the Open File dialog to open a file without loading its folder into the playlist.
# In input.conf add: <key> script-message load-without-folder
$code = {
if ($args[0] -eq 'load-without-folder')
{
$dialog = New-Object Windows.Forms.OpenFileDialog
if ($dialog.ShowDialog() -eq 'OK')
{
$core.LoadFiles($dialog.FileNames, $false, $false);
}
$dialog.Dispose()
}
}
$mp.register_event("client-message", $code)

View File

@@ -0,0 +1,27 @@
Set-Variable wasPaused $false -Option AllScope
$code = {
$isMinimized = $args[0]
$isPaused = $mp.get_property_bool('pause')
if ($isMinimized)
{
if (-not $isPaused)
{
$mp.set_property_bool('pause', $true)
$wasPaused = $true
}
}
else
{
if ($wasPaused -and $isPaused)
{
$mp.set_property_bool('pause', $false)
}
$wasPaused = $false
}
}
$mp.observe_property('window-minimized', 'bool', $code)