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
Sub New()
Dim scriptDir = mp.mpvConfFolderPath + "scripts"
Dim scriptDir = mp.MpvConfFolderPath + "scripts"
If Not Directory.Exists(scriptDir) Then Return
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList
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 input (key/mouse) binding editor with modern UI as mpv compatible standalone application
- 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
- 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
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
<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
### 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)
- clicking the right top corner in full screen mode
@@ -97,5 +107,3 @@ https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lu
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).
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))]
public class RatingAddon : IAddon
{
private Dictionary<string, int> Dic = new Dictionary<string, int>();
Dictionary<string, int> Dic = new Dictionary<string, int>();
public RatingAddon()
{
@@ -18,7 +18,7 @@ namespace RatingAddon
mp.Shutdown += mpv_Shutdown;
}
private void mpv_Shutdown()
void mpv_Shutdown()
{
foreach (var i in Dic)
{
@@ -44,7 +44,7 @@ namespace RatingAddon
}
}
private void mpv_ClientMessage(string[] args)
void mpv_ClientMessage(string[] args)
{
int rating;

View File

@@ -58,7 +58,7 @@ Public Class Msg
End Try
End Sub
Private Shared ShownMessages As String
Shared ShownMessages As String
Public Shared Sub ShowWarning(mainInstruction As String,
Optional content As String = Nothing,
@@ -421,7 +421,7 @@ Public Class TaskDialog(Of T)
Private ExitTickCount As Integer
Private Function DialogProc(hwnd As IntPtr,
Function DialogProc(hwnd As IntPtr,
msg As UInteger,
wParam As IntPtr,
lParam As IntPtr,
@@ -464,7 +464,7 @@ Public Class TaskDialog(Of T)
End Select
End Function
Private Sub MarshalDialogControlStructs()
Sub MarshalDialogControlStructs()
If Not Buttons Is Nothing AndAlso Buttons.Count > 0 Then
ButtonArray = AllocateAndMarshalButtons(Buttons)
Config.pButtons = ButtonArray
@@ -478,7 +478,7 @@ Public Class TaskDialog(Of T)
End If
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 currentPtr = initialPtr

View File

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

View File

@@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
using VBNET;
@@ -15,7 +15,7 @@ namespace mpvnet
public string Name { get; set; }
public Action<string[]> Action { get; set; }
private static List<Command> commands;
static List<Command> commands;
public static List<Command> Commands
{
@@ -58,7 +58,7 @@ namespace mpvnet
public static void open_conf_folder(string[] args)
{
Process.Start(mp.mpvConfFolderPath);
Process.Start(mp.MpvConfFolderPath);
}
public static void show_input_editor(string[] args)
@@ -73,7 +73,7 @@ namespace mpvnet
public static void show_history(string[] args)
{
var fp = mp.mpvConfFolderPath + "history.txt";
var fp = mp.MpvConfFolderPath + "history.txt";
if (File.Exists(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.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using VBNET;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Globalization;
namespace mpvnet
{
public partial class MainForm : Form
{
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;
private float MpvAutofit = 0.50f;
private bool MpvFullscreen;
private int MpvScreen = -1;
private string MpvNetDarkMode = "system";
private string MpvSid = "";
private string MpvAid = "";
private string MpvVid = "";
MenuItemEx TracksMenu;
MenuItemEx ChaptersMenu;
Point LastCursorPosChanged;
int LastCursorChangedTickCount;
bool IgnoreDpiChanged = true;
float MpvAutofit = 0.50f;
bool MpvFullscreen;
int MpvScreen = -1;
string MpvNetDarkMode = "system";
string MpvSid = "";
string MpvAid = "";
string MpvVid = "";
int MpvEdition;
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)
{
if (TracksMenu != null)
TracksMenu.DropDownItems.Clear();
MediaTrack[] audTracks = MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] subTracks = MediaTracks.Where(track => track.Type == "s").ToArray();
MediaTrack[] vidTracks = MediaTracks.Where(track => track.Type == "v").ToArray();
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] subTracks = mp.MediaTracks.Where(track => track.Type == "s").ToArray();
MediaTrack[] vidTracks = mp.MediaTracks.Where(track => track.Type == "v").ToArray();
MediaTrack[] ediTracks = mp.MediaTracks.Where(track => track.Type == "e").ToArray();
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.Checked = MpvVid == track.ID.ToString();
}
@@ -89,7 +94,7 @@ namespace mpvnet
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.Checked = MpvAid == track.ID.ToString();
}
@@ -99,17 +104,40 @@ namespace mpvnet
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.Checked = MpvSid == track.ID.ToString();
}
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.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")
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()
{
string filePath = mp.get_property_string("path");
BeginInvoke(new Action(() => { Text = Path.GetFileName(filePath) + " - mpv.net " + Application.ProductVersion; }));
void Mp_Idle() => BeginInvoke(new Action(() => { Text = "mpv.net " + Application.ProductVersion; }));
Task.Run(new Action(() => {
string historyFilepath = mp.mpvConfFolderPath + "history.txt";
void CM_Popup(object sender, EventArgs e) => CursorHelp.Show();
if (LastHistory != filePath && File.Exists(historyFilepath))
{
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)
void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
Msg.ShowException(e.Exception);
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Msg.ShowError(e.ExceptionObject.ToString());
}
private void mp_VideoSizeChanged()
void mp_VideoSizeChanged()
{
BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight()));
}
private void mp_Shutdown()
void mp_Shutdown()
{
BeginInvoke(new Action(() => Close()));
}
@@ -531,12 +467,9 @@ namespace mpvnet
CursorHelp.Show();
}
bool IsMouseInOSC()
{
return PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
}
bool IsMouseInOSC() => 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))
{
@@ -568,6 +501,7 @@ namespace mpvnet
mp.observe_property_string("sid", mpPropChangeSid);
mp.observe_property_string("aid", mpPropChangeAid);
mp.observe_property_string("vid", mpPropChangeVid);
mp.observe_property_int("edition", mpPropChangeEdition);
mp.Shutdown += mp_Shutdown;
mp.VideoSizeChanged += mp_VideoSizeChanged;
mp.PlaybackRestart += mp_PlaybackRestart;
@@ -582,6 +516,8 @@ namespace mpvnet
void mpPropChangeVid(string value) => MpvVid = value;
void mpPropChangeEdition(int value) => MpvEdition = value;
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
@@ -615,14 +551,14 @@ namespace mpvnet
CheckYouTube();
}
private string LastURL;
void CheckYouTube()
{
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)
mp.LoadURL(clipboard);
}

View File

@@ -3,8 +3,8 @@ using System.Runtime.InteropServices;
public class MediaInfo : IDisposable
{
private IntPtr Handle;
private static bool Loaded;
IntPtr Handle;
static bool Loaded;
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));
}
private bool Disposed;
bool Disposed;
public void Dispose()
{
@@ -57,22 +57,22 @@ public class MediaInfo : IDisposable
~MediaInfo() { Dispose(); }
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string path);
static extern IntPtr LoadLibrary(string path);
[DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_New();
static extern IntPtr MediaInfo_New();
[DllImport("MediaInfo.dll")]
private static extern void MediaInfo_Delete(IntPtr handle);
static extern void MediaInfo_Delete(IntPtr handle);
[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")]
private static extern int MediaInfo_Close(IntPtr handle);
static extern int MediaInfo_Close(IntPtr handle);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr MediaInfo_Get(IntPtr handle,
static extern IntPtr MediaInfo_Get(IntPtr handle,
MediaInfoStreamKind streamKind,
int streamNumber,
string parameter,
@@ -80,7 +80,7 @@ public class MediaInfo : IDisposable
MediaInfoInfoKind kindOfSearch);
[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,
int streamNumber);
}

View File

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

View File

@@ -99,6 +99,15 @@ namespace mpvnet
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)
{
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
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.9.0.0")]
[assembly: AssemblyFileVersion("2.9.0.0")]
[assembly: AssemblyVersion("3.0.0.0")]
[assembly: AssemblyFileVersion("3.0.0.0")]

View File

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

View File

@@ -53,20 +53,23 @@ namespace mpvnet
public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW
public static event Action Hook; // MPV_EVENT_HOOK
public static IntPtr MpvHandle;
public static IntPtr MpvWindowHandle;
public static Addon Addon;
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions = new List<KeyValuePair<string, Action<bool>>>();
public static List<KeyValuePair<string, Action<string>>> StringPropChangeActions = new List<KeyValuePair<string, Action<string>>>();
public static Size VideoSize = new Size(1920, 1080);
public static string mpvConfFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
public static string InputConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
public static string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
public static string mpvNetConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpvnet.conf";
public static List<PythonScript> PythonScripts => new List<PythonScript>();
public static AutoResetEvent AutoResetEvent = new AutoResetEvent(false);
public static IntPtr MpvHandle { get; set; }
public static IntPtr MpvWindowHandle { get; set; }
public static Addon Addon { get; set; }
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<bool>>>();
public static List<KeyValuePair<string, Action<int>>> IntPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<int>>>();
public static List<KeyValuePair<string, Action<string>>> StringPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<string>>>();
public static Size VideoSize { get; set; } = new Size(1920, 1080);
public static string MpvConfFolderPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
public static string InputConfPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
public static string MpvConfPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
public static string MpvNetConfPath { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpvnet.conf";
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 {
get {
@@ -74,8 +77,8 @@ namespace mpvnet
{
_mpvConf = new Dictionary<string, string>();
if (File.Exists(mpvConfPath))
foreach (var i in File.ReadAllLines(mpvConfPath))
if (File.Exists(MpvConfPath))
foreach (var i in File.ReadAllLines(MpvConfPath))
if (i.Contains("=") && ! i.StartsWith("#"))
_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 {
get {
@@ -91,8 +94,8 @@ namespace mpvnet
{
_mpvNetConf = new Dictionary<string, string>();
if (File.Exists(mpvNetConfPath))
foreach (string i in File.ReadAllLines(mpvNetConfPath))
if (File.Exists(MpvNetConfPath))
foreach (string i in File.ReadAllLines(MpvNetConfPath))
if (i.Contains("=") && !i.StartsWith("#"))
_mpvNetConf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
}
@@ -102,11 +105,11 @@ namespace mpvnet
public static void Init()
{
if (!Directory.Exists(mp.mpvConfFolderPath))
Directory.CreateDirectory(mp.mpvConfFolderPath);
if (!Directory.Exists(mp.MpvConfFolderPath))
Directory.CreateDirectory(mp.MpvConfFolderPath);
if (!File.Exists(mp.mpvConfPath))
File.WriteAllText(mp.mpvConfPath, Properties.Resources.mpv_conf);
if (!File.Exists(mp.MpvConfPath))
File.WriteAllText(mp.MpvConfPath, Properties.Resources.mpv_conf);
if (!File.Exists(mp.InputConfPath))
File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf);
@@ -143,7 +146,7 @@ namespace mpvnet
if (Path.GetExtension(scriptPath) == ".ps1")
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")
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
else if (Path.GetExtension(scriptPath) == ".ps1")
@@ -168,6 +171,7 @@ namespace mpvnet
{
case mpv_event_id.MPV_EVENT_SHUTDOWN:
Shutdown?.Invoke();
WriteHistory(null);
AutoResetEvent.Set();
return;
case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
@@ -266,6 +270,11 @@ namespace mpvnet
foreach (var i in StringPropChangeActions)
if (i.Key == propData.name)
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;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke();
@@ -276,6 +285,11 @@ namespace mpvnet
VideoSize = s;
VideoSizeChanged?.Invoke();
}
Task.Run(new Action(() => {
WriteHistory(mp.get_property_string("path"));
ReadMetaData();
}));
break;
case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE:
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)
{
@@ -437,6 +451,16 @@ namespace mpvnet
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)
{
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));
}
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)
{
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));
}
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()
{
var args = Environment.GetCommandLineArgs().Skip(1);
@@ -533,9 +533,9 @@ namespace mpvnet
mp.LoadFolder();
}
private static bool WasFolderLoaded;
static bool WasFolderLoaded;
public static void LoadFolder()
static void LoadFolder()
{
if (WasFolderLoaded)
return;
@@ -561,7 +561,7 @@ namespace mpvnet
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)
byteArrayPointers = new IntPtr[numberOfStrings];
@@ -579,7 +579,7 @@ namespace mpvnet
return rootPointer;
}
public static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, int StringCount)
static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, int StringCount)
{
IntPtr[] pIntPtrArray = new IntPtr[StringCount];
string[] ManagedStringArray = new string[StringCount];
@@ -591,7 +591,7 @@ namespace mpvnet
return ManagedStringArray;
}
public static string StringFromNativeUtf8(IntPtr nativeUtf8)
static string StringFromNativeUtf8(IntPtr nativeUtf8)
{
int len = 0;
while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
@@ -600,7 +600,124 @@ namespace mpvnet
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