Compare commits

...

10 Commits
2.9 ... 3.1

Author SHA1 Message Date
Frank Skare
2415e2ed43 - 2019-04-21 00:18:42 +02:00
Frank Skare
d5d26784e8 - 2019-04-21 00:04:39 +02:00
Frank Skare
6c1bad15f2 - 2019-04-21 00:00:48 +02:00
Frank Skare
5137e43aad - 2019-04-20 23:59:31 +02:00
Frank Skare
6fc0ebf9d5 - 2019-04-20 23:49:05 +02:00
Frank Skare
a0e30ff982 - 2019-04-20 23:27:14 +02:00
Frank Skare
c2a0d95851 - 2019-04-20 23:07:04 +02:00
Frank Skare
34d5d2fff5 - 2019-04-20 20:56:54 +02:00
Frank Skare
baa669fe1e - 2019-04-20 20:51:05 +02:00
Frank Skare
67ecebbf6b - 2019-04-20 04:34:44 +02:00
13 changed files with 376 additions and 279 deletions

View File

@@ -11,7 +11,7 @@ Public Class CSScriptAddon
Implements IAddon Implements IAddon
Sub New() Sub New()
Dim scriptDir = mp.mpvConfFolderPath + "scripts" Dim scriptDir = mp.MpvConfFolderPath + "scripts"
If Not Directory.Exists(scriptDir) Then Return If Not Directory.Exists(scriptDir) Then Return
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList
csFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\Scripts", "*.cs")) csFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\Scripts", "*.cs"))

View File

@@ -23,7 +23,7 @@ Table of contents
- Searchable options dialog with modern UI as mpv compatible standalone application - Searchable options dialog with modern UI as mpv compatible standalone application
- Searchable input (key/mouse) binding editor with modern UI as mpv compatible standalone application - Searchable input (key/mouse) binding editor with modern UI as mpv compatible standalone application
- Modern UI using the OS theme color and dark mode - Modern UI using the OS theme color and dark mode
- Rich addon API for .NET languages, over 700 available mpv properties - Rich addon/extension API for .NET languages, over 700 available mpv properties
- Rich scripting API for Python, C#, Lua, JavaScript and PowerShell - Rich scripting API for Python, C#, Lua, JavaScript and PowerShell
- mpv's OSC (on screen controller (play control bar)), IPC, conf files - mpv's OSC (on screen controller (play control bar)), IPC, conf files
@@ -61,18 +61,28 @@ if it's missing mpv.net generates it with the following defaults:
Scripting is supported via Python, C#, Lua, JavaScript and PowerShell Scripting is supported via Python, C#, Lua, JavaScript and PowerShell
https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lua,-PowerShell) [Scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lua,-PowerShell))
### Support ### Support
<https://forum.doom9.org/showthread.php?t=174841> [Support thread in Doom9 forum](https://forum.doom9.org/showthread.php?t=174841)
<https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows> [Support thread in VideoHelp forum](https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows)
<https://github.com/stax76/mpv.net/issues> [Issue tracker to report bugs and request features](https://github.com/stax76/mpv.net/issues)
### Changelog ### Changelog
### 3.0 (2019-04-20)
- the history feature logs now only files that were opened longer than 90 seconds
- the default input command for cycling the audio tracks was replaced with an
mpv.net command that shows detailed track info and has no 'no audio' track. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L89).
- new website at <https://mpv-net.github.io/mpv.net-web-site/>
- the Tracks menu supports now MKV edition selection. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L106).
- the Navigate menu supports now chapter selection. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L57).
- opening the context menu was crashing if the default binding for Tracks was missing
### 2.9 (2019-04-16) ### 2.9 (2019-04-16)
- clicking the right top corner in full screen mode - clicking the right top corner in full screen mode
@@ -96,6 +106,4 @@ https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lu
- the context menu has a new track menu where the active track - the context menu has a new track menu where the active track
can be seen and selected, it shows video, audio and subtitle can be seen and selected, it shows video, audio and subtitle
tracks with various metadata. [Menu default definition](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L104). tracks with various metadata. [Menu default definition](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L104).
The screenshots were updated showing the [new track menu](https://github.com/stax76/mpv.net#screenshots). The screenshots were updated showing the [new track menu](https://github.com/stax76/mpv.net#screenshots).
[go to download page](https://github.com/stax76/mpv.net/releases)

View File

@@ -10,7 +10,7 @@ namespace RatingAddon
[Export(typeof(IAddon))] [Export(typeof(IAddon))]
public class RatingAddon : IAddon public class RatingAddon : IAddon
{ {
private Dictionary<string, int> Dic = new Dictionary<string, int>(); Dictionary<string, int> Dic = new Dictionary<string, int>();
public RatingAddon() public RatingAddon()
{ {
@@ -18,7 +18,7 @@ namespace RatingAddon
mp.Shutdown += mpv_Shutdown; mp.Shutdown += mpv_Shutdown;
} }
private void mpv_Shutdown() void mpv_Shutdown()
{ {
foreach (var i in Dic) foreach (var i in Dic)
{ {
@@ -44,7 +44,7 @@ namespace RatingAddon
} }
} }
private void mpv_ClientMessage(string[] args) void mpv_ClientMessage(string[] args)
{ {
int rating; int rating;

View File

@@ -58,7 +58,7 @@ Public Class Msg
End Try End Try
End Sub End Sub
Private Shared ShownMessages As String Shared ShownMessages As String
Public Shared Sub ShowWarning(mainInstruction As String, Public Shared Sub ShowWarning(mainInstruction As String,
Optional content As String = Nothing, Optional content As String = Nothing,
@@ -421,11 +421,11 @@ Public Class TaskDialog(Of T)
Private ExitTickCount As Integer Private ExitTickCount As Integer
Private Function DialogProc(hwnd As IntPtr, Function DialogProc(hwnd As IntPtr,
msg As UInteger, msg As UInteger,
wParam As IntPtr, wParam As IntPtr,
lParam As IntPtr, lParam As IntPtr,
lpRefData As IntPtr) As Integer lpRefData As IntPtr) As Integer
Select Case msg Select Case msg
Case TDN_BUTTON_CLICKED, TDN_RADIO_BUTTON_CLICKED Case TDN_BUTTON_CLICKED, TDN_RADIO_BUTTON_CLICKED
If TypeOf SelectedValue Is MsgResult Then If TypeOf SelectedValue Is MsgResult Then
@@ -464,7 +464,7 @@ Public Class TaskDialog(Of T)
End Select End Select
End Function End Function
Private Sub MarshalDialogControlStructs() Sub MarshalDialogControlStructs()
If Not Buttons Is Nothing AndAlso Buttons.Count > 0 Then If Not Buttons Is Nothing AndAlso Buttons.Count > 0 Then
ButtonArray = AllocateAndMarshalButtons(Buttons) ButtonArray = AllocateAndMarshalButtons(Buttons)
Config.pButtons = ButtonArray Config.pButtons = ButtonArray
@@ -478,7 +478,7 @@ Public Class TaskDialog(Of T)
End If End If
End Sub End Sub
Private Shared Function AllocateAndMarshalButtons(structs As List(Of TASKDIALOG_BUTTON)) As IntPtr Shared Function AllocateAndMarshalButtons(structs As List(Of TASKDIALOG_BUTTON)) As IntPtr
Dim initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(TASKDIALOG_BUTTON)) * structs.Count) Dim initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(TASKDIALOG_BUTTON)) * structs.Count)
Dim currentPtr = initialPtr Dim currentPtr = initialPtr

View File

@@ -14,7 +14,7 @@ namespace mpvnet
[ImportMany] [ImportMany]
public IEnumerable<IAddon> Addons = null; public IEnumerable<IAddon> Addons = null;
private readonly CompositionContainer CompositionContainer; readonly CompositionContainer CompositionContainer;
public Addon() public Addon()
{ {
@@ -28,7 +28,7 @@ namespace mpvnet
foreach (string i in Directory.GetDirectories(dir)) foreach (string i in Directory.GetDirectories(dir))
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll")); catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
dir = mp.mpvConfFolderPath + "\\Addons"; dir = mp.MpvConfFolderPath + "\\Addons";
if (Directory.Exists(dir)) if (Directory.Exists(dir))
foreach (string i in Directory.GetDirectories(dir)) foreach (string i in Directory.GetDirectories(dir))

View File

@@ -2,8 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using VBNET; using VBNET;
@@ -15,7 +15,7 @@ namespace mpvnet
public string Name { get; set; } public string Name { get; set; }
public Action<string[]> Action { get; set; } public Action<string[]> Action { get; set; }
private static List<Command> commands; static List<Command> commands;
public static List<Command> Commands public static List<Command> Commands
{ {
@@ -58,7 +58,7 @@ namespace mpvnet
public static void open_conf_folder(string[] args) public static void open_conf_folder(string[] args)
{ {
Process.Start(mp.mpvConfFolderPath); Process.Start(mp.MpvConfFolderPath);
} }
public static void show_input_editor(string[] args) public static void show_input_editor(string[] args)
@@ -73,7 +73,7 @@ namespace mpvnet
public static void show_history(string[] args) public static void show_history(string[] args)
{ {
var fp = mp.mpvConfFolderPath + "history.txt"; var fp = mp.MpvConfFolderPath + "history.txt";
if (File.Exists(fp)) if (File.Exists(fp))
Process.Start(fp); Process.Start(fp);
@@ -197,5 +197,22 @@ namespace mpvnet
} }
})); }));
} }
public static void cycle_audio(string[] args)
{
string filePath = mp.get_property_string("path", false);
if (!File.Exists(filePath)) return;
using (MediaInfo mi = new MediaInfo(filePath))
{
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
if (audTracks.Length < 2) return;
int aid = mp.get_property_int("aid");
aid += 1;
if (aid > audTracks.Length) aid = 1;
mp.commandv("set", "aid", aid.ToString());
mp.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
}
}
} }
} }

View File

@@ -6,32 +6,35 @@ using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using VBNET; using VBNET;
using System.Threading.Tasks; using System.Globalization;
using System.ComponentModel;
namespace mpvnet namespace mpvnet
{ {
public partial class MainForm : Form public partial class MainForm : Form
{ {
public static MainForm Instance { get; set; } public static MainForm Instance { get; set; }
public static IntPtr Hwnd; public static IntPtr Hwnd { get; set; }
private Point LastCursorPosChanged;
private int LastCursorChangedTickCount;
private bool IgnoreDpiChanged = true;
private MenuItemEx TracksMenu;
private List<MediaTrack> MediaTracks = new List<MediaTrack>();
public new ContextMenuStripEx ContextMenu; public new ContextMenuStripEx ContextMenu;
private float MpvAutofit = 0.50f; MenuItemEx TracksMenu;
private bool MpvFullscreen; MenuItemEx ChaptersMenu;
private int MpvScreen = -1;
private string MpvNetDarkMode = "system"; Point LastCursorPosChanged;
private string MpvSid = ""; int LastCursorChangedTickCount;
private string MpvAid = ""; bool IgnoreDpiChanged = true;
private string MpvVid = "";
float MpvAutofit = 0.50f;
bool MpvFullscreen;
int MpvScreen = -1;
string MpvNetDarkMode = "system";
string MpvSid = "";
string MpvAid = "";
string MpvVid = "";
int MpvEdition;
public MainForm() public MainForm()
{ {
@@ -67,19 +70,21 @@ namespace mpvnet
} }
} }
private void ContextMenu_Opening(object sender, CancelEventArgs e) void ContextMenu_Opening(object sender, CancelEventArgs e)
{ {
lock (MediaTracks) lock (mp.MediaTracks)
{ {
TracksMenu.DropDownItems.Clear(); if (TracksMenu != null)
TracksMenu.DropDownItems.Clear();
MediaTrack[] audTracks = MediaTracks.Where(track => track.Type == "a").ToArray(); MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] subTracks = MediaTracks.Where(track => track.Type == "s").ToArray(); MediaTrack[] subTracks = mp.MediaTracks.Where(track => track.Type == "s").ToArray();
MediaTrack[] vidTracks = MediaTracks.Where(track => track.Type == "v").ToArray(); MediaTrack[] vidTracks = mp.MediaTracks.Where(track => track.Type == "v").ToArray();
MediaTrack[] ediTracks = mp.MediaTracks.Where(track => track.Type == "e").ToArray();
foreach (MediaTrack track in vidTracks) foreach (MediaTrack track in vidTracks)
{ {
var mi = ContextMenu.Add("Track > " + track.Text); MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
mi.Action = () => { mp.commandv("set", "vid", track.ID.ToString()); }; mi.Action = () => { mp.commandv("set", "vid", track.ID.ToString()); };
mi.Checked = MpvVid == track.ID.ToString(); mi.Checked = MpvVid == track.ID.ToString();
} }
@@ -89,7 +94,7 @@ namespace mpvnet
foreach (MediaTrack track in audTracks) foreach (MediaTrack track in audTracks)
{ {
var mi = ContextMenu.Add("Track > " + track.Text); MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
mi.Action = () => { mp.commandv("set", "aid", track.ID.ToString()); }; mi.Action = () => { mp.commandv("set", "aid", track.ID.ToString()); };
mi.Checked = MpvAid == track.ID.ToString(); mi.Checked = MpvAid == track.ID.ToString();
} }
@@ -99,17 +104,40 @@ namespace mpvnet
foreach (MediaTrack track in subTracks) foreach (MediaTrack track in subTracks)
{ {
var mi = ContextMenu.Add("Track > " + track.Text); MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
mi.Action = () => { mp.commandv("set", "sid", track.ID.ToString()); }; mi.Action = () => { mp.commandv("set", "sid", track.ID.ToString()); };
mi.Checked = MpvSid == track.ID.ToString(); mi.Checked = MpvSid == track.ID.ToString();
} }
if (subTracks.Length > 0) if (subTracks.Length > 0)
{ {
var mi = ContextMenu.Add("Track > S: No subtitles"); MenuItemEx mi = ContextMenu.Add("Track > S: No subtitles");
mi.Action = () => { mp.commandv("set", "sid", "no"); }; mi.Action = () => { mp.commandv("set", "sid", "no"); };
mi.Checked = MpvSid == "no"; mi.Checked = MpvSid == "no";
} }
if (ediTracks.Length > 0)
ContextMenu.Add("Track > -");
foreach (MediaTrack track in ediTracks)
{
MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
mi.Action = () => { mp.commandv("set", "edition", track.ID.ToString()); };
mi.Checked = MpvEdition == track.ID;
}
}
lock (mp.Chapters)
{
if (ChaptersMenu != null)
ChaptersMenu.DropDownItems.Clear();
foreach (var i in mp.Chapters)
{
MenuItemEx mi = ContextMenu.Add("Navigate > Chapters > " + i.Key);
mi.ShortcutKeyDisplayString = TimeSpan.FromSeconds(i.Value).ToString().Substring(0, 8) + " ";
mi.Action = () => { mp.commandv("seek", i.Value.ToString(CultureInfo.InvariantCulture), "absolute"); };
}
} }
} }
@@ -280,131 +308,39 @@ namespace mpvnet
menuItem.Text.Trim() == "Track") menuItem.Text.Trim() == "Track")
TracksMenu = menuItem; TracksMenu = menuItem;
if (ChaptersMenu == null && menuItem.Text.StartsWith("Chapters ") &&
menuItem.Text.Trim() == "Chapters")
ChaptersMenu = menuItem;
} }
} }
} }
private void ContextMenu_Opened(object sender, EventArgs e) => CursorHelp.Show(); void ContextMenu_Opened(object sender, EventArgs e) => CursorHelp.Show();
private string LastHistory; void mp_PlaybackRestart() => BeginInvoke(new Action(() => { Text = Path.GetFileName(mp.get_property_string("path")) + " - mpv.net " + Application.ProductVersion; }));
private void mp_PlaybackRestart() void Mp_Idle() => BeginInvoke(new Action(() => { Text = "mpv.net " + Application.ProductVersion; }));
{
string filePath = mp.get_property_string("path");
BeginInvoke(new Action(() => { Text = Path.GetFileName(filePath) + " - mpv.net " + Application.ProductVersion; }));
Task.Run(new Action(() => { void CM_Popup(object sender, EventArgs e) => CursorHelp.Show();
string historyFilepath = mp.mpvConfFolderPath + "history.txt";
if (LastHistory != filePath && File.Exists(historyFilepath)) void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
File.AppendAllText(historyFilepath, DateTime.Now.ToString() + " " +
Path.GetFileNameWithoutExtension(filePath) + "\r\n");
LastHistory = filePath;
}
lock (MediaTracks)
{
MediaTracks.Clear();
using (MediaInfo mi = new MediaInfo(filePath))
{
int count = mi.GetCount(MediaInfoStreamKind.Video);
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetVideo(i, "Format"));
Add(track, mi.GetVideo(i, "Format_Profile"));
Add(track, mi.GetVideo(i, "Width") + "x" + mi.GetVideo(i, "Height"));
Add(track, mi.GetVideo(i, "FrameRate") + " FPS");
Add(track, mi.GetVideo(i, "Language/String"));
Add(track, mi.GetVideo(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetVideo(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetVideo(i, "Title"));
track.Text = "V: " + track.Text.Trim(" ,".ToCharArray());
track.Type = "v";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = mi.GetCount(MediaInfoStreamKind.Audio);
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetAudio(i, "Language/String"));
Add(track, mi.GetAudio(i, "Format"));
Add(track, mi.GetAudio(i, "Format_Profile"));
Add(track, mi.GetAudio(i, "BitRate/String"));
Add(track, mi.GetAudio(i, "Channel(s)/String"));
Add(track, mi.GetAudio(i, "SamplingRate/String"));
Add(track, mi.GetAudio(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetAudio(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetAudio(i, "Title"));
track.Text = "A: " + track.Text.Trim(" ,".ToCharArray());
track.Type = "a";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = mi.GetCount(MediaInfoStreamKind.Text);
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetText(i, "Language/String"));
Add(track, mi.GetText(i, "Format"));
Add(track, mi.GetText(i, "Format_Profile"));
Add(track, mi.GetText(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetText(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetText(i, "Title"));
track.Text = "S: " + track.Text.Trim(" ,".ToCharArray());
track.Type = "s";
track.ID = i + 1;
MediaTracks.Add(track);
}
void Add(MediaTrack track, string val)
{
if (!string.IsNullOrEmpty(val) && !(track.Text != null && track.Text.Contains(val)))
track.Text += " " + val + ",";
}
}
}
}));
}
class MediaTrack
{
public string Text { get; set; }
public string Type { get; set; }
public int ID { get; set; }
}
private void Mp_Idle()
{
BeginInvoke(new Action(() => { Text = "mpv.net " + Application.ProductVersion; }));
}
private void CM_Popup(object sender, EventArgs e) => CursorHelp.Show();
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{ {
Msg.ShowException(e.Exception); Msg.ShowException(e.Exception);
} }
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
Msg.ShowError(e.ExceptionObject.ToString()); Msg.ShowError(e.ExceptionObject.ToString());
} }
private void mp_VideoSizeChanged() void mp_VideoSizeChanged()
{ {
BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight())); BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight()));
} }
private void mp_Shutdown() void mp_Shutdown()
{ {
BeginInvoke(new Action(() => Close())); BeginInvoke(new Action(() => Close()));
} }
@@ -531,12 +467,9 @@ namespace mpvnet
CursorHelp.Show(); CursorHelp.Show();
} }
bool IsMouseInOSC() bool IsMouseInOSC() => PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
{
return PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
}
private void Timer_Tick(object sender, EventArgs e) void Timer_Tick(object sender, EventArgs e)
{ {
if (CursorHelp.IsPosDifferent(LastCursorPosChanged)) if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
{ {
@@ -568,6 +501,7 @@ namespace mpvnet
mp.observe_property_string("sid", mpPropChangeSid); mp.observe_property_string("sid", mpPropChangeSid);
mp.observe_property_string("aid", mpPropChangeAid); mp.observe_property_string("aid", mpPropChangeAid);
mp.observe_property_string("vid", mpPropChangeVid); mp.observe_property_string("vid", mpPropChangeVid);
mp.observe_property_int("edition", mpPropChangeEdition);
mp.Shutdown += mp_Shutdown; mp.Shutdown += mp_Shutdown;
mp.VideoSizeChanged += mp_VideoSizeChanged; mp.VideoSizeChanged += mp_VideoSizeChanged;
mp.PlaybackRestart += mp_PlaybackRestart; mp.PlaybackRestart += mp_PlaybackRestart;
@@ -582,6 +516,8 @@ namespace mpvnet
void mpPropChangeVid(string value) => MpvVid = value; void mpPropChangeVid(string value) => MpvVid = value;
void mpPropChangeEdition(int value) => MpvEdition = value;
protected override void OnShown(EventArgs e) protected override void OnShown(EventArgs e)
{ {
base.OnShown(e); base.OnShown(e);
@@ -600,7 +536,7 @@ namespace mpvnet
{ {
base.OnFormClosed(e); base.OnFormClosed(e);
mp.commandv("quit"); mp.commandv("quit");
mp.AutoResetEvent.WaitOne(3000); mp.AutoResetEvent.WaitOne(3000);
} }
protected override void OnLostFocus(EventArgs e) protected override void OnLostFocus(EventArgs e)
@@ -615,14 +551,14 @@ namespace mpvnet
CheckYouTube(); CheckYouTube();
} }
private string LastURL;
void CheckYouTube() void CheckYouTube()
{ {
string clipboard = Clipboard.GetText(); string clipboard = Clipboard.GetText();
if (clipboard.StartsWith("https://www.youtube.com/watch?") && LastURL != clipboard && Visible)
if (clipboard.StartsWith("https://www.youtube.com/watch?") && RegistryHelp.GetValue("HKCU\\Software\\" + Application.ProductName, "LastYouTubeURL") != clipboard && Visible)
{ {
LastURL = clipboard; RegistryHelp.SetValue("HKCU\\Software\\" + Application.ProductName, "LastYouTubeURL", clipboard);
if (Msg.ShowQuestion("Play YouTube URL?") == MsgResult.OK) if (Msg.ShowQuestion("Play YouTube URL?") == MsgResult.OK)
mp.LoadURL(clipboard); mp.LoadURL(clipboard);
} }

View File

@@ -3,8 +3,8 @@ using System.Runtime.InteropServices;
public class MediaInfo : IDisposable public class MediaInfo : IDisposable
{ {
private IntPtr Handle; IntPtr Handle;
private static bool Loaded; static bool Loaded;
public MediaInfo(string sourcepath) public MediaInfo(string sourcepath)
{ {
@@ -42,7 +42,7 @@ public class MediaInfo : IDisposable
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name)); return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
} }
private bool Disposed; bool Disposed;
public void Dispose() public void Dispose()
{ {
@@ -57,32 +57,32 @@ public class MediaInfo : IDisposable
~MediaInfo() { Dispose(); } ~MediaInfo() { Dispose(); }
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string path); static extern IntPtr LoadLibrary(string path);
[DllImport("MediaInfo.dll")] [DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_New(); static extern IntPtr MediaInfo_New();
[DllImport("MediaInfo.dll")] [DllImport("MediaInfo.dll")]
private static extern void MediaInfo_Delete(IntPtr handle); static extern void MediaInfo_Delete(IntPtr handle);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern int MediaInfo_Open(IntPtr handle, string fileName); static extern int MediaInfo_Open(IntPtr handle, string fileName);
[DllImport("MediaInfo.dll")] [DllImport("MediaInfo.dll")]
private static extern int MediaInfo_Close(IntPtr handle); static extern int MediaInfo_Close(IntPtr handle);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr MediaInfo_Get(IntPtr handle, static extern IntPtr MediaInfo_Get(IntPtr handle,
MediaInfoStreamKind streamKind, MediaInfoStreamKind streamKind,
int streamNumber, int streamNumber,
string parameter, string parameter,
MediaInfoInfoKind kindOfInfo, MediaInfoInfoKind kindOfInfo,
MediaInfoInfoKind kindOfSearch); MediaInfoInfoKind kindOfSearch);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern int MediaInfo_Count_Get(IntPtr handle, static extern int MediaInfo_Count_Get(IntPtr handle,
MediaInfoStreamKind streamKind, MediaInfoStreamKind streamKind,
int streamNumber); int streamNumber);
} }
public enum MediaInfoStreamKind public enum MediaInfoStreamKind

View File

@@ -149,7 +149,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
public static Color ColorToolStrip3 { get; set; } public static Color ColorToolStrip3 { get; set; }
public static Color ColorToolStrip4 { get; set; } public static Color ColorToolStrip4 { get; set; }
private int TextOffset; int TextOffset;
public ToolStripRendererEx() public ToolStripRendererEx()
{ {
@@ -321,28 +321,28 @@ public struct HSLColor
Luminosity = l; Luminosity = l;
} }
private double hue; double _Hue;
public int Hue { public int Hue {
get => System.Convert.ToInt32(hue * 240); get => System.Convert.ToInt32(_Hue * 240);
set => hue = CheckRange(value / 240.0); set => _Hue = CheckRange(value / 240.0);
} }
private double saturation; double _Saturation;
public int Saturation { public int Saturation {
get => System.Convert.ToInt32(saturation * 240); get => System.Convert.ToInt32(_Saturation * 240);
set => saturation = CheckRange(value / 240.0); set => _Saturation = CheckRange(value / 240.0);
} }
private double luminosity; double _Luminosity;
public int Luminosity { public int Luminosity {
get => System.Convert.ToInt32(luminosity * 240); get => System.Convert.ToInt32(_Luminosity * 240);
set => luminosity = CheckRange(value / 240.0); set => _Luminosity = CheckRange(value / 240.0);
} }
private double CheckRange(double value) double CheckRange(double value)
{ {
if (value < 0) if (value < 0)
value = 0; value = 0;
@@ -367,21 +367,21 @@ public struct HSLColor
{ {
double r = 0, g = 0, b = 0; double r = 0, g = 0, b = 0;
if (luminosity != 0) if (_Luminosity != 0)
{ {
if (saturation == 0) if (_Saturation == 0)
{ {
b = luminosity; b = _Luminosity;
g = luminosity; g = _Luminosity;
r = luminosity; r = _Luminosity;
} }
else else
{ {
double temp2 = GetTemp2(this); double temp2 = GetTemp2(this);
double temp1 = 2.0 * luminosity - temp2; double temp1 = 2.0 * _Luminosity - temp2;
r = GetColorComponent(temp1, temp2, hue + 1.0 / 3.0); r = GetColorComponent(temp1, temp2, _Hue + 1.0 / 3.0);
g = GetColorComponent(temp1, temp2, hue); g = GetColorComponent(temp1, temp2, _Hue);
b = GetColorComponent(temp1, temp2, hue - 1.0 / 3.0); b = GetColorComponent(temp1, temp2, _Hue - 1.0 / 3.0);
} }
} }
@@ -391,7 +391,7 @@ public struct HSLColor
System.Convert.ToInt32(255 * b)); System.Convert.ToInt32(255 * b));
} }
private static double GetColorComponent(double temp1, double temp2, double temp3) static double GetColorComponent(double temp1, double temp2, double temp3)
{ {
temp3 = MoveIntoRange(temp3); temp3 = MoveIntoRange(temp3);
@@ -405,7 +405,7 @@ public struct HSLColor
return temp1; return temp1;
} }
private static double MoveIntoRange(double temp3) static double MoveIntoRange(double temp3)
{ {
if (temp3 < 0) if (temp3 < 0)
temp3 += 1; temp3 += 1;
@@ -414,14 +414,14 @@ public struct HSLColor
return temp3; return temp3;
} }
private static double GetTemp2(HSLColor hslColor) static double GetTemp2(HSLColor hslColor)
{ {
double temp2; double temp2;
if (hslColor.luminosity < 0.5) if (hslColor._Luminosity < 0.5)
temp2 = hslColor.luminosity * (1.0 + hslColor.saturation); temp2 = hslColor._Luminosity * (1.0 + hslColor._Saturation);
else else
temp2 = hslColor.luminosity + hslColor.saturation - (hslColor.luminosity * hslColor.saturation); temp2 = hslColor._Luminosity + hslColor._Saturation - (hslColor._Luminosity * hslColor._Saturation);
return temp2; return temp2;
} }
@@ -429,17 +429,17 @@ public struct HSLColor
public static HSLColor Convert(Color c) public static HSLColor Convert(Color c)
{ {
HSLColor r = new HSLColor(); HSLColor r = new HSLColor();
r.hue = c.GetHue() / 360.0; r._Hue = c.GetHue() / 360.0;
r.luminosity = c.GetBrightness(); r._Luminosity = c.GetBrightness();
r.saturation = c.GetSaturation(); r._Saturation = c.GetSaturation();
return r; return r;
} }
public void SetRGB(int red, int green, int blue) public void SetRGB(int red, int green, int blue)
{ {
HSLColor hc = HSLColor.Convert(Color.FromArgb(red, green, blue)); HSLColor hc = HSLColor.Convert(Color.FromArgb(red, green, blue));
hue = hc.hue; _Hue = hc._Hue;
saturation = hc.saturation; _Saturation = hc._Saturation;
luminosity = hc.luminosity; _Luminosity = hc._Luminosity;
} }
} }

View File

@@ -99,6 +99,15 @@ namespace mpvnet
rk.SetValue(name, value); rk.SetValue(name, value);
} }
public static string GetValue(string path, string name)
{
using (RegistryKey rk = GetRootKey(path).OpenSubKey(path.Substring(5)))
if (rk != null)
return rk.GetValue(name, "").ToString();
else
return "";
}
public static void RemoveKey(string path) public static void RemoveKey(string path)
{ {
GetRootKey(path).DeleteSubKeyTree(path.Substring(5), false); GetRootKey(path).DeleteSubKeyTree(path.Substring(5), false);
@@ -122,4 +131,11 @@ namespace mpvnet
} }
} }
} }
public class MediaTrack
{
public string Text { get; set; }
public string Type { get; set; }
public int ID { get; set; }
}
} }

View File

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

View File

@@ -53,6 +53,8 @@
_ ignore #menu: Navigate > - _ ignore #menu: Navigate > -
Ctrl+Right no-osd seek 300 #menu: Navigate > Jump 5 min forward Ctrl+Right no-osd seek 300 #menu: Navigate > Jump 5 min forward
Ctrl+Left no-osd seek -300 #menu: Navigate > Jump 5 min backward Ctrl+Left no-osd seek -300 #menu: Navigate > Jump 5 min backward
_ ignore #menu: Navigate > -
_ ignore #menu: Navigate > Chapters
Ctrl++ add video-zoom 0.1 #menu: Pan & Scan > Increase Size Ctrl++ add video-zoom 0.1 #menu: Pan & Scan > Increase Size
Ctrl+- add video-zoom -0.1 #menu: Pan & Scan > Decrease Size Ctrl+- add video-zoom -0.1 #menu: Pan & Scan > Decrease Size
@@ -84,7 +86,7 @@
d cycle deinterlace #menu: Video > Toggle Deinterlace d cycle deinterlace #menu: Video > Toggle Deinterlace
a cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" #menu: Video > Cycle Aspect Ratio a cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" #menu: Video > Cycle Aspect Ratio
KP7 cycle audio #menu: Audio > Cycle/Next KP7 script-message mpv.net cycle-audio #menu: Audio > Cycle/Next
_ ignore #menu: Audio > - _ ignore #menu: Audio > -
KP6 add audio-delay 0.100 #menu: Audio > Delay +0.1 KP6 add audio-delay 0.100 #menu: Audio > Delay +0.1
KP9 add audio-delay -0.100 #menu: Audio > Delay -0.1 KP9 add audio-delay -0.100 #menu: Audio > Delay -0.1
@@ -116,12 +118,12 @@
_ ignore #menu: Speed > - _ ignore #menu: Speed > -
BS set speed 1 #menu: Speed > Reset BS set speed 1 #menu: Speed > Reset
KP0 script-message rate-file 0 #menu: Addons > Rating > 0stars KP0 script-message rate-file 0 #menu: Extensions > Rating > 0stars
KP1 script-message rate-file 1 #menu: Addons > Rating > 1stars KP1 script-message rate-file 1 #menu: Extensions > Rating > 1stars
KP2 script-message rate-file 2 #menu: Addons > Rating > 2stars KP2 script-message rate-file 2 #menu: Extensions > Rating > 2stars
KP3 script-message rate-file 3 #menu: Addons > Rating > 3stars KP3 script-message rate-file 3 #menu: Extensions > Rating > 3stars
KP4 script-message rate-file 4 #menu: Addons > Rating > 4stars KP4 script-message rate-file 4 #menu: Extensions > Rating > 4stars
KP5 script-message rate-file 5 #menu: Addons > Rating > 5stars KP5 script-message rate-file 5 #menu: Extensions > Rating > 5stars
Ctrl+t set ontop yes #menu: View > On Top > Enable Ctrl+t set ontop yes #menu: View > On Top > Enable
Ctrl+T set ontop no #menu: View > On Top > Disable Ctrl+T set ontop no #menu: View > On Top > Disable
@@ -150,6 +152,7 @@
_ ignore #menu: - _ ignore #menu: -
Esc quit #menu: Exit Esc quit #menu: Exit
Q quit-watch-later #menu: Exit Watch Later Q quit-watch-later #menu: Exit Watch Later
> playlist-next > playlist-next
< playlist-prev < playlist-prev
Power quit Power quit

View File

@@ -53,20 +53,23 @@ namespace mpvnet
public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW
public static event Action Hook; // MPV_EVENT_HOOK public static event Action Hook; // MPV_EVENT_HOOK
public static IntPtr MpvHandle; public static IntPtr MpvHandle { get; set; }
public static IntPtr MpvWindowHandle; public static IntPtr MpvWindowHandle { get; set; }
public static Addon Addon; public static Addon Addon { get; set; }
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions = new List<KeyValuePair<string, Action<bool>>>(); public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<bool>>>();
public static List<KeyValuePair<string, Action<string>>> StringPropChangeActions = new List<KeyValuePair<string, Action<string>>>(); public static List<KeyValuePair<string, Action<int>>> IntPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<int>>>();
public static Size VideoSize = new Size(1920, 1080); public static List<KeyValuePair<string, Action<string>>> StringPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<string>>>();
public static string mpvConfFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\"; public static Size VideoSize { get; set; } = new Size(1920, 1080);
public static string InputConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf"; public static string MpvConfFolderPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
public static string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf"; public static string InputConfPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
public static string mpvNetConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpvnet.conf"; public static string MpvConfPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
public static List<PythonScript> PythonScripts => new List<PythonScript>(); public static string MpvNetConfPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpvnet.conf";
public static AutoResetEvent AutoResetEvent = new AutoResetEvent(false); public static List<PythonScript> PythonScripts { get; set; } = new List<PythonScript>();
public static AutoResetEvent AutoResetEvent { get; set; } = new AutoResetEvent(false);
public static List<MediaTrack> MediaTracks { get; set; } = new List<MediaTrack>();
public static List<KeyValuePair<string, double>> Chapters { get; set; } = new List<KeyValuePair<string, double>>();
private static Dictionary<string, string> _mpvConf; static Dictionary<string, string> _mpvConf;
public static Dictionary<string, string> mpvConf { public static Dictionary<string, string> mpvConf {
get { get {
@@ -74,8 +77,8 @@ namespace mpvnet
{ {
_mpvConf = new Dictionary<string, string>(); _mpvConf = new Dictionary<string, string>();
if (File.Exists(mpvConfPath)) if (File.Exists(MpvConfPath))
foreach (var i in File.ReadAllLines(mpvConfPath)) foreach (var i in File.ReadAllLines(MpvConfPath))
if (i.Contains("=") && ! i.StartsWith("#")) if (i.Contains("=") && ! i.StartsWith("#"))
_mpvConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim(); _mpvConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
} }
@@ -83,7 +86,7 @@ namespace mpvnet
} }
} }
private static Dictionary<string, string> _mpvNetConf; static Dictionary<string, string> _mpvNetConf;
public static Dictionary<string, string> mpvNetConf { public static Dictionary<string, string> mpvNetConf {
get { get {
@@ -91,8 +94,8 @@ namespace mpvnet
{ {
_mpvNetConf = new Dictionary<string, string>(); _mpvNetConf = new Dictionary<string, string>();
if (File.Exists(mpvNetConfPath)) if (File.Exists(MpvNetConfPath))
foreach (string i in File.ReadAllLines(mpvNetConfPath)) foreach (string i in File.ReadAllLines(MpvNetConfPath))
if (i.Contains("=") && !i.StartsWith("#")) if (i.Contains("=") && !i.StartsWith("#"))
_mpvNetConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim(); _mpvNetConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
} }
@@ -102,11 +105,11 @@ namespace mpvnet
public static void Init() public static void Init()
{ {
if (!Directory.Exists(mp.mpvConfFolderPath)) if (!Directory.Exists(mp.MpvConfFolderPath))
Directory.CreateDirectory(mp.mpvConfFolderPath); Directory.CreateDirectory(mp.MpvConfFolderPath);
if (!File.Exists(mp.mpvConfPath)) if (!File.Exists(mp.MpvConfPath))
File.WriteAllText(mp.mpvConfPath, Properties.Resources.mpv_conf); File.WriteAllText(mp.MpvConfPath, Properties.Resources.mpv_conf);
if (!File.Exists(mp.InputConfPath)) if (!File.Exists(mp.InputConfPath))
File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf); File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf);
@@ -143,7 +146,7 @@ namespace mpvnet
if (Path.GetExtension(scriptPath) == ".ps1") if (Path.GetExtension(scriptPath) == ".ps1")
PowerShellScript.Init(scriptPath); PowerShellScript.Init(scriptPath);
foreach (var scriptPath in Directory.GetFiles(mp.mpvConfFolderPath + "Scripts")) foreach (var scriptPath in Directory.GetFiles(mp.MpvConfFolderPath + "Scripts"))
if (Path.GetExtension(scriptPath) == ".py") if (Path.GetExtension(scriptPath) == ".py")
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath))); PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
else if (Path.GetExtension(scriptPath) == ".ps1") else if (Path.GetExtension(scriptPath) == ".ps1")
@@ -168,6 +171,7 @@ namespace mpvnet
{ {
case mpv_event_id.MPV_EVENT_SHUTDOWN: case mpv_event_id.MPV_EVENT_SHUTDOWN:
Shutdown?.Invoke(); Shutdown?.Invoke();
WriteHistory(null);
AutoResetEvent.Set(); AutoResetEvent.Set();
return; return;
case mpv_event_id.MPV_EVENT_LOG_MESSAGE: case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
@@ -266,6 +270,11 @@ namespace mpvnet
foreach (var i in StringPropChangeActions) foreach (var i in StringPropChangeActions)
if (i.Key == propData.name) if (i.Key == propData.name)
i.Value.Invoke(StringFromNativeUtf8(Marshal.PtrToStructure<IntPtr>(propData.data))); i.Value.Invoke(StringFromNativeUtf8(Marshal.PtrToStructure<IntPtr>(propData.data)));
if (propData.format == mpv_format.MPV_FORMAT_INT64)
foreach (var i in IntPropChangeActions)
if (i.Key == propData.name)
i.Value.Invoke(Marshal.PtrToStructure<int>(propData.data));
break; break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART: case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke(); PlaybackRestart?.Invoke();
@@ -275,7 +284,12 @@ namespace mpvnet
{ {
VideoSize = s; VideoSize = s;
VideoSizeChanged?.Invoke(); VideoSizeChanged?.Invoke();
} }
Task.Run(new Action(() => {
WriteHistory(mp.get_property_string("path"));
ReadMetaData();
}));
break; break;
case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE: case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE:
ChapterChange?.Invoke(); ChapterChange?.Invoke();
@@ -295,7 +309,7 @@ namespace mpvnet
} }
} }
private static List<PythonEventObject> PythonEventObjects = new List<PythonEventObject>(); static List<PythonEventObject> PythonEventObjects = new List<PythonEventObject>();
public static void register_event(string name, PyRT.PythonFunction pyFunc) public static void register_event(string name, PyRT.PythonFunction pyFunc)
{ {
@@ -437,6 +451,16 @@ namespace mpvnet
throw new Exception($"{name}: {(mpv_error)err}"); throw new Exception($"{name}: {(mpv_error)err}");
} }
public static void observe_property_int(string name, Action<int> action)
{
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_INT64);
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
else
IntPropChangeActions.Add(new KeyValuePair<string, Action<int>>(name, action));
}
public static void observe_property_bool(string name, Action<bool> action) public static void observe_property_bool(string name, Action<bool> action)
{ {
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG); int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
@@ -447,18 +471,6 @@ namespace mpvnet
BoolPropChangeActions.Add(new KeyValuePair<string, Action<bool>>(name, action)); BoolPropChangeActions.Add(new KeyValuePair<string, Action<bool>>(name, action));
} }
public static void unobserve_property_bool(string name, Action<bool> action)
{
foreach (var i in BoolPropChangeActions.ToArray())
if (i.Value == action)
BoolPropChangeActions.Remove(i);
int err = mpv_unobserve_property(MpvHandle, (ulong)action.GetHashCode());
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static void observe_property_string(string name, Action<string> action) public static void observe_property_string(string name, Action<string> action)
{ {
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_STRING); int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_STRING);
@@ -469,18 +481,6 @@ namespace mpvnet
StringPropChangeActions.Add(new KeyValuePair<string, Action<string>>(name, action)); StringPropChangeActions.Add(new KeyValuePair<string, Action<string>>(name, action));
} }
public static void unobserve_property_string(string name, Action<string> action)
{
foreach (var i in StringPropChangeActions.ToArray())
if (i.Value == action)
StringPropChangeActions.Remove(i);
int err = mpv_unobserve_property(MpvHandle, (ulong)action.GetHashCode());
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
}
protected static void ProcessCommandLine() protected static void ProcessCommandLine()
{ {
var args = Environment.GetCommandLineArgs().Skip(1); var args = Environment.GetCommandLineArgs().Skip(1);
@@ -533,9 +533,9 @@ namespace mpvnet
mp.LoadFolder(); mp.LoadFolder();
} }
private static bool WasFolderLoaded; static bool WasFolderLoaded;
public static void LoadFolder() static void LoadFolder()
{ {
if (WasFolderLoaded) if (WasFolderLoaded)
return; return;
@@ -561,7 +561,7 @@ namespace mpvnet
WasFolderLoaded = true; WasFolderLoaded = true;
} }
public static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers) static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
{ {
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel) int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
byteArrayPointers = new IntPtr[numberOfStrings]; byteArrayPointers = new IntPtr[numberOfStrings];
@@ -579,7 +579,7 @@ namespace mpvnet
return rootPointer; return rootPointer;
} }
public static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, int StringCount) static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, int StringCount)
{ {
IntPtr[] pIntPtrArray = new IntPtr[StringCount]; IntPtr[] pIntPtrArray = new IntPtr[StringCount];
string[] ManagedStringArray = new string[StringCount]; string[] ManagedStringArray = new string[StringCount];
@@ -591,7 +591,7 @@ namespace mpvnet
return ManagedStringArray; return ManagedStringArray;
} }
public static string StringFromNativeUtf8(IntPtr nativeUtf8) static string StringFromNativeUtf8(IntPtr nativeUtf8)
{ {
int len = 0; int len = 0;
while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len; while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
@@ -600,7 +600,124 @@ namespace mpvnet
return Encoding.UTF8.GetString(buffer); return Encoding.UTF8.GetString(buffer);
} }
public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0"); static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
static string LastHistoryPath;
static DateTime LastHistoryStartDateTime;
static void WriteHistory(string filePath)
{
int totalMinutes = Convert.ToInt32((DateTime.Now - LastHistoryStartDateTime).TotalMinutes);
if (File.Exists(LastHistoryPath) && totalMinutes > 1)
{
string historyFilepath = mp.MpvConfFolderPath + "history.txt";
File.AppendAllText(historyFilepath, DateTime.Now.ToString().Substring(0, 16) +
" " + totalMinutes.ToString().PadLeft(3) + " " +
Path.GetFileNameWithoutExtension(LastHistoryPath) + "\r\n");
}
LastHistoryPath = filePath;
LastHistoryStartDateTime = DateTime.Now;
}
static void ReadMetaData()
{
lock (MediaTracks)
{
MediaTracks.Clear();
using (MediaInfo mi = new MediaInfo(mp.get_property_string("path")))
{
int count = mi.GetCount(MediaInfoStreamKind.Video);
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetVideo(i, "Format"));
Add(track, mi.GetVideo(i, "Format_Profile"));
Add(track, mi.GetVideo(i, "Width") + "x" + mi.GetVideo(i, "Height"));
Add(track, mi.GetVideo(i, "FrameRate") + " FPS");
Add(track, mi.GetVideo(i, "Language/String"));
Add(track, mi.GetVideo(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetVideo(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetVideo(i, "Title"));
track.Text = "V: " + track.Text.Trim(" ,".ToCharArray());
track.Type = "v";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = mi.GetCount(MediaInfoStreamKind.Audio);
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetAudio(i, "Language/String"));
Add(track, mi.GetAudio(i, "Format"));
Add(track, mi.GetAudio(i, "Format_Profile"));
Add(track, mi.GetAudio(i, "BitRate/String"));
Add(track, mi.GetAudio(i, "Channel(s)/String"));
Add(track, mi.GetAudio(i, "SamplingRate/String"));
Add(track, mi.GetAudio(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetAudio(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetAudio(i, "Title"));
track.Text = "A: " + track.Text.Trim(" ,".ToCharArray());
track.Type = "a";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = mi.GetCount(MediaInfoStreamKind.Text);
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetText(i, "Language/String"));
Add(track, mi.GetText(i, "Format"));
Add(track, mi.GetText(i, "Format_Profile"));
Add(track, mi.GetText(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetText(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetText(i, "Title"));
track.Text = "S: " + track.Text.Trim(" ,".ToCharArray());
track.Type = "s";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = get_property_int("edition-list/count");
for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
track.Text = "E: " + get_property_string($"edition-list/{i}/title");
track.Type = "e";
track.ID = i;
MediaTracks.Add(track);
}
void Add(MediaTrack track, string val)
{
if (!string.IsNullOrEmpty(val) && !(track.Text != null && track.Text.Contains(val)))
track.Text += " " + val + ",";
}
}
}
lock (Chapters)
{
Chapters.Clear();
int count = get_property_int("chapter-list/count");
for (int x = 0; x < count; x++)
{
string text = get_property_string($"chapter-list/{x}/title");
double time = get_property_number($"chapter-list/{x}/time");
Chapters.Add(new KeyValuePair<string, double>(text, time));
}
}
}
} }
public enum EndFileEventMode public enum EndFileEventMode