Compare commits

...

5 Commits
1.5 ... 1.7

Author SHA1 Message Date
Frank Skare
e7d41ff626 - 2019-03-23 15:42:57 +01:00
Frank Skare
f2c526348d - 2019-03-23 04:24:33 +01:00
Frank Skare
b4d2a7e86d - 2019-03-23 04:21:45 +01:00
Frank Skare
98f8e7090a - 2019-03-23 04:10:26 +01:00
Frank Skare
aeb5958be6 - 2019-03-23 04:07:47 +01:00
13 changed files with 232 additions and 111 deletions

View File

@@ -1,5 +1,6 @@
Imports System.ComponentModel.Composition
Imports System.IO
Imports System.Windows.Forms
Imports mpvnet
Imports mpvnet.StaticUsing
@@ -13,7 +14,8 @@ Public Class CSScriptAddon
Sub New()
Dim scriptDir = mp.mpvConfFolderPath + "scripts"
If Not Directory.Exists(scriptDir) Then Return
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs")
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList
csFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\Scripts", "*.cs"))
If csFiles.Count = 0 Then Return
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom

View File

@@ -55,6 +55,7 @@
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />

101
README.md
View File

@@ -18,23 +18,33 @@ mpv manual: https://mpv.io/manual/master/
### Context Menu
The context menu can be customized via input.conf file located at:
C:\Users\Frank\AppData\Roaming\mpv\input.conf
```
C:\Users\username\AppData\Roaming\mpv\input.conf
```
if it's missing mpv.net generates it with the following defaults:
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt
### Settings
mpv.net shares the settings with mpv, settings have to be edited in a config file called mpv.conf located at:
```
C:\Users\username\AppData\Roaming\mpv\mpv.conf
```
if it's missing mpv.net generates it with the following defaults:
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt
### C# Scripting
A simple C# script located at:
C:\Users\Frank\AppData\Roaming\mpv\scripts\test.cs
```
C:\Users\username\AppData\Roaming\mpv\scripts\fullscreen.cs
```
or
startup\scripts\test.cs
```
startup\scripts\fullscreen.cs
```
```
using mpvnet;
@@ -42,14 +52,14 @@ class Script
{
public Script()
{
var fs = mpv.GetStringProp("fullscreen");
mpv.Command("show-text", "fullscreen: " + fs);
mpv.ObserveBoolProp("fullscreen", FullscreenChange);
var fs = mp.get_property_string("fullscreen");
mp.commandv("show-text", "fullscreen: " + fs);
mp.observe_property_bool("fullscreen", FullscreenChange);
}
void FullscreenChange(bool val)
{
mpv.Command("show-text", "fullscreen: " + val.ToString());
mp.commandv("show-text", "fullscreen: " + val.ToString());
}
}
```
@@ -57,13 +67,13 @@ class Script
### Python Scripting
A simple Python script located at:
C:\Users\user\AppData\Roaming\mpv\scripts
```
C:\Users\user\AppData\Roaming\mpv\scripts\seek-show-position.py
```
or
startup\scripts
```
startup\scripts\seek-show-position.py
```
```
# when seeking displays position and
# duration like so: 70:00 / 80:00
@@ -96,23 +106,32 @@ mp.register_event("seek", seek) # or use: mp.Seek += seek
### PowerShell Scripting
A simple PowerShell script located at:
C:\Users\user\AppData\Roaming\mpv\scripts
```
C:\Users\user\AppData\Roaming\mpv\scripts\seek.ps1
```
or
startup\scripts
Please note that PowerShell don't allow assigning to events and mpv.net uses as workaround the script filename.
```
startup\scripts\seek.ps1
```
```
$position = [mp]::get_property_number("time-pos");
[mp]::commandv("show-text", $position.ToString() + " seconds")
```
Please note that PowerShell don't allow assigning to events and mpv.net uses as workaround a matching script filename, a list of available events can be found in the mpv manual or in the file mp.cs in the mpv.net source code.
### Changes
### not yet released
### 1.7
- showing the conf files mpv.net uses now the app that is registered for txt files, before it just shell executed the conf file which only worked if conf files were associated with an application
- leaving fullscreen mode the previous window size and position wasn't restored
- when the source video aspect ratio changes the height is kept and the width is adjusted and a check is performed to assure the window is within screen bounds
### 1.6
- a crash caused by WM_APPCOMMAND (multimedia keyboards) commands was fixed
- support for the 'screen' property was added, it should work both from mpv.conf (screen = 1) and from command line (--screen=1)
- per monitor DPI awareness and better multi monitor support was added
### 1.5
@@ -144,29 +163,3 @@ $position = [mp]::get_property_number("time-pos");
### 1.0
- much more feature packed context menu
### 0.2.5
- mpv lib updated to 2019-02-24
- UI glitch fixed the appeared when started in fullscreen mode
- fixed default video output mode which caused video playback to fail
### 0.2.4
- changed minimum runtime to .NET 4.7.2
- fixed mpv.net not working with new mpv lib
- the track name in the title bar was sometimes wrong
- mpv lib updated to 2018-12-16
- quit-watch-later added to context menu (Shift+Q) to exit and resume at the last position
- ab loop added to menu
- added the possibility to modify mpv.conf settings using the context menu
- added link to the manual and default keys to the menu
### 0.2.2
- history feature added
- mpv lib updated
### 0.2.1
- right-click in fullscreen in the right-left corner closes the app

View File

@@ -62,12 +62,12 @@ namespace mpvnet
public static void show_keys(string[] args)
{
Process.Start(mp.InputConfPath);
Process.Start(NativeHelp.GetAssociatedApplication(".txt"), mp.InputConfPath);
}
public static void show_prefs(string[] args)
{
Process.Start(mp.mpvConfPath);
Process.Start(NativeHelp.GetAssociatedApplication(".txt"), mp.mpvConfPath);
}
public static void history(string[] args)
@@ -148,7 +148,7 @@ namespace mpvnet
bitrate = "0";
var bitrate2 = Convert.ToDouble(bitrate) / 1000.0 / 1000.0;
var format = mp.get_property_string("video-format").ToUpper();
var videoCodec = mp.get_property_string("video-format").ToUpper();
var filename = fileInfo.Name;
var text =
@@ -157,7 +157,7 @@ namespace mpvnet
FormatTime(duration.TotalMinutes) + ":" +
FormatTime(duration.Seconds) + "\n" +
Convert.ToInt32(fileInfo.Length / 1024 / 1024).ToString() +
$" MB - {width} x {height}\n{format} - {bitrate2.ToString("f1")} Mb/s" + "\n" + filename;
$" MB - {width} x {height}\n{videoCodec} - {bitrate2.ToString("f1")} Mb/s" + "\n" + filename;
mp.commandv("show-text", text, "5000");
}

View File

@@ -42,7 +42,8 @@
// MainForm
//
this.AllowDrop = true;
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(1012, 615);
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));

View File

@@ -6,6 +6,8 @@ using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;
using static mpvnet.StaticUsing;
using System.Linq;
using System.Collections.Generic;
namespace mpvnet
{
@@ -16,6 +18,7 @@ namespace mpvnet
private Point LastCursorPosChanged;
private int LastCursorChangedTickCount;
private bool IgnoreDpiChanged = true;
public ContextMenuStripEx CMS;
@@ -26,15 +29,110 @@ namespace mpvnet
try
{
Application.ThreadException += Application_ThreadException;
SetFormPositionAndSize();
Instance = this;
Hwnd = Handle;
Text += " " + Application.ProductVersion;
ChangeFullscreen((mp.mpvConv.ContainsKey("fullscreen") && mp.mpvConv["fullscreen"] == "yes") || (mp.mpvConv.ContainsKey("fs") && mp.mpvConv["fs"] == "yes"));
if (mp.mpvConf.ContainsKey("screen"))
SetScreen(Convert.ToInt32(mp.mpvConf["screen"]));
else
SetScreen(Screen.PrimaryScreen);
ChangeFullscreen((mp.mpvConf.ContainsKey("fullscreen") && mp.mpvConf["fullscreen"] == "yes") ||
(mp.mpvConf.ContainsKey("fs") && mp.mpvConf["fs"] == "yes"));
ProcessCommandLineEarly();
}
catch (Exception ex)
catch (Exception e)
{
HandleException(ex);
MsgError(e.ToString());
}
}
protected void SetScreen(int targetIndex)
{
Screen[] screens = Screen.AllScreens;
if (targetIndex < 0 || targetIndex > screens.Length - 1) return;
SetScreen(screens[Array.IndexOf(screens, screens[targetIndex])]);
}
protected void SetScreen(Screen screen)
{
Rectangle target = screen.Bounds;
Left = target.X + Convert.ToInt32((target.Width - Width) / 2.0);
Top = target.Y + Convert.ToInt32((target.Height - Height) / 2.0);
SetStartFormPositionAndSize();
}
void SetStartFormPositionAndSize()
{
if (IsFullscreen || mp.VideoSize.Width == 0) return;
Screen screen = Screen.FromControl(this);
int height = Convert.ToInt32(screen.Bounds.Height * 0.6);
int width = Convert.ToInt32(height * mp.VideoSize.Width / (double)mp.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
NativeHelp.AddWindowBorders(Handle, ref rect);
int left = middlePos.X - rect.Width / 2;
int top = middlePos.Y - rect.Height / 2;
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, left, top, rect.Width, rect.Height, 4 /* SWP_NOZORDER */);
}
void SetFormPositionAndSizeKeepHeight()
{
if (IsFullscreen || mp.VideoSize.Width == 0) return;
Screen screen = Screen.FromControl(this);
int height = ClientSize.Height;
int width = Convert.ToInt32(height * mp.VideoSize.Width / (double)mp.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
NativeHelp.AddWindowBorders(Handle, ref rect);
int left = middlePos.X - rect.Width / 2;
int top = middlePos.Y - rect.Height / 2;
Screen[] screens = Screen.AllScreens;
if (left < screens[0].Bounds.Left)
left = screens[0].Bounds.Left;
int maxLeft = screens[0].Bounds.Left + screens.Select((sc) => sc.Bounds.Width).Sum() - rect.Width - SystemInformation.CaptionHeight;
if (left > maxLeft)
left = maxLeft;
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, left, top, rect.Width, rect.Height, 4 /* SWP_NOZORDER */);
}
protected void ProcessCommandLineEarly()
{
var args = Environment.GetCommandLineArgs().Skip(1);
foreach (string i in args)
{
if (i.StartsWith("--"))
{
if (i.Contains("="))
{
string left = i.Substring(2, i.IndexOf("=") - 2);
string right = i.Substring(left.Length + 3);
if (left == "screen")
SetScreen(Convert.ToInt32(right));
ChangeFullscreen((left == "fs" || left == "fullscreen") && right == "yes");
}
else
{
string switchName = i.Substring(2);
switch (switchName)
{
case "fs":
case "fullscreen":
ChangeFullscreen(true);
break;
}
}
}
}
}
@@ -107,17 +205,12 @@ namespace mpvnet
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}
void HandleException(Exception e)
{
MsgError(e.ToString());
MsgError(e.Exception.ToString());
}
private void mp_VideoSizeChanged()
{
BeginInvoke(new Action(() => SetFormPositionAndSize()));
BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight()));
}
private void mp_Shutdown()
@@ -139,14 +232,17 @@ namespace mpvnet
{
if (value)
{
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
if (FormBorderStyle != FormBorderStyle.None)
{
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
}
}
else
{
WindowState = FormWindowState.Normal;
FormBorderStyle = FormBorderStyle.Sizable;
SetFormPositionAndSize();
SetFormPositionAndSizeKeepHeight();
}
}
@@ -164,7 +260,7 @@ namespace mpvnet
break;
case 0x319: // WM_APPCOMMAND
if (mp.MpvWindowHandle != IntPtr.Zero)
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
Native.PostMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x0104: // WM_SYSKEYDOWN:
if (mp.MpvWindowHandle != IntPtr.Zero)
@@ -178,14 +274,19 @@ namespace mpvnet
if (!IsMouseInOSC())
mp.command_string("cycle fullscreen");
break;
case 0x02E0: // WM_DPICHANGED
if (IgnoreDpiChanged) break;
var r2 = Marshal.PtrToStructure<Native.RECT>(m.LParam);
Native.SetWindowPos(Handle, IntPtr.Zero, r2.Left, r2.Top, r2.Width, r2.Height, 0);
break;
case 0x0214: // WM_SIZING
var rc = Marshal.PtrToStructure<Native.RECT>(m.LParam);
var r = rc;
NativeHelp.SubtractWindowBorders(Handle, ref r);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
float aspect = mp.VideoSize.Width / (float)mp.VideoSize.Height;
int d_w = (int)(c_h * aspect - c_w);
int d_h = (int)(c_w / aspect - c_h);
int d_w = Convert.ToInt32(c_h * aspect - c_w);
int d_h = Convert.ToInt32(c_w / aspect - c_h);
int[] d_corners = { d_w, d_h, -d_w, -d_h };
int[] corners = { rc.Left, rc.Top, rc.Right, rc.Bottom };
int corner = NativeHelp.GetResizeBorder(m.WParam.ToInt32());
@@ -201,24 +302,6 @@ namespace mpvnet
base.WndProc(ref m);
}
void SetFormPositionAndSize()
{
if (IsFullscreen || mp.VideoSize.Width == 0) return;
var wa = Screen.GetWorkingArea(this);
int h = (int)(wa.Height * 0.6);
int w = (int)(h * mp.VideoSize.Width / (float)mp.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var r = new Native.RECT(new Rectangle(0, 0, w, h));
NativeHelp.AddWindowBorders(Handle, ref r);
int l = middlePos.X - r.Width / 2;
int t = middlePos.Y - r.Height / 2;
if (l < 0) l = 0;
if (t < 0) t = 0;
if (l + r.Width > wa.Width ) l = wa.Width - r.Width;
if (t + r.Height > wa.Height ) t = wa.Height - r.Height;
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, l, t, r.Width, r.Height, 4 /* SWP_NOZORDER */);
}
protected override void OnDragEnter(DragEventArgs e)
{
base.OnDragEnter(e);
@@ -239,7 +322,6 @@ namespace mpvnet
{
base.OnMouseDown(e);
// window-dragging
if (WindowState == FormWindowState.Normal &&
e.Button == MouseButtons.Left &&
e.Y < ClientSize.Height * 0.9)
@@ -260,8 +342,6 @@ namespace mpvnet
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
// send mouse command to make OSC show
mp.command_string($"mouse {e.X} {e.Y}");
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
@@ -306,6 +386,7 @@ namespace mpvnet
CMS.Opened += CMS_Opened;
ContextMenuStrip = CMS;
BuildMenu();
IgnoreDpiChanged = false;
}
protected override void OnFormClosed(FormClosedEventArgs e)

View File

@@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@@ -43,4 +44,17 @@ namespace mpvnet
return MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
}
}
//public class OSVersion
//{
// public static float Windows7 { get; set; } = 6.1f;
// public static float Windows8 { get; set; } = 6.2f;
// public static float Windows81 { get; set; } = 6.3f;
// public static float Windows10 { get; set; } = 10f;
// public static float Current
// {
// get => Environment.OSVersion.Version.Major + Environment.OSVersion.Version.Minor / 10f;
// }
//}
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace mpvnet
{
@@ -30,6 +32,9 @@ namespace mpvnet
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint AssocQueryString(uint flags, uint str, string pszAssoc, string pszExtra, StringBuilder pszOut, ref uint pcchOut);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{

View File

@@ -1,4 +1,6 @@
using System;
using System.IO;
using System.Text;
namespace mpvnet
{
@@ -34,5 +36,25 @@ namespace mpvnet
{
Native.AdjustWindowRect(ref rc, (uint)Native.GetWindowLongPtrW(hwnd, -16 /* GWL_STYLE */), false);
}
public static string GetAssociatedApplication(string ext)
{
uint returnValue = 0U;
// ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE
if (1 == Native.AssocQueryString(0x40, 2, ext, null, null, ref returnValue))
{
if (returnValue > 0)
{
StringBuilder sb = new StringBuilder(Convert.ToInt32(returnValue));
// ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE
if (0 == Native.AssocQueryString(0x40, 2, ext, null, sb, ref returnValue))
{
var ret = sb.ToString();
if (File.Exists(ret)) return ret;
}
}
}
return "";
}
}
}

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("1.5.0.0")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: AssemblyVersion("1.7.0.0")]
[assembly: AssemblyFileVersion("1.7.0.0")]

View File

@@ -38,7 +38,7 @@
w add panscan -0.1 #menu: W ; Pan && Scan > Decrease Height
W add panscan +0.1 #menu: Shift+W ; Pan && Scan > Increase Height
_ ignore #menu: _ ; Pan && Scan > -
Ctrl+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 #menu: Shift+Backspace ; Pan && Scan > Reset
Ctrl+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 #menu: Ctrl+Backspace ; Pan && Scan > Reset
Ctrl+1 add contrast -1 #menu: Ctrl+1 ; Video > Decrease Contrast
Ctrl+2 add contrast 1 #menu: Ctrl+2 ; Video > Increase Contrast

View File

@@ -25,7 +25,9 @@
</compatibility>
<application>
<windowsSettings>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
<dependency>

View File

@@ -64,20 +64,20 @@ namespace mpvnet
public static List<PythonScript> PythonScripts { get; } = new List<PythonScript>();
public static AutoResetEvent AutoResetEvent = new AutoResetEvent(false);
private static Dictionary<string, string> _mpvConv;
private static Dictionary<string, string> _mpvConf;
public static Dictionary<string, string> mpvConv {
public static Dictionary<string, string> mpvConf {
get {
if (_mpvConv == null)
if (_mpvConf == null)
{
_mpvConv = new Dictionary<string, string>();
_mpvConf = new Dictionary<string, string>();
if (File.Exists(mpvConfPath))
foreach (var i in File.ReadAllLines(mpvConfPath))
if (i.Contains("=") && ! i.StartsWith("#"))
_mpvConv[i.Left("=").Trim()] = i.Right("=").Trim();
_mpvConf[i.Left("=").Trim()] = i.Right("=").Trim();
}
return _mpvConv;
return _mpvConf;
}
}