replace v6 with experimental v7 code
This commit is contained in:
215
src/MpvNet/App.cs
Normal file
215
src/MpvNet/App.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
|
||||
using MpvNet.ExtensionMethod;
|
||||
using MpvNet.Help;
|
||||
using MpvNet.MVVM;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class AppClass
|
||||
{
|
||||
public List<string> TempFiles { get; } = new List<string>();
|
||||
|
||||
public string ConfPath { get => Player.ConfigFolder + "mpvnet.conf"; }
|
||||
public string ProcessInstance { get; set; } = "single";
|
||||
public string DarkMode { get; set; } = "always";
|
||||
public string DarkTheme { get; set; } = "dark";
|
||||
public string LightTheme { get; set; } = "light";
|
||||
public string StartSize { get; set; } = "height-session";
|
||||
|
||||
public bool AutoLoadFolder { get; set; } = true;
|
||||
public bool DebugMode { get; set; }
|
||||
public bool Exit { get; set; }
|
||||
public bool IsTerminalAttached { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
|
||||
public bool MediaInfo { get; set; } = true;
|
||||
public bool Queue { get; set; }
|
||||
public bool RememberVolume { get; set; } = true;
|
||||
public bool RememberWindowPosition { get; set; }
|
||||
|
||||
public int StartThreshold { get; set; } = 1500;
|
||||
public int RecentCount { get; set; } = 15;
|
||||
|
||||
public float AutofitAudio { get; set; } = 0.7f;
|
||||
public float AutofitImage { get; set; } = 0.8f;
|
||||
public float MinimumAspectRatio { get; set; }
|
||||
public float MinimumAspectRatioAudio { get; set; }
|
||||
|
||||
readonly ExtensionLoader _extensionManager = new ExtensionLoader();
|
||||
|
||||
AppSettings? _settings;
|
||||
|
||||
public AppClass()
|
||||
{
|
||||
_extensionManager.UnhandledException += ex => Terminal.WriteError(ex);
|
||||
|
||||
StrongReferenceMessenger.Default.Register<MainWindowIsLoadedMessage>(this, (r, msg) =>
|
||||
{
|
||||
TaskHelp.Run(() => _extensionManager.LoadFolder(Player.ConfigFolder + "extensions"));
|
||||
});
|
||||
}
|
||||
|
||||
public AppSettings Settings => _settings ??= SettingsManager.Load();
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var useless1 = Player.ConfigFolder;
|
||||
var useless2 = Player.Conf;
|
||||
|
||||
foreach (var i in Conf)
|
||||
ProcessProperty(i.Key, i.Value, true);
|
||||
|
||||
if (DebugMode)
|
||||
{
|
||||
string filePath = Player.ConfigFolder + "MpvNet-debug.log";
|
||||
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(filePath));
|
||||
Trace.AutoFlush = true;
|
||||
}
|
||||
|
||||
Player.Shutdown += Player_Shutdown;
|
||||
Player.Initialized += Player_Initialized;
|
||||
}
|
||||
|
||||
public static string About => "Copyright (C) 2000-2023 mpv.net/mpv/mplayer\n" +
|
||||
$"{AppInfo.Product} {AppInfo.Version}" + GetLastWriteTime(Environment.ProcessPath!) + "\n" +
|
||||
$"{Player.GetPropertyString("mpv-version")}" + GetLastWriteTime(Folder.Startup + "libmpv-2.dll") + "\n" +
|
||||
$"ffmpeg {Player.GetPropertyString("ffmpeg-version")}\n" + "\nGPL v2 License";
|
||||
|
||||
static string GetLastWriteTime(string path)
|
||||
{
|
||||
if (IsStoreVersion)
|
||||
return "";
|
||||
|
||||
return $" ({File.GetLastWriteTime(path).ToShortDateString()})";
|
||||
}
|
||||
|
||||
static bool IsStoreVersion => Folder.Startup.Contains("FrankSkare.mpvnet");
|
||||
|
||||
void Player_Initialized()
|
||||
{
|
||||
if (RememberVolume)
|
||||
{
|
||||
Player.SetPropertyInt("volume", Settings.Volume);
|
||||
Player.SetPropertyString("mute", Settings.Mute);
|
||||
}
|
||||
}
|
||||
|
||||
void Player_Shutdown()
|
||||
{
|
||||
Settings.Volume = Player.GetPropertyInt("volume");
|
||||
Settings.Mute = Player.GetPropertyString("mute");
|
||||
|
||||
SettingsManager.Save(Settings);
|
||||
|
||||
foreach (string file in TempFiles)
|
||||
FileHelp.Delete(file);
|
||||
}
|
||||
|
||||
Dictionary<string, string>? _Conf;
|
||||
|
||||
public Dictionary<string, string> Conf {
|
||||
get {
|
||||
if (_Conf == null)
|
||||
{
|
||||
_Conf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(ConfPath))
|
||||
foreach (string i in File.ReadAllLines(ConfPath))
|
||||
if (i.Contains('=') && !i.StartsWith("#"))
|
||||
_Conf[i[..i.IndexOf("=")].Trim()] = i[(i.IndexOf("=") + 1)..].Trim();
|
||||
}
|
||||
|
||||
return _Conf;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ProcessProperty(string name, string value, bool writeError = false)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "audio-file-extensions": FileTypes.Audio = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
|
||||
case "auto-load-folder": AutoLoadFolder = value == "yes"; return true;
|
||||
case "autofit-audio": AutofitAudio = value.Trim('%').ToInt(70) / 100f; return true;
|
||||
case "autofit-image": AutofitImage = value.Trim('%').ToInt(80) / 100f; return true;
|
||||
case "dark-mode": DarkMode = value; return true;
|
||||
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
|
||||
case "debug-mode": DebugMode = value == "yes"; return true;
|
||||
case "image-file-extensions": FileTypes.Image = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
|
||||
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
|
||||
case "media-info": MediaInfo = value == "yes"; return true;
|
||||
case "minimum-aspect-ratio-audio": MinimumAspectRatioAudio = value.ToFloat(); return true;
|
||||
case "minimum-aspect-ratio": MinimumAspectRatio = value.ToFloat(); return true;
|
||||
case "process-instance": ProcessInstance = value; return true;
|
||||
case "queue": Queue = value == "yes"; return true;
|
||||
case "recent-count": RecentCount = value.ToInt(15); return true;
|
||||
case "remember-volume": RememberVolume = value == "yes"; return true;
|
||||
case "remember-window-position": RememberWindowPosition = value == "yes"; return true;
|
||||
case "start-size": StartSize = value; return true;
|
||||
case "start-threshold": StartThreshold = value.ToInt(1500); return true;
|
||||
case "video-file-extensions": FileTypes.Video = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
|
||||
|
||||
default:
|
||||
if (writeError)
|
||||
Terminal.WriteError($"unknown MpvNet.conf property: {name}");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static (string Title, string Path) GetTitleAndPath(string input)
|
||||
{
|
||||
if (input.Contains('|'))
|
||||
{
|
||||
var a = input.Split('|');
|
||||
return (a[1], a[0]);
|
||||
}
|
||||
|
||||
return (input, input);
|
||||
}
|
||||
|
||||
InputConf? _inputConf;
|
||||
|
||||
public InputConf InputConf => _inputConf ??= new InputConf(Player.ConfigFolder + "input.conf");
|
||||
|
||||
public void ApplyShowMenuFix()
|
||||
{
|
||||
if (Settings.ShowMenuFixApplied)
|
||||
return;
|
||||
|
||||
if (File.Exists(InputConf.Path))
|
||||
{
|
||||
string content = File.ReadAllText(InputConf.Path);
|
||||
|
||||
if (!content.Contains("script-message mpvnet show-menu") &&
|
||||
!content.Contains("script-message-to mpvnet show-menu"))
|
||||
|
||||
File.WriteAllText(InputConf.Path, BR + content.Trim() + BR +
|
||||
"MBTN_Right script-message-to mpvnet show-menu" + BR);
|
||||
}
|
||||
|
||||
Settings.ShowMenuFixApplied = true;
|
||||
}
|
||||
|
||||
public void ApplyInputDefaultBindingsFix()
|
||||
{
|
||||
if (Settings.InputDefaultBindingsFixApplied)
|
||||
return;
|
||||
|
||||
if (File.Exists(Player.ConfPath))
|
||||
{
|
||||
string content = File.ReadAllText(Player.ConfPath);
|
||||
|
||||
if (content.Contains("input-default-bindings = no"))
|
||||
File.WriteAllText(ConfPath, content.Replace("input-default-bindings = no", ""));
|
||||
|
||||
if (content.Contains("input-default-bindings=no"))
|
||||
File.WriteAllText(ConfPath, content.Replace("input-default-bindings=no", ""));
|
||||
}
|
||||
|
||||
Settings.InputDefaultBindingsFixApplied = true;
|
||||
}
|
||||
}
|
||||
11
src/MpvNet/AppInfo.cs
Normal file
11
src/MpvNet/AppInfo.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public static class AppInfo
|
||||
{
|
||||
public static string Product => GetAssemblyAttribute<AssemblyProductAttribute>().Product;
|
||||
public static Version Version => Assembly.GetEntryAssembly()!.GetName().Version!;
|
||||
static T GetAssemblyAttribute<T>() => (T)(object)Assembly.GetEntryAssembly()!.GetCustomAttributes(typeof(T)).First();
|
||||
}
|
||||
44
src/MpvNet/Binding.cs
Normal file
44
src/MpvNet/Binding.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class Binding : ObservableObject
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Command { get; set; }
|
||||
public string Comment { get; set; }
|
||||
|
||||
public bool IsMenu { get; set; }
|
||||
|
||||
public Binding()
|
||||
{
|
||||
Path = ""; Command = ""; Comment = "";
|
||||
}
|
||||
|
||||
public Binding(string folder = "",
|
||||
string name = "",
|
||||
string command = "",
|
||||
string input = "",
|
||||
string comment = "")
|
||||
{
|
||||
if (folder != "" && name != "")
|
||||
Path = folder + " > " + name;
|
||||
else if (name != "")
|
||||
Path = name;
|
||||
else
|
||||
Path = "";
|
||||
|
||||
Command = command;
|
||||
Input = input;
|
||||
Comment = comment == "" ? Path : comment;
|
||||
}
|
||||
|
||||
string _input = "";
|
||||
|
||||
public string Input
|
||||
{
|
||||
get => _input;
|
||||
set => SetProperty(ref _input, value);
|
||||
}
|
||||
}
|
||||
28
src/MpvNet/Chapter.cs
Normal file
28
src/MpvNet/Chapter.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
using MpvNet.ExtensionMethod;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class Chapter
|
||||
{
|
||||
public string Title { get; set; } = "";
|
||||
public double Time { get; set; }
|
||||
|
||||
string? _timeDisplay;
|
||||
|
||||
public string TimeDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_timeDisplay == null)
|
||||
{
|
||||
_timeDisplay = TimeSpan.FromSeconds(Time).ToString();
|
||||
|
||||
if (_timeDisplay.ContainsEx("."))
|
||||
_timeDisplay = _timeDisplay[.._timeDisplay.LastIndexOf(".")];
|
||||
}
|
||||
|
||||
return _timeDisplay;
|
||||
}
|
||||
}
|
||||
}
|
||||
178
src/MpvNet/Command.cs
Normal file
178
src/MpvNet/Command.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
using MpvNet.Help;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class Command
|
||||
{
|
||||
Dictionary<string, Action<IList<string>>>? _commands;
|
||||
|
||||
public static Command Current { get; } = new();
|
||||
|
||||
public Dictionary<string, Action<IList<string>>> Commands => _commands ??= new()
|
||||
{
|
||||
["open-conf-folder"] = args => ProcessHelp.ShellExecute(Player.ConfigFolder),
|
||||
["play-pause"] = PlayPause,
|
||||
["shell-execute"] = args => ProcessHelp.ShellExecute(args[0]),
|
||||
["show-text"] = args => ShowText(args[0], Convert.ToInt32(args[1]), Convert.ToInt32(args[2])),
|
||||
|
||||
|
||||
// backward compatibility
|
||||
["playlist-add"] = args => PlaylistAdd(Convert.ToInt32(args[0])), // backward compatibility
|
||||
["show-progress"] = args => ShowProgress(), // backward compatibility
|
||||
["cycle-audio"] = args => CycleAudio(), // backward compatibility
|
||||
["cycle-subtitles"] = args => CycleSubtitles(), // backward compatibility
|
||||
["playlist-first"] = args => PlaylistFirst(), // backward compatibility
|
||||
["playlist-last"] = args => PlaylistLast(), // backward compatibility
|
||||
};
|
||||
|
||||
public string FormatTime(double value) => ((int)value).ToString("00");
|
||||
|
||||
public static void PlayPause(IList<string> args)
|
||||
{
|
||||
int count = Player.GetPropertyInt("playlist-count");
|
||||
|
||||
if (count > 0)
|
||||
Player.Command("cycle pause");
|
||||
else if (App.Settings.RecentFiles.Count > 0)
|
||||
{
|
||||
foreach (string i in App.Settings.RecentFiles)
|
||||
{
|
||||
if (i.Contains("://") || File.Exists(i))
|
||||
{
|
||||
Player.LoadFiles(new[] { i }, true, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowText(string text, int duration = 0, int fontSize = 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return;
|
||||
|
||||
if (duration == 0)
|
||||
duration = Player.GetPropertyInt("osd-duration");
|
||||
|
||||
if (fontSize == 0)
|
||||
fontSize = Player.GetPropertyInt("osd-font-size");
|
||||
|
||||
Player.Command("show-text \"${osd-ass-cc/0}{\\\\fs" + fontSize +
|
||||
"}${osd-ass-cc/1}" + text + "\" " + duration);
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
public static void PlaylistAdd(int value)
|
||||
{
|
||||
int pos = Player.PlaylistPos;
|
||||
int count = Player.GetPropertyInt("playlist-count");
|
||||
|
||||
if (count < 2)
|
||||
return;
|
||||
|
||||
pos += value;
|
||||
|
||||
if (pos < 0)
|
||||
pos = count - 1;
|
||||
|
||||
if (pos > count - 1)
|
||||
pos = 0;
|
||||
|
||||
Player.SetPropertyInt("playlist-pos", pos);
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
public void ShowProgress()
|
||||
{
|
||||
TimeSpan position = TimeSpan.FromSeconds(Player.GetPropertyDouble("time-pos"));
|
||||
TimeSpan duration = TimeSpan.FromSeconds(Player.GetPropertyDouble("duration"));
|
||||
|
||||
string text = FormatTime(position.TotalMinutes) + ":" +
|
||||
FormatTime(position.Seconds) + " / " +
|
||||
FormatTime(duration.TotalMinutes) + ":" +
|
||||
FormatTime(duration.Seconds) + " " +
|
||||
DateTime.Now.ToString("H:mm dddd d MMMM", CultureInfo.InvariantCulture);
|
||||
|
||||
Player.CommandV("show-text", text, "5000");
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
public static void CycleAudio()
|
||||
{
|
||||
Player.UpdateExternalTracks();
|
||||
|
||||
lock (Player.MediaTracksLock)
|
||||
{
|
||||
MediaTrack[] tracks = Player.MediaTracks.Where(track => track.Type == "a").ToArray();
|
||||
|
||||
if (tracks.Length < 1)
|
||||
{
|
||||
Player.CommandV("show-text", "No audio tracks");
|
||||
return;
|
||||
}
|
||||
|
||||
int aid = Player.GetPropertyInt("aid");
|
||||
|
||||
if (tracks.Length > 1)
|
||||
{
|
||||
if (++aid > tracks.Length)
|
||||
aid = 1;
|
||||
|
||||
Player.SetPropertyInt("aid", aid);
|
||||
}
|
||||
|
||||
Player.CommandV("show-text", aid + "/" + tracks.Length + ": " + tracks[aid - 1].Text[3..], "5000");
|
||||
}
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
public static void CycleSubtitles()
|
||||
{
|
||||
Player.UpdateExternalTracks();
|
||||
|
||||
lock (Player.MediaTracksLock)
|
||||
{
|
||||
MediaTrack[] tracks = Player.MediaTracks.Where(track => track.Type == "s").ToArray();
|
||||
|
||||
if (tracks.Length < 1)
|
||||
{
|
||||
Player.CommandV("show-text", "No subtitles");
|
||||
return;
|
||||
}
|
||||
|
||||
int sid = Player.GetPropertyInt("sid");
|
||||
|
||||
if (tracks.Length > 1)
|
||||
{
|
||||
if (++sid > tracks.Length)
|
||||
sid = 0;
|
||||
|
||||
Player.SetPropertyInt("sid", sid);
|
||||
}
|
||||
|
||||
if (sid == 0)
|
||||
Player.CommandV("show-text", "No subtitle");
|
||||
else
|
||||
Player.CommandV("show-text", sid + "/" + tracks.Length + ": " + tracks[sid - 1].Text[3..], "5000");
|
||||
}
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
public static void PlaylistFirst()
|
||||
{
|
||||
if (Player.PlaylistPos != 0)
|
||||
Player.SetPropertyInt("playlist-pos", 0);
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
public static void PlaylistLast()
|
||||
{
|
||||
int count = Player.GetPropertyInt("playlist-count");
|
||||
|
||||
if (Player.PlaylistPos < count - 1)
|
||||
Player.SetPropertyInt("playlist-pos", count - 1);
|
||||
}
|
||||
}
|
||||
41
src/MpvNet/ExtensionLoader.cs
Normal file
41
src/MpvNet/ExtensionLoader.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
using MpvNet.ExtensionMethod;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class ExtensionLoader
|
||||
{
|
||||
public event Action<Exception>? UnhandledException;
|
||||
|
||||
readonly List<object?> _refs = new();
|
||||
|
||||
void LoadDll(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Assembly asm = Assembly.LoadFile(path);
|
||||
var type = asm.GetTypes().Where(typeof(IExtension).IsAssignableFrom).First();
|
||||
_refs.Add(Activator.CreateInstance(type));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnhandledException?.Invoke(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFolder(string path)
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
foreach (string dir in Directory.GetDirectories(path))
|
||||
LoadDll(dir.AddSep() + Path.GetFileName(dir) + ".dll");
|
||||
}
|
||||
}
|
||||
|
||||
public interface IExtension
|
||||
{
|
||||
}
|
||||
7
src/MpvNet/ExtensionMethod/ObjectExtension.cs
Normal file
7
src/MpvNet/ExtensionMethod/ObjectExtension.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
namespace MpvNet.ExtensionMethod;
|
||||
|
||||
public static class ObjectExtension
|
||||
{
|
||||
public static string ToStringEx(this object instance) => instance?.ToString() ?? "";
|
||||
}
|
||||
67
src/MpvNet/ExtensionMethod/PathStringExtension.cs
Normal file
67
src/MpvNet/ExtensionMethod/PathStringExtension.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
namespace MpvNet.ExtensionMethod;
|
||||
|
||||
public static class PathStringExtension
|
||||
{
|
||||
public static string Ext(this string filepath) => filepath.Ext(false);
|
||||
|
||||
public static string Ext(this string filepath, bool includeDot)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filepath))
|
||||
return "";
|
||||
|
||||
char[] chars = filepath.ToCharArray();
|
||||
|
||||
for (int x = filepath.Length - 1; x >= 0; x--)
|
||||
{
|
||||
if (chars[x] == Path.DirectorySeparatorChar)
|
||||
return "";
|
||||
|
||||
if (chars[x] == '.')
|
||||
return filepath.Substring(x + (includeDot ? 0 : 1)).ToLowerInvariant();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string FileName(this string instance)
|
||||
{
|
||||
if (string.IsNullOrEmpty(instance))
|
||||
return "";
|
||||
|
||||
int index = instance.LastIndexOf('\\');
|
||||
|
||||
if (index > -1)
|
||||
return instance.Substring(index + 1);
|
||||
|
||||
index = instance.LastIndexOf('/');
|
||||
|
||||
if (index > -1)
|
||||
return instance.Substring(index + 1);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static string ShortPath(this string instance, int maxLength)
|
||||
{
|
||||
if (string.IsNullOrEmpty(instance))
|
||||
return "";
|
||||
|
||||
if (instance.Length > maxLength && instance.Substring(1, 2) == ":\\")
|
||||
instance = instance[..3] + "...\\" + instance.FileName();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Ensure trailing directory separator char
|
||||
public static string AddSep(this string instance)
|
||||
{
|
||||
if (string.IsNullOrEmpty(instance))
|
||||
return "";
|
||||
|
||||
if (!instance.EndsWith(Path.DirectorySeparatorChar.ToString()))
|
||||
instance = instance + Path.DirectorySeparatorChar;
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
30
src/MpvNet/ExtensionMethod/StringExtension.cs
Normal file
30
src/MpvNet/ExtensionMethod/StringExtension.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace MpvNet.ExtensionMethod;
|
||||
|
||||
public static class StringExtension
|
||||
{
|
||||
public static string ToUpperEx(this string instance) => (instance != null) ? instance.ToUpperInvariant() : "";
|
||||
|
||||
public static string ToLowerEx(this string instance) => (instance != null) ? instance.ToLowerInvariant() : "";
|
||||
|
||||
public static string TrimEx(this string? instance) => (instance == null) ? "" : instance.Trim();
|
||||
|
||||
public static int ToInt(this string instance, int defaultValue = 0)
|
||||
{
|
||||
if (int.TryParse(instance, out int result))
|
||||
return result;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static float ToFloat(this string instance) =>
|
||||
float.Parse(instance.Replace(",", "."), NumberStyles.Float, CultureInfo.InvariantCulture);
|
||||
|
||||
public static bool ContainsEx(this string? instance, string? value) =>
|
||||
!string.IsNullOrEmpty(instance) && !string.IsNullOrEmpty(value) && instance.Contains(value);
|
||||
|
||||
public static bool StartsWithEx(this string? instance, string? value) =>
|
||||
(instance != null && value != null) && instance.StartsWith(value);
|
||||
}
|
||||
20
src/MpvNet/FileTypes.cs
Normal file
20
src/MpvNet/FileTypes.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
using MpvNet.ExtensionMethod;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public static class FileTypes
|
||||
{
|
||||
public static string[] Video { get; set; } = "mkv mp4 avi mov flv mpg webm wmv ts vob 264 265 asf avc avs dav h264 h265 hevc m2t m2ts m2v m4v mpeg mpv mts vpy y4m".Split(' ');
|
||||
public static string[] Audio { get; set; } = "mp3 flac m4a mka mp2 ogg opus aac ac3 dts dtshd dtshr dtsma eac3 mpa mpc thd w64 wav".Split(' ');
|
||||
public static string[] Image { get; set; } = { "jpg", "bmp", "png", "gif", "webp" };
|
||||
public static string[] Subtitle { get; } = { "srt", "ass", "idx", "sub", "sup", "ttxt", "txt", "ssa", "smi", "mks" };
|
||||
|
||||
public static bool IsImage(string extension) => Image.Contains(extension);
|
||||
public static bool IsAudio(string extension) => Audio.Contains(extension);
|
||||
|
||||
public static bool IsMedia(string extension) =>
|
||||
Video.Contains(extension) || Audio.Contains(extension) || Image.Contains(extension);
|
||||
|
||||
public static IEnumerable<string> GetMediaFiles(IEnumerable<string> files) => files.Where(i => IsMedia(i.Ext()));
|
||||
}
|
||||
10
src/MpvNet/Folder.cs
Normal file
10
src/MpvNet/Folder.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
using MpvNet.ExtensionMethod;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class Folder
|
||||
{
|
||||
public static string Startup { get; } = Path.GetDirectoryName(Environment.ProcessPath)!.AddSep();
|
||||
public static string AppData { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).AddSep();
|
||||
}
|
||||
11
src/MpvNet/Global.cs
Normal file
11
src/MpvNet/Global.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public static class Global
|
||||
{
|
||||
public static readonly string BR = Environment.NewLine;
|
||||
public static readonly string BR2 = Environment.NewLine + Environment.NewLine;
|
||||
public static readonly MainPlayer Player = new MainPlayer();
|
||||
public static readonly MainPlayer Core = Player; // backward compatibility
|
||||
public static readonly AppClass App = new AppClass();
|
||||
}
|
||||
8
src/MpvNet/GlobalUsings.cs
Normal file
8
src/MpvNet/GlobalUsings.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Diagnostics;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
|
||||
global using static MpvNet.Global;
|
||||
20
src/MpvNet/Help/FileHelp.cs
Normal file
20
src/MpvNet/Help/FileHelp.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
namespace MpvNet.Help;
|
||||
|
||||
public static class FileHelp
|
||||
{
|
||||
public static void Delete(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Terminal.WriteError("Failed to delete file:" + BR + path + BR + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadTextFile(string path) => File.Exists(path) ? File.ReadAllText(path) : "";
|
||||
}
|
||||
26
src/MpvNet/Help/MpvHelp.cs
Normal file
26
src/MpvNet/Help/MpvHelp.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
namespace MpvNet.Help;
|
||||
|
||||
public class MpvHelp
|
||||
{
|
||||
public static string? WM_APPCOMMAND_to_mpv_key(int value) => value switch
|
||||
{
|
||||
5 => "SEARCH", // BROWSER_SEARCH
|
||||
6 => "FAVORITES", // BROWSER_FAVORITES
|
||||
7 => "HOMEPAGE", // BROWSER_HOME
|
||||
15 => "MAIL", // LAUNCH_MAIL
|
||||
33 => "PRINT", // PRINT
|
||||
11 => "NEXT", // MEDIA_NEXTTRACK
|
||||
12 => "PREV", // MEDIA_PREVIOUSTRACK
|
||||
13 => "STOP", // MEDIA_STOP
|
||||
14 => "PLAYPAUSE", // MEDIA_PLAY_PAUSE
|
||||
46 => "PLAY", // MEDIA_PLAY
|
||||
47 => "PAUSE", // MEDIA_PAUSE
|
||||
48 => "RECORD", // MEDIA_RECORD
|
||||
49 => "FORWARD", // MEDIA_FAST_FORWARD
|
||||
50 => "REWIND", // MEDIA_REWIND
|
||||
51 => "CHANNEL_UP", // MEDIA_CHANNEL_UP
|
||||
52 => "CHANNEL_DOWN", // MEDIA_CHANNEL_DOWN
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
15
src/MpvNet/Help/ProcessHelp.cs
Normal file
15
src/MpvNet/Help/ProcessHelp.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace MpvNet.Help;
|
||||
|
||||
public static class ProcessHelp
|
||||
{
|
||||
public static void Execute(string file, string arguments = "", bool shellExecute = false)
|
||||
{
|
||||
using Process proc = new Process();
|
||||
proc.StartInfo.FileName = file;
|
||||
proc.StartInfo.Arguments = arguments;
|
||||
proc.StartInfo.UseShellExecute = shellExecute;
|
||||
proc.Start();
|
||||
}
|
||||
|
||||
public static void ShellExecute(string file, string arguments = "") => Execute(file, arguments, true);
|
||||
}
|
||||
16
src/MpvNet/Help/StringHelp.cs
Normal file
16
src/MpvNet/Help/StringHelp.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace MpvNet.Help;
|
||||
|
||||
public static class StringHelp
|
||||
{
|
||||
public static string GetMD5Hash(string txt)
|
||||
{
|
||||
using MD5 md5 = MD5.Create();
|
||||
byte[] inputBuffer = Encoding.UTF8.GetBytes(txt);
|
||||
byte[] hashBuffer = md5.ComputeHash(inputBuffer);
|
||||
return BitConverter.ToString(md5.ComputeHash(inputBuffer)).Replace("-", "");
|
||||
}
|
||||
}
|
||||
21
src/MpvNet/Help/TaskHelp.cs
Normal file
21
src/MpvNet/Help/TaskHelp.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MpvNet.Help;
|
||||
|
||||
public class TaskHelp
|
||||
{
|
||||
public static void Run(Action action)
|
||||
{
|
||||
Task.Run(() => {
|
||||
try
|
||||
{
|
||||
action.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Terminal.WriteError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
74
src/MpvNet/InputConf.cs
Normal file
74
src/MpvNet/InputConf.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
using MpvNet.Help;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class InputConf
|
||||
{
|
||||
string? _content;
|
||||
bool? _hasMenu;
|
||||
|
||||
public InputConf(string path) { Path = path; }
|
||||
|
||||
public string Path { get; }
|
||||
|
||||
public string Content
|
||||
{
|
||||
get => _content ??= FileHelp.ReadTextFile(Path);
|
||||
set => _content = value;
|
||||
}
|
||||
|
||||
public bool HasMenu => _hasMenu ??= Content.Contains("#menu:");
|
||||
|
||||
public List<Binding> GetMenuBindings()
|
||||
{
|
||||
var confbindings = InputHelp.Parse(Content);
|
||||
|
||||
if (HasMenu)
|
||||
return confbindings;
|
||||
|
||||
var defaultBindings = InputHelp.GetDefaults();
|
||||
|
||||
foreach (Binding defaultBinding in defaultBindings)
|
||||
foreach (Binding confBinding in confbindings)
|
||||
if (defaultBinding.Input == confBinding.Input &&
|
||||
defaultBinding.Command != confBinding.Command)
|
||||
{
|
||||
defaultBinding.Input = "";
|
||||
}
|
||||
|
||||
foreach (Binding defaultBinding in defaultBindings)
|
||||
foreach (Binding confBinding in confbindings)
|
||||
if (defaultBinding.Command == confBinding.Command)
|
||||
defaultBinding.Input = confBinding.Input;
|
||||
|
||||
return defaultBindings;
|
||||
}
|
||||
|
||||
public string GetContent()
|
||||
{
|
||||
if (HasMenu)
|
||||
return Content;
|
||||
else
|
||||
{
|
||||
var defaults = InputHelp.GetDefaults();
|
||||
var removed = new List<Binding>();
|
||||
var conf = InputHelp.Parse(Content);
|
||||
|
||||
foreach (Binding defaultBinding in defaults)
|
||||
foreach (Binding confBinding in conf)
|
||||
if (defaultBinding.Command == confBinding.Command &&
|
||||
defaultBinding.Comment == confBinding.Comment)
|
||||
{
|
||||
defaultBinding.Input = confBinding.Input;
|
||||
removed.Add(confBinding);
|
||||
}
|
||||
|
||||
foreach (Binding binding in removed)
|
||||
conf.Remove(binding);
|
||||
|
||||
defaults.AddRange(conf);
|
||||
return InputHelp.ConvertToString(defaults);
|
||||
}
|
||||
}
|
||||
}
|
||||
376
src/MpvNet/InputHelp.cs
Normal file
376
src/MpvNet/InputHelp.cs
Normal file
@@ -0,0 +1,376 @@
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public static class InputHelp
|
||||
{
|
||||
public static List<Binding> GetDefaults()
|
||||
{
|
||||
List<Binding> bindings = new List<Binding>()
|
||||
{
|
||||
new (_("File"), _("Open Files..."), "script-message-to mpvnet open-files", "o"),
|
||||
new (_("File"), _("Open URL or file from clipboard"), "script-message-to mpvnet open-clipboard", "V"),
|
||||
new (_("File"), _("Open DVD/Blu-ray Drive/Folder..."), "script-message-to mpvnet open-optical-media"),
|
||||
new (_("File"), "-"),
|
||||
new (_("File"), _("Load external audio files..."), "script-message-to mpvnet load-audio", "Alt+a"),
|
||||
new (_("File"), _("Load external subtitle files..."), "script-message-to mpvnet load-sub", "Alt+s"),
|
||||
new (_("File"), "-"),
|
||||
new (_("File"), _("Add files to playlist..."), "script-message-to mpvnet open-files append"),
|
||||
new (_("File"), "-"),
|
||||
new (_("File"), _("Recent")),
|
||||
new (_("Playback"), _("Play/Pause"), "script-message-to mpvnet play-pause", "Space"),
|
||||
new (_("Playback"), _("Stop"), "stop", "Ctrl+s"),
|
||||
new (_("Navigate"), _("Previous File"), "playlist-prev", "F11"),
|
||||
new (_("Navigate"), _("Next File"), "playlist-next", "F12"),
|
||||
new (_("Navigate"), "-"),
|
||||
new (_("Navigate"), _("Next Chapter"), "add chapter 1", "PGUP"),
|
||||
new (_("Navigate"), _("Previous Chapter"), "add chapter -1", "PGDWN"),
|
||||
new (_("Navigate"), "-"),
|
||||
new (_("Navigate"), _("Jump To Next Frame"), "frame-step", "."),
|
||||
new (_("Navigate"), _("Jump To Previous Frame"), "frame-back-step", ","),
|
||||
new (_("Navigate"), "-"),
|
||||
new (_("Navigate"), _("Jump 5 sec forward"), "seek 5", "Right"),
|
||||
new (_("Navigate"), _("Jump 5 sec backward"), "seek -5", "Left"),
|
||||
new (_("Navigate"), "-"),
|
||||
new (_("Navigate"), _("Jump 30 sec forward"), "seek 30", "Up"),
|
||||
new (_("Navigate"), _("Jump 30 sec backward"), "seek -30", "Down"),
|
||||
new (_("Navigate"), "-"),
|
||||
new (_("Navigate"), _("Jump 5 min forward"), "seek 300", "Ctrl+Right"),
|
||||
new (_("Navigate"), _("Jump 5 min backward"), "seek -300", "Ctrl+Left"),
|
||||
new (_("Navigate"), "-"),
|
||||
new (_("Navigate"), _("Titles")),
|
||||
new (_("Navigate"), _("Chapters")),
|
||||
new (_("Pan & Scan"), _("Decrease Size"), "add video-zoom -0.1", "Ctrl+-"),
|
||||
new (_("Pan & Scan"), _("Increase Size"), "add video-zoom 0.1", "Ctrl++"),
|
||||
new (_("Pan & Scan"), "-"),
|
||||
new (_("Pan & Scan"), _("Move Left"), "add video-pan-x -0.01", "Ctrl+KP4"),
|
||||
new (_("Pan & Scan"), _("Move Right"), "add video-pan-x 0.01", "Ctrl+KP6"),
|
||||
new (_("Pan & Scan"), "-"),
|
||||
new (_("Pan & Scan"), _("Move Up"), "add video-pan-y -0.01", "Ctrl+KP8"),
|
||||
new (_("Pan & Scan"), _("Move Down"), "add video-pan-y 0.01", "Ctrl+KP2"),
|
||||
new (_("Pan & Scan"), "-"),
|
||||
new (_("Pan & Scan"), _("Decrease Height"), "add panscan -0.1", "w"),
|
||||
new (_("Pan & Scan"), _("Increase Height"), "add panscan 0.1", "W"),
|
||||
new (_("Pan & Scan"), "-"),
|
||||
new (_("Pan & Scan"), _("Reset"), "set video-zoom 0; set video-pan-x 0; set video-pan-y 0", "Ctrl+BS"),
|
||||
new (_("Video"), _("Decrease Contrast"), "add contrast -1", "Ctrl+1"),
|
||||
new (_("Video"), _("Increase Contrast"), "add contrast 1", "Ctrl+2"),
|
||||
new (_("Video"), "-"),
|
||||
new (_("Video"), _("Decrease Brightness"), "add brightness -1", "Ctrl+3"),
|
||||
new (_("Video"), _("Increase Brightness"), "add brightness 1", "Ctrl+4"),
|
||||
new (_("Video"), "-"),
|
||||
new (_("Video"), _("Decrease Gamma"), "add gamma -1", "Ctrl+5"),
|
||||
new (_("Video"), _("Increase Gamma"), "add gamma 1", "Ctrl+6"),
|
||||
new (_("Video"), "-"),
|
||||
new (_("Video"), _("Decrease Saturation"), "add saturation -1", "Ctrl+7"),
|
||||
new (_("Video"), _("Increase Saturation"), "add saturation 1", "Ctrl+8"),
|
||||
new (_("Video"), "-"),
|
||||
new (_("Video"), _("Take Screenshot"), "async screenshot", "s"),
|
||||
new (_("Video"), _("Take Screenshot without subtitles"), "async screenshot video", "S"),
|
||||
new (_("Video"), _("Toggle Deinterlace"), "cycle deinterlace", "d"),
|
||||
new (_("Video"), _("Cycle Aspect Ratio"), "cycle-values video-aspect 16:9 4:3 2.35:1 -1", "a"),
|
||||
new (_("Video"), _("Rotate Video"), "cycle-values video-rotate 90 180 270 0", "Ctrl+r"),
|
||||
new (_("Audio"), _("Cycle/Next"), "cycle audio", "KP7"),
|
||||
new (_("Audio"), "-"),
|
||||
new (_("Audio"), _("Delay +0.1"), "add audio-delay 0.1", "Ctrl+d"),
|
||||
new (_("Audio"), _("Delay -0.1"), "add audio-delay -0.1", "Ctrl+D"),
|
||||
new (_("Subtitle"), _("Cycle/Next"), "cycle sub", "KP8"),
|
||||
new (_("Subtitle"), _("Toggle Visibility"), "cycle sub-visibility", "v"),
|
||||
new (_("Subtitle"), "-"),
|
||||
new (_("Subtitle"), _("Delay -0.1"), "add sub-delay -0.1", "z"),
|
||||
new (_("Subtitle"), _("Delay +0.1"), "add sub-delay 0.1", "Z"),
|
||||
new (_("Subtitle"), "-"),
|
||||
new (_("Subtitle"), _("Move Up"), "add sub-pos -1", "r"),
|
||||
new (_("Subtitle"), _("Move Down"), "add sub-pos 1", "R"),
|
||||
new (_("Subtitle"), "-"),
|
||||
new (_("Subtitle"), _("Decrease Subtitle Font Size"), "add sub-scale -0.1", "F"),
|
||||
new (_("Subtitle"), _("Increase Subtitle Font Size"), "add sub-scale 0.1", "G"),
|
||||
new (_("Subtitle"), "-"),
|
||||
new (_("Subtitle > Advanced"), _("Toggle overriding SSA/ASS styles with normal styles"), "cycle-values sub-ass-override force no", "u"),
|
||||
new ("", _("Track")),
|
||||
new (_("Volume"), _("Up"), "add volume 2", "+"),
|
||||
new (_("Volume"), _("Down"), "add volume -2", "-"),
|
||||
new (_("Volume"), "-"),
|
||||
new (_("Volume"), _("Mute"), "cycle mute", "m"),
|
||||
new (_("Speed"), _("-10%"), "multiply speed 1/1.1", "["),
|
||||
new (_("Speed"), _("+10%"), "multiply speed 1.1", "]"),
|
||||
new (_("Speed"), "-"),
|
||||
new (_("Speed"), _("Half"), "multiply speed 0.5", "{"),
|
||||
new (_("Speed"), _("Double"), "multiply speed 2.0", "}"),
|
||||
new (_("Speed"), "-"),
|
||||
new (_("Speed"), _("Reset"), "set speed 1", "BS"),
|
||||
new (_("View"), _("Fullscreen"), "cycle fullscreen", "Enter"),
|
||||
new (_("View > Zoom"), _("Enlarge"), "script-message-to mpvnet scale-window 1.2", "Alt++"),
|
||||
new (_("View > Zoom"), _("Shrink"), "script-message-to mpvnet scale-window 0.8", "Alt+-"),
|
||||
new (_("View > Zoom"), "-"),
|
||||
new (_("View > Zoom"), _("50 %"), "script-message-to mpvnet window-scale 0.5", "Alt+0"),
|
||||
new (_("View > Zoom"), _("100 %"), "script-message-to mpvnet window-scale 1.0", "Alt+1"),
|
||||
new (_("View > Zoom"), _("200 %"), "script-message-to mpvnet window-scale 2.0", "Alt+2"),
|
||||
new (_("View > Zoom"), _("300 %"), "script-message-to mpvnet window-scale 3.0", "Alt+3"),
|
||||
new (_("View > Move"), _("Left"), "script-message-to mpvnet move-window left", "Alt+Left"),
|
||||
new (_("View > Move"), _("Right"), "script-message-to mpvnet move-window right", "Alt+Right"),
|
||||
new (_("View > Move"), _("Top"), "script-message-to mpvnet move-window top", "Alt+Up"),
|
||||
new (_("View > Move"), _("Bottom"), "script-message-to mpvnet move-window bottom", "Alt+Down"),
|
||||
new (_("View > Move"), _("Center"), "script-message-to mpvnet move-window center", "Alt+BS"),
|
||||
new (_("View"), _("Show Profiles"), "script-message-to mpvnet show-profiles", "Ctrl+P"),
|
||||
new (_("View"), _("Toggle Border"), "cycle border", "b"),
|
||||
new (_("View"), _("Toggle On Top"), "cycle ontop", "Ctrl+t"),
|
||||
new (_("View"), _("Toggle Statistics"), "script-binding stats/display-stats-toggle", "t"),
|
||||
new (_("View"), _("Toggle OSC Visibility"), "script-binding osc/visibility", "Del"),
|
||||
new (_("View"), _("Show Media Info On-Screen"), "script-message-to mpvnet show-media-info osd", "i"),
|
||||
new (_("View"), _("Show Media Info Message Box"), "script-message-to mpvnet show-media-info msgbox", "Ctrl+m"),
|
||||
new (_("View"), _("Show Progress"), "show-progress", "p"),
|
||||
new (_("View > Advanced"), _("Show Console"), "script-binding console/enable", "`"),
|
||||
new (_("View > Advanced"), _("Show Audio Devices"), "script-message-to mpvnet show-audio-devices"),
|
||||
new (_("View > Advanced"), _("Show Commands"), "script-message-to mpvnet show-commands", "C"),
|
||||
new (_("View > Advanced"), _("Show Demuxers"), "script-message-to mpvnet show-demuxers"),
|
||||
new (_("View > Advanced"), _("Show Decoders"), "script-message-to mpvnet show-decoders"),
|
||||
new ("", _("Profile")),
|
||||
new (_("Settings"), _("Show Config Editor"), "script-message-to mpvnet show-conf-editor", "Ctrl+,"),
|
||||
new (_("Settings"), _("Show Input Editor"), "script-message-to mpvnet show-input-editor", "Ctrl+i"),
|
||||
new (_("Settings"), _("Open Config Folder"), "script-message-to mpvnet open-conf-folder", "Ctrl+f"),
|
||||
new (_("Settings > Setup"), _("Register video file associations"), "script-message-to mpvnet reg-file-assoc video"),
|
||||
new (_("Settings > Setup"), _("Register audio file associations"), "script-message-to mpvnet reg-file-assoc audio"),
|
||||
new (_("Settings > Setup"), _("Register image file associations"), "script-message-to mpvnet reg-file-assoc image"),
|
||||
new (_("Settings > Setup"), _("Unregister file associations"), "script-message-to mpvnet reg-file-assoc unreg"),
|
||||
new (_("Tools"), _("Set/clear A-B loop points"), "ab-loop", "l"),
|
||||
new (_("Tools"), _("Toggle infinite file looping"), "cycle-values loop-file inf no", "L"),
|
||||
new (_("Tools"), _("Shuffle Playlist"), "playlist-shuffle"),
|
||||
new (_("Tools"), _("Toggle Hardware Decoding"), "cycle-values hwdec auto no", "Ctrl+h"),
|
||||
new (_("Tools"), _("Exit"), "quit", "Esc"),
|
||||
new (_("Tools"), _("Exit Watch Later"), "quit-watch-later", "Q"),
|
||||
new (_("Tools"), _("Show current file in File Explorer"), @"run powershell -command ""explorer.exe '/select,' ( \""${path}\"" -replace '/', '\\' )""", "e"),
|
||||
new (_("Help"), _("Website mpv"), "script-message-to mpvnet shell-execute https://mpv.io"),
|
||||
new (_("Help"), _("Website mpv.net"), "script-message-to mpvnet shell-execute https://github.com/mpvnet-player/mpv.net"),
|
||||
new (_("Help"), "-"),
|
||||
new (_("Help"), _("Manual mpv"), "script-message-to mpvnet shell-execute https://mpv.io/manual/stable"),
|
||||
new (_("Help"), _("Manual mpv.net"), "script-message-to mpvnet shell-execute https://github.com/mpvnet-player/mpvnet/blob/master/docs/manual.md"),
|
||||
new (_("Help"), "-"),
|
||||
new (_("Help"), _("About mpv.net"), "script-message-to mpvnet show-about"),
|
||||
new ("", _("Exit"), "quit", "Esc"),
|
||||
new ("", "", "quit", "q", _("Exit")),
|
||||
new ("", "", "script-message-to mpvnet show-menu", "MBTN_Right", _("Show Menu")),
|
||||
new ("", "", "quit", "Power", _("Exit")),
|
||||
new ("", "", "cycle pause", "Play", _("Play/Pause")),
|
||||
new ("", "", "cycle pause", "Pause", _("Play/Pause")),
|
||||
new ("", "", "cycle pause", "PlayPause", _("Play/Pause")),
|
||||
new ("", "", "cycle pause", "MBTN_Mid", _("Play/Pause")),
|
||||
new ("", "", "stop", "Stop", _("Stop")),
|
||||
new ("", "", "seek 60", "Forward", _("Forward")),
|
||||
new ("", "", "seek -60", "Rewind", _("Backward")),
|
||||
new ("", "", "add volume 2", "Wheel_Up", _("Volume Up")),
|
||||
new ("", "", "add volume -2", "Wheel_Down", _("Volume Down")),
|
||||
new ("", "", "add volume 2", "Wheel_Right", _("Volume Up")),
|
||||
new ("", "", "add volume -2", "Wheel_Left", _("Volume Down")),
|
||||
new ("", "", "playlist-prev", "Prev", _("Previous File")),
|
||||
new ("", "", "playlist-next", "Next", _("Next File")),
|
||||
new ("", "", "playlist-prev", "MBTN_Back", _("Previous File")),
|
||||
new ("", "", "playlist-next", "MBTN_Forward", _("Next File")),
|
||||
new ("", "", "playlist-prev", "<", _("Previous File")),
|
||||
new ("", "", "playlist-next", ">", _("Next File")),
|
||||
new ("", "", "ignore", "MBTN_Left", _("Ignore left mouse butten")),
|
||||
new ("", "", "cycle fullscreen", "f", _("Fullscreen")),
|
||||
new ("", "", "cycle fullscreen", "MBTN_Left_DBL", _("Fullscreen")),
|
||||
new ("", "", "cycle fullscreen", "KP_Enter", _("Fullscreen")),
|
||||
new ("", "", "no-osd seek 1 exact", "Shift+Right", _("Seek Forward")),
|
||||
new ("", "", "no-osd seek -1 exact", "Shift+Left", _("Seek Backward")),
|
||||
new ("", "", "no-osd seek 5 exact", "Shift+Up", _("Seek Forward")),
|
||||
new ("", "", "no-osd seek -5 exact", "Shift+Down", _("Seek Backward")),
|
||||
new ("", "", "revert-seek", "Shift+BS", _("Undo previous (or marked) seek")),
|
||||
new ("", "", "revert-seek mark", "Shift+Ctrl+BS", _("Mark position for revert-seek")),
|
||||
new ("", "", "no-osd sub-seek -1", "Ctrl+Shift+Left", _("Seek to previous subtitle")),
|
||||
new ("", "", "no-osd sub-seek 1", "Ctrl+Shift+Right", _("Seek to next subtitle")),
|
||||
new ("", "", "no-osd seek 5", "Ctrl+Wheel_Up", _("Seek Forward")),
|
||||
new ("", "", "no-osd seek -5", "Ctrl+Wheel_Down", _("Seek Backward")),
|
||||
//new (_("Command Palette"), _("Commands"), "script-message-to mpvnet show-command-palette", "F1"),
|
||||
};
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public static string ConvertToString(List<Binding> bindings)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
foreach (Binding binding in bindings)
|
||||
{
|
||||
string cmd = binding.Command.Trim();
|
||||
string input = binding.Input.Trim();
|
||||
string comment = binding.IsMenu ? "menu: " + binding.Path : binding.Comment.Trim();
|
||||
input = input == "" ? "_" : input;
|
||||
string line = input.PadRight(10) + " ";
|
||||
line += cmd == "" ? "ignore" : cmd;
|
||||
|
||||
if (comment != "")
|
||||
line = line.PadRight(40) + " # " + comment;
|
||||
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static List<Binding> Parse(string content)
|
||||
{
|
||||
var bindings = new List<Binding>();
|
||||
|
||||
if (string.IsNullOrEmpty(content))
|
||||
return bindings;
|
||||
|
||||
foreach (string it in content.Split('\r', '\n'))
|
||||
{
|
||||
string line = it.Trim();
|
||||
|
||||
if (line.StartsWith("#") || !line.Contains(' '))
|
||||
continue;
|
||||
|
||||
Binding binding = new Binding();
|
||||
binding.Input = line[..line.IndexOf(" ")];
|
||||
|
||||
if (binding.Input == "_")
|
||||
binding.Input = "";
|
||||
|
||||
if (binding.Input.Contains("CTRL+"))
|
||||
binding.Input = binding.Input.Replace("CTRL+", "Ctrl+");
|
||||
if (binding.Input.Contains("ctrl+"))
|
||||
binding.Input = binding.Input.Replace("ctrl+", "Ctrl+");
|
||||
|
||||
if (binding.Input.Contains("SHIFT+"))
|
||||
binding.Input = binding.Input.Replace("SHIFT+", "Shift+");
|
||||
if (binding.Input.Contains("shift+"))
|
||||
binding.Input = binding.Input.Replace("shift+", "Shift+");
|
||||
|
||||
if (binding.Input.Contains("ALT+"))
|
||||
binding.Input = binding.Input.Replace("ALT+", "Alt+");
|
||||
if (binding.Input.Contains("alt+"))
|
||||
binding.Input = binding.Input.Replace("alt+", "Alt+");
|
||||
|
||||
line = line[(line.IndexOf(" ") + 1)..];
|
||||
|
||||
if (line.Contains("#menu:"))
|
||||
{
|
||||
binding.Path = line[(line.IndexOf("#menu:") + 6)..].Trim();
|
||||
binding.Comment = binding.Path;
|
||||
binding.IsMenu = true;
|
||||
line = line[..line.IndexOf("#menu:")];
|
||||
|
||||
if (binding.Path.Contains(';'))
|
||||
binding.Path = binding.Path[(binding.Path.IndexOf(";") + 1)..].Trim();
|
||||
}
|
||||
else if (line.Contains('#'))
|
||||
{
|
||||
binding.Comment = line[(line.IndexOf("#") + 1)..].Trim();
|
||||
line = line[..line.IndexOf("#")];
|
||||
}
|
||||
|
||||
binding.Command = line.Trim();
|
||||
|
||||
if (binding.Command.ToLower() == "ignore")
|
||||
binding.Command = "";
|
||||
|
||||
bindings.Add(binding);
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public static List<Binding> GetReducedBindings(List<Binding> bindings)
|
||||
{
|
||||
var defaultBindings = GetDefaults();
|
||||
var removedBindings = new List<Binding>();
|
||||
|
||||
foreach (Binding defaultBinding in defaultBindings)
|
||||
{
|
||||
foreach (Binding binding in bindings)
|
||||
{
|
||||
if (defaultBinding.Input == binding.Input &&
|
||||
defaultBinding.Command == binding.Command &&
|
||||
defaultBinding.Comment == binding.Comment)
|
||||
{
|
||||
removedBindings.Add(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Binding binding in bindings.ToArray())
|
||||
if (removedBindings.Contains(binding))
|
||||
bindings.Remove(binding);
|
||||
|
||||
return bindings.ToList();
|
||||
}
|
||||
|
||||
public static List<Binding> GetEditorBindings(string content)
|
||||
{
|
||||
var defaults = GetDefaults();
|
||||
var conf = Parse(content);
|
||||
var removed = new List<Binding>();
|
||||
|
||||
foreach (Binding defaultBinding in defaults)
|
||||
{
|
||||
foreach (Binding confBinding in conf)
|
||||
{
|
||||
if (defaultBinding.Command == confBinding.Command &&
|
||||
defaultBinding.Comment == confBinding.Comment)
|
||||
{
|
||||
defaultBinding.Input = confBinding.Input;
|
||||
removed.Add(confBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Binding binding in removed)
|
||||
conf.Remove(binding);
|
||||
|
||||
defaults.AddRange(conf);
|
||||
return defaults;
|
||||
}
|
||||
|
||||
public static List<Binding> GetBindingsFromContent(string content)
|
||||
{
|
||||
var bindings = new List<Binding>();
|
||||
|
||||
if (!string.IsNullOrEmpty(content))
|
||||
{
|
||||
foreach (string line in content.Split('\r', '\n'))
|
||||
{
|
||||
string value = line.Trim();
|
||||
|
||||
if (value.StartsWith("#"))
|
||||
continue;
|
||||
|
||||
if (!value.Contains(' '))
|
||||
continue;
|
||||
|
||||
Binding binding = new Binding();
|
||||
binding.Input = value[..value.IndexOf(" ")];
|
||||
|
||||
if (binding.Input == "_")
|
||||
binding.Input = "";
|
||||
|
||||
value = value[(value.IndexOf(" ") + 1)..];
|
||||
|
||||
if (value.Contains("#menu:"))
|
||||
{
|
||||
binding.Path = value[(value.IndexOf("#menu:") + 6)..].Trim();
|
||||
value = value[..value.IndexOf("#menu:")];
|
||||
|
||||
if (binding.Path.Contains(';'))
|
||||
binding.Path = binding.Path[(binding.Path.IndexOf(";") + 1)..].Trim();
|
||||
}
|
||||
|
||||
binding.Command = value.Trim();
|
||||
|
||||
if (binding.Command == "")
|
||||
continue;
|
||||
|
||||
if (binding.Command.ToLower() == "ignore")
|
||||
binding.Command = "";
|
||||
|
||||
bindings.Add(binding);
|
||||
}
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public static string _(string value) => value;
|
||||
}
|
||||
688
src/MpvNet/Locale/CS-Messages.pot
Normal file
688
src/MpvNet/Locale/CS-Messages.pot
Normal file
@@ -0,0 +1,688 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-27 09:20+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:29
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:30
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:31
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:32
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:33
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:34
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:35
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:36
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:37
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:38
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:29
|
||||
msgid "Open Files..."
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:30
|
||||
msgid "Open URL or file from clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:31
|
||||
msgid "Open DVD/Blu-ray Drive/Folder..."
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:33
|
||||
msgid "Load external audio files..."
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:34
|
||||
msgid "Load external subtitle files..."
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:36
|
||||
msgid "Add files to playlist..."
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:38
|
||||
msgid "Recent"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:39
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:40
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:39
|
||||
msgid "Play/Pause"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:40
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:41
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:42
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:43
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:44
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:45
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:46
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:47
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:48
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:49
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:50
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:51
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:52
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:53
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:54
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:55
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:56
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:57
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:58
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:59
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:60
|
||||
msgid "Navigate"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:41
|
||||
msgid "Previous File"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:42
|
||||
msgid "Next File"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:44
|
||||
msgid "Next Chapter"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:45
|
||||
msgid "Previous Chapter"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:47
|
||||
msgid "Jump Next Frame"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:48
|
||||
msgid "Jump Previous Frame"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:50
|
||||
msgid "Jump 5 sec forward"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:51
|
||||
msgid "Jump 5 sec backward"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:53
|
||||
msgid "Jump 30 sec forward"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:54
|
||||
msgid "Jump 30 sec backward"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:56
|
||||
msgid "Jump 5 min forward"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:57
|
||||
msgid "Jump 5 min backward"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:59
|
||||
msgid "Titles"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:60
|
||||
msgid "Chapters"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:61
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:62
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:63
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:64
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:65
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:66
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:67
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:68
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:69
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:70
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:71
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:72
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:73
|
||||
msgid "Pan & Scan"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:61
|
||||
msgid "Decrease Size"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:62
|
||||
msgid "Increase Size"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:64
|
||||
msgid "Move Left"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:65
|
||||
msgid "Move Right"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:67
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:101
|
||||
msgid "Move Up"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:68
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:102
|
||||
msgid "Move Down"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:70
|
||||
msgid "Decrease Height"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:71
|
||||
msgid "Increase Height"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:73
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:117
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:74
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:75
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:76
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:77
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:78
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:79
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:80
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:81
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:82
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:83
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:84
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:85
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:86
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:87
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:88
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:89
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:90
|
||||
msgid "Video"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:74
|
||||
msgid "Decrease Contrast"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:75
|
||||
msgid "Increase Contrast"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:77
|
||||
msgid "Decrease Brightness"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:78
|
||||
msgid "Increase Brightness"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:80
|
||||
msgid "Decrease Gamma"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:81
|
||||
msgid "Increase Gamma"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:83
|
||||
msgid "Decrease Saturation"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:84
|
||||
msgid "Increase Saturation"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:86
|
||||
msgid "Take Screenshot"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:87
|
||||
msgid "Take Screenshot without subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:88
|
||||
msgid "Toggle Deinterlace"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:89
|
||||
msgid "Cycle Aspect Ratio"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:90
|
||||
msgid "Rotate Video"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:91
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:92
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:93
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:94
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:91
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:95
|
||||
msgid "Cycle/Next"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:93
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:99
|
||||
msgid "Delay +0.1"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:94
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:98
|
||||
msgid "Delay -0.1"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:95
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:96
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:97
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:98
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:99
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:100
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:101
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:102
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:103
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:104
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:105
|
||||
msgid "Subtitle"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:96
|
||||
msgid "Toggle Visibility"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:104
|
||||
msgid "Decrease Subtitle Font Size"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:105
|
||||
msgid "Increase Subtitle Font Size"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:106
|
||||
msgid "Track"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:107
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:108
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:109
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:110
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:107
|
||||
msgid "Up"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:108
|
||||
msgid "Down"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:110
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:111
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:112
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:113
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:114
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:115
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:116
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:117
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:111
|
||||
msgid "-10%"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:112
|
||||
msgid "+10%"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:114
|
||||
msgid "Half"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:115
|
||||
msgid "Double"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:118
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:119
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:132
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:133
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:134
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:135
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:136
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:137
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:138
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:139
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:140
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:141
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:142
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:143
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:144
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:145
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:118
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:119
|
||||
msgid "Toggle Fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:120
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:121
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:122
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:123
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:124
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:125
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:126
|
||||
msgid "View > Zoom"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:120
|
||||
msgid "Enlarge"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:121
|
||||
msgid "Shrink"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:123
|
||||
msgid "50 %"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:124
|
||||
msgid "100 %"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:125
|
||||
msgid "200 %"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:126
|
||||
msgid "300 %"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:127
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:128
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:129
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:130
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:131
|
||||
msgid "View > Move"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:127
|
||||
msgid "Left"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:128
|
||||
msgid "Right"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:129
|
||||
msgid "Top"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:130
|
||||
msgid "Bottom"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:131
|
||||
msgid "Center"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:132
|
||||
msgid "Show Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:133
|
||||
msgid "Show Profile Selection"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:134
|
||||
msgid "Show Profiles"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:135
|
||||
msgid "Show Audio Tracks"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:136
|
||||
msgid "Show Subtitle Tracks"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:137
|
||||
msgid "Show Chapters"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:138
|
||||
msgid "Toggle Border"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:139
|
||||
msgid "Toggle On Top"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:140
|
||||
msgid "Toggle Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:141
|
||||
msgid "Toggle OSC Visibility"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:142
|
||||
msgid "Show Media Info"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:143
|
||||
msgid "Show Media Info Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:144
|
||||
msgid "Show Progress"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:145
|
||||
msgid "Show Recent"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:146
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:147
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:148
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:149
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:150
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:151
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:152
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:153
|
||||
msgid "View > Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:146
|
||||
msgid "Show Console"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:147
|
||||
msgid "Show Audio Devices"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:148
|
||||
msgid "Show Properties"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:149
|
||||
msgid "Show Commands"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:150
|
||||
msgid "Show Demuxers"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:151
|
||||
msgid "Show Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:152
|
||||
msgid "Show Protocols"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:153
|
||||
msgid "Show Keys"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:154
|
||||
msgid "Profile"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:155
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:156
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:157
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:155
|
||||
msgid "Show Config Editor"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:156
|
||||
msgid "Show Input Editor"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:157
|
||||
msgid "Open Config Folder"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:158
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:159
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:160
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:161
|
||||
msgid "Settings > Setup"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:158
|
||||
msgid "Register video file associations"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:159
|
||||
msgid "Register audio file associations"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:160
|
||||
msgid "Register image file associations"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:161
|
||||
msgid "Unregister file associations"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:162
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:163
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:164
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:165
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:166
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:167
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:168
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:162
|
||||
msgid "Set/clear A-B loop points"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:163
|
||||
msgid "Toggle infinite file looping"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:164
|
||||
msgid "Shuffle Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:165
|
||||
msgid "Toggle Hardware Decoding"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:166
|
||||
msgid "Exit"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:167
|
||||
msgid "Exit Watch Later"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:168
|
||||
msgid "Show current file in File Explorer"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:169
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:170
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:171
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:172
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:173
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:174
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:175
|
||||
msgid "Help"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:169
|
||||
msgid "Website mpv"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:170
|
||||
msgid "Website mpvnet"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:172
|
||||
msgid "Manual mpv"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:173
|
||||
msgid "Manual mpvnet"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet\UI\InputBinding.cs:175
|
||||
msgid "About mpvnet"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet.Windows\Properties\Resources.Designer.cs:79
|
||||
msgid "editor_conf"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet.Windows\Properties\Resources.Designer.cs:101
|
||||
msgid "input_conf"
|
||||
msgstr ""
|
||||
|
||||
#: D:\Projects\CS\mpvnet\src\MpvNet.Windows\Properties\Resources.Designer.cs:146
|
||||
msgid "theme"
|
||||
msgstr ""
|
||||
32
src/MpvNet/Locale/Update-Translations.ps1
Normal file
32
src/MpvNet/Locale/Update-Translations.ps1
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
# # Extract msgids from xaml files in project into pot file.
|
||||
|
||||
# . $PSScriptRoot/XGetText-Xaml.ps1
|
||||
# $xamlFiles = Get-ChildItem -Recurse -File -Filter *.xaml |
|
||||
# Where { $_.FullName -NotLike '*\obj\*' } | ForEach-Object { $_.FullName }
|
||||
# XGetText-Xaml -o obj/xamlmessages.pot -k Gettext,GettextFormatConverter $xamlFiles
|
||||
|
||||
$Root = $PSScriptRoot
|
||||
|
||||
# Write list of .cs files into CS-Files.txt file
|
||||
Get-ChildItem $Root/../.. -Recurse -File -Filter '*.cs' |
|
||||
where { $_ -notmatch '[/\\]obj[/\\]' } |
|
||||
foreach { $_.FullName } |
|
||||
Out-File $Root/CS-Files.txt
|
||||
|
||||
# Extract msgids from cs files in project into pot file
|
||||
xgettext --force-po --from-code=UTF-8 '--language=c#' -o $Root/CS-Messages.pot --files-from=$Root/CS-Files.txt --keyword=_
|
||||
|
||||
# # Merge two pot files into one
|
||||
# msgcat.exe --use-first -o obj/result.pot obj/CS-Messages.pot obj/xamlmessages.pot
|
||||
|
||||
# Update po files with most recent msgids
|
||||
$Locales = @("de")
|
||||
$PoFiles = $Locales | foreach { 'Locale/' + $_ + '/LC_MESSAGES/MpvNet.po' }
|
||||
|
||||
$PoFiles | foreach {
|
||||
# msgmerge --sort-output --update $_ $Root/CS-Messages.pot 2> $null
|
||||
}
|
||||
|
||||
# echo "Po files updated with current msgIds: " $poFiles
|
||||
# echo "You may now edit these files with PoEdit (https://poedit.net/)"
|
||||
73
src/MpvNet/Locale/XGetText-Xaml.ps1
Normal file
73
src/MpvNet/Locale/XGetText-Xaml.ps1
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
function XGetText-Xaml {
|
||||
param(
|
||||
[Parameter(Mandatory=$true,
|
||||
Position=0,
|
||||
ParameterSetName="sourceFiles",
|
||||
HelpMessage="XAML files to extract msgids from.")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string[]]$sourceFiles,
|
||||
[Parameter(Mandatory=$true,
|
||||
HelpMessage="Additional keywords that match MarkupExtensions enclosing msgids to be extracted.")]
|
||||
[Alias("k")]
|
||||
[string[]]
|
||||
$Keywords,
|
||||
[Parameter(Mandatory=$false,
|
||||
HelpMessage="Write output to specified file.")]
|
||||
[Alias("o")]
|
||||
[string]$output="messages.pot")
|
||||
|
||||
$extractedIds = New-Object -TypeName System.Collections.Hashtable
|
||||
|
||||
ForEach ($keyword in $Keywords)
|
||||
{
|
||||
ForEach ($sourceFile in $sourceFiles)
|
||||
{
|
||||
Select-String $sourceFile -Pattern $("{[a-z]?[a-z0-9]*:"+$keyword+ " (([^}{]|{[^}]*})*)}") -AllMatches | ForEach-Object {
|
||||
$filename = $sourceFile
|
||||
$lineNumber = $_.LineNumber
|
||||
$_.Matches | ForEach-Object {
|
||||
$msgid = $_.Groups[1].ToString()
|
||||
|
||||
if ($msgid.StartsWith("'") -and $msgid.EndsWith("'")){
|
||||
$msgid = $msgid.Substring(1, $msgid.Length-2);
|
||||
}
|
||||
|
||||
$msgid = $msgid.Replace("\'", "'")
|
||||
$msgid = $msgid.Replace("\,", ",")
|
||||
|
||||
if (-Not $extractedIds.ContainsKey($msgid))
|
||||
{
|
||||
$extractedIds.Add($msgid, @{Locations = New-Object System.Collections.ArrayList})
|
||||
}
|
||||
[void] $extractedIds[$msgid].Locations.Add('#: ' + $Filename + ':' + $LineNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = '#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: ' + $(Get-Date -Format 'yyyy-mm-dd HH:mmK') + '\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n\n"' + [System.Environment]::NewLine + [System.Environment]::NewLine
|
||||
$extractedIds.GetEnumerator() | ForEach-Object {
|
||||
if ($_.Key -like '*|*' ) {
|
||||
$msgid = $_.Key.Substring($_.Key.indexof("|") +1)
|
||||
$msgctxt = $_.Key.Substring(0, $_.Key.indexof("|"))
|
||||
|
||||
$result = $result + $($_.Value.Locations -join [System.Environment]::NewLine) + [System.Environment]::NewLine + "msgctxt """ + $msgctxt + """" + [System.Environment]::NewLine + "msgid """ + $msgid + """" + [System.Environment]::NewLine + "msgstr """"" + [System.Environment]::NewLine + [System.Environment]::NewLine + [System.Environment]::NewLine
|
||||
}
|
||||
else {
|
||||
$result = $result + $($_.Value.Locations -join [System.Environment]::NewLine) + [System.Environment]::NewLine + "msgid """ + $_.Key + """" + [System.Environment]::NewLine + "msgstr """"" + [System.Environment]::NewLine + [System.Environment]::NewLine + [System.Environment]::NewLine
|
||||
}
|
||||
}
|
||||
|
||||
if ($output -eq '-') {
|
||||
Write-Output $result.ToString()
|
||||
} else {
|
||||
[System.IO.File]::WriteAllLines($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($output), ($result -replace "\r", ""))
|
||||
}
|
||||
}
|
||||
183
src/MpvNet/Locale/de/LC_MESSAGES/mpvgui.po
Normal file
183
src/MpvNet/Locale/de/LC_MESSAGES/mpvgui.po
Normal file
@@ -0,0 +1,183 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-18 08:39+0100\n"
|
||||
"PO-Revision-Date: 2019-03-18 08:40+0100\n"
|
||||
"Last-Translator: Frank Skare <frank.skare.de@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
"X-Poedit-Basepath: ../../..\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-KeywordsList: Localizer.Noop\n"
|
||||
"X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#: MainWindow.xaml:71
|
||||
msgid "Binding string format support: {0:n0}"
|
||||
msgstr "Binding-string-format-unterstützung {0:n0}"
|
||||
|
||||
#: MemoryLeakTestWindow.xaml:15
|
||||
msgid ""
|
||||
"Close this window to test that the attached behavior releases its event "
|
||||
"listeners from the culture tracker."
|
||||
msgstr ""
|
||||
"Schließen Sie dieses Fenster, um zu testen, ob das angehängte Verhalten "
|
||||
"seine Ereignis-Listener vom Culture Tracker freigibt."
|
||||
|
||||
#: MainWindow.xaml:38
|
||||
msgid "Danish"
|
||||
msgstr "Dänisch"
|
||||
|
||||
#: C:\Git\ngettext-avalonia\NGettext.Avalonia.Example\MainWindow.xaml.cs:17
|
||||
msgid "Deferred localization"
|
||||
msgstr "Aaufgeschobene Übersetzung"
|
||||
|
||||
#: MainWindow.xaml:56
|
||||
msgid "Deferred localization example:"
|
||||
msgstr "Beispiel von aufgeschobene Übersetzung:"
|
||||
|
||||
#: MainWindow.xaml:65
|
||||
msgid "Enclosing single-quotes (') are optional"
|
||||
msgstr "Einschließende einfache Anführungszeichen (') sind optional"
|
||||
|
||||
#: MainWindow.xaml:66
|
||||
msgid "Enclosing single-quotes (apostrophes) are optional."
|
||||
msgstr "Einschließende einfache Anführungszeichen (Apostrophe) sind optional."
|
||||
|
||||
#: MainWindow.xaml:34
|
||||
msgid "English"
|
||||
msgstr "Englisch"
|
||||
|
||||
#: MainWindow.xaml:69
|
||||
msgctxt "Example"
|
||||
msgid "GNOME glib syntax context example"
|
||||
msgstr "GNOME glib-Syntaxkontextbeispiel"
|
||||
|
||||
#: MainWindow.xaml:36
|
||||
msgid "German"
|
||||
msgstr "Deutsch"
|
||||
|
||||
#: MainWindow.xaml:46
|
||||
msgid "Localized date time format example:"
|
||||
msgstr "Lokales Datumsformatbeispiel:"
|
||||
|
||||
#: MainWindow.xaml:51
|
||||
msgid "Localized enum combo example:"
|
||||
msgstr "Lokalisierte Enum-Combobox-Beispiel:"
|
||||
|
||||
#: MainWindow.xaml:41
|
||||
msgid "Localized number format example:"
|
||||
msgstr "Lokales Zahlenformatbeispiel:"
|
||||
|
||||
#: MainWindow.xaml:76
|
||||
msgid "Memory leak test progress:"
|
||||
msgstr "Speicherlecktestfortschritt:"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\MainWindow.xaml.cs:97
|
||||
msgid "NGettext.Avalonia Example"
|
||||
msgstr "NGettext.Avalonia-Beispiel"
|
||||
|
||||
#: MainWindow.xaml:73
|
||||
msgid "Run TrackCurrentCultureBehavior memory leak test"
|
||||
msgstr "Den TrackCurrentCultureBehavior-Speicherlecktest ausführen"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\MainWindow.xaml.cs:99
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\MainWindow.xaml.cs:100
|
||||
msgid "Singular"
|
||||
msgid_plural "Plural"
|
||||
msgstr[0] "Singular"
|
||||
msgstr[1] "Plural"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\MainWindow.xaml.cs:102
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\MainWindow.xaml.cs:103
|
||||
#, csharp-format
|
||||
msgid "Singular {0:n3}"
|
||||
msgid_plural "Plural {0:n3}"
|
||||
msgstr[0] "Singular {0:n3}"
|
||||
msgstr[1] "Plural {0:n3}"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\ExampleEnum.cs:16
|
||||
msgctxt "EnumMsgId example"
|
||||
msgid "Some fourth value"
|
||||
msgstr "Ein vierter Wert"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\ExampleEnum.cs:10
|
||||
msgid "Some other value"
|
||||
msgstr "Ein anderer Wert"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\ExampleEnum.cs:13
|
||||
msgid "Some third value"
|
||||
msgstr "Ein dritter Wert"
|
||||
|
||||
#: C:\Git\ngettext-wpf\NGettext.Avalonia.Example\ExampleEnum.cs:7
|
||||
msgid "Some value"
|
||||
msgstr "Ein gewisser Wert"
|
||||
|
||||
#: MainWindow.xaml:70
|
||||
msgid "Text with punctuation: 1, 2, 3"
|
||||
msgstr "Tekst mit Zeichensetzung: 1, 2, 3"
|
||||
|
||||
#: MainWindow.xaml:67
|
||||
msgid "Unenclosed escaped single-quotes (') are supported."
|
||||
msgstr "Unclosed maskierte einfache Anführungszeichen (') werden unterstützt."
|
||||
|
||||
#: MainWindow.xaml:68
|
||||
msgid "Unicode™ in msgIds is supported"
|
||||
msgstr "Unicode™ in msgIds wird unterstützt"
|
||||
|
||||
#: MainWindow.xaml:61
|
||||
msgid "Varying cAsE ExamPle:"
|
||||
msgstr "Beispiel von Variation zwiScHen Groß- und KleInBUchstaBen:"
|
||||
|
||||
#: MainWindow.xaml:60
|
||||
msgid "Varying case example:"
|
||||
msgstr "Beispiel von Variation zwischen Groß- und Kleinbuchstaben:"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgctxt ""
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Project-Id-Version: \n"
|
||||
#~ "Report-Msgid-Bugs-To: \n"
|
||||
#~ "POT-Creation-Date: 2019-02-18 13:15+0100\n"
|
||||
#~ "PO-Revision-Date: 2018-09-28 11:43+0200\n"
|
||||
#~ "Last-Translator: Robert Jørgensgaard Engdahl <rje@accuratech.dk>\n"
|
||||
#~ "Language-Team: \n"
|
||||
#~ "Language: de_DE\n"
|
||||
#~ "MIME-Version: 1.0\n"
|
||||
#~ "Content-Type: text/plain; charset=UTF-8\n"
|
||||
#~ "Content-Transfer-Encoding: 8bit\n"
|
||||
#~ "X-Generator: Poedit 2.1.1\n"
|
||||
#~ "X-Poedit-Basepath: ../../..\n"
|
||||
#~ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
#~ "X-Poedit-KeywordsList: Localizer.Noop\n"
|
||||
#~ "X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgctxt "test"
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Project-Id-Version: \n"
|
||||
#~ "Report-Msgid-Bugs-To: \n"
|
||||
#~ "POT-Creation-Date: 2019-02-18 13:21+0100\n"
|
||||
#~ "PO-Revision-Date: 2018-09-28 11:43+0200\n"
|
||||
#~ "Last-Translator: Robert Jørgensgaard Engdahl <rje@accuratech.dk>\n"
|
||||
#~ "Language-Team: \n"
|
||||
#~ "Language: de_DE\n"
|
||||
#~ "MIME-Version: 1.0\n"
|
||||
#~ "Content-Type: text/plain; charset=UTF-8\n"
|
||||
#~ "Content-Transfer-Encoding: 8bit\n"
|
||||
#~ "X-Generator: Poedit 2.1.1\n"
|
||||
#~ "X-Poedit-Basepath: ../../..\n"
|
||||
#~ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
#~ "X-Poedit-KeywordsList: Localizer.Noop\n"
|
||||
#~ "X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgctxt "EnumMsgId example"
|
||||
#~ msgid "Some third value"
|
||||
#~ msgstr "Ein dritter Wert"
|
||||
13
src/MpvNet/MVVM/Messages.cs
Normal file
13
src/MpvNet/MVVM/Messages.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
|
||||
namespace MpvNet.MVVM;
|
||||
|
||||
public class MainWindowIsLoadedMessage { }
|
||||
|
||||
//public class ScaleWindowMessage : ValueChangedMessage<float>
|
||||
//{
|
||||
// public ScaleWindowMessage(float value) : base(value)
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
10
src/MpvNet/MediaTrack.cs
Normal file
10
src/MpvNet/MediaTrack.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class MediaTrack
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public bool External { get; set; }
|
||||
public string Text { get; set; } = "";
|
||||
public string Type { get; set; } = "";
|
||||
}
|
||||
492
src/MpvNet/MpvClient.cs
Normal file
492
src/MpvNet/MpvClient.cs
Normal file
@@ -0,0 +1,492 @@
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using static MpvNet.Native.LibMpv;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class MpvClient
|
||||
{
|
||||
public event Action<string[]>? ClientMessage; // client-message MPV_EVENT_CLIENT_MESSAGE
|
||||
public event Action<mpv_log_level, string>? LogMessage; // log-message MPV_EVENT_LOG_MESSAGE
|
||||
public event Action<mpv_end_file_reason>? EndFile; // end-file MPV_EVENT_END_FILE
|
||||
public event Action? Shutdown; // shutdown MPV_EVENT_SHUTDOWN
|
||||
public event Action? GetPropertyReply; // get-property-reply MPV_EVENT_GET_PROPERTY_REPLY
|
||||
public event Action? SetPropertyReply; // set-property-reply MPV_EVENT_SET_PROPERTY_REPLY
|
||||
public event Action? CommandReply; // command-reply MPV_EVENT_COMMAND_REPLY
|
||||
public event Action? StartFile; // start-file MPV_EVENT_START_FILE
|
||||
public event Action? FileLoaded; // file-loaded MPV_EVENT_FILE_LOADED
|
||||
public event Action? VideoReconfig; // video-reconfig MPV_EVENT_VIDEO_RECONFIG
|
||||
public event Action? AudioReconfig; // audio-reconfig MPV_EVENT_AUDIO_RECONFIG
|
||||
public event Action? Seek; // seek MPV_EVENT_SEEK
|
||||
public event Action? PlaybackRestart; // playback-restart MPV_EVENT_PLAYBACK_RESTART
|
||||
|
||||
public Dictionary<string, List<Action>> PropChangeActions { get; set; } = new Dictionary<string, List<Action>>();
|
||||
public Dictionary<string, List<Action<int>>> IntPropChangeActions { get; set; } = new Dictionary<string, List<Action<int>>>();
|
||||
public Dictionary<string, List<Action<bool>>> BoolPropChangeActions { get; set; } = new Dictionary<string, List<Action<bool>>>();
|
||||
public Dictionary<string, List<Action<double>>> DoublePropChangeActions { get; set; } = new Dictionary<string, List<Action<double>>>();
|
||||
public Dictionary<string, List<Action<string>>> StringPropChangeActions { get; set; } = new Dictionary<string, List<Action<string>>>();
|
||||
|
||||
public nint Handle { get; set; }
|
||||
|
||||
public void EventLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
IntPtr ptr = mpv_wait_event(Handle, -1);
|
||||
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event))!;
|
||||
|
||||
try
|
||||
{
|
||||
switch (evt.event_id)
|
||||
{
|
||||
case mpv_event_id.MPV_EVENT_SHUTDOWN:
|
||||
OnShutdown();
|
||||
return;
|
||||
case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
|
||||
{
|
||||
var data = (mpv_event_log_message)Marshal.PtrToStructure(evt.data, typeof(mpv_event_log_message))!;
|
||||
OnLogMessage(data);
|
||||
}
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE:
|
||||
{
|
||||
var data = (mpv_event_client_message)Marshal.PtrToStructure(evt.data, typeof(mpv_event_client_message))!;
|
||||
OnClientMessage(data);
|
||||
}
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_VIDEO_RECONFIG:
|
||||
OnVideoReconfig();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_END_FILE:
|
||||
{
|
||||
var data = (mpv_event_end_file)Marshal.PtrToStructure(evt.data, typeof(mpv_event_end_file))!;
|
||||
OnEndFile(data);
|
||||
}
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_FILE_LOADED:
|
||||
OnFileLoaded();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE:
|
||||
{
|
||||
var data = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property))!;
|
||||
OnPropertyChange(data);
|
||||
}
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_GET_PROPERTY_REPLY:
|
||||
OnGetPropertyReply();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_SET_PROPERTY_REPLY:
|
||||
OnSetPropertyReply();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_COMMAND_REPLY:
|
||||
OnCommandReply();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_START_FILE:
|
||||
OnStartFile();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_AUDIO_RECONFIG:
|
||||
OnAudioReconfig();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_SEEK:
|
||||
OnSeek();
|
||||
break;
|
||||
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
|
||||
OnPlaybackRestart();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Terminal.WriteError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnClientMessage(mpv_event_client_message data) =>
|
||||
ClientMessage?.Invoke(ConvertFromUtf8Strings(data.args, data.num_args));
|
||||
|
||||
protected virtual void OnLogMessage(mpv_event_log_message data)
|
||||
{
|
||||
if (LogMessage != null)
|
||||
{
|
||||
string msg = $"[{ConvertFromUtf8(data.prefix)}] {ConvertFromUtf8(data.text)}";
|
||||
LogMessage.Invoke(data.log_level, msg);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChange(mpv_event_property data)
|
||||
{
|
||||
if (data.format == mpv_format.MPV_FORMAT_FLAG)
|
||||
{
|
||||
lock (BoolPropChangeActions)
|
||||
foreach (var pair in BoolPropChangeActions)
|
||||
if (pair.Key == data.name)
|
||||
{
|
||||
bool value = Marshal.PtrToStructure<int>(data.data) == 1;
|
||||
|
||||
foreach (var action in pair.Value)
|
||||
action.Invoke(value);
|
||||
}
|
||||
}
|
||||
else if (data.format == mpv_format.MPV_FORMAT_STRING)
|
||||
{
|
||||
lock (StringPropChangeActions)
|
||||
foreach (var pair in StringPropChangeActions)
|
||||
if (pair.Key == data.name)
|
||||
{
|
||||
string value = ConvertFromUtf8(Marshal.PtrToStructure<IntPtr>(data.data));
|
||||
|
||||
foreach (var action in pair.Value)
|
||||
action.Invoke(value);
|
||||
}
|
||||
}
|
||||
else if (data.format == mpv_format.MPV_FORMAT_INT64)
|
||||
{
|
||||
lock (IntPropChangeActions)
|
||||
foreach (var pair in IntPropChangeActions)
|
||||
if (pair.Key == data.name)
|
||||
{
|
||||
int value = Marshal.PtrToStructure<int>(data.data);
|
||||
|
||||
foreach (var action in pair.Value)
|
||||
action.Invoke(value);
|
||||
}
|
||||
}
|
||||
else if (data.format == mpv_format.MPV_FORMAT_NONE)
|
||||
{
|
||||
lock (PropChangeActions)
|
||||
foreach (var pair in PropChangeActions)
|
||||
if (pair.Key == data.name)
|
||||
foreach (var action in pair.Value)
|
||||
action.Invoke();
|
||||
}
|
||||
else if (data.format == mpv_format.MPV_FORMAT_DOUBLE)
|
||||
{
|
||||
lock (DoublePropChangeActions)
|
||||
foreach (var pair in DoublePropChangeActions)
|
||||
if (pair.Key == data.name)
|
||||
{
|
||||
double value = Marshal.PtrToStructure<double>(data.data);
|
||||
|
||||
foreach (var action in pair.Value)
|
||||
action.Invoke(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnEndFile(mpv_event_end_file data) => EndFile?.Invoke((mpv_end_file_reason)data.reason);
|
||||
protected virtual void OnFileLoaded() => FileLoaded?.Invoke();
|
||||
protected virtual void OnShutdown() => Shutdown?.Invoke();
|
||||
protected virtual void OnGetPropertyReply() => GetPropertyReply?.Invoke();
|
||||
protected virtual void OnSetPropertyReply() => SetPropertyReply?.Invoke();
|
||||
protected virtual void OnCommandReply() => CommandReply?.Invoke();
|
||||
protected virtual void OnStartFile() => StartFile?.Invoke();
|
||||
protected virtual void OnVideoReconfig() => VideoReconfig?.Invoke();
|
||||
protected virtual void OnAudioReconfig() => AudioReconfig?.Invoke();
|
||||
protected virtual void OnSeek() => Seek?.Invoke();
|
||||
protected virtual void OnPlaybackRestart() => PlaybackRestart?.Invoke();
|
||||
|
||||
public void Command(string command)
|
||||
{
|
||||
mpv_error err = mpv_command_string(Handle, command);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error executing command: " + command);
|
||||
}
|
||||
|
||||
public void CommandV(params string[] args)
|
||||
{
|
||||
int count = args.Length + 1;
|
||||
IntPtr[] pointers = new IntPtr[count];
|
||||
IntPtr rootPtr = Marshal.AllocHGlobal(IntPtr.Size * count);
|
||||
|
||||
for (int index = 0; index < args.Length; index++)
|
||||
{
|
||||
var bytes = GetUtf8Bytes(args[index]);
|
||||
IntPtr ptr = Marshal.AllocHGlobal(bytes.Length);
|
||||
Marshal.Copy(bytes, 0, ptr, bytes.Length);
|
||||
pointers[index] = ptr;
|
||||
}
|
||||
|
||||
Marshal.Copy(pointers, 0, rootPtr, count);
|
||||
mpv_error err = mpv_command(Handle, rootPtr);
|
||||
|
||||
foreach (IntPtr ptr in pointers)
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
|
||||
Marshal.FreeHGlobal(rootPtr);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error executing command: " + string.Join("\n", args));
|
||||
}
|
||||
|
||||
public string Expand(string? value)
|
||||
{
|
||||
if (value == null)
|
||||
return "";
|
||||
|
||||
if (!value.Contains("${"))
|
||||
return value;
|
||||
|
||||
string[] args = { "expand-text", value };
|
||||
int count = args.Length + 1;
|
||||
IntPtr[] pointers = new IntPtr[count];
|
||||
IntPtr rootPtr = Marshal.AllocHGlobal(IntPtr.Size * count);
|
||||
|
||||
for (int index = 0; index < args.Length; index++)
|
||||
{
|
||||
var bytes = GetUtf8Bytes(args[index]);
|
||||
IntPtr ptr = Marshal.AllocHGlobal(bytes.Length);
|
||||
Marshal.Copy(bytes, 0, ptr, bytes.Length);
|
||||
pointers[index] = ptr;
|
||||
}
|
||||
|
||||
Marshal.Copy(pointers, 0, rootPtr, count);
|
||||
IntPtr resultNodePtr = Marshal.AllocHGlobal(16);
|
||||
mpv_error err = mpv_command_ret(Handle, rootPtr, resultNodePtr);
|
||||
|
||||
foreach (IntPtr ptr in pointers)
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
|
||||
Marshal.FreeHGlobal(rootPtr);
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
HandleError(err, "error executing command: " + string.Join("\n", args));
|
||||
Marshal.FreeHGlobal(resultNodePtr);
|
||||
return "property expansion error";
|
||||
}
|
||||
|
||||
mpv_node resultNode = Marshal.PtrToStructure<mpv_node>(resultNodePtr);
|
||||
string ret = ConvertFromUtf8(resultNode.str);
|
||||
mpv_free_node_contents(resultNodePtr);
|
||||
Marshal.FreeHGlobal(resultNodePtr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool GetPropertyBool(string name)
|
||||
{
|
||||
mpv_error err = mpv_get_property(Handle, GetUtf8Bytes(name),
|
||||
mpv_format.MPV_FORMAT_FLAG, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error getting property: " + name);
|
||||
|
||||
return lpBuffer.ToInt32() != 0;
|
||||
}
|
||||
|
||||
public void SetPropertyBool(string name, bool value)
|
||||
{
|
||||
long val = value ? 1 : 0;
|
||||
mpv_error err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_FLAG, ref val);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, $"error setting property: {name} = {value}");
|
||||
}
|
||||
|
||||
public int GetPropertyInt(string name)
|
||||
{
|
||||
mpv_error err = mpv_get_property(Handle, GetUtf8Bytes(name),
|
||||
mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0 && App.DebugMode)
|
||||
HandleError(err, "error getting property: " + name);
|
||||
|
||||
return lpBuffer.ToInt32();
|
||||
}
|
||||
|
||||
public void SetPropertyInt(string name, int value)
|
||||
{
|
||||
long val = value;
|
||||
mpv_error err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, $"error setting property: {name} = {value}");
|
||||
}
|
||||
|
||||
public void SetPropertyLong(string name, long value)
|
||||
{
|
||||
mpv_error err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref value);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, $"error setting property: {name} = {value}");
|
||||
}
|
||||
|
||||
public long GetPropertyLong(string name)
|
||||
{
|
||||
mpv_error err = mpv_get_property(Handle, GetUtf8Bytes(name),
|
||||
mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error getting property: " + name);
|
||||
|
||||
return lpBuffer.ToInt64();
|
||||
}
|
||||
|
||||
public double GetPropertyDouble(string name, bool handleError = true)
|
||||
{
|
||||
mpv_error err = mpv_get_property(Handle, GetUtf8Bytes(name),
|
||||
mpv_format.MPV_FORMAT_DOUBLE, out double value);
|
||||
|
||||
if (err < 0 && handleError && App.DebugMode)
|
||||
HandleError(err, "error getting property: " + name);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public void SetPropertyDouble(string name, double value)
|
||||
{
|
||||
double val = value;
|
||||
mpv_error err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, $"error setting property: {name} = {value}");
|
||||
}
|
||||
|
||||
public string GetPropertyString(string name)
|
||||
{
|
||||
mpv_error err = mpv_get_property(Handle, GetUtf8Bytes(name),
|
||||
mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
string ret = ConvertFromUtf8(lpBuffer);
|
||||
mpv_free(lpBuffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (err < 0 && App.DebugMode)
|
||||
HandleError(err, "error getting property: " + name);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public void SetPropertyString(string name, string value)
|
||||
{
|
||||
byte[] bytes = GetUtf8Bytes(value);
|
||||
mpv_error err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, $"error setting property: {name} = {value}");
|
||||
}
|
||||
|
||||
public string GetPropertyOsdString(string name)
|
||||
{
|
||||
mpv_error err = mpv_get_property(Handle, GetUtf8Bytes(name),
|
||||
mpv_format.MPV_FORMAT_OSD_STRING, out IntPtr lpBuffer);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
string ret = ConvertFromUtf8(lpBuffer);
|
||||
mpv_free(lpBuffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error getting property: " + name);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public void ObservePropertyInt(string name, Action<int> action)
|
||||
{
|
||||
lock (IntPropChangeActions)
|
||||
{
|
||||
if (!IntPropChangeActions.ContainsKey(name))
|
||||
{
|
||||
mpv_error err = mpv_observe_property(Handle, 0, name, mpv_format.MPV_FORMAT_INT64);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error observing property: " + name);
|
||||
else
|
||||
IntPropChangeActions[name] = new List<Action<int>>();
|
||||
}
|
||||
|
||||
if (IntPropChangeActions.ContainsKey(name))
|
||||
IntPropChangeActions[name].Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void ObservePropertyDouble(string name, Action<double> action)
|
||||
{
|
||||
lock (DoublePropChangeActions)
|
||||
{
|
||||
if (!DoublePropChangeActions.ContainsKey(name))
|
||||
{
|
||||
mpv_error err = mpv_observe_property(Handle, 0, name, mpv_format.MPV_FORMAT_DOUBLE);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error observing property: " + name);
|
||||
else
|
||||
DoublePropChangeActions[name] = new List<Action<double>>();
|
||||
}
|
||||
|
||||
if (DoublePropChangeActions.ContainsKey(name))
|
||||
DoublePropChangeActions[name].Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void ObservePropertyBool(string name, Action<bool> action)
|
||||
{
|
||||
lock (BoolPropChangeActions)
|
||||
{
|
||||
if (!BoolPropChangeActions.ContainsKey(name))
|
||||
{
|
||||
mpv_error err = mpv_observe_property(Handle, 0, name, mpv_format.MPV_FORMAT_FLAG);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error observing property: " + name);
|
||||
else
|
||||
BoolPropChangeActions[name] = new List<Action<bool>>();
|
||||
}
|
||||
|
||||
if (BoolPropChangeActions.ContainsKey(name))
|
||||
BoolPropChangeActions[name].Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void ObservePropertyString(string name, Action<string> action)
|
||||
{
|
||||
lock (StringPropChangeActions)
|
||||
{
|
||||
if (!StringPropChangeActions.ContainsKey(name))
|
||||
{
|
||||
mpv_error err = mpv_observe_property(Handle, 0, name, mpv_format.MPV_FORMAT_STRING);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error observing property: " + name);
|
||||
else
|
||||
StringPropChangeActions[name] = new List<Action<string>>();
|
||||
}
|
||||
|
||||
if (StringPropChangeActions.ContainsKey(name))
|
||||
StringPropChangeActions[name].Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void ObserveProperty(string name, Action action)
|
||||
{
|
||||
lock (PropChangeActions)
|
||||
{
|
||||
if (!PropChangeActions.ContainsKey(name))
|
||||
{
|
||||
mpv_error err = mpv_observe_property(Handle, 0, name, mpv_format.MPV_FORMAT_NONE);
|
||||
|
||||
if (err < 0)
|
||||
HandleError(err, "error observing property: " + name);
|
||||
else
|
||||
PropChangeActions[name] = new List<Action>();
|
||||
}
|
||||
|
||||
if (PropChangeActions.ContainsKey(name))
|
||||
PropChangeActions[name].Add(action);
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleError(mpv_error err, string msg)
|
||||
{
|
||||
Terminal.WriteError(msg);
|
||||
Terminal.WriteError(GetError(err));
|
||||
}
|
||||
}
|
||||
27
src/MpvNet/MpvNet.csproj
Normal file
27
src/MpvNet/MpvNet.csproj
Normal file
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>libmpvnet</AssemblyName>
|
||||
<Product>mpv.net</Product>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>MpvNet</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\docs\changelog.md" Link="Docs\changelog.md" />
|
||||
<None Include="..\..\docs\manual.md" Link="Docs\manual.md" />
|
||||
<None Include="..\..\README.md" Link="Docs\README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Extension\" />
|
||||
<Folder Include="Input\" />
|
||||
<Folder Include="Docs\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
242
src/MpvNet/Native/LibMpv.cs
Normal file
242
src/MpvNet/Native/LibMpv.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
|
||||
#pragma warning disable IDE1006 // type name starts with underscore
|
||||
#pragma warning disable CA1401 // P/Invokes should not be visible
|
||||
#pragma warning disable CA2101 // Specify marshaling for P/Invoke string arguments
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace MpvNet.Native;
|
||||
|
||||
public static class LibMpv
|
||||
{
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern nint mpv_create();
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern nint mpv_create_client(nint mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string command);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_initialize(nint mpvHandle);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void mpv_destroy(nint mpvHandle);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_command(nint mpvHandle, nint strings);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_command_string(nint mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string command);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_command_ret(nint mpvHandle, nint strings, nint node);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void mpv_free_node_contents(nint node);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern nint mpv_error_string(mpv_error error);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_request_log_messages(nint mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string min_level);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int mpv_set_option(nint mpvHandle, byte[] name, mpv_format format, ref long data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int mpv_set_option_string(nint mpvHandle, byte[] name, byte[] value);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_get_property(nint mpvHandle, byte[] name, mpv_format format, out nint data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_get_property(nint mpvHandle, byte[] name, mpv_format format, out double data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_set_property(nint mpvHandle, byte[] name, mpv_format format, ref byte[] data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_set_property(nint mpvHandle, byte[] name, mpv_format format, ref long data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_set_property(nint mpvHandle, byte[] name, mpv_format format, ref double data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_observe_property(nint mpvHandle, ulong reply_userdata, [MarshalAs(UnmanagedType.LPUTF8Str)] string name, mpv_format format);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int mpv_unobserve_property(nint mpvHandle, ulong registered_reply_userdata);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void mpv_free(nint data);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern nint mpv_wait_event(nint mpvHandle, double timeout);
|
||||
|
||||
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern mpv_error mpv_request_event(nint mpvHandle, mpv_event_id id, int enable);
|
||||
|
||||
public enum mpv_error
|
||||
{
|
||||
MPV_ERROR_SUCCESS = 0,
|
||||
MPV_ERROR_EVENT_QUEUE_FULL = -1,
|
||||
MPV_ERROR_NOMEM = -2,
|
||||
MPV_ERROR_UNINITIALIZED = -3,
|
||||
MPV_ERROR_INVALID_PARAMETER = -4,
|
||||
MPV_ERROR_OPTION_NOT_FOUND = -5,
|
||||
MPV_ERROR_OPTION_FORMAT = -6,
|
||||
MPV_ERROR_OPTION_ERROR = -7,
|
||||
MPV_ERROR_PROPERTY_NOT_FOUND = -8,
|
||||
MPV_ERROR_PROPERTY_FORMAT = -9,
|
||||
MPV_ERROR_PROPERTY_UNAVAILABLE = -10,
|
||||
MPV_ERROR_PROPERTY_ERROR = -11,
|
||||
MPV_ERROR_COMMAND = -12,
|
||||
MPV_ERROR_LOADING_FAILED = -13,
|
||||
MPV_ERROR_AO_INIT_FAILED = -14,
|
||||
MPV_ERROR_VO_INIT_FAILED = -15,
|
||||
MPV_ERROR_NOTHING_TO_PLAY = -16,
|
||||
MPV_ERROR_UNKNOWN_FORMAT = -17,
|
||||
MPV_ERROR_UNSUPPORTED = -18,
|
||||
MPV_ERROR_NOT_IMPLEMENTED = -19,
|
||||
MPV_ERROR_GENERIC = -20
|
||||
}
|
||||
|
||||
public enum mpv_event_id
|
||||
{
|
||||
MPV_EVENT_NONE = 0,
|
||||
MPV_EVENT_SHUTDOWN = 1,
|
||||
MPV_EVENT_LOG_MESSAGE = 2,
|
||||
MPV_EVENT_GET_PROPERTY_REPLY = 3,
|
||||
MPV_EVENT_SET_PROPERTY_REPLY = 4,
|
||||
MPV_EVENT_COMMAND_REPLY = 5,
|
||||
MPV_EVENT_START_FILE = 6,
|
||||
MPV_EVENT_END_FILE = 7,
|
||||
MPV_EVENT_FILE_LOADED = 8,
|
||||
MPV_EVENT_IDLE = 11, //deprecated
|
||||
MPV_EVENT_TICK = 14, //deprecated
|
||||
MPV_EVENT_SCRIPT_INPUT_DISPATCH = 15,
|
||||
MPV_EVENT_CLIENT_MESSAGE = 16,
|
||||
MPV_EVENT_VIDEO_RECONFIG = 17,
|
||||
MPV_EVENT_AUDIO_RECONFIG = 18,
|
||||
MPV_EVENT_SEEK = 20,
|
||||
MPV_EVENT_PLAYBACK_RESTART = 21,
|
||||
MPV_EVENT_PROPERTY_CHANGE = 22,
|
||||
MPV_EVENT_QUEUE_OVERFLOW = 24,
|
||||
MPV_EVENT_HOOK = 25
|
||||
}
|
||||
|
||||
public enum mpv_format
|
||||
{
|
||||
MPV_FORMAT_NONE = 0,
|
||||
MPV_FORMAT_STRING = 1,
|
||||
MPV_FORMAT_OSD_STRING = 2,
|
||||
MPV_FORMAT_FLAG = 3,
|
||||
MPV_FORMAT_INT64 = 4,
|
||||
MPV_FORMAT_DOUBLE = 5,
|
||||
MPV_FORMAT_NODE = 6,
|
||||
MPV_FORMAT_NODE_ARRAY = 7,
|
||||
MPV_FORMAT_NODE_MAP = 8,
|
||||
MPV_FORMAT_BYTE_ARRAY = 9
|
||||
}
|
||||
|
||||
public enum mpv_log_level
|
||||
{
|
||||
MPV_LOG_LEVEL_NONE = 0,
|
||||
MPV_LOG_LEVEL_FATAL = 10,
|
||||
MPV_LOG_LEVEL_ERROR = 20,
|
||||
MPV_LOG_LEVEL_WARN = 30,
|
||||
MPV_LOG_LEVEL_INFO = 40,
|
||||
MPV_LOG_LEVEL_V = 50,
|
||||
MPV_LOG_LEVEL_DEBUG = 60,
|
||||
MPV_LOG_LEVEL_TRACE = 70,
|
||||
}
|
||||
|
||||
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 nint prefix;
|
||||
public nint level;
|
||||
public nint text;
|
||||
public mpv_log_level log_level;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct mpv_event
|
||||
{
|
||||
public mpv_event_id event_id;
|
||||
public int error;
|
||||
public ulong reply_userdata;
|
||||
public nint data;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct mpv_event_client_message
|
||||
{
|
||||
public int num_args;
|
||||
public nint args;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct mpv_event_property
|
||||
{
|
||||
public string name;
|
||||
public mpv_format format;
|
||||
public nint data;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct mpv_event_end_file
|
||||
{
|
||||
public int reason;
|
||||
public int error;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = 16)]
|
||||
public struct mpv_node
|
||||
{
|
||||
[FieldOffset(0)] public nint str;
|
||||
[FieldOffset(0)] public int flag;
|
||||
[FieldOffset(0)] public long int64;
|
||||
[FieldOffset(0)] public double dbl;
|
||||
[FieldOffset(0)] public nint list;
|
||||
[FieldOffset(0)] public nint ba;
|
||||
[FieldOffset(8)] public mpv_format format;
|
||||
}
|
||||
|
||||
public static string[] ConvertFromUtf8Strings(nint utf8StringArray, int stringCount)
|
||||
{
|
||||
nint[] intPtrArray = new nint[stringCount];
|
||||
string[] stringArray = new string[stringCount];
|
||||
Marshal.Copy(utf8StringArray, intPtrArray, 0, stringCount);
|
||||
|
||||
for (int i = 0; i < stringCount; i++)
|
||||
stringArray[i] = ConvertFromUtf8(intPtrArray[i]);
|
||||
|
||||
return stringArray;
|
||||
}
|
||||
|
||||
public static string ConvertFromUtf8(nint nativeUtf8)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
while (Marshal.ReadByte(nativeUtf8, len) != 0)
|
||||
++len;
|
||||
|
||||
byte[] buffer = new byte[len];
|
||||
Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
|
||||
public static string GetError(mpv_error err) => ConvertFromUtf8(mpv_error_string(err));
|
||||
|
||||
public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
|
||||
}
|
||||
125
src/MpvNet/Native/MediaInfo.cs
Normal file
125
src/MpvNet/Native/MediaInfo.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public class MediaInfo : IDisposable
|
||||
{
|
||||
readonly IntPtr Handle;
|
||||
|
||||
public MediaInfo(string file)
|
||||
{
|
||||
if ((Handle = MediaInfo_New()) == IntPtr.Zero)
|
||||
throw new Exception("Failed to call MediaInfo_New");
|
||||
|
||||
if (MediaInfo_Open(Handle, file) == 0)
|
||||
throw new Exception("Error MediaInfo_Open");
|
||||
}
|
||||
|
||||
public string GetInfo(MediaInfoStreamKind kind, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, kind, 0,
|
||||
parameter, MediaInfoKind.Text, MediaInfoKind.Name)) ?? "";
|
||||
}
|
||||
|
||||
public int GetCount(MediaInfoStreamKind kind) => MediaInfo_Count_Get(Handle, kind, -1);
|
||||
|
||||
public string GetGeneral(string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.General,
|
||||
0, parameter, MediaInfoKind.Text, MediaInfoKind.Name)) ?? "";
|
||||
}
|
||||
|
||||
public string GetVideo(int stream, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video,
|
||||
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)) ?? "";
|
||||
}
|
||||
|
||||
public string GetAudio(int stream, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio,
|
||||
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)) ?? "";
|
||||
}
|
||||
|
||||
public string GetText(int stream, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text,
|
||||
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)) ?? "";
|
||||
}
|
||||
|
||||
public string GetSummary(bool complete, bool rawView)
|
||||
{
|
||||
MediaInfo_Option(Handle, "Language", rawView ? "raw" : "");
|
||||
MediaInfo_Option(Handle, "Complete", complete ? "1" : "0");
|
||||
return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, 0)) ?? "";
|
||||
}
|
||||
|
||||
bool Disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Disposed)
|
||||
{
|
||||
if (Handle != IntPtr.Zero)
|
||||
{
|
||||
MediaInfo_Close(Handle);
|
||||
MediaInfo_Delete(Handle);
|
||||
}
|
||||
|
||||
Disposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
~MediaInfo() { Dispose(); }
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern IntPtr MediaInfo_New();
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int MediaInfo_Open(IntPtr handle, string path);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr MediaInfo_Option(IntPtr handle, string option, string value);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern IntPtr MediaInfo_Inform(IntPtr handle, int reserved);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern int MediaInfo_Close(IntPtr handle);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern void MediaInfo_Delete(IntPtr handle);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr MediaInfo_Get(IntPtr handle, MediaInfoStreamKind kind,
|
||||
int stream, string parameter, MediaInfoKind infoKind, MediaInfoKind searchKind);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int MediaInfo_Count_Get(IntPtr handle, MediaInfoStreamKind streamKind, int stream);
|
||||
}
|
||||
|
||||
public enum MediaInfoStreamKind
|
||||
{
|
||||
General,
|
||||
Video,
|
||||
Audio,
|
||||
Text,
|
||||
Other,
|
||||
Image,
|
||||
Menu,
|
||||
Max,
|
||||
}
|
||||
|
||||
public enum MediaInfoKind
|
||||
{
|
||||
Name,
|
||||
Text,
|
||||
Measure,
|
||||
Options,
|
||||
NameText,
|
||||
MeasureText,
|
||||
Info,
|
||||
HowTo
|
||||
}
|
||||
17
src/MpvNet/Native/StringLogicalComparer.cs
Normal file
17
src/MpvNet/Native/StringLogicalComparer.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections;
|
||||
|
||||
namespace MpvNet.Native;
|
||||
|
||||
public class StringLogicalComparer : IComparer, IComparer<string>
|
||||
{
|
||||
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int StrCmpLogical(string? x, string? y);
|
||||
|
||||
static int IComparer_Compare(object? x, object? y) => StrCmpLogical(x!.ToString(), y!.ToString());
|
||||
static int IComparerOfString_Compare(string? x, string? y) => StrCmpLogical(x, y);
|
||||
|
||||
int IComparer.Compare(object? x, object? y) => IComparer_Compare(x, y);
|
||||
int IComparer<string>.Compare(string? x, string? y) => IComparerOfString_Compare(x, y);
|
||||
}
|
||||
1167
src/MpvNet/Player.cs
Normal file
1167
src/MpvNet/Player.cs
Normal file
File diff suppressed because it is too large
Load Diff
60
src/MpvNet/Settings.cs
Normal file
60
src/MpvNet/Settings.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using System.Xml;
|
||||
using System.Drawing;
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
[Serializable()]
|
||||
public class AppSettings
|
||||
{
|
||||
public bool InputDefaultBindingsFixApplied;
|
||||
public bool ShowMenuFixApplied;
|
||||
public int Volume = 70;
|
||||
public List<string> RecentFiles = new List<string>();
|
||||
public Point WindowLocation;
|
||||
public Point WindowPosition;
|
||||
public Size WindowSize;
|
||||
public string ConfigEditorSearch = "Video:";
|
||||
public string Mute = "no";
|
||||
}
|
||||
|
||||
class SettingsManager
|
||||
{
|
||||
public static string SettingsFile => Player.ConfigFolder + "settings.xml";
|
||||
|
||||
public static AppSettings Load()
|
||||
{
|
||||
if (!File.Exists(SettingsFile))
|
||||
return new AppSettings();
|
||||
|
||||
try
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(AppSettings));
|
||||
using FileStream fs = new FileStream(SettingsFile, FileMode.Open);
|
||||
return (AppSettings)serializer.Deserialize(fs)!;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Terminal.WriteError(ex.ToString());
|
||||
return new AppSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
using XmlTextWriter writer = new XmlTextWriter(SettingsFile, Encoding.UTF8);
|
||||
writer.Formatting = Formatting.Indented;
|
||||
writer.Indentation = 4;
|
||||
XmlSerializer serializer = new XmlSerializer(obj.GetType());
|
||||
serializer.Serialize(writer, obj);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Terminal.WriteError(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/MpvNet/Terminal.cs
Normal file
40
src/MpvNet/Terminal.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
namespace MpvNet;
|
||||
|
||||
public static class Terminal
|
||||
{
|
||||
static int Padding { get; } = 60;
|
||||
|
||||
public static void WriteError(object obj, string module = "mpv.net") => Write(obj, module, ConsoleColor.DarkRed, false);
|
||||
|
||||
public static void Write(object obj, string module = "mpv.net") => Write(obj, module, ConsoleColor.Black, true);
|
||||
|
||||
public static void Write(object obj, string module, ConsoleColor color, bool useDefaultColor)
|
||||
{
|
||||
string text = obj + "";
|
||||
|
||||
if (text == "")
|
||||
return;
|
||||
|
||||
if (!string.IsNullOrEmpty(module))
|
||||
module = "[" + module + "] ";
|
||||
|
||||
if (useDefaultColor)
|
||||
Console.ResetColor();
|
||||
else
|
||||
Console.ForegroundColor = color;
|
||||
|
||||
text = module + text;
|
||||
|
||||
if (text.Length < Padding)
|
||||
text = text.PadRight(Padding);
|
||||
|
||||
if (color == ConsoleColor.Red || color == ConsoleColor.DarkRed)
|
||||
Console.Error.WriteLine(text);
|
||||
else
|
||||
Console.WriteLine(text);
|
||||
|
||||
Console.ResetColor();
|
||||
Trace.WriteLine(obj);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user