├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── ask-a-question.md │ ├── report-a-bug.md │ └── request-a-feature.md ├── docs ├── Privacy.md ├── img │ ├── Main.webp │ ├── Menu.jpg │ ├── mpvnet.ico │ ├── mpvnet.pdn │ ├── mpvnet.png │ ├── Playlist.png │ ├── Terminal.png │ ├── ConfEditor.png │ ├── InputEditor.webp │ ├── mpvnet-santa.png │ └── CommandPalette.webp └── Universal Remote │ ├── icon.png │ ├── icon_hires.png │ ├── meta.prop │ ├── layout.xml │ └── remote.lua ├── src ├── mpvnet.ico ├── Resources │ ├── mpvnet.ico │ ├── mpvnet.png │ ├── mpvnet-santa.png │ └── theme.txt ├── Package │ ├── Images │ │ ├── StoreLogo.png │ │ ├── SplashScreen.scale-200.png │ │ ├── LockScreenLogo.scale-200.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-200.png │ │ └── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── Package.appxmanifest │ └── mpv.net.package.wapproj ├── packages.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ └── Resources.Designer.cs ├── App.config ├── Misc │ ├── Global.cs │ ├── Extension.cs │ ├── Terminal.cs │ ├── Msg.cs │ ├── Common.cs │ ├── Settings.cs │ ├── CSharpScriptHost.cs │ ├── MainForm.Designer.cs │ ├── ExtensionMethods.cs │ ├── Program.cs │ ├── Theme.cs │ ├── FolderBrowser.cs │ └── Conf.cs ├── Scripts │ ├── PowerShell │ │ ├── show-in-file-explorer.ps1 │ │ ├── open-file-dialog.ps1 │ │ └── pause-when-minimize.ps1 │ ├── C-Sharp │ │ ├── observe-property-and-draw-text.cs │ │ ├── key-binding.cs │ │ ├── pause-when-minimize.cs │ │ ├── switch-profile-context-menu.cs │ │ ├── delete-current-file.cs │ │ └── rate-file.cs │ ├── JavaScript │ │ ├── show-playlist.js │ │ └── seek-show-position.js │ └── Lua │ │ ├── pause-when-minimize.lua │ │ └── delete-current-file.lua ├── WPF │ ├── MsgBox │ │ ├── MsgBoxUrl.cs │ │ ├── MsgBoxExDelegate.cs │ │ ├── MsgEnumerators.cs │ │ ├── MsgBoxExtendedFunctionality.cs │ │ └── MsgBoxExCheckBoxData.cs │ ├── HandyControl │ │ ├── Tools │ │ │ ├── Interop │ │ │ │ └── Handle │ │ │ │ │ ├── CommonHandles.cs │ │ │ │ │ ├── WpfSafeHandle.cs │ │ │ │ │ ├── BitmapHandle.cs │ │ │ │ │ └── HandleCollector.cs │ │ │ ├── Extension │ │ │ │ └── StringExtension.cs │ │ │ ├── Converter │ │ │ │ └── BorderCircularConverter.cs │ │ │ ├── AnimationHelper.cs │ │ │ ├── Helper │ │ │ │ ├── VisualHelper.cs │ │ │ │ └── ScreenHelper.cs │ │ │ └── RegexPatterns.cs │ │ ├── Controls │ │ │ ├── Attach │ │ │ │ ├── ScrollViewerAttach.cs │ │ │ │ ├── IconElement.cs │ │ │ │ ├── BorderElement.cs │ │ │ │ └── MenuTopLineAttach.cs │ │ │ └── SimplePanel.cs │ │ └── Data │ │ │ └── ValueBoxes.cs │ ├── WPF.cs │ ├── AboutWindow.xaml.cs │ ├── RelayCommand.cs │ ├── AboutWindow.xaml │ ├── SearchTextBoxUserControl.xaml.cs │ ├── OptionSettingControl.xaml.cs │ ├── MenuHelp.cs │ ├── LearnWindow.xaml │ ├── StringSettingControl.xaml │ ├── OptionSettingControl.xaml │ ├── SearchTextBoxUserControl.xaml │ ├── ConfWindow.xaml │ ├── StringSettingControl.xaml.cs │ ├── CommandPaletteControl.xaml.cs │ ├── InputWindow.xaml │ └── InputWindow.xaml.cs ├── .editorconfig ├── Extensions │ └── RatingExtension │ │ ├── ScriptDevelopment.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── RatingExtension.csproj │ │ └── RatingExtension.cs ├── Native │ ├── Taskbar.cs │ ├── MediaInfo.cs │ ├── StockIcon.cs │ └── Native.cs ├── Release.ps1 └── app.manifest ├── .gitattributes ├── README.md └── .gitignore /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: stax76 2 | patreon: stax76 3 | ko_fi: stax76 4 | -------------------------------------------------------------------------------- /docs/Privacy.md: -------------------------------------------------------------------------------- 1 | 2 | mpv.net does not collect any personal information. 3 | -------------------------------------------------------------------------------- /src/mpvnet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/mpvnet.ico -------------------------------------------------------------------------------- /docs/img/Main.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/Main.webp -------------------------------------------------------------------------------- /docs/img/Menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/Menu.jpg -------------------------------------------------------------------------------- /docs/img/mpvnet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/mpvnet.ico -------------------------------------------------------------------------------- /docs/img/mpvnet.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/mpvnet.pdn -------------------------------------------------------------------------------- /docs/img/mpvnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/mpvnet.png -------------------------------------------------------------------------------- /docs/img/Playlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/Playlist.png -------------------------------------------------------------------------------- /docs/img/Terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/Terminal.png -------------------------------------------------------------------------------- /docs/img/ConfEditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/ConfEditor.png -------------------------------------------------------------------------------- /src/Resources/mpvnet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Resources/mpvnet.ico -------------------------------------------------------------------------------- /src/Resources/mpvnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Resources/mpvnet.png -------------------------------------------------------------------------------- /docs/img/InputEditor.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/InputEditor.webp -------------------------------------------------------------------------------- /docs/img/mpvnet-santa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/mpvnet-santa.png -------------------------------------------------------------------------------- /docs/img/CommandPalette.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/img/CommandPalette.webp -------------------------------------------------------------------------------- /docs/Universal Remote/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/Universal Remote/icon.png -------------------------------------------------------------------------------- /src/Resources/mpvnet-santa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Resources/mpvnet-santa.png -------------------------------------------------------------------------------- /src/Package/Images/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/StoreLogo.png -------------------------------------------------------------------------------- /docs/Universal Remote/icon_hires.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/docs/Universal Remote/icon_hires.png -------------------------------------------------------------------------------- /docs/Universal Remote/meta.prop: -------------------------------------------------------------------------------- 1 | 2 | meta.name: custom keys 3 | meta.author: stax76 4 | meta.description: custom keys 5 | meta.tags: mpv 6 | -------------------------------------------------------------------------------- /src/Package/Images/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /src/Package/Images/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /src/Package/Images/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /src/Package/Images/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /src/Package/Images/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /src/Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andyvorld/mpv.net/master/src/Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /src/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ask-a-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ask a question 3 | about: Ask a question about mpv.net 4 | title: '' 5 | labels: question 6 | assignees: stax76 7 | 8 | --- 9 | 10 | This template is meant for usage questions of mpv.net. 11 | -------------------------------------------------------------------------------- /src/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Misc/Global.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | 4 | namespace mpvnet 5 | { 6 | public class Global 7 | { 8 | public static string BR = Environment.NewLine; 9 | public static string BR2 = Environment.NewLine + Environment.NewLine; 10 | 11 | public static CorePlayer Core { get; } = new CorePlayer(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Scripts/PowerShell/show-in-file-explorer.ps1: -------------------------------------------------------------------------------- 1 | 2 | # Shows the current file in File Explorer 3 | 4 | # In input.conf add: script-message show-in-file-explorer 5 | 6 | $code = { 7 | if ($args[0] -eq 'show-in-file-explorer') 8 | { 9 | Start-Process explorer.exe '/n,','/select,',"$($mp.GetPropertyString('path'))" 10 | } 11 | } 12 | 13 | $mp.RegisterEvent("client-message", $code) 14 | -------------------------------------------------------------------------------- /src/WPF/MsgBox/MsgBoxUrl.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows.Media; 4 | 5 | namespace MsgBoxEx 6 | { 7 | public class MsgBoxUrl 8 | { 9 | public Uri URL { get; set; } 10 | public string DisplayName { get; set; } 11 | public Color Foreground { get; set; } 12 | 13 | public MsgBoxUrl() 14 | { 15 | Foreground = MessageBoxEx.DefaultUrlForegroundColor; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /src/WPF/MsgBox/MsgBoxExDelegate.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows; 4 | 5 | namespace MsgBoxEx 6 | { 7 | public abstract class MsgBoxExDelegate 8 | { 9 | public string Message { get; set; } 10 | public string Details { get; set; } 11 | public DateTime MessageDate { get; set; } 12 | 13 | public virtual MessageBoxResult PerformAction(string message, string details = null) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Resources/theme.txt: -------------------------------------------------------------------------------- 1 | 2 | [dark] 3 | 4 | heading = #3C8CC8 5 | foreground = #DDDDDD 6 | foreground2 = #AAAAAA 7 | background = #323232 8 | highlight = #404040 9 | 10 | menu-foreground = #DDDDDD 11 | menu-background = #323232 12 | menu-highlight = #505050 13 | 14 | 15 | [light] 16 | 17 | heading = #0068B2 18 | foreground = #000000 19 | foreground2 = #4C4C4C 20 | background = #F7F7F7 21 | highlight = #DFDFDF 22 | 23 | menu-foreground = #000000 24 | menu-background = #DFDFDF 25 | menu-highlight = #BFBFBF 26 | -------------------------------------------------------------------------------- /src/Scripts/C-Sharp/observe-property-and-draw-text.cs: -------------------------------------------------------------------------------- 1 | 2 | // This script observes the fullscreen property and 3 | // draws text on screen when the property changes. 4 | 5 | using mpvnet; 6 | 7 | class Script 8 | { 9 | CorePlayer Core; 10 | 11 | public Script() 12 | { 13 | Core = Global.Core; 14 | Core.ObservePropertyBool("fullscreen", FullscreenChange); 15 | } 16 | 17 | void FullscreenChange(bool value) 18 | { 19 | Core.CommandV("show-text", "fullscreen: " + value); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Interop/Handle/CommonHandles.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace HandyControl.Tools.Interop 3 | { 4 | internal static class CommonHandles 5 | { 6 | public static readonly int Icon = HandleCollector.RegisterType(nameof(Icon), 20, 500); 7 | 8 | public static readonly int HDC = HandleCollector.RegisterType(nameof(HDC), 100, 2); 9 | 10 | public static readonly int GDI = HandleCollector.RegisterType(nameof(GDI), 50, 500); 11 | 12 | public static readonly int Kernel = HandleCollector.RegisterType(nameof(Kernel), 0, 1000); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/WPF/WPF.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows; 4 | 5 | namespace mpvnet 6 | { 7 | public class WPF 8 | { 9 | public static void Init() 10 | { 11 | if (Application.Current == null) 12 | { 13 | new Application(); 14 | 15 | Application.Current.Resources.MergedDictionaries.Add( 16 | Application.LoadComponent(new Uri("mpvnet;component/WPF/Resources.xaml", 17 | UriKind.Relative)) as ResourceDictionary); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Scripts/PowerShell/open-file-dialog.ps1: -------------------------------------------------------------------------------- 1 | 2 | # Shows the Open File dialog to open a file without loading its folder into the playlist. 3 | 4 | # In input.conf add: script-message load-without-folder 5 | 6 | $code = { 7 | if ($args[0] -eq 'load-without-folder') 8 | { 9 | $dialog = New-Object Windows.Forms.OpenFileDialog 10 | 11 | if ($dialog.ShowDialog() -eq 'OK') 12 | { 13 | $core.LoadFiles($dialog.FileNames, $false, $false); 14 | } 15 | 16 | $dialog.Dispose() 17 | } 18 | } 19 | 20 | $mp.RegisterEvent("client-message", $code) 21 | -------------------------------------------------------------------------------- /src/WPF/AboutWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Windows; 3 | using System.Windows.Input; 4 | 5 | namespace mpvnet 6 | { 7 | public partial class AboutWindow : Window 8 | { 9 | public AboutWindow() 10 | { 11 | InitializeComponent(); 12 | DataContext = this; 13 | ContentBlock.Text = App.Version; 14 | } 15 | 16 | protected override void OnPreviewKeyDown(KeyEventArgs e) => Close(); 17 | protected override void OnMouseDown(MouseButtonEventArgs e) => Close(); 18 | 19 | public Theme Theme => Theme.Current; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Scripts/PowerShell/pause-when-minimize.ps1: -------------------------------------------------------------------------------- 1 | 2 | $code = { 3 | $isMinimized = $args[0] 4 | $isPaused = $mp.GetPropertyBool('pause') 5 | 6 | if ($isMinimized) 7 | { 8 | if (-not $isPaused) 9 | { 10 | $mp.SetPropertyBool('pause', $true) 11 | $script:wasPaused = $true 12 | } 13 | } 14 | else 15 | { 16 | if ($script:wasPaused -and $isPaused) 17 | { 18 | $mp.SetPropertyBool('pause', $false) 19 | } 20 | 21 | $script:wasPaused = $false 22 | } 23 | } 24 | 25 | $mp.ObserveProperty('window-minimized', 'bool', $code) 26 | -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # IDE0058: Expression value is never used 4 | dotnet_diagnostic.IDE0058.severity = none 5 | 6 | # IDE0055: Fix formatting 7 | dotnet_diagnostic.IDE0055.severity = none 8 | 9 | # IDE0022: Use block body for methods 10 | dotnet_diagnostic.IDE0022.severity = none 11 | 12 | # IDE0040: Add accessibility modifiers 13 | dotnet_diagnostic.IDE0040.severity = none 14 | 15 | # IDE0011: Add braces 16 | dotnet_diagnostic.IDE0011.severity = none 17 | 18 | # IDE0010: Add missing cases 19 | dotnet_diagnostic.IDE0010.severity = none 20 | 21 | # IDE0044: Add readonly modifier 22 | dotnet_diagnostic.IDE0044.severity = silent 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/report-a-bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a bug 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: stax76 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/request-a-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Request a feature 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature request 6 | assignees: stax76 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /src/Scripts/JavaScript/show-playlist.js: -------------------------------------------------------------------------------- 1 | 2 | // This script shows the playlist. 3 | 4 | function showPlaylist() 5 | { 6 | // set font size 7 | mp.set_property_number("osd-font-size", 40); 8 | 9 | // show playlist for 5 seconds 10 | mp.command("show-text ${playlist} 5000"); 11 | 12 | // restore original font size in 6 seconds 13 | setTimeout(resetFontSize, 6000); 14 | } 15 | 16 | // restore original font size 17 | function resetFontSize() 18 | { 19 | mp.set_property_number("osd-font-size", size); 20 | } 21 | 22 | // save original font size 23 | var size = mp.get_property_number("osd-font-size"); 24 | 25 | // input.conf: key script-binding show-playlist 26 | mp.add_key_binding(null, "show-playlist", showPlaylist); 27 | -------------------------------------------------------------------------------- /src/WPF/MsgBox/MsgEnumerators.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace MsgBoxEx 3 | { 4 | public enum MessageBoxButtonEx { OK = 0, OKCancel, AbortRetryIgnore, YesNoCancel, YesNo, RetryCancel } 5 | 6 | public enum MessageBoxResultEx { None = 0, OK, Cancel, Abort, Retry, Ignore, Yes, No } 7 | 8 | public enum MessageBoxButtonDefault 9 | { 10 | OK, Cancel, Yes, No, Abort, Retry, Ignore, // specific button 11 | Button1, Button2, Button3, // button by ordinal left-to-right position 12 | MostPositive, LeastPositive, // button by positivity 13 | Forms, // button according to the Windows.Forms standard messagebox 14 | None // no default button 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Controls/Attach/ScrollViewerAttach.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Windows; 3 | 4 | using HandyControl.Data; 5 | 6 | namespace HandyControl.Controls 7 | { 8 | public class ScrollViewerAttach 9 | { 10 | public static readonly DependencyProperty AutoHideProperty = DependencyProperty.RegisterAttached( 11 | "AutoHide", typeof(bool), typeof(ScrollViewerAttach), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits)); 12 | 13 | public static void SetAutoHide(DependencyObject element, bool value) 14 | => element.SetValue(AutoHideProperty, value); 15 | 16 | public static bool GetAutoHide(DependencyObject element) 17 | => (bool) element.GetValue(AutoHideProperty); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Interop/Handle/WpfSafeHandle.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | using Microsoft.Win32.SafeHandles; 3 | 4 | namespace HandyControl.Tools.Interop 5 | { 6 | internal abstract class WpfSafeHandle : SafeHandleZeroOrMinusOneIsInvalid 7 | { 8 | private readonly int _collectorId; 9 | 10 | [SecurityCritical] 11 | protected WpfSafeHandle(bool ownsHandle, int collectorId) : base(ownsHandle) 12 | { 13 | HandleCollector.Add(collectorId); 14 | _collectorId = collectorId; 15 | } 16 | 17 | [SecurityCritical, SecuritySafeCritical] 18 | protected override void Dispose(bool disposing) 19 | { 20 | HandleCollector.Remove(_collectorId); 21 | base.Dispose(disposing); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Scripts/C-Sharp/key-binding.cs: -------------------------------------------------------------------------------- 1 | 2 | // This script adds a key binding. 3 | 4 | using System.Reflection; 5 | 6 | using mpvnet; 7 | 8 | class Script 9 | { 10 | public Script() 11 | { 12 | string content = "ctrl+w script-message my-message-1 my-argument-1"; 13 | string sectionName = Assembly.GetExecutingAssembly().GetName().Name; 14 | CorePlayer core = Global.Core; 15 | core.CommandV("define-section", sectionName, content, "force"); 16 | core.CommandV("enable-section", sectionName); 17 | core.ClientMessage += ClientMessage; 18 | } 19 | 20 | void ClientMessage(string[] args) 21 | { 22 | switch (args[0]) 23 | { 24 | case "my-message-1": 25 | Msg.ShowInfo(args[1]); 26 | break; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/WPF/RelayCommand.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows.Input; 4 | 5 | namespace mpvnet 6 | { 7 | public class RelayCommand : ICommand 8 | { 9 | public event EventHandler CanExecuteChanged; 10 | 11 | Action ExecuteAction; 12 | 13 | Predicate CanExecutePredicate; 14 | 15 | public RelayCommand(Action executeAction, Predicate canExecutePredicate = null) 16 | { 17 | ExecuteAction = executeAction; 18 | CanExecutePredicate = canExecutePredicate; 19 | } 20 | 21 | public bool CanExecute(object parameter) => CanExecutePredicate == null || CanExecutePredicate(parameter); 22 | 23 | public void Execute(object parameter) => ExecuteAction(parameter); 24 | 25 | public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Scripts/Lua/pause-when-minimize.lua: -------------------------------------------------------------------------------- 1 | 2 | -- https://github.com/mpv-player/mpv/blob/master/TOOLS/lua/pause-when-minimize.lua 3 | 4 | -- This script pauses playback when minimizing the window, and resumes playback 5 | -- if it's brought back again. If the player was already paused when minimizing, 6 | -- then try not to mess with the pause state. 7 | 8 | local did_minimize = false 9 | 10 | mp.observe_property("window-minimized", "bool", function(name, value) 11 | local pause = mp.get_property_native("pause") 12 | if value == true then 13 | if pause == false then 14 | mp.set_property_native("pause", true) 15 | did_minimize = true 16 | end 17 | elseif value == false then 18 | if did_minimize and (pause == true) then 19 | mp.set_property_native("pause", false) 20 | end 21 | did_minimize = false 22 | end 23 | end) 24 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Extension/StringExtension.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.ComponentModel; 4 | 5 | namespace HandyControl.Tools.Extension 6 | { 7 | public static class StringExtension 8 | { 9 | public static T Value(this string input) 10 | { 11 | try 12 | { 13 | return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input); 14 | } 15 | catch 16 | { 17 | return default; 18 | } 19 | } 20 | 21 | public static object Value(this string input, Type type) 22 | { 23 | try 24 | { 25 | return TypeDescriptor.GetConverter(type).ConvertFromString(input); 26 | } 27 | catch 28 | { 29 | return null; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/WPF/MsgBox/MsgBoxExtendedFunctionality.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace MsgBoxEx 3 | { 4 | public class MsgBoxExtendedFunctionality 5 | { 6 | public MessageBoxButtonDefault ButtonDefault { get; set; } 7 | public string DetailsText { get; set; } 8 | public MsgBoxExCheckBoxData CheckBoxData { get; set; } 9 | public MsgBoxExDelegate MessageDelegate { get; set; } 10 | public bool ExitAfterAction { get; set; } 11 | public string DelegateToolTip { get; set; } 12 | 13 | public MsgBoxUrl URL { get; set; } 14 | 15 | public MsgBoxExtendedFunctionality() 16 | { 17 | ButtonDefault = MessageBoxButtonDefault.Forms; 18 | DetailsText = null; 19 | CheckBoxData = null; 20 | MessageDelegate = null; 21 | URL = null; 22 | DelegateToolTip = "Click this icon for additional info/actions."; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Scripts/JavaScript/seek-show-position.js: -------------------------------------------------------------------------------- 1 | 2 | // When seeking displays position and duration like so: 70:00 / 80:00 3 | // Which is different from most players which use: 01:10:00 / 01:20:00 4 | // In input.conf set the input command prefix no-osd infront of the seek command. 5 | 6 | function add_zero(val) 7 | { 8 | val = Math.round(val); 9 | return val > 9 ? "" + val : "0" + val; 10 | } 11 | 12 | function format(val) 13 | { 14 | var sec = Math.round(val); 15 | 16 | if (sec < 0) 17 | sec = 0; 18 | 19 | pos_min_floor = Math.floor(sec / 60); 20 | sec_rest = sec - pos_min_floor * 60; 21 | return add_zero(pos_min_floor) + ":" + add_zero(sec_rest); 22 | } 23 | 24 | function on_seek(_) 25 | { 26 | pos = mp.get_property_number("time-pos"); 27 | dur = mp.get_property_number("duration"); 28 | 29 | if (pos > dur) 30 | pos = dur; 31 | 32 | mp.commandv("show-text", format(pos) + " / " + format(dur)); 33 | } 34 | 35 | mp.register_event("seek", on_seek); 36 | -------------------------------------------------------------------------------- /src/WPF/AboutWindow.xaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | mpv.net 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Data/ValueBoxes.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace HandyControl.Data 3 | { 4 | internal static class ValueBoxes 5 | { 6 | internal static object TrueBox = true; 7 | internal static object FalseBox = false; 8 | internal static object Double0Box = .0; 9 | internal static object Double01Box = .1; 10 | internal static object Double1Box = 1.0; 11 | internal static object Double10Box = 10.0; 12 | internal static object Double20Box = 20.0; 13 | internal static object Double100Box = 100.0; 14 | internal static object Double200Box = 200.0; 15 | internal static object Double300Box = 300.0; 16 | internal static object DoubleNeg1Box = -1.0; 17 | internal static object Int0Box = 0; 18 | internal static object Int1Box = 1; 19 | internal static object Int2Box = 2; 20 | internal static object Int5Box = 5; 21 | internal static object Int99Box = 99; 22 | internal static object BooleanBox(bool value) => value ? TrueBox : FalseBox; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Converter/BorderCircularConverter.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Globalization; 4 | using System.Windows; 5 | using System.Windows.Data; 6 | 7 | namespace HandyControl.Tools.Converter 8 | { 9 | public class BorderCircularConverter : IMultiValueConverter 10 | { 11 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (values.Length == 2 && values[0] is double width && values[1] is double height) 14 | { 15 | if (width < double.Epsilon || height < double.Epsilon) 16 | { 17 | return new CornerRadius(); 18 | } 19 | 20 | var min = Math.Min(width, height); 21 | return new CornerRadius(min / 2); 22 | } 23 | 24 | return DependencyProperty.UnsetValue; 25 | } 26 | 27 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 28 | { 29 | throw new NotSupportedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Scripts/C-Sharp/pause-when-minimize.cs: -------------------------------------------------------------------------------- 1 | 2 | // Pauses playback when window is minimized and resumes afterwards. 3 | 4 | using System; 5 | using System.Windows.Forms; 6 | 7 | using mpvnet; 8 | 9 | class Script 10 | { 11 | MainForm MainForm; 12 | CorePlayer Core; 13 | 14 | bool WasPlaying; 15 | bool WasPaused; 16 | 17 | public Script() 18 | { 19 | Core = Global.Core; 20 | MainForm = MainForm.Instance; 21 | MainForm.Resize += Form_Resize; 22 | } 23 | 24 | void Form_Resize(object sender, EventArgs e) 25 | { 26 | if (MainForm.WindowState == FormWindowState.Minimized) 27 | { 28 | WasPlaying = !Core.GetPropertyBool("pause"); 29 | 30 | if (WasPlaying) 31 | { 32 | Core.SetPropertyBool("pause", true, true); 33 | WasPaused = true; 34 | } 35 | } 36 | else 37 | { 38 | if (WasPaused) 39 | { 40 | Core.SetPropertyBool("pause", false, true); 41 | WasPaused = false; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Controls/SimplePanel.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | 6 | namespace HandyControl.Controls 7 | { 8 | public class SimplePanel : Panel 9 | { 10 | protected override Size MeasureOverride(Size constraint) 11 | { 12 | var maxSize = new Size(); 13 | 14 | foreach (UIElement child in InternalChildren) 15 | { 16 | if (child != null) 17 | { 18 | child.Measure(constraint); 19 | maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width); 20 | maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height); 21 | } 22 | } 23 | 24 | return maxSize; 25 | } 26 | 27 | protected override Size ArrangeOverride(Size arrangeSize) 28 | { 29 | foreach (UIElement child in InternalChildren) 30 | { 31 | child?.Arrange(new Rect(arrangeSize)); 32 | } 33 | 34 | return arrangeSize; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace mpvnet.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Scripts/C-Sharp/switch-profile-context-menu.cs: -------------------------------------------------------------------------------- 1 | 2 | // This script creates context menu items dynamically. 3 | 4 | using mpvnet; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | 8 | class Script 9 | { 10 | MainForm MainForm; 11 | CorePlayer Core; 12 | 13 | public Script() 14 | { 15 | Core = Global.Core; 16 | MainForm = MainForm.Instance; 17 | MainForm.ContextMenu.Opening += ContextMenu_Opening; 18 | } 19 | 20 | void ContextMenu_Opening(object sender, CancelEventArgs e) 21 | { 22 | // edit input.conf and add 'Edition' menu item there 23 | MenuItem menuItem = MainForm.FindMenuItem("Edition"); 24 | 25 | if (menuItem == null) 26 | return; 27 | 28 | menuItem.DropDownItems.Clear(); 29 | var editionTracks = Core.MediaTracks.Where(track => track.Type == "e"); 30 | 31 | foreach (MediaTrack track in editionTracks) 32 | { 33 | MenuItem mi = new MenuItem(track.Text); 34 | mi.Action = () => { Core.CommandV("set", "edition", track.ID.ToString()); }; 35 | mi.Checked = Core.Edition == track.ID; 36 | menuItem.DropDownItems.Add(mi); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Interop/Handle/BitmapHandle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.ConstrainedExecution; 3 | using System.Runtime.InteropServices; 4 | using System.Security; 5 | 6 | namespace HandyControl.Tools.Interop 7 | { 8 | internal sealed class BitmapHandle : WpfSafeHandle 9 | { 10 | [SecurityCritical] 11 | private BitmapHandle() : this(true) 12 | { 13 | } 14 | 15 | [SecurityCritical] 16 | private BitmapHandle(bool ownsHandle) : base(ownsHandle, CommonHandles.GDI) 17 | { 18 | } 19 | 20 | [SecurityCritical] 21 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 22 | protected override bool ReleaseHandle() 23 | { 24 | return InteropMethods.DeleteObject(handle); 25 | } 26 | 27 | [SecurityCritical] 28 | internal HandleRef MakeHandleRef(object obj) 29 | { 30 | return new HandleRef(obj, handle); 31 | } 32 | 33 | [SecurityCritical] 34 | internal static BitmapHandle CreateFromHandle(IntPtr hbitmap, bool ownsHandle = true) 35 | { 36 | return new BitmapHandle(ownsHandle) 37 | { 38 | handle = hbitmap, 39 | }; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Extensions/RatingExtension/ScriptDevelopment.cs: -------------------------------------------------------------------------------- 1 | 2 | //// This script adds dynamic menu items for profile switching. 3 | 4 | //// In input.conf add a menu item called 'Profiles' 5 | 6 | //using mpvnet; 7 | //using System.ComponentModel; 8 | //using System.Linq; 9 | 10 | //class Script 11 | //{ 12 | // MainForm MainForm; 13 | // CorePlayer Core; 14 | 15 | // public Script() 16 | // { 17 | // Core = Global.Core; 18 | // MainForm = MainForm.Instance; 19 | // MainForm.ContextMenu.Opening += ContextMenu_Opening; 20 | // } 21 | 22 | // void ContextMenu_Opening(object sender, CancelEventArgs e) 23 | // { 24 | // MenuItem menuItem = MainForm.FindMenuItem("My Menu"); 25 | 26 | // if (menuItem == null) 27 | // { 28 | // Terminal.WriteError("Profiles menu item not found.", "switch-profile-context-menu.cs"); 29 | // return; 30 | // } 31 | 32 | // menuItem.DropDownItems.Clear(); 33 | // var editionTracks = Core.MediaTracks.Where(track => track.Type == "e"); 34 | 35 | // foreach (int i in new[] {1, 2, 3}) 36 | // { 37 | // MenuItem mi = new MenuItem(i.ToString()); 38 | // mi.Action = () => { Core.commandv("show-text", i.ToString()); }; 39 | // menuItem.DropDownItems.Add(mi); 40 | // } 41 | // } 42 | //} 43 | -------------------------------------------------------------------------------- /src/Misc/Extension.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.Composition; 5 | using System.ComponentModel.Composition.Hosting; 6 | using System.IO; 7 | 8 | using static mpvnet.Global; 9 | 10 | namespace mpvnet 11 | { 12 | public class Extension 13 | { 14 | [ImportMany] 15 | public IEnumerable Extensions = null; 16 | 17 | readonly CompositionContainer CompositionContainer; 18 | 19 | public Extension() 20 | { 21 | try 22 | { 23 | AggregateCatalog catalog = new AggregateCatalog(); 24 | string dir = Core.ConfigFolder + "extensions"; 25 | 26 | if (Directory.Exists(dir)) 27 | foreach (string extDir in Directory.GetDirectories(dir)) 28 | catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll")); 29 | 30 | if (catalog.Catalogs.Count > 0) 31 | { 32 | CompositionContainer = new CompositionContainer(catalog); 33 | CompositionContainer.ComposeParts(this); 34 | } 35 | } 36 | catch (Exception ex) 37 | { 38 | App.ShowException(ex); 39 | } 40 | } 41 | } 42 | 43 | public interface IExtension 44 | { 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Misc/Terminal.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Diagnostics; 4 | 5 | namespace mpvnet 6 | { 7 | public static class Terminal 8 | { 9 | static int Padding { get; } = 60; 10 | 11 | public static void WriteError(object obj, string module = "mpv.net") 12 | { 13 | Write(obj, module, ConsoleColor.DarkRed, false); 14 | } 15 | 16 | public static void Write(object obj, string module = "mpv.net") 17 | { 18 | Write(obj, module, ConsoleColor.Black, true); 19 | } 20 | 21 | public static void Write(object obj, string module, ConsoleColor color, bool useDefaultColor) 22 | { 23 | if (obj == null) 24 | return; 25 | 26 | string value = obj.ToString(); 27 | 28 | if (!string.IsNullOrEmpty(module)) 29 | module = "[" + module + "] "; 30 | 31 | if (useDefaultColor) 32 | Console.ResetColor(); 33 | else 34 | Console.ForegroundColor = color; 35 | 36 | value = module + value; 37 | 38 | if (value.Length < Padding) 39 | value = value.PadRight(Padding); 40 | 41 | if (color == ConsoleColor.Red || color == ConsoleColor.DarkRed) 42 | Console.Error.WriteLine(value); 43 | else 44 | Console.WriteLine(value); 45 | 46 | Console.ResetColor(); 47 | Trace.WriteLine(obj); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docs/Universal Remote/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/Universal Remote/remote.lua: -------------------------------------------------------------------------------- 1 | 2 | -- https://github.com/unifiedremote/Docs/blob/master/libs/keyboard.md 3 | 4 | -- https://github.com/unifiedremote/Docs/blob/master/res/keys.md 5 | 6 | local kb = libs.keyboard; 7 | 8 | actions.play = function () 9 | kb.stroke("space"); 10 | end 11 | 12 | actions.next = function () 13 | kb.stroke("F12"); 14 | end 15 | 16 | actions.prev = function () 17 | kb.stroke("F11"); 18 | end 19 | 20 | actions.enter = function () 21 | kb.stroke("enter"); 22 | end 23 | 24 | actions.left = function () 25 | kb.stroke("left"); 26 | end 27 | 28 | actions.right = function () 29 | kb.stroke("right"); 30 | end 31 | 32 | actions.up = function () 33 | kb.stroke("up"); 34 | end 35 | 36 | actions.down = function () 37 | kb.stroke("down"); 38 | end 39 | 40 | actions.vol_minus = function () 41 | kb.text("-"); 42 | end 43 | 44 | actions.vol_plus = function () 45 | kb.text("+"); 46 | end 47 | 48 | actions.mute = function () 49 | kb.stroke("m"); 50 | end 51 | 52 | actions.info = function () 53 | kb.stroke("i"); 54 | end 55 | 56 | actions.KP0 = function () 57 | kb.stroke("num0"); 58 | end 59 | 60 | actions.KP1 = function () 61 | kb.stroke("num1"); 62 | end 63 | 64 | actions.KP2 = function () 65 | kb.stroke("num2"); 66 | end 67 | 68 | actions.KP3 = function () 69 | kb.stroke("num3"); 70 | end 71 | 72 | actions.KP4 = function () 73 | kb.stroke("num4"); 74 | end 75 | 76 | actions.KP5 = function () 77 | kb.stroke("num5"); 78 | end 79 | 80 | actions.KP6 = function () 81 | kb.stroke("num6"); 82 | end 83 | 84 | actions.KP7 = function () 85 | kb.stroke("num7"); 86 | end 87 | 88 | actions.KP8 = function () 89 | kb.stroke("num8"); 90 | end 91 | 92 | actions.KP9 = function () 93 | kb.stroke("num9"); 94 | end 95 | 96 | actions.ab_loop = function () 97 | kb.stroke("l"); 98 | end 99 | 100 | actions.zoom_in = function () 101 | kb.stroke("ctrl", "oem_plus"); 102 | end 103 | 104 | actions.zoom_out = function () 105 | kb.stroke("ctrl", "oem_minus"); 106 | end 107 | -------------------------------------------------------------------------------- /src/Scripts/Lua/delete-current-file.lua: -------------------------------------------------------------------------------- 1 | 2 | -- This script deletes the file that is currently playing. 3 | 4 | -- input.conf: 5 | 6 | -- KP0 script-binding delete_current_file/delete 7 | -- 0 script-binding delete_current_file/delete 8 | 9 | -- KP1 script-binding delete_current_file/confirm 10 | -- 1 script-binding delete_current_file/confirm 11 | 12 | function delete() 13 | FileToDelete = mp.get_property("path") 14 | DeleteTime = os.time() 15 | mp.commandv("show-text", "Press 1 to delete file", "10000") 16 | end 17 | 18 | function confirm() 19 | local path = mp.get_property("path") 20 | 21 | if FileToDelete == path and (os.time() - DeleteTime) < 10 then 22 | mp.commandv("show-text", "") 23 | 24 | local count = mp.get_property_number("playlist-count") 25 | local pos = mp.get_property_number("playlist-pos") 26 | local newPos = 0 27 | 28 | if pos == count - 1 then 29 | newPos = pos - 1 30 | else 31 | newPos = pos + 1 32 | end 33 | 34 | if newPos > -1 then 35 | mp.command("set pause no") 36 | mp.set_property_number("playlist-pos", newPos) 37 | end 38 | 39 | mp.command("playlist-remove " .. pos) 40 | 41 | local ps_code = [[& { 42 | Start-Sleep -Seconds 2 43 | Add-Type -AssemblyName Microsoft.VisualBasic 44 | [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile('FileToDelete', 'OnlyErrorDialogs', 'SendToRecycleBin') 45 | }]] 46 | 47 | local escapedFileToDelete = string.gsub(FileToDelete, "'", "''") 48 | escapedFileToDelete = string.gsub(escapedFileToDelete, "’", "’’") 49 | escapedFileToDelete = string.gsub(escapedFileToDelete, "%%", "%%%%") 50 | ps_code = string.gsub(ps_code, "FileToDelete", escapedFileToDelete) 51 | 52 | mp.command_native({ 53 | name = "subprocess", 54 | playback_only = false, 55 | detach = true, 56 | args = { 'powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', ps_code }, 57 | }) 58 | end 59 | end 60 | 61 | mp.add_key_binding(nil, "delete", delete) 62 | mp.add_key_binding(nil, "confirm", confirm) 63 | -------------------------------------------------------------------------------- /src/Misc/Common.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace mpvnet 6 | { 7 | public class StringPair 8 | { 9 | public string Name { get; set; } 10 | public string Value { get; set; } 11 | } 12 | 13 | public class ConfParser 14 | { 15 | public static List Parse(string content) 16 | { 17 | string[] lines = content.Split("\r\n".ToCharArray()); 18 | var sections = new List(); 19 | ConfSection currentGroup = null; 20 | 21 | foreach (string i in lines) 22 | { 23 | string line = i.Trim(); 24 | 25 | if (string.IsNullOrEmpty(line)) 26 | continue; 27 | 28 | if (line.StartsWith("[") && line.EndsWith("]")) 29 | { 30 | currentGroup = new ConfSection() { Name = line.TrimStart('[').TrimEnd(']') }; 31 | sections.Add(currentGroup); 32 | } 33 | else if (line.Contains("=")) 34 | { 35 | string name = line.Substring(0, line.IndexOf("=")).Trim(); 36 | string value = line.Substring(line.IndexOf("=") + 1).Trim(); 37 | 38 | currentGroup.Items.Add(new StringPair() { Name = name, Value = value }); 39 | } 40 | } 41 | 42 | return sections; 43 | } 44 | } 45 | 46 | public class ConfSection 47 | { 48 | public string Name { get; set; } 49 | public List Items { get; set; } = new List(); 50 | 51 | public bool HasName(string name) 52 | { 53 | foreach (var i in Items) 54 | if (i.Name == name) 55 | return true; 56 | return false; 57 | } 58 | 59 | public string GetValue(string name) 60 | { 61 | foreach (var i in Items) 62 | if (i.Name == name) 63 | return i.Value; 64 | return null; 65 | } 66 | 67 | public List GetValues(string name) => Items.Where(i => i.Name == name).ToList(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Misc/Settings.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Drawing; 5 | using System.IO; 6 | using System.Text; 7 | using System.Xml.Serialization; 8 | using System.Xml; 9 | 10 | using static mpvnet.Global; 11 | 12 | namespace mpvnet 13 | { 14 | [Serializable()] 15 | public class AppSettings 16 | { 17 | public bool InputDefaultBindingsFixApplied; 18 | public int LastUpdateCheck; 19 | public int Volume = 70; 20 | public List RecentFiles = new List(); 21 | public Point WindowLocation; 22 | public Point WindowPosition; 23 | public Size WindowSize; 24 | public string ConfigEditorSearch = ""; 25 | public string Mute = "no"; 26 | public string UpdateCheckVersion = ""; 27 | } 28 | 29 | class SettingsManager 30 | { 31 | public static string SettingsFile => Core.ConfigFolder + "settings.xml"; 32 | 33 | public static AppSettings Load() 34 | { 35 | if (!File.Exists(SettingsFile)) 36 | return new AppSettings(); 37 | 38 | try 39 | { 40 | XmlSerializer serializer = new XmlSerializer(typeof(AppSettings)); 41 | 42 | using (FileStream fs = new FileStream(SettingsFile, FileMode.Open)) 43 | return (AppSettings)serializer.Deserialize(fs); 44 | } 45 | catch (Exception ex) 46 | { 47 | Terminal.WriteError(ex.ToString()); 48 | return new AppSettings(); 49 | } 50 | } 51 | 52 | public static void Save(object obj) 53 | { 54 | try 55 | { 56 | using (XmlTextWriter writer = new XmlTextWriter(SettingsFile, Encoding.UTF8)) 57 | { 58 | writer.Formatting = Formatting.Indented; 59 | writer.Indentation = 4; 60 | XmlSerializer serializer = new XmlSerializer(obj.GetType()); 61 | serializer.Serialize(writer, obj); 62 | } 63 | } 64 | catch (Exception ex) 65 | { 66 | Terminal.WriteError(ex.ToString()); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Scripts/C-Sharp/delete-current-file.cs: -------------------------------------------------------------------------------- 1 | 2 | // C# Script that deletes the current file 3 | 4 | // In input.conf add: 5 | 6 | // KP0 script-message delete-current-file delete #menu: Script > Delete current file > Delete 7 | // 0 script-message delete-current-file delete #menu: Script > Delete current file > Delete 8 | 9 | // KP1 script-message delete-current-file confirm #menu: Script > Delete current file > Confirm 10 | // 1 script-message delete-current-file confirm #menu: Script > Delete current file > Confirm 11 | 12 | using System; 13 | using System.IO; 14 | using System.Threading; 15 | 16 | using Microsoft.VisualBasic.FileIO; 17 | 18 | using mpvnet; 19 | 20 | class Script 21 | { 22 | string FileToDelete; 23 | DateTime DeleteTime; 24 | CorePlayer Core; 25 | 26 | public Script() 27 | { 28 | Core = Global.Core; 29 | Core.ClientMessage += ClientMessage; 30 | } 31 | 32 | void ClientMessage(string[] args) 33 | { 34 | if (args == null || args.Length != 2 || args[0] != "delete-current-file") 35 | return; 36 | 37 | if (args[1] == "delete") 38 | { 39 | FileToDelete = Core.GetPropertyString("path"); 40 | DeleteTime = DateTime.Now; 41 | Core.CommandV("show-text", "Press 1 to delete file", "10000"); 42 | } 43 | else if (args[1] == "confirm") 44 | { 45 | TimeSpan ts = DateTime.Now - DeleteTime; 46 | string path = Core.GetPropertyString("path"); 47 | 48 | if (FileToDelete == path && ts.TotalSeconds < 10 && File.Exists(FileToDelete)) 49 | { 50 | Core.CommandV("show-text", ""); 51 | 52 | int count = Core.GetPropertyInt("playlist-count"); 53 | int pos = Core.GetPropertyInt("playlist-pos"); 54 | int newPos = pos == count - 1 ? pos - 1 : pos + 1; 55 | 56 | if (newPos > -1) 57 | Core.SetPropertyNumber("playlist-pos", newPos); 58 | 59 | Core.Command("playlist-remove " + pos); 60 | 61 | App.RunTask(() => { 62 | Thread.Sleep(2000); 63 | FileSystem.DeleteFile(FileToDelete, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin); 64 | }); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Controls/Attach/BorderElement.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Data; 5 | 6 | using HandyControl.Data; 7 | using HandyControl.Tools.Converter; 8 | 9 | namespace HandyControl.Controls 10 | { 11 | public class BorderElement 12 | { 13 | public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached( 14 | "CornerRadius", typeof(CornerRadius), typeof(BorderElement), new FrameworkPropertyMetadata(default(CornerRadius), FrameworkPropertyMetadataOptions.Inherits)); 15 | 16 | public static void SetCornerRadius(DependencyObject element, CornerRadius value) => element.SetValue(CornerRadiusProperty, value); 17 | 18 | public static CornerRadius GetCornerRadius(DependencyObject element) => (CornerRadius) element.GetValue(CornerRadiusProperty); 19 | 20 | public static readonly DependencyProperty CircularProperty = DependencyProperty.RegisterAttached( 21 | "Circular", typeof(bool), typeof(BorderElement), new PropertyMetadata(ValueBoxes.FalseBox, OnCircularChanged)); 22 | 23 | private static void OnCircularChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 24 | { 25 | if (d is Border border) 26 | { 27 | if ((bool) e.NewValue) 28 | { 29 | var binding = new MultiBinding 30 | { 31 | Converter = new BorderCircularConverter() 32 | }; 33 | binding.Bindings.Add(new Binding(FrameworkElement.ActualWidthProperty.Name) { Source = border }); 34 | binding.Bindings.Add(new Binding(FrameworkElement.ActualHeightProperty.Name) { Source = border }); 35 | border.SetBinding(Border.CornerRadiusProperty, binding); 36 | } 37 | else 38 | { 39 | BindingOperations.ClearBinding(border, FrameworkElement.ActualWidthProperty); 40 | BindingOperations.ClearBinding(border, FrameworkElement.ActualHeightProperty); 41 | BindingOperations.ClearBinding(border, Border.CornerRadiusProperty); 42 | } 43 | } 44 | } 45 | 46 | public static void SetCircular(DependencyObject element, bool value) 47 | => element.SetValue(CircularProperty, ValueBoxes.BooleanBox(value)); 48 | 49 | public static bool GetCircular(DependencyObject element) 50 | => (bool) element.GetValue(CircularProperty); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/WPF/StringSettingControl.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 41 | 42 | 51 | 52 | 53 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/Misc/CSharpScriptHost.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.CodeDom.Compiler; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using Microsoft.CSharp; 9 | 10 | using static mpvnet.Global; 11 | 12 | namespace mpvnet 13 | { 14 | class CSharpScriptHost 15 | { 16 | static List References = new List(); 17 | 18 | public static void ExecuteScriptsInFolder(string folder) 19 | { 20 | if (Directory.Exists(folder)) 21 | foreach (string file in Directory.GetFiles(folder, "*.cs")) 22 | App.RunTask(() => Execute(file)); 23 | } 24 | 25 | static void Execute(string file) 26 | { 27 | string code = File.ReadAllText(file); 28 | string filename = Path.GetFileNameWithoutExtension(file) + " " + StringHelp.GetMD5Hash(code) + ".dll"; 29 | string outputFile = Path.Combine(Path.GetTempPath(), filename); 30 | 31 | if (!File.Exists(outputFile)) 32 | Compile(outputFile, file); 33 | 34 | if (File.Exists(outputFile)) 35 | { 36 | object instance = Assembly.LoadFile(outputFile).CreateInstance("Script"); 37 | 38 | if (instance != null) 39 | References.Add(instance); 40 | else 41 | Terminal.WriteError("Failed to initialize script.", outputFile.FileName()); 42 | } 43 | } 44 | 45 | public static void Compile(string outputFile, string file) 46 | { 47 | CSharpCodeProvider provider = new CSharpCodeProvider(); 48 | CompilerParameters parameters = new CompilerParameters(); 49 | 50 | string[] dependencies = { 51 | Folder.Startup + "mpvnet.exe", 52 | "Microsoft.VisualBasic.dll", 53 | "System.Core.dll", "System.Data.dll", "System.dll", "System.Drawing.dll", "System.Web.dll", 54 | "System.Windows.Forms.dll", "System.Xaml.dll", "System.Xml.dll", "System.Xml.Linq.dll", 55 | "WPF\\PresentationCore.dll", "WPF\\PresentationFramework.dll", "WPF\\WindowsBase.dll" 56 | }; 57 | 58 | foreach (string i in dependencies) 59 | parameters.ReferencedAssemblies.Add(i); 60 | 61 | parameters.OutputAssembly = outputFile; 62 | CompilerResults results = provider.CompileAssemblyFromFile(parameters, file); 63 | 64 | var errors = results.Errors.Cast().Select(i => "Line Number " + 65 | i.Line + "\n" + "Error Number: " + i.ErrorNumber + "\n" + i.ErrorText); 66 | 67 | if (errors.Count() > 0) 68 | Terminal.WriteError(string.Join(BR2, errors), Path.GetFileName(file)); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Misc/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace mpvnet 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 33 | this.CursorTimer = new System.Windows.Forms.Timer(this.components); 34 | this.ProgressTimer = new System.Windows.Forms.Timer(this.components); 35 | this.SuspendLayout(); 36 | // 37 | // CursorTimer 38 | // 39 | this.CursorTimer.Enabled = true; 40 | this.CursorTimer.Interval = 1000; 41 | this.CursorTimer.Tick += new System.EventHandler(this.CursorTimer_Tick); 42 | // 43 | // ProgressTimer 44 | // 45 | this.ProgressTimer.Tick += new System.EventHandler(this.ProgressTimer_Tick); 46 | // 47 | // MainForm 48 | // 49 | this.AllowDrop = true; 50 | this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F); 51 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; 52 | this.BackColor = System.Drawing.Color.Black; 53 | this.ClientSize = new System.Drawing.Size(348, 0); 54 | this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 55 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 56 | this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); 57 | this.Name = "MainForm"; 58 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 59 | this.ResumeLayout(false); 60 | 61 | } 62 | 63 | #endregion 64 | 65 | private System.Windows.Forms.Timer CursorTimer; 66 | private System.Windows.Forms.Timer ProgressTimer; 67 | } 68 | } -------------------------------------------------------------------------------- /src/Scripts/C-Sharp/rate-file.cs: -------------------------------------------------------------------------------- 1 | 2 | // This script writes a rating to the filename of rated videos when mpv.net shuts down. 3 | 4 | // In input.conf add: 5 | 6 | // KP0 script-message rate-file 0 #menu: Script > Rating > 0stars 7 | // KP1 script-message rate-file 1 #menu: Script > Rating > 1stars 8 | // KP2 script-message rate-file 2 #menu: Script > Rating > 2stars 9 | // KP3 script-message rate-file 3 #menu: Script > Rating > 3stars 10 | // KP4 script-message rate-file 4 #menu: Script > Rating > 4stars 11 | // KP5 script-message rate-file 5 #menu: Script > Rating > 5stars 12 | 13 | using System; 14 | using System.Collections.Generic; 15 | using System.IO; 16 | using System.Windows.Forms; 17 | 18 | using mpvnet; 19 | 20 | class Script 21 | { 22 | // dictionory to store the filename and the rating 23 | Dictionary Dic = new Dictionary(); 24 | CorePlayer Core; 25 | 26 | public Script() // plugin initialization 27 | { 28 | Core = Global.Core; 29 | Core.ClientMessage += ClientMessage; //handles keys defined in input.conf 30 | Core.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN 31 | } 32 | 33 | // handles MPV_EVENT_SHUTDOWN 34 | void Shutdown() 35 | { 36 | foreach (var i in Dic) 37 | { 38 | string filepath = i.Key; 39 | int rating = i.Value; 40 | 41 | if (string.IsNullOrEmpty(filepath) || !File.Exists(filepath)) 42 | return; 43 | 44 | string basename = Path.GetFileNameWithoutExtension(filepath); 45 | 46 | for (int x = 0; x < 6; x++) 47 | if (basename.Contains(" (" + x + "stars)")) 48 | basename = basename.Replace(" (" + x + "stars)", ""); 49 | 50 | basename += " (" + rating + "stars)"; 51 | 52 | string newPath = Path.Combine(Path.GetDirectoryName(filepath), 53 | basename + Path.GetExtension(filepath)); 54 | 55 | if (filepath.ToLower() != newPath.ToLower()) 56 | File.Move(filepath, newPath); 57 | 58 | File.SetLastWriteTime(newPath, DateTime.Now); 59 | } 60 | } 61 | 62 | //handles keys defined in input.conf 63 | void ClientMessage(string[] args) 64 | { 65 | if (args == null || args.Length != 2 || args[0] != "rate-file") 66 | return; 67 | 68 | int rating; 69 | 70 | if (int.TryParse(args[1], out rating)) 71 | { 72 | string path = Core.GetPropertyString("path"); 73 | 74 | if (!File.Exists(path)) 75 | return; 76 | 77 | Dic[path] = rating; 78 | Core.CommandV("show-text", "Rating: " + rating); 79 | } 80 | else if (args[1] == "about") 81 | MessageBox.Show("This extension writes a rating to the filename of rated videos when mpv.net shuts down.", 82 | "Rating Extension"); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/AnimationHelper.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using System.Windows; 6 | using System.Windows.Media; 7 | using System.Windows.Media.Animation; 8 | 9 | using HandyControl.Tools.Extension; 10 | 11 | namespace HandyControl.Tools 12 | { 13 | public class AnimationHelper 14 | { 15 | public static ThicknessAnimation CreateAnimation(Thickness thickness = default, double milliseconds = 200) 16 | { 17 | return new ThicknessAnimation(thickness, new Duration(TimeSpan.FromMilliseconds(milliseconds))) 18 | { 19 | EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut } 20 | }; 21 | } 22 | 23 | public static DoubleAnimation CreateAnimation(double toValue, double milliseconds = 200) 24 | { 25 | return new DoubleAnimation(toValue, new Duration(TimeSpan.FromMilliseconds(milliseconds))) 26 | { 27 | EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut } 28 | }; 29 | } 30 | 31 | internal static void DecomposeGeometryStr(string geometryStr, out double[] arr) 32 | { 33 | var collection = Regex.Matches(geometryStr, RegexPatterns.DigitsPattern); 34 | arr = new double[collection.Count]; 35 | for (var i = 0; i < collection.Count; i++) 36 | { 37 | arr[i] = collection[i].Value.Value(); 38 | } 39 | } 40 | 41 | internal static Geometry ComposeGeometry(string[] strings, double[] arr) 42 | { 43 | var builder = new StringBuilder(strings[0]); 44 | for (var i = 0; i < arr.Length; i++) 45 | { 46 | var s = strings[i + 1]; 47 | var n = arr[i]; 48 | if (!double.IsNaN(n)) 49 | { 50 | builder.Append(n).Append(s); 51 | } 52 | } 53 | 54 | return Geometry.Parse(builder.ToString()); 55 | } 56 | 57 | internal static Geometry InterpolateGeometry(double[] from, double[] to, double progress, string[] strings) 58 | { 59 | var accumulated = new double[to.Length]; 60 | for (var i = 0; i < to.Length; i++) 61 | { 62 | var fromValue = from[i]; 63 | accumulated[i] = fromValue + (to[i] - fromValue) * progress; 64 | } 65 | 66 | return ComposeGeometry(strings, accumulated); 67 | } 68 | 69 | internal static double[] InterpolateGeometryValue(double[] from, double[] to, double progress) 70 | { 71 | var accumulated = new double[to.Length]; 72 | for (var i = 0; i < to.Length; i++) 73 | { 74 | var fromValue = from[i]; 75 | accumulated[i] = fromValue + (to[i] - fromValue) * progress; 76 | } 77 | 78 | return accumulated; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Extensions/RatingExtension/RatingExtension.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {55C88710-539D-4402-84C8-31694841C731} 8 | Library 9 | Properties 10 | RatingExtension 11 | RatingExtension 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | true 18 | bin\ 19 | DEBUG;TRACE 20 | full 21 | AnyCPU 22 | 7.3 23 | prompt 24 | MinimumRecommendedRules.ruleset 25 | 26 | 27 | bin\ 28 | TRACE 29 | true 30 | pdbonly 31 | AnyCPU 32 | 7.3 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {1751f378-8edf-4b62-be6d-304c7c287089} 58 | mpv.net 59 | False 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Helper/VisualHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows; 4 | using System.Windows.Interop; 5 | using System.Windows.Media; 6 | using HandyControl.Tools.Interop; 7 | 8 | namespace HandyControl.Tools 9 | { 10 | public static class VisualHelper 11 | { 12 | internal static VisualStateGroup TryGetVisualStateGroup(DependencyObject d, string groupName) 13 | { 14 | var root = GetImplementationRoot(d); 15 | if (root == null) return null; 16 | 17 | return VisualStateManager 18 | .GetVisualStateGroups(root)? 19 | .OfType() 20 | .FirstOrDefault(group => string.CompareOrdinal(groupName, group.Name) == 0); 21 | } 22 | 23 | internal static FrameworkElement GetImplementationRoot(DependencyObject d) => 24 | 1 == VisualTreeHelper.GetChildrenCount(d) 25 | ? VisualTreeHelper.GetChild(d, 0) as FrameworkElement 26 | : null; 27 | 28 | public static T GetChild(DependencyObject d) where T : DependencyObject 29 | { 30 | if (d == null) return default; 31 | if (d is T t) return t; 32 | 33 | for (var i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++) 34 | { 35 | var child = VisualTreeHelper.GetChild(d, i); 36 | 37 | var result = GetChild(child); 38 | if (result != null) return result; 39 | } 40 | 41 | return default; 42 | } 43 | 44 | public static T GetParent(DependencyObject d) where T : DependencyObject 45 | { 46 | if (d == null) 47 | return default; 48 | 49 | if (d is T) 50 | return d as T; 51 | 52 | if (d is Window) 53 | return null; 54 | 55 | return GetParent(VisualTreeHelper.GetParent(d)); 56 | } 57 | 58 | public static IntPtr GetHandle(this Visual visual) => (PresentationSource.FromVisual(visual) as HwndSource)?.Handle ?? IntPtr.Zero; 59 | 60 | internal static void HitTestVisibleElements(Visual visual, HitTestResultCallback resultCallback, HitTestParameters parameters) => 61 | VisualTreeHelper.HitTest(visual, ExcludeNonVisualElements, resultCallback, parameters); 62 | 63 | private static HitTestFilterBehavior ExcludeNonVisualElements(DependencyObject potentialHitTestTarget) 64 | { 65 | if (!(potentialHitTestTarget is Visual)) return HitTestFilterBehavior.ContinueSkipSelfAndChildren; 66 | 67 | if (!(potentialHitTestTarget is UIElement uIElement) || uIElement.IsVisible && uIElement.IsEnabled) 68 | return HitTestFilterBehavior.Continue; 69 | 70 | return HitTestFilterBehavior.ContinueSkipSelfAndChildren; 71 | } 72 | 73 | internal static bool ModifyStyle(IntPtr hWnd, int styleToRemove, int styleToAdd) 74 | { 75 | var windowLong = InteropMethods.GetWindowLong(hWnd, InteropValues.GWL.STYLE); 76 | var num = (windowLong & ~styleToRemove) | styleToAdd; 77 | if (num == windowLong) return false; 78 | InteropMethods.SetWindowLong(hWnd, InteropValues.GWL.STYLE, num); 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/RegexPatterns.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace HandyControl.Tools 3 | { 4 | public sealed class RegexPatterns 5 | { 6 | public const string MailPattern = 7 | @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"; 8 | 9 | public const string PhonePattern = @"^((13[0-9])|(15[^4,\d])|(18[0,5-9]))\d{8}$"; 10 | 11 | public const string IpPattern = 12 | @"^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 13 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 14 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 15 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"; 16 | 17 | public const string IpAPattern = 18 | @"^(12[0-6]|1[0-1]\d|[1-9]?\d)\." 19 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 20 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 21 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"; 22 | 23 | public const string IpBPattern = 24 | @"^(19[0-1]|12[8-9]|1[3-8]\d)\." 25 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 26 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 27 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"; 28 | 29 | public const string IpCPattern = 30 | @"^(19[2-9]|22[0-3]|2[0-1]\d)\." 31 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 32 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 33 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"; 34 | 35 | public const string IpDPattern = 36 | @"^(22[4-9]|23\d\." 37 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 38 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 39 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"; 40 | 41 | public const string IpEPattern = 42 | @"^(25[0-5]|24\d\." 43 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 44 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\." 45 | + @"(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$"; 46 | 47 | public const string ChinesePattern = @"^[\u4e00-\u9fa5]$"; 48 | 49 | public const string UrlPattern = 50 | @"((http|ftp|https)://)(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\&%_\./-~-]*)?"; 51 | 52 | public const string NumberPattern = @"^\d+$"; 53 | 54 | public const string DigitsPattern = @"[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?"; 55 | 56 | public const string PIntPattern = @"^[1-9]\d*$"; 57 | 58 | public const string NIntPattern = @"^-[1-9]\d*$ "; 59 | 60 | public const string IntPattern = @"^-?[1-9]\d*|0$"; 61 | 62 | public const string NnIntPattern = @"^[1-9]\d*|0$"; 63 | 64 | public const string NpIntPattern = @"^-[1-9]\d*|0$"; 65 | 66 | public const string PDoublePattern = @"^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$"; 67 | 68 | public const string NDoublePattern = @"^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$"; 69 | 70 | public const string DoublePattern = @"^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$"; 71 | 72 | public const string NnDoublePattern = @"^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$"; 73 | 74 | public const string NpDoublePattern = @"^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$"; 75 | 76 | public object GetValue(string propertyName) => GetType().GetField(propertyName).GetValue(null); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Misc/ExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Text.RegularExpressions; 5 | 6 | public static class TestStringExtension 7 | { 8 | public static bool ContainsEx(this string instance, string value) 9 | { 10 | if (instance != null && value != null) 11 | return instance.Contains(value); 12 | 13 | return false; 14 | } 15 | 16 | public static bool StartsWithEx(this string instance, string value) 17 | { 18 | if (instance != null && value != null) 19 | return instance.StartsWith(value); 20 | 21 | return false; 22 | } 23 | } 24 | 25 | public static class ConvertToStringExtension 26 | { 27 | public static string ToUpperEx(this string instance) 28 | { 29 | if (instance != null) 30 | return instance.ToUpperInvariant(); 31 | 32 | return ""; 33 | } 34 | 35 | public static string ToLowerEx(this string instance) 36 | { 37 | if (instance != null) 38 | return instance.ToLowerInvariant(); 39 | 40 | return ""; 41 | } 42 | 43 | public static string TrimEx(this string instance) 44 | { 45 | if (instance == null) 46 | return ""; 47 | 48 | return instance.Trim(); 49 | } 50 | } 51 | 52 | public static class ConvertStringExtension 53 | { 54 | public static int ToInt(this string instance) 55 | { 56 | int.TryParse(instance, out int result); 57 | return result; 58 | } 59 | 60 | public static float ToFloat(this string instance) 61 | { 62 | float.TryParse(instance.Replace(",", "."), NumberStyles.Float, 63 | CultureInfo.InvariantCulture, out float result); 64 | 65 | return result; 66 | } 67 | } 68 | 69 | public static class PathStringExtension 70 | { 71 | // returns the extension with lower case and without preceding dot. 72 | public static string Ext(this string instance) 73 | { 74 | if (instance == null) 75 | return ""; 76 | 77 | return Path.GetExtension(instance).TrimStart('.').ToLower(); 78 | } 79 | 80 | public static string FileName(this string instance) 81 | { 82 | if (string.IsNullOrEmpty(instance)) 83 | return ""; 84 | 85 | int index = instance.LastIndexOf('\\'); 86 | 87 | if (index > -1) 88 | return instance.Substring(index + 1); 89 | 90 | index = instance.LastIndexOf('/'); 91 | 92 | if (index > -1) 93 | return instance.Substring(index + 1); 94 | 95 | return instance; 96 | } 97 | 98 | public static string ShortPath(this string instance, int maxLength) 99 | { 100 | if (string.IsNullOrEmpty(instance)) 101 | return ""; 102 | 103 | if (instance.Length > maxLength && instance.Substring(1, 2) == ":\\") 104 | instance = instance.Substring(0, 3) + "...\\" + instance.FileName(); 105 | 106 | return instance; 107 | } 108 | 109 | // Ensure trailing directory separator char 110 | public static string AddSep(this string instance) 111 | { 112 | if (string.IsNullOrEmpty(instance)) 113 | return ""; 114 | 115 | if (!instance.EndsWith(Path.DirectorySeparatorChar.ToString())) 116 | instance = instance + Path.DirectorySeparatorChar; 117 | 118 | return instance; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/WPF/OptionSettingControl.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | 28 | 29 | 40 | 41 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/WPF/SearchTextBoxUserControl.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 16 | 17 | 25 | 26 | 36 | 37 | 86 | 87 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Helper/ScreenHelper.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | using HandyControl.Tools.Interop; 8 | 9 | namespace HandyControl.Tools 10 | { 11 | internal class ScreenHelper 12 | { 13 | internal static void FindMaximumSingleMonitorRectangle(Rect windowRect, out Rect screenSubRect, out Rect monitorRect) 14 | { 15 | var windowRect2 = new InteropValues.RECT(windowRect); 16 | FindMaximumSingleMonitorRectangle(windowRect2, out var rect, out var rect2); 17 | screenSubRect = new Rect(rect.Position, rect.Size); 18 | monitorRect = new Rect(rect2.Position, rect2.Size); 19 | } 20 | 21 | private static void FindMaximumSingleMonitorRectangle(InteropValues.RECT windowRect, out InteropValues.RECT screenSubRect, out InteropValues.RECT monitorRect) 22 | { 23 | var rects = new List(); 24 | InteropMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, 25 | delegate (IntPtr hMonitor, IntPtr hdcMonitor, ref InteropValues.RECT rect, IntPtr lpData) 26 | { 27 | var monitorInfo = default(InteropValues.MONITORINFO); 28 | monitorInfo.cbSize = (uint) Marshal.SizeOf(typeof(InteropValues.MONITORINFO)); 29 | InteropMethods.GetMonitorInfo(hMonitor, ref monitorInfo); 30 | rects.Add(monitorInfo.rcWork); 31 | return true; 32 | }, IntPtr.Zero); 33 | 34 | var num = 0L; 35 | 36 | screenSubRect = new InteropValues.RECT 37 | { 38 | Left = 0, 39 | Right = 0, 40 | Top = 0, 41 | Bottom = 0 42 | }; 43 | 44 | monitorRect = new InteropValues.RECT 45 | { 46 | Left = 0, 47 | Right = 0, 48 | Top = 0, 49 | Bottom = 0 50 | }; 51 | 52 | foreach (var current in rects) 53 | { 54 | var rect = current; 55 | InteropMethods.IntersectRect(out var rECT2, ref rect, ref windowRect); 56 | var num2 = (long) (rECT2.Width * rECT2.Height); 57 | if (num2 > num) 58 | { 59 | screenSubRect = rECT2; 60 | monitorRect = current; 61 | num = num2; 62 | } 63 | } 64 | } 65 | 66 | internal static void FindMonitorRectsFromPoint(Point point, out Rect monitorRect, out Rect workAreaRect) 67 | { 68 | var intPtr = InteropMethods.MonitorFromPoint(new InteropValues.POINT 69 | { 70 | X = (int) point.X, 71 | Y = (int) point.Y 72 | }, 2); 73 | 74 | monitorRect = new Rect(0.0, 0.0, 0.0, 0.0); 75 | workAreaRect = new Rect(0.0, 0.0, 0.0, 0.0); 76 | 77 | if (intPtr != IntPtr.Zero) 78 | { 79 | InteropValues.MONITORINFO monitorInfo = default; 80 | monitorInfo.cbSize = (uint) Marshal.SizeOf(typeof(InteropValues.MONITORINFO)); 81 | InteropMethods.GetMonitorInfo(intPtr, ref monitorInfo); 82 | monitorRect = new Rect(monitorInfo.rcMonitor.Position, monitorInfo.rcMonitor.Size); 83 | workAreaRect = new Rect(monitorInfo.rcWork.Position, monitorInfo.rcWork.Size); 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Misc/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows.Forms; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | using System.Threading; 7 | using System.Diagnostics; 8 | 9 | namespace mpvnet 10 | { 11 | static class Program 12 | { 13 | [STAThread] 14 | static void Main() 15 | { 16 | try 17 | { 18 | Application.EnableVisualStyles(); 19 | Application.SetCompatibleTextRenderingDefault(false); 20 | 21 | if (App.IsTerminalAttached) 22 | Native.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/); 23 | 24 | string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray(); 25 | 26 | if (args.Length > 0 && args[0] == "--register-file-associations") 27 | { 28 | FileAssociation.Register(args[1], args.Skip(1).ToArray()); 29 | return; 30 | } 31 | 32 | App.Init(); 33 | Mutex mutex = new Mutex(true, StringHelp.GetMD5Hash(App.ConfPath), out bool isFirst); 34 | 35 | if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst) 36 | { 37 | List args2 = new List(); 38 | args2.Add(App.ProcessInstance); 39 | 40 | foreach (string arg in args) 41 | { 42 | if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") || 43 | arg.Contains(":\\") || arg.StartsWith("\\\\"))) 44 | 45 | args2.Add(arg); 46 | else if (arg == "--queue") 47 | args2[0] = "queue"; 48 | else if (arg.StartsWith("--command=")) 49 | { 50 | args2[0] = "command"; 51 | args2.Add(arg.Substring(10)); 52 | } 53 | } 54 | 55 | Process[] procs = Process.GetProcessesByName("mpvnet"); 56 | 57 | for (int i = 0; i < 20; i++) 58 | { 59 | foreach (Process proc in procs) 60 | { 61 | if (proc.MainWindowHandle != IntPtr.Zero) 62 | { 63 | Native.AllowSetForegroundWindow(proc.Id); 64 | var data = new Native.COPYDATASTRUCT(); 65 | data.lpData = string.Join("\n", args2.ToArray()); 66 | data.cbData = data.lpData.Length * 2 + 1; 67 | Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data); 68 | mutex.Dispose(); 69 | 70 | if (App.IsTerminalAttached) 71 | Native.FreeConsole(); 72 | 73 | return; 74 | } 75 | } 76 | 77 | Thread.Sleep(50); 78 | } 79 | 80 | mutex.Dispose(); 81 | return; 82 | } 83 | 84 | Application.Run(new MainForm()); 85 | 86 | if (App.IsTerminalAttached) 87 | Native.FreeConsole(); 88 | 89 | mutex.Dispose(); 90 | } 91 | catch (Exception ex) 92 | { 93 | Msg.ShowException(ex); 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/WPF/ConfWindow.xaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 39 | 40 | 47 | 48 | 49 | 50 | 51 | 52 | 60 | 61 | 62 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Open config folder 79 | Preview mpv.conf 80 | Show mpv manual 81 | Show support forum 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/Native/MediaInfo.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Runtime.InteropServices; 4 | 5 | public class MediaInfo : IDisposable 6 | { 7 | IntPtr Handle; 8 | 9 | public MediaInfo(string file) 10 | { 11 | if ((Handle = MediaInfo_New()) == IntPtr.Zero) 12 | throw new Exception("Failed to call MediaInfo_New"); 13 | 14 | if (MediaInfo_Open(Handle, file) == 0) 15 | throw new Exception("Error MediaInfo_Open"); 16 | } 17 | 18 | public string GetInfo(MediaInfoStreamKind kind, string parameter) 19 | { 20 | return Marshal.PtrToStringUni(MediaInfo_Get(Handle, kind, 0, 21 | parameter, MediaInfoKind.Text, MediaInfoKind.Name)); 22 | } 23 | 24 | public int GetCount(MediaInfoStreamKind kind) => MediaInfo_Count_Get(Handle, kind, -1); 25 | 26 | public string GetVideo(int stream, string parameter) 27 | { 28 | return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video, 29 | stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)); 30 | } 31 | 32 | public string GetAudio(int stream, string parameter) 33 | { 34 | return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio, 35 | stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)); 36 | } 37 | 38 | public string GetText(int stream, string parameter) 39 | { 40 | return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, 41 | stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)); 42 | } 43 | 44 | public string GetSummary(bool complete, bool rawView) 45 | { 46 | MediaInfo_Option(Handle, "Language", rawView ? "raw" : ""); 47 | MediaInfo_Option(Handle, "Complete", complete ? "1" : "0"); 48 | return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, 0)) ?? ""; 49 | } 50 | 51 | bool Disposed; 52 | 53 | public void Dispose() 54 | { 55 | if (!Disposed) 56 | { 57 | if (Handle != IntPtr.Zero) 58 | { 59 | MediaInfo_Close(Handle); 60 | MediaInfo_Delete(Handle); 61 | } 62 | 63 | Disposed = true; 64 | } 65 | } 66 | 67 | ~MediaInfo() 68 | { 69 | Dispose(); 70 | } 71 | 72 | [DllImport("MediaInfo.dll")] 73 | static extern IntPtr MediaInfo_New(); 74 | 75 | [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] 76 | static extern int MediaInfo_Open(IntPtr handle, string path); 77 | 78 | [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] 79 | static extern IntPtr MediaInfo_Option(IntPtr handle, string option, string value); 80 | 81 | [DllImport("MediaInfo.dll")] 82 | static extern IntPtr MediaInfo_Inform(IntPtr handle, int reserved); 83 | 84 | [DllImport("MediaInfo.dll")] 85 | static extern int MediaInfo_Close(IntPtr handle); 86 | 87 | [DllImport("MediaInfo.dll")] 88 | static extern void MediaInfo_Delete(IntPtr handle); 89 | 90 | [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] 91 | static extern IntPtr MediaInfo_Get(IntPtr handle, MediaInfoStreamKind kind, 92 | int stream, string parameter, MediaInfoKind infoKind, MediaInfoKind searchKind); 93 | 94 | [DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)] 95 | static extern int MediaInfo_Count_Get(IntPtr handle, MediaInfoStreamKind streamKind, int stream); 96 | } 97 | 98 | public enum MediaInfoStreamKind 99 | { 100 | General, 101 | Video, 102 | Audio, 103 | Text, 104 | Other, 105 | Image, 106 | Menu, 107 | Max, 108 | } 109 | 110 | public enum MediaInfoKind 111 | { 112 | Name, 113 | Text, 114 | Measure, 115 | Options, 116 | NameText, 117 | MeasureText, 118 | Info, 119 | HowTo 120 | } 121 | -------------------------------------------------------------------------------- /src/Misc/Theme.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Collections.Generic; 3 | using System.Windows.Media; 4 | 5 | namespace mpvnet 6 | { 7 | public class Theme 8 | { 9 | public string Name { get; set; } 10 | public Dictionary Dictionary { get; } = new Dictionary(); 11 | 12 | public static List DefaultThemes { get; set; } 13 | public static List CustomThemes { get; set; } 14 | 15 | public static Theme Current { get; set; } 16 | 17 | public Brush Background { get; set; } 18 | public Brush Foreground { get; set; } 19 | public Brush Foreground2 { get; set; } 20 | public Brush Heading { get; set; } 21 | public Brush MenuBackground { get; set; } 22 | public Brush MenuHighlight { get; set; } 23 | 24 | public Brush GetBrush(string key) 25 | { 26 | return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key])); 27 | } 28 | 29 | public Color GetColor(string key) => (Color)ColorConverter.ConvertFromString(Dictionary[key]); 30 | 31 | public static void Init(string customContent, string defaultContent, string activeTheme) 32 | { 33 | Current = null; 34 | 35 | DefaultThemes = Load(defaultContent); 36 | CustomThemes = Load(customContent); 37 | 38 | foreach (Theme theme in CustomThemes) 39 | { 40 | if (theme.Name == activeTheme) 41 | { 42 | bool isKeyMissing = false; 43 | 44 | foreach (string key in DefaultThemes[0].Dictionary.Keys) 45 | { 46 | if (!theme.Dictionary.ContainsKey(key)) 47 | { 48 | isKeyMissing = true; 49 | Terminal.WriteError($"Theme '{activeTheme}' misses '{key}'"); 50 | break; 51 | } 52 | } 53 | 54 | if (!isKeyMissing) 55 | Current = theme; 56 | 57 | break; 58 | } 59 | } 60 | 61 | if (Current == null) 62 | foreach (Theme theme in DefaultThemes) 63 | if (theme.Name == activeTheme) 64 | Current = theme; 65 | 66 | if (Current == null) 67 | Current = DefaultThemes[0]; 68 | 69 | Current.Background = Current.GetBrush("background"); 70 | Current.Foreground = Current.GetBrush("foreground"); 71 | Current.Foreground2 = Current.GetBrush("foreground2"); 72 | Current.Heading = Current.GetBrush("heading"); 73 | Current.MenuBackground = Current.GetBrush("menu-background"); 74 | Current.MenuHighlight = Current.GetBrush("menu-highlight"); 75 | } 76 | 77 | static List Load(string content) 78 | { 79 | List list = new List(); 80 | Theme theme = null; 81 | 82 | foreach (string currentLine in (content ?? "").Split(new [] { '\r', '\n' })) 83 | { 84 | string line = currentLine.Trim(); 85 | 86 | if (line.StartsWith("[") && line.EndsWith("]")) 87 | list.Add(theme = new Theme() { Name = line.Substring(1, line.Length - 2).Trim() }); 88 | 89 | if (line.Contains("=") && theme != null) 90 | { 91 | string left = line.Substring(0, line.IndexOf("=")).Trim(); 92 | theme.Dictionary[left] = line.Substring(line.IndexOf("=") + 1).Trim(); 93 | } 94 | } 95 | 96 | return list; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Native/StockIcon.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Runtime.InteropServices; 4 | 5 | public class StockIcon 6 | { 7 | [DllImport("shell32.dll")] 8 | public static extern int SHGetStockIconInfo(SHSTOCKICONID siid, SHSTOCKICONFLAGS uFlags, ref SHSTOCKICONINFO info); 9 | 10 | [DllImport("user32.dll")] 11 | public static extern bool DestroyIcon(IntPtr handle); 12 | 13 | public static IntPtr GetIcon(SHSTOCKICONID identifier, SHSTOCKICONFLAGS flags) 14 | { 15 | SHSTOCKICONINFO info = new SHSTOCKICONINFO(); 16 | info.cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(SHSTOCKICONINFO))); 17 | Marshal.ThrowExceptionForHR(SHGetStockIconInfo(identifier, flags, ref info)); 18 | return info.hIcon; 19 | } 20 | 21 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 22 | public struct SHSTOCKICONINFO 23 | { 24 | public uint cbSize; 25 | public IntPtr hIcon; 26 | int iSysImageIndex; 27 | int iIcon; 28 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 29 | string szPath; 30 | } 31 | 32 | public enum SHSTOCKICONFLAGS : uint 33 | { 34 | SHGSI_ICONLOCATION = 0, 35 | SHGSI_ICON = 0x000000100, 36 | SHGSI_SYSICONINDEX = 0x000004000, 37 | SHGSI_LINKOVERLAY = 0x000008000, 38 | SHGSI_SELECTED = 0x000010000, 39 | SHGSI_LARGEICON = 0x000000000, 40 | SHGSI_SMALLICON = 0x000000001, 41 | SHGSI_SHELLICONSIZE = 0x000000004 42 | } 43 | 44 | public enum SHSTOCKICONID : uint 45 | { 46 | DocumentNotAssociated = 0, 47 | DocumentAssociated = 1, 48 | Application = 2, 49 | Folder = 3, 50 | FolderOpen = 4, 51 | Drive525 = 5, 52 | Drive35 = 6, 53 | DriveRemove = 7, 54 | DriveFixed = 8, 55 | DriveNetwork = 9, 56 | DriveNetworkDisabled = 10, 57 | DriveCD = 11, 58 | DriveRAM = 12, 59 | World = 13, 60 | Server = 15, 61 | Printer = 16, 62 | MyNetwork = 17, 63 | Find = 22, 64 | Help = 23, 65 | Share = 28, 66 | Link = 29, 67 | SlowFile = 30, 68 | Recycler = 31, 69 | RecyclerFull = 32, 70 | MediaCDAudio = 40, 71 | Lock = 47, 72 | AutoList = 49, 73 | PrinterNet = 50, 74 | ServerShare = 51, 75 | PrinterFax = 52, 76 | PrinterFaxNet = 53, 77 | PrinterFile = 54, 78 | Stack = 55, 79 | MediaSVCD = 56, 80 | StuffedFolder = 57, 81 | DriveUnknown = 58, 82 | DriveDVD = 59, 83 | MediaDVD = 60, 84 | MediaDVDRAM = 61, 85 | MediaDVDRW = 62, 86 | MediaDVDR = 63, 87 | MediaDVDROM = 64, 88 | MediaCDAudioPlus = 65, 89 | MediaCDRW = 66, 90 | MediaCDR = 67, 91 | MediaCDBurn = 68, 92 | MediaBlankCD = 69, 93 | MediaCDROM = 70, 94 | AudioFiles = 71, 95 | ImageFiles = 72, 96 | VideoFiles = 73, 97 | MixedFiles = 74, 98 | FolderBack = 75, 99 | FolderFront = 76, 100 | Shield = 77, 101 | Warning = 78, 102 | Info = 79, 103 | Error = 80, 104 | Key = 81, 105 | Software = 82, 106 | Rename = 83, 107 | Delete = 84, 108 | MediaAudioDVD = 85, 109 | MediaMovieDVD = 86, 110 | MediaEnhancedCD = 87, 111 | MediaEnhancedDVD = 88, 112 | MediaHDDVD = 89, 113 | MediaBluRay = 90, 114 | MediaVCD = 91, 115 | MediaDVDPlusR = 92, 116 | MediaDVDPlusRW = 93, 117 | DesktopPC = 94, 118 | MobilePC = 95, 119 | Users = 96, 120 | MediaSmartMedia = 97, 121 | MediaCompactFlash = 98, 122 | DeviceCellPhone = 99, 123 | DeviceCamera = 100, 124 | DeviceVideoCamera = 101, 125 | DeviceAudioPlayer = 102, 126 | NetworkConnect = 103, 127 | Internet = 104, 128 | ZipFile = 105, 129 | Settings = 106 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Tools/Interop/Handle/HandleCollector.cs: -------------------------------------------------------------------------------- 1 | // reference from https://referencesource.microsoft.com/#WindowsBase/Shared/MS/Win32/HandleCollector.cs,d0f99220d8e1b708 2 | 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace HandyControl.Tools.Interop 7 | { 8 | internal static class HandleCollector 9 | { 10 | private static HandleType[] HandleTypes; 11 | private static int HandleTypeCount; 12 | 13 | private static readonly object HandleMutex = new object(); 14 | 15 | internal static IntPtr Add(IntPtr handle, int type) 16 | { 17 | HandleTypes[type - 1].Add(); 18 | return handle; 19 | } 20 | 21 | [System.Security.SecuritySafeCritical] 22 | internal static SafeHandle Add(SafeHandle handle, int type) 23 | { 24 | HandleTypes[type - 1].Add(); 25 | return handle; 26 | } 27 | 28 | internal static void Add(int type) 29 | { 30 | HandleTypes[type - 1].Add(); 31 | } 32 | 33 | internal static int RegisterType(string typeName, int expense, int initialThreshold) 34 | { 35 | lock (HandleMutex) 36 | { 37 | if (HandleTypeCount == 0 || HandleTypeCount == HandleTypes.Length) 38 | { 39 | HandleType[] newTypes = new HandleType[HandleTypeCount + 10]; 40 | if (HandleTypes != null) 41 | { 42 | Array.Copy(HandleTypes, 0, newTypes, 0, HandleTypeCount); 43 | } 44 | HandleTypes = newTypes; 45 | } 46 | 47 | HandleTypes[HandleTypeCount++] = new HandleType(expense, initialThreshold); 48 | return HandleTypeCount; 49 | } 50 | } 51 | 52 | internal static IntPtr Remove(IntPtr handle, int type) 53 | { 54 | HandleTypes[type - 1].Remove(); 55 | return handle; 56 | } 57 | 58 | [System.Security.SecuritySafeCritical] 59 | internal static SafeHandle Remove(SafeHandle handle, int type) 60 | { 61 | HandleTypes[type - 1].Remove(); 62 | return handle; 63 | } 64 | 65 | internal static void Remove(int type) 66 | { 67 | HandleTypes[type - 1].Remove(); 68 | } 69 | 70 | private class HandleType 71 | { 72 | private readonly int _initialThreshHold; 73 | private int _threshHold; 74 | private int _handleCount; 75 | private readonly int _deltaPercent; 76 | 77 | internal HandleType(int expense, int initialThreshHold) 78 | { 79 | _initialThreshHold = initialThreshHold; 80 | _threshHold = initialThreshHold; 81 | _deltaPercent = 100 - expense; 82 | } 83 | 84 | internal void Add() 85 | { 86 | lock (this) 87 | { 88 | _handleCount++; 89 | var performCollect = NeedCollection(); 90 | 91 | if (!performCollect) 92 | { 93 | return; 94 | } 95 | } 96 | 97 | GC.Collect(); 98 | 99 | var sleep = (100 - _deltaPercent) / 4; 100 | System.Threading.Thread.Sleep(sleep); 101 | } 102 | 103 | private bool NeedCollection() 104 | { 105 | 106 | if (_handleCount > _threshHold) 107 | { 108 | _threshHold = _handleCount + _handleCount * _deltaPercent / 100; 109 | return true; 110 | } 111 | 112 | var oldThreshHold = 100 * _threshHold / (100 + _deltaPercent); 113 | if (oldThreshHold >= _initialThreshHold && _handleCount < (int) (oldThreshHold * .9F)) 114 | { 115 | _threshHold = oldThreshHold; 116 | } 117 | 118 | return false; 119 | } 120 | 121 | internal void Remove() 122 | { 123 | lock (this) 124 | { 125 | _handleCount--; 126 | 127 | _handleCount = Math.Max(0, _handleCount); 128 | } 129 | } 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/WPF/StringSettingControl.xaml.cs: -------------------------------------------------------------------------------- 1 | 2 | using mpvnet; 3 | using System; 4 | using System.Globalization; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Media; 8 | 9 | using WinForms = System.Windows.Forms; 10 | 11 | namespace DynamicGUI 12 | { 13 | public partial class StringSettingControl : UserControl, ISettingControl 14 | { 15 | StringSetting StringSetting; 16 | 17 | public StringSettingControl(StringSetting stringSetting) 18 | { 19 | StringSetting = stringSetting; 20 | InitializeComponent(); 21 | DataContext = this; 22 | TitleTextBox.Text = stringSetting.Name; 23 | HelpTextBox.Text = stringSetting.Help; 24 | ValueTextBox.Text = StringSetting.Value; 25 | 26 | if (StringSetting.Width > 0) 27 | ValueTextBox.Width = StringSetting.Width; 28 | 29 | if (StringSetting.Type != "folder" && StringSetting.Type != "color") 30 | Button.Visibility = Visibility.Hidden; 31 | 32 | Link.SetURL(StringSetting.URL); 33 | 34 | if (string.IsNullOrEmpty(stringSetting.URL)) 35 | LinkTextBlock.Visibility = Visibility.Collapsed; 36 | } 37 | 38 | public Theme Theme => Theme.Current; 39 | 40 | string _SearchableText; 41 | 42 | public string SearchableText { 43 | get { 44 | if (_SearchableText is null) 45 | _SearchableText = (TitleTextBox.Text + HelpTextBox.Text +ValueTextBox.Text).ToLower(); 46 | 47 | return _SearchableText; 48 | } 49 | } 50 | 51 | public bool Contains(string searchString) => SearchableText.Contains(searchString.ToLower()); 52 | public SettingBase SettingBase => StringSetting; 53 | 54 | public string Text 55 | { 56 | get => StringSetting.Value; 57 | set => StringSetting.Value = value; 58 | } 59 | 60 | void Button_Click(object sender, RoutedEventArgs e) 61 | { 62 | switch (StringSetting.Type) 63 | { 64 | case "folder": 65 | FolderBrowser fb = new FolderBrowser(); 66 | fb.InitialDirectory = ValueTextBox.Text; 67 | 68 | if (fb.Show()) 69 | ValueTextBox.Text = fb.SelectedPath; 70 | break; 71 | case "color": 72 | using (var dialog = new WinForms.ColorDialog()) 73 | { 74 | dialog.FullOpen = true; 75 | 76 | try 77 | { 78 | if (!string.IsNullOrEmpty(ValueTextBox.Text)) 79 | { 80 | Color col = GetColor(ValueTextBox.Text); 81 | dialog.Color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B); 82 | } 83 | } catch {} 84 | 85 | if (dialog.ShowDialog() == WinForms.DialogResult.OK) 86 | ValueTextBox.Text = "#" + dialog.Color.ToArgb().ToString("X8"); 87 | } 88 | break; 89 | } 90 | } 91 | 92 | void ValueTextBox_TextChanged(object sender, TextChangedEventArgs e) => Update(); 93 | 94 | Color GetColor(string value) 95 | { 96 | if (value.Contains("/")) 97 | { 98 | string[] a = value.Split('/'); 99 | 100 | if (a.Length == 3) 101 | return Color.FromRgb(ToByte(a[0]), ToByte(a[1]), ToByte(a[2])); 102 | else if (a.Length == 4) 103 | return Color.FromArgb(ToByte(a[3]), ToByte(a[0]), ToByte(a[1]), ToByte(a[2])); 104 | } 105 | 106 | return (Color)ColorConverter.ConvertFromString(value); 107 | 108 | Byte ToByte(string val) => Convert.ToByte(Convert.ToSingle(val, CultureInfo.InvariantCulture) * 255); 109 | } 110 | 111 | public void Update() 112 | { 113 | if (StringSetting.Type == "color") 114 | { 115 | Color c = Colors.Transparent; 116 | 117 | if (ValueTextBox.Text != "") 118 | try { c = GetColor(ValueTextBox.Text); } catch {} 119 | 120 | ValueTextBox.Background = new SolidColorBrush(c); 121 | } 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/WPF/HandyControl/Controls/Attach/MenuTopLineAttach.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Controls.Primitives; 6 | 7 | using HandyControl.Tools; 8 | using HandyControl.Tools.Interop; 9 | 10 | namespace HandyControl.Controls 11 | { 12 | public class MenuTopLineAttach 13 | { 14 | public static readonly DependencyProperty PopupProperty = DependencyProperty.RegisterAttached( 15 | "Popup", typeof(Popup), typeof(MenuTopLineAttach), new PropertyMetadata(default(Popup), OnPopupChanged)); 16 | 17 | private static void OnPopupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 18 | { 19 | var topLine = (FrameworkElement)d; 20 | 21 | if (e.NewValue is Popup) 22 | { 23 | Popup popup = e.NewValue as Popup; 24 | MenuItem menuItem = popup.TemplatedParent as MenuItem; 25 | SetTopLine(menuItem, topLine); 26 | menuItem.Loaded += MenuItem_Loaded; 27 | } 28 | } 29 | 30 | private static void MenuItem_Loaded(object sender, RoutedEventArgs e) 31 | { 32 | var menuItem = (FrameworkElement)sender; 33 | menuItem.Unloaded += MenuItem_Unloaded; 34 | var topLine = GetTopLine(menuItem); 35 | var popup = GetPopup(topLine); 36 | if (popup != null) 37 | { 38 | popup.Opened += Popup_Opened; 39 | } 40 | } 41 | 42 | private static void MenuItem_Unloaded(object sender, RoutedEventArgs e) 43 | { 44 | var menuItem = (FrameworkElement)sender; 45 | menuItem.Unloaded -= MenuItem_Unloaded; 46 | var topLine = GetTopLine(menuItem); 47 | var popup = GetPopup(topLine); 48 | if (popup != null) 49 | { 50 | popup.Opened -= Popup_Opened; 51 | } 52 | } 53 | 54 | private static void Popup_Opened(object sender, EventArgs e) 55 | { 56 | var popup = (Popup)sender; 57 | if (popup.TemplatedParent is MenuItem menuItem) 58 | { 59 | var topLine = GetTopLine(menuItem); 60 | if (topLine == null) return; 61 | 62 | topLine.HorizontalAlignment = HorizontalAlignment.Left; 63 | topLine.Width = menuItem.ActualWidth; 64 | topLine.Margin = new Thickness(); 65 | 66 | var positionLeftTop = menuItem.PointToScreen(new Point()); 67 | var positionRightBottom = menuItem.PointToScreen(new Point(menuItem.ActualWidth, menuItem.ActualHeight)); 68 | ScreenHelper.FindMonitorRectsFromPoint(InteropMethods.GetCursorPos(), out _, out var workAreaRect); 69 | var panel = VisualHelper.GetParent(topLine); 70 | 71 | if (positionLeftTop.X < 0) 72 | { 73 | 74 | topLine.Margin = new Thickness(positionLeftTop.X - panel.Margin.Left, 0, 0, 0); 75 | } 76 | else if (positionLeftTop.X + panel.ActualWidth > workAreaRect.Right) 77 | { 78 | var overflowWidth = positionRightBottom.X - workAreaRect.Right; 79 | if (overflowWidth > 0) 80 | { 81 | topLine.Width -= overflowWidth + panel.Margin.Right; 82 | } 83 | topLine.HorizontalAlignment = HorizontalAlignment.Left; 84 | topLine.Margin = new Thickness(positionLeftTop.X + panel.ActualWidth - workAreaRect.Right + panel.Margin.Right, 0, 0, 0); 85 | } 86 | 87 | if (positionRightBottom.Y > workAreaRect.Bottom) 88 | { 89 | topLine.Width = 0; 90 | topLine.HorizontalAlignment = HorizontalAlignment.Stretch; 91 | topLine.Margin = new Thickness(); 92 | } 93 | } 94 | } 95 | 96 | public static void SetPopup(DependencyObject element, Popup value) 97 | => element.SetValue(PopupProperty, value); 98 | 99 | public static Popup GetPopup(DependencyObject element) 100 | => (Popup)element.GetValue(PopupProperty); 101 | 102 | internal static readonly DependencyProperty TopLineProperty = DependencyProperty.RegisterAttached( 103 | "TopLine", typeof(FrameworkElement), typeof(MenuTopLineAttach), new PropertyMetadata(default(FrameworkElement))); 104 | 105 | internal static void SetTopLine(DependencyObject element, FrameworkElement value) 106 | => element.SetValue(TopLineProperty, value); 107 | 108 | internal static FrameworkElement GetTopLine(DependencyObject element) 109 | => (FrameworkElement)element.GetValue(TopLineProperty); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Package/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 15 | 16 | 17 | mpv.net 18 | Frank Skare 19 | Images\StoreLogo.png 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | .264 56 | .265 57 | .asf 58 | .avc 59 | .avi 60 | .avs 61 | .dav 62 | .flv 63 | .h264 64 | .h265 65 | .hevc 66 | .m2t 67 | .m2ts 68 | .m2v 69 | .m4v 70 | .mkv 71 | .mov 72 | .mp4 73 | .mpeg 74 | .mpg 75 | .mpv 76 | .mts 77 | .ts 78 | .vob 79 | .vpy 80 | .webm 81 | .wmv 82 | .y4m 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | .aac 91 | .ac3 92 | .dts 93 | .dtshd 94 | .dtshr 95 | .dtsma 96 | .eac3 97 | .flac 98 | .m4a 99 | .mka 100 | .mp2 101 | .mp3 102 | .mpa 103 | .mpc 104 | .ogg 105 | .opus 106 | .thd 107 | .w64 108 | .wav 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /src/WPF/CommandPaletteControl.xaml.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.ComponentModel; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Input; 10 | using System.Windows.Media; 11 | 12 | namespace mpvnet 13 | { 14 | public partial class CommandPaletteControl : UserControl 15 | { 16 | public ICollectionView CollectionView { get; set; } 17 | public ICommand EscapeCommand { get; } 18 | public ICommand ExecuteCommand { get; } 19 | public CollectionViewSource CollectionViewSource { get; } 20 | public ObservableCollection Items { get; } = new ObservableCollection(); 21 | 22 | public CommandPaletteControl() 23 | { 24 | InitializeComponent(); 25 | DataContext = this; 26 | CollectionViewSource = new CollectionViewSource() { Source = Items }; 27 | CollectionView = CollectionViewSource.View; 28 | CollectionView.Filter = new Predicate(item => Filter((CommandPaletteItem)item)); 29 | MainListView.ItemsSource = CollectionView; 30 | 31 | EscapeCommand = new RelayCommand(OnEscapeCommand); 32 | ExecuteCommand = new RelayCommand(OnExecuteCommand); 33 | 34 | SearchControl.SearchTextBox.PreviewKeyDown += SearchTextBox_PreviewKeyDown; 35 | SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged; 36 | SearchControl.HideClearButton = true; 37 | 38 | if (Environment.OSVersion.Version < new Version(10, 0)) 39 | MainBorder.CornerRadius = new CornerRadius(0); 40 | } 41 | 42 | void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) 43 | { 44 | CollectionView.Refresh(); 45 | SelectFirst(); 46 | } 47 | 48 | void SearchTextBox_PreviewKeyDown(object sender, KeyEventArgs e) 49 | { 50 | switch (e.Key) 51 | { 52 | case Key.Up: 53 | { 54 | int index = MainListView.SelectedIndex; 55 | index -= 1; 56 | 57 | if (index < 0) 58 | index = 0; 59 | 60 | MainListView.SelectedIndex = index; 61 | MainListView.ScrollIntoView(MainListView.SelectedItem); 62 | } 63 | break; 64 | case Key.Down: 65 | { 66 | int index = MainListView.SelectedIndex; 67 | 68 | if (++index > MainListView.Items.Count - 1) 69 | index = MainListView.Items.Count - 1; 70 | 71 | MainListView.SelectedIndex = index; 72 | MainListView.ScrollIntoView(MainListView.SelectedItem); 73 | } 74 | break; 75 | } 76 | } 77 | 78 | void MainListView_SizeChanged(object sender, SizeChangedEventArgs e) => AdjustHeight(); 79 | 80 | void MainListView_MouseUp(object sender, MouseButtonEventArgs e) => Execute(); 81 | 82 | void OnEscapeCommand(object param) => MainForm.Instance.HideCommandPalette(); 83 | 84 | void OnExecuteCommand(object param) => Execute(); 85 | 86 | void OnLoaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox); 87 | 88 | public Theme Theme => Theme.Current; 89 | 90 | bool Filter(CommandPaletteItem item) 91 | { 92 | string filter = SearchControl.SearchTextBox.Text.ToLower(); 93 | 94 | if (filter == "" || item.Text.ToLower().Contains(filter) || 95 | item.SecondaryText.ToLower().Contains(filter)) 96 | 97 | return true; 98 | 99 | return false; 100 | } 101 | 102 | public void SelectFirst() 103 | { 104 | if (MainListView.Items.Count > 0) 105 | { 106 | MainListView.SelectedIndex = 0; 107 | MainListView.ScrollIntoView(MainListView.SelectedItem); 108 | } 109 | } 110 | 111 | void Execute() 112 | { 113 | if (MainListView.SelectedItem != null) 114 | { 115 | CommandPaletteItem item = MainListView.SelectedItem as CommandPaletteItem; 116 | MainForm.Instance.HideCommandPalette(); 117 | item.Action.Invoke(); 118 | MainForm.Instance.Voodoo(); 119 | } 120 | } 121 | 122 | public void SetItems(IEnumerable items) 123 | { 124 | Items.Clear(); 125 | 126 | foreach (var i in items) 127 | Items.Add(i); 128 | } 129 | 130 | public void AdjustHeight() 131 | { 132 | double actualHeight = SearchControl.ActualHeight + MainListView.ActualHeight + 5 + 16; 133 | int dpi = Native.GetDPI(MainForm.Instance.Handle); 134 | MainForm.Instance.CommandPaletteHost.Height = (int)(actualHeight / 96.0 * dpi); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Extensions/RatingExtension/RatingExtension.cs: -------------------------------------------------------------------------------- 1 | 2 | // This extension writes a rating to the filename of rated videos when mpv.net shuts down. 3 | 4 | // The input.conf setup: 5 | 6 | // KP0 script-message rate-file 0 #menu: Extensions > Rating > 0stars 7 | // KP1 script-message rate-file 1 #menu: Extensions > Rating > 1stars 8 | // KP2 script-message rate-file 2 #menu: Extensions > Rating > 2stars 9 | // KP3 script-message rate-file 3 #menu: Extensions > Rating > 3stars 10 | // KP4 script-message rate-file 4 #menu: Extensions > Rating > 4stars 11 | // KP5 script-message rate-file 5 #menu: Extensions > Rating > 5stars 12 | // _ ignore #menu: Extensions > Rating > - 13 | // _ script-message rate-file about #menu: Extensions > Rating > About 14 | 15 | using System; 16 | using System.Collections.Generic; 17 | using System.ComponentModel.Composition; 18 | using System.IO; 19 | using System.Threading; 20 | using System.Windows.Forms; 21 | 22 | using Microsoft.VisualBasic.FileIO; 23 | 24 | using mpvnet; 25 | using static mpvnet.Global; 26 | 27 | namespace RatingExtension // the assembly name must end with 'Extension'! 28 | { 29 | [Export(typeof(IExtension))] 30 | public class RatingExtension : IExtension 31 | { 32 | //Script script = new Script(); 33 | 34 | // dictionory to store the filename and the rating 35 | Dictionary Dic = new Dictionary(); 36 | 37 | string FileToDelete; 38 | DateTime DeleteTime; 39 | 40 | public RatingExtension() // plugin initialization 41 | { 42 | Core.ClientMessage += ClientMessage; //handles keys defined in input.conf 43 | Core.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN 44 | } 45 | 46 | // handles MPV_EVENT_SHUTDOWN 47 | void Shutdown() 48 | { 49 | foreach (var i in Dic) 50 | { 51 | string filepath = i.Key; 52 | int rating = i.Value; 53 | 54 | if (string.IsNullOrEmpty(filepath) || !File.Exists(filepath)) 55 | return; 56 | 57 | string basename = Path.GetFileNameWithoutExtension(filepath); 58 | 59 | for (int x = 0; x < 6; x++) 60 | if (basename.Contains(" (" + x + "stars)")) 61 | basename = basename.Replace(" (" + x + "stars)", ""); 62 | 63 | basename += $" ({rating}stars)"; 64 | 65 | string newPath = Path.Combine(Path.GetDirectoryName(filepath), 66 | basename + Path.GetExtension(filepath)); 67 | 68 | if (filepath.ToLower() != newPath.ToLower()) 69 | File.Move(filepath, newPath); 70 | 71 | File.SetLastWriteTime(newPath, DateTime.Now); 72 | } 73 | } 74 | 75 | //handles keys defined in input.conf 76 | void ClientMessage(string[] args) 77 | { 78 | if (args[0] != "rate-file") 79 | return; 80 | 81 | if (int.TryParse(args[1], out int rating)) 82 | { 83 | string path = Core.GetPropertyString("path"); 84 | 85 | if (!File.Exists(path)) 86 | return; 87 | 88 | if (rating == 0 || rating == 1) 89 | Delete(rating); 90 | else 91 | { 92 | Dic[path] = rating; 93 | Core.CommandV("show-text", $"Rating: {rating}"); 94 | } 95 | } 96 | else if (args[1] == "about") 97 | MessageBox.Show($"This extension writes a rating to the filename of rated videos " + 98 | "when mpv.net shuts down." + BR2 + 99 | "The input.conf defaults contain key bindings for this extension to set ratings.", 100 | "Rating Extension"); 101 | } 102 | 103 | void Delete(int rating) 104 | { 105 | if (rating == 0) 106 | { 107 | FileToDelete = Core.GetPropertyString("path"); 108 | DeleteTime = DateTime.Now; 109 | Core.CommandV("show-text", "Press 1 to delete file", "5000"); 110 | } 111 | else 112 | { 113 | TimeSpan ts = DateTime.Now - DeleteTime; 114 | string path = Core.GetPropertyString("path"); 115 | 116 | if (FileToDelete == path && ts.TotalSeconds < 5 && File.Exists(FileToDelete)) 117 | { 118 | Core.Command("playlist-remove current"); 119 | int pos = Core.GetPropertyInt("playlist-pos"); 120 | 121 | if (pos == -1) 122 | { 123 | int count = Core.GetPropertyInt("playlist-count"); 124 | 125 | if (count > 0) 126 | Core.SetPropertyInt("playlist-pos", count - 1); 127 | } 128 | 129 | Thread.Sleep(2000); 130 | FileSystem.DeleteFile(FileToDelete, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin); 131 | } 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![](docs/img/mpvnet.png) 3 | 4 | ![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/stax76/mpv.net) ![GitHub closed issues](https://img.shields.io/github/issues-closed/stax76/mpv.net) ![GitHub All Releases](https://img.shields.io/github/downloads/stax76/mpv.net/total) ![GitHub tag (latest by date)](https://img.shields.io/github/tag-date/stax76/mpv.net) ![GitHub stars](https://img.shields.io/github/stars/stax76/mpv.net) 5 | 6 | 🎞 mpv.net 7 | ========== 8 | 9 | mpv.net is a modern media player for Windows based on the popular [mpv](https://mpv.io) player. 10 | 11 | 12 | #### Graphical User Interface 13 | 14 | Modern GUI with customizable color themes. 15 | 16 | 17 | #### Command Line Interface 18 | 19 | mpv.net supports mpv's property based command line switches. 20 | 21 | 22 | #### High quality video output 23 | 24 | Video output that is capable of many features loved by videophiles, 25 | such as video scaling with popular high quality algorithms, 26 | color management, frame timing, interpolation, HDR, and more. 27 | 28 | 29 | #### On Screen Controller 30 | 31 | Play controls with a modern flat design. 32 | 33 | 34 | #### GPU video decoding 35 | 36 | Leverages the FFmpeg hwaccel APIs to support DXVA2 video decoding acceleration. 37 | 38 | 39 | #### Active development 40 | 41 | mpv.net is under active development. 42 | 43 | 44 | #### Based on libmpv 45 | 46 | mpv.net is based on libmpv which offers a straightforward C API that 47 | was designed from the ground up to make mpv usable as a library and 48 | facilitate easy integration into other applications. 49 | mpv is like VLC not based on DirectShow or Media Foundation. 50 | 51 | 52 | Table of contents 53 | ----------------- 54 | 55 | - [Features](#features-that-mpv-and-mpvnet-have-in-common) 56 | - [Support](#support) 57 | - [Download](#download) 58 | - [Manual](#manual) 59 | - [Screenshots](#screenshots) 60 | 61 | 62 | Features that mpv and mpv.net have in common 63 | -------------------------------------------- 64 | 65 | - Lua and JavaScript Scripting 66 | - Simple config files that are easy to read and edit 67 | - JSON IPC to control the player with a external programs 68 | - On Screen Controler (OSC, play control buttons) with modern flat design 69 | - Command Line Interface 70 | - Started from a terminal status, error and debug output is printed on the terminal 71 | - DXVA2 video decoding acceleration 72 | - Video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more 73 | - Browser extensions to start mpv(.net) from the browser 74 | - Fast seek performance 75 | - Fast startup performance 76 | - Usable as video player, audio player and image viewer with a wide range of supported formats 77 | - Built-in decoders, no external codecs have to be installed 78 | - Build-in media streaming (requires youtube-dl being installed) 79 | - External audio and subtitle files can be loaded manually or automatically 80 | - Screenshot feature 81 | - Watch later feature to save the video position 82 | 83 | 84 | Features exclusiv to mpv.net 85 | ---------------------------- 86 | 87 | - High degree of mpv compatibility, almost all mpv features are available 88 | - Modern graphical user interface with customizable color themes 89 | - Customizable context menu defined in the same file as the key bindings 90 | - Searchable config editor 91 | - Searchable input (shorcut keys) editor 92 | - C# and PowerShell Scripting 93 | - Global keyboard shortcuts 94 | - Command palette to quickly and easily find commands and keys 95 | - Extension API for .NET languages (C#, VB.NET and F#) 96 | - Setup as x64 installer, portable, Chocolatey and WinGet 97 | - Setup dialog for system integration (file associations etc.) 98 | - File history feature to log time and filename 99 | - Files can be enqueued from File Explorer 100 | - Update check and update routine 101 | 102 | 103 | ## [Support](docs/Manual.md#support) 104 | 105 | [Support section of the manual.](docs/Manual.md#support) 106 | 107 | 108 | ## [Download](docs/Manual.md#download) 109 | 110 | [Download section of the manual.](docs/Manual.md#download) 111 | 112 | 113 | ## [Manual](docs/Manual.md) 114 | 115 | [The mpv.net documentation.](docs/Manual.md) 116 | 117 | 118 | Screenshots 119 | ----------- 120 | 121 | #### Main Window 122 | 123 | ![Main Window](docs/img/Main.webp) 124 | 125 | 126 | #### Context Menu 127 | 128 | Context menu using dark mode. 129 | 130 | ![Context Menu](docs/img/Menu.jpg) 131 | 132 | 133 | #### Config Editor 134 | 135 | Searchable config editor as alternative to edit the conf file manually. 136 | 137 | ![](docs/img/ConfEditor.png) 138 | 139 | 140 | #### Terminal 141 | 142 | OSD console and status printed on the terminal. 143 | 144 | ![](docs/img/Terminal.png) 145 | 146 | 147 | #### Input Editor 148 | 149 | Searchable key and mouse binding editor. 150 | 151 | ![Input Editor](docs/img/InputEditor.webp) 152 | 153 | 154 | #### Command Palette 155 | 156 | Command Palette to easily find commands and shortcut keys. 157 | 158 | ![Command Palette](docs/img/CommandPalette.webp) 159 | 160 | 161 | #### Playlist 162 | 163 | The command palette based playlist showing my favorite artist of the stax record label. 164 | 165 | ![Playlist](docs/img/Playlist.png) 166 | 167 | 168 | Related apps 169 | ------------ 170 | 171 | Find a list of related apps: 172 | 173 | https://stax76.github.io/frankskare 174 | -------------------------------------------------------------------------------- /src/Misc/FolderBrowser.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Runtime.InteropServices; 7 | using System.Windows.Forms; 8 | 9 | namespace mpvnet 10 | { 11 | public class FolderBrowser 12 | { 13 | public string SelectedPath { get; set; } 14 | 15 | string _initialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 16 | 17 | public string InitialDirectory { 18 | get => _initialDirectory; 19 | set { 20 | if (Directory.Exists(value)) 21 | _initialDirectory = value; 22 | } 23 | } 24 | 25 | public bool Show() => Show(GetOwnerHandle()); 26 | 27 | public bool Show(IntPtr hWndOwner) 28 | { 29 | ShowDialogResult result = VistaDialog.Show(hWndOwner, InitialDirectory); 30 | 31 | if (result.Result) 32 | SelectedPath = result.FileName; 33 | 34 | return result.Result; 35 | } 36 | 37 | struct ShowDialogResult 38 | { 39 | public bool Result { get; set; } 40 | public string FileName { get; set; } 41 | } 42 | 43 | public static IntPtr GetOwnerHandle() 44 | { 45 | IntPtr foregroundWindow = GetForegroundWindow(); 46 | GetWindowThreadProcessId(foregroundWindow, out var procID); 47 | 48 | using (var proc = Process.GetCurrentProcess()) 49 | if (proc.Id == procID) 50 | return foregroundWindow; 51 | 52 | return IntPtr.Zero; 53 | } 54 | 55 | [DllImport("user32.dll")] 56 | public static extern IntPtr GetForegroundWindow(); 57 | 58 | [DllImport("user32.dll")] 59 | public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 60 | 61 | static class VistaDialog 62 | { 63 | const string foldersFilter = "Folders|\n"; 64 | const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 65 | static Assembly windowsFormsAssembly = typeof(FileDialog).Assembly; 66 | static Type iFileDialogType = windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog"); 67 | static MethodInfo createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", flags); 68 | static MethodInfo onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", flags); 69 | static MethodInfo getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", flags); 70 | static MethodInfo setOptionsMethodInfo = iFileDialogType.GetMethod("SetOptions", flags); 71 | static uint fosPickFoldersBitFlag = (uint)windowsFormsAssembly 72 | .GetType("System.Windows.Forms.FileDialogNative+FOS") 73 | .GetField("FOS_PICKFOLDERS") 74 | .GetValue(null); 75 | static ConstructorInfo vistaDialogEventsConstructorInfo = windowsFormsAssembly 76 | .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents") 77 | .GetConstructor(flags, null, new[] { typeof(FileDialog) }, null); 78 | static MethodInfo adviseMethodInfo = iFileDialogType.GetMethod("Advise"); 79 | static MethodInfo unAdviseMethodInfo = iFileDialogType.GetMethod("Unadvise"); 80 | static MethodInfo showMethodInfo = iFileDialogType.GetMethod("Show"); 81 | 82 | public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory) 83 | { 84 | var openFileDialog = new OpenFileDialog 85 | { 86 | AddExtension = false, 87 | CheckFileExists = false, 88 | DereferenceLinks = true, 89 | Filter = foldersFilter, 90 | InitialDirectory = initialDirectory, 91 | Multiselect = false, 92 | }; 93 | 94 | var iFileDialog = createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { }); 95 | onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog }); 96 | setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint)getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | fosPickFoldersBitFlag }); 97 | var adviseParametersWithOutputConnectionToken = new[] { vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U }; 98 | adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken); 99 | 100 | try 101 | { 102 | int retVal = (int)showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle }); 103 | 104 | return new ShowDialogResult 105 | { 106 | Result = retVal == 0, 107 | FileName = openFileDialog.FileName 108 | }; 109 | } 110 | finally 111 | { 112 | unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] }); 113 | } 114 | } 115 | } 116 | 117 | class WindowWrapper : IWin32Window 118 | { 119 | IntPtr _handle; 120 | public WindowWrapper(IntPtr handle) { _handle = handle; } 121 | public IntPtr Handle => _handle; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Misc/Conf.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Windows; 5 | using System.Windows.Documents; 6 | using System.Windows.Navigation; 7 | 8 | namespace mpvnet 9 | { 10 | public class Conf 11 | { 12 | public static List LoadConf(string content) 13 | { 14 | List settingsList = new List(); 15 | 16 | foreach (ConfSection section in ConfParser.Parse(content)) 17 | { 18 | SettingBase baseSetting = null; 19 | 20 | if (section.HasName("option")) 21 | { 22 | OptionSetting optionSetting = new OptionSetting(); 23 | baseSetting = optionSetting; 24 | optionSetting.Default = section.GetValue("default"); 25 | optionSetting.Value = optionSetting.Default; 26 | 27 | foreach (var i in section.GetValues("option")) 28 | { 29 | var opt = new OptionSettingOption(); 30 | 31 | if (i.Value.Contains(" ")) 32 | { 33 | opt.Name = i.Value.Substring(0, i.Value.IndexOf(" ")); 34 | opt.Help = i.Value.Substring(i.Value.IndexOf(" ")).Trim(); 35 | } 36 | else 37 | opt.Name = i.Value; 38 | 39 | if (opt.Name == optionSetting.Default) 40 | opt.Text = opt.Name + " (Default)"; 41 | 42 | opt.OptionSetting = optionSetting; 43 | optionSetting.Options.Add(opt); 44 | } 45 | } 46 | else 47 | { 48 | StringSetting stringSetting = new StringSetting(); 49 | baseSetting = stringSetting; 50 | stringSetting.Default = section.HasName("default") ? section.GetValue("default") : ""; 51 | } 52 | 53 | baseSetting.Name = section.GetValue("name"); 54 | baseSetting.File = section.GetValue("file"); 55 | baseSetting.Filter = section.GetValue("filter"); 56 | 57 | if (section.HasName("help")) baseSetting.Help = section.GetValue("help"); 58 | if (section.HasName("url")) baseSetting.URL = section.GetValue("url"); 59 | if (section.HasName("width")) baseSetting.Width = Convert.ToInt32(section.GetValue("width")); 60 | if (section.HasName("type")) baseSetting.Type = section.GetValue("type"); 61 | 62 | if (baseSetting.Help.ContainsEx("\\n")) 63 | baseSetting.Help = baseSetting.Help.Replace("\\n", "\n"); 64 | 65 | settingsList.Add(baseSetting); 66 | } 67 | 68 | return settingsList; 69 | } 70 | } 71 | 72 | public class ConfItem 73 | { 74 | public string Comment { get; set; } = ""; 75 | public string File { get; set; } = ""; 76 | public string LineComment { get; set; } = ""; 77 | public string Name { get; set; } = ""; 78 | public string Section { get; set; } = ""; 79 | public string Value { get; set; } = ""; 80 | 81 | public bool IsSectionItem { get; set; } 82 | public SettingBase SettingBase { get; set; } 83 | } 84 | 85 | public abstract class SettingBase 86 | { 87 | public string Default { get; set; } 88 | public string File { get; set; } 89 | public string Filter { get; set; } 90 | public string Help { get; set; } 91 | public string Name { get; set; } 92 | public string StartValue { get; set; } 93 | public string Type { get; set; } 94 | public string URL { get; set; } 95 | public string Value { get; set; } 96 | 97 | public int Width { get; set; } 98 | public ConfItem ConfItem { get; set; } 99 | } 100 | 101 | public class StringSetting : SettingBase 102 | { 103 | } 104 | 105 | public class OptionSetting : SettingBase 106 | { 107 | public List Options = new List(); 108 | } 109 | 110 | public class OptionSettingOption 111 | { 112 | public string Name { get; set; } 113 | public string Help { get; set; } 114 | 115 | public OptionSetting OptionSetting { get; set; } 116 | 117 | string _Text; 118 | 119 | public string Text 120 | { 121 | get => string.IsNullOrEmpty(_Text) ? Name : _Text; 122 | set => _Text = value; 123 | } 124 | 125 | public bool Checked 126 | { 127 | get => OptionSetting.Value == Name ; 128 | set { 129 | if (value) 130 | OptionSetting.Value = Name; 131 | } 132 | } 133 | 134 | public Visibility Visibility 135 | { 136 | get => string.IsNullOrEmpty(Help) ? Visibility.Collapsed : Visibility.Visible; 137 | } 138 | } 139 | 140 | interface ISettingControl 141 | { 142 | bool Contains(string searchString); 143 | SettingBase SettingBase { get; } 144 | } 145 | 146 | public class HyperlinkEx : Hyperlink 147 | { 148 | void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e) 149 | { 150 | ProcessHelp.ShellExecute(e.Uri.AbsoluteUri); 151 | } 152 | 153 | public void SetURL(string url) 154 | { 155 | if (string.IsNullOrEmpty(url)) 156 | return; 157 | 158 | NavigateUri = new Uri(url); 159 | RequestNavigate += HyperLinkEx_RequestNavigate; 160 | Inlines.Clear(); 161 | Inlines.Add(url); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/WPF/InputWindow.xaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 33 | 34 | 40 | 41 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 89 | 90 | 103 | 104 | 105 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | # ========================= 255 | # Operating System Files 256 | # ========================= 257 | 258 | # OSX 259 | # ========================= 260 | 261 | .DS_Store 262 | .AppleDouble 263 | .LSOverride 264 | 265 | # Thumbnails 266 | ._* 267 | 268 | # Files that might appear in the root of a volume 269 | .DocumentRevisions-V100 270 | .fseventsd 271 | .Spotlight-V100 272 | .TemporaryItems 273 | .Trashes 274 | .VolumeIcon.icns 275 | 276 | # Directories potentially created on remote AFP share 277 | .AppleDB 278 | .AppleDesktop 279 | Network Trash Folder 280 | Temporary Items 281 | .apdisk 282 | 283 | # Windows 284 | # ========================= 285 | 286 | # Windows image file caches 287 | Thumbs.db 288 | ehthumbs.db 289 | 290 | # Folder config file 291 | Desktop.ini 292 | 293 | # Recycle Bin used on file shares 294 | $RECYCLE.BIN/ 295 | 296 | # Windows Installer files 297 | *.cab 298 | *.msi 299 | *.msm 300 | *.msp 301 | 302 | # Windows shortcuts 303 | *.lnk 304 | -------------------------------------------------------------------------------- /src/WPF/InputWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Input; 10 | 11 | using static mpvnet.Global; 12 | 13 | namespace mpvnet 14 | { 15 | public partial class InputWindow : Window 16 | { 17 | ICollectionView CollectionView; 18 | string InitialInputConfContent; 19 | 20 | public InputWindow() 21 | { 22 | InitializeComponent(); 23 | DataContext = this; 24 | InitialInputConfContent = GetInputConfContent(); 25 | SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged; 26 | DataGrid.SelectionMode = DataGridSelectionMode.Single; 27 | CollectionViewSource collectionViewSource = new CollectionViewSource() { Source = CommandItem.Items }; 28 | CollectionView = collectionViewSource.View; 29 | CollectionView.Filter = new Predicate(item => Filter((CommandItem)item)); 30 | DataGrid.ItemsSource = CollectionView; 31 | } 32 | 33 | public Theme Theme => Theme.Current; 34 | 35 | void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) 36 | { 37 | CollectionView.Refresh(); 38 | 39 | if (SearchControl.SearchTextBox.Text == "?") 40 | { 41 | SearchControl.SearchTextBox.Text = ""; 42 | 43 | Msg.ShowInfo("Filtering" + BR2 + 44 | "Reduce the filter scope with:" + BR2 + 45 | "i input" + BR2 + 46 | "m menu" + BR2 + 47 | "c command" + BR2 + 48 | "If only one character is entered input search is performed."); 49 | } 50 | } 51 | 52 | bool Filter(CommandItem item) 53 | { 54 | if (item.Command == "") 55 | return false; 56 | 57 | string searchText = SearchControl.SearchTextBox.Text.ToLower(); 58 | 59 | if (searchText == "" || searchText == "?") 60 | return true; 61 | 62 | if (searchText.Length == 1) 63 | return item.Input.ToLower().Replace("ctrl+", "").Replace("shift+", "").Replace("alt+", "") == searchText.ToLower(); 64 | else if (searchText.StartsWith("i ") || searchText.StartsWith("i:") || searchText.Length == 1) 65 | { 66 | if (searchText.Length > 1) 67 | searchText = searchText.Substring(2).Trim(); 68 | 69 | if (searchText.Length < 3) 70 | return item.Input.ToLower().Replace("ctrl+", "").Replace("shift+", "").Replace("alt+", "").Contains(searchText); 71 | else 72 | return item.Input.ToLower().Contains(searchText); 73 | } 74 | else if (searchText.StartsWith("m ") || searchText.StartsWith("m:")) 75 | return item.Path.ToLower().Contains(searchText.Substring(2).Trim()); 76 | else if (searchText.StartsWith("c ") || searchText.StartsWith("c:")) 77 | return item.Command.ToLower().Contains(searchText.Substring(2).Trim()); 78 | else if (item.Command.ToLower().Contains(searchText) || 79 | item.Path.ToLower().Contains(searchText) || 80 | item.Input.ToLower().Contains(searchText)) 81 | { 82 | return true; 83 | } 84 | return false; 85 | } 86 | 87 | void ButtonClick(object sender, RoutedEventArgs e) 88 | { 89 | CommandItem item = ((Button)e.Source).DataContext as CommandItem; 90 | 91 | if (item is null) 92 | return; 93 | 94 | LearnWindow w = new LearnWindow(); 95 | w.Owner = this; 96 | w.InputItem = item; 97 | w.ShowDialog(); 98 | 99 | var items = new Dictionary(); 100 | 101 | foreach (CommandItem i in CommandItem.Items) 102 | items[i.Input] = i; 103 | } 104 | 105 | void Window_Loaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox); 106 | 107 | string GetInputConfContent() 108 | { 109 | string text = null; 110 | 111 | foreach (string line in Properties.Resources.input_conf.Split(new[] { "\r\n" }, StringSplitOptions.None)) 112 | { 113 | string test = line.Trim(); 114 | 115 | if (test == "" || test.StartsWith("#")) 116 | text += test + BR; 117 | } 118 | 119 | text = BR + text.Trim() + BR2; 120 | 121 | foreach (CommandItem item in CommandItem.Items) 122 | { 123 | string input = item.Input == "" ? "_" : item.Input; 124 | string line = input.PadRight(10); 125 | 126 | if (item.Command.Trim() == "") 127 | line += " ignore"; 128 | else 129 | line += " " + item.Command.Trim(); 130 | 131 | if (item.Path.Trim() != "") 132 | line = line.PadRight(40) + " #menu: " + item.Path; 133 | 134 | text += line + BR; 135 | } 136 | 137 | return text; 138 | } 139 | 140 | void Window_Closed(object sender, EventArgs e) 141 | { 142 | if (InitialInputConfContent == GetInputConfContent()) 143 | return; 144 | 145 | File.WriteAllText(Core.InputConfPath, GetInputConfContent()); 146 | Msg.ShowInfo("Changes will be available on next startup."); 147 | } 148 | 149 | void DataGrid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e) 150 | { 151 | DataGrid grid = (DataGrid)sender; 152 | 153 | if (e.Command == DataGrid.DeleteCommand) 154 | if (Msg.ShowQuestion($"Confirm to delete: {(grid.SelectedItem as CommandItem).Input} ({(grid.SelectedItem as CommandItem).Path})") != MessageBoxResult.OK) 155 | e.Handled = true; 156 | } 157 | 158 | protected override void OnKeyDown(KeyEventArgs e) 159 | { 160 | base.OnKeyDown(e); 161 | 162 | if (e.Key == Key.Escape) 163 | Close(); 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/Package/mpv.net.package.wapproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15.0 5 | 6 | 7 | 8 | Debug 9 | x86 10 | 11 | 12 | Release 13 | x86 14 | 15 | 16 | Debug 17 | x64 18 | 19 | 20 | Release 21 | x64 22 | 23 | 24 | Debug 25 | ARM 26 | 27 | 28 | Release 29 | ARM 30 | 31 | 32 | Debug 33 | ARM64 34 | 35 | 36 | Release 37 | ARM64 38 | 39 | 40 | Debug 41 | AnyCPU 42 | 43 | 44 | Release 45 | AnyCPU 46 | 47 | 48 | 49 | $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ 50 | 51 | 52 | 53 | 81daee3a-76ff-4494-9384-d28a651d70bb 54 | 10.0.22000.0 55 | 10.0.14393.0 56 | en-US 57 | false 58 | ..\mpv.net.csproj 59 | False 60 | False 61 | True 62 | neutral 63 | True 64 | 0 65 | 66 | 67 | Always 68 | 69 | 70 | Always 71 | 72 | 73 | Always 74 | 75 | 76 | Always 77 | 78 | 79 | Always 80 | 81 | 82 | Always 83 | 84 | 85 | Always 86 | 87 | 88 | Always 89 | 90 | 91 | Always 92 | 93 | 94 | Always 95 | 96 | 97 | 98 | Designer 99 | 100 | 101 | 102 | 103 | mpv.net\MediaInfo.dll 104 | PreserveNewest 105 | 106 | 107 | mpv.net\Microsoft.Management.Infrastructure.dll 108 | PreserveNewest 109 | 110 | 111 | mpv.net\mpv-1.dll 112 | PreserveNewest 113 | 114 | 115 | mpv.net\mpvnet.com 116 | PreserveNewest 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/Native/Native.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Drawing; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace mpvnet 7 | { 8 | public class Native 9 | { 10 | static Version Windows_10_1607 = new Version(10, 0, 14393); // Windows 10 1607 11 | 12 | [DllImport("kernel32.dll")] 13 | public static extern bool AttachConsole(int dwProcessId); 14 | 15 | [DllImport("kernel32.dll")] 16 | public static extern bool FreeConsole(); 17 | 18 | [DllImport("kernel32.dll")] 19 | public static extern IntPtr LoadLibrary(string path); 20 | 21 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 22 | public static extern IntPtr FindWindowEx( 23 | IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle); 24 | 25 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 26 | public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); 27 | 28 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 29 | public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam); 30 | 31 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 32 | public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); 33 | 34 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 35 | public static extern int RegisterWindowMessage(string id); 36 | 37 | [DllImport("user32.dll")] 38 | public static extern bool AllowSetForegroundWindow(int dwProcessId); 39 | 40 | [DllImport("user32.dll")] 41 | public static extern void ReleaseCapture(); 42 | 43 | [DllImport("user32.dll")] 44 | public static extern int GetDpiForWindow(IntPtr hwnd); 45 | 46 | [DllImport("user32.dll")] 47 | public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu); 48 | 49 | [DllImport("user32.dll")] 50 | public static extern bool AdjustWindowRectExForDpi( 51 | ref RECT lpRect, uint dwStyle, bool bMenu, uint dwExStyle, uint dpi); 52 | 53 | [DllImport("user32.dll")] 54 | public static extern bool SetWindowPos( 55 | IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); 56 | 57 | [DllImport("user32.dll", EntryPoint = "GetWindowLong")] 58 | static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex); 59 | 60 | [DllImport("user32.dll")] 61 | static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); 62 | 63 | public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex) 64 | { 65 | if (IntPtr.Size == 8) 66 | return GetWindowLongPtr(hWnd, nIndex); 67 | else 68 | return GetWindowLong32(hWnd, nIndex); 69 | } 70 | 71 | [DllImport("user32.dll", EntryPoint = "SetWindowLong")] 72 | public static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, uint dwNewLong); 73 | 74 | [DllImport("user32.dll")] 75 | public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, uint dwNewLong); 76 | 77 | public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong) 78 | { 79 | if (IntPtr.Size == 8) 80 | return SetWindowLongPtr(hWnd, nIndex, dwNewLong); 81 | else 82 | return SetWindowLong32(hWnd, nIndex, dwNewLong); 83 | } 84 | 85 | [DllImport("gdi32.dll")] 86 | public static extern int GetDeviceCaps(IntPtr hdc, int nIndex); 87 | 88 | [StructLayout(LayoutKind.Sequential)] 89 | public struct RECT 90 | { 91 | public int Left; 92 | public int Top; 93 | public int Right; 94 | public int Bottom; 95 | 96 | public RECT(Rectangle r) 97 | { 98 | Left = r.Left; 99 | Top = r.Top; 100 | Right = r.Right; 101 | Bottom = r.Bottom; 102 | } 103 | 104 | public RECT(int left, int top, int right, int bottom) 105 | { 106 | Left = left; 107 | Top = top; 108 | Right = right; 109 | Bottom = bottom; 110 | } 111 | 112 | public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom); 113 | public Size Size => new Size(Right - Left, Bottom - Top); 114 | public int Width => Right - Left; 115 | public int Height => Bottom - Top; 116 | } 117 | 118 | [StructLayout(LayoutKind.Sequential)] 119 | public struct COPYDATASTRUCT 120 | { 121 | public IntPtr dwData; 122 | public int cbData; 123 | [MarshalAs(UnmanagedType.LPTStr)] 124 | public string lpData; 125 | } 126 | 127 | public static int GetResizeBorder(int v) 128 | { 129 | switch (v) 130 | { 131 | case 1 /* WMSZ_LEFT */ : return 3; 132 | case 3 /* WMSZ_TOP */ : return 2; 133 | case 2 /* WMSZ_RIGHT */ : return 3; 134 | case 6 /* WMSZ_BOTTOM */ : return 2; 135 | case 4 /* WMSZ_TOPLEFT */ : return 1; 136 | case 5 /* WMSZ_TOPRIGHT */ : return 1; 137 | case 7 /* WMSZ_BOTTOMLEFT */ : return 3; 138 | case 8 /* WMSZ_BOTTOMRIGHT */ : return 3; 139 | default: return -1; 140 | } 141 | } 142 | 143 | public static void SubtractWindowBorders(IntPtr hwnd, ref RECT rc, int dpi) 144 | { 145 | RECT r = new RECT(0, 0, 0, 0); 146 | AddWindowBorders(hwnd, ref r, dpi); 147 | rc.Left -= r.Left; 148 | rc.Top -= r.Top; 149 | rc.Right -= r.Right; 150 | rc.Bottom -= r.Bottom; 151 | } 152 | 153 | public static void AddWindowBorders(IntPtr hwnd, ref RECT rc, int dpi) 154 | { 155 | uint windowStyle = (uint)GetWindowLong(hwnd, -16); // GWL_STYLE 156 | uint windowStyleEx = (uint)GetWindowLong(hwnd, -20); // GWL_EXSTYLE 157 | 158 | if (Environment.OSVersion.Version >= Windows_10_1607) 159 | AdjustWindowRectExForDpi(ref rc, windowStyle, false, windowStyleEx, (uint)dpi); 160 | else 161 | AdjustWindowRect(ref rc, windowStyle, false); 162 | } 163 | 164 | public static int GetDPI(IntPtr hwnd) 165 | { 166 | if (Environment.OSVersion.Version >= Windows_10_1607 && hwnd != IntPtr.Zero) 167 | return GetDpiForWindow(hwnd); 168 | else 169 | using (Graphics gx = Graphics.FromHwnd(hwnd)) 170 | return GetDeviceCaps(gx.GetHdc(), 88 /*LOGPIXELSX*/); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace mpvnet.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvnet.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to 65 | ///[setting] 66 | ///name = hwdec 67 | ///file = mpv 68 | ///default = no 69 | ///filter = Video 70 | ///url = https://mpv.io/manual/master/#options-hwdec 71 | ///help = Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit: 72 | /// 73 | ///option = no always use software decoding 74 | ///option = auto enable best hw decoder 75 | ///option = yes exact [rest of string was truncated]";. 76 | /// 77 | internal static string editor_conf { 78 | get { 79 | return ResourceManager.GetString("editor_conf", resourceCulture); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized string similar to 85 | ///# This file defines the key and mouse bindings and also the context menu of mpv.net. 86 | /// 87 | ///# A input and config editor can be found in the context menu under 'Settings'. 88 | /// 89 | ///# The mpv.conf defaults of mpv.net contain input-default-bindings=yes and 90 | ///# input-builtin-bindings=no which disables the input defaults of mpv. 91 | /// 92 | ///# The input test mode can be started via command line: --input-test 93 | /// 94 | ///# The input key list can be printed with --input-keylist or 95 | ///# shown from the context menu under: View > Show Keys 96 | /// 97 | ///# m [rest of string was truncated]";. 98 | /// 99 | internal static string input_conf { 100 | get { 101 | return ResourceManager.GetString("input_conf", resourceCulture); 102 | } 103 | } 104 | 105 | /// 106 | /// Looks up a localized resource of type System.Drawing.Bitmap. 107 | /// 108 | internal static System.Drawing.Bitmap mpvnet { 109 | get { 110 | object obj = ResourceManager.GetObject("mpvnet", resourceCulture); 111 | return ((System.Drawing.Bitmap)(obj)); 112 | } 113 | } 114 | 115 | /// 116 | /// Looks up a localized resource of type System.Drawing.Bitmap. 117 | /// 118 | internal static System.Drawing.Bitmap mpvnet_santa { 119 | get { 120 | object obj = ResourceManager.GetObject("mpvnet_santa", resourceCulture); 121 | return ((System.Drawing.Bitmap)(obj)); 122 | } 123 | } 124 | 125 | /// 126 | /// Looks up a localized string similar to 127 | ///[dark] 128 | /// 129 | ///heading = #3C8CC8 130 | ///foreground = #DDDDDD 131 | ///foreground2 = #AAAAAA 132 | ///background = #323232 133 | ///highlight = #404040 134 | /// 135 | ///menu-foreground = #DDDDDD 136 | ///menu-background = #323232 137 | ///menu-highlight = #505050 138 | /// 139 | /// 140 | ///[light] 141 | /// 142 | ///heading = #0068B2 143 | ///foreground = #000000 144 | ///foreground2 = #4C4C4C 145 | ///background = #F7F7F7 146 | ///highlight = #DFDFDF 147 | /// 148 | ///menu-foreground = #000000 149 | ///menu-background = #DFDFDF 150 | ///menu-highlight = #BFBFBF 151 | ///. 152 | /// 153 | internal static string theme { 154 | get { 155 | return ResourceManager.GetString("theme", resourceCulture); 156 | } 157 | } 158 | } 159 | } 160 | --------------------------------------------------------------------------------