Compare commits

..

7 Commits
2.8 ... 2.9

Author SHA1 Message Date
Frank Skare
e9a8b1962a - 2019-04-16 19:04:52 +02:00
Frank Skare
3ded1573f4 - 2019-04-16 18:46:24 +02:00
Frank Skare
d38adcfc70 - 2019-04-16 18:42:03 +02:00
Frank Skare
5f1f5b3811 - 2019-04-16 18:31:39 +02:00
Frank Skare
c18c70c2af - 2019-04-16 18:14:22 +02:00
Frank Skare
9cdd76e1ac - 2019-04-13 03:07:57 +02:00
Frank Skare
7db8a1e534 - 2019-04-13 03:05:07 +02:00
20 changed files with 543 additions and 365 deletions

View File

@@ -22,7 +22,8 @@ Table of contents
- Customizable context menu defined in the same file as the key bindings - Customizable context menu defined in the same file as the key bindings
- 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
- Rich addon API for .NET languages - Modern UI using the OS theme color and dark mode
- Rich addon 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
@@ -30,6 +31,8 @@ Table of contents
![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvnet.png) ![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvnet.png)
![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvnetContextMenu.png)
![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvConfEdit.png) ![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvConfEdit.png)
![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvInputEdit.png) ![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshots/mpvInputEdit.png)
@@ -56,7 +59,7 @@ if it's missing mpv.net generates it with the following defaults:
### Scripting ### Scripting
Scripting is supported for 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) https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lua,-PowerShell)
@@ -70,51 +73,29 @@ https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lu
### Changelog ### Changelog
### 2.8 (2019-04-12) ### 2.9 (2019-04-16)
- Win 7 dark-mode render issue fix - clicking the right top corner in full screen mode
closes the player but it did not work on all displays
- the info display was changed to display the filename on top
so it's not displayed in the middle of the screen
- on start up of the conf editor all text is now selected in the
search text box so it's ready for a new search to be typed
- the conf editor was changed to write the settings to disk
only if the settings were actually modified, also the message
that says that the settings will be available on next start
is now only shown if the settings were actually modified.
- there was an instance in the context menu where the sub menu
arrow was overlapping with the text
- in the input editor when only one character is entered in the
search text box the search is performed only in the input and
not in the command or menu
- in the input editor the routine that generates the input string
was completely rewritten because it was adding Shift where it
wasn't necessary (it took a huge amount of time to implement)
- the context menu has a new track menu where the active track
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).
### 2.7 (2019-04-12) [go to download page](https://github.com/stax76/mpv.net/releases)
- the autofit mpv property was added to the conf editor
- the routine that writes the mpv.conf file in the conf editor was completely rewritten
- the conf editor has a dedicated page for mpv.net specific settings,
these settings are saved in the same folder as mpv.conf using mpvnet.conf as filename,
the first setting there is dark-mode
- new optional dark theme
[go to download page](https://github.com/stax76/mpv.net/releases)
### 2.6 (2019-04-09)
- on Win 7 controls in the conf editor were using a difficult too read too light color
- context menu renderer changed to look like Win 10 design, except colors are still system theme colors
### 2.5 (2019-04-08)
- in case the input conf don't contain a menu definition mpv.net creates the default menu instead no menu like before
- all message boxes were migrated to use the TaskDialog API
- an improvement in the previous release unfortunately introduced a bug
causing the conf editor not to save settings
### 2.4 (2019-04-06)
- new options added to the conf GUI editor: gpu-context, gpu-api, scale, cscale,
dscale, dither-depth, correct-downscaling, sigmoid-upscaling, deband
- the conf edit GUI has a 'Apply' feature added to write the conf to mpv.conf
without the need to close the conf edit GUI
- the input edit GUI shows a message box when a duplicate is detected and it has
a new feature to reduce the filter scope to eather of input, menu or command and
the editor writes always the same help on top of input.conf as it is found in the defaults
- the conf edit GUI was often starting out of working area bounds and is now starting with center screen
- the startup size was reduced and a issue was fixed that when the screen property
was defined for a screen that isn't connected the startup size wasn't applied
- added feature to load external audio and subtitle files in the menu under:
Open > Load external audio|subtitle files (default binding at:
[input.conf](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt))
- previously the conf edit GUI removed settings from the conf file if the setting
was set to the default, the new behavior is not to remove anything
- the autofit mpv property was partly implemented, you can use 'autofit = 50%' in mpv.conf or
'--autofit=50%' on the command line, WxH isn't implemented and only percent values are accepted.
There is a new wiki page explaining the mpv.net limitations compared to the original mpv:
[Limitations](https://github.com/stax76/mpv.net/wiki/Limitations)

View File

@@ -89,9 +89,9 @@ namespace mpvnet
{ {
try try
{ {
var fileInfo = new FileInfo(mp.get_property_string("path")); FileInfo fileInfo = new FileInfo(mp.get_property_string("path"));
using (var mediaInfo = new MediaInfo(fileInfo.FullName)) using (MediaInfo mediaInfo = new MediaInfo(fileInfo.FullName))
{ {
string width = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "Width"); string width = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "Width");
@@ -107,11 +107,11 @@ namespace mpvnet
string text = ""; string text = "";
if (performer != "") text += "Artist: " + performer + "\n"; if (performer != "") text += "Artist: " + performer + "\n";
if (title != "") text += "Title: " + title + "\n"; if (title != "") text += "Title: " + title + "\n";
if (album != "") text += "Album: " + album + "\n"; if (album != "") text += "Album: " + album + "\n";
if (genre != "") text += "Genre: " + genre + "\n"; if (genre != "") text += "Genre: " + genre + "\n";
if (date != "") text += "Year: " + date + "\n"; if (date != "") text += "Year: " + date + "\n";
if (duration != "") text += "Length: " + duration + "\n"; if (duration != "") text += "Length: " + duration + "\n";
mp.commandv("show-text", text, "5000"); mp.commandv("show-text", text, "5000");
} }
@@ -125,17 +125,19 @@ namespace mpvnet
if (bitrate == "") if (bitrate == "")
bitrate = "0"; bitrate = "0";
var bitrate2 = Convert.ToDouble(bitrate) / 1000.0 / 1000.0; double bitrate2 = Convert.ToDouble(bitrate) / 1000.0 / 1000.0;
var videoCodec = mp.get_property_string("video-format").ToUpper(); string videoCodec = mp.get_property_string("video-format").ToUpper();
var filename = fileInfo.Name; string filename = fileInfo.Name;
var text = string text = filename + "\n" +
FormatTime(position.TotalMinutes) + ":" + FormatTime(position.TotalMinutes) + ":" +
FormatTime(position.Seconds) + " / " + FormatTime(position.Seconds) + " / " +
FormatTime(duration.TotalMinutes) + ":" + FormatTime(duration.TotalMinutes) + ":" +
FormatTime(duration.Seconds) + "\n" + FormatTime(duration.Seconds) + "\n" +
Convert.ToInt32(fileInfo.Length / 1024 / 1024).ToString() + $"{width} x {height}\n" +
$" MB - {width} x {height}\n{videoCodec} - {bitrate2.ToString("f1")} Mb/s" + "\n" + filename; $"{bitrate2.ToString("f1")} Mb/s\n" +
Convert.ToInt32(fileInfo.Length / 1024 / 1024).ToString() + " MB\n" +
$"{videoCodec}\n";
mp.commandv("show-text", text, "5000"); mp.commandv("show-text", text, "5000");
} }

View File

@@ -8,6 +8,8 @@ using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using VBNET; using VBNET;
using System.Threading.Tasks;
using System.ComponentModel;
namespace mpvnet namespace mpvnet
{ {
@@ -19,12 +21,17 @@ namespace mpvnet
private Point LastCursorPosChanged; private Point LastCursorPosChanged;
private int LastCursorChangedTickCount; private int LastCursorChangedTickCount;
private bool IgnoreDpiChanged = true; private bool IgnoreDpiChanged = true;
private MenuItemEx TracksMenu;
private List<MediaTrack> MediaTracks = new List<MediaTrack>();
public new ContextMenuStripEx ContextMenu;
private float MpvAutofit = 0.50f; private float MpvAutofit = 0.50f;
private bool MpvFullscreen; private bool MpvFullscreen;
private int MpvScreen = -1; private int MpvScreen = -1;
private string MpvNetDarkMode = "system"; private string MpvNetDarkMode = "system";
private string MpvSid = "";
public ContextMenuStripEx CMS; private string MpvAid = "";
private string MpvVid = "";
public MainForm() public MainForm()
{ {
@@ -60,6 +67,52 @@ namespace mpvnet
} }
} }
private void ContextMenu_Opening(object sender, CancelEventArgs e)
{
lock (MediaTracks)
{
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();
foreach (MediaTrack track in vidTracks)
{
var mi = ContextMenu.Add("Track > " + track.Text);
mi.Action = () => { mp.commandv("set", "vid", track.ID.ToString()); };
mi.Checked = MpvVid == track.ID.ToString();
}
if (vidTracks.Length > 0)
ContextMenu.Add("Track > -");
foreach (MediaTrack track in audTracks)
{
var mi = ContextMenu.Add("Track > " + track.Text);
mi.Action = () => { mp.commandv("set", "aid", track.ID.ToString()); };
mi.Checked = MpvAid == track.ID.ToString();
}
if (subTracks.Length > 0)
ContextMenu.Add("Track > -");
foreach (MediaTrack track in subTracks)
{
var 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");
mi.Action = () => { mp.commandv("set", "sid", "no"); };
mi.Checked = MpvSid == "no";
}
}
}
protected void SetScreen(int targetIndex) protected void SetScreen(int targetIndex)
{ {
Screen[] screens = Screen.AllScreens; Screen[] screens = Screen.AllScreens;
@@ -210,7 +263,7 @@ namespace mpvnet
else else
input = ""; input = "";
var menuItem = CMS.Add(path, () => { MenuItemEx menuItem = ContextMenu.Add(path, () => {
try { try {
mp.command_string(command); mp.command_string(command);
} }
@@ -220,26 +273,113 @@ namespace mpvnet
}); });
if (menuItem != null) if (menuItem != null)
menuItem.ShortcutKeyDisplayString = input.Replace("_","") + " "; {
menuItem.ShortcutKeyDisplayString = input.Replace("_", "") + " ";
if (TracksMenu == null && menuItem.Text.StartsWith("Track ") &&
menuItem.Text.Trim() == "Track")
TracksMenu = menuItem;
}
} }
} }
private void CMS_Opened(object sender, EventArgs e) => CursorHelp.Show(); private void ContextMenu_Opened(object sender, EventArgs e) => CursorHelp.Show();
private string LastHistory; private string LastHistory;
private void mp_PlaybackRestart() private void mp_PlaybackRestart()
{ {
var filename = mp.get_property_string("filename"); string filePath = mp.get_property_string("path");
BeginInvoke(new Action(() => { Text = filename + " - mpv.net " + Application.ProductVersion; })); BeginInvoke(new Action(() => { Text = Path.GetFileName(filePath) + " - mpv.net " + Application.ProductVersion; }));
var historyFilepath = mp.mpvConfFolderPath + "history.txt";
if (LastHistory != filename && File.Exists(historyFilepath)) Task.Run(new Action(() => {
{ string historyFilepath = mp.mpvConfFolderPath + "history.txt";
File.AppendAllText(historyFilepath, DateTime.Now.ToString() + " " +
Path.GetFileNameWithoutExtension(filename) + "\r\n"); if (LastHistory != filePath && File.Exists(historyFilepath))
LastHistory = filename; {
} 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() private void Mp_Idle()
@@ -378,11 +518,7 @@ namespace mpvnet
Native.PostMessage(Handle, 0xA1 /* WM_NCLBUTTONDOWN */, HTCAPTION, IntPtr.Zero); Native.PostMessage(Handle, 0xA1 /* WM_NCLBUTTONDOWN */, HTCAPTION, IntPtr.Zero);
} }
var sb = Screen.FromControl(this).Bounds; if (Width - e.Location.X < 10 && e.Location.Y < 10)
var p1 = new Point(sb.Width, 0);
var p2 = PointToScreen(e.Location);
if (Math.Abs(p1.X - p2.X) < 10 && Math.Abs(p1.Y - p2.Y) < 10)
mp.commandv("quit"); mp.commandv("quit");
} }
@@ -409,7 +545,7 @@ namespace mpvnet
} }
else if (Environment.TickCount - LastCursorChangedTickCount > 1500 && else if (Environment.TickCount - LastCursorChangedTickCount > 1500 &&
!IsMouseInOSC() && ClientRectangle.Contains(PointToClient(MousePosition)) && !IsMouseInOSC() && ClientRectangle.Contains(PointToClient(MousePosition)) &&
Form.ActiveForm == this && !CMS.Visible) Form.ActiveForm == this && !ContextMenu.Visible)
{ {
CursorHelp.Hide(); CursorHelp.Hide();
} }
@@ -429,6 +565,9 @@ namespace mpvnet
mp.Init(); mp.Init();
mp.observe_property_bool("fullscreen", mpPropChangeFullscreen); mp.observe_property_bool("fullscreen", mpPropChangeFullscreen);
mp.observe_property_bool("ontop", mpPropChangeOnTop); mp.observe_property_bool("ontop", mpPropChangeOnTop);
mp.observe_property_string("sid", mpPropChangeSid);
mp.observe_property_string("aid", mpPropChangeAid);
mp.observe_property_string("vid", mpPropChangeVid);
mp.Shutdown += mp_Shutdown; mp.Shutdown += mp_Shutdown;
mp.VideoSizeChanged += mp_VideoSizeChanged; mp.VideoSizeChanged += mp_VideoSizeChanged;
mp.PlaybackRestart += mp_PlaybackRestart; mp.PlaybackRestart += mp_PlaybackRestart;
@@ -437,15 +576,22 @@ namespace mpvnet
void mpPropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value)); void mpPropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value));
void mpPropChangeAid(string value) => MpvAid = value;
void mpPropChangeSid(string value) => MpvSid = value;
void mpPropChangeVid(string value) => MpvVid = value;
protected override void OnShown(EventArgs e) protected override void OnShown(EventArgs e)
{ {
base.OnShown(e); base.OnShown(e);
if ((MpvNetDarkMode == "system" && Misc.IsDarkTheme) || MpvNetDarkMode == "always") if ((MpvNetDarkMode == "system" && Misc.IsDarkTheme) || MpvNetDarkMode == "always")
ToolStripRendererEx.ColorTheme = Color.Black; ToolStripRendererEx.ColorTheme = Color.Black;
CMS = new ContextMenuStripEx(components); ContextMenu = new ContextMenuStripEx(components);
CMS.Opened += CMS_Opened; ContextMenu.Opened += ContextMenu_Opened;
ContextMenuStrip = CMS; ContextMenu.Opening += ContextMenu_Opening;
BuildMenu(); BuildMenu();
ContextMenuStrip = ContextMenu;
IgnoreDpiChanged = false; IgnoreDpiChanged = false;
CheckYouTube(); CheckYouTube();
} }

View File

@@ -25,6 +25,23 @@ public class MediaInfo : IDisposable
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, 0, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name)); return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, 0, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
} }
public int GetCount(MediaInfoStreamKind streamKind) => MediaInfo_Count_Get(Handle, streamKind, -1);
public string GetVideo(int streamNumber, string parameter)
{
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
}
public string GetAudio(int streamNumber, string parameter)
{
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
}
public string GetText(int streamNumber, string parameter)
{
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
}
private bool Disposed; private bool Disposed;
public void Dispose() public void Dispose()
@@ -37,10 +54,7 @@ public class MediaInfo : IDisposable
} }
} }
~MediaInfo() ~MediaInfo() { Dispose(); }
{
Dispose();
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string path); private static extern IntPtr LoadLibrary(string path);
@@ -49,16 +63,26 @@ public class MediaInfo : IDisposable
private static extern IntPtr MediaInfo_New(); private static extern IntPtr MediaInfo_New();
[DllImport("MediaInfo.dll")] [DllImport("MediaInfo.dll")]
private static extern void MediaInfo_Delete(IntPtr Handle); private 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); private static extern int MediaInfo_Open(IntPtr handle, string fileName);
[DllImport("MediaInfo.dll")] [DllImport("MediaInfo.dll")]
private static extern int MediaInfo_Close(IntPtr Handle); private 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, MediaInfoStreamKind StreamKind, int StreamNumber, string Parameter, MediaInfoInfoKind KindOfInfo, MediaInfoInfoKind KindOfSearch); private static extern IntPtr MediaInfo_Get(IntPtr handle,
MediaInfoStreamKind streamKind,
int streamNumber,
string parameter,
MediaInfoInfoKind kindOfInfo,
MediaInfoInfoKind kindOfSearch);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern int MediaInfo_Count_Get(IntPtr handle,
MediaInfoStreamKind streamKind,
int streamNumber);
} }
public enum MediaInfoStreamKind public enum MediaInfoStreamKind
@@ -67,8 +91,10 @@ public enum MediaInfoStreamKind
Video, Video,
Audio, Audio,
Text, Text,
Chapters, Other,
Image Image,
Menu,
Max,
} }
public enum MediaInfoInfoKind public enum MediaInfoInfoKind

View File

@@ -6,7 +6,6 @@ using System.Drawing.Text;
using Microsoft.Win32; using Microsoft.Win32;
using System.Windows.Forms; using System.Windows.Forms;
using System.Drawing; using System.Drawing;
using System.Diagnostics;
public class ContextMenuStripEx : ContextMenuStrip public class ContextMenuStripEx : ContextMenuStrip
{ {
@@ -24,110 +23,23 @@ public class ContextMenuStripEx : ContextMenuStrip
Renderer = new ToolStripRendererEx(); Renderer = new ToolStripRendererEx();
} }
public ActionMenuItem Add(string path) public MenuItemEx Add(string path)
{ {
return Add(path, null); return Add(path, null);
} }
public ActionMenuItem Add(string path, Action action) public MenuItemEx Add(string path, Action action, bool enabled = true)
{ {
return Add(path, action, true); MenuItemEx ret = MenuItemEx.Add(Items, path, action);
} if (ret == null) return null;
public ActionMenuItem Add(string path, Action action, bool enabled)
{
var ret = ActionMenuItem.Add(Items, path, action);
if (ret == null)
return null;
ret.Enabled = enabled; ret.Enabled = enabled;
return ret; return ret;
} }
public ActionMenuItem Add(string path, Action action, Func<bool> enabledFunc)
{
var ret = ActionMenuItem.Add(Items, path, action);
return ret;
}
}
public class ActionMenuItem : MenuItemEx
{
private Action Action;
public ActionMenuItem()
{
}
public ActionMenuItem(string text, Action action)
{
this.Text = text;
this.Action = action;
}
protected override void OnClick(EventArgs e)
{
Application.DoEvents();
if (Action != null)
Action();
base.OnClick(e);
}
public static ActionMenuItem Add<T>(ToolStripItemCollection items, string path, Action<T> action, T value)
{
return Add(items, path, () => action(value));
}
public static ActionMenuItem Add(ToolStripItemCollection items, string path, Action action)
{
var a = path.Split(new[] { " > ", " | " }, StringSplitOptions.RemoveEmptyEntries);
var l = items;
for (var x = 0; x <= a.Length - 1; x++)
{
var found = false;
foreach (var i in l.OfType<ToolStripMenuItem>())
{
if (x < a.Length - 1)
{
if (i.Text == a[x] + " ")
{
found = true;
l = i.DropDownItems;
}
}
}
if (!found)
{
if (x == a.Length - 1)
{
if (a[x] == "-")
l.Add(new ToolStripSeparator());
else
{
ActionMenuItem item = new ActionMenuItem(a[x] + " ", action);
l.Add(item);
l = item.DropDownItems;
return item;
}
}
else
{
ActionMenuItem item = new ActionMenuItem();
item.Text = a[x] + " ";
l.Add(item);
l = item.DropDownItems;
}
}
}
return null;
}
} }
public class MenuItemEx : ToolStripMenuItem public class MenuItemEx : ToolStripMenuItem
{ {
public static bool UseTooltips { get; set; } public Action Action { get; set; }
public MenuItemEx() public MenuItemEx()
{ {
@@ -137,20 +49,81 @@ public class MenuItemEx : ToolStripMenuItem
{ {
} }
public MenuItemEx(string text, Action action) : base(text)
{
Action = action;
}
protected override void OnClick(EventArgs e)
{
Application.DoEvents();
Action?.Invoke();
base.OnClick(e);
}
public static MenuItemEx Add<T>(ToolStripItemCollection items, string path, Action<T> action, T value)
{
return Add(items, path, () => action(value));
}
public static MenuItemEx Add(ToolStripItemCollection items, string path, Action action)
{
string[] a = path.Split(new[] { " > ", " | " }, StringSplitOptions.RemoveEmptyEntries);
var itemsCollection = items;
for (int x = 0; x < a.Length; x++)
{
bool found = false;
foreach (var i in itemsCollection.OfType<ToolStripMenuItem>())
{
if (x < a.Length - 1)
{
if (i.Text == a[x] + " ")
{
found = true;
itemsCollection = i.DropDownItems;
}
}
}
if (!found)
{
if (x == a.Length - 1)
{
if (a[x] == "-")
itemsCollection.Add(new ToolStripSeparator());
else
{
MenuItemEx item = new MenuItemEx(a[x] + " ", action);
itemsCollection.Add(item);
itemsCollection = item.DropDownItems;
return item;
}
}
else
{
MenuItemEx item = new MenuItemEx();
item.Text = a[x] + " ";
itemsCollection.Add(item);
itemsCollection = item.DropDownItems;
}
}
}
return null;
}
public override Size GetPreferredSize(Size constrainingSize) public override Size GetPreferredSize(Size constrainingSize)
{ {
var ret = base.GetPreferredSize(constrainingSize); Size size = base.GetPreferredSize(constrainingSize);
ret.Height = Convert.ToInt32(Font.Height * 1.4); size.Height = Convert.ToInt32(Font.Height * 1.4);
return ret; return size;
} }
public void CloseAll(object item) public void CloseAll(object item)
{ {
if (item is ToolStripItem) if (item is ToolStripItem)
{ CloseAll(((ToolStripItem)item).Owner);
var d = (ToolStripItem)item;
CloseAll(d.Owner);
}
if (item is ToolStripDropDown) if (item is ToolStripDropDown)
{ {
@@ -159,12 +132,6 @@ public class MenuItemEx : ToolStripMenuItem
CloseAll(d.OwnerItem); CloseAll(d.OwnerItem);
} }
} }
protected override void OnClick(EventArgs e)
{
Application.DoEvents();
base.OnClick(e);
}
} }
public class ToolStripRendererEx : ToolStripSystemRenderer public class ToolStripRendererEx : ToolStripSystemRenderer
@@ -187,6 +154,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
public ToolStripRendererEx() public ToolStripRendererEx()
{ {
var argb = Convert.ToInt32(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0)); var argb = Convert.ToInt32(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0));
if (argb == 0) if (argb == 0)
argb = Color.LightBlue.ToArgb(); argb = Color.LightBlue.ToArgb();
if (ColorTheme == Color.Empty) if (ColorTheme == Color.Empty)
@@ -198,7 +166,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
public static void InitColors(Color c) public static void InitColors(Color c)
{ {
ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100); ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100);
ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(200); ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(160);
ColorSelection = HSLColor.Convert(c).ToColorSetLuminosity(180); ColorSelection = HSLColor.Convert(c).ToColorSetLuminosity(180);
ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(210); ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(210);
ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240); ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240);
@@ -209,6 +177,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
ColorBackground = Color.FromArgb(50, 50, 50); ColorBackground = Color.FromArgb(50, 50, 50);
ColorSelection = Color.FromArgb(80, 80, 80); ColorSelection = Color.FromArgb(80, 80, 80);
ColorForeground = Color.White; ColorForeground = Color.White;
ColorChecked = Color.FromArgb(90, 90, 90);
} }
ColorToolStrip1 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 1))); ColorToolStrip1 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 1)));
@@ -259,20 +228,18 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{ {
e.Item.ForeColor = Color.Black; Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
var r = new Rectangle(Point.Empty, e.Item.Size);
var g = e.Graphics;
if (!(e.Item.Owner is MenuStrip)) if (!(e.Item.Owner is MenuStrip))
g.Clear(ColorBackground); e.Graphics.Clear(ColorBackground);
if (e.Item.Selected && e.Item.Enabled) if (e.Item.Selected && e.Item.Enabled)
{ {
g.SmoothingMode = SmoothingMode.AntiAlias; e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
var r2 = new Rectangle(r.X + 2, r.Y, r.Width - 4, r.Height - 1); rect = new Rectangle(rect.X + 2, rect.Y, rect.Width - 4, rect.Height - 1);
r2.Inflate(-1, -1); rect.Inflate(-1, -1);
using (SolidBrush b = new SolidBrush(ColorSelection)) using (SolidBrush b = new SolidBrush(ColorSelection))
g.FillRectangle(b, r2); e.Graphics.FillRectangle(b, rect);
} }
} }
@@ -299,8 +266,32 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
{ {
int x = Convert.ToInt32(e.ImageRectangle.Height * 0.2); if (e.Item.GetType() != typeof(MenuItemEx))
e.Graphics.DrawImage(e.Image, new Point(x, x)); return;
MenuItemEx item = e.Item as MenuItemEx;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
if (!item.Checked)
return;
Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
rect = new Rectangle(rect.X + 2, rect.Y, rect.Height - 1, rect.Height - 1);
rect.Inflate(-1, -1);
using (Brush brush = new SolidBrush(ColorChecked))
e.Graphics.FillRectangle(brush, rect);
float ellipseWidth = rect.Height / 3f;
RectangleF rectF = new RectangleF(rect.X + rect.Height / 2f - ellipseWidth / 2f,
rect.Y + rect.Height / 2f - ellipseWidth / 2f,
ellipseWidth,
ellipseWidth);
using (Brush brush = new SolidBrush(ColorForeground))
e.Graphics.FillEllipse(brush, rectF);
} }
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
@@ -332,24 +323,21 @@ public struct HSLColor
private double hue; private 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; private 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; private 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);
} }
@@ -399,7 +387,7 @@ public struct HSLColor
return Color.FromArgb( return Color.FromArgb(
System.Convert.ToInt32(255 * r), System.Convert.ToInt32(255 * r),
System.Convert.ToInt32(255 * g), System.Convert.ToInt32(255 * g),
System.Convert.ToInt32(255 * b)); System.Convert.ToInt32(255 * b));
} }

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.8.0.0")] [assembly: AssemblyVersion("2.9.0.0")]
[assembly: AssemblyFileVersion("2.8.0.0")] [assembly: AssemblyFileVersion("2.9.0.0")]

View File

@@ -41,18 +41,18 @@
_ ignore #menu: Navigate > - _ ignore #menu: Navigate > -
PGUP add chapter 1 #menu: Navigate > Next Chapter PGUP add chapter 1 #menu: Navigate > Next Chapter
PGDWN add chapter -1 #menu: Navigate > Previous Chapter PGDWN add chapter -1 #menu: Navigate > Previous Chapter
_ ignore #menu: Navigate > -
. frame-step #menu: Seek > Next Frame . frame-step #menu: Navigate > Jump Next Frame
, frame-back-step #menu: Seek > Previous Frame , frame-back-step #menu: Navigate > Jump Previous Frame
_ ignore #menu: Seek > - _ ignore #menu: Navigate > -
Right no-osd seek 7 #menu: Seek > 7 sec forward Right no-osd seek 7 #menu: Navigate > Jump 7 sec forward
Left no-osd seek -7 #menu: Seek > 7 sec backward Left no-osd seek -7 #menu: Navigate > Jump 7 sec backward
_ ignore #menu: Seek > - _ ignore #menu: Navigate > -
Up no-osd seek 40 #menu: Seek > 40 sec forward Up no-osd seek 40 #menu: Navigate > Jump 40 sec forward
Down no-osd seek -40 #menu: Seek > 40 sec backward Down no-osd seek -40 #menu: Navigate > Jump 40 sec backward
_ ignore #menu: Seek > - _ ignore #menu: Navigate > -
Ctrl+Right no-osd seek 300 #menu: Seek > 5 min forward Ctrl+Right no-osd seek 300 #menu: Navigate > Jump 5 min forward
Ctrl+Left no-osd seek -300 #menu: Seek > 5 min backward Ctrl+Left no-osd seek -300 #menu: Navigate > Jump 5 min backward
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
@@ -101,6 +101,8 @@
_ add sub-scale -0.1 #menu: Subtitle > Decrease Subtitle Font Size _ add sub-scale -0.1 #menu: Subtitle > Decrease Subtitle Font Size
_ add sub-scale 0.1 #menu: Subtitle > Increase Subtitle Font Size _ add sub-scale 0.1 #menu: Subtitle > Increase Subtitle Font Size
_ ignore #menu: Track
+ add volume 10 #menu: Volume > Up + add volume 10 #menu: Volume > Up
- add volume -10 #menu: Volume > Down - add volume -10 #menu: Volume > Down
_ ignore #menu: Volume > - _ ignore #menu: Volume > -

View File

@@ -57,6 +57,7 @@ namespace mpvnet
public static IntPtr MpvWindowHandle; public static IntPtr MpvWindowHandle;
public static Addon Addon; public static Addon Addon;
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions = new List<KeyValuePair<string, Action<bool>>>(); 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 Size VideoSize = new Size(1920, 1080);
public static string mpvConfFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\"; 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 InputConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
@@ -254,12 +255,17 @@ namespace mpvnet
Seek?.Invoke(); Seek?.Invoke();
break; break;
case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE: case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE:
var event_propertyData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property)); var propData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property));
if (event_propertyData.format == mpv_format.MPV_FORMAT_FLAG) if (propData.format == mpv_format.MPV_FORMAT_FLAG)
foreach (var i in BoolPropChangeActions) foreach (var i in BoolPropChangeActions)
if (i.Key== event_propertyData.name) if (i.Key== propData.name)
i.Value.Invoke(Marshal.PtrToStructure<int>(event_propertyData.data) == 1); i.Value.Invoke(Marshal.PtrToStructure<int>(propData.data) == 1);
if (propData.format == mpv_format.MPV_FORMAT_STRING)
foreach (var i in StringPropChangeActions)
if (i.Key == propData.name)
i.Value.Invoke(StringFromNativeUtf8(Marshal.PtrToStructure<IntPtr>(propData.data)));
break; break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART: case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke(); PlaybackRestart?.Invoke();
@@ -379,7 +385,7 @@ namespace mpvnet
if (err < 0 && throwOnException) if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}"); throw new Exception($"{name}: {(mpv_error)err}");
var ret = StringFromNativeUtf8(lpBuffer); string ret = StringFromNativeUtf8(lpBuffer);
mpv_free(lpBuffer); mpv_free(lpBuffer);
return ret; return ret;
@@ -453,6 +459,28 @@ namespace mpvnet
throw new Exception($"{name}: {(mpv_error)err}"); 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);
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
else
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);

View File

@@ -27,6 +27,7 @@ namespace DynamicGUI
baseSetting = optionSetting; baseSetting = optionSetting;
optionSetting.Default = setting["default"]; optionSetting.Default = setting["default"];
optionSetting.Value = optionSetting.Default; optionSetting.Value = optionSetting.Default;
optionSetting.StartValue = optionSetting.Default;
foreach (TomlTable option in setting["options"]) foreach (TomlTable option in setting["options"])
{ {
@@ -65,6 +66,7 @@ namespace DynamicGUI
{ {
public string Name { get; set; } public string Name { get; set; }
public string Value { get; set; } public string Value { get; set; }
public string StartValue { get; set; }
public string Help { get; set; } public string Help { get; set; }
public string Default { get; set; } public string Default { get; set; }
public string HelpURL { get; set; } public string HelpURL { get; set; }

View File

@@ -9,6 +9,7 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using DynamicGUI; using DynamicGUI;
using Microsoft.Win32; using Microsoft.Win32;
@@ -54,22 +55,9 @@ namespace mpvConfEdit
if (!((darkMode == "system" && isDarkTheme) || darkMode == "always")) if (!((darkMode == "system" && isDarkTheme) || darkMode == "always"))
return; return;
//Background = new SolidColorBrush(Colors.Black);
Foreground = Brushes.White; Foreground = Brushes.White;
Foreground2 = Brushes.Silver; Foreground2 = Brushes.Silver;
Background = Brushes.Black; Background = Brushes.Black;
//foreach (var i in MainStackPanel.Children)
//{
// switch (i)
// {
// case OptionSettingControl c:
// c.Foreground = Brushes.White;
// c.Background = Brushes.Black;
// break;
// }
//}
} }
private void LoadSettings(List<SettingBase> settingsDefinitions, private void LoadSettings(List<SettingBase> settingsDefinitions,
@@ -85,6 +73,7 @@ namespace mpvConfEdit
if (setting.Name == pair.Key) if (setting.Name == pair.Key)
{ {
setting.Value = pair.Value; setting.Value = pair.Value;
setting.StartValue = pair.Value;
continue; continue;
} }
} }
@@ -162,6 +151,19 @@ namespace mpvConfEdit
void WriteToDisk() void WriteToDisk()
{ {
bool isDirty = false;
foreach (SettingBase i in MpvSettingsDefinitions)
if (i.StartValue != i.Value)
isDirty = true;
foreach (SettingBase i in MpvNetSettingsDefinitions)
if (i.StartValue != i.Value)
isDirty = true;
if (!isDirty)
return;
WriteToDisk(MpvConfPath, MpvConf, MpvSettingsDefinitions); WriteToDisk(MpvConfPath, MpvConf, MpvSettingsDefinitions);
WriteToDisk(MpvNetConfPath, MpvNetConf, MpvNetSettingsDefinitions); WriteToDisk(MpvNetConfPath, MpvNetConf, MpvNetSettingsDefinitions);
@@ -227,6 +229,7 @@ namespace mpvConfEdit
private void MainWindow1_Loaded(object sender, RoutedEventArgs e) private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
{ {
SearchControl.SearchTextBox.SelectAll();
Keyboard.Focus(SearchControl.SearchTextBox); Keyboard.Focus(SearchControl.SearchTextBox);
} }

View File

@@ -51,5 +51,5 @@ using System.Windows;
// 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("1.7.0.0")] [assembly: AssemblyVersion("1.8.0.0")]
[assembly: AssemblyFileVersion("1.7.0.0")] [assembly: AssemblyFileVersion("1.8.0.0")]

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
@@ -10,7 +9,6 @@ namespace mpvInputEdit
{ {
public partial class InputWindow : Window public partial class InputWindow : Window
{ {
string InputString = "";
public InputItem InputItem { get; set; } public InputItem InputItem { get; set; }
public string NewKey { get; set; } = ""; public string NewKey { get; set; } = "";
@@ -32,22 +30,21 @@ namespace mpvInputEdit
void OnKeyUp(WF.KeyEventArgs e) void OnKeyUp(WF.KeyEventArgs e)
{ {
if (e.KeyCode == WF.Keys.None) return;
char c = Convert.ToChar(e.KeyCode);
string text = InputString;
if (e.KeyCode == WF.Keys.ControlKey || e.KeyCode == WF.Keys.ShiftKey || if (e.KeyCode == WF.Keys.ControlKey || e.KeyCode == WF.Keys.ShiftKey ||
e.KeyCode == WF.Keys.Menu) e.KeyCode == WF.Keys.Menu || e.KeyCode == WF.Keys.None)
{
return;
}
if (text == "") return;
{
text = e.KeyCode.ToString(); string text = "";
if (text.Length == 1) uint charValue = MapVirtualKey((uint)e.KeyCode, 2);
text = text.ToLowerInvariant();
} if (charValue == 0 || (charValue & 1 << 31) == 1 << 31)
text = e.KeyCode.ToString().Trim();
else
try {
text = Convert.ToChar(charValue).ToString().ToLower().Trim();
}
catch {}
for (int i = 0; i < 13; i++) for (int i = 0; i < 13; i++)
if ("D" + i.ToString() == text) if ("D" + i.ToString() == text)
@@ -90,14 +87,6 @@ namespace mpvInputEdit
text = "Esc"; break; text = "Esc"; break;
case WF.Keys.PrintScreen: case WF.Keys.PrintScreen:
text = "Print"; break; text = "Print"; break;
case WF.Keys.Right:
text = "Right"; break;
case WF.Keys.Left:
text = "Left"; break;
case WF.Keys.Up:
text = "Up"; break;
case WF.Keys.Down:
text = "Down"; break;
case WF.Keys.Play: case WF.Keys.Play:
text = "Play"; break; text = "Play"; break;
case WF.Keys.Pause: case WF.Keys.Pause:
@@ -130,20 +119,24 @@ namespace mpvInputEdit
text = "Cancel"; break; text = "Cancel"; break;
} }
if (text == "#") bool shiftWasHandled = false;
text = "Sharp";
bool isAlt = GetKeyState(18) < (short)0; bool isAlt = GetKeyState(18) < (short)0;
bool isShift = GetKeyState(16) < (short)0; bool isShift = GetKeyState(16) < (short)0;
bool isCtrl = GetKeyState(17) < (short)0; bool isCtrl = GetKeyState(17) < (short)0;
if (!(isAlt && isCtrl && !isShift) && !(isShift && !isAlt && !isCtrl && !int.TryParse(text.Replace("F", ""), out int value))) if (text.Length == 1 && isShift && text[0] != GetModifiedKey(text[0]))
{ {
if (isAlt) text = "Alt+" + text; text = GetModifiedKey(text[0]).ToString();
if (isShift) text = "Shift+" + text; shiftWasHandled = true;
if (isCtrl) text = "Ctrl+" + text;
} }
if (text == "#") text = "Sharp";
if (isAlt) text = "Alt+" + text;
if (isShift && !shiftWasHandled) text = "Shift+" + text;
if (isCtrl) text = "Ctrl+" + text;
if (!string.IsNullOrEmpty(text)) if (!string.IsNullOrEmpty(text))
SetKey(text); SetKey(text);
} }
@@ -155,13 +148,8 @@ namespace mpvInputEdit
KeyLabel.Content = key; KeyLabel.Content = key;
} }
void OnKeyPress(WF.KeyPressEventArgs e) [DllImport("user32.dll")]
{ static extern uint MapVirtualKey(uint uCode, uint uMapType);
if (char.IsControl(e.KeyChar))
InputString = "";
else
InputString = e.KeyChar.ToString();
}
public static WF.Keys ModifierKeys { public static WF.Keys ModifierKeys {
get { get {
@@ -176,80 +164,78 @@ namespace mpvInputEdit
} }
} }
public static char GetModifiedKey(char c)
{
short vkKeyScanResult = VkKeyScan(c);
if (vkKeyScanResult == -1)
return c;
uint code = (uint)vkKeyScanResult & 0xff;
byte[] b = new byte[256];
b[0x10] = 0x80;
uint r;
if (1 != ToAscii(code, code, b, out r, 0))
return c;
return (char)r;
}
void ProcessKeyEventArgs(ref WF.Message m) void ProcessKeyEventArgs(ref WF.Message m)
{ {
int WM_CHAR = 258, WM_SYSCHAR = 262, /*WM_KEYDOWN = 256, WM_SYSKEYDOWN = 260,*/ int WM_KEYUP = 0x0101, WM_SYSKEYUP = 0x0105, WM_APPCOMMAND = 0x0319;
WM_KEYUP = 0x0101, WM_SYSKEYUP = 0x0105, WM_APPCOMMAND = 0x0319;
IntPtr newWParam = IntPtr.Zero; if (m.Msg == WM_KEYUP || m.Msg == WM_SYSKEYUP)
WF.KeyEventArgs ke = null; OnKeyUp(new WF.KeyEventArgs((WF.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys));
WF.KeyPressEventArgs kpe = null; else if (m.Msg == WM_APPCOMMAND)
if (m.Msg == WM_CHAR || m.Msg == WM_SYSCHAR)
{ {
kpe = new WF.KeyPressEventArgs(unchecked((char)(long)m.WParam)); switch ((AppCommand)(m.LParam.ToInt32() >> 16))
OnKeyPress(kpe);
newWParam = (IntPtr)kpe.KeyChar;
}
else
{
ke = new WF.KeyEventArgs((WF.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys);
if (m.Msg == WM_KEYUP || m.Msg == WM_SYSKEYUP)
OnKeyUp(ke);
if (m.Msg == WM_APPCOMMAND)
{ {
switch ((AppCommand)(m.LParam.ToInt32() >> 16)) case AppCommand.MEDIA_CHANNEL_DOWN:
{ SetKey("Channel_Down");
case AppCommand.MEDIA_CHANNEL_DOWN: break;
SetKey("Channel_Down"); case AppCommand.MEDIA_CHANNEL_UP:
break; SetKey("Channel_Up");
case AppCommand.MEDIA_CHANNEL_UP: break;
SetKey("Channel_Up"); case AppCommand.MEDIA_FAST_FORWARD:
break; SetKey("Forward");
case AppCommand.MEDIA_FAST_FORWARD: break;
SetKey("Forward"); case AppCommand.MEDIA_REWIND:
break; SetKey("Rewind");
case AppCommand.MEDIA_REWIND: break;
SetKey("Rewind"); case AppCommand.MEDIA_PAUSE:
break; SetKey("Pause");
case AppCommand.MEDIA_PAUSE: break;
SetKey("Pause"); case AppCommand.MEDIA_PLAY:
break; SetKey("Play");
case AppCommand.MEDIA_PLAY: break;
SetKey("Play"); case AppCommand.MEDIA_PLAY_PAUSE:
break; SetKey("PlayPause");
case AppCommand.MEDIA_PLAY_PAUSE: break;
SetKey("PlayPause"); case AppCommand.MEDIA_NEXTTRACK:
break; SetKey("Next");
case AppCommand.MEDIA_NEXTTRACK: break;
SetKey("Next"); case AppCommand.MEDIA_PREVIOUSTRACK:
break; SetKey("Prev");
case AppCommand.MEDIA_PREVIOUSTRACK: break;
SetKey("Prev"); case AppCommand.MEDIA_RECORD:
break; SetKey("Record");
case AppCommand.MEDIA_RECORD: break;
SetKey("Record"); case AppCommand.MEDIA_STOP:
break; SetKey("Stop");
case AppCommand.MEDIA_STOP: break;
SetKey("Stop"); case AppCommand.VolumeUp:
break; SetKey("Volume_Up");
case AppCommand.VolumeUp: break;
SetKey("Volume_Up"); case AppCommand.VolumeDown:
break; SetKey("Volume_Down");
case AppCommand.VolumeDown: break;
SetKey("Volume_Down"); case AppCommand.VolumeMute:
break; SetKey("Mute");
case AppCommand.VolumeMute: break;
SetKey("Mute");
break;
}
} }
} }
if (kpe != null)
m.WParam = newWParam;
} }
internal enum AppCommand internal enum AppCommand
@@ -273,6 +259,16 @@ namespace mpvInputEdit
[DllImport("user32.dll", CharSet = CharSet.Auto)] [DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern short GetKeyState(int keyCode); public static extern short GetKeyState(int keyCode);
[DllImport("user32.dll")]
static extern short VkKeyScan(char c);
[DllImport("user32.dll", SetLastError = true)]
static extern int ToAscii(uint uVirtKey,
uint uScanCode,
byte[] lpKeyState,
out uint lpChar,
uint flags);
private void Window_Loaded(object sender, RoutedEventArgs e) private void Window_Loaded(object sender, RoutedEventArgs e)
{ {
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);

View File

@@ -37,9 +37,10 @@ namespace mpvInputEdit
string searchText = SearchControl.SearchTextBox.Text.ToLower(); string searchText = SearchControl.SearchTextBox.Text.ToLower();
if (searchText == "") return true; if (searchText == "") return true;
if (searchText.StartsWith("i ") || searchText.StartsWith("i:")) if (searchText.StartsWith("i ") || searchText.StartsWith("i:") || searchText.Length == 1)
{ {
searchText = searchText.Substring(2).Trim(); if (searchText.Length > 1)
searchText = searchText.Substring(2).Trim();
if (searchText.Length < 3) if (searchText.Length < 3)
return item.Input.ToLower().Replace("ctrl+", "").Replace("shift+", "").Replace("alt+", "").Contains(searchText); return item.Input.ToLower().Replace("ctrl+", "").Replace("shift+", "").Replace("alt+", "").Contains(searchText);

View File

@@ -12,7 +12,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mpv(.net) input edit")] [assembly: AssemblyProduct("mpv(.net) input edit")]
[assembly: AssemblyCopyright("Copyright © 2017 stax76")] [assembly: AssemblyCopyright("Copyright © 2017-2019 stax76")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@@ -51,5 +51,5 @@ using System.Windows;
// 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("1.3.0.0")] [assembly: AssemblyVersion("1.5.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyFileVersion("1.5.0.0")]

View File

@@ -29,7 +29,7 @@ namespace Controls
SearchClearButton.Visibility = Visibility.Visible; SearchClearButton.Visibility = Visibility.Visible;
if (SearchTextBox.Text == "?") if (SearchTextBox.Text == "?")
MessageBox.Show("Filtering works by searching in the Input, Menu and Command but it's possible to reduce the filter scope to either of Input, Menu or Command by prefixing as follows:\n\ni <input search>\ni: <input search>\n\nm <menu search>\nm: <menu search>\n\nc <command search>\nc: <command search>", "Filtering", MessageBoxButton.OK, MessageBoxImage.Information); MessageBox.Show("Filtering works by searching in the Input, Menu and Command but it's possible to reduce the filter scope to either of Input, Menu or Command by prefixing as follows:\n\ni <input search>\ni: <input search>\n\nm <menu search>\nm: <menu search>\n\nc <command search>\nc: <command search>\n\nIf only one character is entered the search will be performed only in the input.", "Filtering", MessageBoxButton.OK, MessageBoxImage.Information);
} }
} }
} }

View File

@@ -110,6 +110,9 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="..\README.md">
<Link>README.md</Link>
</None>
<None Include="app.manifest" /> <None Include="app.manifest" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB