Compare commits

...

43 Commits
0.2.2 ... 1.8

Author SHA1 Message Date
Frank Skare
07b6d4379e - 2019-03-25 09:50:14 +01:00
Frank Skare
8a6659b1bf - 2019-03-23 18:18:55 +01:00
Frank Skare
e7d41ff626 - 2019-03-23 15:42:57 +01:00
Frank Skare
f2c526348d - 2019-03-23 04:24:33 +01:00
Frank Skare
b4d2a7e86d - 2019-03-23 04:21:45 +01:00
Frank Skare
98f8e7090a - 2019-03-23 04:10:26 +01:00
Frank Skare
aeb5958be6 - 2019-03-23 04:07:47 +01:00
Frank Skare
1d16861b0b 1.5 2019-03-21 18:31:18 +01:00
Frank Skare
4366c47a09 - 2019-03-21 18:30:10 +01:00
Frank Skare
fc3dd45b72 - 2019-03-19 12:03:55 +01:00
Frank Skare
66cf3a9b2f - 2019-03-19 10:31:27 +01:00
Frank Skare
a9c2150c47 - 2019-03-19 10:16:48 +01:00
Frank Skare
b77bbd5aec 1.3 2019-03-19 09:56:05 +01:00
Frank Skare
92b58873e2 - 2019-03-18 22:16:31 +01:00
Frank Skare
c8214b2d94 - 2019-03-18 22:07:50 +01:00
Frank Skare
f77defecfd - 2019-03-18 22:07:04 +01:00
Frank Skare
6fec4bada7 - 2019-03-18 22:06:23 +01:00
Frank Skare
c508761c36 - 2019-03-18 22:00:08 +01:00
Frank Skare
3fd1285ad8 - 2019-03-17 20:56:10 +01:00
Frank Skare
91a67c29a7 - 2019-03-14 21:40:08 +01:00
Frank Skare
c8ce0b6dfc 1.1 2019-03-14 07:02:38 +01:00
Frank Skare
c075f4982b 1.1 2019-03-14 05:22:39 +01:00
Frank Skare
303355ce63 1.2 2019-03-14 05:19:57 +01:00
Frank Skare
a392c2c6da - 2019-03-13 22:22:51 +01:00
Frank Skare
72d6f44e47 - 2019-03-12 01:21:31 +01:00
Frank Skare
2e695e43bf 1.0.0.0 2019-03-11 22:05:30 +01:00
Frank Skare
207c2fc685 1.0.0.0 2019-03-11 21:59:26 +01:00
Frank Skare
3939dc7924 1.0.0.0 2019-03-11 21:33:37 +01:00
Frank Skare
97521e034f 1.0.0.0 2019-03-11 21:27:06 +01:00
Frank Skare
d91bba6521 1.0.0.0 2019-03-11 21:10:14 +01:00
stax76
7e1c30ffa0 Update README.md 2019-03-11 06:24:20 +01:00
Frank Skare
e957101268 - 2019-03-11 06:16:39 +01:00
Frank Skare
c25c605672 - 2019-03-11 02:55:27 +01:00
Frank Skare
54a8982e6d - 2019-03-09 16:16:20 +01:00
Frank Skare
7b68e8b581 - 2019-03-09 16:07:37 +01:00
Frank Skare
3a66bff0cc - 2019-03-09 15:56:49 +01:00
Frank Skare
6022809080 - 2019-03-08 22:51:34 +01:00
Frank Skare
714eb7c9fa 0.2.5 2019-02-27 21:18:12 +01:00
Frank Skare
0f68c0cd3e 0.2.4 2018-12-20 00:08:21 +01:00
Frank Skare
ea8de8bd5a 0.2.3 2018-12-19 23:42:32 +01:00
Frank Skare
e31284171c 0.2.3 2018-12-19 23:35:16 +01:00
Frank Skare
f115a5cf3a 0.2.3 2018-12-19 23:28:38 +01:00
stax76
5e3e734245 - 2018-05-28 22:18:34 +02:00
92 changed files with 5221 additions and 7224 deletions

View File

@@ -1,9 +1,10 @@
Imports System.ComponentModel.Composition
Imports System.IO
Imports System.Windows.Forms
Imports vbnet
Imports mpvnet
Imports vbnet.UI.MainModule
Imports mpvnet.StaticUsing
Imports CSScriptLibrary
<Export(GetType(IAddon))>
@@ -11,9 +12,10 @@ Public Class CSScriptAddon
Implements IAddon
Sub New()
Dim scriptDir = Folder.AppDataRoaming + "mpv\scripts"
Dim scriptDir = mp.mpvConfFolderPath + "scripts"
If Not Directory.Exists(scriptDir) Then Return
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs")
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList
csFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\Scripts", "*.cs"))
If csFiles.Count = 0 Then Return
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom
@@ -21,7 +23,7 @@ Public Class CSScriptAddon
Try
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(i))
Catch ex As Exception
MsgException(ex)
MsgError(ex.ToString)
End Try
Next
End Sub

View File

@@ -10,7 +10,7 @@
<AssemblyName>CSScriptAddon</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Windows</MyType>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>..\mpvnet\bin\Debug\Addons\CSScript\</OutputPath>
<OutputPath>..\mpv.net\bin\Debug\Addons\CSScriptAddon\</OutputPath>
<DocumentationFile>
</DocumentationFile>
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
@@ -52,23 +52,15 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>.\CSScriptLibrary.dll</HintPath>
</Reference>
<Reference Include="mpvnet, Version=0.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\mpvnet\bin\Debug\mpvnet.exe</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="vbnet">
<HintPath>..\vbnet\bin\Debug\vbnet.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
@@ -121,5 +113,12 @@
<ItemGroup>
<Content Include="CSScriptLibrary.dll" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>

View File

@@ -8,11 +8,11 @@ Imports System.Runtime.InteropServices
' Review the values of the assembly attributes
<Assembly: AssemblyTitle("PowerShellAddon")>
<Assembly: AssemblyTitle("CSScriptAddon")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("PowerShellAddon")>
<Assembly: AssemblyCopyright("Copyright © 2017")>
<Assembly: AssemblyProduct("CSScriptAddon")>
<Assembly: AssemblyCopyright("Copyright © 2019")>
<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>

View File

@@ -15,7 +15,7 @@ Option Explicit On
Namespace My
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0"), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Partial Friend NotInheritable Class MySettings
Inherits Global.System.Configuration.ApplicationSettingsBase

166
README.md
View File

@@ -1,30 +1,61 @@
# mpv.net
mpv.net is a libmpv based media player for Windows, it looks and works like mpv, even shares the settings and therefore the mpv documentation applies, it can be found at:
mpv.net is a libmpv based media player for Windows, it looks and works like mpv, even shares the settings and therefore the mpv documentation applies.
https://mpv.io/manual/master/
mpv and mpv.net have a learning curve and are only suitable for experienced users.
mpv manual: https://mpv.io/manual/master/
Table of contents
-------
- [Features](#features)
- [Context Menu](#context-menu)
- [Settings](#settings)
- [C# Scripting](#cs-scripting)
- [Python Scripting](#python-scripting)
- [PowerShell Scripting](#powershell-scripting)
- [Changelog](#changelog)
### Features
- mpv's OSC, IPC, Lua/JS, conf files and more
- Context menu which can be customized
- Addons implemented with the Managed Extension Framework (MEF)
- C# scripts implemented with CS-Script
- Customizable context menu defined in the same file as the keybindings
- Addon API for .NET languages
- 5 different scripting languages are supported, Python scripting implemented with IronPython, C# implemented with CS-Script, Lua and JavaScript implemented in libmpv and PowerShell
- mpv's OSC, IPC, conf files and more
![](https://github.com/stax76/mpvnet/blob/master/mpvnet/screenshot.jpg)
![](https://raw.githubusercontent.com/stax76/mpv.net/master/screenshot.png)
### Context Menu
The context menu can be customized via input.conf file located at:
```
C:\Users\username\AppData\Roaming\mpv\input.conf
```
if it's missing mpv.net generates it with the following defaults:
C:\Users\Frank\AppData\Roaming\mpv\input.conf
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt
https://github.com/stax76/mpvnet/blob/master/mpvnet/Resources/input_conf.txt
### Settings
mpv.net shares the settings with mpv, settings have to be edited in a config file called mpv.conf located at:
```
C:\Users\username\AppData\Roaming\mpv\mpv.conf
```
if it's missing mpv.net generates it with the following defaults:
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt
### C# Scripting
A simple C# script located at: C:\Users\Frank\AppData\Roaming\mpv\scripts\test.cs
A simple C# script located at:
```
C:\Users\username\AppData\Roaming\mpv\scripts\fullscreen.cs
```
or
```
startup\scripts\fullscreen.cs
```
```
using mpvnet;
@@ -32,25 +63,118 @@ class Script
{
public Script()
{
var fs = mpv.GetStringProp("fullscreen");
mpv.Command("show-text", "fullscreen: " + fs);
mpv.ObserveBoolProp("fullscreen", FullscreenChange);
var fs = mp.get_property_string("fullscreen");
mp.commandv("show-text", "fullscreen: " + fs);
mp.observe_property_bool("fullscreen", FullscreenChange);
}
void FullscreenChange(bool val)
{
mpv.Command("show-text", "fullscreen: " + val.ToString());
mp.commandv("show-text", "fullscreen: " + val.ToString());
}
}
```
### Changes
### Python Scripting
### 0.2.2
A simple Python script located at:
```
C:\Users\user\AppData\Roaming\mpv\scripts\seek-show-position.py
```
or
```
startup\scripts\seek-show-position.py
```
```
# when seeking displays position and
# duration like so: 70:00 / 80:00
# which is different from mpv which
# uses 01:10:00 / 01:20:00
- history feature added
- mpv lib updated
import math
### 0.2.1
def seek():
mp.commandv('show-text',
format(mp.get_property_number("time-pos")) + " / " + format(mp.get_property_number("duration")))
- right-click in fullscreen in the right-left corner closes the app
def format(f):
sec = round(f)
if sec < 0:
sec = 0
pos_min_floor = math.floor(sec / 60)
sec_rest = sec - pos_min_floor * 60
return add_zero(pos_min_floor) + ":" + add_zero(sec_rest)
def add_zero(val):
val = round(val)
return "" + str(int(val)) if (val > 9) else "0" + str(int(val))
mp.register_event("seek", seek) # or use: mp.Seek += seek
```
### PowerShell Scripting
A simple PowerShell script located at:
```
C:\Users\user\AppData\Roaming\mpv\scripts\seek.ps1
```
or
```
startup\scripts\seek.ps1
```
```
$position = [mp]::get_property_number("time-pos");
[mp]::commandv("show-text", $position.ToString() + " seconds")
```
Please note that PowerShell don't allow assigning to events and mpv.net uses as workaround a matching script filename, a list of available events can be found in the mpv manual or in the file mp.cs in the mpv.net source code.
### Changelog
### 1.8
- new config editor added
### 1.7
- showing the conf files mpv.net uses now the app that is registered for txt files, before it just shell executed the conf file which only worked if conf files were associated with an application
- leaving fullscreen mode the previous window size and position wasn't restored
- when the source video aspect ratio changes the height is kept and the width is adjusted and a check is performed to assure the window is within screen bounds
### 1.6
- a crash caused by WM_APPCOMMAND (multimedia keyboards) commands was fixed
- support for the 'screen' property was added, it should work both from mpv.conf (screen = 1) and from command line (--screen=1)
- per monitor DPI awareness and better multi monitor support was added
### 1.5
- the info command supports now info for music files instead of showing an exception on music files
- added support for WM_APPCOMMAND API to support media keyboards
- fixed Alt key input not working
- mpv.net API methods renamed to match the names used in the Lua/JS API
### 1.4
- the last thread sync fix wasn't working well, the delayed shutdown should be gone for good now
- libmpv updated
### 1.3
- besides Lua/JavaScript/C#/Python there is now PowerShell supported as fifth scripting language
- in case there isn't yet a mpv.conf file mpv.net creates the file with certain default settings that were previously set on every mpv.net start. This was changed to provide transparency on which settings mpv.net uses. These default settings can be seen here: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt
### 1.2
- a thread synchonisation bug which caused the shutdown to be delayed or frozen was fixed, it also caused the Shutdown event not to fire which caused the rating plugin not to work
### 1.1
- added support for Python scripting via IronPython
- show tracks and show playlist didn't work because the duration wasn't defined in the key bindings
### 1.0
- much more feature packed context menu

View File

@@ -5,11 +5,11 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Rating")]
[assembly: AssemblyTitle("RatingAddon")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Rating")]
[assembly: AssemblyProduct("RatingAddon")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@@ -1,21 +1,21 @@
using System;
using System.ComponentModel.Composition;
using System.Collections.Generic;
using mpvnet;
using System.IO;
namespace Rating
using mpvnet;
namespace RatingAddon
{
[Export(typeof(IAddon))]
public class Rating : IAddon
public class RatingAddon : IAddon
{
private Dictionary<string, int> Dic = new Dictionary<string, int>();
public Rating()
public RatingAddon()
{
mpv.ClientMessage += mpv_ClientMessage;
mpv.Shutdown += mpv_Shutdown;
mp.ClientMessage += mpv_ClientMessage;
mp.Shutdown += mpv_Shutdown;
}
private void mpv_Shutdown()
@@ -51,8 +51,8 @@ namespace Rating
if (args?.Length != 2 || args[0] != "rate-file" || ! int.TryParse(args[1], out rating))
return;
Dic[mpv.GetStringProp("path")] = rating;
mpv.Command("show-text", $"Rating: {rating}");
Dic[mp.get_property_string("path")] = rating;
mp.commandv("show-text", $"Rating: {rating}");
}
}
}

View File

@@ -7,9 +7,9 @@
<ProjectGuid>{55C88710-539D-4402-84C8-31694841C731}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Rating</RootNamespace>
<RootNamespace>RatingAddon</RootNamespace>
<AssemblyName>RatingAddon</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -17,7 +17,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\mpvnet\bin\Debug\Addons\Rating\</OutputPath>
<OutputPath>..\mpv.net\bin\Debug\Addons\RatingAddon\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -67,10 +67,6 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="mpvnet">
<HintPath>..\mpvnet\bin\Debug\mpvnet.exe</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
@@ -82,8 +78,15 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Rating.cs" />
<Compile Include="RatingAddon.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,31 +0,0 @@
// when seeking displays position and
// duration like so: 00:00 / 120:00
// this is different from MPC which
// uses 00:00:00 / 02:00:00
function add_zero(val)
{
val = Math.round(val);
return val > 9 ? "" + val : "0" + val;
}
function format(val)
{
var sec = Math.round(val);
if (sec < 0)
sec = 0;
pos_min_floor = Math.floor(sec / 60);
sec_rest = sec - pos_min_floor * 60;
return add_zero(pos_min_floor) + ":" + add_zero(sec_rest);
}
function on_seek(_)
{
mp.commandv("show-text",
format(mp.get_property_number("time-pos")) + " / " +
format(mp.get_property_number("duration")));
}
mp.register_event("seek", on_seek);

View File

@@ -3,15 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.8
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpv.net", "mpvnet\mpv.net.csproj", "{1751F378-8EDF-4B62-BE6D-304C7C287089}"
ProjectSection(ProjectDependencies) = postProject
{55C88710-539D-4402-84C8-31694841C731} = {55C88710-539D-4402-84C8-31694841C731}
{71808A87-8B1C-4DF8-957C-D79C3B164CCA} = {71808A87-8B1C-4DF8-957C-D79C3B164CCA}
EndProjectSection
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpv.net", "mpv.net\mpv.net.csproj", "{1751F378-8EDF-4B62-BE6D-304C7C287089}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rating", "RatingAddon\Rating.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "vbnet", "vbnet\vbnet.vbproj", "{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingAddon", "RatingAddon\RatingAddon.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CSScriptAddon", "CSScriptAddon\CSScriptAddon.vbproj", "{71808A87-8B1C-4DF8-957C-D79C3B164CCA}"
EndProject
@@ -49,18 +43,6 @@ Global
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.Build.0 = Release|x64
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.ActiveCfg = Release|x86
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.Build.0 = Release|x86
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Debug|x64.Build.0 = Debug|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Debug|x86.ActiveCfg = Debug|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Debug|x86.Build.0 = Debug|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Release|Any CPU.Build.0 = Release|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Release|x64.ActiveCfg = Release|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Release|x64.Build.0 = Release|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Release|x86.ActiveCfg = Release|Any CPU
{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}.Release|x86.Build.0 = Release|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x64.ActiveCfg = Debug|Any CPU

View File

@@ -1,31 +1,11 @@
/**
*mpv.net
*Copyright(C) 2017 stax76
*
*This program is free software: you can redistribute it and/or modify
*it under the terms of the GNU General Public License as published by
*the Free Software Foundation, either version 3 of the License, or
*(at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program. If not, see http://www.gnu.org/licenses/.
*/
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Windows.Forms;
using static vbnet.UI.MainModule;
// MEF (Managed Extension Framework)
using static mpvnet.StaticUsing;
namespace mpvnet
{
@@ -48,7 +28,7 @@ namespace mpvnet
foreach (string i in Directory.GetDirectories(dir))
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\Addons";
dir = mp.mpvConfFolderPath + "\\Addons";
if (Directory.Exists(dir))
foreach (string i in Directory.GetDirectories(dir))
@@ -62,7 +42,7 @@ namespace mpvnet
}
catch (Exception e)
{
MsgException(e);
MsgError(e.ToString());
}
}
}

6
mpv.net/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
</configuration>

179
mpv.net/Command.cs Normal file
View File

@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using static mpvnet.StaticUsing;
namespace mpvnet
{
public class Command
{
public string Name { get; set; }
public Action<string[]> Action { get; set; }
private static List<Command> commands;
public static List<Command> Commands
{
get
{
if (commands == null)
{
commands = new List<Command>();
Type type = typeof(Command);
MethodInfo[] methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
foreach (var i in methods)
{
ParameterInfo[] parameters = i.GetParameters();
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(string[]))
continue;
Command cmd = new Command() { Name = i.Name.Replace("_","-"), Action = (Action<string[]>)i.CreateDelegate(typeof(Action<string[]>)) };
commands.Add(cmd);
}
}
return commands;
}
}
public static void open_files(string[] args)
{
MainForm.Instance.Invoke(new Action(() => {
using (var d = new OpenFileDialog())
{
d.Multiselect = true;
d.Filter = Misc.GetFilter(Misc.FileTypes);
if (d.ShowDialog() == DialogResult.OK)
mp.LoadFiles(d.FileNames);
}
}));
}
public static void open_config_folder(string[] args)
{
Process.Start(mp.mpvConfFolderPath);
}
public static void show_keys(string[] args)
{
Process.Start(NativeHelp.GetAssociatedApplication(".txt"), mp.InputConfPath);
}
public static void show_prefs(string[] args)
{
Process.Start(NativeHelp.GetAssociatedApplication(".txt"), mp.mpvConfPath);
}
public static void show_conf_editor(string[] args)
{
using (var p = new Process())
{
p.StartInfo.FileName = Application.StartupPath + "\\mpvSettingsEditor.exe";
p.StartInfo.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
p.Start();
}
}
public static void history(string[] args)
{
var fp = mp.mpvConfFolderPath + "history.txt";
if (File.Exists(fp))
Process.Start(fp);
else
if (MsgQuestion("Create history.txt file in config folder?\n\nmpv.net will write the date, time and filename of opened files to it.") == DialogResult.OK)
File.WriteAllText(fp, "");
}
public static void shell_execute(string[] args)
{
Process.Start(args[0]);
}
public static void set_setting(string[] args)
{
bool changed = false;
var lines = File.ReadAllLines(mp.mpvConfPath);
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Contains("=") &&
lines[i].Substring(0, lines[i].IndexOf("=")).Trim("# ".ToCharArray()) == args[0])
{
lines[i] = args[0] + " = " + args[1];
changed = true;
}
}
if (changed)
File.WriteAllText(mp.mpvConfPath, String.Join(Environment.NewLine, lines));
else
File.WriteAllText(mp.mpvConfPath, File.ReadAllText(mp.mpvConfPath) + Environment.NewLine + args[0] + " = " + args[1]);
MainForm.Instance.ShowMsgBox("Please restart mpv.net", MessageBoxIcon.Information);
}
public static void show_info(string[] args)
{
var fileInfo = new FileInfo(mp.get_property_string("path"));
using (var mediaInfo = new MediaInfo(fileInfo.FullName))
{
string width = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "Width");
if (width == "")
{
string performer = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Performer");
string title = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Title");
string album = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Album");
string genre = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Genre");
string date = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Recorded_Date");
string duration = mediaInfo.GetInfo(MediaInfoStreamKind.Audio, "Duration/String");
string text = "";
if (performer != "") text += "Artist: " + performer + "\n";
if (title != "") text += "Title: " + title + "\n";
if (album != "") text += "Album: " + album + "\n";
if (genre != "") text += "Genre: " + genre + "\n";
if (date != "") text += "Year: " + date + "\n";
if (duration != "") text += "Length: " + duration + "\n";
mp.commandv("show-text", text, "5000");
}
else
{
string height = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "Height");
TimeSpan position = TimeSpan.FromSeconds(mp.get_property_number("time-pos"));
TimeSpan duration = TimeSpan.FromSeconds(mp.get_property_number("duration"));
string bitrate = mediaInfo.GetInfo(MediaInfoStreamKind.Video, "BitRate");
if (bitrate == "")
bitrate = "0";
var bitrate2 = Convert.ToDouble(bitrate) / 1000.0 / 1000.0;
var videoCodec = mp.get_property_string("video-format").ToUpper();
var filename = fileInfo.Name;
var text =
FormatTime(position.TotalMinutes) + ":" +
FormatTime(position.Seconds) + " / " +
FormatTime(duration.TotalMinutes) + ":" +
FormatTime(duration.Seconds) + "\n" +
Convert.ToInt32(fileInfo.Length / 1024 / 1024).ToString() +
$" MB - {width} x {height}\n{videoCodec} - {bitrate2.ToString("f1")} Mb/s" + "\n" + filename;
mp.commandv("show-text", text, "5000");
}
string FormatTime(double value) => ((int)value).ToString("00");
}
}
}
}

View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mpvnet
{

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -42,10 +42,10 @@
// MainForm
//
this.AllowDrop = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(20F, 48F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(1553, 1000);
this.ClientSize = new System.Drawing.Size(1012, 615);
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);

411
mpv.net/MainForm.cs Normal file
View File

@@ -0,0 +1,411 @@
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;
using static mpvnet.StaticUsing;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace mpvnet
{
public partial class MainForm : Form
{
public static MainForm Instance { get; set; }
public static IntPtr Hwnd;
private Point LastCursorPosChanged;
private int LastCursorChangedTickCount;
private bool IgnoreDpiChanged = true;
public ContextMenuStripEx CMS;
public MainForm()
{
InitializeComponent();
try
{
Application.ThreadException += Application_ThreadException;
Instance = this;
Hwnd = Handle;
Text += " " + Application.ProductVersion;
if (mp.mpvConf.ContainsKey("screen"))
SetScreen(Convert.ToInt32(mp.mpvConf["screen"]));
else
SetScreen(Screen.PrimaryScreen);
ChangeFullscreen((mp.mpvConf.ContainsKey("fullscreen") && mp.mpvConf["fullscreen"] == "yes") ||
(mp.mpvConf.ContainsKey("fs") && mp.mpvConf["fs"] == "yes"));
ProcessCommandLineEarly();
}
catch (Exception e)
{
MsgError(e.ToString());
}
}
protected void SetScreen(int targetIndex)
{
Screen[] screens = Screen.AllScreens;
if (targetIndex < 0 || targetIndex > screens.Length - 1) return;
SetScreen(screens[Array.IndexOf(screens, screens[targetIndex])]);
}
protected void SetScreen(Screen screen)
{
Rectangle target = screen.Bounds;
Left = target.X + Convert.ToInt32((target.Width - Width) / 2.0);
Top = target.Y + Convert.ToInt32((target.Height - Height) / 2.0);
SetStartFormPositionAndSize();
}
void SetStartFormPositionAndSize()
{
if (IsFullscreen || mp.VideoSize.Width == 0) return;
Screen screen = Screen.FromControl(this);
int height = Convert.ToInt32(screen.Bounds.Height * 0.6);
int width = Convert.ToInt32(height * mp.VideoSize.Width / (double)mp.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
NativeHelp.AddWindowBorders(Handle, ref rect);
int left = middlePos.X - rect.Width / 2;
int top = middlePos.Y - rect.Height / 2;
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, left, top, rect.Width, rect.Height, 4 /* SWP_NOZORDER */);
}
void SetFormPositionAndSizeKeepHeight()
{
if (IsFullscreen || mp.VideoSize.Width == 0) return;
Screen screen = Screen.FromControl(this);
int height = ClientSize.Height;
int width = Convert.ToInt32(height * mp.VideoSize.Width / (double)mp.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
NativeHelp.AddWindowBorders(Handle, ref rect);
int left = middlePos.X - rect.Width / 2;
int top = middlePos.Y - rect.Height / 2;
Screen[] screens = Screen.AllScreens;
if (left < screens[0].Bounds.Left)
left = screens[0].Bounds.Left;
int maxLeft = screens[0].Bounds.Left + screens.Select((sc) => sc.Bounds.Width).Sum() - rect.Width - SystemInformation.CaptionHeight;
if (left > maxLeft)
left = maxLeft;
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, left, top, rect.Width, rect.Height, 4 /* SWP_NOZORDER */);
}
protected void ProcessCommandLineEarly()
{
var args = Environment.GetCommandLineArgs().Skip(1);
foreach (string i in args)
{
if (i.StartsWith("--"))
{
if (i.Contains("="))
{
string left = i.Substring(2, i.IndexOf("=") - 2);
string right = i.Substring(left.Length + 3);
if (left == "screen")
SetScreen(Convert.ToInt32(right));
ChangeFullscreen((left == "fs" || left == "fullscreen") && right == "yes");
}
else
{
string switchName = i.Substring(2);
switch (switchName)
{
case "fs":
case "fullscreen":
ChangeFullscreen(true);
break;
}
}
}
}
}
public void BuildMenu()
{
foreach (var i in File.ReadAllText(mp.InputConfPath).SplitLinesNoEmpty())
{
if (!i.Contains("#menu:"))
continue;
var left = i.Left("#menu:").Trim();
if (left.StartsWith("#"))
continue;
var cmd = left.Right(" ").Trim();
var menu = i.Right("#menu:").Trim();
var key = menu.Left(";").Trim();
var path = menu.Right(";").Trim();
if (path == "" || cmd == "")
continue;
var menuItem = CMS.Add(path, () => {
try
{
mp.command_string(cmd);
}
catch (Exception e)
{
MsgError(e.ToString());
}
});
if (menuItem != null)
menuItem.ShortcutKeyDisplayString = key.Replace("_","") + " ";
}
}
private void CMS_Opened(object sender, EventArgs e)
{
CursorHelp.Show();
}
private string LastHistory;
private void mp_PlaybackRestart()
{
var filename = mp.get_property_string("filename");
BeginInvoke(new Action(() => { Text = filename + " - mpv.net " + Application.ProductVersion; }));
var historyFilepath = mp.mpvConfFolderPath + "history.txt";
if (LastHistory != filename && File.Exists(historyFilepath))
{
File.AppendAllText(historyFilepath, DateTime.Now.ToString() + " " +
Path.GetFileNameWithoutExtension(filename) + "\r\n");
LastHistory = filename;
}
}
private void Mp_Idle()
{
BeginInvoke(new Action(() => { Text = "mpv.net " + Application.ProductVersion; }));
}
private void CM_Popup(object sender, EventArgs e)
{
CursorHelp.Show();
}
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MsgError(e.Exception.ToString());
}
private void mp_VideoSizeChanged()
{
BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight()));
}
private void mp_Shutdown()
{
BeginInvoke(new Action(() => Close()));
}
public bool IsFullscreen
{
get => WindowState == FormWindowState.Maximized;
}
void mp_ChangeFullscreen(bool value)
{
BeginInvoke(new Action(() => ChangeFullscreen(value)));
}
void ChangeFullscreen(bool value)
{
if (value)
{
if (FormBorderStyle != FormBorderStyle.None)
{
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
}
}
else
{
WindowState = FormWindowState.Normal;
FormBorderStyle = FormBorderStyle.Sizable;
SetFormPositionAndSizeKeepHeight();
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x0201: // WM_LBUTTONDOWN
case 0x0202: // WM_LBUTTONUP
case 0x0100: // WM_KEYDOWN
case 0x0101: // WM_KEYUP
case 0x020A: // WM_MOUSEWHEEL
if (mp.MpvWindowHandle != IntPtr.Zero)
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x319: // WM_APPCOMMAND
if (mp.MpvWindowHandle != IntPtr.Zero)
Native.PostMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x0104: // WM_SYSKEYDOWN:
if (mp.MpvWindowHandle != IntPtr.Zero)
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x0105: // WM_SYSKEYUP:
if (mp.MpvWindowHandle != IntPtr.Zero)
Native.SendMessage(mp.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x203: // Native.WM.LBUTTONDBLCLK
if (!IsMouseInOSC())
mp.command_string("cycle fullscreen");
break;
case 0x02E0: // WM_DPICHANGED
if (IgnoreDpiChanged) break;
var r2 = Marshal.PtrToStructure<Native.RECT>(m.LParam);
Native.SetWindowPos(Handle, IntPtr.Zero, r2.Left, r2.Top, r2.Width, r2.Height, 0);
break;
case 0x0214: // WM_SIZING
var rc = Marshal.PtrToStructure<Native.RECT>(m.LParam);
var r = rc;
NativeHelp.SubtractWindowBorders(Handle, ref r);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
float aspect = mp.VideoSize.Width / (float)mp.VideoSize.Height;
int d_w = Convert.ToInt32(c_h * aspect - c_w);
int d_h = Convert.ToInt32(c_w / aspect - c_h);
int[] d_corners = { d_w, d_h, -d_w, -d_h };
int[] corners = { rc.Left, rc.Top, rc.Right, rc.Bottom };
int corner = NativeHelp.GetResizeBorder(m.WParam.ToInt32());
if (corner >= 0)
corners[corner] -= d_corners[corner];
Marshal.StructureToPtr<Native.RECT>(new Native.RECT(corners[0], corners[1], corners[2], corners[3]), m.LParam, false);
m.Result = new IntPtr(1);
return;
}
base.WndProc(ref m);
}
protected override void OnDragEnter(DragEventArgs e)
{
base.OnDragEnter(e);
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
protected override void OnDragDrop(DragEventArgs e)
{
base.OnDragDrop(e);
if (e.Data.GetDataPresent(DataFormats.FileDrop))
mp.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[]);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (WindowState == FormWindowState.Normal &&
e.Button == MouseButtons.Left &&
e.Y < ClientSize.Height * 0.9)
{
var HTCAPTION = new IntPtr(2);
Native.ReleaseCapture();
Native.PostMessage(Handle, 0xA1 /* WM_NCLBUTTONDOWN */, HTCAPTION, IntPtr.Zero);
}
var sb = Screen.FromControl(this).Bounds;
var p1 = new Point(sb.Width, 0);
var p2 = PointToScreen(e.Location);
if (Math.Abs(p1.X - p2.X) < 10 && Math.Abs(p1.Y - p2.Y) < 10)
mp.commandv("quit");
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
mp.command_string($"mouse {e.X} {e.Y}");
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
CursorHelp.Show();
}
bool IsMouseInOSC()
{
return PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
}
private void Timer_Tick(object sender, EventArgs e)
{
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
{
LastCursorPosChanged = Control.MousePosition;
LastCursorChangedTickCount = Environment.TickCount;
}
else if (Environment.TickCount - LastCursorChangedTickCount > 1500 &&
!IsMouseInOSC() && ClientRectangle.Contains(PointToClient(MousePosition)) &&
Form.ActiveForm == this && !CMS.Visible)
{
CursorHelp.Hide();
}
}
public DialogResult ShowMsgBox(string message, MessageBoxIcon icon)
{
var buttons = MessageBoxButtons.OK;
if (icon == MessageBoxIcon.Question) buttons = MessageBoxButtons.OKCancel;
var fn = new Func<DialogResult>(() => MessageBox.Show(
message, Application.ProductName, buttons, MessageBoxIcon.Information));
return (DialogResult)Invoke(fn);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
mp.Init();
mp.observe_property_bool("fullscreen", mp_ChangeFullscreen);
mp.Shutdown += mp_Shutdown;
mp.VideoSizeChanged += mp_VideoSizeChanged;
mp.PlaybackRestart += mp_PlaybackRestart;
mp.Idle += Mp_Idle;
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
CMS = new ContextMenuStripEx(components);
CMS.Opened += CMS_Opened;
ContextMenuStrip = CMS;
BuildMenu();
IgnoreDpiChanged = false;
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
mp.commandv("quit");
mp.AutoResetEvent.WaitOne(3000);
}
}
}

84
mpv.net/MediaInfo.cs Normal file
View File

@@ -0,0 +1,84 @@
using System;
using System.Runtime.InteropServices;
public class MediaInfo : IDisposable
{
private IntPtr Handle;
private static bool Loaded;
public MediaInfo(string sourcepath)
{
if (!Loaded)
{
if (LoadLibrary("MediaInfo.dll") == IntPtr.Zero)
throw new Exception("Failed to load MediaInfo.dll.");
Loaded = true;
}
Handle = MediaInfo_New();
MediaInfo_Open(Handle, sourcepath);
}
public string GetInfo(MediaInfoStreamKind streamKind, string parameter)
{
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, 0, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
}
private bool Disposed;
public void Dispose()
{
if (!Disposed)
{
Disposed = true;
MediaInfo_Close(Handle);
MediaInfo_Delete(Handle);
}
}
~MediaInfo()
{
Dispose();
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string path);
[DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_New();
[DllImport("MediaInfo.dll")]
private static extern void MediaInfo_Delete(IntPtr Handle);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern int MediaInfo_Open(IntPtr Handle, string FileName);
[DllImport("MediaInfo.dll")]
private static extern int MediaInfo_Close(IntPtr Handle);
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr MediaInfo_Get(IntPtr Handle, MediaInfoStreamKind StreamKind, int StreamNumber, string Parameter, MediaInfoInfoKind KindOfInfo, MediaInfoInfoKind KindOfSearch);
}
public enum MediaInfoStreamKind
{
General,
Video,
Audio,
Text,
Chapters,
Image
}
public enum MediaInfoInfoKind
{
Name,
Text,
Measure,
Options,
NameText,
MeasureText,
Info,
HowTo
}

491
mpv.net/Menu.cs Normal file
View File

@@ -0,0 +1,491 @@
using System;
using System.Linq;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using Microsoft.Win32;
using System.Windows.Forms;
using System.Drawing;
public class ContextMenuStripEx : ContextMenuStrip
{
public ContextMenuStripEx()
{
}
public ContextMenuStripEx(IContainer container) : base(container)
{
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
Renderer = new ToolStripRendererEx();
}
public ActionMenuItem Add(string path)
{
return Add(path, null);
}
public ActionMenuItem Add(string path, Action action)
{
return Add(path, action, true);
}
public ActionMenuItem Add(string path, Action action, bool enabled)
{
var ret = ActionMenuItem.Add(Items, path, action);
if (ret == null)
return null;
ret.Enabled = enabled;
return ret;
}
public ActionMenuItem Add(string path, Action action, Func<bool> enabledFunc)
{
var ret = ActionMenuItem.Add(Items, path, action);
return ret;
}
}
public class ActionMenuItem : MenuItemEx
{
private Action Action;
public ActionMenuItem()
{
}
public ActionMenuItem(string text, Action action)
{
this.Text = text;
this.Action = action;
}
protected override void OnClick(EventArgs e)
{
Application.DoEvents();
if (Action != null)
Action();
base.OnClick(e);
}
public static ActionMenuItem Add<T>(ToolStripItemCollection items, string path, Action<T> action, T value)
{
return Add(items, path, () => action(value));
}
public static ActionMenuItem Add(ToolStripItemCollection items, string path, Action action)
{
var a = path.Split(new[] { " > ", " | " }, StringSplitOptions.RemoveEmptyEntries);
var l = items;
for (var x = 0; x <= a.Length - 1; x++)
{
var found = false;
foreach (var i in l.OfType<ToolStripMenuItem>())
{
if (x < a.Length - 1)
{
if (i.Text == a[x] + " ")
{
found = true;
l = i.DropDownItems;
}
}
}
if (!found)
{
if (x == a.Length - 1)
{
if (a[x] == "-")
l.Add(new ToolStripSeparator());
else
{
ActionMenuItem item = new ActionMenuItem(a[x] + " ", action);
l.Add(item);
l = item.DropDownItems;
return item;
}
}
else
{
ActionMenuItem item = new ActionMenuItem();
item.Text = a[x] + " ";
l.Add(item);
l = item.DropDownItems;
}
}
}
return null;
}
}
public class MenuItemEx : ToolStripMenuItem
{
public static bool UseTooltips { get; set; }
public MenuItemEx()
{
}
public MenuItemEx(string text) : base(text)
{
}
public override Size GetPreferredSize(Size constrainingSize)
{
var ret = base.GetPreferredSize(constrainingSize);
ret.Height = Convert.ToInt32(Font.Height * 1.4);
return ret;
}
public void CloseAll(object item)
{
if (item is ToolStripItem)
{
var d = (ToolStripItem)item;
CloseAll(d.Owner);
}
if (item is ToolStripDropDown)
{
var d = (ToolStripDropDown)item;
d.Close();
CloseAll(d.OwnerItem);
}
}
protected override void OnClick(EventArgs e)
{
Application.DoEvents();
base.OnClick(e);
}
}
public class ToolStripRendererEx : ToolStripSystemRenderer
{
public static Color ColorChecked { get; set; }
public static Color ColorBorder { get; set; }
public static Color ColorTop { get; set; }
public static Color ColorBottom { get; set; }
public static Color ColorBackground { get; set; }
public static Color ColorToolStrip1 { get; set; }
public static Color ColorToolStrip2 { get; set; }
public static Color ColorToolStrip3 { get; set; }
public static Color ColorToolStrip4 { get; set; }
private int TextOffset;
public ToolStripRendererEx()
{
var argb = Convert.ToInt32(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0));
if (argb == 0)
argb = Color.LightBlue.ToArgb();
InitColors(Color.FromArgb(argb));
}
public static void InitColors(Color c)
{
ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100);
ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(200);
ColorBottom = HSLColor.Convert(c).ToColorSetLuminosity(220);
ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(230);
ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240);
ColorToolStrip1 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 1)));
ColorToolStrip2 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.7f)));
ColorToolStrip3 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.1f)));
ColorToolStrip4 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.4f)));
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
ControlPaint.DrawBorder(e.Graphics, e.AffectedBounds, Color.FromArgb(160, 175, 195), ButtonBorderStyle.Solid);
}
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
if (e.Item is ToolStripMenuItem && !(e.Item.Owner is MenuStrip))
{
Rectangle rect = e.TextRectangle;
var dropDown = e.ToolStrip as ToolStripDropDownMenu;
if (dropDown == null || dropDown.ShowImageMargin || dropDown.ShowCheckMargin)
TextOffset = Convert.ToInt32(e.Item.Height * 1.1);
else
TextOffset = Convert.ToInt32(e.Item.Height * 0.2);
e.TextRectangle = new Rectangle(TextOffset, Convert.ToInt32((e.Item.Height - rect.Height) / 2.0), rect.Width, rect.Height);
}
base.OnRenderItemText(e);
}
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
if (!(e.ToolStrip is ToolStripDropDownMenu) && !(e.ToolStrip.LayoutStyle == ToolStripLayoutStyle.VerticalStackWithOverflow))
{
Rectangle r = new Rectangle(-1, -1, e.AffectedBounds.Width, e.AffectedBounds.Height);
using (SolidBrush b = new SolidBrush(ColorToolStrip2))
{
e.Graphics.FillRectangle(b, r);
}
}
}
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
e.Item.ForeColor = Color.Black;
var r = new Rectangle(Point.Empty, e.Item.Size);
var g = e.Graphics;
if (!(e.Item.Owner is MenuStrip))
g.Clear(ColorBackground);
if (e.Item.Selected && e.Item.Enabled)
{
if (e.Item.Owner is MenuStrip)
DrawButton(e);
else
{
g.SmoothingMode = SmoothingMode.AntiAlias;
var r2 = new Rectangle(r.X + 2, r.Y, r.Width - 4, r.Height - 1);
using (Pen pen = new Pen(ColorBorder))
{
g.DrawRectangle(pen, r2);
}
r2.Inflate(-1, -1);
using (SolidBrush b = new SolidBrush(ColorBottom))
{
g.FillRectangle(b, r2);
}
}
}
}
public void DrawButton(ToolStripItemRenderEventArgs e)
{
var gx = e.Graphics;
var rect = new Rectangle(Point.Empty, e.Item.Size);
var rect2 = new Rectangle(rect.X, rect.Y, rect.Width - 1, rect.Height - 1);
using (Pen pen = new Pen(ColorBorder))
gx.DrawRectangle(pen, rect2);
rect2.Inflate(-1, -1);
var tsb = e.Item as ToolStripButton;
if (tsb != null && tsb.Checked)
using (SolidBrush brush = new SolidBrush(ColorChecked))
gx.FillRectangle(brush, rect2);
else
using (SolidBrush brush = new SolidBrush(ColorBottom))
gx.FillRectangle(brush, rect2);
}
protected override void OnRenderDropDownButtonBackground(ToolStripItemRenderEventArgs e)
{
if (e.Item.Selected)
DrawButton(e);
}
protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
{
var button = (ToolStripButton)e.Item;
if (e.Item.Selected || button.Checked)
DrawButton(e);
}
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
var value = e.Direction == ArrowDirection.Down ? 0x36 : 0x34;
var s = Convert.ToChar(value).ToString();
var font = new Font("Marlett", e.Item.Font.Size - 2);
var size = e.Graphics.MeasureString(s, font);
var x = Convert.ToInt32(e.Item.Width - size.Width);
var y = Convert.ToInt32((e.Item.Height - size.Height) / 2.0) + 1;
e.Graphics.DrawString(s, font, Brushes.Black, x, y);
}
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
{
int x = Convert.ToInt32(e.ImageRectangle.Height * 0.2);
e.Graphics.DrawImage(e.Image, new Point(x, x));
}
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
if (e.Item.IsOnDropDown)
{
e.Graphics.Clear(ColorBackground);
int right = e.Item.Width - Convert.ToInt32(TextOffset / 5.0);
int top = e.Item.Height / 2;
top -= 1;
using (Pen p = new Pen(Color.Gray))
e.Graphics.DrawLine(p, new Point(TextOffset, top), new Point(right, top));
}
else if (e.Vertical)
{
var bounds = e.Item.Bounds;
using (Pen p = new Pen(SystemColors.ControlDarkDark))
e.Graphics.DrawLine(p,
Convert.ToInt32(bounds.Width / 2.0),
Convert.ToInt32(bounds.Height * 0.15),
Convert.ToInt32(bounds.Width / 2.0),
Convert.ToInt32(bounds.Height * 0.85));
}
}
}
public struct HSLColor
{
public HSLColor(Color color) : this()
{
SetRGB(color.R, color.G, color.B);
}
public HSLColor(int h, int s, int l) : this()
{
Hue = h;
Saturation = s;
Luminosity = l;
}
private double hue;
public int Hue
{
get => System.Convert.ToInt32(hue * 240);
set => hue = CheckRange(value / 240.0);
}
private double saturation;
public int Saturation
{
get => System.Convert.ToInt32(saturation * 240);
set => saturation = CheckRange(value / 240.0);
}
private double luminosity;
public int Luminosity
{
get => System.Convert.ToInt32(luminosity * 240);
set => luminosity = CheckRange(value / 240.0);
}
private double CheckRange(double value)
{
if (value < 0)
value = 0;
else if (value > 1)
value = 1;
return value;
}
public Color ToColorAddLuminosity(int luminosity)
{
Luminosity += luminosity;
return ToColor();
}
public Color ToColorSetLuminosity(int luminosity)
{
Luminosity = luminosity;
return ToColor();
}
public Color ToColor()
{
double r = 0, g = 0, b = 0;
if (luminosity != 0)
{
if (saturation == 0)
{
b = luminosity;
g = luminosity;
r = luminosity;
}
else
{
double temp2 = GetTemp2(this);
double temp1 = 2.0 * luminosity - temp2;
r = GetColorComponent(temp1, temp2, hue + 1.0 / 3.0);
g = GetColorComponent(temp1, temp2, hue);
b = GetColorComponent(temp1, temp2, hue - 1.0 / 3.0);
}
}
return Color.FromArgb(
System.Convert.ToInt32(255 * r),
System.Convert.ToInt32(255 * g),
System.Convert.ToInt32(255 * b));
}
private static double GetColorComponent(double temp1, double temp2, double temp3)
{
temp3 = MoveIntoRange(temp3);
if (temp3 < 1 / 6.0)
return temp1 + (temp2 - temp1) * 6.0 * temp3;
else if (temp3 < 0.5)
return temp2;
else if (temp3 < 2 / 3.0)
return temp1 + ((temp2 - temp1) * (2 / 3.0 - temp3) * 6);
else
return temp1;
}
private static double MoveIntoRange(double temp3)
{
if (temp3 < 0)
temp3 += 1;
else if (temp3 > 1)
temp3 -= 1;
return temp3;
}
private static double GetTemp2(HSLColor hslColor)
{
double temp2;
if (hslColor.luminosity < 0.5)
temp2 = hslColor.luminosity * (1.0 + hslColor.saturation);
else
temp2 = hslColor.luminosity + hslColor.saturation - (hslColor.luminosity * hslColor.saturation);
return temp2;
}
public static HSLColor Convert(Color c)
{
HSLColor r = new HSLColor();
r.hue = c.GetHue() / 360.0;
r.luminosity = c.GetBrightness();
r.saturation = c.GetSaturation();
return r;
}
public void SetRGB(int red, int green, int blue)
{
HSLColor hc = HSLColor.Convert(Color.FromArgb(red, green, blue));
hue = hc.hue;
saturation = hc.saturation;
luminosity = hc.luminosity;
}
}

View File

@@ -1,6 +1,8 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace mpvnet
{
@@ -24,4 +26,35 @@ namespace mpvnet
int IComparerOfString_Compare(string x, string y) => StrCmpLogical(x, y);
int IComparer<string>.Compare(string x, string y) => IComparerOfString_Compare(x, y);
}
public class StaticUsing
{
public static void MsgInfo(string message)
{
MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
public static void MsgError(string message)
{
MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
public static DialogResult MsgQuestion(string message)
{
return MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
}
}
//public class OSVersion
//{
// public static float Windows7 { get; set; } = 6.1f;
// public static float Windows8 { get; set; } = 6.2f;
// public static float Windows81 { get; set; } = 6.3f;
// public static float Windows10 { get; set; } = 10f;
// public static float Current
// {
// get => Environment.OSVersion.Version.Major + Environment.OSVersion.Version.Minor / 10f;
// }
//}
}

View File

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

View File

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

129
mpv.net/PowerShellScript.cs Normal file
View File

@@ -0,0 +1,129 @@
using System;
using System.IO;
using System.Threading;
using System.Management.Automation.Runspaces;
using static mpvnet.StaticUsing;
using System.Reflection;
using System.Threading.Tasks;
namespace mpvnet
{
public class PowerShellScript
{
public static object Execute(string code, string[] parameters)
{
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.ApartmentState = ApartmentState.STA;
runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
runspace.Open();
using (Pipeline pipeline = runspace.CreatePipeline())
{
pipeline.Commands.AddScript(
@"Using namespace mpvnet;
Using namespace System;
[System.Reflection.Assembly]::LoadWithPartialName(""mpvnet"")");
pipeline.Commands.AddScript(code);
try
{
var ret = pipeline.Invoke(parameters);
if (ret.Count > 0)
return ret[0];
}
catch (Exception ex)
{
try
{
using (Pipeline pipeline2 = runspace.CreatePipeline())
{
pipeline2.Commands.AddScript("$PSVersionTable.PSVersion.Major * 10 +" +
"$PSVersionTable.PSVersion.Minor");
if (Convert.ToInt32(pipeline2.Invoke()[0].ToString()) < 51)
throw new Exception();
}
}
catch
{
MsgError("PowerShell Setup Problem\r\n\r\nEnsure you have at least PowerShell 5.1 installed.");
return null;
}
MsgError(ex.ToString());
}
}
}
return null;
}
public static void Init(string filePath)
{
foreach (var eventInfo in typeof(mp).GetEvents())
{
if (eventInfo.Name.ToLower() ==
Path.GetFileNameWithoutExtension(filePath).ToLower().Replace("-", ""))
{
PowerShellEventObject eventObject = new PowerShellEventObject();
MethodInfo mi;
eventObject.FilePath = filePath;
if (eventInfo.EventHandlerType == typeof(Action))
{
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.Invoke));
}
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
{
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.InvokeEndFileEventMode));
}
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
{
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.InvokeStrings));
}
else
throw new Exception();
eventObject.EventInfo = eventInfo;
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
eventObject.Delegate = handler;
eventInfo.AddEventHandler(eventObject, handler);
return;
}
}
Task.Run(() =>
{
PowerShellScript.Execute(File.ReadAllText(filePath), new string[] {});
});
}
}
public class PowerShellEventObject
{
public EventInfo EventInfo { get; set; }
public Delegate Delegate { get; set; }
public string FilePath { get; set; }
public void Invoke()
{
Task.Run(() => { PowerShellScript.Execute(File.ReadAllText(FilePath), new string[] { }); });
}
public void InvokeEndFileEventMode(EndFileEventMode arg)
{
Task.Run(() =>
{
PowerShellScript.Execute(File.ReadAllText(FilePath), new string[] { arg.ToString() });
});
}
public void InvokeStrings(string[] args)
{
Task.Run(() => {
PowerShellScript.Execute(File.ReadAllText(FilePath), args);
});
}
}
}

View File

@@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("mpv.net")]
[assembly: AssemblyDescription("mpv/libmpv based player with pure mpv experience")]
[assembly: AssemblyDescription("libmpv based player with pure mpv experience")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mpv.net")]
[assembly: AssemblyCopyright("Copyright © 2017 stax76")]
[assembly: AssemblyCopyright("Copyright © 2019 stax76")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.2.0")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyVersion("1.8.0.0")]
[assembly: AssemblyFileVersion("1.8.0.0")]

97
mpv.net/Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,97 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace mpvnet.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvnet.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to # mpv.net key bindings, mouse bindings and context menu configuration
///
/// o script-message mpv.net open-files #menu: O ; Open Files...
/// _ ignore #menu: _ ; -
/// Space cycle pause #menu: Space, Enter ; Play/Pause
/// Enter cycle pause
/// s stop #menu: S ; Stop
/// _ ignore #menu: _ ; -
/// f cycle fullscreen #menu: F ; Toggle Fullscreen /// [rest of string was truncated]&quot;;.
/// </summary>
internal static string input_conf {
get {
return ResourceManager.GetString("input_conf", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to input-ar-delay = 500
///input-ar-rate = 20
///volume = 50
///hwdec = yes
///vo = direct3d
///keep-open = yes
///keep-open-pause = no
///osd-playing-msg = &apos;${filename}&apos;
///screenshot-directory = ~~desktop/.
/// </summary>
internal static string mpv_conf {
get {
return ResourceManager.GetString("mpv_conf", resourceCulture);
}
}
}
}

View File

@@ -119,6 +119,9 @@
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="input_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\input_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
<value>..\Resources\input.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="mpv_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\mpv.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
</root>

View File

@@ -12,7 +12,7 @@ namespace mpvnet.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

56
mpv.net/PythonScript.cs Normal file
View File

@@ -0,0 +1,56 @@
using System;
using System.Reflection;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using static mpvnet.StaticUsing;
using PyRT = IronPython.Runtime;
namespace mpvnet
{
public class PythonScript
{
ScriptEngine engine;
ScriptScope scope;
public PythonScript(string code)
{
try
{
engine = Python.CreateEngine();
scope = engine.CreateScope();
scope.ImportModule("clr");
engine.Execute("import clr", scope);
engine.Execute("clr.AddReference(\"mpvnet\")", scope);
engine.Execute("from mpvnet import *", scope);
engine.Execute(code, scope);
}
catch (Exception ex)
{
MsgError(ex.ToString());
}
}
}
public class PythonEventObject
{
public PyRT.PythonFunction PythonFunction { get; set; }
public EventInfo EventInfo { get; set; }
public Delegate Delegate { get; set; }
public void Invoke()
{
PyRT.Operations.PythonCalls.Call(PythonFunction);
}
public void InvokeEndFileEventMode(EndFileEventMode arg)
{
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
}
public void InvokeStrings(string[] arg)
{
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
}
}
}

View File

@@ -0,0 +1,137 @@
# mpv.net key bindings, mouse bindings and context menu configuration
o script-message mpv.net open-files #menu: O ; Open Files...
_ ignore #menu: _ ; -
Space cycle pause #menu: Space, Enter ; Play/Pause
Enter cycle pause
s stop #menu: S ; Stop
_ ignore #menu: _ ; -
f cycle fullscreen #menu: F ; Toggle Fullscreen
F11 playlist-prev #menu: F11 ; Navigate > Previous
F12 playlist-next #menu: F12 ; Navigate > Next
_ ignore #menu: _ ; Navigate > -
PGUP add chapter 1 #menu: Page Up ; Navigate > Next Chapter
PGDWN add chapter -1 #menu: Page Down ; Navigate > Previous Chapter
. frame-step #menu: . ; Seek > Next Frame
, frame-back-step #menu: , ; Seek > Previous Frame
_ ignore #menu: _ ; Seek > -
Right no-osd seek 7 #menu: Right ; Seek > 7 sec forward
Left no-osd seek -7 #menu: Left ; Seek > 7 sec backward
_ ignore #menu: _ ; Seek > -
Up no-osd seek 40 #menu: Up ; Seek > 40 sec forward
Down no-osd seek -40 #menu: Down ; Seek > 40 sec backward
_ ignore #menu: _ ; Seek > -
Ctrl+Right no-osd seek 300 #menu: Ctrl+Right ; Seek > 5 min forward
Ctrl+Left no-osd seek -300 #menu: Ctrl+Left ; Seek > 5 min backward
Ctrl++ add video-zoom 0.1 #menu: Ctrl++ ; Pan && Scan > Increase Size
Ctrl+- add video-zoom -0.1 #menu: Ctrl+- ; Pan && Scan > Decrease Size
_ ignore #menu: _ ; Pan && Scan > -
Ctrl+KP4 add video-pan-x -0.01 #menu: Ctrl+Numpad 4 ; Pan && Scan > Move Left
Ctrl+KP6 add video-pan-x 0.01 #menu: Ctrl+Numpad 6 ; Pan && Scan > Move Right
_ ignore #menu: _ ; Pan && Scan > -
Ctrl+KP8 add video-pan-y -0.01 #menu: Ctrl+Numpad 8 ; Pan && Scan > Move Up
Ctrl+KP2 add video-pan-y 0.01 #menu: Ctrl+Numpad 2 ; Pan && Scan > Move Down
_ ignore #menu: _ ; Pan && Scan > -
w add panscan -0.1 #menu: W ; Pan && Scan > Decrease Height
W add panscan +0.1 #menu: Shift+W ; Pan && Scan > Increase Height
_ ignore #menu: _ ; Pan && Scan > -
Ctrl+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 #menu: Ctrl+Backspace ; Pan && Scan > Reset
Ctrl+1 add contrast -1 #menu: Ctrl+1 ; Video > Decrease Contrast
Ctrl+2 add contrast 1 #menu: Ctrl+2 ; Video > Increase Contrast
_ ignore #menu: _ ; Video > -
Ctrl+3 add brightness -1 #menu: Ctrl+3 ; Video > Decrease Brightness
Ctrl+4 add brightness 1 #menu: Ctrl+4 ; Video > Increase Brightness
_ ignore #menu: _ ; Video > -
Ctrl+5 add gamma -1 #menu: Ctrl+5 ; Video > Decrease Gamma
Ctrl+6 add gamma 1 #menu: Ctrl+6 ; Video > Increase Gamma
_ ignore #menu: _ ; Video > -
Ctrl+7 add saturation -1 #menu: Ctrl+7 ; Video > Decrease Saturation
Ctrl+8 add saturation 1 #menu: Ctrl+8 ; Video > Increase Saturation
_ ignore #menu: _ ; Video > -
Ctrl+S async screenshot #menu: Ctrl+S ; Video > Take Screenshot
d cycle deinterlace #menu: D ; Video > Toggle Deinterlace
a cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" #menu: A ; Video > Cycle Aspect Ratio
KP7 cycle audio #menu: Keypad 7 ; Audio > Cycle/Next
_ ignore #menu: _ ; Audio > -
KP6 add audio-delay 0.100 #menu: Keypad 6 ; Audio > Delay +0.1
KP9 add audio-delay -0.100 #menu: Keypad 9 ; Audio > Delay -0.1
KP8 cycle sub #menu: Keypad 8 ; Subtitle > Cycle/Next
v cycle sub-visibility #menu: V ; Subtitle > Toggle Visibility
_ ignore #menu: _ ; Subtitle > -
z add sub-delay -0.1 #menu: Z ; Subtitle > Delay -0.1
Z add sub-delay +0.1 #menu: Shift+Z ; Subtitle > Delay +0.1
_ ignore #menu: _ ; Subtitle > -
r add sub-pos -1 #menu: R ; Subtitle > Move Up
R add sub-pos +1 #menu: Shift+R ; Subtitle > Move Down
_ ignore #menu: _ ; Subtitle > -
_ add sub-scale -0.1 #menu: _ ; Subtitle > Decrease Subtitle Font Size
_ add sub-scale +0.1 #menu: _ ; Subtitle > Increase Subtitle Font Size
+ add volume 10 #menu: + ; Volume > Up
- add volume -10 #menu: - ; Volume > Down
WHEEL_UP add volume 10
WHEEL_DOWN add volume -10
_ ignore #menu: _ ; Volume > -
m cycle mute #menu: M ; Volume > Mute
[ multiply speed 0.9 #menu: [ ; Speed > -10%
] multiply speed 1.1 #menu: ] ; Speed > +10%
_ ignore #menu: _ ; Speed > -
{ multiply speed 0.5 #menu: { ; Speed > Half
} multiply speed 2.0 #menu: } ; Speed > Double
_ ignore #menu: _ ; Speed > -
BS set speed 1 #menu: Backspace ; Speed > Reset
KP0 script-message rate-file 0 #menu: Keypad 0 ; Addons > Rating > 0stars
KP1 script-message rate-file 1 #menu: Keypad 1 ; Addons > Rating > 1stars
KP2 script-message rate-file 2 #menu: Keypad 2 ; Addons > Rating > 2stars
KP3 script-message rate-file 3 #menu: Keypad 3 ; Addons > Rating > 3stars
KP4 script-message rate-file 4 #menu: Keypad 4 ; Addons > Rating > 4stars
KP5 script-message rate-file 5 #menu: Keypad 5 ; Addons > Rating > 5stars
_ script-message mpv.net set-setting hwdec yes #menu: _ ; Settings > Hardware Decoding > Enable
_ script-message mpv.net set-setting hwdec no #menu: _ ; Settings > Hardware Decoding > Disable
p script-message mpv.net show-prefs #menu: P ; Settings > Show mpv config file
e script-message mpv.net show-conf-editor #menu: E ; Settings > Show mpv config editor
k script-message mpv.net show-keys #menu: K ; Settings > Show Keys
c script-message mpv.net open-config-folder #menu: C ; Settings > Open Config Folder
i script-message mpv.net show-info #menu: I ; Tools | Info
t script-binding stats/display-stats #menu: T ; Tools > Show Statistics
T script-binding stats/display-stats-toggle #menu: Shift+T ; Tools > Toggle Statistics
_ ignore #menu: _ ; Tools > -
h script-message mpv.net history #menu: H ; Tools > Show History
l ab-loop #menu: L ; Tools > Set/clear A-B loop points
L cycle-values loop-file "inf" "no" #menu: Shift+L ; Tools > Toggle Infinite Looping
DEL script-binding osc/visibility #menu: Delete ; Tools > Toggle OSC Visibility
Ctrl+H cycle-values hwdec "auto" "no" #menu: Ctrl+H ; Tools > Cycle Hardware Decoding
F8 show-text ${playlist} 5000 #menu: F8 ; Tools > Show Playlist
F9 show-text ${track-list} 5000 #menu: F9 ; Tools > Show Audio/Video/Subtitle List
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: _ ; Help > Show mpv manual
_ script-message mpv.net shell-execute https://github.com/mpv-player/mpv/blob/master/etc/input.conf #menu: _ ; Help > Show mpv default keys
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt #menu: _ ; Help > Show mpv.net default keys
_ script-message mpv.net shell-execute https://github.com/stax76/mpvnet #menu: _ ; Help > Show mpv.net web site
_ ignore #menu: _ ; -
Esc quit #menu: Escape ; Exit
Q quit-watch-later #menu: Shift+Q ; Exit Watch Later
> playlist-next
< playlist-prev
POWER quit
PLAY cycle pause
PAUSE cycle pause
PLAYPAUSE cycle pause
STOP quit
FORWARD seek 60
REWIND seek -60
VOLUME_UP add volume 2
VOLUME_DOWN add volume -2
MUTE cycle mute

View File

@@ -0,0 +1,12 @@
# mpv manual: https://mpv.io/manual/master/
# mpv.net mpv.conf defaults: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt
input-ar-delay = 500
input-ar-rate = 20
volume = 50
hwdec = yes
vo = direct3d
keep-open = yes
keep-open-pause = no
osd-playing-msg = ${filename}
screenshot-directory = ~~desktop/

120
mpv.net/StringExtensions.cs Normal file
View File

@@ -0,0 +1,120 @@
using System;
using System.Linq;
using System.IO;
public static class StringExtensions
{
public static string ExtFull(this string filepath)
{
return Ext(filepath, true);
}
public static string Ext(this string filepath)
{
return Ext(filepath, false);
}
public static string Ext(this string filepath, bool dot)
{
if (string.IsNullOrEmpty(filepath))
return "";
var chars = filepath.ToCharArray();
for (var x = filepath.Length - 1; x >= 0; x += -1)
{
if (chars[x] == Path.DirectorySeparatorChar)
return "";
if (chars[x] == '.')
return filepath.Substring(x + (dot ? 0 : 1)).ToLower();
}
return "";
}
public static string Left(this string value, int index)
{
if (string.IsNullOrEmpty(value) || index < 0)
return "";
if (index > value.Length)
return value;
return value.Substring(0, index);
}
public static string Left(this string value, string start)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
return "";
if (!value.Contains(start))
return "";
return value.Substring(0, value.IndexOf(start));
}
public static string LeftLast(this string value, string start)
{
if (!value.Contains(start))
return "";
return value.Substring(0, value.LastIndexOf(start));
}
public static string Right(this string value, string start)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
return "";
if (!value.Contains(start))
return "";
return value.Substring(value.IndexOf(start) + start.Length);
}
public static string RightLast(this string value, string start)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
return "";
if (!value.Contains(start))
return "";
return value.Substring(value.LastIndexOf(start) + start.Length);
}
public static string[] SplitNoEmpty(this string value, params string[] delimiters)
{
return value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
}
public static string[] SplitKeepEmpty(this string value, params string[] delimiters)
{
return value.Split(delimiters, StringSplitOptions.None);
}
public static string[] SplitNoEmptyAndWhiteSpace(this string value, params string[] delimiters)
{
if (string.IsNullOrEmpty(value))
return null;
var a = SplitNoEmpty(value, delimiters);
for (var i = 0; i <= a.Length - 1; i++)
a[i] = a[i].Trim();
var l = a.ToList();
while (l.Contains(""))
l.Remove("");
return l.ToArray();
}
public static string[] SplitLinesNoEmpty(this string value)
{
return SplitNoEmpty(value, Environment.NewLine);
}
}

View File

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

View File

@@ -27,7 +27,10 @@ namespace mpvnet
public static extern int mpv_set_option_string(IntPtr mpvHandle, byte[] name, byte[] value);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref IntPtr data);
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, out IntPtr data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref byte[] data);
@@ -102,7 +105,8 @@ namespace mpvnet
MPV_EVENT_PLAYBACK_RESTART = 21,
MPV_EVENT_PROPERTY_CHANGE = 22,
MPV_EVENT_CHAPTER_CHANGE = 23,
MPV_EVENT_QUEUE_OVERFLOW = 24
MPV_EVENT_QUEUE_OVERFLOW = 24,
MPV_EVENT_HOOK = 25
}
public enum mpv_format
@@ -131,7 +135,16 @@ namespace mpvnet
MPV_LOG_LEVEL_TRACE = 70,
}
[StructLayout(LayoutKind.Sequential)]
public enum mpv_end_file_reason
{
MPV_END_FILE_REASON_EOF = 0,
MPV_END_FILE_REASON_STOP = 2,
MPV_END_FILE_REASON_QUIT = 3,
MPV_END_FILE_REASON_ERROR = 4,
MPV_END_FILE_REASON_REDIRECT = 5
}
[StructLayout(LayoutKind.Sequential)]
public struct mpv_event_log_message
{
public string prefix;
@@ -159,9 +172,16 @@ namespace mpvnet
[StructLayout(LayoutKind.Sequential)]
public struct mpv_event_property
{
[MarshalAs(UnmanagedType.LPUTF8Str)] public string name;
public string name;
public mpv_format format;
public IntPtr data;
}
[StructLayout(LayoutKind.Sequential)]
public struct mpv_event_end_file
{
public int reason;
public int error;
}
}
}

534
mpv.net/mp.cs Normal file
View File

@@ -0,0 +1,534 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static mpvnet.libmpv;
using static mpvnet.Native;
using static mpvnet.StaticUsing;
using PyRT = IronPython.Runtime;
namespace mpvnet
{
public delegate void MpvBoolPropChangeHandler(string propName, bool value);
public class mp
{
public static event Action VideoSizeChanged;
// Lua/JS evens libmpv events
// MPV_EVENT_NONE
public static event Action Shutdown; // shutdown MPV_EVENT_SHUTDOWN
public static event Action LogMessage; // log-message MPV_EVENT_LOG_MESSAGE
public static event Action GetPropertyReply; // get-property-reply MPV_EVENT_GET_PROPERTY_REPLY
public static event Action SetPropertyReply; // set-property-reply MPV_EVENT_SET_PROPERTY_REPLY
public static event Action CommandReply; // command-reply MPV_EVENT_COMMAND_REPLY
public static event Action StartFile; // start-file MPV_EVENT_START_FILE
public static event Action<EndFileEventMode> EndFile; // end-file MPV_EVENT_END_FILE
public static event Action FileLoaded; // file-loaded MPV_EVENT_FILE_LOADED
public static event Action TracksChanged; // MPV_EVENT_TRACKS_CHANGED
public static event Action TrackSwitched; // MPV_EVENT_TRACK_SWITCHED
public static event Action Idle; // idle MPV_EVENT_IDLE
public static event Action Pause; // MPV_EVENT_PAUSE
public static event Action Unpause; // MPV_EVENT_UNPAUSE
public static event Action Tick; // tick MPV_EVENT_TICK
public static event Action ScriptInputDispatch; // MPV_EVENT_SCRIPT_INPUT_DISPATCH
public static event Action<string[]> ClientMessage; // client-message MPV_EVENT_CLIENT_MESSAGE
public static event Action VideoReconfig; // video-reconfig MPV_EVENT_VIDEO_RECONFIG
public static event Action AudioReconfig; // audio-reconfig MPV_EVENT_AUDIO_RECONFIG
public static event Action MetadataUpdate; // MPV_EVENT_METADATA_UPDATE
public static event Action Seek; // seek MPV_EVENT_SEEK
public static event Action PlaybackRestart; // playback-restart MPV_EVENT_PLAYBACK_RESTART
// MPV_EVENT_PROPERTY_CHANGE
public static event Action ChapterChange; // MPV_EVENT_CHAPTER_CHANGE
public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW
public static event Action Hook; // MPV_EVENT_HOOK
public static IntPtr MpvHandle;
public static IntPtr MpvWindowHandle;
public static Addon Addon;
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions = new List<KeyValuePair<string, Action<bool>>>();
public static Size VideoSize = new Size(1920, 1080);
public static string mpvConfFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
public static string InputConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\input.conf";
public static string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
public static List<PythonScript> PythonScripts { get; } = new List<PythonScript>();
public static AutoResetEvent AutoResetEvent = new AutoResetEvent(false);
private static Dictionary<string, string> _mpvConf;
public static Dictionary<string, string> mpvConf {
get {
if (_mpvConf == null)
{
_mpvConf = new Dictionary<string, string>();
if (File.Exists(mpvConfPath))
foreach (var i in File.ReadAllLines(mpvConfPath))
if (i.Contains("=") && ! i.StartsWith("#"))
_mpvConf[i.Left("=").Trim()] = i.Right("=").Trim();
}
return _mpvConf;
}
}
public static void Init()
{
if (!Directory.Exists(mp.mpvConfFolderPath))
Directory.CreateDirectory(mp.mpvConfFolderPath);
if (!File.Exists(mp.mpvConfPath))
File.WriteAllText(mp.mpvConfPath, Properties.Resources.mpv_conf);
if (!File.Exists(mp.InputConfPath))
File.WriteAllText(mp.InputConfPath, Properties.Resources.input_conf);
LoadLibrary("mpv-1.dll");
MpvHandle = mpv_create();
set_property_string("input-default-bindings", "yes");
set_property_string("osc", "yes");
set_property_string("config", "yes");
set_property_string("wid", MainForm.Hwnd.ToString());
set_property_string("force-window", "yes");
set_property_string("input-media-keys", "yes");
mpv_initialize(MpvHandle);
ProcessCommandLine();
Task.Run(() => { LoadScripts(); });
Task.Run(() => { Addon = new Addon(); });
Task.Run(() => { EventLoop(); });
}
public static void LoadScripts()
{
string[] jsLua = { ".lua", ".js" };
string[] startupScripts = Directory.GetFiles(Application.StartupPath + "\\Scripts");
foreach (var scriptPath in startupScripts)
if (jsLua.Contains(Path.GetExtension(scriptPath).ToLower()))
mp.commandv("load-script", $"{scriptPath}");
foreach (var scriptPath in startupScripts)
if (Path.GetExtension(scriptPath) == ".py")
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
foreach (var scriptPath in startupScripts)
if (Path.GetExtension(scriptPath) == ".ps1")
PowerShellScript.Init(scriptPath);
foreach (var scriptPath in Directory.GetFiles(mp.mpvConfFolderPath + "Scripts"))
if (Path.GetExtension(scriptPath) == ".py")
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
else if (Path.GetExtension(scriptPath) == ".ps1")
PowerShellScript.Init(scriptPath);
}
public static void EventLoop()
{
while (true)
{
IntPtr ptr = mpv_wait_event(MpvHandle, -1);
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event));
if (MpvWindowHandle == IntPtr.Zero)
MpvWindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
//Debug.WriteLine(evt.event_id.ToString());
switch (evt.event_id)
{
case mpv_event_id.MPV_EVENT_SHUTDOWN:
Shutdown?.Invoke();
AutoResetEvent.Set();
return;
case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
LogMessage?.Invoke();
break;
case mpv_event_id.MPV_EVENT_GET_PROPERTY_REPLY:
GetPropertyReply?.Invoke();
break;
case mpv_event_id.MPV_EVENT_SET_PROPERTY_REPLY:
SetPropertyReply?.Invoke();
break;
case mpv_event_id.MPV_EVENT_COMMAND_REPLY:
CommandReply?.Invoke();
break;
case mpv_event_id.MPV_EVENT_START_FILE:
StartFile?.Invoke();
break;
case mpv_event_id.MPV_EVENT_END_FILE:
var end_fileData = (mpv_event_end_file)Marshal.PtrToStructure(evt.data, typeof(mpv_event_end_file));
EndFile?.Invoke((EndFileEventMode)end_fileData.reason);
break;
case mpv_event_id.MPV_EVENT_FILE_LOADED:
FileLoaded?.Invoke();
LoadFolder();
break;
case mpv_event_id.MPV_EVENT_TRACKS_CHANGED:
TracksChanged?.Invoke();
break;
case mpv_event_id.MPV_EVENT_TRACK_SWITCHED:
TrackSwitched?.Invoke();
break;
case mpv_event_id.MPV_EVENT_IDLE:
Idle?.Invoke();
break;
case mpv_event_id.MPV_EVENT_PAUSE:
Pause?.Invoke();
break;
case mpv_event_id.MPV_EVENT_UNPAUSE:
Unpause?.Invoke();
break;
case mpv_event_id.MPV_EVENT_TICK:
Tick?.Invoke();
break;
case mpv_event_id.MPV_EVENT_SCRIPT_INPUT_DISPATCH:
ScriptInputDispatch?.Invoke();
break;
case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE:
if (ClientMessage != null)
{
var client_messageData = (mpv_event_client_message)Marshal.PtrToStructure(evt.data, typeof(mpv_event_client_message));
var args = NativeUtf8StrArray2ManagedStrArray(client_messageData.args, client_messageData.num_args);
if (args != null && args.Length > 1 && args[0] == "mpv.net")
foreach (var i in mpvnet.Command.Commands)
if (args[1] == i.Name)
try
{
i.Action(args.Skip(2).ToArray());
}
catch (Exception ex)
{
MsgError(ex.GetType().Name + "\r\n\r\n" + ex.ToString());
}
ClientMessage?.Invoke(args);
}
break;
case mpv_event_id.MPV_EVENT_VIDEO_RECONFIG:
VideoReconfig?.Invoke();
break;
case mpv_event_id.MPV_EVENT_AUDIO_RECONFIG:
AudioReconfig?.Invoke();
break;
case mpv_event_id.MPV_EVENT_METADATA_UPDATE:
MetadataUpdate?.Invoke();
break;
case mpv_event_id.MPV_EVENT_SEEK:
Seek?.Invoke();
break;
case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE:
var event_propertyData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property));
if (event_propertyData.format == mpv_format.MPV_FORMAT_FLAG)
foreach (var i in BoolPropChangeActions)
if (i.Key== event_propertyData.name)
i.Value.Invoke(Marshal.PtrToStructure<int>(event_propertyData.data) == 1);
break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke();
Size s = new Size(get_property_int("dwidth"), get_property_int("dheight"));
if (VideoSize != s && s != Size.Empty)
{
VideoSize = s;
VideoSizeChanged?.Invoke();
}
break;
case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE:
ChapterChange?.Invoke();
break;
case mpv_event_id.MPV_EVENT_QUEUE_OVERFLOW:
QueueOverflow?.Invoke();
break;
case mpv_event_id.MPV_EVENT_HOOK:
Hook?.Invoke();
break;
}
}
}
private static List<PythonEventObject> PythonEventObjects = new List<PythonEventObject>();
public static void register_event(string name, PyRT.PythonFunction pyFunc)
{
foreach (var eventInfo in typeof(mp).GetEvents())
{
if (eventInfo.Name.ToLower() == name.Replace("-", ""))
{
PythonEventObject eventObject = new PythonEventObject();
PythonEventObjects.Add(eventObject);
eventObject.PythonFunction = pyFunc;
MethodInfo mi;
if (eventInfo.EventHandlerType == typeof(Action))
{
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.Invoke));
}
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
{
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.InvokeEndFileEventMode));
}
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
{
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.InvokeStrings));
}
else
throw new Exception();
eventObject.EventInfo = eventInfo;
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
eventObject.Delegate = handler;
eventInfo.AddEventHandler(eventObject, handler);
break;
}
}
}
public static void unregister_event(PyRT.PythonFunction pyFunc)
{
foreach (var eventObjects in PythonEventObjects)
if (eventObjects.PythonFunction == pyFunc)
eventObjects.EventInfo.RemoveEventHandler(eventObjects, eventObjects.Delegate);
}
public static void commandv(params string[] args)
{
if (MpvHandle == IntPtr.Zero)
return;
IntPtr mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out IntPtr[] byteArrayPointers);
int err = mpv_command(MpvHandle, mainPtr);
if (err < 0)
throw new Exception($"{(mpv_error)err}");
foreach (var ptr in byteArrayPointers)
Marshal.FreeHGlobal(ptr);
Marshal.FreeHGlobal(mainPtr);
}
public static void command_string(string command, bool throwException = false)
{
if (MpvHandle == IntPtr.Zero)
return;
int err = mpv_command_string(MpvHandle, command);
if (err < 0 && throwException)
throw new Exception($"{(mpv_error)err}\r\n\r\n" + command);
}
public static void set_property_string(string name, string value, bool throwOnException = false)
{
byte[] bytes = GetUtf8Bytes(value);
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static string get_property_string(string name, bool throwOnException = false)
{
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
var ret = StringFromNativeUtf8(lpBuffer);
mpv_free(lpBuffer);
return ret;
}
public static int get_property_int(string name, bool throwOnException = false)
{
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
else
return lpBuffer.ToInt32();
}
public static double get_property_number(string name, bool throwOnException = false)
{
double val = 0;
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
else
return val;
}
public static bool get_property_bool(string name, bool throwOnException = false)
{
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_FLAG, out IntPtr lpBuffer);
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
else
return lpBuffer.ToInt32() == 1;
}
public static void set_property_int(string name, int value, bool throwOnException = false)
{
Int64 val = value;
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static void observe_property_bool(string name, Action<bool> action)
{
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
else
BoolPropChangeActions.Add(new KeyValuePair<string, Action<bool>>(name, action));
}
public static void unobserve_property_bool(string name, Action<bool> action)
{
foreach (var i in BoolPropChangeActions.ToArray())
if (i.Value == action)
BoolPropChangeActions.Remove(i);
int err = mpv_unobserve_property(MpvHandle, (ulong)action.GetHashCode());
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
}
protected static void ProcessCommandLine()
{
var args = Environment.GetCommandLineArgs().Skip(1);
foreach (string i in args)
if (!i.StartsWith("--") && File.Exists(i))
mp.commandv("loadfile", i, "append");
mp.set_property_string("playlist-pos", "0");
foreach (string i in args)
{
if (i.StartsWith("--"))
{
if (i.Contains("="))
{
string left = i.Substring(2, i.IndexOf("=") - 2);
string right = i.Substring(left.Length + 3);
mp.set_property_string(left, right);
}
else
mp.set_property_string(i.Substring(2), "yes");
}
}
}
public static void LoadFiles(string[] files)
{
int count = mp.get_property_int("playlist-count");
foreach (string file in files)
mp.commandv("loadfile", file, "append");
mp.set_property_int("playlist-pos", count);
for (int i = 0; i < count; i++)
mp.commandv("playlist-remove", "0");
mp.LoadFolder();
}
private static bool WasFolderLoaded;
public static void LoadFolder()
{
if (WasFolderLoaded)
return;
if (get_property_int("playlist-count") == 1)
{
string[] types = "264 265 3gp aac ac3 avc avi avs bmp divx dts dtshd dtshr dtsma eac3 evo flac flv h264 h265 hevc hvc jpg jpeg m2t m2ts m2v m4a m4v mka mkv mlp mov mp2 mp3 mp4 mpa mpeg mpg mpv mts ogg ogm opus pcm png pva raw rmvb thd thd+ac3 true-hd truehd ts vdr vob vpy w64 wav webm wmv y4m".Split(' ');
string path = get_property_string("path");
List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
files = files.Where((file) => types.Contains(file.Ext())).ToList();
files.Sort(new StringLogicalComparer());
int index = files.IndexOf(path);
files.Remove(path);
foreach (string i in files)
commandv("loadfile", i, "append");
if (index > 0)
commandv("playlist-move", "0", (index + 1).ToString());
}
WasFolderLoaded = true;
}
public static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
{
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
byteArrayPointers = new IntPtr[numberOfStrings];
IntPtr rootPointer = Marshal.AllocCoTaskMem(IntPtr.Size * numberOfStrings);
for (int index = 0; index < arr.Length; index++)
{
var bytes = GetUtf8Bytes(arr[index]);
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
byteArrayPointers[index] = unmanagedPointer;
}
Marshal.Copy(byteArrayPointers, 0, rootPointer, numberOfStrings);
return rootPointer;
}
public static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, int StringCount)
{
IntPtr[] pIntPtrArray = new IntPtr[StringCount];
string[] ManagedStringArray = new string[StringCount];
Marshal.Copy(pUnmanagedStringArray, pIntPtrArray, 0, StringCount);
for (int i = 0; i < StringCount; i++)
ManagedStringArray[i] = StringFromNativeUtf8(pIntPtrArray[i]);
return ManagedStringArray;
}
public static string StringFromNativeUtf8(IntPtr nativeUtf8)
{
int len = 0;
while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
byte[] buffer = new byte[len];
Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
}
public enum EndFileEventMode
{
Eof,
Stop,
Quit,
Error,
Redirect,
Unknown
}
}

View File

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 264 KiB

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>mpvnet</RootNamespace>
<AssemblyName>mpvnet</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
@@ -24,6 +24,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -94,17 +95,54 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="IKVM.Reflection, Version=7.2.4630.5, Culture=neutral, PublicKeyToken=13235d27fcbfff58, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\IKVM.Reflection.dll</HintPath>
</Reference>
<Reference Include="IronPython, Version=2.7.9.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\IronPython.dll</HintPath>
</Reference>
<Reference Include="IronPython.Modules, Version=2.7.9.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\IronPython.Modules.dll</HintPath>
</Reference>
<Reference Include="IronPythonAddon">
<HintPath>IronPython\IronPythonAddon.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Dynamic, Version=1.2.2.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\Microsoft.Dynamic.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Scripting, Version=1.2.2.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>IronPython\Microsoft.Scripting.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Addon.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="MediaInfo.cs" />
<Compile Include="Menu.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="PowerShellScript.cs" />
<Compile Include="PythonScript.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="libmpv.cs" />
<Compile Include="MainForm.cs">
@@ -114,7 +152,7 @@
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Misc.cs" />
<Compile Include="mpv.cs" />
<Compile Include="mp.cs" />
<Compile Include="Command.cs" />
<Compile Include="Native.cs" />
<Compile Include="NativeHelp.cs" />
@@ -123,18 +161,15 @@
<Compile Include="UI.cs" />
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.manifest" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
@@ -144,6 +179,7 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Content Include="Resources\mpv.conf.txt" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
@@ -151,13 +187,7 @@
<ItemGroup>
<Content Include="mpv.ico" />
<Content Include="screenshot.jpg" />
<None Include="Resources\input_conf.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\vbnet\vbnet.vbproj">
<Project>{af1b21c5-28fc-4d47-ad0b-54f6a38391a6}</Project>
<Name>vbnet</Name>
</ProjectReference>
<Content Include="Resources\input.conf.txt" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

4
mpv.net/packages.config Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.PowerShell.5.ReferenceAssemblies" version="1.1.0" targetFramework="net472" />
</packages>

View File

Before

Width:  |  Height:  |  Size: 497 KiB

After

Width:  |  Height:  |  Size: 497 KiB

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>

View File

@@ -0,0 +1,9 @@
<Application x:Class="DynamicGUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DynamicGUI"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,8 @@
using System.Windows;
namespace DynamicGUI
{
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,88 @@
[[settings]]
name = "volume"
default = ""
help = "volume=<integer> Set the startup volume. 0 means silence, 100 means no volume reduction or amplification. Negative values can be passed for compatibility, but are treated as 0. Since mpv 0.18.1, this always controls the internal mixer (aka \"softvol\")."
[[settings]]
name = "screen"
default = ""
help = "screen=<default|0-32> In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on. Default: default."
[[settings]]
name = "osd-playing-msg"
default = ""
width = 300
help = "osd-playing-msg=<value> Show a message on OSD when playback starts. The string is expanded for properties, e.g. --osd-playing-msg='file: ${filename}' will show the message file: followed by a space and the currently played filename."
helpurl = "https://mpv.io/manual/master/#property-expansion"
[[settings]]
name = "fullscreen"
alias = "fs"
default = "no"
help = "fullscreen=<yes|no>, fs=<yes|no> Start the player in fullscreen mode. Default: no."
options = [{ name = "yes" }, { name = "no", text = "no (Default)" }]
[[settings]]
name = "hwdec"
default = "no"
helpurl = "https://mpv.io/manual/master/#options-hwdec"
help = "hwdec=<mode> 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."
options = [{ name = "no", text = "no (Default)", help = "always use software decoding (Default)" },
{ name = "auto", help = "enable best hw decoder (see below)" },
{ name = "yes", help = "exactly the same as auto" },
{ name = "auto-copy", help = "enable best hw decoder with copy-back (see below)" },
{ name = "dxva2", help = "requires --vo=gpu with --gpu-context=d3d11, --gpu-context=angle or --gpu-context=dxinterop (Windows only)" },
{ name = "dxva2-copy", help = "copies video back to system RAM (Windows only)" },
{ name = "d3d11va", help = "requires --vo=gpu with --gpu-context=d3d11 or --gpu-context=angle (Windows 8+ only)" },
{ name = "d3d11va-copy", help = "copies video back to system RAM (Windows 8+ only)" },
{ name = "cuda", help = "requires --vo=gpu (Any platform CUDA is available)" },
{ name = "cuda-copy", help = "copies video back to system RAM (Any platform CUDA is available)" },
{ name = "nvdec", help = "requires --vo=gpu (Any platform CUDA is available)" },
{ name = "nvdec-copy", help = "copies video back to system RAM (Any platform CUDA is available)" },
{ name = "crystalhd", help = "copies video back to system RAM (Any platform supported by hardware)" },
{ name = "rkmpp", help = "requires --vo=gpu (some RockChip devices only)" }]
[[settings]]
name = "vo"
default = "gpu"
helpurl = "https://mpv.io/manual/master/#video-output-drivers-vo"
help = "gpu=<mode> Video output drivers to be used. Default = gpu."
options = [{ name = "direct3d", help = "Video output driver that uses the Direct3D interface" },
{ name = "gpu", text = "gpu (Default)", help = "General purpose, customizable, GPU-accelerated video output driver. It supports extended scaling methods, dithering, color management, custom shaders, HDR, and more. (Default)" }]
[[settings]]
name = "keep-open-pause"
default = "yes"
help = "keep-open-pause=<yes|no> If set to no, instead of pausing when --keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again. Default: yes."
options = [{ name = "yes", text = "yes (Default)" }, { name = "no" }]
[[settings]]
name = "keep-open"
default = "no"
help = "keep-open=<yes|no|always> Do not terminate when playing or seeking beyond the end of the file, and there is not next file to be played (and --loop is not used). Instead, pause the player. When trying to seek beyond end of the file, the player will attempt to seek to the last frame.\n\nNormally, this will act like set pause yes on EOF, unless the --keep-open-pause=no option is set."
options = [{ name = "no", text = "no (Default)", help = "If the current file ends, go to the next file or terminate. (Default.)" },
{ name = "yes", help = "Don't terminate if the current file is the last playlist entry. Equivalent to --keep-open without arguments."},
{ name = "always", help = "Like yes, but also applies to files before the last playlist entry. This means playback will never automatically advance to the next file."}]
[[settings]]
name = "loop-file"
alias = "loop"
default = ""
help = "loop-file=<N|inf|no>, loop=<N|inf|no> Loop a single file N times. inf means forever, no means normal playback. For compatibility, --loop-file and --loop-file=yes are also accepted, and are the same as --loop-file=inf.\n\nThe difference to --loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file.\n\n--loop is an alias for this option."
[[settings]]
name = "screenshot-directory"
default = ""
width = 500
folder = true
help = "screenshot-directory=<value> Store screenshots in this directory. This path is joined with the filename generated by --screenshot-template. If the template filename is already absolute, the directory is ignored.\n\nIf the directory does not exist, it is created on the first screenshot. If it is not a directory, an error is generated when trying to write a screenshot.\n\nThis option is not set by default, and thus will write screenshots to the directory from which mpv was started. In pseudo-gui mode (see PSEUDO GUI MODE), this is set to the desktop."
[[settings]]
name = "input-ar-delay"
default = ""
help = "input-ar-delay=<integer> Delay in milliseconds before we start to autorepeat a key (0 to disable)."
[[settings]]
name = "input-ar-rate"
default = ""
help = "input-ar-rate=<integer> Number of key presses to generate per second on autorepeat."

View File

@@ -0,0 +1,107 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Tommy;
namespace DynamicGUI
{
public class Settings
{
public static List<SettingBase> LoadSettings(string filepath)
{
TomlTable table;
using (StreamReader reader = new StreamReader(File.OpenRead(filepath)))
table = TOML.Parse(reader);
List<SettingBase> settingsList = new List<SettingBase>();
foreach (TomlTable setting in table["settings"])
{
SettingBase baseSetting = null;
if (setting.HasKey("options"))
{
OptionSetting optionSetting = new OptionSetting();
baseSetting = optionSetting;
optionSetting.Default = setting["default"];
optionSetting.Value = optionSetting.Default;
foreach (TomlTable option in setting["options"])
{
var opt = new OptionSettingOption();
opt.Name = option["name"];
if (option.HasKey("help"))
opt.Help = option["help"];
if (option.HasKey("text"))
opt.Text = option["text"];
opt.OptionSetting = optionSetting;
optionSetting.Options.Add(opt);
}
}
else if (setting["default"].IsString)
{
StringSetting stringSetting = new StringSetting();
baseSetting = stringSetting;
stringSetting.Default = setting["default"];
if (setting.HasKey("folder")) stringSetting.IsFolder = true;
}
baseSetting.Name = setting["name"];
if (setting.HasKey("help")) baseSetting.Help = setting["help"];
if (setting.HasKey("alias")) baseSetting.Alias = setting["alias"];
if (setting.HasKey("width")) baseSetting.Width = setting["width"];
settingsList.Add(baseSetting);
}
return settingsList;
}
}
public abstract class SettingBase
{
public string Name { get; set; }
public string Alias { get; set; }
public string Help { get; set; }
public string HelpURL { get; set; }
public int Width { get; set; }
}
public class StringSetting : SettingBase
{
public string Default { get; set; }
public string Value { get; set; }
public bool IsFolder { get; set; }
}
public class OptionSetting : SettingBase
{
public string Default { get; set; }
public string Value { get; set; }
public List<OptionSettingOption> Options = new List<OptionSettingOption>();
}
public class OptionSettingOption
{
public string Name { get; set; }
public string Help { get; set; }
public OptionSetting OptionSetting { get; set; }
private string _Text;
public string Text
{
get => string.IsNullOrEmpty(_Text) ? Name : _Text;
set => _Text = value;
}
//private bool _IsChecked;
public bool IsChecked
{
get => OptionSetting.Value == Name ;
set {
if (value)
OptionSetting.Value = Name;
}
}
}
}

View File

@@ -0,0 +1,7 @@
namespace DynamicGUI
{
interface ISearch
{
bool Contains(string searchString);
}
}

View File

@@ -0,0 +1,25 @@
<UserControl x:Name="OptionSettingControl1" x:Class="DynamicGUI.OptionSettingControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DynamicGUI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="20,0">
<WrapPanel Orientation="Vertical">
<TextBox x:Name="TitleTextBox" FontSize="20" Margin="0,0,0,10" BorderThickness="0" IsReadOnly="True"></TextBox>
<ItemsControl x:Name="ItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Vertical">
<RadioButton x:Name="RadioButton" VerticalContentAlignment="Center" IsChecked="{Binding IsChecked}" GroupName="{Binding OptionSetting.Name}" Content="{Binding Text}" FontSize="16" FontWeight="Normal" VerticalAlignment="Top"></RadioButton>
<TextBox x:Name="ItemHelpTextBox" TextWrapping="WrapWithOverflow" Text="{Binding Help}" Margin="10,0,0,0" BorderThickness="0" IsReadOnly="True" Padding="7,0,0,0" MinHeight="0"></TextBox>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" Margin="0,10" BorderThickness="0" IsReadOnly="True" Padding="0"></TextBox>
</WrapPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,36 @@
using DynamicGUI;
using System.Windows.Controls;
namespace DynamicGUI
{
public partial class OptionSettingControl : UserControl, ISearch
{
private OptionSetting OptionSetting;
public OptionSettingControl(OptionSetting optionSetting)
{
OptionSetting = optionSetting;
InitializeComponent();
TitleTextBox.Text = optionSetting.Name;
HelpTextBox.Text = optionSetting.Help;
ItemsControl.ItemsSource = optionSetting.Options;
}
private string _SearchableText;
public string SearchableText {
get {
if (_SearchableText is null)
{
_SearchableText = TitleTextBox.Text + HelpTextBox.Text;
foreach (var i in OptionSetting.Options)
_SearchableText += i.Text + i.Help + i.Name;
_SearchableText = _SearchableText.ToLower();
}
return _SearchableText;
}
}
public bool Contains(string searchString) => SearchableText.Contains(searchString.ToLower());
}
}

View File

@@ -0,0 +1,24 @@
<UserControl x:Name="StringSettingControl1" x:Class="DynamicGUI.StringSettingControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DynamicGUI"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800" >
<Grid Margin="20,0">
<WrapPanel Orientation="Vertical">
<TextBox x:Name="TitleTextBox" FontSize="20" Margin="0,0,0,10" BorderThickness="0" IsReadOnly="True"></TextBox>
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox x:Name="ValueTextBox" Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="150" HorizontalAlignment="Left" Height="20"/>
<Button x:Name="Button" Height="20" Grid.Column="1" Visibility="{Binding Path=Text, ElementName=StringSettingControl1}" Margin="5,0,0,0" Width="20" Click="Button_Click">...</Button>
</Grid>
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" Margin="0,0,0,10" BorderThickness="0" IsReadOnly="True"></TextBox>
</WrapPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,54 @@
using System.Windows;
using System.Windows.Controls;
namespace DynamicGUI
{
public partial class StringSettingControl : UserControl, ISearch
{
private StringSetting StringSetting;
public StringSettingControl(StringSetting stringSetting)
{
StringSetting = stringSetting;
InitializeComponent();
TitleTextBox.Text = stringSetting.Name;
HelpTextBox.Text = stringSetting.Help;
ValueTextBox.Text = stringSetting.Value;
if (stringSetting.Width > 0)
ValueTextBox.Width = stringSetting.Width;
if (!StringSetting.IsFolder)
Button.Visibility = Visibility.Hidden;
}
private string _SearchableText;
public string SearchableText {
get {
if (_SearchableText is null)
_SearchableText = (TitleTextBox.Text + HelpTextBox.Text +ValueTextBox.Text).ToLower();
return _SearchableText;
}
}
public bool Contains(string searchString) => SearchableText.Contains(searchString.ToLower());
public string Text
{
get => StringSetting.Value;
set => StringSetting.Value = value;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
using (var d = new System.Windows.Forms.FolderBrowserDialog())
{
d.Description = "Choose a folder.";
d.SelectedPath = ValueTextBox.Text;
if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK)
ValueTextBox.Text = d.SelectedPath;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
<Window xmlns:DynamicGUI="clr-namespace:DynamicGUI" x:Name="MainWindow1" x:Class="DynamicGUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DynamicGUI"
mc:Ignorable="d"
Height="500" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="White" Width="300" Margin="0,0,0,10">
<TextBlock Margin="5,2" MinWidth="50" Text="Search..." Foreground="LightSteelBlue" IsHitTestVisible="False" />
<TextBox MinWidth="50" Name="SearchTextBox" Background="Transparent" TextChanged="SearchTextBox_TextChanged" />
</Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1">
<WrapPanel x:Name="MainWrapPanel"></WrapPanel>
</ScrollViewer>
</Grid>
</Window>

View File

@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using DynamicGUI;
namespace DynamicGUI
{
public partial class MainWindow : Window
{
public string mpvConfPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\mpv.conf";
private List<SettingBase> mpvSettings = Settings.LoadSettings("Definitions.toml");
public MainWindow()
{
InitializeComponent();
Title = (Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0] as AssemblyProductAttribute).Product + " " + Assembly.GetExecutingAssembly().GetName().Version.ToString();
foreach (var setting in mpvSettings)
{
foreach (var pair in mpvConf)
{
if (setting.Name == pair.Key || setting.Alias == pair.Key)
switch (setting)
{
case StringSetting s:
s.Value = pair.Value;
continue;
case OptionSetting s:
s.Value = pair.Value;
break;
}
}
switch (setting)
{
case StringSetting s:
MainWrapPanel.Children.Add(new StringSettingControl(s));
break;
case OptionSetting s:
MainWrapPanel.Children.Add(new OptionSettingControl(s));
break;
}
}
}
private Dictionary<string, string> _mpvConf;
public Dictionary<string, string> mpvConf {
get {
if (_mpvConf == null)
{
_mpvConf = new Dictionary<string, string>();
if (File.Exists(mpvConfPath))
foreach (var i in File.ReadAllLines(mpvConfPath))
if (i.Contains("=") && !i.Trim().StartsWith("#"))
{
int pos = i.IndexOf("=");
_mpvConf[i.Substring(0, pos).Trim()] = i.Substring(pos + 1).Trim();
}
}
return _mpvConf;
}
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
foreach (var mpvSetting in mpvSettings)
{
switch (mpvSetting)
{
case StringSetting s:
if ((s.Value ?? "") != s.Default)
mpvConf[s.Name] = s.Value;
else
mpvConf.Remove(s.Name);
break;
case OptionSetting s:
if ((s.Value ?? "") != s.Default)
mpvConf[s.Name] = s.Value;
else
mpvConf.Remove(s.Name);
break;
}
}
if (!File.Exists(mpvConfPath))
File.WriteAllText(mpvConfPath, "");
List<string> lines = File.ReadAllLines(mpvConfPath).ToList();
foreach (var mpvSetting in mpvSettings)
{
foreach (var line in lines.ToArray())
{
string test = line.Replace("#", "").Replace(" ", "");
if (test.StartsWith(mpvSetting.Alias + "="))
{
lines.Remove(line);
foreach (var pair in mpvConf.ToArray())
if (test.StartsWith(pair.Key + "="))
mpvConf.Remove(pair.Key);
}
}
}
foreach (var pair in mpvConf)
{
bool changed = false;
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains("=") &&
lines[i].Substring(0, lines[i].IndexOf("=")).Trim("# ".ToCharArray()) == pair.Key)
{
lines[i] = pair.Key + " = " + pair.Value;
changed = true;
}
}
if (!changed)
lines.Add(pair.Key + " = " + pair.Value);
}
foreach (var mpvSetting in mpvSettings)
{
foreach (var line in lines.ToArray())
{
string test = line.Replace("#", "").Replace(" ", "");
if (test.StartsWith(mpvSetting.Name + "=") && !mpvConf.ContainsKey(mpvSetting.Name))
lines.Remove(line);
}
}
File.WriteAllText(mpvConfPath, String.Join(Environment.NewLine, lines));
MessageBox.Show("If running, restart mpv/mpv.net", Title, MessageBoxButton.OK, MessageBoxImage.Information);
}
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
for (int i = MainWrapPanel.Children.Count - 1; i >= 0; i--)
{
if ((MainWrapPanel.Children[i] as ISearch).Contains(SearchTextBox.Text))
MainWrapPanel.Children[i].Visibility = Visibility.Visible;
else
MainWrapPanel.Children[i].Visibility = Visibility.Collapsed;
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("mpv settings editor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mpv settings editor")]
[assembly: AssemblyCopyright("Copyright © stax76")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.0.0")]
[assembly: AssemblyFileVersion("0.1.0.0")]

View File

@@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace mpvnet.Properties {
namespace DynamicGUI.Properties {
using System;
@@ -19,7 +19,7 @@ namespace mpvnet.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -39,7 +39,7 @@ namespace mpvnet.Properties {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvnet.Properties.Resources", typeof(Resources).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvSettingsEditor.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -59,26 +59,5 @@ namespace mpvnet.Properties {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to
///#key command key caption menu path/caption
///
///o script-message mpv.net open-files #menu: O; Open Files
///
///Space pause #menu: Space ; Play/Pause
///s stop #menu: S ; Stop
///
///F11 playlist-prev #menu: F11 ; Navigate | Previous
///F12 playlist-next #menu: F12 ; Navigate | Next
///
///Ctrl++ add video-zoom 0.1 #menu: Ctrl++ ; Pan &amp;&amp; Scan | Increase Size
///Ctrl+- add video-zoom -0.1 #menu: Ct [rest of string was truncated]&quot;;.
/// </summary>
internal static string input_conf {
get {
return ResourceManager.GetString("input_conf", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace DynamicGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C4FEAA45-001D-4DC8-8BFA-621527326D09}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>mpvSettingsEditor</RootNamespace>
<AssemblyName>mpvSettingsEditor</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>8.0</LangVersion>
<NullableReferenceTypes>true</NullableReferenceTypes>
<NullableContextOptions>enable</NullableContextOptions>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="DynamicGUI\DynamicGUI.cs" />
<Compile Include="DynamicGUI\OptionSettingControl.xaml.cs">
<DependentUpon>OptionSettingControl.xaml</DependentUpon>
</Compile>
<Compile Include="DynamicGUI\StringSettingControl.xaml.cs">
<DependentUpon>StringSettingControl.xaml</DependentUpon>
</Compile>
<Compile Include="DynamicGUI\Tommy.cs" />
<Page Include="DynamicGUI\OptionSettingControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="DynamicGUI\StringSettingControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="DynamicGUI\Misc.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<None Include="Definitions.toml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28714.193
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpvSettingsEditor", "mpvSettingsEditor.csproj", "{C4FEAA45-001D-4DC8-8BFA-621527326D09}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4FEAA45-001D-4DC8-8BFA-621527326D09}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {959F2890-E1FC-47A2-856C-A42F8C955D15}
EndGlobalSection
EndGlobal

View File

@@ -1,130 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using vbnet;
using static vbnet.UI.MainModule;
namespace mpvnet
{
public class Command
{
public string Name { get; set; }
public Action<string[]> Action { get; set; }
private static List<Command> commands;
public static List<Command> Commands
{
get
{
if (commands == null)
{
commands = new List<Command>();
var type = typeof(Command);
var methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
foreach (var i in methods)
{
var parameters = i.GetParameters();
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(string[]))
continue;
var cmd = new Command() { Name = i.Name.Replace("_","-"), Action = (Action<string[]>)i.CreateDelegate(typeof(Action<string[]>)) };
commands.Add(cmd);
}
}
return commands;
}
}
public static void open_files(string[] args)
{
MainForm.Instance.Invoke(new Action(() => {
using (var d = new OpenFileDialog())
{
d.Multiselect = true;
d.Filter = Misc.GetFilter(Misc.FileTypes);
if (d.ShowDialog() == DialogResult.OK)
mpv.LoadFiles(d.FileNames);
}
}));
}
public static void open_config_folder(string[] args)
{
ProcessHelp.Start(Folder.AppDataRoaming + "mpv");
}
public static void show_keys(string[] args)
{
ProcessHelp.Start(OS.GetTextEditor(), '"' + mpv.InputConfPath + '"');
}
public static void show_prefs(string[] args)
{
string filepath = Folder.AppDataRoaming + "mpv\\mpv.conf";
if (!File.Exists(filepath))
{
var dirPath = Folder.AppDataRoaming + "mpv\\";
if (!Directory.Exists(dirPath))
Directory.CreateDirectory(dirPath);
File.WriteAllText(filepath, "# https://mpv.io/manual/master/#configuration-files");
}
ProcessHelp.Start(OS.GetTextEditor(), '"' + filepath + '"');
}
public static void history(string[] args)
{
var fp = Folder.AppDataRoaming + "mpv\\history.txt";
if (MsgQuestion($"Create history.txt file in config folder?{BR2}mpv.net will write the date, time and filename of opened file to it.") == DialogResult.OK)
File.WriteAllText(fp, "");
}
public static void show_info(string[] args)
{
try
{
var fi = new FileInfo(mpv.GetStringProp("path"));
using (var mi = new MediaInfo(fi.FullName))
{
var w = mi.GetInfo(StreamKind.Video, "Width");
var h = mi.GetInfo(StreamKind.Video, "Height");
var pos = TimeSpan.FromSeconds(mpv.GetIntProp("time-pos"));
var dur = TimeSpan.FromSeconds(mpv.GetIntProp("duration"));
var br = Convert.ToInt32(mi.GetInfo(StreamKind.Video, "BitRate")) / 1000.0 / 1000.0;
var vf = mpv.GetStringProp("video-format").ToUpper();
var fn = fi.Name;
if (fn.Length > 60)
fn = fn.Insert(59, BR);
var info =
FormatTime(pos.TotalMinutes) + ":" +
FormatTime(pos.Seconds) + " / " +
FormatTime(dur.TotalMinutes) + ":" +
FormatTime(dur.Seconds) + "\n" +
((int)(fi.Length / 1024 / 1024)).ToString() +
$" MB - {w} x {h}\n{vf} - {br.ToString("f1")} Mb/s" + "\n" + fn;
mpv.Command("show-text", info, "5000");
string FormatTime(double value) => ((int)(Math.Floor(value))).ToString("00");
}
}
catch (Exception)
{
}
}
}
}

View File

@@ -1,297 +0,0 @@
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using vbnet;
using vbnet.UI;
using static vbnet.UI.MainModule;
namespace mpvnet
{
public partial class MainForm : Form
{
public static MainForm Instance { get; set; }
public static IntPtr Hwnd;
private Point LastCursorPosChanged;
private int LastCursorChangedTickCount;
private bool IsCloseRequired = true;
public ContextMenuStripEx CMS;
public MainForm()
{
try
{
Application.ThreadException += Application_ThreadException;
InitializeComponent();
SetFormPosSize();
Instance = this;
Hwnd = Handle;
mpv.Init();
mpv.ObserveBoolProp("fullscreen", MpvChangeFullscreen);
mpv.AfterShutdown += Mpv_AfterShutdown;
mpv.VideoSizeChanged += Mpv_VideoSizeChanged;
mpv.PlaybackRestart += mpv_PlaybackRestart;
ToolStripManager.Renderer = new ToolStripRendererEx(ToolStripRenderModeEx.SystemDefault);
CMS = new ContextMenuStripEx(components);
CMS.Opened += CMS_Opened;
ContextMenuStrip = CMS;
BuildMenu();
}
catch (Exception e)
{
HandleException(e);
}
}
public void BuildMenu()
{
if (!File.Exists(mpv.InputConfPath))
{
var dirPath = Folder.AppDataRoaming + "mpv\\";
if (!Directory.Exists(dirPath))
Directory.CreateDirectory(dirPath);
File.WriteAllText(mpv.InputConfPath, Properties.Resources.input_conf);
}
foreach (var i in File.ReadAllText(mpv.InputConfPath).SplitLinesNoEmpty())
{
if (!i.Contains("#menu:"))
continue;
var left = i.Left("#menu:").Trim();
if (left.StartsWith("#"))
continue;
var cmd = left.Right(" ").Trim();
var menu = i.Right("#menu:").Trim();
var key = menu.Left(";").Trim();
var path = menu.Right(";").Trim();
if (path == "" || cmd == "")
continue;
var menuItem = CMS.Add(path, () => {
try
{
mpv.CommandString(cmd, false);
}
catch (Exception e)
{
MsgException(e);
}
});
if (menuItem != null)
menuItem.ShortcutKeyDisplayString = key.Replace("_","") + " ";
}
}
private void CMS_Opened(object sender, EventArgs e)
{
CursorHelp.Show();
}
private void mpv_PlaybackRestart()
{
var fn = mpv.GetStringProp("filename");
BeginInvoke(new Action(() => { Text = fn + " - mpv.net " + Application.ProductVersion; }));
var fp = Folder.AppDataRoaming + "mpv\\history.txt";
if (File.Exists(fp))
File.AppendAllText(fp, DateTime.Now.ToString() + " " + Path.GetFileNameWithoutExtension(fn) + BR);
}
private void CM_Popup(object sender, EventArgs e)
{
CursorHelp.Show();
}
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}
void HandleException(Exception e)
{
MsgException(e);
}
private void Mpv_VideoSizeChanged()
{
BeginInvoke(new Action(() => SetFormPosSize()));
}
private void Mpv_AfterShutdown()
{
if (IsCloseRequired)
Invoke(new Action(() => Close()));
}
public bool IsFullscreen
{
get { return WindowState == FormWindowState.Maximized; }
}
void MpvChangeFullscreen(bool value)
{
BeginInvoke(new Action(() => ChangeFullscreen(value)));
}
void ChangeFullscreen(bool value)
{
if (value)
{
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
}
else
{
WindowState = FormWindowState.Normal;
FormBorderStyle = FormBorderStyle.Sizable;
SetFormPosSize();
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x0201: // WM_LBUTTONDOWN
case 0x0202: // WM_LBUTTONUP
case 0x0100: // WM_KEYDOWN
case 0x0101: // WM_KEYUP
case 0x020A: // WM_MOUSEWHEEL
if (mpv.MpvWindowHandle != IntPtr.Zero)
Native.SendMessage(mpv.MpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x203: // Native.WM.LBUTTONDBLCLK
if (!IsMouseInOSC())
mpv.CommandString("cycle fullscreen");
break;
case 0x0214: // WM_SIZING
var rc = Marshal.PtrToStructure<Native.RECT>(m.LParam);
var r = rc;
NativeHelp.SubtractWindowBorders(Handle, ref r);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
float aspect = mpv.VideoSize.Width / (float)mpv.VideoSize.Height;
int d_w = (int)(c_h * aspect - c_w);
int d_h = (int)(c_w / aspect - c_h);
int[] d_corners = { d_w, d_h, -d_w, -d_h };
int[] corners = { rc.Left, rc.Top, rc.Right, rc.Bottom };
int corner = NativeHelp.GetResizeBorder(m.WParam.ToInt32());
if (corner >= 0)
corners[corner] -= d_corners[corner];
Marshal.StructureToPtr<Native.RECT>(new Native.RECT(corners[0], corners[1], corners[2], corners[3]), m.LParam, false);
m.Result = new IntPtr(1);
return;
}
base.WndProc(ref m);
}
void SetFormPosSize()
{
if (IsFullscreen || mpv.VideoSize.Width == 0) return;
var wa = Screen.GetWorkingArea(this);
int h = (int)(wa.Height * 0.6);
int w = (int)(h * mpv.VideoSize.Width / (float)mpv.VideoSize.Height);
Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var r = new Native.RECT(new Rectangle(0, 0, w, h));
NativeHelp.AddWindowBorders(Handle, ref r);
int l = middlePos.X - r.Width / 2;
int t = middlePos.Y - r.Height / 2;
if (l < 0) l = 0;
if (t < 0) t = 0;
if (l + r.Width > wa.Width ) l = wa.Width - r.Width;
if (t + r.Height > wa.Height ) t = wa.Height - r.Height;
Native.SetWindowPos(Handle, IntPtr.Zero /* HWND_TOP */, l, t, r.Width, r.Height, 4 /* SWP_NOZORDER */);
}
protected override void OnDragEnter(DragEventArgs e)
{
base.OnDragEnter(e);
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
protected override void OnDragDrop(DragEventArgs e)
{
base.OnDragDrop(e);
if (e.Data.GetDataPresent(DataFormats.FileDrop))
mpv.LoadFiles(e.Data.GetData(DataFormats.FileDrop) as String[]);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
// window-dragging
if (WindowState == FormWindowState.Normal &&
e.Button == MouseButtons.Left &&
e.Y < ClientSize.Height * 0.9)
{
var HTCAPTION = new IntPtr(2);
Native.ReleaseCapture();
Native.PostMessage(Handle, 0xA1 /* WM_NCLBUTTONDOWN */, HTCAPTION, IntPtr.Zero);
}
var sb = Screen.FromControl(this).Bounds;
var p1 = new Point(sb.Width, 0);
var p2 = PointToScreen(e.Location);
if (Math.Abs(p1.X - p2.X) < 10 && Math.Abs(p1.Y - p2.Y) < 10)
Close();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
// send mouse command to make OSC show
mpv.CommandString($"mouse {e.X} {e.Y}");
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
CursorHelp.Show();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
IsCloseRequired = false;
mpv.Command("quit");
}
bool IsMouseInOSC()
{
return PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
}
private void Timer_Tick(object sender, EventArgs e)
{
if (CursorHelp.IsPosDifferent(LastCursorPosChanged))
{
LastCursorPosChanged = Control.MousePosition;
LastCursorChangedTickCount = Environment.TickCount;
}
else if (Environment.TickCount - LastCursorChangedTickCount > 1500 &&
!IsMouseInOSC() && ClientRectangle.Contains(PointToClient(MousePosition)) &&
Form.ActiveForm == this && !CMS.Visible)
{
CursorHelp.Hide();
}
}
}
}

View File

@@ -1,51 +0,0 @@
#key command key caption menu path/caption
o script-message mpv.net open-files #menu: O; Open Files
Space cycle pause #menu: Space ; Play/Pause
s stop #menu: S ; Stop
F11 playlist-prev #menu: F11 ; Navigate | Previous
F12 playlist-next #menu: F12 ; Navigate | Next
Ctrl++ add video-zoom 0.1 #menu: Ctrl++ ; Pan && Scan | Increase Size
Ctrl+- add video-zoom -0.1 #menu: Ctrl+- ; Pan && Scan | Decrease Size
Enter cycle fullscreen #menu: Enter ; Cycle Fullscreen
KP7 cycle audio #menu: Numpad 7 ; Cycle Audio
KP8 cycle sub #menu: Numpad 8 ; Cycle Subtitle
+ add volume 5 #menu: + ; Volume | Up
- add volume -5 #menu: - ; Volume | Down
Axis_Up add volume 5 # wheel up
Axis_Down add volume -5 # wheel down
_ ignore #menu: _ ; Volume | -
m cycle mute #menu: M ; Volume | Mute
KP6 add audio-delay 0.100 #menu: Numpad 6 ; Audio | Delay +0.1
KP9 add audio-delay -0.100 #menu: Numpad 9 ; Audio | Delay -0.1
Right seek 5 #menu: Right ; Seek | 10 sec forward
Left seek -5 #menu: Left ; Seek | 10 sec backward
_ ignore #menu: _ ; Seek | -
Up seek 60 #menu: Up ; Seek | 1 min forward
Down seek -60 #menu: Down ; Seek | 1 min backward
_ ignore #menu: _ ; Seek | -
Ctrl+Right seek 300 #menu: Ctrl+Right ; Seek | 5 min forward
Ctrl+Left seek -300 #menu: Ctrl+Left ; Seek | 5 min backward
KP0 script-message rate-file 0 #menu: Numpad 0 ; Addons | Rating | 0stars
KP1 script-message rate-file 1 #menu: Numpad 1 ; Addons | Rating | 1stars
KP2 script-message rate-file 2 #menu: Numpad 2 ; Addons | Rating | 2stars
KP3 script-message rate-file 3 #menu: Numpad 3 ; Addons | Rating | 3stars
KP4 script-message rate-file 4 #menu: Numpad 4 ; Addons | Rating | 4stars
KP5 script-message rate-file 5 #menu: Numpad 5 ; Addons | Rating | 5stars
p script-message mpv.net show-prefs #menu: P ; Preferences
k script-message mpv.net show-keys #menu: K ; Keys
i script-message mpv.net show-info #menu: I ; Tools | Info
c script-message mpv.net open-config-folder #menu: _ ; Tools | Config Folder
h script-message mpv.net history #menu: H ; Tools | History
Esc quit #menu: Escape ; Exit

View File

@@ -1,630 +0,0 @@
using System;
using System.Linq;
using System.IO;
public static class StringExtensions
{
// public static string Multiply(this string instance, int multiplier)
// {
// StringBuilder sb = new StringBuilder(multiplier * instance.Length);
// for (var i = 0; i <= multiplier - 1; i++)
// {
// sb.Append(instance);
// }
// return sb.ToString();
// }
// public static bool IsValidFileName(string instance)
// {
// if (string.IsNullOrEmpty(instance))
// return false;
// string chars = "\"*/:<>?\\|";
// foreach (var i in instance)
// {
// if (chars.Contains(i.ToString()))
// return false;
// if (Convert.ToInt32(i) < 32)
// return false;
// }
// return true;
// }
// [Extension()]
// public static string FileName(string instance)
// {
// if (string.IsNullOrEmpty(instance))
// return "";
// dynamic index = instance.LastIndexOf(Path.DirectorySeparatorChar);
// if (index > -1)
// return instance.Substring(index + 1);
// return instance;
// }
// [Extension()]
// public static string Upper(string instance)
// {
// if (string.IsNullOrEmpty(instance))
// return "";
// return instance.ToUpperInvariant;
// }
// [Extension()]
// public static string Lower(string instance)
// {
// if (string.IsNullOrEmpty(instance))
// return "";
// return instance.ToLowerInvariant;
// }
// [Extension()]
// public static string ChangeExt(string instance, string value)
// {
// if (string.IsNullOrEmpty(instance))
// return "";
// if (string.IsNullOrEmpty(value))
// return instance;
// if (!value.StartsWith("."))
// value = "." + value;
// return instance.DirAndBase + value.ToLower;
// }
// [Extension()]
// public static string Escape(string instance)
// {
// if (string.IsNullOrEmpty(instance))
// return "";
// dynamic chars = " ()".ToCharArray;
// foreach (void i_loopVariable in chars)
// {
// i = i_loopVariable;
// if (instance.Contains(i))
// return "\"" + instance + "\"";
// }
// return instance;
// }
// [Extension()]
// public static string Parent(string instance)
// {
// return DirPath.GetParent(instance);
// }
// [Extension()]
// public static string ExistingParent(string instance)
// {
// dynamic ret = instance.Parent;
// if (!Directory.Exists(ret))
// ret = ret.Parent;
// else
// return ret;
// if (!Directory.Exists(ret))
// ret = ret.Parent;
// else
// return ret;
// if (!Directory.Exists(ret))
// ret = ret.Parent;
// else
// return ret;
// if (!Directory.Exists(ret))
// ret = ret.Parent;
// else
// return ret;
// if (!Directory.Exists(ret))
// ret = ret.Parent;
// else
// return ret;
// return ret;
// }
public static string ExtFull(this string filepath)
{
return Ext(filepath, true);
}
public static string Ext(this string filepath)
{
return Ext(filepath, false);
}
public static string Ext(this string filepath, bool dot)
{
if (string.IsNullOrEmpty(filepath))
return "";
var chars = filepath.ToCharArray();
for (var x = filepath.Length - 1; x >= 0; x += -1)
{
if (chars[x] == Path.DirectorySeparatorChar)
return "";
if (chars[x] == '.')
return filepath.Substring(x + (dot ? 0 : 1)).ToLower();
}
return "";
}
// [Extension()]
// public static string Base(string instance)
// {
// return FilePath.GetBase(instance);
// }
// [Extension()]
// public static string Dir(string instance)
// {
// return FilePath.GetDir(instance);
// }
// [Extension()]
// public static string DirName(string instance)
// {
// return DirPath.GetName(instance);
// }
// [Extension()]
// public static string DirAndBase(string instance)
// {
// return FilePath.GetDirAndBase(instance);
// }
// [Extension()]
// public static bool ContainsAll(string instance, IEnumerable<string> all)
// {
// if (!string.IsNullOrEmpty(instance))
// return all.All(arg => instance.Contains(arg));
// }
// [Extension()]
// public static bool ContainsAny(string instance, IEnumerable<string> any)
// {
// if (!string.IsNullOrEmpty(instance))
// return any.Any(arg => instance.Contains(arg));
// }
// [Extension()]
// public static string ToTitleCase(string value)
// {
// //TextInfo.ToTitleCase won't work on all upper strings
// return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower);
// }
// [Extension()]
// public static bool IsInt(string value)
// {
// return int.TryParse(value, null);
// }
// [Extension()]
// public static int ToInt(string value, int defaultValue = 0)
// {
// if (!int.TryParse(value, null))
// return defaultValue;
// return Convert.ToInt32(value);
// }
// [Extension()]
// public static bool IsSingle(string value)
// {
// if (!string.IsNullOrEmpty(value))
// {
// if (value.Contains(","))
// value = value.Replace(",", ".");
// return float.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, null);
// }
// }
// [Extension()]
// public static float ToSingle(string value, float defaultValue = 0)
// {
// if (!string.IsNullOrEmpty(value))
// {
// if (value.Contains(","))
// value = value.Replace(",", ".");
// float ret = 0;
// if (float.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, ret))
// {
// return ret;
// }
// }
// return defaultValue;
// }
// [Extension()]
// public static bool IsDouble(string value)
// {
// if (!string.IsNullOrEmpty(value))
// {
// if (value.Contains(","))
// value = value.Replace(",", ".");
// return double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, null);
// }
// }
// [Extension()]
// public static double ToDouble(string value, float defaultValue = 0)
// {
// if (!string.IsNullOrEmpty(value))
// {
// if (value.Contains(","))
// value = value.Replace(",", ".");
// double ret = 0;
// if (double.TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, ret))
// {
// return ret;
// }
// }
// return defaultValue;
// }
public static string Left(this string value, int index)
{
if (string.IsNullOrEmpty(value) || index < 0)
return "";
if (index > value.Length)
return value;
return value.Substring(0, index);
}
public static string Left(this string value, string start)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
return "";
if (!value.Contains(start))
return "";
return value.Substring(0, value.IndexOf(start));
}
public static string LeftLast(this string value, string start)
{
if (!value.Contains(start))
return "";
return value.Substring(0, value.LastIndexOf(start));
}
public static string Right(this string value, string start)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
return "";
if (!value.Contains(start))
return "";
return value.Substring(value.IndexOf(start) + start.Length);
}
public static string RightLast(this string value, string start)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(start))
return "";
if (!value.Contains(start))
return "";
return value.Substring(value.LastIndexOf(start) + start.Length);
}
// [Extension()]
// public static bool EqualIgnoreCase(string a, string b)
// {
// if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b))
// return false;
// return string.Compare(a, b, StringComparison.OrdinalIgnoreCase) == 0;
// }
// [Extension()]
// public static string Shorten(string value, int maxLength)
// {
// if (string.IsNullOrEmpty(value) || value.Length <= maxLength)
// {
// return value;
// }
// return value.Substring(0, maxLength);
// }
public static string[] SplitNoEmpty(this string value, params string[] delimiters)
{
return value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
}
public static string[] SplitKeepEmpty(this string value, params string[] delimiters)
{
return value.Split(delimiters, StringSplitOptions.None);
}
public static string[] SplitNoEmptyAndWhiteSpace(this string value, params string[] delimiters)
{
if (string.IsNullOrEmpty(value))
return null;
var a = SplitNoEmpty(value, delimiters);
for (var i = 0; i <= a.Length - 1; i++)
a[i] = a[i].Trim();
var l = a.ToList();
while (l.Contains(""))
l.Remove("");
return l.ToArray();
}
public static string[] SplitLinesNoEmpty(this string value)
{
return SplitNoEmpty(value, Environment.NewLine);
}
// [Extension()]
// public static string RemoveChars(string value, string chars)
// {
// dynamic ret = value;
// foreach (void i_loopVariable in value)
// {
// i = i_loopVariable;
// if (chars.IndexOf(i) >= 0)
// {
// ret = ret.Replace(i, "");
// }
// }
// return ret;
// }
// [Extension()]
// public static string DeleteRight(string value, int count)
// {
// return Strings.Left(value, value.Length - count);
// }
// [Extension()]
// public static string ReplaceUnicode(string value)
// {
// if (value.Contains(Convert.ToChar(0x2212)))
// {
// value = value.Replace(Convert.ToChar(0x2212), '-');
// }
// return value;
// }
// [Extension()]
// public static void ToClipboard(string value)
// {
// if (!string.IsNullOrEmpty(value))
// {
// Clipboard.SetText(value);
// }
// else
// {
// Clipboard.Clear();
// }
// }
//}
public class DirPath : PathBase
{
// public static string TrimTrailingSeparator(string path)
// {
// if (string.IsNullOrEmpty(path))
// return "";
// if (path.EndsWith(Separator) && !(path.Length <= 3))
// {
// return path.TrimEnd(Separator);
// }
// return path;
// }
// public static string FixSeperator(string path)
// {
// if (path.Contains("\\") && Separator != "\\")
// {
// path = path.Replace("\\", Separator);
// }
// if (path.Contains("/") && Separator != "/")
// {
// path = path.Replace("/", Separator);
// }
// return path;
// }
// public static string GetParent(string path)
// {
// if (string.IsNullOrEmpty(path))
// return "";
// dynamic temp = TrimTrailingSeparator(path);
// if (temp.Contains(Separator))
// path = temp.LeftLast(Separator) + Separator;
// return path;
// }
// public static string GetName(string path)
// {
// if (string.IsNullOrEmpty(path))
// return "";
// path = TrimTrailingSeparator(path);
// return path.RightLast(Separator);
// }
// public static bool IsFixedDrive(string path)
// {
// try
// {
// if (!string.IsNullOrEmpty(path))
// return new DriveInfo(path).DriveType == DriveType.Fixed;
// }
// catch (Exception ex)
// {
// }
// }
}
public class FilePath : PathBase
{
// private string Value;
// public FilePath(string path)
// {
// Value = path;
// }
// public static string GetDir(string path)
// {
// if (string.IsNullOrEmpty(path))
// return "";
// if (path.Contains("\\"))
// path = path.LeftLast("\\") + "\\";
// return path;
// }
// public static string GetDirAndBase(string path)
// {
// return GetDir(path) + GetBase(path);
// }
// public static string GetName(string path)
// {
// if ((path != null))
// {
// dynamic index = path.LastIndexOf(IO.Path.DirectorySeparatorChar);
// if (index > -1)
// {
// return path.Substring(index + 1);
// }
// }
// return path;
// }
// public static string GetDirNoSep(string path)
// {
// path = GetDir(path);
// if (path.EndsWith(Separator))
// path = TrimSep(path);
// return path;
// }
// public static string GetBase(string path)
// {
// if (string.IsNullOrEmpty(path))
// return "";
// dynamic ret = path;
// if (ret.Contains(Separator))
// ret = ret.RightLast(Separator);
// if (ret.Contains("."))
// ret = ret.LeftLast(".");
// return ret;
// }
// public static string TrimSep(string path)
// {
// if (string.IsNullOrEmpty(path))
// return "";
// if (path.EndsWith(Separator) && !path.EndsWith(":" + Separator))
// {
// return path.TrimEnd(Separator);
// }
// return path;
// }
// public static string GetDirNameOnly(string path)
// {
// return FilePath.GetDirNoSep(path).RightLast("\\");
// }
}
public class PathBase
{
//public static char Separator {
// get { return Path.DirectorySeparatorChar; }
//}
// public static bool IsSameBase(string a, string b)
// {
// return FilePath.GetBase(a).EqualIgnoreCase(FilePath.GetBase(b));
// }
// public static bool IsSameDir(string a, string b)
// {
// return FilePath.GetDir(a).EqualIgnoreCase(FilePath.GetDir(b));
// }
// public static bool IsValidFileSystemName(string name)
// {
// if (string.IsNullOrEmpty(name))
// return false;
// dynamic chars = "\"*/:<>?\\|^".ToCharArray;
// foreach (void i_loopVariable in name.ToCharArray)
// {
// i = i_loopVariable;
// if (chars.Contains(i))
// return false;
// if (Convert.ToInt32(i) < 32)
// return false;
// }
// return true;
// }
// public static string RemoveIllegalCharsFromName(string name)
// {
// if (string.IsNullOrEmpty(name))
// return "";
// dynamic chars = "\"*/:<>?\\|^".ToCharArray;
// foreach (void i_loopVariable in name.ToCharArray)
// {
// i = i_loopVariable;
// if (chars.Contains(i))
// {
// name = name.Replace(i, "_");
// }
// }
// for (x = 1; x <= 31; x++)
// {
// if (name.Contains(Convert.ToChar(x)))
// {
// name = name.Replace(Convert.ToChar(x), '_');
// }
// }
// return name;
}
}

View File

@@ -1,314 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Drawing;
using static mpvnet.libmpv;
using static mpvnet.Native;
using vbnet;
using static vbnet.UI.MainModule;
using System.Diagnostics;
namespace mpvnet
{
public delegate void MpvBoolPropChangeHandler(string propName, bool value);
public class mpv
{
public static event Action<string[]> ClientMessage;
public static event Action Shutdown;
public static event Action AfterShutdown;
public static event Action FileLoaded;
public static event Action PlaybackRestart;
public static event Action VideoSizeChanged;
public static IntPtr MpvHandle;
public static IntPtr MpvWindowHandle;
public static Addon Addon;
public static List<Action<bool>> BoolPropChangeActions = new List<Action<bool>>();
public static Size VideoSize = new Size(1920, 1080);
public static string InputConfPath = Folder.AppDataRoaming + "mpv\\input.conf";
public static StringPairList BindingList = new StringPairList();
public static void Init()
{
LoadLibrary("mpv-1.dll");
MpvHandle = mpv_create();
SetIntProp("input-ar-delay", 500);
SetIntProp("input-ar-rate", 20);
SetIntProp("volume", 50);
SetStringProp("hwdec", "auto");
SetStringProp("input-default-bindings", "yes");
SetStringProp("opengl-backend", "angle");
SetStringProp("osd-playing-msg", "'${filename}'");
SetStringProp("profile", "opengl-hq");
SetStringProp("screenshot-directory", "~~desktop/");
SetStringProp("vo", "opengl");
SetStringProp("keep-open", "always");
SetStringProp("keep-open-pause", "no");
SetStringProp("osc", "yes");
SetStringProp("config", "yes");
SetStringProp("wid", MainForm.Hwnd.ToString());
SetStringProp("force-window", "yes");
mpv_initialize(MpvHandle);
ProcessCommandLine();
Task.Run(() => { Addon = new Addon(); });
Task.Run(() => { EventLoop(); });
}
public static void EventLoop()
{
while (true)
{
IntPtr ptr = mpv_wait_event(MpvHandle, -1);
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event));
Debug.WriteLine(evt.event_id);
if (MpvWindowHandle == IntPtr.Zero)
MpvWindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
switch (evt.event_id)
{
case mpv_event_id.MPV_EVENT_SHUTDOWN:
Shutdown?.Invoke();
AfterShutdown?.Invoke();
return;
case mpv_event_id.MPV_EVENT_FILE_LOADED:
FileLoaded?.Invoke();
break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke();
var s = new Size(GetIntProp("dwidth"), GetIntProp("dheight"));
if (VideoSize != s)
{
VideoSize = s;
VideoSizeChanged?.Invoke();
}
break;
case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE:
if (ClientMessage != null)
{
var client_messageData = (mpv_event_client_message)Marshal.PtrToStructure(evt.data, typeof(mpv_event_client_message));
var args = NativeUtf8StrArray2ManagedStrArray(client_messageData.args, client_messageData.num_args);
if (args != null && args.Length > 1 && args[0] == "mpv.net")
foreach (var i in mpvnet.Command.Commands)
if (args[1] == i.Name)
i.Action(args.Skip(2).ToArray());
ClientMessage?.Invoke(args);
}
break;
case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE:
var eventData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property));
if (eventData.format == mpv_format.MPV_FORMAT_FLAG)
foreach (var action in BoolPropChangeActions)
action.Invoke(Marshal.PtrToStructure<int>(eventData.data) == 1);
break;
}
}
}
public static void Command(params string[] args)
{
if (MpvHandle == IntPtr.Zero)
return;
IntPtr[] byteArrayPointers;
var mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out byteArrayPointers);
int err = mpv_command(MpvHandle, mainPtr);
if (err < 0)
throw new Exception($"{(mpv_error)err}");
foreach (var ptr in byteArrayPointers)
Marshal.FreeHGlobal(ptr);
Marshal.FreeHGlobal(mainPtr);
}
public static void CommandString(string command, bool throwException = true)
{
if (MpvHandle == IntPtr.Zero)
return;
int err = mpv_command_string(MpvHandle, command);
if (err < 0 && throwException)
throw new Exception($"{(mpv_error)err}" + BR2 + command);
}
public static void SetStringProp(string name, string value, bool throwException = true)
{
var bytes = GetUtf8Bytes(value);
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
if (err < 0 && throwException)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static string GetStringProp(string name)
{
var lpBuffer = IntPtr.Zero;
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref lpBuffer);
var ret = StringFromNativeUtf8(lpBuffer);
mpv_free(lpBuffer);
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
return ret;
}
public static int GetIntProp(string name, bool throwException = true)
{
var lpBuffer = IntPtr.Zero;
int err = mpv_get_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref lpBuffer);
if (err < 0 && throwException)
throw new Exception($"{name}: {(mpv_error)err}");
else
return lpBuffer.ToInt32();
}
public static void SetIntProp(string name, int value)
{
Int64 val = value;
int err = mpv_set_property(MpvHandle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static void ObserveBoolProp(string name, Action<bool> action)
{
BoolPropChangeActions.Add(action);
int err = mpv_observe_property(MpvHandle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static void UnobserveBoolProp(string name, Action<bool> action)
{
BoolPropChangeActions.Remove(action);
int err = mpv_unobserve_property(MpvHandle, (ulong)action.GetHashCode());
if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}");
}
public static void ProcessCommandLine()
{
var args = Environment.GetCommandLineArgs().Skip(1);
foreach (string i in args)
if (!i.StartsWith("--") && File.Exists(i))
mpv.Command("loadfile", i, "append");
mpv.SetStringProp("playlist-pos", "0", false);
foreach (string i in args)
{
if (i.StartsWith("--"))
{
if (i.Contains("="))
{
string left = i.Substring(2, i.IndexOf("=") - 2);
string right = i.Substring(left.Length + 3);
mpv.SetStringProp(left, right);
}
else
mpv.SetStringProp(i.Substring(2), "yes");
}
}
LoadFolder();
}
public static void LoadFiles(string[] files)
{
int count = mpv.GetIntProp("playlist-count");
foreach (string file in files)
mpv.Command("loadfile", file, "append");
mpv.SetIntProp("playlist-pos", count);
for (int i = 0; i < count; i++)
mpv.Command("playlist-remove", "0");
mpv.LoadFolder();
}
public static void LoadFolder()
{
if (GetIntProp("playlist-count") == 1)
{
string[] types = "264 265 3gp aac ac3 avc avi avs bmp divx dts dtshd dtshr dtsma eac3 evo flac flv h264 h265 hevc hvc jpg jpeg m2t m2ts m2v m4a m4v mka mkv mlp mov mp2 mp3 mp4 mpa mpeg mpg mpv mts ogg ogm opus pcm png pva raw rmvb thd thd+ac3 true-hd truehd ts vdr vob vpy w64 wav webm wmv y4m".Split(' ');
string path = GetStringProp("path");
List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
files = files.Where((file) => types.Contains(file.Ext())).ToList();
files.Sort(new StringLogicalComparer());
int index = files.IndexOf(path);
files.Remove(path);
foreach (string i in files)
Command("loadfile", i, "append");
if (index > 0)
Command("playlist-move", "0", (index + 1).ToString());
}
}
public static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
{
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
byteArrayPointers = new IntPtr[numberOfStrings];
IntPtr rootPointer = Marshal.AllocCoTaskMem(IntPtr.Size * numberOfStrings);
for (int index = 0; index < arr.Length; index++)
{
var bytes = GetUtf8Bytes(arr[index]);
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
byteArrayPointers[index] = unmanagedPointer;
}
Marshal.Copy(byteArrayPointers, 0, rootPointer, numberOfStrings);
return rootPointer;
}
public static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr pUnmanagedStringArray, int StringCount)
{
IntPtr[] pIntPtrArray = new IntPtr[StringCount];
string[] ManagedStringArray = new string[StringCount];
Marshal.Copy(pUnmanagedStringArray, pIntPtrArray, 0, StringCount);
for (int i = 0; i < StringCount; i++)
ManagedStringArray[i] = StringFromNativeUtf8(pIntPtrArray[i]);
return ManagedStringArray;
}
public static string StringFromNativeUtf8(IntPtr nativeUtf8)
{
int len = 0;
while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
byte[] buffer = new byte[len];
Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
}
}

12
release.ps1 Normal file
View File

@@ -0,0 +1,12 @@
$scriptDir = Split-Path -Path $PSCommandPath -Parent
$exePath = $scriptDir + "\mpv.net\bin\Debug\mpvnet.exe"
$version = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath).FileVersion
$desktopDir = [Environment]::GetFolderPath("Desktop")
$targetDir = $desktopDir + "\mpv.net-" + $version
Copy-Item C:\Users\frank\Daten\Projekte\CS\mpv.net\mpvSettingsEditor\bin\mpvSettingsEditor.exe "C:\Users\frank\Daten\Projekte\CS\mpv.net\mpv.net\bin\Debug\mpvSettingsEditor.exe" -Force
Copy-Item C:\Users\frank\Daten\Projekte\CS\mpv.net\mpvSettingsEditor\bin\Definitions.toml "C:\Users\frank\Daten\Projekte\CS\mpv.net\mpv.net\bin\Debug\Definitions.toml" -Force
Copy-Item $scriptDir\mpv.net\bin\Debug $targetDir -Recurse -Exclude System.Management.Automation.xml -Force
Copy-Item $scriptDir\README.md $targetDir\README.md -Force
$7zPath = "C:\Program Files\7-Zip\7z.exe"
$args = "a -t7z -mx9 $targetDir.7z -r $targetDir\*"
Start-Process -FilePath $7zPath -ArgumentList $args

View File

@@ -1,8 +0,0 @@
using namespace System.Diagnostics
$exePath = "D:\Projekte\VS\CS\mpvnet\mpvnet\bin\Debug\mpvnet.exe"
$version = [FileVersionInfo]::GetVersionInfo($exePath).FileVersion
$targetDir = "C:\Users\Frank\Desktop\mpv-net-" + $version
Copy-Item D:\Projekte\VS\CS\mpvnet\mpvnet\bin\Debug $targetDir -recurse
$addonDir = $targetDir + "\Addons"
remove-item $addonDir -Recurse -Include *vbnet.pdb, *mpvnet.exe, *mpvnet.exe.config, *mpvnet.pdb, *vbnet.dll
D:\Projekte\VS\VB\util\bin\util.exe -pack $targetDir

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -1,790 +0,0 @@
Imports System.Drawing.Drawing2D
Imports System.Globalization
Imports System.IO
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Security.Cryptography
Imports System.Text
Imports Microsoft.Win32
Imports VB6 = Microsoft.VisualBasic
Imports vbnet.UI
Module StringExtensions
<Extension>
Public Function Multiply(instance As String, multiplier As Integer) As String
Dim sb As New StringBuilder(multiplier * instance.Length)
For i = 0 To multiplier - 1
sb.Append(instance)
Next
Return sb.ToString()
End Function
<Extension>
Function IsValidFileName(instance As String) As Boolean
If instance = "" Then Return False
Dim chars = """*/:<>?\|"
For Each i In instance
If chars.Contains(i) Then Return False
If Convert.ToInt32(i) < 32 Then Return False
Next
Return True
End Function
<Extension>
Function IsANSICompatible(instance As String) As Boolean
If instance = "" Then Return True
Dim bytes = Encoding.Convert(Encoding.Unicode, Encoding.Default, Encoding.Unicode.GetBytes(instance))
Return instance = Encoding.Unicode.GetString(Encoding.Convert(Encoding.Default, Encoding.Unicode, bytes))
End Function
<Extension()>
Function FileName(instance As String) As String
If instance = "" Then Return ""
Dim index = instance.LastIndexOf(Path.DirectorySeparatorChar)
If index > -1 Then Return instance.Substring(index + 1)
Return instance
End Function
<Extension()>
Function Upper(instance As String) As String
If instance = "" Then Return ""
Return instance.ToUpperInvariant
End Function
<Extension()>
Function Lower(instance As String) As String
If instance = "" Then Return ""
Return instance.ToLowerInvariant
End Function
<Extension()>
Function ChangeExt(instance As String, value As String) As String
If instance = "" Then Return ""
If value = "" Then Return instance
If Not value.StartsWith(".") Then value = "." + value
Return instance.DirAndBase + value.ToLower
End Function
<Extension()>
Function Escape(instance As String) As String
If instance = "" Then Return ""
Dim chars = " ()".ToCharArray
For Each i In chars
If instance.Contains(i) Then Return """" + instance + """"
Next
Return instance
End Function
<Extension()>
Function Parent(instance As String) As String
Return DirPath.GetParent(instance)
End Function
<Extension()>
Function ExistingParent(instance As String) As String
Dim ret = instance.Parent
If Not Directory.Exists(ret) Then ret = ret.Parent Else Return ret
If Not Directory.Exists(ret) Then ret = ret.Parent Else Return ret
If Not Directory.Exists(ret) Then ret = ret.Parent Else Return ret
If Not Directory.Exists(ret) Then ret = ret.Parent Else Return ret
If Not Directory.Exists(ret) Then ret = ret.Parent Else Return ret
Return ret
End Function
<Extension()>
Function Ext(instance As String) As String
Return FilePath.GetExt(instance)
End Function
<Extension()>
Function ExtFull(instance As String) As String
Return FilePath.GetExtFull(instance)
End Function
<Extension()>
Function Base(instance As String) As String
Return FilePath.GetBase(instance)
End Function
<Extension()>
Function Dir(instance As String) As String
Return FilePath.GetDir(instance)
End Function
<Extension()>
Function DirName(instance As String) As String
Return DirPath.GetName(instance)
End Function
<Extension()>
Function DirAndBase(instance As String) As String
Return FilePath.GetDirAndBase(instance)
End Function
<Extension()>
Function ContainsAll(instance As String, all As IEnumerable(Of String)) As Boolean
If instance <> "" Then Return all.All(Function(arg) instance.Contains(arg))
End Function
<Extension()>
Function ContainsAny(instance As String, any As IEnumerable(Of String)) As Boolean
If instance <> "" Then Return any.Any(Function(arg) instance.Contains(arg))
End Function
<Extension()>
Function EqualsAny(instance As String, ParamArray values As String()) As Boolean
If instance = "" OrElse values.NothingOrEmpty Then Return False
Return values.Contains(instance)
End Function
<Extension()>
Function FixDir(instance As String) As String
If instance = "" Then Return ""
While instance.EndsWith(DirPath.Separator + DirPath.Separator)
instance = instance.Substring(0, instance.Length - 1)
End While
If instance.EndsWith(DirPath.Separator) Then Return instance
Return instance + DirPath.Separator
End Function
<Extension()>
Function FixBreak(value As String) As String
value = value.Replace(VB6.ChrW(13) + VB6.ChrW(10), VB6.ChrW(10))
value = value.Replace(VB6.ChrW(13), VB6.ChrW(10))
Return value.Replace(VB6.ChrW(10), VB6.ChrW(13) + VB6.ChrW(10))
End Function
<Extension()>
Function ContainsUnicode(value As String) As Boolean
If value = "" Then Return False
For Each i In value
If Convert.ToInt32(i) > 255 Then Return True
Next
End Function
<Extension()>
Function ToTitleCase(value As String) As String
'TextInfo.ToTitleCase won't work on all upper strings
Return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower)
End Function
<Extension()>
Function IsInt(value As String) As Boolean
Return Integer.TryParse(value, Nothing)
End Function
<Extension()>
Function ToInt(value As String, Optional defaultValue As Integer = 0) As Integer
If Not Integer.TryParse(value, Nothing) Then Return defaultValue
Return CInt(value)
End Function
<Extension()>
Function IsSingle(value As String) As Boolean
If value <> "" Then
If value.Contains(",") Then value = value.Replace(",", ".")
Return Single.TryParse(value,
NumberStyles.Float Or NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
Nothing)
End If
End Function
<Extension()>
Function ToSingle(value As String, Optional defaultValue As Single = 0) As Single
If value <> "" Then
If value.Contains(",") Then value = value.Replace(",", ".")
Dim ret As Single
If Single.TryParse(value,
NumberStyles.Float Or NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
ret) Then
Return ret
End If
End If
Return defaultValue
End Function
<Extension()>
Function IsDouble(value As String) As Boolean
If value <> "" Then
If value.Contains(",") Then value = value.Replace(",", ".")
Return Double.TryParse(value,
NumberStyles.Float Or NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
Nothing)
End If
End Function
<Extension()>
Function ToDouble(value As String, Optional defaultValue As Single = 0) As Double
If value <> "" Then
If value.Contains(",") Then value = value.Replace(",", ".")
Dim ret As Double
If Double.TryParse(value,
NumberStyles.Float Or NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
ret) Then
Return ret
End If
End If
Return defaultValue
End Function
<Extension()>
Function FormatColumn(value As String, delimiter As String) As String
If value = "" Then Return ""
Dim lines = value.SplitKeepEmpty(BR)
Dim leftSides As New List(Of String)
For Each i In lines
Dim pos = i.IndexOf(delimiter)
If pos > 0 Then
leftSides.Add(i.Substring(0, pos).Trim)
Else
leftSides.Add(i)
End If
Next
Dim highest = Aggregate i In leftSides Into Max(i.Length)
Dim ret As New List(Of String)
For i = 0 To lines.Length - 1
Dim line = lines(i)
If line.Contains(delimiter) Then
ret.Add(leftSides(i).PadRight(highest) + " " + delimiter + " " + line.Substring(line.IndexOf(delimiter) + 1).Trim)
Else
ret.Add(leftSides(i))
End If
Next
Return ret.Join(BR)
End Function
<Extension()>
Sub WriteANSIFile(instance As String, path As String)
WriteFile(instance, path, Encoding.Default)
End Sub
<Extension()>
Sub WriteUTF8File(instance As String, path As String)
WriteFile(instance, path, Encoding.UTF8)
End Sub
<Extension()>
Sub WriteFile(value As String, path As String, encoding As Encoding)
Try
File.WriteAllText(path, value, encoding)
Catch ex As Exception
MsgException(ex)
End Try
End Sub
<Extension()>
Function Left(value As String, index As Integer) As String
If value = "" OrElse index < 0 Then Return ""
If index > value.Length Then Return value
Return value.Substring(0, index)
End Function
<Extension()>
Function Left(value As String, start As String) As String
If value = "" OrElse start = "" Then Return ""
If Not value.Contains(start) Then Return ""
Return value.Substring(0, value.IndexOf(start))
End Function
<Extension()>
Function LeftLast(value As String, start As String) As String
If Not value.Contains(start) Then Return ""
Return value.Substring(0, value.LastIndexOf(start))
End Function
<Extension()>
Function Right(value As String, start As String) As String
If value = "" OrElse start = "" Then Return ""
If Not value.Contains(start) Then Return ""
Return value.Substring(value.IndexOf(start) + start.Length)
End Function
<Extension()>
Function RightLast(value As String, start As String) As String
If value = "" OrElse start = "" Then Return ""
If Not value.Contains(start) Then Return ""
Return value.Substring(value.LastIndexOf(start) + start.Length)
End Function
<Extension()>
Function EqualIgnoreCase(a As String, b As String) As Boolean
If a = "" OrElse b = "" Then Return False
Return String.Compare(a, b, StringComparison.OrdinalIgnoreCase) = 0
End Function
<Extension()>
Function Shorten(value As String, maxLength As Integer) As String
If value = "" OrElse value.Length <= maxLength Then
Return value
End If
Return value.Substring(0, maxLength)
End Function
<Extension()>
Function SplitNoEmpty(value As String, ParamArray delimiters As String()) As String()
Return value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
End Function
<Extension()>
Function SplitKeepEmpty(value As String, ParamArray delimiters As String()) As String()
Return value.Split(delimiters, StringSplitOptions.None)
End Function
<Extension()>
Function SplitNoEmptyAndWhiteSpace(value As String, ParamArray delimiters As String()) As String()
If value = "" Then Return {}
Dim a = SplitNoEmpty(value, delimiters)
For i = 0 To a.Length - 1
a(i) = a(i).Trim
Next
Dim l = a.ToList
While l.Contains("")
l.Remove("")
End While
Return l.ToArray
End Function
<Extension()>
Function SplitLinesNoEmpty(value As String) As String()
Return SplitNoEmpty(value, Environment.NewLine)
End Function
<Extension()>
Function RemoveChars(value As String, chars As String) As String
Dim ret = value
For Each i In value
If chars.IndexOf(i) >= 0 Then
ret = ret.Replace(i, "")
End If
Next
Return ret
End Function
<Extension()>
Function DeleteRight(value As String, count As Integer) As String
Return Left(value, value.Length - count)
End Function
<Extension()>
Function ReplaceUnicode(value As String) As String
If value.Contains(Convert.ToChar(&H2212)) Then
value = value.Replace(Convert.ToChar(&H2212), "-"c)
End If
Return value
End Function
<Extension()>
Function SHA512Hash(value As String) As String
Dim crypt = SHA512CryptoServiceProvider.Create()
Dim hash = crypt.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value))
Dim sb As New StringBuilder()
For Each i In hash
sb.Append(i.ToString("x2"))
Next
Return sb.ToString()
End Function
<Extension()>
Sub ToClipboard(value As String)
If value <> "" Then
Clipboard.SetText(value)
Else
Clipboard.Clear()
End If
End Sub
End Module
Module MiscExtensions
<Extension()>
Function ToInvariantString(instance As Double, format As String) As String
Dim ret = instance.ToString(format, CultureInfo.InvariantCulture)
If (ret.Contains(".") OrElse ret.Contains(",")) AndAlso ret.EndsWith("0") Then
ret = ret.TrimEnd("0"c)
End If
Return ret
End Function
<Extension()>
Function ToInvariantString(instance As IConvertible) As String
If Not instance Is Nothing Then Return instance.ToString(CultureInfo.InvariantCulture)
End Function
<Extension()>
Function ContainsAny(Of T)(instance As IEnumerable(Of T), ParamArray values As T()) As Boolean
Return instance.Where(Function(arg) values.Contains(arg)).Count > 0
End Function
<Extension()>
Function Sort(Of T)(instance As IEnumerable(Of T)) As IEnumerable(Of T)
Dim ret = instance.ToArray
Array.Sort(Of T)(ret)
Return ret
End Function
<Extension()>
Function Join(instance As IEnumerable(Of String),
delimiter As String,
Optional removeEmpty As Boolean = False) As String
If instance Is Nothing Then Return Nothing
Dim containsEmpty As Boolean
For Each item In instance
If item = "" Then
containsEmpty = True
Exit For
End If
Next
If containsEmpty AndAlso removeEmpty Then instance = instance.Where(Function(arg) arg <> "")
Return String.Join(delimiter, instance)
End Function
<Extension()>
Function GetAttribute(Of T)(mi As MemberInfo) As T
Dim attributes = mi.GetCustomAttributes(True)
If Not attributes.NothingOrEmpty Then
If attributes.Length = 1 Then
If TypeOf attributes(0) Is T Then
Return DirectCast(attributes(0), T)
End If
Else
For Each i In attributes
If TypeOf i Is T Then
Return DirectCast(i, T)
End If
Next
End If
End If
End Function
<Extension()>
Function IsDigit(c As Char) As Boolean
Return Char.IsDigit(c)
End Function
<Extension()>
Function EnsureRange(value As Integer, min As Integer, max As Integer) As Integer
If value < min Then
value = min
ElseIf value > max Then
value = max
End If
Return value
End Function
<Extension()>
Function NeutralCulture(ci As CultureInfo) As CultureInfo
If ci.IsNeutralCulture Then Return ci Else Return ci.Parent
End Function
<Extension()>
Function NothingOrEmpty(strings As IEnumerable(Of String)) As Boolean
If strings Is Nothing OrElse strings.Count = 0 Then Return True
For Each i In strings
If i = "" Then Return True
Next
End Function
<Extension()>
Function NothingOrEmpty(objects As IEnumerable(Of Object)) As Boolean
If objects Is Nothing OrElse objects.Count = 0 Then Return True
For Each i In objects
If i Is Nothing Then Return True
Next
End Function
End Module
Module RegistryKeyExtensions
Private Function GetValue(Of T)(rootKey As RegistryKey, key As String, name As String) As T
Using k = rootKey.OpenSubKey(key)
If Not k Is Nothing Then
Dim r = k.GetValue(name)
If Not r Is Nothing Then
Try
Return CType(r, T)
Catch ex As Exception
End Try
End If
End If
End Using
End Function
<Extension()>
Function GetString(rootKey As RegistryKey, subKey As String, name As String) As String
Return GetValue(Of String)(rootKey, subKey, name)
End Function
<Extension()>
Function GetInt(rootKey As RegistryKey, subKey As String, name As String) As Integer
Return GetValue(Of Integer)(rootKey, subKey, name)
End Function
<Extension()>
Function GetBoolean(rootKey As RegistryKey, subKey As String, name As String) As Boolean
Return GetValue(Of Boolean)(rootKey, subKey, name)
End Function
<Extension()>
Function GetValueNames(rootKey As RegistryKey, subKeyName As String) As IEnumerable(Of String)
Using k = rootKey.OpenSubKey(subKeyName)
If Not k Is Nothing Then
Return k.GetValueNames
End If
End Using
Return {}
End Function
<Extension()>
Sub GetSubKeys(rootKey As RegistryKey, keys As List(Of RegistryKey))
If Not rootKey Is Nothing Then
keys.Add(rootKey)
For Each i In rootKey.GetSubKeyNames
GetSubKeys(rootKey.OpenSubKey(i), keys)
Next
End If
End Sub
<Extension()>
Sub Write(rootKey As RegistryKey, subKey As String, valueName As String, valueValue As Object)
Dim k = rootKey.OpenSubKey(subKey, True)
If k Is Nothing Then
k = rootKey.CreateSubKey(subKey, RegistryKeyPermissionCheck.ReadWriteSubTree)
End If
k.SetValue(valueName, valueValue)
k.Close()
End Sub
<Extension()>
Sub DeleteValue(rootKey As RegistryKey, key As String, valueName As String)
Using k = rootKey.OpenSubKey(key, True)
If Not k Is Nothing Then
k.DeleteValue(valueName, False)
End If
End Using
End Sub
End Module
Module ControlExtension
<Extension()>
Sub ScaleClientSize(instance As Control, width As Single, height As Single)
instance.ClientSize = New Size(CInt(instance.Font.Height * width), CInt(instance.Font.Height * height))
End Sub
<Extension()>
Sub SetFontStyle(instance As Control, style As FontStyle)
instance.Font = New Font(instance.Font.FontFamily, instance.Font.Size, style)
End Sub
<Extension()>
Sub AddClickAction(instance As Control, action As Action)
AddHandler instance.Click, Sub() action()
End Sub
<Extension()>
Function ClientMousePos(instance As Control) As Point
Return instance.PointToClient(Control.MousePosition)
End Function
<Extension()>
Function GetMaxTextSpace(instance As Control, ParamArray values As String()) As String
Dim ret As String
For x = 4 To 2 Step -1
ret = values.Join("".PadRight(x))
Dim testWidth = TextRenderer.MeasureText(ret, instance.Font).Width
If testWidth < instance.Width - 2 OrElse x = 2 Then Return ret
Next
Return ret
End Function
End Module
Module UIExtensions
<Extension()>
Sub ClearAndDisplose(instance As ToolStripItemCollection)
For Each i In instance.OfType(Of IDisposable).ToArray
i.Dispose()
Next
instance.Clear()
End Sub
<Extension()>
Function ResizeToSmallIconSize(img As Image) As Image
If Not img Is Nothing AndAlso img.Size <> SystemInformation.SmallIconSize Then
Dim s = SystemInformation.SmallIconSize
Dim r As New Bitmap(s.Width, s.Height)
Using g = Graphics.FromImage(DirectCast(r, Image))
g.SmoothingMode = SmoothingMode.AntiAlias
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.PixelOffsetMode = PixelOffsetMode.HighQuality
g.DrawImage(img, 0, 0, s.Width, s.Height)
End Using
Return r
End If
Return img
End Function
<Extension()>
Function ResizeImage(image As Image, ByVal height As Integer) As Image
Dim percentHeight = height / image.Height
Dim ret = New Bitmap(CInt(image.Width * percentHeight), CInt(height))
Using g = Graphics.FromImage(ret)
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.DrawImage(image, 0, 0, ret.Width, ret.Height)
End Using
Return ret
End Function
<Extension()>
Sub SetSelectedPath(d As FolderBrowserDialog, path As String)
If Not Directory.Exists(path) Then path = path.ExistingParent
If Directory.Exists(path) Then d.SelectedPath = path
End Sub
<Extension()>
Sub SetInitDir(d As FileDialog, ParamArray paths As String())
For Each i In paths
If Not Directory.Exists(i) Then i = i.ExistingParent
If Directory.Exists(i) Then
d.InitialDirectory = i
Exit For
End If
Next
End Sub
<Extension()>
Sub SetFilter(d As FileDialog, values As IEnumerable(Of String))
d.Filter = GetFilter(values)
End Sub
Function GetFilter(values As IEnumerable(Of String)) As String
Return "*." + values.Join(";*.") + "|*." + values.Join(";*.") + "|All Files|*.*"
End Function
<Extension()>
Sub SendMessageCue(tb As TextBox, value As String, hideWhenFocused As Boolean)
Dim wParam = If(hideWhenFocused, 0, 1)
Native.SendMessage(tb.Handle, Native.EM_SETCUEBANNER, wParam, value)
End Sub
<Extension()>
Sub SendMessageCue(c As ComboBox, value As String)
Native.SendMessage(c.Handle, Native.CB_SETCUEBANNER, 1, value)
End Sub
Function GetPropertyValue(obj As String, propertyName As String) As Object
obj.GetType.GetProperty(propertyName).GetValue(obj)
End Function
<Extension()>
Sub RemoveSelection(dgv As DataGridView)
For Each i As DataGridViewRow In dgv.SelectedRows
dgv.Rows.Remove(i)
Next
If dgv.SelectedRows.Count = 0 AndAlso dgv.RowCount > 0 Then
dgv.Rows(dgv.RowCount - 1).Selected = True
End If
End Sub
<Extension()>
Function CanMoveUp(dgv As DataGridView) As Boolean
Return dgv.SelectedRows.Count > 0 AndAlso dgv.SelectedRows(0).Index > 0
End Function
<Extension()>
Function CanMoveDown(dgv As DataGridView) As Boolean
Return dgv.SelectedRows.Count > 0 AndAlso dgv.SelectedRows(0).Index < dgv.RowCount - 1
End Function
<Extension()>
Sub MoveSelectionUp(dgv As DataGridView)
If CanMoveUp(dgv) Then
Dim bs = DirectCast(dgv.DataSource, BindingSource)
Dim pos = bs.Position
bs.RaiseListChangedEvents = False
Dim current = bs.Current
bs.Remove(current)
pos -= 1
bs.Insert(pos, current)
bs.Position = pos
bs.RaiseListChangedEvents = True
bs.ResetBindings(False)
End If
End Sub
<Extension()>
Sub MoveSelectionDown(dgv As DataGridView)
If CanMoveDown(dgv) Then
Dim bs = DirectCast(dgv.DataSource, BindingSource)
Dim pos = bs.Position
bs.RaiseListChangedEvents = False
Dim current = bs.Current
bs.Remove(current)
pos += 1
bs.Insert(pos, current)
bs.Position = pos
bs.RaiseListChangedEvents = True
bs.ResetBindings(False)
End If
End Sub
End Module

View File

@@ -1,141 +0,0 @@
Public Structure HSLColor
Public Sub New(color As Color)
SetRGB(color.R, color.G, color.B)
End Sub
Public Sub New(h As Integer, s As Integer, l As Integer)
Hue = h
Saturation = s
Luminosity = l
End Sub
Private HueValue As Double
Property Hue As Integer
Get
Return CInt(HueValue * 240)
End Get
Set(value As Integer)
HueValue = CheckRange(value / 240)
End Set
End Property
Private SaturationValue As Double
Property Saturation As Integer
Get
Return CInt(SaturationValue * 240)
End Get
Set(value As Integer)
SaturationValue = CheckRange(value / 240)
End Set
End Property
Private LuminosityValue As Double
Property Luminosity As Integer
Get
Return CInt(LuminosityValue * 240)
End Get
Set(value As Integer)
LuminosityValue = CheckRange(value / 240)
End Set
End Property
Private Function CheckRange(value As Double) As Double
If value < 0 Then
value = 0
ElseIf value > 1 Then
value = 1
End If
Return value
End Function
Function ToColorAddLuminosity(luminosity As Integer) As Color
Me.Luminosity += luminosity
Return ToColor()
End Function
Function ToColorSetLuminosity(luminosity As Integer) As Color
Me.Luminosity = luminosity
Return ToColor()
End Function
Function ToColor() As Color
Dim r, g, b As Double
If LuminosityValue <> 0 Then
If SaturationValue = 0 Then
b = LuminosityValue
g = LuminosityValue
r = LuminosityValue
Else
Dim temp2 = GetTemp2(Me)
Dim temp1 = 2.0 * LuminosityValue - temp2
r = GetColorComponent(temp1, temp2, HueValue + 1.0 / 3.0)
g = GetColorComponent(temp1, temp2, HueValue)
b = GetColorComponent(temp1, temp2, HueValue - 1.0 / 3.0)
End If
End If
Return Color.FromArgb(CInt(255 * r), CInt(255 * g), CInt(255 * b))
End Function
Private Shared Function GetColorComponent(temp1 As Double,
temp2 As Double,
temp3 As Double) As Double
temp3 = MoveIntoRange(temp3)
If temp3 < 1 / 6 Then
Return temp1 + (temp2 - temp1) * 6.0 * temp3
ElseIf temp3 < 0.5 Then
Return temp2
ElseIf temp3 < 2 / 3 Then
Return temp1 + ((temp2 - temp1) * ((2 / 3) - temp3) * 6)
Else
Return temp1
End If
End Function
Private Shared Function MoveIntoRange(temp3 As Double) As Double
If temp3 < 0 Then
temp3 += 1
ElseIf temp3 > 1 Then
temp3 -= 1
End If
Return temp3
End Function
Private Shared Function GetTemp2(hslColor As HSLColor) As Double
Dim temp2 As Double
If hslColor.LuminosityValue < 0.5 Then
temp2 = hslColor.LuminosityValue * (1.0 + hslColor.SaturationValue)
Else
temp2 = hslColor.LuminosityValue + hslColor.SaturationValue - (hslColor.LuminosityValue * hslColor.SaturationValue)
End If
Return temp2
End Function
Public Shared Function Convert(c As Color) As HSLColor
Dim r As New HSLColor()
r.HueValue = c.GetHue() / 360.0
r.LuminosityValue = c.GetBrightness()
r.SaturationValue = c.GetSaturation()
Return r
End Function
Public Sub SetRGB(red As Integer, green As Integer, blue As Integer)
Dim hc = HSLColor.Convert(Color.FromArgb(red, green, blue))
HueValue = hc.HueValue
SaturationValue = hc.SaturationValue
LuminosityValue = hc.LuminosityValue
End Sub
End Structure

View File

@@ -1,133 +0,0 @@
Namespace UI
Public Module MainModule
Public ReadOnly BR As String = Environment.NewLine
Public ReadOnly BR2 As String = Environment.NewLine + Environment.NewLine
Sub MsgInfo(text As String, Optional content As String = Nothing)
Msg(text, content, MsgIcon.Info, TaskDialogButtons.Ok)
End Sub
Sub MsgError(text As String, Optional content As String = Nothing)
If text = "" Then text = content
If text = "" Then Exit Sub
Using td As New TaskDialog(Of String)
td.AllowCancel = False
If content = "" Then
If text.Length < 80 Then
td.MainInstruction = text
Else
td.Content = text
End If
Else
td.MainInstruction = text
td.Content = content
End If
td.MainIcon = TaskDialogIcon.Error
td.Footer = "[copymsg: Copy Message]"
td.Show()
End Using
End Sub
Sub MsgWarn(text As String, Optional content As String = Nothing)
Msg(text, content, MsgIcon.Warning, TaskDialogButtons.Ok)
End Sub
Function MsgOK(text As String) As Boolean
Return Msg(text, Nothing, MsgIcon.Question, TaskDialogButtons.OkCancel) = DialogResult.OK
End Function
Function MsgQuestion(text As String,
Optional buttons As TaskDialogButtons = TaskDialogButtons.OkCancel) As DialogResult
Return Msg(text, Nothing, MsgIcon.Question, buttons)
End Function
Function MsgQuestion(heading As String,
content As String,
Optional buttons As TaskDialogButtons = TaskDialogButtons.OkCancel) As DialogResult
Return Msg(heading, content, MsgIcon.Question, buttons)
End Function
Function Msg(mainInstruction As String,
content As String,
icon As MsgIcon,
buttons As TaskDialogButtons,
Optional defaultButton As DialogResult = DialogResult.None) As DialogResult
Try
If mainInstruction Is Nothing Then mainInstruction = ""
Using td As New TaskDialog(Of DialogResult)
td.AllowCancel = False
td.DefaultButton = defaultButton
If content Is Nothing Then
If mainInstruction.Length < 80 Then
td.MainInstruction = mainInstruction
Else
td.Content = mainInstruction
End If
Else
td.MainInstruction = mainInstruction
td.Content = content
End If
Select Case icon
Case MsgIcon.Error
td.MainIcon = TaskDialogIcon.Error
Case MsgIcon.Warning
td.MainIcon = TaskDialogIcon.Warning
Case MsgIcon.Info
td.MainIcon = TaskDialogIcon.Info
End Select
If buttons = TaskDialogButtons.OkCancel Then
td.AddButton("OK", DialogResult.OK)
td.AddButton("Cancel", DialogResult.Cancel) 'don't use system language
Else
td.CommonButtons = buttons
End If
Return td.Show()
End Using
Catch ex As Exception
MsgBox(mainInstruction + content, MessageBoxIcon.Error)
End Try
End Function
Sub MsgException(e As Exception, Optional msg As String = Nothing, Optional timeout As Integer = 0)
Try
Using td As New TaskDialog(Of String)
If msg = "" Then
td.MainInstruction = e.GetType.Name + $" ({Application.ProductVersion})"
Else
td.MainInstruction = msg
End If
td.Timeout = timeout
td.Content = e.Message
td.MainIcon = TaskDialogIcon.Error
td.ExpandedInformation = e.ToString
td.Footer = "[copymsg: Copy Message]"
td.Show()
End Using
Catch
MsgBox(e.GetType.Name + BR2 + e.Message + BR2 + e.ToString, MessageBoxIcon.Error)
End Try
End Sub
Sub MsgBox(text As String, icon As MessageBoxIcon)
MessageBox.Show(text, Application.ProductName, MessageBoxButtons.OK, icon)
End Sub
End Module
Public Enum MsgIcon
None = MessageBoxIcon.None
Info = MessageBoxIcon.Information
[Error] = MessageBoxIcon.Error
Warning = MessageBoxIcon.Warning
Question = MessageBoxIcon.Question
End Enum
End Namespace

View File

@@ -1,93 +0,0 @@
Imports System.Runtime.InteropServices
Public Class MediaInfo
Implements IDisposable
Private Handle As IntPtr
Shared Loaded As Boolean
Sub New(sourcepath As String)
If Not Loaded Then
If LoadLibrary("MediaInfo.dll") = IntPtr.Zero Then Throw New Exception("Failed to load MediaInfo.dll.")
Loaded = True
End If
Handle = MediaInfo_New()
MediaInfo_Open(Handle, sourcepath)
End Sub
Public Function GetInfo(streamKind As StreamKind, parameter As String) As String
Return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, 0, parameter, InfoKind.Text, InfoKind.Name))
End Function
#Region "IDisposable"
Private Disposed As Boolean
Sub Dispose() Implements IDisposable.Dispose
If Not Disposed Then
Disposed = True
MediaInfo_Close(Handle)
MediaInfo_Delete(Handle)
End If
End Sub
Protected Overrides Sub Finalize()
Dispose()
End Sub
#End Region
#Region "native"
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode)>
Private Shared Function LoadLibrary(path As String) As IntPtr
End Function
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_New() As IntPtr
End Function
<DllImport("MediaInfo.dll")>
Private Shared Sub MediaInfo_Delete(Handle As IntPtr)
End Sub
<DllImport("MediaInfo.dll", CharSet:=CharSet.Unicode)>
Private Shared Function MediaInfo_Open(Handle As IntPtr, FileName As String) As Integer
End Function
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_Close(Handle As IntPtr) As Integer
End Function
<DllImport("MediaInfo.dll", CharSet:=CharSet.Unicode)>
Private Shared Function MediaInfo_Get(Handle As IntPtr,
StreamKind As StreamKind,
StreamNumber As Integer, Parameter As String,
KindOfInfo As InfoKind,
KindOfSearch As InfoKind) As IntPtr
End Function
#End Region
End Class
Public Enum StreamKind
General
Video
Audio
Text
Chapters
Image
End Enum
Public Enum InfoKind
Name
Text
Measure
Options
NameText
MeasureText
Info
HowTo
End Enum

View File

@@ -1,403 +0,0 @@
Imports System.ComponentModel
Namespace UI
Public Class MenuItemEx
Inherits ToolStripMenuItem
Shared Property UseTooltips As Boolean
Sub New()
End Sub
Sub New(text As String)
MyBase.New(text)
End Sub
Public Overrides Function GetPreferredSize(constrainingSize As Size) As Size
Dim ret = MyBase.GetPreferredSize(constrainingSize)
ret.Height = CInt(Font.Height * 1.4)
Return ret
End Function
Sub SetImage(symbol As Symbol)
SetImage(symbol, Me)
End Sub
Shared Async Sub SetImage(symbol As Symbol, mi As ToolStripMenuItem)
If symbol = Symbol.None Then
mi.Image = Nothing
Exit Sub
End If
Dim img = Await ImageHelp.GetSymbolImageAsync(symbol)
Try
If Not mi.IsDisposed Then
mi.ImageScaling = ToolStripItemImageScaling.None
mi.Image = img
End If
Catch
End Try
End Sub
Private Function ShouldSerializeHelpText() As Boolean
Return HelpValue <> ""
End Function
Private HelpValue As String
Property Help() As String
Get
Return HelpValue
End Get
Set(Value As String)
HelpValue = Value
If UseTooltips Then
If HelpValue <> "" Then
If HelpValue.Length < 80 Then
ToolTipText = HelpValue.TrimEnd("."c)
Else
ToolTipText = "Right-click for help"
End If
End If
End If
End Set
End Property
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
If e.Button = MouseButtons.Right AndAlso Help <> "" Then
CloseAll(Me)
ShowHelp(Text, Help)
End If
MyBase.OnMouseDown(e)
End Sub
Sub ShowHelp(title As String, content As String)
If title <> "" Then title = title.TrimEnd("."c, ":"c)
MsgInfo(title, content)
End Sub
Sub CloseAll(item As Object)
If TypeOf item Is ToolStripItem Then
Dim d = DirectCast(item, ToolStripItem)
CloseAll(d.Owner)
End If
If TypeOf item Is ToolStripDropDown Then
Dim d = DirectCast(item, ToolStripDropDown)
d.Close()
CloseAll(d.OwnerItem)
End If
End Sub
Protected Overrides Sub OnClick(e As EventArgs)
Application.DoEvents()
MyBase.OnClick(e)
End Sub
End Class
Public Class ActionMenuItem
Inherits MenuItemEx
Private Action As Action
Property EnabledFunc As Func(Of Boolean)
Property VisibleFunc As Func(Of Boolean)
Property Form As Form
Sub New()
End Sub
Sub New(text As String, a As Action)
Me.New(text, a, Nothing)
End Sub
Sub New(text As String,
action As Action,
Optional tooltip As String = Nothing,
Optional enabled As Boolean = True)
Me.Text = text
Me.Action = action
Me.Help = tooltip
Me.Enabled = enabled
End Sub
Private ShortcutValue As Keys
Property Shortcut As Keys
Get
Return ShortcutValue
End Get
Set(value As Keys)
ShortcutValue = value
ShortcutKeyDisplayString = KeysHelp.GetKeyString(value) + " "
AddHandler Form.KeyDown, AddressOf KeyDown
End Set
End Property
Sub KeyDown(sender As Object, e As KeyEventArgs)
If Enabled AndAlso e.KeyData = Shortcut AndAlso
If(EnabledFunc Is Nothing, True, EnabledFunc.Invoke) AndAlso
If(VisibleFunc Is Nothing, True, VisibleFunc.Invoke) Then
PerformClick()
e.Handled = True
End If
End Sub
Sub Opening(sender As Object, e As CancelEventArgs)
If Not EnabledFunc Is Nothing Then Enabled = EnabledFunc.Invoke
If Not VisibleFunc Is Nothing Then Visible = VisibleFunc.Invoke
End Sub
Protected Overrides Sub OnClick(e As EventArgs)
Application.DoEvents()
If Not Action Is Nothing Then Action()
MyBase.OnClick(e)
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If Not Form Is Nothing Then RemoveHandler Form.KeyDown, AddressOf KeyDown
Action = Nothing
EnabledFunc = Nothing
VisibleFunc = Nothing
Form = Nothing
End Sub
Shared Function Add(Of T)(items As ToolStripItemCollection,
path As String,
action As Action(Of T),
value As T,
Optional help As String = Nothing) As ActionMenuItem
Return Add(items, path, Sub() action(value), help)
End Function
Shared Function Add(items As ToolStripItemCollection,
path As String) As ActionMenuItem
Return Add(items, path, Nothing)
End Function
Shared Function Add(items As ToolStripItemCollection,
path As String,
action As Action) As ActionMenuItem
Return Add(items, path, action, Symbol.None, Nothing)
End Function
Shared Function Add(items As ToolStripItemCollection,
path As String,
action As Action,
tip As String) As ActionMenuItem
Return Add(items, path, action, Symbol.None, tip)
End Function
Shared Function Add(items As ToolStripItemCollection,
path As String,
action As Action,
symbol As Symbol,
Optional tip As String = Nothing) As ActionMenuItem
Dim a = path.SplitNoEmpty(" | ")
Dim l = items
For x = 0 To a.Length - 1
Dim found = False
For Each i In l.OfType(Of ToolStripMenuItem)()
If x < a.Length - 1 Then
If i.Text = a(x) Then
found = True
l = i.DropDownItems
End If
End If
Next
If Not found Then
If x = a.Length - 1 Then
If a(x) = "-" Then
l.Add(New ToolStripSeparator)
Else
Dim item As New ActionMenuItem(a(x), action, tip)
item.SetImage(symbol)
l.Add(item)
l = item.DropDownItems
Return item
End If
Else
Dim item As New ActionMenuItem()
item.Text = a(x)
l.Add(item)
l = item.DropDownItems
End If
End If
Next
End Function
End Class
Public Class ContextMenuStripEx
Inherits ContextMenuStrip
Private FormValue As Form
Sub New()
End Sub
Sub New(container As IContainer)
MyBase.New(container)
End Sub
Protected Overrides Sub OnOpening(e As CancelEventArgs)
MyBase.OnOpening(e)
MenuHelp.SetRenderer(Me)
End Sub
Protected Overrides Sub OnHandleCreated(e As EventArgs)
MyBase.OnHandleCreated(e)
Font = New Font("Segoe UI", 9)
End Sub
<DefaultValue(GetType(Form), Nothing)>
Property Form As Form
Get
Return FormValue
End Get
Set(value As Form)
AddHandler value.Disposed, Sub() Dispose()
FormValue = value
End Set
End Property
Function Add(path As String) As ActionMenuItem
Return Add(path, Nothing)
End Function
Function Add(path As String,
action As Action) As ActionMenuItem
Return Add(path, action, Nothing)
End Function
Function Add(path As String,
action As Action,
help As String) As ActionMenuItem
Return Add(path, action, help, True)
End Function
Function Add(path As String,
action As Action,
help As String,
enabled As Boolean) As ActionMenuItem
Dim ret = ActionMenuItem.Add(Items, path, action)
If ret Is Nothing Then Exit Function
ret.Form = Form
ret.Help = help
ret.Enabled = enabled
AddHandler Opening, AddressOf ret.Opening
Return ret
End Function
Function Add(path As String,
action As Action,
shortcut As Keys,
enabledFunc As Func(Of Boolean),
Optional help As String = Nothing) As ActionMenuItem
Dim ret = ActionMenuItem.Add(Items, path, action)
ret.Form = Form
ret.Shortcut = shortcut
ret.EnabledFunc = enabledFunc
ret.Help = help
AddHandler Opening, AddressOf ret.Opening
Return ret
End Function
Function GetTips() As StringPairList
Dim ret As New StringPairList
For Each i In GetItems.OfType(Of ActionMenuItem)()
If i.Help <> "" Then
Dim pair As New StringPair
If i.Text.EndsWith("...") Then
pair.Name = i.Text.TrimEnd("."c)
Else
pair.Name = i.Text
End If
pair.Value = i.Help
ret.Add(pair)
End If
Next
Return ret
End Function
Function GetKeys() As StringPairList
Dim ret As New StringPairList
For Each i In GetItems.OfType(Of ActionMenuItem)()
If i.ShortcutKeyDisplayString <> "" Then
Dim sp As New StringPair
If i.Text.EndsWith("...") Then
sp.Name = i.Text.TrimEnd("."c)
Else
sp.Name = i.Text
End If
sp.Value = i.ShortcutKeyDisplayString
ret.Add(sp)
End If
Next
Return ret
End Function
Function GetItems() As List(Of ToolStripItem)
Dim ret As New List(Of ToolStripItem)
AddItemsRecursive(Items, ret)
Return ret
End Function
Shared Sub AddItemsRecursive(searchList As ToolStripItemCollection, returnList As List(Of ToolStripItem))
For Each i As ToolStripItem In searchList
returnList.Add(i)
If TypeOf i Is ToolStripDropDownItem Then
AddItemsRecursive(DirectCast(i, ToolStripDropDownItem).DropDownItems, returnList)
End If
Next
End Sub
End Class
Public Class MenuHelp
Shared Sub SetRenderer(ms As ToolStrip)
ms.Renderer = New ToolStripRendererEx(ToolStripRenderModeEx.SystemAuto)
End Sub
End Class
Public Enum ToolStripRenderModeEx
SystemAuto
SystemDefault
Win7Auto
Win7Default
Win10Auto
Win10Default
End Enum
End Namespace

View File

@@ -1,465 +0,0 @@
Imports System.ComponentModel
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports System.Text
Imports vbnet.UI
Public Class OSVersion
Shared Property Windows7 As Single = 6.1
Shared Property Windows8 As Single = 6.2
Shared Property Windows10 As Single = 10.0
Shared ReadOnly Property Current As Single
Get
Return CSng(Environment.OSVersion.Version.Major + Environment.OSVersion.Version.Minor / 10)
End Get
End Property
End Class
Public Class ProcessHelp
Shared Sub Start(cmd As String, Optional args As String = Nothing)
Try
Process.Start(cmd, args)
Catch ex As Exception
If cmd Like "http*://*" Then
MsgError("Failed to open URL with browser." + BR2 + cmd, ex.Message)
ElseIf File.Exists(cmd) Then
MsgError("Failed to launch file." + BR2 + cmd, ex.Message)
ElseIf Directory.Exists(cmd) Then
MsgError("Failed to launch directory." + BR2 + cmd, ex.Message)
Else
MsgException(ex, "Failed to execute command:" + BR2 + cmd + BR2 + "Arguments:" + BR2 + args)
End If
End Try
End Sub
End Class
Public Class KeysHelp
Private Shared Converter As TypeConverter = TypeDescriptor.GetConverter(GetType(Keys))
Private Shared KeysTexts As Dictionary(Of Keys, String)
Shared Sub New()
KeysTexts = New Dictionary(Of Keys, String)
KeysTexts(Keys.Add) = "+ (Numpad)"
KeysTexts(Keys.Back) = "Back"
KeysTexts(Keys.Decimal) = "Decimal"
KeysTexts(Keys.Delete) = "Delete"
KeysTexts(Keys.Divide) = "Divide"
KeysTexts(Keys.Down) = "Down"
KeysTexts(Keys.End) = "End"
KeysTexts(Keys.Enter) = "Enter"
KeysTexts(Keys.Escape) = "Escape"
KeysTexts(Keys.Home) = "Home"
KeysTexts(Keys.Insert) = "Insert"
KeysTexts(Keys.Left) = "Left"
KeysTexts(Keys.Multiply) = "Multiply"
KeysTexts(Keys.Next) = "Page Down"
KeysTexts(Keys.Prior) = "Page Up"
KeysTexts(Keys.Right) = "Right"
KeysTexts(Keys.Space) = "Space"
KeysTexts(Keys.Subtract) = "- (Numpad)"
KeysTexts(Keys.Up) = "Up"
KeysTexts(Keys.Control) = "Control"
KeysTexts(Keys.Alt) = "Alt"
KeysTexts(Keys.Shift) = "Shift"
KeysTexts(Keys.D0) = "0"
KeysTexts(Keys.D1) = "1"
KeysTexts(Keys.D2) = "2"
KeysTexts(Keys.D3) = "3"
KeysTexts(Keys.D4) = "4"
KeysTexts(Keys.D5) = "5"
KeysTexts(Keys.D6) = "6"
KeysTexts(Keys.D7) = "7"
KeysTexts(Keys.D8) = "8"
KeysTexts(Keys.D9) = "9"
KeysTexts(Keys.NumPad0) = "0 (Numpad)"
KeysTexts(Keys.NumPad1) = "1 (Numpad)"
KeysTexts(Keys.NumPad2) = "2 (Numpad)"
KeysTexts(Keys.NumPad3) = "3 (Numpad)"
KeysTexts(Keys.NumPad4) = "4 (Numpad)"
KeysTexts(Keys.NumPad5) = "5 (Numpad)"
KeysTexts(Keys.NumPad6) = "6 (Numpad)"
KeysTexts(Keys.NumPad7) = "7 (Numpad)"
KeysTexts(Keys.NumPad8) = "8 (Numpad)"
KeysTexts(Keys.NumPad9) = "9 (Numpad)"
End Sub
Shared Function GetKeyString(k As Keys) As String
If k = Keys.None Then Return ""
Dim s = ""
If (k And Keys.Control) = Keys.Control Then
k = k Xor Keys.Control
s += "Ctrl+"
End If
If (k And Keys.Alt) = Keys.Alt Then
k = k Xor Keys.Alt
s += "Alt+"
End If
If (k And Keys.Shift) = Keys.Shift Then
k = k Xor Keys.Shift
s += "Shift+"
End If
If KeysTexts.ContainsKey(k) Then
s += KeysTexts(k)
Else
Dim value = MapVirtualKey(CInt(k), 2) 'MAPVK_VK_TO_CHAR
If value = 0 OrElse (value And 1 << 31) = 1 << 31 Then
s += k.ToString
Else
s += Convert.ToChar(value)
End If
End If
Return s
End Function
<DllImport("user32.dll")>
Shared Function MapVirtualKey(wCode As Integer, wMapType As Integer) As Integer
End Function
End Class
<Serializable>
Public Class StringPair
Implements IComparable(Of StringPair)
Property Name As String
Property Value As String
Sub New()
End Sub
Sub New(name As String, text As String)
Me.Name = name
Me.Value = text
End Sub
Function CompareTo(other As StringPair) As Integer Implements System.IComparable(Of StringPair).CompareTo
Return Name.CompareTo(other.Name)
End Function
End Class
<Serializable()>
Public Class StringPairList
Inherits List(Of StringPair)
Sub New()
End Sub
Sub New(list As IEnumerable(Of StringPair))
AddRange(list)
End Sub
Overloads Sub Add(name As String, text As String)
Add(New StringPair(name, text))
End Sub
End Class
Public Class Folder
#Region "System"
Shared ReadOnly Property Desktop() As String
Get
Return Environment.GetFolderPath(Environment.SpecialFolder.Desktop).FixDir
End Get
End Property
Shared ReadOnly Property Startup() As String
Get
Return Application.StartupPath.FixDir
End Get
End Property
Shared ReadOnly Property Current() As String
Get
Return Environment.CurrentDirectory.FixDir
End Get
End Property
Shared ReadOnly Property Temp() As String
Get
Return Path.GetTempPath.FixDir
End Get
End Property
Shared ReadOnly Property System() As String
Get
Return Environment.SystemDirectory.FixDir
End Get
End Property
Shared ReadOnly Property Programs() As String
Get
Return GetFolderPath(Environment.SpecialFolder.ProgramFiles).FixDir
End Get
End Property
Shared ReadOnly Property Home() As String
Get
Return GetFolderPath(Environment.SpecialFolder.UserProfile).FixDir
End Get
End Property
Shared ReadOnly Property AppDataCommon() As String
Get
Return GetFolderPath(Environment.SpecialFolder.CommonApplicationData).FixDir
End Get
End Property
Shared ReadOnly Property AppDataLocal() As String
Get
Return GetFolderPath(Environment.SpecialFolder.LocalApplicationData).FixDir
End Get
End Property
Shared ReadOnly Property AppDataRoaming() As String
Get
Return GetFolderPath(Environment.SpecialFolder.ApplicationData).FixDir
End Get
End Property
Shared ReadOnly Property Windows() As String
Get
Return GetFolderPath(Environment.SpecialFolder.Windows).FixDir
End Get
End Property
#End Region
#Region "StaxRip"
Shared ReadOnly Property Apps As String
Get
Return Folder.Startup + "Apps\"
End Get
End Property
#End Region
<DllImport("shfolder.dll", CharSet:=CharSet.Unicode)>
Private Shared Function SHGetFolderPath(hwndOwner As IntPtr, nFolder As Integer, hToken As IntPtr, dwFlags As Integer, lpszPath As StringBuilder) As Integer
End Function
Private Shared Function GetFolderPath(folder As Environment.SpecialFolder) As String
Dim sb As New StringBuilder(260)
SHGetFolderPath(IntPtr.Zero, CInt(folder), IntPtr.Zero, 0, sb)
Dim ret = sb.ToString.FixDir '.NET fails on 'D:'
Call New FileIOPermission(FileIOPermissionAccess.PathDiscovery, ret).Demand()
Return ret
End Function
End Class
Public Class PathBase
Shared ReadOnly Property Separator() As Char
Get
Return Path.DirectorySeparatorChar
End Get
End Property
Shared Function IsSameBase(a As String, b As String) As Boolean
Return FilePath.GetBase(a).EqualIgnoreCase(FilePath.GetBase(b))
End Function
Shared Function IsSameDir(a As String, b As String) As Boolean
Return FilePath.GetDir(a).EqualIgnoreCase(FilePath.GetDir(b))
End Function
Shared Function IsValidFileSystemName(name As String) As Boolean
If name = "" Then Return False
Dim chars = """*/:<>?\|^".ToCharArray
For Each i In name.ToCharArray
If chars.Contains(i) Then Return False
If Convert.ToInt32(i) < 32 Then Return False
Next
Return True
End Function
Shared Function RemoveIllegalCharsFromName(name As String) As String
If name = "" Then Return ""
Dim chars = """*/:<>?\|^".ToCharArray
For Each i In name.ToCharArray
If chars.Contains(i) Then
name = name.Replace(i, "_")
End If
Next
For x = 1 To 31
If name.Contains(Convert.ToChar(x)) Then
name = name.Replace(Convert.ToChar(x), "_"c)
End If
Next
Return name
End Function
End Class
Public Class DirPath
Inherits PathBase
Shared Function TrimTrailingSeparator(path As String) As String
If path = "" Then Return ""
If path.EndsWith(Separator) AndAlso Not path.Length <= 3 Then
Return path.TrimEnd(Separator)
End If
Return path
End Function
Shared Function FixSeperator(path As String) As String
If path.Contains("\") AndAlso Separator <> "\" Then
path = path.Replace("\", Separator)
End If
If path.Contains("/") AndAlso Separator <> "/" Then
path = path.Replace("/", Separator)
End If
Return path
End Function
Shared Function GetParent(path As String) As String
If path = "" Then Return ""
Dim temp = TrimTrailingSeparator(path)
If temp.Contains(Separator) Then path = temp.LeftLast(Separator) + Separator
Return path
End Function
Shared Function GetName(path As String) As String
If path = "" Then Return ""
path = TrimTrailingSeparator(path)
Return path.RightLast(Separator)
End Function
Shared Function IsInSysDir(path As String) As Boolean
If path = "" Then Return False
If Not path.EndsWith("\") Then path += "\"
Return path.ToUpper.Contains(Folder.Programs.ToUpper)
End Function
Shared Function IsFixedDrive(path As String) As Boolean
Try
If path <> "" Then Return New DriveInfo(path).DriveType = DriveType.Fixed
Catch ex As Exception
End Try
End Function
End Class
Public Class FilePath
Inherits PathBase
Private Value As String
Sub New(path As String)
Value = path
End Sub
Shared Function GetDir(path As String) As String
If path = "" Then Return ""
If path.Contains("\") Then path = path.LeftLast("\") + "\"
Return path
End Function
Shared Function GetDirAndBase(path As String) As String
Return GetDir(path) + GetBase(path)
End Function
Shared Function GetName(path As String) As String
If Not path Is Nothing Then
Dim index = path.LastIndexOf(IO.Path.DirectorySeparatorChar)
If index > -1 Then
Return path.Substring(index + 1)
End If
End If
Return path
End Function
Shared Function GetExtFull(filepath As String) As String
Return GetExt(filepath, True)
End Function
Shared Function GetExt(filepath As String) As String
Return GetExt(filepath, False)
End Function
Shared Function GetExt(filepath As String, dot As Boolean) As String
If filepath = "" Then Return ""
Dim chars = filepath.ToCharArray
For x = filepath.Length - 1 To 0 Step -1
If chars(x) = Separator Then Return ""
If chars(x) = "."c Then Return filepath.Substring(x + If(dot, 0, 1)).ToLower
Next
Return ""
End Function
Shared Function GetDirNoSep(path As String) As String
path = GetDir(path)
If path.EndsWith(Separator) Then path = TrimSep(path)
Return path
End Function
Shared Function GetBase(path As String) As String
If path = "" Then Return ""
Dim ret = path
If ret.Contains(Separator) Then ret = ret.RightLast(Separator)
If ret.Contains(".") Then ret = ret.LeftLast(".")
Return ret
End Function
Shared Function TrimSep(path As String) As String
If path = "" Then Return ""
If path.EndsWith(Separator) AndAlso Not path.EndsWith(":" + Separator) Then
Return path.TrimEnd(Separator)
End If
Return path
End Function
Shared Function GetDirNameOnly(path As String) As String
Return FilePath.GetDirNoSep(path).RightLast("\")
End Function
End Class
Public Class OS
Shared Function GetTextEditor() As String
Dim ret = GetAssociatedApplication(".txt")
If ret <> "" Then Return ret
Return "notepad.exe"
End Function
Shared Function GetAssociatedApplication(ext As String) As String
Dim c = 0UI
'ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE
If 1 = Native.AssocQueryString(&H40, 2, ext, Nothing, Nothing, c) Then
If c > 0 Then
Dim sb As New StringBuilder(CInt(c))
'ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE
If 0 = Native.AssocQueryString(&H40, 2, ext, Nothing, sb, c) Then
Dim ret = sb.ToString
If File.Exists(ret) Then Return ret
End If
End If
End If
End Function
End Class

View File

@@ -1,13 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>false</MySubMain>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>1</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

View File

@@ -1,35 +0,0 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
<Assembly: AssemblyTitle("vbnet")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("vbnet")>
<Assembly: AssemblyCopyright("Copyright © 2017")>
<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("82111131-50ca-475d-afda-bafda7e5bf69")>
' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -1,63 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Imports System
Namespace My.Resources
'This class was auto-generated by the StronglyTypedResourceBuilder
'class via a tool like ResGen or Visual Studio.
'To add or remove a member, edit your .ResX file then rerun ResGen
'with the /str option, or rebuild your VS project.
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Returns the cached ResourceManager instance used by this class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("vbnet.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set
resourceCulture = value
End Set
End Property
End Module
End Namespace

View File

@@ -1,73 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.42000
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Partial Friend NotInheritable Class MySettings
Inherits Global.System.Configuration.ApplicationSettingsBase
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
#Region "My.Settings Auto-Save Functionality"
#If _MyType = "WindowsForms" Then
Private Shared addedHandler As Boolean
Private Shared addedHandlerLockObject As New Object
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs)
If My.Application.SaveMySettingsOnExit Then
My.Settings.Save()
End If
End Sub
#End If
#End Region
Public Shared ReadOnly Property [Default]() As MySettings
Get
#If _MyType = "WindowsForms" Then
If Not addedHandler Then
SyncLock addedHandlerLockObject
If Not addedHandler Then
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
addedHandler = True
End If
End SyncLock
End If
#End If
Return defaultInstance
End Get
End Property
End Class
End Namespace
Namespace My
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
Friend Module MySettingsProperty
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
Friend ReadOnly Property Settings() As Global.vbnet.My.MySettings
Get
Return Global.vbnet.My.MySettings.Default
End Get
End Property
End Module
End Namespace

View File

@@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -1,278 +0,0 @@
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Native
Public Delegate Function CallbackHandler(handle As IntPtr, parameter As Integer) As Boolean
<DllImport("gdi32.dll")>
Public Shared Function ExcludeClipRect(hdc As IntPtr, nLeftRect As Integer, nTopRect As Integer, nRightRect As Integer, nBottomRect As Integer) As Integer
End Function
#Region "Constants"
Friend Const EM_SETCUEBANNER As Integer = &H1501
Friend Const CB_SETCUEBANNER As Integer = &H1703
#End Region
#Region "Function"
#Region "user32.dll"
<DllImport("user32.dll", SetLastError:=True)>
Shared Function SetWindowPos(hWnd As IntPtr,
hWndInsertAfter As IntPtr,
X As Integer,
Y As Integer,
cx As Integer,
cy As Integer,
uFlags As UInteger) As Boolean
End Function
<DllImport("user32.dll")>
Shared Function GetWindowLong(hWnd As IntPtr, nIndex As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function RegisterWindowMessage(id As String) As Integer
End Function
<DllImport("user32.dll")>
Shared Function RegisterHotKey(hWnd As IntPtr, id As Integer, fsModifiers As Integer, vk As Integer) As Boolean
End Function
<DllImport("user32.dll")>
Shared Function MapVirtualKey(wCode As Integer, wMapType As Integer) As Integer
End Function
<DllImport("user32.dll")>
Shared Function UnregisterHotKey(hWnd As IntPtr, id As Integer) As Boolean
End Function
<DllImport("user32.dll")>
Shared Function GetForegroundWindow() As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)>
Shared Function GetWindowThreadProcessId(hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
End Function
<DllImport("user32.dll")>
Shared Function SetForegroundWindow(handle As IntPtr) As Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function GetWindowModuleFileName(hwnd As IntPtr,
lpszFileName As StringBuilder,
cchFileNameMax As UInteger) As UInteger
End Function
<DllImport("user32.dll")>
Shared Function SendMessage(handle As IntPtr,
message As Int32,
wParam As IntPtr,
lParam As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function SendMessage(hWnd As IntPtr,
Msg As Int32,
wParam As IntPtr,
lParam As String) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function SendMessage(hWnd As IntPtr,
Msg As Int32,
wParam As Integer,
lParam As Integer) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function SendMessage(hWnd As IntPtr,
Msg As Int32,
wParam As Integer,
lParam As String) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function SendMessage(hWnd As IntPtr,
Msg As Int32,
ByRef wParam As IntPtr,
lParam As StringBuilder) As IntPtr
End Function
<DllImport("user32.dll")>
Shared Function SendMessageTimeout(windowHandle As IntPtr,
msg As Integer,
wParam As IntPtr,
lParam As IntPtr,
flags As Integer,
timeout As Integer,
ByRef result As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function PostMessage(hwnd As IntPtr,
wMsg As Integer,
wParam As IntPtr,
lParam As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")>
Shared Sub ReleaseCapture()
End Sub
<DllImport("user32.dll")>
Public Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As Integer
End Function
#End Region
#Region "kernel32.dll"
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode)>
Shared Function LoadLibrary(path As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)>
Shared Function FreeLibrary(hModule As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Shared Function FormatMessage(dwFlags As Integer,
lpSource As IntPtr,
dwMessageId As Integer,
dwLanguageId As Integer,
ByRef lpBuffer As String,
nSize As Integer,
Arguments As IntPtr) As Integer
End Function
#End Region
<DllImport("uxtheme.dll", CharSet:=CharSet.Unicode)>
Shared Function SetWindowTheme(hWnd As IntPtr,
pszSubAppName As String,
pszSubIdList As String) As Integer
End Function
<DllImport("Shlwapi.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Shared Function AssocQueryString(
flags As UInteger,
str As UInteger,
pszAssoc As String,
pszExtra As String,
pszOut As StringBuilder,
ByRef pcchOut As UInteger) As UInteger
End Function
#End Region
#Region "Structures"
Public Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
Sub New(r As Rectangle)
Left = r.Left
Top = r.Top
Right = r.Right
Bottom = r.Bottom
End Sub
Public Sub New(left As Integer, top As Integer, right As Integer, bottom As Integer)
Me.Left = left
Me.Top = top
Me.Right = right
Me.Bottom = bottom
End Sub
Function ToRectangle() As Rectangle
Return Rectangle.FromLTRB(Left, Top, Right, Bottom)
End Function
End Structure
Public Structure SHFILEINFO
Public hIcon As IntPtr
Public iIcon As Integer
Public dwAttributes As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)>
Public szDisplayName As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)>
Public szTypeName As String
End Structure
Public Structure NMHDR
Public hwndFrom As Integer
Public idFrom As Integer
Public code As Integer
End Structure
Public Structure NCCALCSIZE_PARAMS
Public rgrc0, rgrc1, rgrc2 As RECT
Public lppos As IntPtr
End Structure
#End Region
End Class
Public Class Taskbar
Private Taskbar As ITaskbarList3 = DirectCast(New TaskBarCommunication(), ITaskbarList3)
Property Handle As IntPtr
Public Sub New(handle As IntPtr)
Me.Handle = handle
End Sub
<ComImportAttribute>
<InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)>
<GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")>
Private Interface ITaskbarList3
'ITaskbarList
<PreserveSig> Sub HrInit()
<PreserveSig> Sub AddTab(hwnd As IntPtr)
<PreserveSig> Sub DeleteTab(hwnd As IntPtr)
<PreserveSig> Sub ActivateTab(hwnd As IntPtr)
<PreserveSig> Sub SetActiveAlt(hwnd As IntPtr)
'ITaskbarList2
<PreserveSig> Sub MarkFullscreenWindow(hwnd As IntPtr, <MarshalAs(UnmanagedType.Bool)> fFullscreen As Boolean)
'ITaskbarList3
<PreserveSig> Sub SetProgressValue(hwnd As IntPtr, ullCompleted As UInt64, ullTotal As UInt64)
<PreserveSig> Sub SetProgressState(hwnd As IntPtr, state As TaskbarStates)
End Interface
<ComImportAttribute>
<ClassInterfaceAttribute(ClassInterfaceType.None)>
<GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")>
Private Class TaskBarCommunication
End Class
Public Sub SetState(taskbarState As TaskbarStates)
Taskbar.SetProgressState(Handle, taskbarState)
End Sub
Public Sub SetValue(progressValue As Double, progressMax As Double)
Taskbar.SetProgressValue(Handle, CULng(Math.Truncate(progressValue)), CULng(Math.Truncate(progressMax)))
End Sub
End Class
Public Enum TaskbarStates
NoProgress = 0
Indeterminate = &H1
Normal = &H2
[Error] = &H4
Paused = &H8
End Enum

View File

@@ -1,551 +0,0 @@
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Text.RegularExpressions
Namespace UI
Public Delegate Function PFTASKDIALOGCALLBACK(hwnd As IntPtr,
msg As UInteger,
wParam As IntPtr,
lParam As IntPtr,
lpRefData As IntPtr) As Integer
Public Class TaskDialog(Of T)
Inherits TaskDialog
Implements IDisposable
Private IdValueDic As New Dictionary(Of Integer, T)
Private IdTextDic As New Dictionary(Of Integer, String)
Private CommandLinkShieldList As New List(Of Integer)
Private ButtonArray As IntPtr, RadioButtonArray As IntPtr
Private Buttons As New List(Of TASKDIALOG_BUTTON)
Private RadioButtons As New List(Of TASKDIALOG_BUTTON)
Private Config As TASKDIALOGCONFIG
Sub New()
Config = New TASKDIALOGCONFIG()
Config.cbSize = CUInt(Marshal.SizeOf(Config))
Config.hwndParent = GetHandle()
Config.hInstance = IntPtr.Zero
Config.dwFlags = Flags.TDF_ALLOW_DIALOG_CANCELLATION
Config.dwCommonButtons = TaskDialogButtons.None
Config.MainIcon = New TASKDIALOGCONFIG_ICON_UNION(0)
Config.FooterIcon = New TASKDIALOGCONFIG_ICON_UNION(0)
Config.cxWidth = 0
Config.cButtons = 0
Config.cRadioButtons = 0
Config.pButtons = IntPtr.Zero
Config.pRadioButtons = IntPtr.Zero
Config.nDefaultButton = 0
Config.nDefaultRadioButton = 0
Config.pszWindowTitle = Application.ProductName
Config.pszMainInstruction = ""
Config.pszContent = ""
Config.pszVerificationText = Nothing
Config.pszExpandedInformation = Nothing
Config.pszExpandedControlText = Nothing
Config.pszCollapsedControlText = Nothing
Config.pszFooter = Nothing
Config.pfCallback = New PFTASKDIALOGCALLBACK(AddressOf DialogProc)
End Sub
Function GetHandle() As IntPtr
Dim r As New StringBuilder(260)
Dim h = GetForegroundWindow()
GetWindowModuleFileName(h, r, 260)
If r.ToString.Replace(".vshost", "").Base = Application.ExecutablePath.Base Then Return h
End Function
#Region "Constants"
Const TDE_CONTENT As Integer = 0
Const TDE_EXPANDED_INFORMATION As Integer = 1
Const TDE_FOOTER As Integer = 2
Const TDE_MAIN_INSTRUCTION As Integer = 3
Const TDN_CREATED As Integer = 0
Const TDN_NAVIGATED As Integer = 1
Const TDN_BUTTON_CLICKED As Integer = 2
Const TDN_HYPERLINK_CLICKED As Integer = 3
Const TDN_TIMER As Integer = 4
Const TDN_DESTROYED As Integer = 5
Const TDN_RADIO_BUTTON_CLICKED As Integer = 6
Const TDN_DIALOG_CONSTRUCTED As Integer = 7
Const TDN_VERIFICATION_CLICKED As Integer = 8
Const TDN_HELP As Integer = 9
Const TDN_EXPANDO_BUTTON_CLICKED As Integer = 10
Const TDM_NAVIGATE_PAGE As Integer = &H400 + 101
Const TDM_CLICK_BUTTON As Integer = &H400 + 102 'wParam = Button ID
Const TDM_SET_MARQUEE_PROGRESS_BAR As Integer = &H400 + 103 'wParam = 0 (nonMarque) wParam != 0 (Marquee)
Const TDM_SET_PROGRESS_BAR_STATE As Integer = &H400 + 104 'wParam = new progress state
Const TDM_SET_PROGRESS_BAR_RANGE As Integer = &H400 + 105 'lParam = MAKELPARAM(nMinRange, nMaxRange)
Const TDM_SET_PROGRESS_BAR_POS As Integer = &H400 + 106 'wParam = new position
Const TDM_SET_PROGRESS_BAR_MARQUEE As Integer = &H400 + 107 'wParam = 0 (stop marquee), wParam != 0 (start marquee), lparam = speed (milliseconds between repaints)
Const TDM_SET_ELEMENT_TEXT As Integer = &H400 + 108 'wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
Const TDM_CLICK_RADIO_BUTTON As Integer = &H400 + 110 'wParam = Radio Button ID
Const TDM_ENABLE_BUTTON As Integer = &H400 + 111 'lParam = 0 (disable), lParam != 0 (enable), wParam = Button ID
Const TDM_ENABLE_RADIO_BUTTON As Integer = &H400 + 112 'lParam = 0 (disable), lParam != 0 (enable), wParam = Radio Button ID
Const TDM_CLICK_VERIFICATION As Integer = &H400 + 113 'wParam = 0 (unchecked), 1 (checked), lParam = 1 (set key focus)
Const TDM_UPDATE_ELEMENT_TEXT As Integer = &H400 + 114 'wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
Const TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE As Integer = &H400 + 115 'wParam = Button ID, lParam = 0 (elevation not required), lParam != 0 (elevation required)
Const TDM_UPDATE_ICON As Integer = &H400 + 116 'wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise)
#End Region
#Region "Properties"
Private AllowCancelValue As Boolean
WriteOnly Property AllowCancel() As Boolean
Set(Value As Boolean)
If Value Then
Config.dwFlags = Config.dwFlags Or Flags.TDF_ALLOW_DIALOG_CANCELLATION
ElseIf (Config.dwFlags And Flags.TDF_ALLOW_DIALOG_CANCELLATION) = Flags.TDF_ALLOW_DIALOG_CANCELLATION Then
Config.dwFlags = Config.dwFlags Xor Flags.TDF_ALLOW_DIALOG_CANCELLATION
End If
End Set
End Property
Property MainInstruction() As String
Get
Return Config.pszMainInstruction
End Get
Set(Value As String)
Config.pszMainInstruction = Value
End Set
End Property
Property Content() As String
Get
Return Config.pszContent
End Get
Set(Value As String)
Config.pszContent = ExpandWikiMarkup(Value)
End Set
End Property
Property ExpandedInformation() As String
Get
Return Config.pszExpandedInformation
End Get
Set(Value As String)
Config.pszExpandedInformation = ExpandWikiMarkup(Value)
End Set
End Property
Property VerificationText() As String
Get
Return Config.pszVerificationText
End Get
Set(Value As String)
Config.pszVerificationText = Value
End Set
End Property
Property DefaultButton() As DialogResult
Get
Return CType(Config.nDefaultButton, DialogResult)
End Get
Set(Value As DialogResult)
Config.nDefaultButton = Value
End Set
End Property
Property Footer() As String
Get
Return Config.pszFooter
End Get
Set(Value As String)
Config.pszFooter = ExpandWikiMarkup(Value)
End Set
End Property
WriteOnly Property MainIcon() As TaskDialogIcon
Set(Value As TaskDialogIcon)
Config.MainIcon = New TASKDIALOGCONFIG_ICON_UNION(Value)
End Set
End Property
Private SelectedIDValue As Integer = -1
Property SelectedID As Integer
Get
Return SelectedIDValue
End Get
Set(value As Integer)
For Each i In IdValueDic
If i.Key = value Then SelectedIDValue = value
Next
End Set
End Property
Private SelectedValueValue As T
Property SelectedValue() As T
Get
If IdValueDic.ContainsKey(SelectedID) Then Return IdValueDic(SelectedID)
Return SelectedValueValue
End Get
Set(value As T)
SelectedValueValue = value
End Set
End Property
Private SelectedTextValue As String
Property SelectedText() As String
Get
If IdTextDic.ContainsKey(SelectedID) Then Return IdTextDic(SelectedID)
Return SelectedTextValue
End Get
Set(value As String)
SelectedTextValue = value
End Set
End Property
Property CheckBoxChecked() As Boolean
Get
Return (Config.dwFlags And Flags.TDF_VERIFICATION_FLAG_CHECKED) = Flags.TDF_VERIFICATION_FLAG_CHECKED
End Get
Set(value As Boolean)
If value Then
Config.dwFlags = Config.dwFlags Or Flags.TDF_VERIFICATION_FLAG_CHECKED
ElseIf CheckBoxChecked Then
Config.dwFlags = Config.dwFlags Xor Flags.TDF_VERIFICATION_FLAG_CHECKED
End If
End Set
End Property
Private CommonButtonsValue As TaskDialogButtons
Property CommonButtons() As TaskDialogButtons
Get
Return Config.dwCommonButtons
End Get
Set(Value As TaskDialogButtons)
Config.dwCommonButtons = Value
End Set
End Property
Private TimeoutValue As Integer
Property Timeout As Integer
Get
Return CInt(TimeoutValue / 1000)
End Get
Set(Value As Integer)
TimeoutValue = Value * 1000
If Value > 0 Then
Config.dwFlags = Config.dwFlags Or Flags.TDF_CALLBACK_TIMER
End If
End Set
End Property
#End Region
#Region "Methods"
Sub AddButton(text As String, value As T)
Dim id = 1000 + IdValueDic.Count + 1
IdValueDic(id) = value
Buttons.Add(New TASKDIALOG_BUTTON(id, text))
End Sub
Function ExpandWikiMarkup(value As String) As String
If value.Contains("[") Then
Dim re As New Regex("\[(\w+?:.*?) (.+?)\]")
Dim m = re.Match(value)
If m.Success Then
Config.dwFlags = Config.dwFlags Or Flags.TDF_ENABLE_HYPERLINKS
value = re.Replace(value, "<a href=""$1"">$2</a>")
End If
End If
Return value
End Function
Sub AddCommandLink(text As String, value As T)
Dim id = 1000 + IdValueDic.Count + 1
IdValueDic(id) = value
IdTextDic(id) = text
Buttons.Add(New TASKDIALOG_BUTTON(id, text))
Config.dwFlags = Config.dwFlags Or Flags.TDF_USE_COMMAND_LINKS
End Sub
Sub AddCommandLink(text As String,
description As String,
value As T,
Optional setShield As Boolean = False)
Dim id = 1000 + IdValueDic.Count + 1
IdValueDic(id) = value
If setShield Then CommandLinkShieldList.Add(id)
If description <> "" Then text = text + BR + description
Buttons.Add(New TASKDIALOG_BUTTON(id, text))
Config.dwFlags = Config.dwFlags Or Flags.TDF_USE_COMMAND_LINKS
End Sub
Sub AddRadioButton(text As String, value As T)
Dim id = 1000 + IdValueDic.Count + 1
IdValueDic(id) = value
RadioButtons.Add(New TASKDIALOG_BUTTON(id, text))
End Sub
Function Show() As T
MarshalDialogControlStructs()
Dim isChecked As Boolean
Dim hr = TaskDialogIndirect(Config, Nothing, Nothing, isChecked)
CheckBoxChecked = isChecked
If hr < 0 Then Marshal.ThrowExceptionForHR(hr)
If TypeOf SelectedValue Is DialogResult Then SelectedValue = DirectCast(CObj(SelectedID), T)
Return SelectedValue
End Function
Private ExitTickCount As Integer
Private Function DialogProc(hwnd As IntPtr,
msg As UInteger,
wParam As IntPtr,
lParam As IntPtr,
lpRefData As IntPtr) As Integer
Select Case msg
Case TDN_BUTTON_CLICKED, TDN_RADIO_BUTTON_CLICKED
If TypeOf SelectedValue Is DialogResult Then
SelectedIDValue = wParam.ToInt32
Else
SelectedID = wParam.ToInt32
End If
Case TDN_TIMER
If ExitTickCount = 0 Then
ExitTickCount = Environment.TickCount + Timeout * 1000
End If
If Environment.TickCount > ExitTickCount Then
SendMessage(hwnd, TDM_CLICK_BUTTON, DialogResult.OK, 0)
End If
Case TDN_HYPERLINK_CLICKED
Dim url = Marshal.PtrToStringUni(lParam)
If url.StartsWith("mailto:") OrElse url Like "http*://*" Then
ProcessHelp.Start(url)
ElseIf url = "copymsg:" Then
Clipboard.SetText(MainInstruction + BR2 + Content + BR2 + ExpandedInformation)
MsgBox("Message was copied to clipboard.", MessageBoxIcon.Information)
End If
Case TDN_CREATED
For Each i In CommandLinkShieldList
SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, i, 1)
Next
End Select
Return 0
End Function
Private Sub MarshalDialogControlStructs()
If Not Buttons Is Nothing AndAlso Buttons.Count > 0 Then
ButtonArray = AllocateAndMarshalButtons(Buttons)
Config.pButtons = ButtonArray
Config.cButtons = CUInt(Buttons.Count)
End If
If Not RadioButtons Is Nothing AndAlso RadioButtons.Count > 0 Then
RadioButtonArray = AllocateAndMarshalButtons(RadioButtons)
Config.pRadioButtons = RadioButtonArray
Config.cRadioButtons = CUInt(RadioButtons.Count)
End If
End Sub
Private Shared Function AllocateAndMarshalButtons(structs As List(Of TASKDIALOG_BUTTON)) As IntPtr
Dim initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(TASKDIALOG_BUTTON)) * structs.Count)
Dim currentPtr = initialPtr
For Each button In structs
Marshal.StructureToPtr(button, currentPtr, False)
currentPtr = CType((currentPtr.ToInt64 + Marshal.SizeOf(button)), IntPtr)
Next
Return initialPtr
End Function
#End Region
#Region "IDispose Pattern"
Private disposed As Boolean
Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overrides Sub Finalize()
Try
Dispose(False)
Finally
MyBase.Finalize()
End Try
End Sub
Protected Sub Dispose(disposing As Boolean)
If Not disposed Then
disposed = True
If ButtonArray <> IntPtr.Zero Then
Marshal.FreeHGlobal(ButtonArray)
ButtonArray = IntPtr.Zero
End If
If RadioButtonArray <> IntPtr.Zero Then
Marshal.FreeHGlobal(RadioButtonArray)
RadioButtonArray = IntPtr.Zero
End If
If disposing Then
End If
End If
End Sub
#End Region
End Class
Public Class TaskDialog
<DllImport("comctl32", CharSet:=CharSet.Unicode, SetLastError:=True)>
Shared Function TaskDialogIndirect(<[In]()> pTaskConfig As TASKDIALOGCONFIG,
<Out()> ByRef pnButton As Integer,
<Out()> ByRef pnRadioButton As Integer,
<MarshalAs(UnmanagedType.Bool)> <Out()> ByRef pVerificationFlagChecked As Boolean) As Integer
End Function
<DllImport("user32.dll")>
Shared Function GetForegroundWindow() As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function GetWindowModuleFileName(hwnd As IntPtr,
lpszFileName As StringBuilder,
cchFileNameMax As UInteger) As UInteger
End Function
<DllImport("user32.dll", CharSet:=CharSet.Unicode)>
Shared Function SendMessage(hWnd As IntPtr,
Msg As Int32,
wParam As Integer,
lParam As Integer) As IntPtr
End Function
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=4)>
Public Class TASKDIALOGCONFIG
Public cbSize As UInteger
Public hwndParent As IntPtr
Public hInstance As IntPtr
Public dwFlags As Flags
Public dwCommonButtons As TaskDialogButtons
<MarshalAs(UnmanagedType.LPWStr)>
Public pszWindowTitle As String
Public MainIcon As TASKDIALOGCONFIG_ICON_UNION
<MarshalAs(UnmanagedType.LPWStr)>
Public pszMainInstruction As String
<MarshalAs(UnmanagedType.LPWStr)>
Public pszContent As String
Public cButtons As UInteger
Public pButtons As IntPtr
Public nDefaultButton As Integer
Public cRadioButtons As UInteger
Public pRadioButtons As IntPtr
Public nDefaultRadioButton As Integer
<MarshalAs(UnmanagedType.LPWStr)>
Public pszVerificationText As String
<MarshalAs(UnmanagedType.LPWStr)>
Public pszExpandedInformation As String
<MarshalAs(UnmanagedType.LPWStr)>
Public pszExpandedControlText As String
<MarshalAs(UnmanagedType.LPWStr)>
Public pszCollapsedControlText As String
Public FooterIcon As TASKDIALOGCONFIG_ICON_UNION
<MarshalAs(UnmanagedType.LPWStr)>
Public pszFooter As String
Public pfCallback As PFTASKDIALOGCALLBACK
Public lpCallbackData As IntPtr
Public cxWidth As UInteger
End Class
'TASKDIALOG_FLAGS
Public Enum Flags
NONE = 0
TDF_ENABLE_HYPERLINKS = &H1
TDF_USE_HICON_MAIN = &H2
TDF_USE_HICON_FOOTER = &H4
TDF_ALLOW_DIALOG_CANCELLATION = &H8
TDF_USE_COMMAND_LINKS = &H10
TDF_USE_COMMAND_LINKS_NO_ICON = &H20
TDF_EXPAND_FOOTER_AREA = &H40
TDF_EXPANDED_BY_DEFAULT = &H80
TDF_VERIFICATION_FLAG_CHECKED = &H100
TDF_SHOW_PROGRESS_BAR = &H200
TDF_SHOW_MARQUEE_PROGRESS_BAR = &H400
TDF_CALLBACK_TIMER = &H800
TDF_POSITION_RELATIVE_TO_WINDOW = &H1000
TDF_RTL_LAYOUT = &H2000
TDF_NO_DEFAULT_RADIO_BUTTON = &H4000
End Enum
<StructLayout(LayoutKind.Explicit, CharSet:=CharSet.Unicode)>
Public Structure TASKDIALOGCONFIG_ICON_UNION
Sub New(i As Integer)
spacer = IntPtr.Zero
pszIcon = 0
hMainIcon = i
End Sub
<FieldOffset(0)>
Public hMainIcon As Integer
<FieldOffset(0)>
Public pszIcon As Integer
<FieldOffset(0)>
Public spacer As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential,
CharSet:=CharSet.Unicode, Pack:=4)>
Public Structure TASKDIALOG_BUTTON
Sub New(n As Integer, txt As String)
nButtonID = n
pszButtonText = txt
End Sub
Public nButtonID As Integer
<MarshalAs(UnmanagedType.LPWStr)>
Public pszButtonText As String
End Structure
End Class
Public Enum TaskDialogButtons
None = &H0
Ok = &H1
Yes = &H2
No = &H4
Cancel = &H8
Retry = &H10
RetryCancel = Retry Or Cancel
Close = &H20
OkCancel = Ok Or Cancel
YesNo = Yes Or No
YesNoCancel = YesNo Or Cancel
End Enum
Public Enum TaskDialogIcon
Warning = 65535 'TD_WARNING_ICON
[Error] = 65534 'TD_ERROR_ICON
Info = 65533 'TD_INFORMATION_ICON
Shield = 65532 'TD_SHIELD_ICON
SecurityShieldBlue = 65531
SecurityWarning = 65530
SecurityError = 65529
SecuritySuccess = 65528
SecurityShieldGray = 65527
End Enum
End Namespace

View File

@@ -1,311 +0,0 @@
Imports System.Drawing.Drawing2D
Imports System.Drawing.Text
Imports Microsoft.Win32
Namespace UI
Public Class ToolStripRendererEx
Inherits ToolStripSystemRenderer
Shared RenderMode As ToolStripRenderModeEx
Shared Property ColorChecked As Color
Shared Property ColorBorder As Color
Shared Property ColorTop As Color
Shared Property ColorBottom As Color
Shared Property ColorBackground As Color
Shared Property ColorToolStrip1 As Color
Shared Property ColorToolStrip2 As Color
Shared Property ColorToolStrip3 As Color
Shared Property ColorToolStrip4 As Color
Private TextOffset As Integer
Sub New(mode As ToolStripRenderModeEx)
RenderMode = mode
InitColors(mode)
End Sub
Shared Function IsAutoRenderMode() As Boolean
Return _
RenderMode = ToolStripRenderModeEx.SystemAuto OrElse
RenderMode = ToolStripRenderModeEx.Win7Auto OrElse
RenderMode = ToolStripRenderModeEx.Win10Auto
End Function
Shared Sub InitColors(renderMode As ToolStripRenderModeEx)
If ToolStripRendererEx.IsAutoRenderMode Then
Dim argb = CInt(Registry.GetValue("HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0))
If argb = 0 Then argb = Color.LightBlue.ToArgb
InitColors(Color.FromArgb(argb))
Else
ColorBorder = Color.FromArgb(&HFF83ABDC)
ColorTop = Color.FromArgb(&HFFE7F0FB)
ColorBottom = Color.FromArgb(&HFFCCE1FB)
ColorBackground = SystemColors.Control
ColorToolStrip1 = Color.FromArgb(&HFFFDFEFF)
ColorToolStrip2 = Color.FromArgb(&HFFE6F0FA)
ColorToolStrip3 = Color.FromArgb(&HFFDCE6F4)
ColorToolStrip4 = Color.FromArgb(&HFFDDE9F7)
End If
End Sub
Shared Sub InitColors(c As Color)
ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100)
ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(200)
ColorBottom = HSLColor.Convert(c).ToColorSetLuminosity(220)
ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(230)
ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240)
ColorToolStrip1 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 1)))
ColorToolStrip2 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.7)))
ColorToolStrip3 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.1)))
ColorToolStrip4 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.4)))
End Sub
Protected Overrides Sub OnRenderToolStripBorder(e As ToolStripRenderEventArgs)
ControlPaint.DrawBorder(e.Graphics, e.AffectedBounds, Color.FromArgb(160, 175, 195), ButtonBorderStyle.Solid)
End Sub
Protected Overloads Overrides Sub OnRenderItemText(e As ToolStripItemTextRenderEventArgs)
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias
If TypeOf e.Item Is ToolStripMenuItem AndAlso Not TypeOf e.Item.Owner Is MenuStrip Then
Dim r = e.TextRectangle
Dim dropDown = TryCast(e.ToolStrip, ToolStripDropDownMenu)
If dropDown Is Nothing OrElse dropDown.ShowImageMargin OrElse dropDown.ShowCheckMargin Then
TextOffset = CInt(e.Item.Height * 1.1)
Else
TextOffset = CInt(e.Item.Height * 0.2)
End If
e.TextRectangle = New Rectangle(TextOffset, CInt((e.Item.Height - r.Height) / 2), r.Width, r.Height)
End If
MyBase.OnRenderItemText(e)
End Sub
Protected Overrides Sub OnRenderToolStripBackground(e As ToolStripRenderEventArgs)
If Not TypeOf e.ToolStrip Is ToolStripDropDownMenu AndAlso
Not e.ToolStrip.LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow Then
Dim r As New Rectangle(-1, -1, e.AffectedBounds.Width, e.AffectedBounds.Height)
If IsFlat() Then
Using b As New SolidBrush(ColorToolStrip2)
e.Graphics.FillRectangle(b, r)
End Using
Else
Dim cb As New ColorBlend()
cb.Colors = {ColorToolStrip1, ColorToolStrip2, ColorToolStrip3, ColorToolStrip4}
cb.Positions = {0.0F, 0.5F, 0.5F, 1.0F}
Using b As New LinearGradientBrush(r, ColorToolStrip1, ColorToolStrip4, 90)
b.InterpolationColors = cb
e.Graphics.FillRectangle(b, r)
End Using
End If
End If
End Sub
Protected Overrides Sub OnRenderMenuItemBackground(e As ToolStripItemRenderEventArgs)
e.Item.ForeColor = Color.Black
Dim left = 22
Dim r = New Rectangle(Point.Empty, e.Item.Size)
Dim g = e.Graphics
If Not TypeOf e.Item.Owner Is MenuStrip Then
g.Clear(ColorBackground)
End If
If e.Item.Selected AndAlso e.Item.Enabled Then
If TypeOf e.Item.Owner Is MenuStrip Then
DrawButton(e)
Else
g.SmoothingMode = SmoothingMode.AntiAlias
Dim r2 = New Rectangle(r.X + 2, r.Y, r.Width - 4, r.Height - 1)
If IsFlat() Then
Using pen As New Pen(ColorBorder)
g.DrawRectangle(pen, r2)
End Using
r2.Inflate(-1, -1)
Using b As New SolidBrush(ColorBottom)
g.FillRectangle(b, r2)
End Using
Else
Using path = CreateRoundRectangle(r2, 3)
Using b As New LinearGradientBrush(r2,
ControlPaint.LightLight(ControlPaint.LightLight(ColorTop)),
ControlPaint.LightLight(ControlPaint.LightLight(ColorBottom)),
90.0F)
g.FillPath(b, path)
End Using
Using p As New Pen(ColorBorder)
g.DrawPath(p, path)
End Using
End Using
r2.Inflate(-1, -1)
Using path = CreateRoundRectangle(r2, 3)
Using b As New LinearGradientBrush(r2, ColorTop, ColorBottom, 90.0F)
g.FillPath(b, path)
End Using
End Using
End If
End If
End If
End Sub
Sub DrawButton(e As ToolStripItemRenderEventArgs)
Dim g = e.Graphics
Dim r = New Rectangle(Point.Empty, e.Item.Size)
Dim r2 = New Rectangle(r.X, r.Y, r.Width - 1, r.Height - 1)
If IsFlat() Then
Using pen As New Pen(ColorBorder)
g.DrawRectangle(pen, r2)
End Using
r2.Inflate(-1, -1)
Dim tsb = TryCast(e.Item, ToolStripButton)
If Not tsb Is Nothing AndAlso tsb.Checked Then
Using brush As New SolidBrush(ColorChecked)
g.FillRectangle(brush, r2)
End Using
Else
Using brush As New SolidBrush(ColorBottom)
g.FillRectangle(brush, r2)
End Using
End If
Else
g.SmoothingMode = SmoothingMode.AntiAlias
Dim c1 = HSLColor.Convert(ColorToolStrip1).ToColorAddLuminosity(15)
Dim c2 = HSLColor.Convert(ColorToolStrip2).ToColorAddLuminosity(15)
Dim c3 = HSLColor.Convert(ColorToolStrip3).ToColorAddLuminosity(15)
Dim c4 = HSLColor.Convert(ColorToolStrip4).ToColorAddLuminosity(15)
Dim cb As New ColorBlend()
cb.Colors = {c1, c2, c3, c4}
cb.Positions = {0.0F, 0.5F, 0.5F, 1.0F}
Using path = CreateRoundRectangle(r2, 3)
Using b As New LinearGradientBrush(r2, c1, c4, 90)
b.InterpolationColors = cb
g.FillPath(b, path)
End Using
Using p As New Pen(ColorBorder)
g.DrawPath(p, path)
End Using
End Using
r2.Inflate(-1, -1)
c1 = HSLColor.Convert(ColorToolStrip1).ToColorAddLuminosity(5)
c2 = HSLColor.Convert(ColorToolStrip2).ToColorAddLuminosity(5)
c3 = HSLColor.Convert(ColorToolStrip3).ToColorAddLuminosity(-10)
c4 = HSLColor.Convert(ColorToolStrip4).ToColorAddLuminosity(-10)
cb.Colors = {c1, c2, c3, c4}
cb.Positions = {0.0F, 0.5F, 0.5F, 1.0F}
Using b As New LinearGradientBrush(r2, c1, c4, 90)
b.InterpolationColors = cb
Using path = CreateRoundRectangle(r2, 3)
g.FillPath(b, path)
End Using
End Using
End If
End Sub
Protected Overrides Sub OnRenderDropDownButtonBackground(e As ToolStripItemRenderEventArgs)
If e.Item.Selected Then DrawButton(e)
End Sub
Protected Overrides Sub OnRenderButtonBackground(e As ToolStripItemRenderEventArgs)
Dim button = DirectCast(e.Item, ToolStripButton)
If e.Item.Selected OrElse button.Checked Then DrawButton(e)
End Sub
Protected Overloads Overrides Sub OnRenderArrow(e As ToolStripArrowRenderEventArgs)
Dim value = If(e.Direction = ArrowDirection.Down, &H36, &H34)
Dim s = Convert.ToChar(value).ToString
Dim font = New Font("Marlett", e.Item.Font.Size - 2)
Dim size = e.Graphics.MeasureString(s, font)
Dim x = CInt(e.Item.Width - size.Width)
Dim y = CInt((e.Item.Height - size.Height) / 2) + 1
e.Graphics.DrawString(s, font, Brushes.Black, x, y)
End Sub
Protected Overrides Sub OnRenderItemCheck(e As ToolStripItemImageRenderEventArgs)
Dim x = CInt(e.ImageRectangle.Height * 0.2)
e.Graphics.DrawImage(e.Image, New Point(x, x))
End Sub
Protected Overloads Overrides Sub OnRenderSeparator(e As ToolStripSeparatorRenderEventArgs)
If e.Item.IsOnDropDown Then
e.Graphics.Clear(ColorBackground)
Dim right = e.Item.Width - CInt(TextOffset / 5)
Dim top = e.Item.Height \ 2
top -= 1
Dim b = e.Item.Bounds
Using p As New Pen(Color.Gray)
e.Graphics.DrawLine(p, New Point(TextOffset, top), New Point(right, top))
End Using
ElseIf e.Vertical Then
Dim b = e.Item.Bounds
Using p As New Pen(SystemColors.ControlDarkDark)
e.Graphics.DrawLine(p, CInt(b.Width / 2), CInt(b.Height * 0.15), CInt(b.Width / 2), CInt(b.Height * 0.85))
End Using
End If
End Sub
Public Shared Function CreateRoundRectangle(r As Rectangle, radius As Integer) As GraphicsPath
Dim path As New GraphicsPath()
Dim l = r.Left
Dim t = r.Top
Dim w = r.Width
Dim h = r.Height
Dim d = radius << 1
path.AddArc(l, t, d, d, 180, 90)
path.AddLine(l + radius, t, l + w - radius, t)
path.AddArc(l + w - d, t, d, d, 270, 90)
path.AddLine(l + w, t + radius, l + w, t + h - radius)
path.AddArc(l + w - d, t + h - d, d, d, 0, 90)
path.AddLine(l + w - radius, t + h, l + radius, t + h)
path.AddArc(l, t + h - d, d, d, 90, 90)
path.AddLine(l, t + h - radius, l, t + radius)
path.CloseFigure()
Return path
End Function
Shared Function IsFlat() As Boolean
If RenderMode = ToolStripRenderModeEx.Win10Default Then Return True
If RenderMode = ToolStripRenderModeEx.Win10Auto Then Return True
If (RenderMode = ToolStripRenderModeEx.SystemDefault OrElse
RenderMode = ToolStripRenderModeEx.SystemAuto) AndAlso
OSVersion.Current >= OSVersion.Windows8 Then Return True
End Function
End Class
End Namespace

File diff suppressed because it is too large Load Diff

View File

@@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AF1B21C5-28FC-4D47-AD0B-54F6A38391A6}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>vbnet</RootNamespace>
<AssemblyName>vbnet</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Windows</MyType>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>
</DocumentationFile>
<NoWarn>42030,42104,42105,42106,42107,42108,42109,42353,42354,42355</NoWarn>
<WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>
</DocumentationFile>
<NoWarn>42030,42104,42105,42106,42107,42108,42109,42353,42354,42355</NoWarn>
<WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>On</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<Import Include="System.Drawing" />
<Import Include="System.Linq" />
<Import Include="System.Windows.Forms" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<ItemGroup>
<Compile Include="Extensions.vb" />
<Compile Include="HSLColor.vb" />
<Compile Include="MainModule.vb" />
<Compile Include="MediaInfo.vb" />
<Compile Include="Menu.vb">
<SubType>Component</SubType>
</Compile>
<Compile Include="Misc.vb" />
<Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
<Compile Include="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="My Project\Settings.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="Native.vb" />
<Compile Include="TaskDialog.vb" />
<Compile Include="ToolStripRendererEx.vb" />
<Compile Include="UI.vb" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
<None Include="My Project\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<CustomToolNamespace>My</CustomToolNamespace>
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>