Compare commits
433 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d31237d5f | ||
|
|
3705e2abbf | ||
|
|
7d73529c83 | ||
|
|
2e59d49ad1 | ||
|
|
f61eef8961 | ||
|
|
efb4c085d5 | ||
|
|
4a045d6a91 | ||
|
|
da1a78cfa3 | ||
|
|
5b3697fbde | ||
|
|
726d759589 | ||
|
|
ed614332f7 | ||
|
|
9d46064dca | ||
|
|
407b49b3ad | ||
|
|
0e92d4ec0c | ||
|
|
4f96835e19 | ||
|
|
56d954d94e | ||
|
|
a8aeb1e3e9 | ||
|
|
415fd266a2 | ||
|
|
51f9e17380 | ||
|
|
28045ad33e | ||
|
|
e1bd44cd00 | ||
|
|
27d6026213 | ||
|
|
c67d5f10f8 | ||
|
|
5f73be07e8 | ||
|
|
0cad09d2bb | ||
|
|
54b2612bb8 | ||
|
|
82b4d19282 | ||
|
|
23a587c819 | ||
|
|
d69eecd494 | ||
|
|
0d4cc59f9a | ||
|
|
a394536a8c | ||
|
|
ebcd20ceb5 | ||
|
|
964c2f4dd2 | ||
|
|
e985047a54 | ||
|
|
bafc09a948 | ||
|
|
14a172b78b | ||
|
|
2eb324bf41 | ||
|
|
afe9ad5128 | ||
|
|
cc657d4ec2 | ||
|
|
1270dd474e | ||
|
|
e9ea70838d | ||
|
|
e7fde60150 | ||
|
|
2028113d58 | ||
|
|
4d55423fc7 | ||
|
|
d82874409d | ||
|
|
930ba2b0e7 | ||
|
|
4743f365a1 | ||
|
|
194ff5d62b | ||
|
|
5a726a01e0 | ||
|
|
fee13353ec | ||
|
|
cd3543fff4 | ||
|
|
c54f240346 | ||
|
|
7f55ad908a | ||
|
|
d586a82e37 | ||
|
|
722e06a02b | ||
|
|
2f76d2b775 | ||
|
|
7519977124 | ||
|
|
2e65b9ceb8 | ||
|
|
04bffca206 | ||
|
|
ff5a164c69 | ||
|
|
26b391a8d9 | ||
|
|
32eed33c82 | ||
|
|
639893f2e7 | ||
|
|
42b0cc1a64 | ||
|
|
6f7fa6c9d6 | ||
|
|
e6fb775dcd | ||
|
|
ece15ca9bb | ||
|
|
6b3c2788df | ||
|
|
067bdd20d7 | ||
|
|
97ce08c4c7 | ||
|
|
fbb9cbdc33 | ||
|
|
815adca198 | ||
|
|
ce3d5792ad | ||
|
|
74fc0b3ed7 | ||
|
|
604a1e8499 | ||
|
|
56ade0a0d1 | ||
|
|
6294a96aea | ||
|
|
9a95953a04 | ||
|
|
8d9c0c9092 | ||
|
|
e399ca672f | ||
|
|
660345d18a | ||
|
|
3844db6e79 | ||
|
|
5374e20757 | ||
|
|
bc6167c4ee | ||
|
|
7979f77284 | ||
|
|
71b90ed5cb | ||
|
|
9d2e236b3e | ||
|
|
d42657a3f0 | ||
|
|
e4818fae18 | ||
|
|
7b39bfcbc4 | ||
|
|
fd6f3c94dd | ||
|
|
dd10c07fb5 | ||
|
|
3bbfdcffdd | ||
|
|
6b7c4e1724 | ||
|
|
d3ad1091ec | ||
|
|
65177c448b | ||
|
|
1cdecb3810 | ||
|
|
20ea755a93 | ||
|
|
3b7bc95869 | ||
|
|
5380daad53 | ||
|
|
a5f4d848d4 | ||
|
|
cf0f9bfa01 | ||
|
|
68461e05da | ||
|
|
397b988851 | ||
|
|
eddb95e791 | ||
|
|
fa1183710b | ||
|
|
f468fd9c56 | ||
|
|
22f2aa93a8 | ||
|
|
c2c0a8f190 | ||
|
|
da3e6655c6 | ||
|
|
856959a4d1 | ||
|
|
9053ecb4ee | ||
|
|
33fd7fc09b | ||
|
|
d005f19755 | ||
|
|
1081007009 | ||
|
|
e6c0a67483 | ||
|
|
265e18985d | ||
|
|
8dc204e81a | ||
|
|
b9b604bfe3 | ||
|
|
05027cd458 | ||
|
|
9bbde49a5c | ||
|
|
cfca7786f3 | ||
|
|
be57edf2c5 | ||
|
|
f48901355a | ||
|
|
ca153fecfc | ||
|
|
e3227de8b4 | ||
|
|
4a202245b5 | ||
|
|
b94f9de582 | ||
|
|
7371949730 | ||
|
|
857926696c | ||
|
|
4451a6c185 | ||
|
|
ea6a71b7c3 | ||
|
|
625dddcfbb | ||
|
|
0cd769fc0c | ||
|
|
f5e0c92824 | ||
|
|
327a097bcf | ||
|
|
68626fa536 | ||
|
|
8935101058 | ||
|
|
6947c925b9 | ||
|
|
4562131078 | ||
|
|
21188f0942 | ||
|
|
1316559ebc | ||
|
|
cd576f9211 | ||
|
|
1bac8e8937 | ||
|
|
e6d0449f8f | ||
|
|
e0e40b7918 | ||
|
|
b59f16a425 | ||
|
|
46b110d93b | ||
|
|
7e8a654ada | ||
|
|
c2c33228a0 | ||
|
|
0a28f13d51 | ||
|
|
9f3a1da931 | ||
|
|
05874ad6be | ||
|
|
078e8046bd | ||
|
|
b07901485e | ||
|
|
a37cbef8a8 | ||
|
|
8debcc171c | ||
|
|
e230f0f474 | ||
|
|
558bd67591 | ||
|
|
a7e4892acf | ||
|
|
a0ba69c1aa | ||
|
|
1e7e80577d | ||
|
|
2177308b02 | ||
|
|
a8c2409ed1 | ||
|
|
1ef9e64a41 | ||
|
|
f0546485cf | ||
|
|
032e91e4b4 | ||
|
|
1447636eb7 | ||
|
|
966f96a02b | ||
|
|
954c014708 | ||
|
|
ad30dc5ae2 | ||
|
|
3f74344b99 | ||
|
|
96d8d88d09 | ||
|
|
8626b8283f | ||
|
|
d90025e8fe | ||
|
|
a572bd8553 | ||
|
|
0f5146e58c | ||
|
|
9c6c0f3506 | ||
|
|
8c36cc8b8c | ||
|
|
44435057d7 | ||
|
|
135bdeb638 | ||
|
|
93c93b620d | ||
|
|
247aefbf07 | ||
|
|
0a8397652f | ||
|
|
ecd5b01161 | ||
|
|
1e9893977d | ||
|
|
4fd6b13e0f | ||
|
|
d21d36c196 | ||
|
|
fbffbea641 | ||
|
|
9899c2cd27 | ||
|
|
10370e9ae2 | ||
|
|
d391e24784 | ||
|
|
430fef0ac4 | ||
|
|
8430842679 | ||
|
|
9d37e67901 | ||
|
|
e98ff53058 | ||
|
|
b47d3c34f2 | ||
|
|
54dd261df0 | ||
|
|
8eb7e41d16 | ||
|
|
2068bfb6fa | ||
|
|
dfc1ac712e | ||
|
|
d96587cb7b | ||
|
|
005550af55 | ||
|
|
543e2905cc | ||
|
|
a49b9bea61 | ||
|
|
9ea9cb2757 | ||
|
|
5543381a14 | ||
|
|
cd6dcf4640 | ||
|
|
d321ab477f | ||
|
|
1cd0f87278 | ||
|
|
936274fc3b | ||
|
|
2bbaa30322 | ||
|
|
cedd54d64d | ||
|
|
38604459a6 | ||
|
|
0a48a0dc6f | ||
|
|
85a23fbae1 | ||
|
|
01da76bdc4 | ||
|
|
1f1553e159 | ||
|
|
2af84941ca | ||
|
|
a82f558acf | ||
|
|
d13f7201ba | ||
|
|
89aa0c6133 | ||
|
|
1699467e0d | ||
|
|
7a27ab0513 | ||
|
|
2a0c68e4ec | ||
|
|
91c42d4d3f | ||
|
|
49d56166d7 | ||
|
|
1ac603b904 | ||
|
|
d5b2923c68 | ||
|
|
b80b375df1 | ||
|
|
2b2b60b90f | ||
|
|
3977283ecb | ||
|
|
d27778775d | ||
|
|
5c053bb5eb | ||
|
|
83658aa476 | ||
|
|
e0111b6f12 | ||
|
|
e308bbf928 | ||
|
|
1817fbc0fd | ||
|
|
3b149aea54 | ||
|
|
7575a2d736 | ||
|
|
17c198e711 | ||
|
|
1f8635e9c4 | ||
|
|
37e6c198a1 | ||
|
|
751c8779f4 | ||
|
|
9e2bf46636 | ||
|
|
3529323d93 | ||
|
|
ba52c1f8b5 | ||
|
|
bf2070d758 | ||
|
|
7a1de4cf0f | ||
|
|
caf0bee161 | ||
|
|
cedd694e8e | ||
|
|
d1c58585f5 | ||
|
|
0fce626c46 | ||
|
|
adb8f38c0d | ||
|
|
735ee42580 | ||
|
|
103ae81b8b | ||
|
|
8e351193e1 | ||
|
|
d57b9281a1 | ||
|
|
e07627377e | ||
|
|
8899f4b772 | ||
|
|
e7fd268927 | ||
|
|
c8fe3a4c43 | ||
|
|
19c2502c31 | ||
|
|
56dae4babd | ||
|
|
bc20d7527c | ||
|
|
3d325d4fe5 | ||
|
|
ba0141cfb1 | ||
|
|
d32c7b4056 | ||
|
|
63f064ba1c | ||
|
|
e5c9df31e4 | ||
|
|
c0a8e895f7 | ||
|
|
064ae44ecf | ||
|
|
005ba6e5ea | ||
|
|
9f6aba6cbd | ||
|
|
87e3d9ca3e | ||
|
|
29a0eae3d5 | ||
|
|
01b2492cde | ||
|
|
d2b1ca0c69 | ||
|
|
91b429e6b0 | ||
|
|
fa05e95892 | ||
|
|
701a58a4bf | ||
|
|
387c3f7896 | ||
|
|
eeb0189577 | ||
|
|
de4c2d6d70 | ||
|
|
63ee598ebd | ||
|
|
1bf8e568c5 | ||
|
|
f8f58dba5e | ||
|
|
ebb8ad351a | ||
|
|
0202c34c6f | ||
|
|
c3f2b22ff5 | ||
|
|
c1a03c3e4b | ||
|
|
e041908f04 | ||
|
|
270559c3f7 | ||
|
|
0dfd19eb45 | ||
|
|
9cdba6d2f2 | ||
|
|
50bf09ff8d | ||
|
|
c54fa708f8 | ||
|
|
7698e873ca | ||
|
|
89b8de2c40 | ||
|
|
259d2d882a | ||
|
|
b7fbef5a88 | ||
|
|
0ca9ac93f1 | ||
|
|
f7b3900a0a | ||
|
|
c98036dc42 | ||
|
|
a9e7ae4b97 | ||
|
|
30fb744114 | ||
|
|
d465516a6a | ||
|
|
0b951875e6 | ||
|
|
5ed65733a0 | ||
|
|
caac45a871 | ||
|
|
f4f69816a7 | ||
|
|
1dddf129df | ||
|
|
ca9690c3b3 | ||
|
|
3b0b098bda | ||
|
|
c72080e92c | ||
|
|
237a3cf132 | ||
|
|
562f149fff | ||
|
|
dc85372c36 | ||
|
|
2595465ec7 | ||
|
|
1db733ae13 | ||
|
|
ba3bc48297 | ||
|
|
5e16c47100 | ||
|
|
a13c6648a3 | ||
|
|
5dc244d6f6 | ||
|
|
da9bc4199b | ||
|
|
1868957388 | ||
|
|
0139a1ef70 | ||
|
|
0989b7ef95 | ||
|
|
16924e5a3b | ||
|
|
502e1a9651 | ||
|
|
36a7bbcfab | ||
|
|
8fda90e09a | ||
|
|
269457dbde | ||
|
|
c93647841e | ||
|
|
0f78ea38ac | ||
|
|
7eb60f3e4c | ||
|
|
2636da446e | ||
|
|
c7fab24044 | ||
|
|
2ce1f3d9c1 | ||
|
|
d2f9108c22 | ||
|
|
3a2b9ee542 | ||
|
|
5c93bc00f7 | ||
|
|
19c09da4e1 | ||
|
|
95c9c115b2 | ||
|
|
2512c02bff | ||
|
|
351fae8344 | ||
|
|
30b562a1e1 | ||
|
|
8a9a017875 | ||
|
|
fa0b0f496f | ||
|
|
83b5d9b65c | ||
|
|
b199d33f7a | ||
|
|
a7b6f79ee1 | ||
|
|
fc3c5ee3a7 | ||
|
|
ed71cb704f | ||
|
|
a9474b1c22 | ||
|
|
be3b31f7e6 | ||
|
|
b2884e2037 | ||
|
|
3910776b54 | ||
|
|
b37272db8b | ||
|
|
08a23430c7 | ||
|
|
ba41b8026f | ||
|
|
4aeb00afb5 | ||
|
|
6e6015b185 | ||
|
|
68240ac49d | ||
|
|
bafc481117 | ||
|
|
9198d610ad | ||
|
|
ad4199aff0 | ||
|
|
3164e2322c | ||
|
|
a6d4570b81 | ||
|
|
4fc9c61ecf | ||
|
|
5a969aac7d | ||
|
|
1b9229d4d9 | ||
|
|
225979d220 | ||
|
|
0c3a03181a | ||
|
|
867a83f15a | ||
|
|
1d78d4e4e2 | ||
|
|
23bef4d971 | ||
|
|
9b95b87177 | ||
|
|
aa8ae225c5 | ||
|
|
1bb05c4d99 | ||
|
|
619fcef63f | ||
|
|
9170e55d81 | ||
|
|
dc1240f606 | ||
|
|
cb11279091 | ||
|
|
fd956d401f | ||
|
|
6ea8a67390 | ||
|
|
6d02203727 | ||
|
|
0d396947c1 | ||
|
|
6c85ea9625 | ||
|
|
2d9a67c502 | ||
|
|
d9000a570b | ||
|
|
f35ab46c3f | ||
|
|
143934ca49 | ||
|
|
669750eaf4 | ||
|
|
cde8a6495a | ||
|
|
c774d4d490 | ||
|
|
55cafbcdbf | ||
|
|
4f508f3af0 | ||
|
|
8cea79e67f | ||
|
|
c6c3a3e8fa | ||
|
|
8c87ac0c47 | ||
|
|
d777ca912a | ||
|
|
c9ffbaa679 | ||
|
|
1476059601 | ||
|
|
757502e8bf | ||
|
|
4bbf84532e | ||
|
|
433d741c68 | ||
|
|
8fdbe22dd8 | ||
|
|
8bed98ded5 | ||
|
|
4abfa73fba | ||
|
|
b868d63946 | ||
|
|
3bdb88787e | ||
|
|
8b74abc2f6 | ||
|
|
a516f9f947 | ||
|
|
ecab31f108 | ||
|
|
c5a5a09300 | ||
|
|
5a2f5614a3 | ||
|
|
5e0162f2c8 | ||
|
|
14ba006de1 | ||
|
|
8f7aa7db2d | ||
|
|
3e70e8e5ea | ||
|
|
36f5357ff7 | ||
|
|
dc3b275291 | ||
|
|
abc49f55d5 | ||
|
|
40b9f21101 | ||
|
|
164076e237 | ||
|
|
b7d948f12d | ||
|
|
22e4ba1824 | ||
|
|
efd2ddf367 | ||
|
|
2415e2ed43 | ||
|
|
d5d26784e8 | ||
|
|
6c1bad15f2 | ||
|
|
5137e43aad |
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: stax76
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: stax76
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -1,29 +0,0 @@
|
||||
Imports System.ComponentModel.Composition
|
||||
Imports System.IO
|
||||
Imports System.Windows.Forms
|
||||
|
||||
Imports mpvnet
|
||||
|
||||
Imports CSScriptLibrary
|
||||
|
||||
<Export(GetType(IAddon))>
|
||||
Public Class CSScriptAddon
|
||||
Implements IAddon
|
||||
|
||||
Sub New()
|
||||
Dim scriptDir = mp.MpvConfFolderPath + "scripts"
|
||||
If Not Directory.Exists(scriptDir) Then Return
|
||||
Dim csFiles = Directory.GetFiles(scriptDir, "*.cs").ToList
|
||||
csFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\Scripts", "*.cs"))
|
||||
If csFiles.Count = 0 Then Return
|
||||
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom
|
||||
|
||||
For Each i In csFiles
|
||||
Try
|
||||
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(i))
|
||||
Catch ex As Exception
|
||||
MainForm.Instance.ShowMsgBox(ex.ToString(), MessageBoxIcon.Error)
|
||||
End Try
|
||||
Next
|
||||
End Sub
|
||||
End Class
|
||||
@@ -1,124 +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>{71808A87-8B1C-4DF8-957C-D79C3B164CCA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>CSScriptAddon</RootNamespace>
|
||||
<AssemblyName>CSScriptAddon</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<OutputPath>..\mpv.net\bin\Addons\CSScriptAddon\</OutputPath>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<NoWarn>42105,42106,42107,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>..\mpv.net\bin\Addons\CSScriptAddon\</OutputPath>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<NoWarn>42105,42106,42107,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="CSScriptLibrary, Version=3.27.5.0, Culture=neutral, PublicKeyToken=70fcc3d18c749033, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>.\CSScriptLibrary.dll</HintPath>
|
||||
</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" />
|
||||
</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.Linq" />
|
||||
<Import Include="System.Xml.Linq" />
|
||||
<Import Include="System.Threading.Tasks" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CSScriptAddon.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>
|
||||
</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>
|
||||
<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>
|
||||
13
CSScriptAddon/My Project/Application.Designer.vb
generated
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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("CSScriptAddon")>
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("")>
|
||||
<Assembly: AssemblyProduct("CSScriptAddon")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2019")>
|
||||
<Assembly: AssemblyTrademark("")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
'The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
<Assembly: Guid("4a748201-3948-497d-b156-7d172a332bd6")>
|
||||
|
||||
' 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")>
|
||||
63
CSScriptAddon/My Project/Resources.Designer.vb
generated
@@ -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("CSScriptAddon.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
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
73
CSScriptAddon/My Project/Settings.Designer.vb
generated
@@ -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.9.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.CSScriptAddon.My.MySettings
|
||||
Get
|
||||
Return Global.CSScriptAddon.My.MySettings.Default
|
||||
End Get
|
||||
End Property
|
||||
End Module
|
||||
End Namespace
|
||||
@@ -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>
|
||||
519
Changelog.md
Normal file
@@ -0,0 +1,519 @@
|
||||
|
||||
5.4.8.1 Beta (not yet released)
|
||||
============
|
||||
|
||||
|
||||
|
||||
|
||||
5.4.8.0
|
||||
=======
|
||||
|
||||
- fix learn window of input editor (much work)
|
||||
- fix black one pixel bar on right side
|
||||
- fix beep sound when closed from taskbar
|
||||
|
||||
|
||||
5.4.7.4 Beta (not yet released)
|
||||
============
|
||||
|
||||
- the media key issue should now be fixed!
|
||||
- libmpv and youtube-dl update
|
||||
|
||||
|
||||
5.4.7.3 Beta
|
||||
============
|
||||
|
||||
- new setting media-keys added, can be found in the config editor in the input tab.
|
||||
|
||||
|
||||
5.4.7.2 Beta
|
||||
============
|
||||
|
||||
- another attempt to fix a app command issue. WM_APPCOMMAND (mpv calls this media keys)
|
||||
based input is no longer directly passed to mpv but rather handled in mpv.net directly
|
||||
translating the native commands to mpv keys and sent via keypress input command to mpv
|
||||
- another attempt to fix a crash caused by powershell 5.1 not being installed
|
||||
|
||||
|
||||
5.4.7.1 Beta
|
||||
============
|
||||
|
||||
- log error fix, mpv.net does now ignore all log messages because libmpv already
|
||||
prints the log messages to the the terminal
|
||||
- the release script now also outputs x86 beta versions so x86 users can test betas
|
||||
|
||||
|
||||
5.4.7.0
|
||||
=======
|
||||
|
||||
- log error fix
|
||||
- workaround to support AviSynth portable (ffmpeg blocks loading AviSynth from path env var)
|
||||
- attempt to fix not reproducible volume input issue
|
||||
- attempt to fix exception caused by powershell being not available on Win 7
|
||||
|
||||
|
||||
5.4.6.0
|
||||
=======
|
||||
|
||||
- youtube-dl update
|
||||
- auto update routine fix
|
||||
|
||||
|
||||
5.4.5.1 Beta
|
||||
============
|
||||
|
||||
- extensions no longer need to end with *Extension.dll but rather
|
||||
the file name and the directory name must be identical
|
||||
- text encoding exception fix
|
||||
- the PowerShell script host is more feature complete, easier to use
|
||||
and more efficient, there were however many PowerShell and C# breaking
|
||||
changes requrired to make the core more robust and efficient
|
||||
- Python 2 script host removed, Python 3 support is planned for summer
|
||||
|
||||
|
||||
5.4.5.0
|
||||
=======
|
||||
|
||||
stable release, no changes since the last beta
|
||||
|
||||
|
||||
5.4.4.6 Beta
|
||||
============
|
||||
|
||||
- using start-size=video the window size was not remembered
|
||||
after fullscreen mode was left.
|
||||
- using start-size=video the window can now use the entire
|
||||
working area using autofit-larger=100
|
||||
|
||||
|
||||
5.4.4.5 Beta
|
||||
============
|
||||
|
||||
- overhaul of the [webpage](README.md) and the [manual](Manual.md).
|
||||
- change that possibly could fix a multimedia keyboard volume issue.
|
||||
|
||||
|
||||
5.4.4.4 Beta
|
||||
============
|
||||
|
||||
- with `border=no` the OSC top bar window buttons min, max and close are fully supported.
|
||||
- anamorphic videos are shown without black bars, the window is resized according to the ascpect ratio.
|
||||
- PowerShell 5.1 was made optional.
|
||||
- full implementation for `window-minimized` and `window-maximized`,
|
||||
scripts that depend on this like pause-when-minimize.lua are now fully supported.
|
||||
- fix cycling from maximized to fullscreen and back.
|
||||
|
||||
|
||||
5.4.4.3 Beta
|
||||
============
|
||||
|
||||
- update MediaInfo 20.03
|
||||
- update libmpv 2020-04-12, it supports vpy playback, read manual or ask in forum
|
||||
- mpv property `window-maximized` support added, cycling it from input.conf
|
||||
is not recommended, use native Windows shortcuts Win+Up, Win+Down
|
||||
- the mpv.net `start-size` option supports `always` to always remember the window height
|
||||
- if the window was maximized before fullscreen was entered, it's now set to
|
||||
maximized after fullscreen was left
|
||||
- with `border=no` the OSC did not auto hide after the mouse curser left the window
|
||||
- the script that modified the seek OSD was removed, it still can be found in the mpv wiki
|
||||
- certain videos were showed with black bars
|
||||
|
||||
|
||||
### 5.4.4.2
|
||||
|
||||
- update: libmpv shinchiro 0.32.0-258-g281f5c63c1
|
||||
- update: youtube-dl
|
||||
|
||||
- new: d3d11va-zero-copy setting added to conf editor
|
||||
- new: hdr-compute-peak setting added to conf editor
|
||||
- new: flag cli switches support now `--no-flag` in addition to `--flag=no`
|
||||
https://mpv.io/manual/master/#usage
|
||||
- new: cli switches can also start with single `-` instead of double `--`
|
||||
https://mpv.io/manual/master/#legacy-option-syntax
|
||||
- new: PowerShell script host was completely rewritten, events can be assigned
|
||||
by using `Register-ObjectEvent`, the scripting wiki page was updated
|
||||
https://github.com/stax76/mpv.net/wiki/Scripting#powershell
|
||||
- new: Context Menu > View > Show Profiles
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L147
|
||||
- new: Context Menu > View > Show Properties
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L148
|
||||
- new: Context Menu > View > Show Commands
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149
|
||||
- new: config editor tab is now remembered
|
||||
- new: osd-duration setting added to config editor and default mpv.conf
|
||||
- new: external console replaced with internal console, in case mpv.conf is missing it's
|
||||
generated with correct Hight DPI font size scale settings.
|
||||
`script-opts=console-scale=<dpiscale>`
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L150
|
||||
https://mpv.io/manual/master/#console
|
||||
- new: blue color in dark theme is now less intense
|
||||
https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme
|
||||
- new: menu item 'View > Show Progress' (p key) to show progress bar
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L146
|
||||
- new: `script-message mpv.net playlist-first`, unlike mpv does not
|
||||
restart if the first file is already active
|
||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L44
|
||||
- new: if mpv.net is started from the terminal and an error happens then the error
|
||||
is printed to the terminal instead of shown with a message box
|
||||
- fix: update routine did only work when mpv.net was located in 'Program Files'
|
||||
- fix: fatal errors were ignored and only seen in the terminal, now a message box is shown
|
||||
- fix: when start-size=video was used then enlarging or shrinking the window size was broken
|
||||
|
||||
### 5.4.4.0
|
||||
|
||||
- new: forecolors in the dark theme are slightly darker now
|
||||
- new: readme/website and manual were improved
|
||||
- new: source code includes now the release script to build the archives and setup files
|
||||
- new: the history feature now uses the full path
|
||||
- new: install via Scoop and Chocolatey added to readme/website (Restia666Ashdoll)
|
||||
- new: update check, it must be enabled first in the conf editor under General
|
||||
- new: update feature, requires PowerShell 5 and curl,
|
||||
an up to date Windows 10 system has both included.
|
||||
Main menu (input.conf) must be reset or updated manually ([defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt))
|
||||
|
||||
- update: libmpv shinchiro 2019-11-10
|
||||
|
||||
- fix: often the OSC was shown when fullscreen was entered
|
||||
or on app startup, this is now suppressed
|
||||
- fix: the file association routine uses no longer 'Play with mpv.net' for the
|
||||
default open verb caption because it doesn't support multi selection,
|
||||
it shows now only Open, the manual explains how to get multi selection
|
||||
in File Explorer, read about it [here](https://github.com/stax76/mpv.net/blob/master/Manual.md#open-with)
|
||||
- fix: x86 builds had an older version included because
|
||||
of a misconfiguration in the solution file
|
||||
|
||||
### 5.4.3.0
|
||||
|
||||
- new: the color themes can now be customized ([manual](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme))
|
||||
- new: three new sections were added to the [manual](https://github.com/stax76/mpv.net/blob/master/Manual.md):
|
||||
1. [Color Theme](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme)
|
||||
2. [Hidden and secret features](https://github.com/stax76/mpv.net/blob/master/Manual.md#hidden-and-secret-features)
|
||||
3. [External Tools](https://github.com/stax76/mpv.net/blob/master/Manual.md#external-tools)
|
||||
|
||||
- fix: window restore from maximized and from minimized was broken
|
||||
- fix: it's possible to multi select files in File Explorer and press
|
||||
enter to open the files, this did however only work when the
|
||||
auto load folder feature was disabled or the shift key was
|
||||
pressed (blocks auto load folder). Now it should also work
|
||||
without shift key and with auto load folder being enabled
|
||||
|
||||
- update: libmpv shinchiro 2019-10-27
|
||||
- update: youtube-dl 2019-10-31
|
||||
|
||||
### 5.4.2.1 Beta
|
||||
|
||||
- pressing shift key suppresses auto-load-folder
|
||||
- switch --queue added, this will not clear the playlist but append
|
||||
and it will suppress auto-load-folder. To get a 'Add to mpv.net playlist'
|
||||
context menu item in explorer with multi selection support use my
|
||||
[Open with++](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist) shell extension, as far as I know multi selection
|
||||
can not be done using the Registry but only via shell extension
|
||||
- window-size mpv property support added ([default bindings](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L137))
|
||||
- the config editor keeps profiles and comments in mpv.conf intact!
|
||||
- the options in the config editor are better organized
|
||||
|
||||
### 5.4.2
|
||||
|
||||
- new: the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting#powershell) was improved
|
||||
- new: Toggle Shuffle has been added to the menu defaults
|
||||
- new: for URLs the media title is shown in the title bar and in the info command
|
||||
instead of displaying the URL, mpv.conf defaults were changed to use
|
||||
[protocol.https] osd-playing-msg = '${media-title}'
|
||||
|
||||
- fix: on the very first start volume was set to 0 and mute was set to yes
|
||||
- fix: there was a sound when closed from taskbar
|
||||
- fix: the log feature was not working
|
||||
- fix: clipboard monitoring removed because it was causing to many issues
|
||||
- fix: restore resulted in collapsed window when maximized = yes was used
|
||||
|
||||
- update: libmpv shinchiro 2019-10-06
|
||||
- update: youtube-dl 2019-10-01
|
||||
|
||||
### 5.4.1.1
|
||||
|
||||
- a issue with the taskbar-progress feature was fixed
|
||||
- improved PowerShell scrip host
|
||||
|
||||
### 5.4.1
|
||||
|
||||
- fix ArgumentOutOfRangeException
|
||||
|
||||
### 5.4
|
||||
|
||||
- added taskbar-progress implementation
|
||||
- added new setting to start with maximized window
|
||||
- long file paths work now even if not enabled by the OS
|
||||
- fixed history being written even when history file wasn't created prior
|
||||
- libmpv updated to shinchiro 2019-08-31
|
||||
|
||||
### 5.3
|
||||
|
||||
- added new feature: Open > Open DVD/Blu-ray Drive/Folder...
|
||||
- the default of remember-volume has been set to yes
|
||||
- scale, cscale, dscale defaults have been set to spline36,
|
||||
profile=gpu-hq is not used in the defaults because it starts very slow
|
||||
- new menu items have been added to navigate to the first and
|
||||
last playlist position, key bindings: Home, End
|
||||
- new config setting recent-count added, amount of menu items
|
||||
shown under 'Open > Recent'
|
||||
- in the config dialog the description for keep-open was corrected
|
||||
because unlike mpv, mpv.net will never terminate automatically
|
||||
- there was a rare occasion where the mpv.net logo wasn't shown
|
||||
- fix excessive memory usage using `osd-scale-by-window = no`
|
||||
- mpv setting osd-scale-by-window added to config dialog
|
||||
|
||||
### 5.2.1
|
||||
|
||||
- fixed race condition causing various features to fail
|
||||
|
||||
### 5.2
|
||||
|
||||
- bug fix for single-instance not working with unicode filenames
|
||||
- bug fix for logo not shown on start
|
||||
- osd-visibility.js script was removed because the OSC uses too much memory
|
||||
- youtube-dl was updated
|
||||
- libmpv was updated to shinchiro 2019-08-04
|
||||
- in case mpv.net was started from a terminal it sets now the mpv property input-terminal to yes,
|
||||
this means mpv.net will now receive and handle input keys from the terminal
|
||||
- certain command line properties didn't work (input-terminal, terminal, input-file,
|
||||
config, config-dir, input-conf, load-scripts, script, scripts, player-operation-mode)
|
||||
- the about dialog shows now the mpv version and build date
|
||||
- the dialog that asks for a config folder has now a cancel option
|
||||
|
||||
### 5.1
|
||||
|
||||
- many [wiki pages](https://github.com/stax76/mpv.net/wiki) were improved
|
||||
- the logo/icon had a very small cosmetic change
|
||||
- the help in the context menu was improved,
|
||||
for quick access consider the command palette (F1 key)
|
||||
- config options specific to mpv.net are now available from the command line
|
||||
- the input editor no longer has known limitations, 'alt gr' and ctrl+alt are working now
|
||||
- the help in the input editor was simplified and the filter logic was improved
|
||||
- fixed issue in file associations causing mpv.net not to appear in OS default apps
|
||||
- 'Tools > Manage File Associations' was replaced by 'Tools > OS Setup',
|
||||
it has now a feature to add and remove mpv.net to and from the Path
|
||||
environment variable and the OS default apps settings can be opened (Win 10 only)
|
||||
- startup folder and config folder being identical was causing a critical issue
|
||||
as mpv.net was loading extensions twice and scripts four times, now identical
|
||||
folders are no longer permitted
|
||||
- error messages are shown when unknown scripts and extensions are found in the startup folder
|
||||
because user scripts and extensions are supposed to be located in the config folder instead
|
||||
- changing from maximized to fullscreen did not work
|
||||
- the search field in the config editor was not always remembered
|
||||
- new setting remember-volume added, saves volume and mute on exit
|
||||
and restores it on start.
|
||||
- it's now enforced that mpv properties on the command line and in
|
||||
the mpv.conf config file are lowercase, if not a error is shown
|
||||
- gpu-api vulkan was not working if media files were opened via
|
||||
command line (that included Explorer)
|
||||
- new setting minimum-aspect-ratio added, minimum aspect ratio for the window,
|
||||
this was previously hard coded to 1.3
|
||||
- new setting auto-load-folder added, for single files automatically load
|
||||
the entire directory into the playlist, previously this was forced,
|
||||
now it can be disabled
|
||||
- new setting themed-menu added, follow theme color in context menu,
|
||||
default: no. UI related settings have now a separate UI tab in the config editor
|
||||
|
||||
### 5.0
|
||||
|
||||
- [changed icon design](https://github.com/stax76/mpv.net/blob/master/img/mpvnet.png)
|
||||
- libmpv was updated to shinchiro 2019-07-14
|
||||
- new or improved config editor settings: screenshot-directory,
|
||||
screenshot-format, screenshot-tag-colorspace, screenshot-high-bit-depth,
|
||||
screenshot-jpeg-source-chroma, screenshot-template, screenshot-jpeg-quality,
|
||||
screenshot-png-compression, screenshot-png-filter
|
||||
- mpv.conf preview feature added to config editor, it previews the mpv.conf content
|
||||
- in the entire project the term addon was replaced with the term extension,
|
||||
unfortunately this will break user extensions. The reason for this drastic
|
||||
change is that there exist too many different terms, addons, addins,
|
||||
extensions, modules, packages etc.. mpv.net follows Google Chrome as the worlds
|
||||
most popular extendable app, Chrome uses the term Extension.
|
||||
- a thread synchronization bug was fixed, the shutdown thread was aborted
|
||||
if it was running more than 3 seconds, this caused the rating extension
|
||||
to fail if it was waiting for a drive to wake up
|
||||
- a new JavaScript was included to show the playlist with a smaller font size,
|
||||
the script is located at startup/scripts
|
||||
- terminal support added using mpvnet.com !
|
||||
- script engine performance and error handling was improved
|
||||
- the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting) was improved
|
||||
- the C# scripting host extension was converted from VB to C# because it's not
|
||||
only used for hosting but I also use it now to code and debug script code
|
||||
- there was a copy paste bug in the file association feature resulting in keys
|
||||
from mpv being overwritten instead of using mpv.net keys. Thanks to floppyD!
|
||||
- there was a exception fixed that happened opening rar files
|
||||
- instead of using the OS theme color there are now default colors
|
||||
for dark-color and light-color
|
||||
|
||||
### 4.7.7
|
||||
|
||||
- on Win 7 the theme color was hardcoded to DarkSlateGrey because
|
||||
WPF was returning a bad color on Win 7, this was fixed by reading
|
||||
the theme color from the Registry on Win 7. If the theme color
|
||||
is identical to the background color it's corrected
|
||||
- dark-color setting was added to overwrite the OS theme color used in dark mode,
|
||||
find the setting on the General tab
|
||||
- light-color setting was added to overwrite the OS theme color used in non dark mode,
|
||||
find the setting on the General tab
|
||||
- various changes regarding input handling, multi media keys and
|
||||
mouse forward/backward were successfully tested
|
||||
- it's now possible to use a custom folder as config folder,
|
||||
A TaskDialog shows five options: 1. appdata mpv.net, 2. appdata mpv (shared with mpv),
|
||||
3. portable_config, 4. startup, 5. custom
|
||||
- slightly increased startup performance, start-threshold setting added.
|
||||
Threshold in milliseconds to wait for libmpv returning the video resolution
|
||||
before the window is shown, otherwise default dimensions are used as defined
|
||||
by autofit and start-size. Default: 1500
|
||||
- autofit-smaller setting added. Minimum window height in percent. Default: 40%
|
||||
- autofit-larger setting added. Maximum window height in percent. Default: 75%
|
||||
|
||||
### 4.7.3
|
||||
|
||||
- fix cursor showing load activity on startup
|
||||
- added file size and type to info command using audio files
|
||||
- added image format support to the info command, to file
|
||||
association management, to folder loading, to Everything
|
||||
- readme/github have a updated features and architecture section
|
||||
|
||||
### 4.7.1
|
||||
|
||||
- few layout problems were fixed, autosize for instance did not work
|
||||
|
||||
### 4.7
|
||||
|
||||
- remember-height was replaced with start-size, when start-size is set
|
||||
to video the main video starts directly with the native video size,
|
||||
before it was starting with the autofit size first and was only
|
||||
afterwards resized to the native video size
|
||||
- on exit the window location can be saved with remember-position
|
||||
- in the learn window of the input editor underscores were stripped
|
||||
because they have a special meaning in WPF labels
|
||||
- fix for keys/input not working for MBTN_LEFT_DBL, MBTN_BACK, MBTN_FORWARD
|
||||
- in the learn window of the input editor support was added for
|
||||
mouse left, mouse left double, mouse mid, mouse forward, mouse back
|
||||
- libmpv was updated to shinchiro 2019-07-07
|
||||
- when border is none it wasn't possible to minimize the window from
|
||||
the task bar because this is the WinForms default behavier. This
|
||||
was fixed by calling Spy++ to the rescue and adding WS_MINIMIZEBOX
|
||||
in CreateParams
|
||||
|
||||
### 4.6
|
||||
|
||||
- fix for middle mouse button not working
|
||||
- fix of logo overlay using a huge amount of memory (thx for the [ghacks article](https://www.ghacks.net/2019/07/05/a-look-at-mpv-net-a-mpv-frontend-with-everything-integration/))
|
||||
- fix config dialog showing a message about app restart without reason
|
||||
- when multiple files are selected in File Explorer and enter is
|
||||
pressed, the files are opened as selected, the order is random though
|
||||
because Explorer starts multiple mpv.net processes concurrently
|
||||
- libmpv was updated to shinchiro 2019-06-30
|
||||
- the [mpv.conf defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt) were changed to show a larger OSC
|
||||
- in case a file is opened that has a aspect ratio smaller then 1.2 then
|
||||
the window size will use a aspect ratio of 1.8
|
||||
- new JavaScript script osc-visibility.js included in the distribution
|
||||
under startup\scripts. It sets the OSC to be always on for audio files
|
||||
and auto for non audio files
|
||||
|
||||
### 4.5
|
||||
|
||||
- opening a URL manually no longer uses a input box but uses the clipboard directly
|
||||
- the manifest was missing the company attribute which caused
|
||||
mpv.net not appearing in the 'Open with' menu of the File Explorer,
|
||||
thanks to 44vince44 for pointing this out!!!
|
||||
- new Python and C# script examples were added to the wiki and the scripting and
|
||||
extension documentation was improved
|
||||
- invalid command line arguments were ignored, now an error message is shown
|
||||
- a description on how to start mpv.net from Google Chrome was added to the
|
||||
manual, it's useful to play videos from sites like YouTube, find the
|
||||
description [here](https://github.com/stax76/mpv.net/blob/master/Manual.md#chrome-extension)
|
||||
- new config setting remember-height added to remember the window height,
|
||||
otherwise the video's native resolution is used
|
||||
- support for protocols other then http added
|
||||
|
||||
### 4.4
|
||||
|
||||
- clipboard-monitoring was replaced by url-whitelist:
|
||||
Keyword whitelist to monitor the clipboard for URLs to play.
|
||||
Default: tube vimeo ard zdf
|
||||
- some settings like colors didn't work because enclosing quotes were missing
|
||||
- when single process queue is used the folder is no longer loaded
|
||||
- the playlist is never cleared whenever the control key is down but
|
||||
files and URLs are appended instead
|
||||
- powershell script hosting bugs were fixed and a new powershell example script
|
||||
was added to the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting#powershell)
|
||||
- the menu entry for the command palette was renamed to 'Show All Commands' and
|
||||
the default key binding was changed to F1 which is also the default in VS Code
|
||||
- the default key binding of the Everything media search was changed to F3
|
||||
- support for the mpv property 'border' was added to the config editor
|
||||
to show/hide the window decoration (titlebar, border). A toggle menu item and
|
||||
key binding (b) was added as well ([Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L135))
|
||||
|
||||
### 4.3.1
|
||||
|
||||
- there was a old bug setting the screen property
|
||||
|
||||
### 4.3
|
||||
|
||||
- there was new bug in file association feature
|
||||
|
||||
### 4.2
|
||||
|
||||
- the help and layout in the config editor was improved
|
||||
- clipboard monitoring for URLs can be disabled in the settings
|
||||
- the context menu has a new feature: Open > Add files to playlist,
|
||||
it appends files to the playlist [(Default binding)](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L33)
|
||||
- a setting was added to force using a single mpv.net process instance
|
||||
|
||||
### 4.1
|
||||
|
||||
- drag & drop support for subtitles was added
|
||||
- libmpv was updated
|
||||
- command line support for stdin and URLs was added
|
||||
- there was a crash happening when the player is
|
||||
minimized in the taskbar
|
||||
|
||||
### 4.0
|
||||
|
||||
- on the start screen the mpv.NET icon is shown instead of the mpv icon,
|
||||
feedback and contributions regarding the icon are welcome! The paint.net
|
||||
pdn and png source is located [here](https://github.com/stax76/mpv.net/tree/master/img)
|
||||
- everytime only one file is opened the complete folder is loaded in the playlist
|
||||
- the info command (i key) shows the audio format
|
||||
- new options osd-font-size, sub-font, sub-font-size
|
||||
- new color options with dedicated GUI support: sub-color, sub-border-color, sub-back-color
|
||||
- the config editor no longer shows the command line switches
|
||||
- the github start page was greatly improved
|
||||
- the setup.ps1 PowerShell script was greatly improved in regard of error handling and readability
|
||||
- a [manual to mpv.net](Manual.md) was created
|
||||
|
||||
### 3.7
|
||||
|
||||
- new icon design, probably better then before but still too simple
|
||||
- the radio buttons in the config editor have now a Windows 10 like design,
|
||||
they are larger and use the Windows theme color
|
||||
|
||||
### 3.6.1
|
||||
|
||||
- there was a bug causing an exception if both the input editor and config editor
|
||||
is opened, as soon as one is opened, the other can't be opened
|
||||
|
||||
### 3.6
|
||||
|
||||
- playing files from rar archives caused an exception
|
||||
- there was a bug that caused underscores beeing removed from input like MBTN_LEFT_DBL
|
||||
- the search clear button in the input editor had a render issue in dark mode
|
||||
- new search feature added to search and play media files, requires
|
||||
[Everything](https://www.voidtools.com) to be installed. [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L29)
|
||||
|
||||
### 3.5
|
||||
|
||||
- when the main windows gets activated and the clipboard content starts with http
|
||||
mpv.net will ask to play the URL, previously this was restricted to YouTube URLs
|
||||
- Python script errors show line and column whenever it is supported by IronPython
|
||||
- if conf files exist in the startup directory mpv.net will use the startup
|
||||
directory as config directory instead of creating default conf files in appdata
|
||||
- renamed commands are handled now by migration code instead of being broken
|
||||
|
||||
### 3.4
|
||||
|
||||
- new feature added to manage file associations from within the app. It can be found in the menu at: Tools > Manage... [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149)
|
||||
- new zip download option added
|
||||
- new x86 download option added
|
||||
24
LICENSE.txt
@@ -1,10 +1,24 @@
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 stax76
|
||||
Copyright (C) 2017-2020 Frank Skare (stax76)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and ssociated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and ssociated documentation
|
||||
files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
187
README.md
@@ -1,111 +1,148 @@
|
||||
# mpv.net
|
||||
|
||||
mpv.net is a libmpv based media player for Windows, it looks and works like mpv and also shares the same settings as mpv and therefore the mpv documentation applies.
|
||||

|
||||
|
||||
mpv and mpv.net have a learning curve.
|
||||
    
|
||||
|
||||
🎞 mpv.net
|
||||
==========
|
||||
|
||||
mpv.net is a modern media player for Windows based on the popular [mpv](https://mpv.io) player.
|
||||
|
||||
|
||||
#### Graphical User Interface
|
||||
|
||||
Modern GUI with customizable color themes.
|
||||
|
||||
|
||||
#### Command Line Interface
|
||||
|
||||
mpv.net supports mpvs property based command line switches.
|
||||
|
||||
|
||||
#### High quality video output
|
||||
|
||||
Video output that is capable of many features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more.
|
||||
|
||||
|
||||
#### On Screen Controller
|
||||
|
||||
Play controls with a modern flat design.
|
||||
|
||||
|
||||
#### GPU video decoding
|
||||
|
||||
Leverages the FFmpeg hwaccel APIs to support DXVA2 video decoding acceleration.
|
||||
|
||||
|
||||
#### Active development
|
||||
|
||||
mpv.net is under active development.
|
||||
|
||||
|
||||
#### Based on libmpv
|
||||
|
||||
mpv.net is based on libmpv which offers a straightforward C API that was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications. mpv is like VLC not based on DirectShow or Media Foundation.
|
||||
|
||||
mpv manual: <https://mpv.io/manual/master/>
|
||||
|
||||
Table of contents
|
||||
-----------------
|
||||
|
||||
- [Features](#features)
|
||||
- [Screenshots](#screenshots)
|
||||
- [Context Menu](#context-menu)
|
||||
- [Settings](#settings)
|
||||
- [Scripting](#scripting)
|
||||
- [Support](#support)
|
||||
- [Changelog](#changelog)
|
||||
- [Download](#download)
|
||||
- [Manual](#manual)
|
||||
- [Screenshots](#screenshots)
|
||||
|
||||
### Features
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- High degree of mpv compatibility, almost all mpv features are available
|
||||
- Customizable context menu defined in the same file as the key bindings
|
||||
- Searchable options dialog with modern UI as mpv compatible standalone application
|
||||
- Searchable input (key/mouse) binding editor with modern UI as mpv compatible standalone application
|
||||
- Modern UI using the OS theme color and dark mode
|
||||
- Rich addon/extension API for .NET languages, over 700 available mpv properties
|
||||
- Rich scripting API for Python, C#, Lua, JavaScript and PowerShell
|
||||
- mpv's OSC (on screen controller (play control bar)), IPC, conf files
|
||||
- Config dialog
|
||||
- Shorcut key editor
|
||||
- Many features like the config editor and shortcut key editor are fully searchable
|
||||
- Configuration files that are easy to read and edit
|
||||
- Command palette to quickly find commands and keys
|
||||
- Modern graphical user interface with customizable color themes
|
||||
- Extension API for .NET languages (C#, VB.NET and F#)
|
||||
- Scripting API for C#, Lua, JavaScript and PowerShell
|
||||
- JSON IPC to control the player with a external programs
|
||||
- On Screen Controler (OSC, play control buttons) with modern flat design
|
||||
- Command Line Interface
|
||||
- Started from a terminal status and debug output is printed on the terminal
|
||||
- DXVA2 video decoding acceleration
|
||||
- Video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more
|
||||
- File search feature powered by the popular search and index tool Everything
|
||||
- Browser extensions to start mpv.net from the browser
|
||||
- Fast seek performance
|
||||
- Fast startup performance
|
||||
- Usable as video player, audio player and image viewer with a wide range of supported formats
|
||||
- Built-in decoders, no external codecs have to be installed
|
||||
- Setup as x64, x86, installer, portable, Chocolatey and Scoop
|
||||
- Build-in media streaming via youtube-dl
|
||||
- File associations can be created by the setup and from the player
|
||||
- External audio and subtitle files can be loaded manually or automatically
|
||||
- Screenshot feature
|
||||
- File history feature to log time and filename
|
||||
- Watch later feature to save the position
|
||||
- Files can be enqueued from File Explorer
|
||||
- Update check and update routine
|
||||
|
||||
### Screenshots
|
||||
|
||||

|
||||
## [Support](Manual.md#support)
|
||||
|
||||

|
||||
[Support section of the manual.](Manual.md#support)
|
||||
|
||||

|
||||
|
||||

|
||||
## [Download](Manual.md#download)
|
||||
|
||||
### Context Menu
|
||||
[Download section of the manual.](Manual.md#download)
|
||||
|
||||
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:
|
||||
|
||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt>
|
||||
## [Manual](Manual.md)
|
||||
|
||||
### Settings
|
||||
[The mpv.net documentation.](Manual.md)
|
||||
|
||||
mpv.net shares the settings with mpv, settings can be edited in a settings dialog or in a config file called mpv.conf located at:
|
||||
```
|
||||
C:\Users\user\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>
|
||||
Screenshots
|
||||
-----------
|
||||
|
||||
### Scripting
|
||||
#### Main Window
|
||||
|
||||
Scripting is supported via Python, C#, Lua, JavaScript and PowerShell
|
||||

|
||||
|
||||
[Scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting-(CSharp,-Python,-JavaScript,-Lua,-PowerShell))
|
||||
|
||||
### Support
|
||||
#### Context Menu
|
||||
|
||||
[Support thread in Doom9 forum](https://forum.doom9.org/showthread.php?t=174841)
|
||||
Context menu using dark mode.
|
||||
|
||||
[Support thread in VideoHelp forum](https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows)
|
||||

|
||||
|
||||
[Issue tracker to report bugs and request features](https://github.com/stax76/mpv.net/issues)
|
||||
|
||||
### Changelog
|
||||
#### Config Editor
|
||||
|
||||
### 3.0 (2019-04-20)
|
||||
Searchable config editor as alternative to edit the conf file manually.
|
||||
|
||||
- the history feature logs now only files that were opened longer than 90 seconds
|
||||
- the default input command for cycling the audio tracks was replaced with an
|
||||
mpv.net command that shows detailed track info and has no 'no audio' track
|
||||
- new web site for mpv.net <https://mpv-net.github.io/mpv.net-web-site/>
|
||||
- the Tracks menu supports now MKV edition selection. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L106).
|
||||
- the Navigate menu supports now chapter selection. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L57).
|
||||
- opening the context menu was crashing if the default binding for Tracks was missing
|
||||

|
||||
|
||||
[go to download page](https://github.com/stax76/mpv.net/releases)
|
||||
|
||||
### 2.9 (2019-04-16)
|
||||
#### Terminal
|
||||
|
||||
- clicking the right top corner in full screen mode
|
||||
closes the player but it did not work on all displays
|
||||
- the info display was changed to display the filename on top
|
||||
so it's not displayed in the middle of the screen
|
||||
- on start up of the conf editor all text is now selected in the
|
||||
search text box so it's ready for a new search to be typed
|
||||
- the conf editor was changed to write the settings to disk
|
||||
only if the settings were actually modified, also the message
|
||||
that says that the settings will be available on next start
|
||||
is now only shown if the settings were actually modified.
|
||||
- there was an instance in the context menu where the sub menu
|
||||
arrow was overlapping with the text
|
||||
- in the input editor when only one character is entered in the
|
||||
search text box the search is performed only in the input and
|
||||
not in the command or menu
|
||||
- in the input editor the routine that generates the input string
|
||||
was completely rewritten because it was adding Shift where it
|
||||
wasn't necessary (it took a huge amount of time to implement)
|
||||
- the context menu has a new track menu where the active track
|
||||
can be seen and selected, it shows video, audio and subtitle
|
||||
tracks with various metadata. [Menu default definition](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L104).
|
||||
The screenshots were updated showing the [new track menu](https://github.com/stax76/mpv.net#screenshots).
|
||||
OSD console and status printed on the terminal.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Input Editor
|
||||
|
||||
Searchable key and mouse binding editor.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command Palette
|
||||
|
||||
Command Palette to find commands and shortcut keys easily.
|
||||
|
||||

|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using mpvnet;
|
||||
|
||||
namespace RatingAddon
|
||||
{
|
||||
[Export(typeof(IAddon))]
|
||||
public class RatingAddon : IAddon
|
||||
{
|
||||
Dictionary<string, int> Dic = new Dictionary<string, int>();
|
||||
|
||||
public RatingAddon()
|
||||
{
|
||||
mp.ClientMessage += mpv_ClientMessage;
|
||||
mp.Shutdown += mpv_Shutdown;
|
||||
}
|
||||
|
||||
void mpv_Shutdown()
|
||||
{
|
||||
foreach (var i in Dic)
|
||||
{
|
||||
string filepath = i.Key;
|
||||
int rating = i.Value;
|
||||
|
||||
if (String.IsNullOrEmpty(filepath) || ! File.Exists(filepath))
|
||||
return;
|
||||
|
||||
string basename = Path.GetFileNameWithoutExtension(filepath);
|
||||
|
||||
for (int x = 0; x < 6; x++)
|
||||
if (basename.Contains(" (" + x.ToString() + "stars)"))
|
||||
basename = basename.Replace(" (" + x.ToString() + "stars)", "");
|
||||
|
||||
basename += $" ({rating}stars)";
|
||||
string newPath = Path.Combine(Path.GetDirectoryName(filepath), basename + Path.GetExtension(filepath));
|
||||
|
||||
if (filepath.ToLower() != newPath.ToLower())
|
||||
File.Move(filepath, newPath);
|
||||
|
||||
File.SetLastWriteTime(newPath, DateTime.Now);
|
||||
}
|
||||
}
|
||||
|
||||
void mpv_ClientMessage(string[] args)
|
||||
{
|
||||
int rating;
|
||||
|
||||
if (args?.Length != 2 || args[0] != "rate-file" || ! int.TryParse(args[1], out rating))
|
||||
return;
|
||||
|
||||
Dic[mp.get_property_string("path")] = rating;
|
||||
mp.commandv("show-text", $"Rating: {rating}");
|
||||
}
|
||||
}
|
||||
}
|
||||
97
Release.ps1
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$desktopDir = [Environment]::GetFolderPath('Desktop')
|
||||
$exePath = $PSScriptRoot + '\mpv.net\bin\x64\mpvnet.exe'
|
||||
$versionInfo = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath)
|
||||
$vsDir = 'C:\Program Files (x86)\Microsoft Visual Studio\2019'
|
||||
$msBuild = $vsDir + '\Community\MSBuild\Current\Bin\MSBuild.exe'
|
||||
$inno = 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe'
|
||||
$7z = 'C:\Program Files\7-Zip\7z.exe'
|
||||
|
||||
$cloudDirectories = 'C:\Users\frank\OneDrive\Public\mpv.net\',
|
||||
'C:\Users\frank\Dropbox\Public\mpv.net\'
|
||||
|
||||
function UploadBeta($sourceFile)
|
||||
{
|
||||
foreach ($cloudDirectory in $cloudDirectories)
|
||||
{
|
||||
if (-not (Test-Path $cloudDirectory))
|
||||
{
|
||||
throw $cloudDirectory
|
||||
}
|
||||
|
||||
$targetFile = $cloudDirectory + (Split-Path $sourceFile -Leaf)
|
||||
|
||||
if (Test-Path $targetFile)
|
||||
{
|
||||
throw $targetFile
|
||||
}
|
||||
|
||||
Copy-Item $sourceFile $targetFile
|
||||
}
|
||||
}
|
||||
|
||||
if ($versionInfo.FilePrivatePart -eq 0)
|
||||
{
|
||||
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x64
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x86
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
& $inno /Darch=x64 setup.iss
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
& $inno /Darch=x86 setup.iss
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
$targetDir = $desktopDir + "\mpv.net-portable-x64-$($versionInfo.FileVersion)"
|
||||
Copy-Item .\mpv.net\bin\x64 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
$targetDir = $desktopDir + "\mpv.net-portable-x86-$($versionInfo.FileVersion)"
|
||||
Copy-Item .\mpv.net\bin\x86 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
Set-Clipboard ($versionInfo.FileVersion + "`n`nChangelog:`n`n" +
|
||||
'https://github.com/stax76/mpv.net/blob/master/Changelog.md' + "`n`nDownload:`n`n" +
|
||||
'https://github.com/stax76/mpv.net/blob/master/Manual.md#stable')
|
||||
}
|
||||
else
|
||||
{
|
||||
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x64
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x86
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
$targetDir = "$desktopDir\mpv.net-portable-x64-$($versionInfo.FileVersion)-beta"
|
||||
Copy-Item .\mpv.net\bin\x64 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
UploadBeta "$targetDir.7z"
|
||||
|
||||
$targetDir = $desktopDir + "\mpv.net-portable-x86-$($versionInfo.FileVersion)-beta"
|
||||
Copy-Item .\mpv.net\bin\x86 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
UploadBeta "$targetDir.7z"
|
||||
|
||||
foreach ($cloudDirectory in $cloudDirectories)
|
||||
{
|
||||
Invoke-Item $cloudDirectory
|
||||
}
|
||||
|
||||
Set-Clipboard ($versionInfo.FileVersion + " Beta`n`nChangelog:`n`n" +
|
||||
'https://github.com/stax76/mpv.net/blob/master/Changelog.md' + "`n`nDownload:`n`n" +
|
||||
'https://github.com/stax76/mpv.net/blob/master/Manual.md#beta')
|
||||
}
|
||||
|
||||
Write-Host 'successfully finished' -ForegroundColor Green
|
||||
13
VBNET/My Project/Application.Designer.vb
generated
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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 © 2019")>
|
||||
<Assembly: AssemblyTrademark("")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
'The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
<Assembly: Guid("a5571ff4-12ae-4e1a-ad2b-863b07d1b952")>
|
||||
|
||||
' 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")>
|
||||
62
VBNET/My Project/Resources.Designer.vb
generated
@@ -1,62 +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.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", "4.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(ByVal value As Global.System.Globalization.CultureInfo)
|
||||
resourceCulture = value
|
||||
End Set
|
||||
End Property
|
||||
End Module
|
||||
End Namespace
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
73
VBNET/My Project/Settings.Designer.vb
generated
@@ -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", "11.0.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(ByVal sender As Global.System.Object, ByVal 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
|
||||
@@ -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>
|
||||
@@ -1,678 +0,0 @@
|
||||
Imports System.IO
|
||||
Imports System.Reflection
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports System.Text
|
||||
Imports System.Text.RegularExpressions
|
||||
Imports System.Threading
|
||||
|
||||
Public Delegate Function PFTASKDIALOGCALLBACK(hwnd As IntPtr,
|
||||
msg As UInteger,
|
||||
wParam As IntPtr,
|
||||
lParam As IntPtr,
|
||||
lpRefData As IntPtr) As Integer
|
||||
Public Class Msg
|
||||
Public Shared Property SupportURL As String
|
||||
|
||||
Public Shared Sub Show(mainInstruction As String, Optional content As String = Nothing)
|
||||
Show(mainInstruction, content, MsgIcon.Info, MsgButtons.Ok)
|
||||
End Sub
|
||||
|
||||
Public Shared Sub ShowError(mainInstruction As String, Optional content As String = Nothing)
|
||||
If mainInstruction = "" Then mainInstruction = content
|
||||
If mainInstruction = "" Then Exit Sub
|
||||
|
||||
Using td As New TaskDialog(Of String)
|
||||
td.AllowCancel = False
|
||||
|
||||
If content = "" Then
|
||||
If mainInstruction.Length < 80 Then
|
||||
td.MainInstruction = mainInstruction
|
||||
Else
|
||||
td.Content = mainInstruction
|
||||
End If
|
||||
Else
|
||||
td.MainInstruction = mainInstruction
|
||||
td.Content = content
|
||||
End If
|
||||
|
||||
td.MainIcon = MsgIcon.Error
|
||||
td.Footer = "[copymsg Copy Message]"
|
||||
If SupportURL <> "" Then td.Footer += $" [{SupportURL} Contact Support]"
|
||||
td.Show()
|
||||
End Using
|
||||
End Sub
|
||||
|
||||
Public Shared Sub ShowException(e As Exception)
|
||||
Try
|
||||
Using td As New TaskDialog(Of String)
|
||||
td.MainInstruction = e.GetType.Name
|
||||
td.Content = e.Message
|
||||
td.MainIcon = MsgIcon.Error
|
||||
td.ExpandedInformation = e.ToString
|
||||
td.Footer = "[copymsg Copy Message]"
|
||||
If SupportURL <> "" Then td.Footer += $" [{SupportURL} Contact Support]"
|
||||
td.Show()
|
||||
End Using
|
||||
Catch
|
||||
MsgBox(e.GetType.Name + vbCrLf + vbCrLf + e.Message + vbCrLf + vbCrLf + e.ToString, MsgBoxStyle.Critical)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Shared ShownMessages As String
|
||||
|
||||
Public Shared Sub ShowWarning(mainInstruction As String,
|
||||
Optional content As String = Nothing,
|
||||
Optional onlyOnce As Boolean = False)
|
||||
|
||||
If onlyOnce AndAlso ShownMessages?.Contains(mainInstruction + content) Then Exit Sub
|
||||
Show(mainInstruction, content, MsgIcon.Warning, MsgButtons.Ok)
|
||||
If onlyOnce Then ShownMessages += mainInstruction + content
|
||||
End Sub
|
||||
|
||||
Public Shared Function ShowQuestion(mainInstruction As String,
|
||||
Optional buttons As MsgButtons = MsgButtons.OkCancel) As MsgResult
|
||||
|
||||
Return Show(mainInstruction, Nothing, MsgIcon.None, buttons)
|
||||
End Function
|
||||
|
||||
Public Shared Function ShowQuestion(mainInstruction As String,
|
||||
content As String,
|
||||
Optional buttons As MsgButtons = MsgButtons.OkCancel) As MsgResult
|
||||
Return Show(mainInstruction, content, MsgIcon.None, buttons)
|
||||
End Function
|
||||
|
||||
Public Shared Function Show(mainInstruction As String,
|
||||
content As String,
|
||||
icon As MsgIcon,
|
||||
buttons As MsgButtons,
|
||||
Optional defaultButton As MsgResult = MsgResult.None) As MsgResult
|
||||
|
||||
If mainInstruction Is Nothing Then mainInstruction = ""
|
||||
|
||||
Using td As New TaskDialog(Of MsgResult)
|
||||
td.AllowCancel = False
|
||||
td.DefaultButton = defaultButton
|
||||
td.MainIcon = icon
|
||||
|
||||
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
|
||||
|
||||
If buttons = MsgButtons.OkCancel Then
|
||||
td.AddButton("OK", MsgResult.OK)
|
||||
td.AddButton("Cancel", MsgResult.Cancel) 'don't use system language
|
||||
Else
|
||||
td.CommonButtons = buttons
|
||||
End If
|
||||
|
||||
Return td.Show()
|
||||
End Using
|
||||
End Function
|
||||
End Class
|
||||
|
||||
Public Class TaskDialog(Of T)
|
||||
Inherits TaskDialogNative
|
||||
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 = TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION
|
||||
Config.dwCommonButtons = MsgButtons.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 = DirectCast(Assembly.GetEntryAssembly().GetCustomAttributes(GetType(AssemblyProductAttribute), True)(0), AssemblyProductAttribute).Product
|
||||
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 sb As New StringBuilder(260)
|
||||
Dim foregroundHandle = GetForegroundWindow()
|
||||
GetWindowModuleFileName(foregroundHandle, sb, 260)
|
||||
|
||||
If Path.GetFileName(sb.ToString.Replace(".vshost", "")) =
|
||||
Path.GetFileName(System.Reflection.Assembly.GetEntryAssembly().Location) Then
|
||||
|
||||
Return foregroundHandle
|
||||
End If
|
||||
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 TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION
|
||||
ElseIf (Config.dwFlags And TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION) = TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION Then
|
||||
Config.dwFlags = Config.dwFlags Xor TASKDIALOG_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 MsgResult
|
||||
Get
|
||||
Return CType(Config.nDefaultButton, MsgResult)
|
||||
End Get
|
||||
Set(Value As MsgResult)
|
||||
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 MsgIcon
|
||||
Set(Value As MsgIcon)
|
||||
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 TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) = TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED
|
||||
End Get
|
||||
Set(value As Boolean)
|
||||
If value Then
|
||||
Config.dwFlags = Config.dwFlags Or TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED
|
||||
ElseIf CheckBoxChecked Then
|
||||
Config.dwFlags = Config.dwFlags Xor TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Private CommonButtonsValue As MsgButtons
|
||||
|
||||
Property CommonButtons() As MsgButtons
|
||||
Get
|
||||
Return Config.dwCommonButtons
|
||||
End Get
|
||||
Set(Value As MsgButtons)
|
||||
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 TASKDIALOG_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("\[(.*?) (.+?)\]")
|
||||
Dim m = re.Match(value)
|
||||
|
||||
If m.Success Then
|
||||
Config.dwFlags = Config.dwFlags Or TASKDIALOG_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, Optional value As T = Nothing)
|
||||
Dim id = 1000 + IdValueDic.Count + 1
|
||||
Dim temp As Object = text
|
||||
IdValueDic(id) = If(value Is Nothing, CType(temp, T), value)
|
||||
IdTextDic(id) = text
|
||||
Buttons.Add(New TASKDIALOG_BUTTON(id, text))
|
||||
Config.dwFlags = Config.dwFlags Or TASKDIALOG_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 + vbCrLf + description
|
||||
Buttons.Add(New TASKDIALOG_BUTTON(id, text))
|
||||
Config.dwFlags = Config.dwFlags Or TASKDIALOG_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 MsgResult Then SelectedValue = DirectCast(CObj(SelectedID), T)
|
||||
Return SelectedValue
|
||||
End Function
|
||||
|
||||
Private ExitTickCount As Integer
|
||||
|
||||
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 MsgResult 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, New IntPtr(MsgResult.OK), IntPtr.Zero)
|
||||
End If
|
||||
Case TDN_HYPERLINK_CLICKED
|
||||
Dim url = Marshal.PtrToStringUni(lParam)
|
||||
|
||||
If url.StartsWith("mailto") OrElse url.StartsWith("http") Then
|
||||
Process.Start(url)
|
||||
ElseIf url = "copymsg" Then
|
||||
Dim thread As New Thread(
|
||||
New ThreadStart(Sub()
|
||||
System.Windows.Forms.Clipboard.SetText(MainInstruction + vbCrLf + vbCrLf + Content + vbCrLf + vbCrLf + ExpandedInformation)
|
||||
MsgBox("Message was copied to clipboard.",
|
||||
MsgBoxStyle.Information,
|
||||
DirectCast(Assembly.GetEntryAssembly().GetCustomAttributes(GetType(AssemblyProductAttribute), True)(0), AssemblyProductAttribute).Product)
|
||||
End Sub))
|
||||
thread.SetApartmentState(ApartmentState.STA)
|
||||
thread.Start()
|
||||
End If
|
||||
Case TDN_CREATED
|
||||
For Each i In CommandLinkShieldList
|
||||
SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, New IntPtr(i), New IntPtr(1))
|
||||
Next
|
||||
End Select
|
||||
End Function
|
||||
|
||||
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
|
||||
|
||||
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 TaskDialogNative
|
||||
<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")>
|
||||
Shared Function SendMessage(handle As IntPtr,
|
||||
message As Int32,
|
||||
wParam As IntPtr,
|
||||
lParam As IntPtr) 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 TASKDIALOG_FLAGS
|
||||
Public dwCommonButtons As MsgButtons
|
||||
<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
|
||||
|
||||
Public Enum TASKDIALOG_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 MsgButtons
|
||||
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 MsgIcon
|
||||
None = 0
|
||||
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
|
||||
|
||||
Public Enum MsgResult
|
||||
None = 0
|
||||
OK = 1
|
||||
Cancel = 2
|
||||
Abort = 3
|
||||
Retry = 4
|
||||
Ignore = 5
|
||||
Yes = 6
|
||||
No = 7
|
||||
End Enum
|
||||
@@ -1,109 +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>{A1D11294-05BF-4D77-B008-AECF1AA93C9F}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>VBNET</RootNamespace>
|
||||
<AssemblyName>VBNET</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<Deterministic>true</Deterministic>
|
||||
</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>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>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.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.Linq" />
|
||||
<Import Include="System.Xml.Linq" />
|
||||
<Import Include="System.Threading.Tasks" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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="TaskDialog.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>
|
||||
@@ -5,12 +5,12 @@ 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("RatingAddon")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyTitle("RatingExtension")]
|
||||
[assembly: AssemblyDescription("RatingExtension")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RatingAddon")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
||||
[assembly: AssemblyProduct("RatingExtension")]
|
||||
[assembly: AssemblyCopyright("Copyright (C) 2017-2020 Frank Skare (stax76)")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
66
extensions/RatingExtension/RatingExtension.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
// This extension writes a rating to the filename of rated videos when mpv.net shuts down.
|
||||
|
||||
// The input.conf defaults contain key bindings for this extension to set ratings.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using mpvnet;
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace RatingExtension // the assembly name must end with 'Extension'
|
||||
{
|
||||
[Export(typeof(IExtension))]
|
||||
public class RatingExtension : IExtension
|
||||
{
|
||||
// dictionory to store the filename and the rating
|
||||
Dictionary<string, int> Dic = new Dictionary<string, int>();
|
||||
|
||||
public RatingExtension() // plugin initialization
|
||||
{
|
||||
core.ClientMessage += ClientMessage; //handles keys defined in input.conf
|
||||
core.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN
|
||||
}
|
||||
|
||||
// handles MPV_EVENT_SHUTDOWN
|
||||
void Shutdown()
|
||||
{
|
||||
foreach (var i in Dic)
|
||||
{
|
||||
string filepath = i.Key;
|
||||
int rating = i.Value;
|
||||
if (String.IsNullOrEmpty(filepath) || !File.Exists(filepath))
|
||||
return;
|
||||
string basename = Path.GetFileNameWithoutExtension(filepath);
|
||||
|
||||
for (int x = 0; x < 6; x++)
|
||||
if (basename.Contains(" (" + x + "stars)"))
|
||||
basename = basename.Replace(" (" + x + "stars)", "");
|
||||
|
||||
basename += $" ({rating}stars)";
|
||||
string newPath = Path.Combine(Path.GetDirectoryName(filepath), basename + Path.GetExtension(filepath));
|
||||
if (filepath.ToLower() != newPath.ToLower())
|
||||
File.Move(filepath, newPath);
|
||||
File.SetLastWriteTime(newPath, DateTime.Now);
|
||||
}
|
||||
}
|
||||
|
||||
//handles keys defined in input.conf
|
||||
void ClientMessage(string[] args)
|
||||
{
|
||||
if (args[0] != "rate-file") return;
|
||||
|
||||
if (int.TryParse(args[1], out int rating))
|
||||
{
|
||||
string path = core.get_property_string("path");
|
||||
if (!File.Exists(path)) return;
|
||||
Dic[path] = rating;
|
||||
core.commandv("show-text", $"Rating: {rating}");
|
||||
}
|
||||
else if (args[1] == "about")
|
||||
Msg.Show("Rating Extension", "This extension writes a rating to the filename of rated videos when mpv.net shuts down.\n\nThe input.conf defaults contain key bindings for this extension to set ratings.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,32 +7,15 @@
|
||||
<ProjectGuid>{55C88710-539D-4402-84C8-31694841C731}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>RatingAddon</RootNamespace>
|
||||
<AssemblyName>RatingAddon</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<RootNamespace>RatingExtension</RootNamespace>
|
||||
<AssemblyName>RatingExtension</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\mpv.net\bin\x86\Debug\</OutputPath>
|
||||
<OutputPath>..\..\mpv.net\bin\x86\Extensions\RatingExtension\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@@ -40,7 +23,7 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\mpv.net\bin\x86\Release\</OutputPath>
|
||||
<OutputPath>..\..\mpv.net\bin\x86\Extensions\RatingExtension\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -50,7 +33,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\mpv.net\bin\x64\Debug\</OutputPath>
|
||||
<OutputPath>..\..\mpv.net\bin\x64\Extensions\RatingExtension\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
@@ -58,7 +41,7 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>..\mpv.net\bin\x64\Release\</OutputPath>
|
||||
<OutputPath>..\..\mpv.net\bin\x64\Extensions\RatingExtension\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -78,11 +61,11 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="RatingAddon.cs" />
|
||||
<Compile Include="RatingExtension.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
|
||||
<ProjectReference Include="..\..\mpv.net\mpv.net.csproj">
|
||||
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
|
||||
<Name>mpv.net</Name>
|
||||
<Private>False</Private>
|
||||
36
extensions/ScriptingExtension/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
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("RatingExtension")]
|
||||
[assembly: AssemblyDescription("RatingExtension")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
||||
[assembly: AssemblyProduct("RatingExtension")]
|
||||
[assembly: AssemblyCopyright("Copyright (C) 2017-2020 Frank Skare (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)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("55c88710-539d-4402-84c8-31694841c731")]
|
||||
|
||||
// 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")]
|
||||
56
extensions/ScriptingExtension/ScriptingExtension.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
// This extension implements the C# scripting feature of mpv.net which
|
||||
// is based on CS-Script (https://www.cs-script.net).
|
||||
|
||||
// I also use this extension to code scripts in order to have full
|
||||
// code completion and debugger support, once the script code is
|
||||
// finished I move it from the extension to a standalone script.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using mpvnet;
|
||||
using CSScriptLibrary;
|
||||
using static mpvnet.Core;
|
||||
|
||||
// the file name of extensions must end with 'Extension'
|
||||
namespace ScriptingExtension
|
||||
{
|
||||
[Export(typeof(IExtension))]
|
||||
public class ScriptingExtension : IExtension
|
||||
{
|
||||
//Script Script;
|
||||
|
||||
public ScriptingExtension()
|
||||
{
|
||||
//Script = new Script();
|
||||
List<string> files = new List<string>();
|
||||
|
||||
if (Directory.Exists(core.ConfigFolder + "scripts-cs"))
|
||||
files.AddRange(Directory.GetFiles(core.ConfigFolder + "scripts-cs", "*.cs"));
|
||||
|
||||
if (Directory.Exists(Folder.Startup + "scripts"))
|
||||
foreach (string path in Directory.GetFiles(Folder.Startup + "scripts", "*.cs"))
|
||||
files.AddRange(Directory.GetFiles(Folder.Startup + "scripts", "*.cs"));
|
||||
|
||||
if (files.Count == 0)
|
||||
return;
|
||||
|
||||
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
try
|
||||
{
|
||||
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(file));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
App.ShowException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
extensions/ScriptingExtension/ScriptingExtension.csproj
Normal file
@@ -0,0 +1,80 @@
|
||||
<?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>{94255EF2-C823-4D82-9017-0E993CC0F5A1}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ScriptingExtension</RootNamespace>
|
||||
<AssemblyName>ScriptingExtension</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\mpv.net\bin\x86\Extensions\ScriptingExtension\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\..\mpv.net\bin\x86\Extensions\ScriptingExtension\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\mpv.net\bin\x64\Extensions\ScriptingExtension\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>..\..\mpv.net\bin\x64\Extensions\ScriptingExtension\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="CSScriptLibrary">
|
||||
<HintPath>.\CSScriptLibrary.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ScriptingExtension.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="script.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>
|
||||
31
extensions/ScriptingExtension/ScriptingExtension.sln
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29123.88
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingExtension", "ScriptingExtension.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.Build.0 = Debug|x64
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.Build.0 = Debug|x86
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.ActiveCfg = Release|x64
|
||||
{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
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C8A53BF6-B00A-4215-B9D7-801ADB9C8F60}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
19
extensions/ScriptingExtension/script.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
using System.IO;
|
||||
|
||||
using mpvnet;
|
||||
using static mpvnet.Core;
|
||||
|
||||
class Script
|
||||
{
|
||||
public Script()
|
||||
{
|
||||
core.Shutdown += Shutdown;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(@"C:\Users\frank\Desktop\aaa"))
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
BIN
img/Avatar.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
img/CommandPalette.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
img/ConfEditor.png
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
img/InputEditor.png
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
img/Main.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
img/MediaSearch.png
Normal file
|
After Width: | Height: | Size: 628 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
BIN
img/Terminal.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
img/mpvnet.ico
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
img/mpvnet.pdn
Normal file
BIN
img/mpvnet.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
48
mpv.net.sln
@@ -5,70 +5,42 @@ VisualStudioVersion = 16.0.28729.10
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
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}") = "RatingAddon", "RatingAddon\RatingAddon.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingExtension", "extensions\RatingExtension\RatingExtension.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
|
||||
EndProject
|
||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CSScriptAddon", "CSScriptAddon\CSScriptAddon.vbproj", "{71808A87-8B1C-4DF8-957C-D79C3B164CCA}"
|
||||
EndProject
|
||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "VBNET", "VBNET\VBNET.vbproj", "{A1D11294-05BF-4D77-B008-AECF1AA93C9F}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingExtension", "extensions\ScriptingExtension\ScriptingExtension.csproj", "{94255EF2-C823-4D82-9017-0E993CC0F5A1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.Build.0 = Debug|x64
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.Build.0 = Debug|x86
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.ActiveCfg = Release|x64
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.Build.0 = Release|x64
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.ActiveCfg = Release|x86
|
||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.Build.0 = Release|x86
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.Build.0 = Debug|x64
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.Build.0 = Debug|x86
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.ActiveCfg = Release|x64
|
||||
{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
|
||||
{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
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A1D11294-05BF-4D77-B008-AECF1AA93C9F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x64.Build.0 = Debug|x64
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x86.Build.0 = Debug|x86
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x64.ActiveCfg = Release|x64
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x64.Build.0 = Release|x64
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x86.ActiveCfg = Release|x86
|
||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using VBNET;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Addon
|
||||
{
|
||||
[ImportMany]
|
||||
public IEnumerable<IAddon> Addons = null;
|
||||
|
||||
readonly CompositionContainer CompositionContainer;
|
||||
|
||||
public Addon()
|
||||
{
|
||||
try
|
||||
{
|
||||
AggregateCatalog catalog = new AggregateCatalog();
|
||||
|
||||
string dir = Application.StartupPath + "\\Addons";
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
foreach (string i in Directory.GetDirectories(dir))
|
||||
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
|
||||
|
||||
dir = mp.MpvConfFolderPath + "\\Addons";
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
foreach (string i in Directory.GetDirectories(dir))
|
||||
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
|
||||
|
||||
if (catalog.Catalogs.Count > 0)
|
||||
{
|
||||
CompositionContainer = new CompositionContainer(catalog);
|
||||
CompositionContainer.ComposeParts(this);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAddon
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@
|
||||
<configSections>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using VBNET;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Command
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Action<string[]> Action { get; set; }
|
||||
|
||||
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_conf_folder(string[] args)
|
||||
{
|
||||
Process.Start(mp.MpvConfFolderPath);
|
||||
}
|
||||
|
||||
public static void show_input_editor(string[] args)
|
||||
{
|
||||
Process.Start(Application.StartupPath + "\\mpvInputEdit.exe");
|
||||
}
|
||||
|
||||
public static void show_conf_editor(string[] args)
|
||||
{
|
||||
Process.Start(Application.StartupPath + "\\mpvConfEdit.exe");
|
||||
}
|
||||
|
||||
public static void show_history(string[] args)
|
||||
{
|
||||
var fp = mp.MpvConfFolderPath + "history.txt";
|
||||
|
||||
if (File.Exists(fp))
|
||||
Process.Start(fp);
|
||||
else
|
||||
if (Msg.ShowQuestion("Create history.txt file in config folder?",
|
||||
"mpv.net will write the date, time and filename of opened files to it.") == MsgResult.OK)
|
||||
File.WriteAllText(fp, "");
|
||||
}
|
||||
|
||||
public static void shell_execute(string[] args) => Process.Start(args[0]);
|
||||
|
||||
public static void show_info(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(mp.get_property_string("path"));
|
||||
|
||||
using (MediaInfo 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";
|
||||
|
||||
double bitrate2 = Convert.ToDouble(bitrate) / 1000.0 / 1000.0;
|
||||
string videoCodec = mp.get_property_string("video-format").ToUpper();
|
||||
string filename = fileInfo.Name;
|
||||
|
||||
string text = filename + "\n" +
|
||||
FormatTime(position.TotalMinutes) + ":" +
|
||||
FormatTime(position.Seconds) + " / " +
|
||||
FormatTime(duration.TotalMinutes) + ":" +
|
||||
FormatTime(duration.Seconds) + "\n" +
|
||||
$"{width} x {height}\n" +
|
||||
$"{bitrate2.ToString("f1")} Mb/s\n" +
|
||||
Convert.ToInt32(fileInfo.Length / 1024 / 1024).ToString() + " MB\n" +
|
||||
$"{videoCodec}\n";
|
||||
|
||||
mp.commandv("show-text", text, "5000");
|
||||
}
|
||||
|
||||
string FormatTime(double value) => ((int)value).ToString("00");
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void execute_mpv_command(string[] args)
|
||||
{
|
||||
MainForm.Instance.Invoke(new Action(() => {
|
||||
string command = Microsoft.VisualBasic.Interaction.InputBox("Enter a mpv command to be executed.");
|
||||
if (string.IsNullOrEmpty(command)) return;
|
||||
mp.command_string(command, false);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void open_url(string[] args)
|
||||
{
|
||||
MainForm.Instance.Invoke(new Action(() => {
|
||||
string command = Microsoft.VisualBasic.Interaction.InputBox("Enter URL to be opened.");
|
||||
if (string.IsNullOrEmpty(command)) return;
|
||||
mp.LoadURL(command);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void load_sub(string[] args)
|
||||
{
|
||||
MainForm.Instance.BeginInvoke(new Action(() => {
|
||||
using (var d = new OpenFileDialog())
|
||||
{
|
||||
d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false));
|
||||
d.Multiselect = true;
|
||||
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
foreach (string i in d.FileNames)
|
||||
mp.commandv("sub-add", i);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void load_audio(string[] args)
|
||||
{
|
||||
MainForm.Instance.BeginInvoke(new Action(() => {
|
||||
using (var d = new OpenFileDialog())
|
||||
{
|
||||
d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false));
|
||||
d.Multiselect = true;
|
||||
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
foreach (string i in d.FileNames)
|
||||
mp.commandv("audio-add", i);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void cycle_audio(string[] args)
|
||||
{
|
||||
string filePath = mp.get_property_string("path", false);
|
||||
if (!File.Exists(filePath)) return;
|
||||
|
||||
using (MediaInfo mi = new MediaInfo(filePath))
|
||||
{
|
||||
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
|
||||
if (audTracks.Length < 2) return;
|
||||
int aid = mp.get_property_int("aid");
|
||||
aid += 1;
|
||||
if (aid > audTracks.Length) aid = 1;
|
||||
mp.commandv("set", "aid", aid.ToString());
|
||||
mp.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,25 @@
|
||||
using System;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Navigation;
|
||||
|
||||
using Tommy;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
public static List<SettingBase> LoadSettings(string filepath)
|
||||
public static List<SettingBase> LoadSettings(string content)
|
||||
{
|
||||
TomlTable table;
|
||||
using (StreamReader reader = new StreamReader(File.OpenRead(filepath)))
|
||||
|
||||
using (StringReader reader = new StringReader(content))
|
||||
table = TOML.Parse(reader);
|
||||
|
||||
List<SettingBase> settingsList = new List<SettingBase>();
|
||||
|
||||
foreach (TomlTable setting in table["settings"])
|
||||
@@ -27,56 +32,74 @@ namespace DynamicGUI
|
||||
baseSetting = optionSetting;
|
||||
optionSetting.Default = setting["default"];
|
||||
optionSetting.Value = optionSetting.Default;
|
||||
optionSetting.StartValue = 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"];
|
||||
else if (opt.Name == optionSetting.Default)
|
||||
opt.Text = opt.Name + " (Default)";
|
||||
|
||||
opt.OptionSetting = optionSetting;
|
||||
optionSetting.Options.Add(opt);
|
||||
}
|
||||
}
|
||||
else if (setting["default"].IsString)
|
||||
else
|
||||
{
|
||||
StringSetting stringSetting = new StringSetting();
|
||||
baseSetting = stringSetting;
|
||||
stringSetting.Default = setting["default"];
|
||||
if (setting.HasKey("folder")) stringSetting.IsFolder = true;
|
||||
stringSetting.Default = setting.HasKey("default") ? setting["default"].ToString() : "";
|
||||
}
|
||||
|
||||
baseSetting.Name = setting["name"];
|
||||
baseSetting.File = setting["file"];
|
||||
baseSetting.Filter = setting["filter"];
|
||||
|
||||
if (setting.HasKey("help")) baseSetting.Help = setting["help"];
|
||||
if (setting.HasKey("helpurl")) baseSetting.HelpURL = setting["helpurl"];
|
||||
if (setting.HasKey("url")) baseSetting.URL = setting["url"];
|
||||
if (setting.HasKey("width")) baseSetting.Width = setting["width"];
|
||||
if (setting.HasKey("type")) baseSetting.Type = setting["type"];
|
||||
|
||||
settingsList.Add(baseSetting);
|
||||
}
|
||||
return settingsList;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfItem
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
public string Value { get; set; } = "";
|
||||
public string Comment { get; set; } = "";
|
||||
public string LineComment { get; set; } = "";
|
||||
public string Section { get; set; } = "";
|
||||
public string File { get; set; } = "";
|
||||
public bool IsSectionItem { get; set; }
|
||||
public SettingBase SettingBase { get; set; }
|
||||
}
|
||||
|
||||
public abstract class SettingBase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string File { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string StartValue { get; set; }
|
||||
public string Help { get; set; }
|
||||
public string Default { get; set; }
|
||||
public string HelpURL { get; set; }
|
||||
public string URL { get; set; }
|
||||
public string Filter { get; set; }
|
||||
public string Type { get; set; }
|
||||
public int Width { get; set; }
|
||||
public ConfItem ConfItem { get; set; }
|
||||
}
|
||||
|
||||
public class StringSetting : SettingBase
|
||||
{
|
||||
public bool IsFolder { get; set; }
|
||||
}
|
||||
|
||||
public class OptionSetting : SettingBase
|
||||
@@ -91,7 +114,7 @@ namespace DynamicGUI
|
||||
|
||||
public OptionSetting OptionSetting { get; set; }
|
||||
|
||||
private string _Text;
|
||||
string _Text;
|
||||
|
||||
public string Text
|
||||
{
|
||||
@@ -99,7 +122,7 @@ namespace DynamicGUI
|
||||
set => _Text = value;
|
||||
}
|
||||
|
||||
public bool IsChecked
|
||||
public bool Checked
|
||||
{
|
||||
get => OptionSetting.Value == Name ;
|
||||
set {
|
||||
@@ -107,6 +130,11 @@ namespace DynamicGUI
|
||||
OptionSetting.Value = Name;
|
||||
}
|
||||
}
|
||||
|
||||
public Visibility Visibility
|
||||
{
|
||||
get => string.IsNullOrEmpty(Help) ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
interface ISettingControl
|
||||
@@ -117,7 +145,7 @@ namespace DynamicGUI
|
||||
|
||||
public class HyperlinkEx : Hyperlink
|
||||
{
|
||||
private void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
Process.Start(e.Uri.AbsoluteUri);
|
||||
}
|
||||
64
mpv.net/DynamicGUI/OptionSettingControl.xaml
Normal file
@@ -0,0 +1,64 @@
|
||||
<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"
|
||||
xmlns:mpvnet="clr-namespace:mpvnet"
|
||||
mc:Ignorable="d"
|
||||
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
|
||||
<Grid Margin="20,0">
|
||||
<StackPanel>
|
||||
<TextBox x:Name="TitleTextBox"
|
||||
FontSize="24"
|
||||
Margin="0,10"
|
||||
BorderThickness="0"
|
||||
IsReadOnly="True"
|
||||
Foreground="{x:Static mpvnet:Theme.Heading}"
|
||||
Background="{x:Static mpvnet:Theme.Background}" />
|
||||
|
||||
<ItemsControl x:Name="ItemsControl">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<WrapPanel Orientation="Vertical">
|
||||
<RadioButton x:Name="RadioButton"
|
||||
VerticalContentAlignment="Center"
|
||||
IsChecked="{Binding Checked}"
|
||||
GroupName="{Binding OptionSetting.Name}"
|
||||
Content="{Binding Text}"
|
||||
FontSize="16"
|
||||
FontWeight="Normal"
|
||||
VerticalAlignment="Top"
|
||||
Foreground="{x:Static mpvnet:Theme.Foreground}"/>
|
||||
|
||||
<TextBox x:Name="ItemHelpTextBox"
|
||||
TextWrapping="WrapWithOverflow"
|
||||
Text="{Binding Help}"
|
||||
Visibility="{Binding Visibility}"
|
||||
Margin="10,0,0,0" BorderThickness="0"
|
||||
IsReadOnly="True" Padding="7,0,0,0"
|
||||
MinHeight="0"
|
||||
Foreground="{x:Static mpvnet:Theme.Foreground2}"
|
||||
Background="{x:Static mpvnet:Theme.Background}"/>
|
||||
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBox x:Name="HelpTextBox"
|
||||
TextWrapping="WrapWithOverflow"
|
||||
BorderThickness="0"
|
||||
IsReadOnly="True"
|
||||
Margin="0,10,0,0"
|
||||
Foreground="{x:Static mpvnet:Theme.Foreground}"
|
||||
Background="{x:Static mpvnet:Theme.Background}"/>
|
||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,33 +1,42 @@
|
||||
using System.Windows;
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public partial class OptionSettingControl : UserControl, ISettingControl
|
||||
{
|
||||
private OptionSetting OptionSetting;
|
||||
OptionSetting OptionSetting;
|
||||
|
||||
public OptionSettingControl(OptionSetting optionSetting)
|
||||
{
|
||||
OptionSetting = optionSetting;
|
||||
InitializeComponent();
|
||||
TitleTextBox.Text = optionSetting.Name;
|
||||
|
||||
if (string.IsNullOrEmpty(optionSetting.Help))
|
||||
HelpTextBox.Visibility = Visibility.Collapsed;
|
||||
|
||||
HelpTextBox.Text = optionSetting.Help;
|
||||
ItemsControl.ItemsSource = optionSetting.Options;
|
||||
Link.SetURL(optionSetting.HelpURL);
|
||||
if (string.IsNullOrEmpty(optionSetting.HelpURL))
|
||||
|
||||
if (string.IsNullOrEmpty(optionSetting.URL))
|
||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||
|
||||
Link.SetURL(optionSetting.URL);
|
||||
}
|
||||
|
||||
private string _SearchableText;
|
||||
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;
|
||||
@@ -37,4 +46,4 @@ namespace DynamicGUI
|
||||
public SettingBase SettingBase => OptionSetting;
|
||||
public bool Contains(string searchString) => SearchableText.Contains(searchString.ToLower());
|
||||
}
|
||||
}
|
||||
}
|
||||
58
mpv.net/DynamicGUI/StringSettingControl.xaml
Normal file
@@ -0,0 +1,58 @@
|
||||
<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"
|
||||
xmlns:mpvnet="clr-namespace:mpvnet"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
|
||||
<Grid Margin="20,0">
|
||||
<StackPanel>
|
||||
<TextBox x:Name="TitleTextBox"
|
||||
FontSize="24"
|
||||
Margin="0,10"
|
||||
BorderThickness="0"
|
||||
IsReadOnly="True"
|
||||
Foreground="{x:Static mpvnet:Theme.Heading}"
|
||||
Background="{x:Static mpvnet:Theme.Background}"/>
|
||||
|
||||
<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"
|
||||
Height="20"
|
||||
HorizontalAlignment="Left"
|
||||
Foreground="{x:Static mpvnet:Theme.Foreground}"
|
||||
Background="{x:Static mpvnet:Theme.Background}"
|
||||
CaretBrush="{x:Static mpvnet:Theme.Foreground}"
|
||||
TextChanged="ValueTextBox_TextChanged"/>
|
||||
|
||||
<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"
|
||||
BorderThickness="0"
|
||||
IsReadOnly="True"
|
||||
Foreground="{x:Static mpvnet:Theme.Foreground}"
|
||||
Background="{x:Static mpvnet:Theme.Background}"/>
|
||||
|
||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
122
mpv.net/DynamicGUI/StringSettingControl.xaml.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using WinForms = System.Windows.Forms;
|
||||
|
||||
namespace DynamicGUI
|
||||
{
|
||||
public partial class StringSettingControl : UserControl, ISettingControl
|
||||
{
|
||||
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.Type != "folder" && StringSetting.Type != "color")
|
||||
Button.Visibility = Visibility.Hidden;
|
||||
|
||||
Link.SetURL(StringSetting.URL);
|
||||
|
||||
if (string.IsNullOrEmpty(stringSetting.URL))
|
||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
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 SettingBase SettingBase => StringSetting;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => StringSetting.Value;
|
||||
set => StringSetting.Value = value;
|
||||
}
|
||||
|
||||
void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
switch (StringSetting.Type)
|
||||
{
|
||||
case "folder":
|
||||
using (var d = new WinForms.FolderBrowserDialog())
|
||||
{
|
||||
d.Description = "Choose a folder.";
|
||||
d.SelectedPath = ValueTextBox.Text;
|
||||
|
||||
if (d.ShowDialog() == WinForms.DialogResult.OK)
|
||||
ValueTextBox.Text = d.SelectedPath;
|
||||
}
|
||||
break;
|
||||
case "color":
|
||||
using (var dialog = new WinForms.ColorDialog())
|
||||
{
|
||||
dialog.FullOpen = true;
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ValueTextBox.Text))
|
||||
{
|
||||
Color col = GetColor(ValueTextBox.Text);
|
||||
dialog.Color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
if (dialog.ShowDialog() == WinForms.DialogResult.OK)
|
||||
ValueTextBox.Text = "#" + dialog.Color.ToArgb().ToString("X8");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ValueTextBox_TextChanged(object sender, TextChangedEventArgs e) => Update();
|
||||
|
||||
Color GetColor(string value)
|
||||
{
|
||||
if (value.Contains("/"))
|
||||
{
|
||||
string[] a = value.Split('/');
|
||||
|
||||
if (a.Length == 3)
|
||||
return Color.FromRgb(ToByte(a[0]), ToByte(a[1]), ToByte(a[2]));
|
||||
else if (a.Length == 4)
|
||||
return Color.FromArgb(ToByte(a[3]), ToByte(a[0]), ToByte(a[1]), ToByte(a[2]));
|
||||
}
|
||||
|
||||
return (Color)ColorConverter.ConvertFromString(value);
|
||||
|
||||
Byte ToByte(string val) => Convert.ToByte(Convert.ToSingle(val, CultureInfo.InvariantCulture) * 255);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (StringSetting.Type == "color")
|
||||
{
|
||||
Color c = Colors.Transparent;
|
||||
|
||||
if (ValueTextBox.Text != "")
|
||||
try { c = GetColor(ValueTextBox.Text); } catch {}
|
||||
|
||||
ValueTextBox.Background = new SolidColorBrush(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1752,7 +1752,6 @@ namespace Tommy
|
||||
}
|
||||
else
|
||||
stringBuilder.Append(c);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 stax76
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and ssociated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,567 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
using VBNET;
|
||||
using System.Globalization;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
public static MainForm Instance { get; set; }
|
||||
public static IntPtr Hwnd { get; set; }
|
||||
|
||||
public new ContextMenuStripEx ContextMenu;
|
||||
|
||||
MenuItemEx TracksMenu;
|
||||
MenuItemEx ChaptersMenu;
|
||||
|
||||
Point LastCursorPosChanged;
|
||||
int LastCursorChangedTickCount;
|
||||
bool IgnoreDpiChanged = true;
|
||||
|
||||
float MpvAutofit = 0.50f;
|
||||
bool MpvFullscreen;
|
||||
int MpvScreen = -1;
|
||||
string MpvNetDarkMode = "system";
|
||||
string MpvSid = "";
|
||||
string MpvAid = "";
|
||||
string MpvVid = "";
|
||||
int MpvEdition;
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
try
|
||||
{
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
Application.ThreadException += Application_ThreadException;
|
||||
Msg.SupportURL = "https://github.com/stax76/mpv.net#support";
|
||||
|
||||
Instance = this;
|
||||
Hwnd = Handle;
|
||||
MinimumSize = new Size(FontHeight * 16, FontHeight * 9);
|
||||
Text += " " + Application.ProductVersion;
|
||||
|
||||
foreach (var i in mp.mpvConf)
|
||||
ProcessMpvProperty(i.Key, i.Value);
|
||||
|
||||
foreach (var i in mp.mpvNetConf)
|
||||
ProcessMpvNetProperty(i.Key, i.Value);
|
||||
|
||||
ProcessCommandLineEarly();
|
||||
|
||||
if (MpvScreen == -1) MpvScreen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen);
|
||||
SetScreen(MpvScreen);
|
||||
|
||||
ChangeFullscreen(MpvFullscreen);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenu_Opening(object sender, CancelEventArgs e)
|
||||
{
|
||||
lock (mp.MediaTracks)
|
||||
{
|
||||
if (TracksMenu != null)
|
||||
TracksMenu.DropDownItems.Clear();
|
||||
|
||||
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
|
||||
MediaTrack[] subTracks = mp.MediaTracks.Where(track => track.Type == "s").ToArray();
|
||||
MediaTrack[] vidTracks = mp.MediaTracks.Where(track => track.Type == "v").ToArray();
|
||||
MediaTrack[] ediTracks = mp.MediaTracks.Where(track => track.Type == "e").ToArray();
|
||||
|
||||
foreach (MediaTrack track in vidTracks)
|
||||
{
|
||||
MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "vid", track.ID.ToString()); };
|
||||
mi.Checked = MpvVid == track.ID.ToString();
|
||||
}
|
||||
|
||||
if (vidTracks.Length > 0)
|
||||
ContextMenu.Add("Track > -");
|
||||
|
||||
foreach (MediaTrack track in audTracks)
|
||||
{
|
||||
MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "aid", track.ID.ToString()); };
|
||||
mi.Checked = MpvAid == track.ID.ToString();
|
||||
}
|
||||
|
||||
if (subTracks.Length > 0)
|
||||
ContextMenu.Add("Track > -");
|
||||
|
||||
foreach (MediaTrack track in subTracks)
|
||||
{
|
||||
MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "sid", track.ID.ToString()); };
|
||||
mi.Checked = MpvSid == track.ID.ToString();
|
||||
}
|
||||
|
||||
if (subTracks.Length > 0)
|
||||
{
|
||||
MenuItemEx mi = ContextMenu.Add("Track > S: No subtitles");
|
||||
mi.Action = () => { mp.commandv("set", "sid", "no"); };
|
||||
mi.Checked = MpvSid == "no";
|
||||
}
|
||||
|
||||
if (ediTracks.Length > 0)
|
||||
ContextMenu.Add("Track > -");
|
||||
|
||||
foreach (MediaTrack track in ediTracks)
|
||||
{
|
||||
MenuItemEx mi = ContextMenu.Add("Track > " + track.Text);
|
||||
mi.Action = () => { mp.commandv("set", "edition", track.ID.ToString()); };
|
||||
mi.Checked = MpvEdition == track.ID;
|
||||
}
|
||||
}
|
||||
|
||||
lock (mp.Chapters)
|
||||
{
|
||||
if (ChaptersMenu != null)
|
||||
ChaptersMenu.DropDownItems.Clear();
|
||||
|
||||
foreach (var i in mp.Chapters)
|
||||
{
|
||||
MenuItemEx mi = ContextMenu.Add("Navigate > Chapters > " + i.Key);
|
||||
mi.ShortcutKeyDisplayString = TimeSpan.FromSeconds(i.Value).ToString().Substring(0, 8) + " ";
|
||||
mi.Action = () => { mp.commandv("seek", i.Value.ToString(CultureInfo.InvariantCulture), "absolute"); };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetScreen(int targetIndex)
|
||||
{
|
||||
Screen[] screens = Screen.AllScreens;
|
||||
if (targetIndex < 0) targetIndex = 0;
|
||||
if (targetIndex > screens.Length - 1) targetIndex = screens.Length - 1;
|
||||
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 * MpvAutofit);
|
||||
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;
|
||||
if (height > screen.Bounds.Height * 0.9) height = Convert.ToInt32(screen.Bounds.Height * MpvAutofit);
|
||||
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);
|
||||
ProcessMpvProperty(left, right);
|
||||
ProcessMpvNetProperty(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
string switchName = i.Substring(2);
|
||||
|
||||
switch (switchName)
|
||||
{
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
MpvFullscreen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessMpvProperty(string name, string value)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "autofit":
|
||||
if (value.Length == 3 && value.EndsWith("%"))
|
||||
if (int.TryParse(value.Substring(0, 2), out int result))
|
||||
MpvAutofit = result / 100f;
|
||||
break;
|
||||
case "fs":
|
||||
case "fullscreen":
|
||||
MpvFullscreen = value == "yes";
|
||||
break;
|
||||
case "screen":
|
||||
MpvScreen = Convert.ToInt32(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessMpvNetProperty(string name, string value)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "dark-mode":
|
||||
MpvNetDarkMode = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildMenu()
|
||||
{
|
||||
string content = File.ReadAllText(mp.InputConfPath);
|
||||
List<string> lines = null;
|
||||
Dictionary<string, string> commandInputDic = new Dictionary<string, string>();
|
||||
|
||||
if (content.Contains("#menu:"))
|
||||
lines = content.Split("\r\n".ToCharArray()).ToList();
|
||||
else
|
||||
{
|
||||
lines = Properties.Resources.input_conf.Split("\r\n".ToCharArray()).ToList();
|
||||
|
||||
foreach (string i in content.Split("\r\n".ToCharArray()))
|
||||
{
|
||||
string line = i.Trim();
|
||||
if (line.StartsWith("#") || !line.Contains(" ")) continue;
|
||||
string input = line.Substring(0, line.IndexOf(" ")).Trim();
|
||||
string command = line.Substring(line.IndexOf(" ") + 1).Trim();
|
||||
commandInputDic[command] = input;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string i in lines)
|
||||
{
|
||||
if (!i.Contains("#menu:")) continue;
|
||||
string left = i.Substring(0, i.IndexOf("#menu:")).Trim();
|
||||
if (left.StartsWith("#")) continue;
|
||||
string command = left.Substring(left.IndexOf(" ") + 1).Trim();
|
||||
string menu = i.Substring(i.IndexOf("#menu:") + "#menu:".Length).Trim();
|
||||
string input = left.Substring(0, left.IndexOf(" "));
|
||||
if (input == "_") input = "";
|
||||
if (menu.Contains(";")) input = menu.Substring(0, menu.IndexOf(";")).Trim();
|
||||
string path = menu.Substring(menu.IndexOf(";") + 1).Trim().Replace("&", "&&");
|
||||
if (path == "" || command == "") continue;
|
||||
|
||||
if (commandInputDic.Count > 0)
|
||||
if (commandInputDic.ContainsKey(command))
|
||||
input = commandInputDic[command];
|
||||
else
|
||||
input = "";
|
||||
|
||||
MenuItemEx menuItem = ContextMenu.Add(path, () => {
|
||||
try {
|
||||
mp.command_string(command);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
if (menuItem != null)
|
||||
{
|
||||
menuItem.ShortcutKeyDisplayString = input.Replace("_", "") + " ";
|
||||
|
||||
if (TracksMenu == null && menuItem.Text.StartsWith("Track ") &&
|
||||
menuItem.Text.Trim() == "Track")
|
||||
|
||||
TracksMenu = menuItem;
|
||||
|
||||
if (ChaptersMenu == null && menuItem.Text.StartsWith("Chapters ") &&
|
||||
menuItem.Text.Trim() == "Chapters")
|
||||
|
||||
ChaptersMenu = menuItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenu_Opened(object sender, EventArgs e) => CursorHelp.Show();
|
||||
|
||||
void mp_PlaybackRestart() => BeginInvoke(new Action(() => { Text = Path.GetFileName(mp.get_property_string("path")) + " - mpv.net " + Application.ProductVersion; }));
|
||||
|
||||
void Mp_Idle() => BeginInvoke(new Action(() => { Text = "mpv.net " + Application.ProductVersion; }));
|
||||
|
||||
void CM_Popup(object sender, EventArgs e) => CursorHelp.Show();
|
||||
|
||||
void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
Msg.ShowException(e.Exception);
|
||||
}
|
||||
|
||||
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Msg.ShowError(e.ExceptionObject.ToString());
|
||||
}
|
||||
|
||||
void mp_VideoSizeChanged()
|
||||
{
|
||||
BeginInvoke(new Action(() => SetFormPositionAndSizeKeepHeight()));
|
||||
}
|
||||
|
||||
void mp_Shutdown()
|
||||
{
|
||||
BeginInvoke(new Action(() => Close()));
|
||||
}
|
||||
|
||||
public bool IsFullscreen => WindowState == FormWindowState.Maximized;
|
||||
|
||||
void mpPropChangeFullscreen(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.Data.GetDataPresent(DataFormats.Text))
|
||||
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[]);
|
||||
if (e.Data.GetDataPresent(DataFormats.Text))
|
||||
mp.LoadURL(e.Data.GetData(DataFormats.Text).ToString());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (Width - e.Location.X < 10 && e.Location.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() => PointToClient(Control.MousePosition).Y > ClientSize.Height * 0.9;
|
||||
|
||||
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 && !ContextMenu.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, icon));
|
||||
return (DialogResult)Invoke(fn);
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
mp.Init();
|
||||
mp.observe_property_bool("fullscreen", mpPropChangeFullscreen);
|
||||
mp.observe_property_bool("ontop", mpPropChangeOnTop);
|
||||
mp.observe_property_string("sid", mpPropChangeSid);
|
||||
mp.observe_property_string("aid", mpPropChangeAid);
|
||||
mp.observe_property_string("vid", mpPropChangeVid);
|
||||
mp.observe_property_int("edition", mpPropChangeEdition);
|
||||
mp.Shutdown += mp_Shutdown;
|
||||
mp.VideoSizeChanged += mp_VideoSizeChanged;
|
||||
mp.PlaybackRestart += mp_PlaybackRestart;
|
||||
mp.Idle += Mp_Idle;
|
||||
}
|
||||
|
||||
void mpPropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value));
|
||||
|
||||
void mpPropChangeAid(string value) => MpvAid = value;
|
||||
|
||||
void mpPropChangeSid(string value) => MpvSid = value;
|
||||
|
||||
void mpPropChangeVid(string value) => MpvVid = value;
|
||||
|
||||
void mpPropChangeEdition(int value) => MpvEdition = value;
|
||||
|
||||
protected override void OnShown(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
if ((MpvNetDarkMode == "system" && Misc.IsDarkTheme) || MpvNetDarkMode == "always")
|
||||
ToolStripRendererEx.ColorTheme = Color.Black;
|
||||
ContextMenu = new ContextMenuStripEx(components);
|
||||
ContextMenu.Opened += ContextMenu_Opened;
|
||||
ContextMenu.Opening += ContextMenu_Opening;
|
||||
BuildMenu();
|
||||
ContextMenuStrip = ContextMenu;
|
||||
IgnoreDpiChanged = false;
|
||||
CheckYouTube();
|
||||
}
|
||||
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
base.OnFormClosed(e);
|
||||
mp.commandv("quit");
|
||||
mp.AutoResetEvent.WaitOne(3000);
|
||||
}
|
||||
|
||||
protected override void OnLostFocus(EventArgs e)
|
||||
{
|
||||
base.OnLostFocus(e);
|
||||
CursorHelp.Show();
|
||||
}
|
||||
|
||||
protected override void OnActivated(EventArgs e)
|
||||
{
|
||||
base.OnActivated(e);
|
||||
CheckYouTube();
|
||||
}
|
||||
|
||||
void CheckYouTube()
|
||||
{
|
||||
string clipboard = Clipboard.GetText();
|
||||
|
||||
if (clipboard.StartsWith("https://www.youtube.com/watch?") && RegistryHelp.GetValue("HKCU\\Software\\" + Application.ProductName, "LastYouTubeURL") != clipboard && Visible)
|
||||
{
|
||||
RegistryHelp.SetValue("HKCU\\Software\\" + Application.ProductName, "LastYouTubeURL", clipboard);
|
||||
|
||||
if (Msg.ShowQuestion("Play YouTube URL?") == MsgResult.OK)
|
||||
mp.LoadURL(clipboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class MediaInfo : IDisposable
|
||||
{
|
||||
IntPtr Handle;
|
||||
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));
|
||||
}
|
||||
|
||||
public int GetCount(MediaInfoStreamKind streamKind) => MediaInfo_Count_Get(Handle, streamKind, -1);
|
||||
|
||||
public string GetVideo(int streamNumber, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
||||
}
|
||||
|
||||
public string GetAudio(int streamNumber, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
||||
}
|
||||
|
||||
public string GetText(int streamNumber, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
||||
}
|
||||
|
||||
bool Disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Disposed)
|
||||
{
|
||||
Disposed = true;
|
||||
MediaInfo_Close(Handle);
|
||||
MediaInfo_Delete(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
~MediaInfo() { Dispose(); }
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr LoadLibrary(string path);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern IntPtr MediaInfo_New();
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern void MediaInfo_Delete(IntPtr handle);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int MediaInfo_Open(IntPtr handle, string fileName);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern int MediaInfo_Close(IntPtr handle);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr MediaInfo_Get(IntPtr handle,
|
||||
MediaInfoStreamKind streamKind,
|
||||
int streamNumber,
|
||||
string parameter,
|
||||
MediaInfoInfoKind kindOfInfo,
|
||||
MediaInfoInfoKind kindOfSearch);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int MediaInfo_Count_Get(IntPtr handle,
|
||||
MediaInfoStreamKind streamKind,
|
||||
int streamNumber);
|
||||
}
|
||||
|
||||
public enum MediaInfoStreamKind
|
||||
{
|
||||
General,
|
||||
Video,
|
||||
Audio,
|
||||
Text,
|
||||
Other,
|
||||
Image,
|
||||
Menu,
|
||||
Max,
|
||||
}
|
||||
|
||||
public enum MediaInfoInfoKind
|
||||
{
|
||||
Name,
|
||||
Text,
|
||||
Measure,
|
||||
Options,
|
||||
NameText,
|
||||
MeasureText,
|
||||
Info,
|
||||
HowTo
|
||||
}
|
||||
141
mpv.net/Misc.cs
@@ -1,141 +0,0 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Misc
|
||||
{
|
||||
public static readonly string[] FileTypes = "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(' ');
|
||||
|
||||
public static string GetFilter(IEnumerable<string> values) => "*." +
|
||||
String.Join(";*.", values) + "|*." + String.Join(";*.", values) + "|All Files|*.*";
|
||||
|
||||
public static bool IsDarkTheme {
|
||||
get {
|
||||
object value = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
|
||||
if (value is null) value = 1;
|
||||
return (int)value == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StringLogicalComparer : IComparer, IComparer<string>
|
||||
{
|
||||
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int StrCmpLogical(string x, string y);
|
||||
|
||||
int IComparer_Compare(object x, object y) => StrCmpLogical(x.ToString(), y.ToString());
|
||||
int IComparer.Compare(object x, object y) => IComparer_Compare(x, y);
|
||||
int IComparerOfString_Compare(string x, string y) => StrCmpLogical(x, y);
|
||||
int IComparer<string>.Compare(string x, string y) => IComparerOfString_Compare(x, y);
|
||||
}
|
||||
|
||||
public class FileAssociation
|
||||
{
|
||||
static string ExePath = Application.ExecutablePath;
|
||||
static string ExeFilename = Path.GetFileName(Application.ExecutablePath);
|
||||
static string ExeFilenameNoExt = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
|
||||
static string[] Types;
|
||||
public static string[] VideoTypes = "mpg avi vob mp4 mkv avs 264 mov wmv flv h264 asf webm mpeg mpv y4m avc hevc 265 h265 m2v m2ts vpy mts webm m4v".Split(" ".ToCharArray());
|
||||
public static string[] AudioTypes = "mp2 mp3 ac3 wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 ogg mka aac opus flac mpa".Split(" ".ToCharArray());
|
||||
|
||||
public static void Register(string[] types)
|
||||
{
|
||||
Types = types;
|
||||
|
||||
RegistryHelp.SetValue(@"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename, null, ExePath);
|
||||
RegistryHelp.SetValue($"HKCR\\Applications\\{ExeFilename}", "FriendlyAppName", "mpv.net media player");
|
||||
RegistryHelp.SetValue($"HKCR\\Applications\\{ExeFilename}\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\"");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv\Capabilities", "ApplicationDescription", "mpv.net media player");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv\Capabilities", "ApplicationName", "mpv.net");
|
||||
RegistryHelp.SetValue($"HKCR\\SystemFileAssociations\\video\\OpenWithList\\{ExeFilename}", null, "");
|
||||
RegistryHelp.SetValue($"HKCR\\SystemFileAssociations\\audio\\OpenWithList\\{ExeFilename}", null, "");
|
||||
|
||||
foreach (string ext in Types)
|
||||
{
|
||||
RegistryHelp.SetValue($"HKCR\\Applications\\{ExeFilename}\\SupportedTypes", "." + ext, "");
|
||||
RegistryHelp.SetValue($"HKCR\\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
|
||||
RegistryHelp.SetValue($"HKCR\\" + "." + ext + "\\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
|
||||
if (VideoTypes.Contains(ext))
|
||||
RegistryHelp.SetValue($"HKCR\\" + "." + ext, "PerceivedType", "video");
|
||||
if (AudioTypes.Contains(ext))
|
||||
RegistryHelp.SetValue($"HKCR\\" + "." + ext, "PerceivedType", "audio");
|
||||
RegistryHelp.SetValue($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open", null, "Play with " + Application.ProductName);
|
||||
RegistryHelp.SetValue($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\"");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Unregister()
|
||||
{
|
||||
RegistryHelp.RemoveKey(@"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename);
|
||||
RegistryHelp.RemoveKey($"HKCR\\Applications\\{ExeFilename}");
|
||||
RegistryHelp.RemoveKey(@"HKLM\SOFTWARE\Clients\Media\mpv.net");
|
||||
RegistryHelp.RemoveKey($"HKCR\\SystemFileAssociations\\video\\OpenWithList\\{ExeFilename}");
|
||||
RegistryHelp.RemoveKey($"HKCR\\SystemFileAssociations\\audio\\OpenWithList\\{ExeFilename}");
|
||||
|
||||
foreach (string id in Registry.ClassesRoot.GetSubKeyNames())
|
||||
{
|
||||
if (id.StartsWith(ExeFilenameNoExt + "."))
|
||||
Registry.ClassesRoot.DeleteSubKeyTree(id);
|
||||
|
||||
RegistryHelp.RemoveValue($"HKCR\\Software\\Classes\\" + id + "\\OpenWithProgIDs", ExeFilenameNoExt + id);
|
||||
RegistryHelp.RemoveValue($"HKLM\\Software\\Classes\\" + id + "\\OpenWithProgIDs", ExeFilenameNoExt + id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RegistryHelp
|
||||
{
|
||||
public static void SetValue(string path, string name, string value)
|
||||
{
|
||||
using (RegistryKey rk = GetRootKey(path).CreateSubKey(path.Substring(5), RegistryKeyPermissionCheck.ReadWriteSubTree))
|
||||
rk.SetValue(name, value);
|
||||
}
|
||||
|
||||
public static string GetValue(string path, string name)
|
||||
{
|
||||
using (RegistryKey rk = GetRootKey(path).OpenSubKey(path.Substring(5)))
|
||||
if (rk != null)
|
||||
return rk.GetValue(name, "").ToString();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void RemoveKey(string path)
|
||||
{
|
||||
GetRootKey(path).DeleteSubKeyTree(path.Substring(5), false);
|
||||
}
|
||||
|
||||
public static void RemoveValue(string path, string name)
|
||||
{
|
||||
using (RegistryKey rk = GetRootKey(path).OpenSubKey(path.Substring(5), true))
|
||||
if (!(rk is null))
|
||||
rk.DeleteValue(name, false);
|
||||
}
|
||||
|
||||
static RegistryKey GetRootKey(string path)
|
||||
{
|
||||
switch (path.Substring(0, 4))
|
||||
{
|
||||
case "HKLM": return Registry.LocalMachine;
|
||||
case "HKCU": return Registry.CurrentUser;
|
||||
case "HKCR": return Registry.ClassesRoot;
|
||||
default: throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MediaTrack
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public string Type { get; set; }
|
||||
public int ID { get; set; }
|
||||
}
|
||||
}
|
||||
194
mpv.net/Misc/App.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public static class App
|
||||
{
|
||||
public static string[] VideoTypes { get; } = "264 265 asf avc avi avs flv h264 h265 hevc m2ts m2v m4v mkv mov mp4 mpeg mpg mpv mts ts vob vpy webm wmv y4m".Split(' ');
|
||||
public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(' ');
|
||||
public static string[] ImageTypes { get; } = {"jpg", "bmp", "gif", "png"};
|
||||
public static string[] SubtitleTypes { get; } = { "srt", "ass", "idx", "sup", "ttxt", "ssa", "smi" };
|
||||
|
||||
public static string RegPath { get; } = @"HKCU\Software\" + Application.ProductName;
|
||||
public static string ConfPath { get => core.ConfigFolder + "mpvnet.conf"; }
|
||||
public static string ProcessInstance { get; set; } = "single";
|
||||
public static string DarkMode { get; set; } = "always";
|
||||
public static string DarkTheme { get; set; } = "dark";
|
||||
public static string LightTheme { get; set; } = "light";
|
||||
public static string StartSize { get; set; } = "previous";
|
||||
|
||||
public static bool RememberPosition { get; set; }
|
||||
public static bool DebugMode { get; set; }
|
||||
public static bool IsStartedFromTerminal { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
|
||||
public static bool RememberVolume { get; set; } = true;
|
||||
public static bool AutoLoadFolder { get; set; } = true;
|
||||
public static bool Queue { get; set; }
|
||||
public static bool UpdateCheck { get; set; }
|
||||
|
||||
public static int StartThreshold { get; set; } = 1500;
|
||||
public static int RecentCount { get; set; } = 15;
|
||||
|
||||
public static float MinimumAspectRatio { get; set; } = 1.2f;
|
||||
|
||||
public static Extension Extension { get; set; }
|
||||
|
||||
public static bool IsDarkMode {
|
||||
get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
string dummy = core.ConfigFolder;
|
||||
var dummy2 = core.Conf;
|
||||
|
||||
foreach (var i in Conf)
|
||||
ProcessProperty(i.Key, i.Value, true);
|
||||
|
||||
if (App.DebugMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
string filePath = core.ConfigFolder + "mpvnet-debug.log";
|
||||
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(filePath));
|
||||
Trace.AutoFlush = true;
|
||||
|
||||
//if (App.DebugMode)
|
||||
// Trace.WriteLine("");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Msg.ShowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
string themeContent = null;
|
||||
|
||||
if (File.Exists(core.ConfigFolder + "theme.conf"))
|
||||
themeContent = File.ReadAllText(core.ConfigFolder + "theme.conf");
|
||||
|
||||
Theme.Init(
|
||||
themeContent,
|
||||
Properties.Resources.theme,
|
||||
IsDarkMode ? DarkTheme : LightTheme);
|
||||
|
||||
core.Shutdown += Shutdown;
|
||||
core.Initialized += Initialized;
|
||||
}
|
||||
|
||||
public static void RunAction(Action action)
|
||||
{
|
||||
Task.Run(() => {
|
||||
try
|
||||
{
|
||||
action.Invoke();
|
||||
Debug.WriteLine(Environment.TickCount);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ShowException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void ShowException(object obj)
|
||||
{
|
||||
if (obj is Exception e)
|
||||
{
|
||||
if (App.IsStartedFromTerminal)
|
||||
ConsoleHelp.WriteError(e.ToString());
|
||||
else
|
||||
Msg.ShowException(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (App.IsStartedFromTerminal)
|
||||
ConsoleHelp.WriteError(obj.ToString());
|
||||
else
|
||||
Msg.ShowError(obj.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowError(string title, string msg)
|
||||
{
|
||||
if (App.IsStartedFromTerminal)
|
||||
{
|
||||
ConsoleHelp.WriteError(title);
|
||||
ConsoleHelp.WriteError(msg);
|
||||
}
|
||||
else
|
||||
Msg.ShowError(title, msg);
|
||||
}
|
||||
|
||||
static void Initialized()
|
||||
{
|
||||
if (RememberVolume)
|
||||
{
|
||||
core.set_property_int("volume", RegistryHelp.GetInt(App.RegPath, "Volume", 70));
|
||||
core.set_property_string("mute", RegistryHelp.GetString(App.RegPath, "Mute", "no"));
|
||||
}
|
||||
}
|
||||
|
||||
static void Shutdown()
|
||||
{
|
||||
if (RememberVolume)
|
||||
{
|
||||
RegistryHelp.SetValue(App.RegPath, "Volume", core.get_property_int("volume"));
|
||||
RegistryHelp.SetValue(App.RegPath, "Mute", core.get_property_string("mute"));
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, string> _Conf;
|
||||
|
||||
public static Dictionary<string, string> Conf {
|
||||
get {
|
||||
if (_Conf == null)
|
||||
{
|
||||
_Conf = new Dictionary<string, string>();
|
||||
|
||||
if (File.Exists(ConfPath))
|
||||
foreach (string i in File.ReadAllLines(ConfPath))
|
||||
if (i.Contains("=") && !i.StartsWith("#"))
|
||||
_Conf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||
}
|
||||
return _Conf;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ProcessProperty(string name, string value, bool writeError = false)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "remember-position": RememberPosition = value == "yes"; return true;
|
||||
case "debug-mode": DebugMode = value == "yes"; return true;
|
||||
case "remember-volume": RememberVolume = value == "yes"; return true;
|
||||
case "queue": Queue = value == "yes"; return true;
|
||||
case "auto-load-folder": AutoLoadFolder = value == "yes"; return true;
|
||||
case "update-check": UpdateCheck = value == "yes"; return true;
|
||||
case "start-size": StartSize = value; return true;
|
||||
case "process-instance": ProcessInstance = value; return true;
|
||||
case "dark-mode": DarkMode = value; return true;
|
||||
case "start-threshold": StartThreshold = value.Int(); return true;
|
||||
case "recent-count": RecentCount = value.Int(); return true;
|
||||
case "minimum-aspect-ratio": MinimumAspectRatio = value.Float(); return true;
|
||||
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
|
||||
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
|
||||
default:
|
||||
if (writeError)
|
||||
ConsoleHelp.WriteError($"unknown mpvnet.conf property: {name}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
366
mpv.net/Misc/Commands.cs
Normal file
@@ -0,0 +1,366 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
|
||||
using VB = Microsoft.VisualBasic;
|
||||
|
||||
using static NewLine;
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Commands
|
||||
{
|
||||
public static void Execute(string id, string[] args)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case "open-files": OpenFiles(args); break;
|
||||
case "update-check": UpdateCheck.CheckOnline(true); break;
|
||||
case "open-url": OpenURL(); break;
|
||||
case "open-optical-media": Open_DVD_Or_BD_Folder(); break;
|
||||
case "manage-file-associations": // deprecated 2019
|
||||
case "show-setup-dialog": ShowDialog(typeof(SetupWindow)); break;
|
||||
case "cycle-audio": CycleAudio(); break;
|
||||
case "load-audio": LoadAudio(); break;
|
||||
case "load-sub": LoadSubtitle(); break;
|
||||
case "execute-mpv-command": ExecuteMpvCommand(); break;
|
||||
case "show-history": ShowHistory(); break;
|
||||
case "show-media-search": ShowDialog(typeof(EverythingWindow)); break;
|
||||
case "show-command-palette": ShowDialog(typeof(CommandPaletteWindow)); break;
|
||||
case "show-about": ShowDialog(typeof(AboutWindow)); break;
|
||||
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
|
||||
case "show-input-editor": ShowDialog(typeof(InputWindow)); break;
|
||||
case "open-conf-folder": Process.Start(core.ConfigFolder); break;
|
||||
case "shell-execute": Process.Start(args[0]); break;
|
||||
case "show-info": ShowInfo(); break;
|
||||
case "playlist-first": PlaylistFirst(); break;
|
||||
case "playlist-last": PlaylistLast(); break;
|
||||
case "show-profiles": ShowProfiles(); break;
|
||||
case "show-properties": ShowProperties(); break;
|
||||
case "show-commands": ShowCommands(); break;
|
||||
case "add-files-to-playlist": OpenFiles("append"); break; // deprecated 2019
|
||||
default: Msg.ShowError($"No command '{id}' found."); break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void InvokeOnMainThread(Action action) => MainForm.Instance.BeginInvoke(action);
|
||||
|
||||
public static void ShowDialog(Type winType)
|
||||
{
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
Window win = Activator.CreateInstance(winType) as Window;
|
||||
new WindowInteropHelper(win).Owner = MainForm.Instance.Handle;
|
||||
win.ShowDialog();
|
||||
}));
|
||||
}
|
||||
|
||||
public static void OpenFiles(params string[] args)
|
||||
{
|
||||
bool append = Control.ModifierKeys.HasFlag(Keys.Control);
|
||||
bool loadFolder = true;
|
||||
|
||||
foreach (string arg in args)
|
||||
{
|
||||
if (arg == "append") append = true;
|
||||
if (arg == "no-folder") loadFolder = false;
|
||||
}
|
||||
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
using (var d = new OpenFileDialog() { Multiselect = true })
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
core.LoadFiles(d.FileNames, loadFolder, append);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void Open_DVD_Or_BD_Folder()
|
||||
{
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
using (var d = new FolderBrowserDialog())
|
||||
{
|
||||
d.Description = "Select a DVD or Blu-ray folder.";
|
||||
d.ShowNewFolderButton = false;
|
||||
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
if (Directory.Exists(d.SelectedPath + "\\BDMV"))
|
||||
{
|
||||
core.set_property_string("bluray-device", d.SelectedPath);
|
||||
core.LoadFiles(new[] { @"bd://" }, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
core.set_property_string("dvd-device", d.SelectedPath);
|
||||
core.LoadFiles(new[] { @"dvd://" }, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void PlaylistFirst()
|
||||
{
|
||||
int pos = core.get_property_int("playlist-pos");
|
||||
|
||||
if (pos != 0)
|
||||
core.set_property_int("playlist-pos", 0);
|
||||
}
|
||||
|
||||
public static void PlaylistLast()
|
||||
{
|
||||
int pos = core.get_property_int("playlist-pos");
|
||||
int count = core.get_property_int("playlist-count");
|
||||
|
||||
if (pos < count - 1)
|
||||
core.set_property_int("playlist-pos", count - 1);
|
||||
}
|
||||
|
||||
public static void ShowHistory()
|
||||
{
|
||||
if (File.Exists(core.ConfigFolder + "history.txt"))
|
||||
Process.Start(core.ConfigFolder + "history.txt");
|
||||
else
|
||||
{
|
||||
if (Msg.ShowQuestion("Create history.txt file in config folder?",
|
||||
"mpv.net will write the date, time and filename of opened files to it.") == MsgResult.OK)
|
||||
|
||||
File.WriteAllText(core.ConfigFolder + "history.txt", "");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
string performer, title, album, genre, date, duration, text = "";
|
||||
long fileSize = 0;
|
||||
string path = core.get_property_string("path");
|
||||
|
||||
if (path.Contains("://"))
|
||||
path = core.get_property_string("media-title");
|
||||
|
||||
int width = core.get_property_int("video-params/w");
|
||||
int height = core.get_property_int("video-params/h");
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
fileSize = new FileInfo(path).Length;
|
||||
|
||||
if (App.AudioTypes.Contains(path.ShortExt()))
|
||||
{
|
||||
using (MediaInfo mediaInfo = new MediaInfo(path))
|
||||
{
|
||||
performer = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Performer");
|
||||
title = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Title");
|
||||
album = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Album");
|
||||
genre = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Genre");
|
||||
date = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Recorded_Date");
|
||||
duration = mediaInfo.GetInfo(MediaInfoStreamKind.Audio, "Duration/String");
|
||||
|
||||
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";
|
||||
text += "Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n";
|
||||
text += "Type: " + path.ShortExt().ToUpper();
|
||||
|
||||
core.commandv("show-text", text, "5000");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (App.ImageTypes.Contains(path.ShortExt()))
|
||||
{
|
||||
using (MediaInfo mediaInfo = new MediaInfo(path))
|
||||
{
|
||||
text =
|
||||
"Width: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Width") + "\n" +
|
||||
"Height: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Height") + "\n" +
|
||||
"Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n" +
|
||||
"Type: " + path.ShortExt().ToUpper();
|
||||
|
||||
core.commandv("show-text", text, "5000");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeSpan position = TimeSpan.FromSeconds(core.get_property_number("time-pos"));
|
||||
TimeSpan duration2 = TimeSpan.FromSeconds(core.get_property_number("duration"));
|
||||
string videoFormat = core.get_property_string("video-format").ToUpper();
|
||||
string audioCodec = core.get_property_string("audio-codec-name").ToUpper();
|
||||
|
||||
text = path.FileName() + "\n" +
|
||||
FormatTime(position.TotalMinutes) + ":" +
|
||||
FormatTime(position.Seconds) + " / " +
|
||||
FormatTime(duration2.TotalMinutes) + ":" +
|
||||
FormatTime(duration2.Seconds) + "\n" +
|
||||
$"{width} x {height}\n";
|
||||
|
||||
if (fileSize > 0)
|
||||
text += Convert.ToInt32(fileSize / 1024.0 / 1024.0) + " MB\n";
|
||||
|
||||
text += $"{videoFormat}\n{audioCodec}";
|
||||
|
||||
core.commandv("show-text", text, "5000");
|
||||
string FormatTime(double value) => ((int)value).ToString("00");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
App.ShowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteMpvCommand() // deprecated 2019
|
||||
{
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
string command = VB.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegistryHelp.GetString(App.RegPath, "RecentExecutedCommand"));
|
||||
|
||||
if (string.IsNullOrEmpty(command))
|
||||
return;
|
||||
|
||||
RegistryHelp.SetValue(App.RegPath, "RecentExecutedCommand", command);
|
||||
core.command(command, false);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void OpenURL()
|
||||
{
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
string clipboard = System.Windows.Forms.Clipboard.GetText();
|
||||
|
||||
if (string.IsNullOrEmpty(clipboard) || (!clipboard.Contains("://") && !File.Exists(clipboard)) || clipboard.Contains("\n"))
|
||||
{
|
||||
App.ShowError("No URL found", "The clipboard does not contain a valid URL or file.");
|
||||
return;
|
||||
}
|
||||
|
||||
core.LoadFiles(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control));
|
||||
}));
|
||||
}
|
||||
|
||||
public static void LoadSubtitle()
|
||||
{
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
using (var d = new OpenFileDialog())
|
||||
{
|
||||
string path = core.get_property_string("path");
|
||||
|
||||
if (File.Exists(path))
|
||||
d.InitialDirectory = Path.GetDirectoryName(path);
|
||||
|
||||
d.Multiselect = true;
|
||||
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
foreach (string filename in d.FileNames)
|
||||
core.commandv("sub-add", filename);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void LoadAudio()
|
||||
{
|
||||
InvokeOnMainThread(new Action(() => {
|
||||
using (var d = new OpenFileDialog())
|
||||
{
|
||||
string path = core.get_property_string("path");
|
||||
if (File.Exists(path))
|
||||
d.InitialDirectory = Path.GetDirectoryName(path);
|
||||
d.Multiselect = true;
|
||||
|
||||
if (d.ShowDialog() == DialogResult.OK)
|
||||
foreach (string i in d.FileNames)
|
||||
core.commandv("audio-add", i);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void CycleAudio()
|
||||
{
|
||||
string path = core.get_property_string("path");
|
||||
|
||||
if (!File.Exists(path))
|
||||
return;
|
||||
|
||||
using (MediaInfo mi = new MediaInfo(path))
|
||||
{
|
||||
MediaTrack[] audTracks = core.MediaTracks.Where(track => track.Type == "a").ToArray();
|
||||
|
||||
if (audTracks.Length < 2)
|
||||
return;
|
||||
|
||||
int aid = core.get_property_int("aid");
|
||||
aid += 1;
|
||||
|
||||
if (aid > audTracks.Length)
|
||||
aid = 1;
|
||||
|
||||
core.commandv("set", "aid", aid.ToString());
|
||||
core.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
|
||||
}
|
||||
}
|
||||
|
||||
static void ShowProfiles()
|
||||
{
|
||||
string code = @"
|
||||
foreach ($item in ($json | ConvertFrom-Json | foreach { $_ } | sort name))
|
||||
{
|
||||
$item.name
|
||||
''
|
||||
|
||||
foreach ($option in $item.options)
|
||||
{
|
||||
' ' + $option.key + ' = ' + $option.value
|
||||
}
|
||||
|
||||
''
|
||||
}";
|
||||
|
||||
string json = core.get_property_string("profile-list");
|
||||
string file = Path.GetTempPath() + @"\mpv profile-list.txt";
|
||||
File.WriteAllText(file, BR + PowerShell.InvokeAndReturnString(code, "json", json));
|
||||
Process.Start(file);
|
||||
}
|
||||
|
||||
static void ShowCommands()
|
||||
{
|
||||
string code = @"
|
||||
foreach ($item in ($json | ConvertFrom-Json | foreach { $_ } | sort name))
|
||||
{
|
||||
''
|
||||
$item.name
|
||||
|
||||
foreach ($arg in $item.args)
|
||||
{
|
||||
$value = $arg.name + ' <' + $arg.type.ToLower() + '>'
|
||||
|
||||
if ($arg.optional -eq $true)
|
||||
{
|
||||
$value = '[' + $value + ']'
|
||||
}
|
||||
|
||||
' ' + $value
|
||||
}
|
||||
}";
|
||||
|
||||
string json = core.get_property_string("command-list");
|
||||
string file = Path.GetTempPath() + @"\mpv command-list.txt";
|
||||
File.WriteAllText(file, PowerShell.InvokeAndReturnString(code, "json", json) + BR);
|
||||
Process.Start(file);
|
||||
}
|
||||
|
||||
static void ShowProperties()
|
||||
{
|
||||
string file = Path.GetTempPath() + @"\mpv property-list.txt";
|
||||
var props = core.get_property_string("property-list").Split(',').OrderBy(prop => prop);
|
||||
File.WriteAllText(file, BR + string.Join(BR, props) + BR);
|
||||
Process.Start(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
mpv.net/Misc/Extension.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Extension
|
||||
{
|
||||
[ImportMany]
|
||||
public IEnumerable<IExtension> Extensions = null;
|
||||
|
||||
readonly CompositionContainer CompositionContainer;
|
||||
|
||||
public Extension()
|
||||
{
|
||||
try
|
||||
{
|
||||
AggregateCatalog catalog = new AggregateCatalog();
|
||||
string dir = Folder.Startup + "Extensions";
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
string[] knownExtensions = { "RatingExtension", "ScriptingExtension" };
|
||||
|
||||
foreach (string extDir in Directory.GetDirectories(dir))
|
||||
{
|
||||
if (knownExtensions.Contains(Path.GetFileName(extDir)))
|
||||
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
|
||||
else
|
||||
ConsoleHelp.WriteError("Failed to load extension:\n\n" + extDir +
|
||||
"\n\nOnly extensions that ship with mpv.net are allowed in <startup>\\extensions" +
|
||||
"\n\nUser extensions have to use <config folder>\\extensions" +
|
||||
"\n\nNever copy or install a new mpv.net version over a old mpv.net version.");
|
||||
}
|
||||
}
|
||||
|
||||
dir = core.ConfigFolder + "extensions";
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
foreach (string extDir in Directory.GetDirectories(dir))
|
||||
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
|
||||
|
||||
if (catalog.Catalogs.Count > 0)
|
||||
{
|
||||
CompositionContainer = new CompositionContainer(catalog);
|
||||
CompositionContainer.ComposeParts(this);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.ShowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IExtension
|
||||
{
|
||||
}
|
||||
}
|
||||
32
mpv.net/Misc/ExtensionMethods.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static string FileName(this string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) return "";
|
||||
int index = path.LastIndexOf('\\');
|
||||
if (index > -1) return path.Substring(index + 1);
|
||||
index = path.LastIndexOf('/');
|
||||
if (index > -1) return path.Substring(index + 1);
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string ShortExt(this string path)
|
||||
{
|
||||
return Path.GetExtension(path).ToLower().TrimStart('.');
|
||||
}
|
||||
|
||||
public static int Int(this string value)
|
||||
{
|
||||
int.TryParse(value, out int result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float Float(this string value)
|
||||
{
|
||||
float.TryParse(value.Replace(",", "."), NumberStyles.Float, CultureInfo.InvariantCulture, out float result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
111
mpv.net/Misc/Help.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public static class ConsoleHelp
|
||||
{
|
||||
public static int Padding { get; set; }
|
||||
|
||||
public static void WriteError(object obj, string module = "mpv.net")
|
||||
{
|
||||
Write(obj, module, ConsoleColor.Red, false);
|
||||
}
|
||||
|
||||
public static void Write(object obj, string module = "mpv.net")
|
||||
{
|
||||
Write(obj, module, ConsoleColor.Black, true);
|
||||
}
|
||||
|
||||
public static void Write(object obj, string module, ConsoleColor color)
|
||||
{
|
||||
Write(obj, module, color, false);
|
||||
}
|
||||
|
||||
public static void Write(object obj, string module, ConsoleColor color, bool useDefaultColor)
|
||||
{
|
||||
if (obj == null)
|
||||
return;
|
||||
|
||||
string value = obj.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(module))
|
||||
module = "[" + module + "] ";
|
||||
|
||||
if (useDefaultColor)
|
||||
Console.ResetColor();
|
||||
else
|
||||
Console.ForegroundColor = color;
|
||||
|
||||
value = module + value;
|
||||
|
||||
if (Padding > 0 && value.Length < Padding)
|
||||
value = value.PadRight(Padding);
|
||||
|
||||
Console.WriteLine(value);
|
||||
Console.ResetColor();
|
||||
Trace.WriteLine(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public class CursorHelp
|
||||
{
|
||||
static bool IsVisible = true;
|
||||
|
||||
public static void Show()
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
Cursor.Show();
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Hide()
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
Cursor.Hide();
|
||||
IsVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPosDifferent(Point screenPos)
|
||||
{
|
||||
return
|
||||
Math.Abs(screenPos.X - Control.MousePosition.X) > 10 ||
|
||||
Math.Abs(screenPos.Y - Control.MousePosition.Y) > 10;
|
||||
}
|
||||
}
|
||||
|
||||
public class mpvHelp
|
||||
{
|
||||
public static string WM_APPCOMMAND_to_mpv_key(int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 5: return "SEARCH"; // BROWSER_SEARCH
|
||||
case 6: return "FAVORITES"; // BROWSER_FAVORITES
|
||||
case 7: return "HOMEPAGE"; // BROWSER_HOME
|
||||
case 15: return "MAIL"; // LAUNCH_MAIL
|
||||
case 33: return "PRINT"; // PRINT
|
||||
case 11: return "NEXT"; // MEDIA_NEXTTRACK
|
||||
case 12: return "PREV"; // MEDIA_PREVIOUSTRACK
|
||||
case 13: return "STOP"; // MEDIA_STOP
|
||||
case 14: return "PLAYPAUSE"; // MEDIA_PLAY_PAUSE
|
||||
case 46: return "PLAY"; // MEDIA_PLAY
|
||||
case 47: return "PAUSE"; // MEDIA_PAUSE
|
||||
case 48: return "RECORD"; // MEDIA_RECORD
|
||||
case 49: return "FORWARD"; // MEDIA_FAST_FORWARD
|
||||
case 50: return "REWIND"; // MEDIA_REWIND
|
||||
case 51: return "CHANNEL_UP"; // MEDIA_CHANNEL_UP
|
||||
case 52: return "CHANNEL_DOWN"; // MEDIA_CHANNEL_DOWN
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
200
mpv.net/Misc/Misc.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Sys
|
||||
{
|
||||
public static bool IsDarkTheme {
|
||||
get {
|
||||
object value = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
|
||||
|
||||
if (value is null)
|
||||
value = 1;
|
||||
|
||||
return (int)value == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StringLogicalComparer : IComparer, IComparer<string>
|
||||
{
|
||||
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int StrCmpLogical(string x, string y);
|
||||
|
||||
int IComparer_Compare(object x, object y) => StrCmpLogical(x.ToString(), y.ToString());
|
||||
int IComparer.Compare(object x, object y) => IComparer_Compare(x, y);
|
||||
int IComparerOfString_Compare(string x, string y) => StrCmpLogical(x, y);
|
||||
int IComparer<string>.Compare(string x, string y) => IComparerOfString_Compare(x, y);
|
||||
}
|
||||
|
||||
public class FileAssociation
|
||||
{
|
||||
static string ExePath = Application.ExecutablePath;
|
||||
static string ExeFilename = Path.GetFileName(Application.ExecutablePath);
|
||||
static string ExeFilenameNoExt = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
|
||||
static string[] Types;
|
||||
|
||||
public static void Register(string[] types)
|
||||
{
|
||||
Types = types;
|
||||
|
||||
RegistryHelp.SetValue(@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename, null, ExePath);
|
||||
RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename, "FriendlyAppName", "mpv.net media player");
|
||||
RegistryHelp.SetValue($@"HKCR\Applications\{ExeFilename}\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationDescription", "mpv.net media player");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationName", "mpv.net");
|
||||
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename, null, "");
|
||||
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename, null, "");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net", @"SOFTWARE\Clients\Media\mpv.net\Capabilities");
|
||||
|
||||
foreach (string ext in Types)
|
||||
{
|
||||
RegistryHelp.SetValue($@"HKCR\Applications\{ExeFilename}\SupportedTypes", "." + ext, "");
|
||||
RegistryHelp.SetValue($@"HKCR\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
|
||||
RegistryHelp.SetValue($@"HKCR\" + "." + ext + @"\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
|
||||
|
||||
if (App.VideoTypes.Contains(ext))
|
||||
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "video");
|
||||
|
||||
if (App.AudioTypes.Contains(ext))
|
||||
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "audio");
|
||||
|
||||
if (App.ImageTypes.Contains(ext))
|
||||
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "image");
|
||||
|
||||
RegistryHelp.SetValue($@"HKCR\" + ExeFilenameNoExt + "." + ext + @"\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
|
||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Unregister()
|
||||
{
|
||||
RegistryHelp.RemoveKey($@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename);
|
||||
RegistryHelp.RemoveKey($@"HKCR\Applications\" + ExeFilename);
|
||||
RegistryHelp.RemoveKey($@"HKLM\SOFTWARE\Clients\Media\mpv.net");
|
||||
RegistryHelp.RemoveKey($@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename);
|
||||
RegistryHelp.RemoveKey($@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename);
|
||||
RegistryHelp.RemoveValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net");
|
||||
|
||||
foreach (string id in Registry.ClassesRoot.GetSubKeyNames())
|
||||
{
|
||||
if (id.StartsWith(ExeFilenameNoExt + "."))
|
||||
Registry.ClassesRoot.DeleteSubKeyTree(id);
|
||||
|
||||
RegistryHelp.RemoveValue($@"HKCR\Software\Classes\{id}\OpenWithProgIDs", ExeFilenameNoExt + id);
|
||||
RegistryHelp.RemoveValue($@"HKLM\Software\Classes\{id}\OpenWithProgIDs", ExeFilenameNoExt + id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MediaTrack
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public string Type { get; set; }
|
||||
public int ID { get; set; }
|
||||
}
|
||||
|
||||
public class CommandItem : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public string Path { get; set; } = "";
|
||||
public string Command { get; set; } = "";
|
||||
|
||||
public CommandItem() { }
|
||||
|
||||
public CommandItem(SerializationInfo info, StreamingContext context) { }
|
||||
|
||||
void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
string _Input = "";
|
||||
|
||||
public string Input {
|
||||
get => _Input;
|
||||
set {
|
||||
_Input = value;
|
||||
NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public static ObservableCollection<CommandItem> GetItems(string content)
|
||||
{
|
||||
var items = new ObservableCollection<CommandItem>();
|
||||
|
||||
if (!string.IsNullOrEmpty(content))
|
||||
{
|
||||
foreach (string line in content.Split('\r', '\n'))
|
||||
{
|
||||
string val = line.Trim();
|
||||
|
||||
if (val.StartsWith("#"))
|
||||
continue;
|
||||
|
||||
if (!val.Contains(" "))
|
||||
continue;
|
||||
|
||||
CommandItem item = new CommandItem();
|
||||
item.Input = val.Substring(0, val.IndexOf(" "));
|
||||
|
||||
if (item.Input == "_")
|
||||
item.Input = "";
|
||||
|
||||
val = val.Substring(val.IndexOf(" ") + 1);
|
||||
|
||||
if (val.Contains("#menu:"))
|
||||
{
|
||||
item.Path = val.Substring(val.IndexOf("#menu:") + 6).Trim();
|
||||
val = val.Substring(0, val.IndexOf("#menu:"));
|
||||
|
||||
if (item.Path.Contains(";"))
|
||||
item.Path = item.Path.Substring(item.Path.IndexOf(";") + 1).Trim();
|
||||
}
|
||||
|
||||
item.Command = val.Trim();
|
||||
|
||||
if (item.Command == "")
|
||||
continue;
|
||||
|
||||
if (item.Command.ToLower() == "ignore")
|
||||
item.Command = "";
|
||||
|
||||
items.Add(item);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
static ObservableCollection<CommandItem> _Items;
|
||||
|
||||
public static ObservableCollection<CommandItem> Items {
|
||||
get {
|
||||
if (_Items is null)
|
||||
_Items = GetItems(File.ReadAllText(core.InputConfPath));
|
||||
|
||||
return _Items;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Folder
|
||||
{
|
||||
public static string Startup { get; } = Application.StartupPath + @"\";
|
||||
}
|
||||
}
|
||||
8
mpv.net/Misc/NewLine.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
using System;
|
||||
|
||||
public static class NewLine
|
||||
{
|
||||
public static string BR = Environment.NewLine;
|
||||
public static string BR2 = Environment.NewLine + Environment.NewLine;
|
||||
}
|
||||
244
mpv.net/Misc/PowerShell.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using static mpvnet.Core;
|
||||
using static NewLine;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class PowerShell
|
||||
{
|
||||
public Runspace Runspace { get; set; }
|
||||
public Pipeline Pipeline { get; set; }
|
||||
public string Module { get; set; }
|
||||
public bool Print { get; set; }
|
||||
public List<string> Scripts { get; } = new List<string>();
|
||||
public List<KeyValuePair<string, object>> Variables = new List<KeyValuePair<string, object>>();
|
||||
public string[] Parameters { get; }
|
||||
public event Action<string, object[]> Event;
|
||||
public event Action<string, object> PropertyChanged;
|
||||
public List<KeyValuePair<string, ScriptBlock>> EventHandlers = new List<KeyValuePair<string, ScriptBlock>>();
|
||||
public List<KeyValuePair<string, ScriptBlock>> PropChangedHandlers = new List<KeyValuePair<string, ScriptBlock>>();
|
||||
|
||||
public static List<PowerShell> Instances { get; } = new List<PowerShell>();
|
||||
|
||||
public object Invoke() => Invoke(null, null);
|
||||
|
||||
public object Invoke(string variable, object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Runspace = RunspaceFactory.CreateRunspace();
|
||||
Runspace.ApartmentState = ApartmentState.STA;
|
||||
Runspace.Open();
|
||||
Pipeline = Runspace.CreatePipeline();
|
||||
|
||||
foreach (string script in Scripts)
|
||||
Pipeline.Commands.AddScript(script);
|
||||
|
||||
if (Parameters != null)
|
||||
foreach (string param in Parameters)
|
||||
foreach (Command command in Pipeline.Commands)
|
||||
command.Parameters.Add(null, param);
|
||||
|
||||
Runspace.SessionStateProxy.SetVariable("mp", this);
|
||||
|
||||
foreach (var i in Variables)
|
||||
Runspace.SessionStateProxy.SetVariable(i.Key, i.Value);
|
||||
|
||||
if (!string.IsNullOrEmpty(variable))
|
||||
Runspace.SessionStateProxy.SetVariable(variable, obj);
|
||||
|
||||
if (Print)
|
||||
{
|
||||
Pipeline.Output.DataReady += Output_DataReady;
|
||||
Pipeline.Error.DataReady += Error_DataReady;
|
||||
}
|
||||
|
||||
return Pipeline.Invoke();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
string message = e.Message + BR + BR + e.ErrorRecord.ScriptStackTrace.Replace(
|
||||
" <ScriptBlock>, <No file>", "") + BR + BR + Module + BR;
|
||||
|
||||
throw new PowerShellException(message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static string InvokeAndReturnString(string code, string varName, object varValue)
|
||||
{
|
||||
PowerShell ps = new PowerShell() { Print = false };
|
||||
ps.Scripts.Add(code);
|
||||
string ret = string.Join(Environment.NewLine, (ps.Invoke(varName, varValue)
|
||||
as IEnumerable<object>).Select(item => item.ToString())).ToString();
|
||||
ps.Runspace.Dispose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void Output_DataReady(object sender, EventArgs e)
|
||||
{
|
||||
var output = sender as PipelineReader<PSObject>;
|
||||
|
||||
while (output.Count > 0)
|
||||
ConsoleHelp.Write(output.Read(), Module);
|
||||
}
|
||||
|
||||
public void Error_DataReady(object sender, EventArgs e)
|
||||
{
|
||||
var output = sender as PipelineReader<Object>;
|
||||
|
||||
while (output.Count > 0)
|
||||
ConsoleHelp.WriteError(output.Read(), Module);
|
||||
}
|
||||
|
||||
public void RedirectStreams(PSEventJob job)
|
||||
{
|
||||
if (Print)
|
||||
{
|
||||
job.Output.DataAdded += Output_DataAdded;
|
||||
job.Error.DataAdded += Error_DataAdded;
|
||||
}
|
||||
}
|
||||
|
||||
public void commandv(params string[] args) => core.commandv(args);
|
||||
|
||||
public void command(string command) => core.command(command);
|
||||
|
||||
public bool get_property_bool(string name) => core.get_property_bool(name);
|
||||
|
||||
public void set_property_bool(string name, bool value) => core.set_property_bool(name, value);
|
||||
|
||||
public int get_property_int(string name) => core.get_property_int(name);
|
||||
|
||||
public void set_property_int(string name, int value) => core.set_property_int(name, value);
|
||||
|
||||
public double get_property_number(string name) => core.get_property_number(name);
|
||||
|
||||
public void set_property_number(string name, double value) => core.set_property_number(name, value);
|
||||
|
||||
public string get_property_string(string name) => core.get_property_string(name);
|
||||
|
||||
public void set_property_string(string name, string value) => core.set_property_string(name, value);
|
||||
|
||||
public void observe_property(string name, string type, ScriptBlock sb)
|
||||
{
|
||||
PropChangedHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "bool": case "boolean":
|
||||
core.observe_property_bool(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||
break;
|
||||
case "string":
|
||||
core.observe_property_string(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||
break;
|
||||
case "int": case "integer":
|
||||
core.observe_property_int(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||
break;
|
||||
case "float": case "double":
|
||||
core.observe_property_double(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||
break;
|
||||
case "nil": case "none": case "native":
|
||||
core.observe_property(name, () => Task.Run(() => PropertyChanged.Invoke(name, null)));
|
||||
break;
|
||||
default:
|
||||
App.ShowError("Invalid Type", "Valid types are: bool or boolean, string, int or integer, float or double, nil or none or native");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void register_event(string name, ScriptBlock sb)
|
||||
{
|
||||
EventHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
|
||||
|
||||
switch (name)
|
||||
{
|
||||
case "log-message":
|
||||
core.LogMessageAsync += (level, msg) => Event.Invoke("log-message", new object[] { level, msg });
|
||||
break;
|
||||
|
||||
case "end-file":
|
||||
core.EndFileAsync += (reason) => Event.Invoke("end-file", new object[] { reason });
|
||||
break;
|
||||
|
||||
case "client-message":
|
||||
core.ClientMessageAsync += (args) => Event.Invoke("client-message", args);
|
||||
break;
|
||||
|
||||
case "shutdown":
|
||||
core.Shutdown += () => Event.Invoke("shutdown", null);
|
||||
break;
|
||||
|
||||
case "get-property-reply":
|
||||
core.GetPropertyReplyAsync += () => Event.Invoke("get-property-reply", null);
|
||||
break;
|
||||
|
||||
case "set-property-reply":
|
||||
core.SetPropertyReplyAsync += () => Event.Invoke("set-property-reply", null);
|
||||
break;
|
||||
|
||||
case "command-reply":
|
||||
core.CommandReplyAsync += () => Event.Invoke("command-reply", null);
|
||||
break;
|
||||
|
||||
case "start-file":
|
||||
core.StartFileAsync += () => Event.Invoke("start-file", null);
|
||||
break;
|
||||
|
||||
case "file-loaded":
|
||||
core.FileLoadedAsync += () => Event.Invoke("file-loaded", null);
|
||||
break;
|
||||
|
||||
case "idle":
|
||||
core.IdleAsync += () => Event.Invoke("idle", null);
|
||||
break;
|
||||
|
||||
case "video-reconfig":
|
||||
core.VideoReconfigAsync += () => Event.Invoke("video-reconfig", null);
|
||||
break;
|
||||
|
||||
case "audio-reconfig":
|
||||
core.AudioReconfigAsync += () => Event.Invoke("audio-reconfig", null);
|
||||
break;
|
||||
|
||||
case "seek":
|
||||
core.SeekAsync += () => Event.Invoke("seek", null);
|
||||
break;
|
||||
|
||||
case "playback-restart":
|
||||
core.PlaybackRestartAsync += () => Event.Invoke("playback-restart", null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Output_DataAdded(object sender, DataAddedEventArgs e)
|
||||
{
|
||||
var output = sender as PSDataCollection<PSObject>;
|
||||
ConsoleHelp.Write(output[e.Index], Module);
|
||||
}
|
||||
|
||||
void Error_DataAdded(object sender, DataAddedEventArgs e)
|
||||
{
|
||||
var error = sender as PSDataCollection<ErrorRecord>;
|
||||
ConsoleHelp.WriteError(error[e.Index], Module);
|
||||
}
|
||||
}
|
||||
|
||||
public class PowerShellException : Exception
|
||||
{
|
||||
public PowerShellException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
100
mpv.net/Misc/Program.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
try
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
if (App.IsStartedFromTerminal)
|
||||
WinAPI.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
|
||||
|
||||
if (core.ConfigFolder == "")
|
||||
return;
|
||||
|
||||
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
||||
|
||||
if (args.Length == 2 && args[0] == "--reg-file-assoc")
|
||||
{
|
||||
if (args[1] == "audio") FileAssociation.Register(App.AudioTypes);
|
||||
if (args[1] == "video") FileAssociation.Register(App.VideoTypes);
|
||||
if (args[1] == "image") FileAssociation.Register(App.ImageTypes);
|
||||
if (args[1] == "unreg") FileAssociation.Unregister();
|
||||
return;
|
||||
}
|
||||
|
||||
App.Init();
|
||||
Mutex mutex = new Mutex(true, "mpvnetProcessInstance", out bool isFirst);
|
||||
|
||||
if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst)
|
||||
{
|
||||
List<string> files = new List<string>();
|
||||
files.Add(App.ProcessInstance);
|
||||
|
||||
foreach (string arg in args)
|
||||
{
|
||||
if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") ||
|
||||
arg.Contains(":\\") || arg.StartsWith("\\\\")))
|
||||
|
||||
files.Add(arg);
|
||||
else if (arg == "--queue")
|
||||
files[0] = "queue";
|
||||
}
|
||||
|
||||
Process[] procs = Process.GetProcessesByName("mpvnet");
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
foreach (Process proc in procs)
|
||||
{
|
||||
if (proc.MainWindowHandle != IntPtr.Zero)
|
||||
{
|
||||
WinAPI.AllowSetForegroundWindow(proc.Id);
|
||||
var data = new WinAPI.COPYDATASTRUCT();
|
||||
data.lpData = string.Join("\n", files.ToArray());
|
||||
data.cbData = data.lpData.Length * 2 + 1;
|
||||
WinAPI.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data);
|
||||
mutex.Dispose();
|
||||
|
||||
if (App.IsStartedFromTerminal)
|
||||
WinAPI.FreeConsole();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
|
||||
mutex.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
Application.Run(new MainForm());
|
||||
|
||||
if (App.IsStartedFromTerminal)
|
||||
WinAPI.FreeConsole();
|
||||
|
||||
mutex.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
mpv.net/Misc/RegistryHelp.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System.Windows.Forms;
|
||||
|
||||
public class RegistryHelp
|
||||
{
|
||||
public static string ApplicationKey { get; } = @"HKCU\Software\" + Application.ProductName;
|
||||
|
||||
public static void SetValue(string path, string name, object value)
|
||||
{
|
||||
using (RegistryKey regKey = GetRootKey(path).CreateSubKey(path.Substring(5), RegistryKeyPermissionCheck.ReadWriteSubTree))
|
||||
regKey.SetValue(name, value);
|
||||
}
|
||||
|
||||
public static string GetString(string path, string name, string defaultValue = "")
|
||||
{
|
||||
object value = GetValue(path, name, defaultValue);
|
||||
return !(value is string) ? defaultValue : value.ToString();
|
||||
}
|
||||
|
||||
public static int GetInt(string path, string name, int defaultValue = 0)
|
||||
{
|
||||
object value = GetValue(path, name, defaultValue);
|
||||
return !(value is int) ? defaultValue : (int)value;
|
||||
}
|
||||
|
||||
public static bool GetBool(string path, string name, bool defaultValue = false)
|
||||
{
|
||||
object val = GetValue(path, name, defaultValue);
|
||||
return val is bool ? (bool)val : defaultValue;
|
||||
}
|
||||
|
||||
public static object GetValue(string path, string name, object defaultValue = null)
|
||||
{
|
||||
using (RegistryKey regKey = GetRootKey(path).OpenSubKey(path.Substring(5)))
|
||||
return regKey == null ? null : regKey.GetValue(name, defaultValue);
|
||||
}
|
||||
|
||||
public static void RemoveKey(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
GetRootKey(path).DeleteSubKeyTree(path.Substring(5), false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static void RemoveValue(string path, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RegistryKey regKey = GetRootKey(path).OpenSubKey(path.Substring(5), true))
|
||||
if (regKey != null)
|
||||
regKey.DeleteValue(name, false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
static RegistryKey GetRootKey(string path)
|
||||
{
|
||||
switch (path.Substring(0, 4))
|
||||
{
|
||||
case "HKLM": return Registry.LocalMachine;
|
||||
case "HKCU": return Registry.CurrentUser;
|
||||
case "HKCR": return Registry.ClassesRoot;
|
||||
default: throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
96
mpv.net/Misc/Theme.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Theme
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, string> Dictionary { get; } = new Dictionary<string, string>();
|
||||
|
||||
public static List<Theme> DefaultThemes { get; set; }
|
||||
public static List<Theme> CustomThemes { get; set; }
|
||||
|
||||
public static Theme Current { get; set; }
|
||||
|
||||
public static Brush Foreground { get; set; }
|
||||
public static Brush Foreground2 { get; set; }
|
||||
public static Brush Background { get; set; }
|
||||
public static Brush Heading { get; set; }
|
||||
|
||||
public System.Drawing.Color GetWinFormsColor(string key)
|
||||
{
|
||||
return System.Drawing.ColorTranslator.FromHtml(Dictionary[key]);
|
||||
}
|
||||
|
||||
public Brush GetBrush(string key)
|
||||
{
|
||||
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key]));
|
||||
}
|
||||
|
||||
public static void Init(string customContent, string defaultContent, string activeTheme)
|
||||
{
|
||||
DefaultThemes = Load(defaultContent);
|
||||
CustomThemes = Load(customContent);
|
||||
|
||||
foreach (Theme theme in CustomThemes)
|
||||
{
|
||||
if (theme.Name == activeTheme)
|
||||
{
|
||||
bool isKeyMissing = false;
|
||||
|
||||
foreach (string key in DefaultThemes[0].Dictionary.Keys)
|
||||
{
|
||||
if (!theme.Dictionary.ContainsKey(key))
|
||||
{
|
||||
isKeyMissing = true;
|
||||
ConsoleHelp.WriteError($"Theme '{activeTheme}' misses '{key}'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isKeyMissing)
|
||||
Current = theme;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Current == null)
|
||||
foreach (Theme theme in DefaultThemes)
|
||||
if (theme.Name == activeTheme)
|
||||
Current = theme;
|
||||
|
||||
if (Current == null)
|
||||
Current = DefaultThemes[0];
|
||||
|
||||
Foreground = Current.GetBrush("foreground");
|
||||
Foreground2 = Current.GetBrush("foreground2");
|
||||
Background = Current.GetBrush("background");
|
||||
Heading = Current.GetBrush("heading");
|
||||
}
|
||||
|
||||
static List<Theme> Load(string content)
|
||||
{
|
||||
List<Theme> list = new List<Theme>();
|
||||
Theme theme = null;
|
||||
|
||||
foreach (string currentLine in (content ?? "").Split(new [] { '\r', '\n' }))
|
||||
{
|
||||
string line = currentLine.Trim();
|
||||
|
||||
if (line.StartsWith("[") && line.EndsWith("]"))
|
||||
list.Add(theme = new Theme() { Name = line.Substring(1, line.Length - 2).Trim() });
|
||||
|
||||
if (line.Contains("=") && theme != null)
|
||||
{
|
||||
string left = line.Substring(0, line.IndexOf("=")).Trim();
|
||||
theme.Dictionary[left] = line.Substring(line.IndexOf("=") + 1).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
mpv.net/Misc/UpdateCheck.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using static mpvnet.Core;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
class UpdateCheck
|
||||
{
|
||||
public static void DailyCheck()
|
||||
{
|
||||
if (App.UpdateCheck && RegistryHelp.GetInt(RegistryHelp.ApplicationKey, "UpdateCheckLast")
|
||||
!= DateTime.Now.DayOfYear)
|
||||
|
||||
CheckOnline();
|
||||
}
|
||||
|
||||
public static async void CheckOnline(bool showUpToDateMessage = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
RegistryHelp.SetValue(RegistryHelp.ApplicationKey, "UpdateCheckLast", DateTime.Now.DayOfYear);
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "mpv.net");
|
||||
var response = await client.GetAsync("https://api.github.com/repos/stax76/mpv.net/releases/latest");
|
||||
response.EnsureSuccessStatusCode();
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
Match match = Regex.Match(content, @"""mpv\.net-portable-x64-([\d\.]+)\.7z""");
|
||||
Version onlineVersion = Version.Parse(match.Groups[1].Value);
|
||||
Version currentVersion = Assembly.GetEntryAssembly().GetName().Version;
|
||||
|
||||
if (onlineVersion <= currentVersion)
|
||||
{
|
||||
if (showUpToDateMessage)
|
||||
Msg.Show($"{Application.ProductName} is up to date.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((RegistryHelp.GetString(RegistryHelp.ApplicationKey, "UpdateCheckVersion")
|
||||
!= onlineVersion.ToString() || showUpToDateMessage) && Msg.ShowQuestion(
|
||||
$"New version {onlineVersion} is available, update now?") == MsgResult.OK)
|
||||
{
|
||||
string arch = IntPtr.Size == 8 ? "64" : "86";
|
||||
string url = $"https://github.com/stax76/mpv.net/releases/download/{onlineVersion}/mpv.net-portable-x{arch}-{onlineVersion}.7z";
|
||||
|
||||
using (Process proc = new Process())
|
||||
{
|
||||
proc.StartInfo.UseShellExecute = true;
|
||||
proc.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
proc.StartInfo.FileName = "PowerShell";
|
||||
proc.StartInfo.Arguments = $"-NoLogo -NoExit -File \"{Folder.Startup + "Update.ps1"}\" \"{url}\" \"{Application.StartupPath.TrimEnd('\\')}\"";
|
||||
|
||||
if (Folder.Startup.Contains("Program Files"))
|
||||
proc.StartInfo.Verb = "runas";
|
||||
|
||||
proc.Start();
|
||||
}
|
||||
|
||||
core.command("quit");
|
||||
}
|
||||
|
||||
RegistryHelp.SetValue(RegistryHelp.ApplicationKey, "UpdateCheckVersion", onlineVersion.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (showUpToDateMessage)
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class Native
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr LoadLibrary(string dllToLoad);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern string SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern void ReleaseCapture();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetWindowLongPtrW(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
|
||||
public RECT(Rectangle r)
|
||||
{
|
||||
Left = r.Left;
|
||||
Top = r.Top;
|
||||
Right = r.Right;
|
||||
Bottom = r.Bottom;
|
||||
}
|
||||
|
||||
public RECT(int left, int top, int right, int bottom)
|
||||
{
|
||||
Left = left;
|
||||
Top = top;
|
||||
Right = right;
|
||||
Bottom = bottom;
|
||||
}
|
||||
|
||||
public Rectangle ToRectangle() { return Rectangle.FromLTRB(Left, Top, Right, Bottom); }
|
||||
public Size Size => new Size(Right - Left, Bottom - Top);
|
||||
public int Width => Right - Left;
|
||||
public int Height => Bottom - Top;
|
||||
}
|
||||
}
|
||||
}
|
||||
113
mpv.net/Native/MediaInfo.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class MediaInfo : IDisposable
|
||||
{
|
||||
IntPtr Handle;
|
||||
|
||||
public MediaInfo(string file)
|
||||
{
|
||||
if ((Handle = MediaInfo_New()) == IntPtr.Zero)
|
||||
throw new Exception("Failed to call MediaInfo_New");
|
||||
|
||||
if (MediaInfo_Open(Handle, file) == 0)
|
||||
throw new Exception("Error MediaInfo_Open");
|
||||
}
|
||||
|
||||
public string GetInfo(MediaInfoStreamKind kind, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, kind, 0,
|
||||
parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||
}
|
||||
|
||||
public int GetCount(MediaInfoStreamKind kind) => MediaInfo_Count_Get(Handle, kind, -1);
|
||||
|
||||
public string GetVideo(int stream, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video,
|
||||
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||
}
|
||||
|
||||
public string GetAudio(int stream, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio,
|
||||
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||
}
|
||||
|
||||
public string GetText(int stream, string parameter)
|
||||
{
|
||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text,
|
||||
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||
}
|
||||
|
||||
bool Disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Disposed)
|
||||
{
|
||||
if (Handle != IntPtr.Zero)
|
||||
{
|
||||
MediaInfo_Close(Handle);
|
||||
MediaInfo_Delete(Handle);
|
||||
}
|
||||
|
||||
Disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
~MediaInfo()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern IntPtr MediaInfo_New();
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int MediaInfo_Open(IntPtr handle, string path);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr MediaInfo_Option(IntPtr handle, string option, string value);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern IntPtr MediaInfo_Inform(IntPtr handle, int reserved);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern int MediaInfo_Close(IntPtr handle);
|
||||
|
||||
[DllImport("MediaInfo.dll")]
|
||||
static extern void MediaInfo_Delete(IntPtr handle);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr MediaInfo_Get(IntPtr handle, MediaInfoStreamKind kind,
|
||||
int stream, string parameter, MediaInfoKind infoKind, MediaInfoKind searchKind);
|
||||
|
||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||
static extern int MediaInfo_Count_Get(IntPtr handle, MediaInfoStreamKind streamKind, int stream);
|
||||
}
|
||||
|
||||
public enum MediaInfoStreamKind
|
||||
{
|
||||
General,
|
||||
Video,
|
||||
Audio,
|
||||
Text,
|
||||
Other,
|
||||
Image,
|
||||
Menu,
|
||||
Max,
|
||||
}
|
||||
|
||||
public enum MediaInfoKind
|
||||
{
|
||||
Name,
|
||||
Text,
|
||||
Measure,
|
||||
Options,
|
||||
NameText,
|
||||
MeasureText,
|
||||
Info,
|
||||
HowTo
|
||||
}
|
||||
99
mpv.net/Native/Native.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class WinAPI
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool AttachConsole(int dwProcessId);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool FreeConsole();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr LoadLibrary(string path);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int RegisterWindowMessage(string id);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool AllowSetForegroundWindow(int dwProcessId);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern void ReleaseCapture();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
|
||||
static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
|
||||
static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);
|
||||
|
||||
public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
|
||||
{
|
||||
if (IntPtr.Size == 8)
|
||||
return GetWindowLong64(hWnd, nIndex);
|
||||
else
|
||||
return GetWindowLong32(hWnd, nIndex);
|
||||
}
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
|
||||
public RECT(Rectangle r)
|
||||
{
|
||||
Left = r.Left;
|
||||
Top = r.Top;
|
||||
Right = r.Right;
|
||||
Bottom = r.Bottom;
|
||||
}
|
||||
|
||||
public RECT(int left, int top, int right, int bottom)
|
||||
{
|
||||
Left = left;
|
||||
Top = top;
|
||||
Right = right;
|
||||
Bottom = bottom;
|
||||
}
|
||||
|
||||
public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom);
|
||||
public Size Size => new Size(Right - Left, Bottom - Top);
|
||||
public int Width => Right - Left;
|
||||
public int Height => Bottom - Top;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct COPYDATASTRUCT
|
||||
{
|
||||
public IntPtr dwData;
|
||||
public int cbData;
|
||||
[MarshalAs(UnmanagedType.LPTStr)]
|
||||
public string lpData;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
|
||||
using System;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
@@ -20,9 +21,9 @@ namespace mpvnet
|
||||
}
|
||||
}
|
||||
|
||||
public static void SubtractWindowBorders(IntPtr hwnd, ref Native.RECT rc)
|
||||
public static void SubtractWindowBorders(IntPtr hwnd, ref WinAPI.RECT rc)
|
||||
{
|
||||
var b = new Native.RECT(0, 0, 0, 0);
|
||||
var b = new WinAPI.RECT(0, 0, 0, 0);
|
||||
AddWindowBorders(hwnd, ref b);
|
||||
rc.Left -= b.Left;
|
||||
rc.Top -= b.Top;
|
||||
@@ -30,9 +31,9 @@ namespace mpvnet
|
||||
rc.Bottom -= b.Bottom;
|
||||
}
|
||||
|
||||
public static void AddWindowBorders(IntPtr hwnd, ref Native.RECT rc)
|
||||
public static void AddWindowBorders(IntPtr hwnd, ref WinAPI.RECT rc)
|
||||
{
|
||||
Native.AdjustWindowRect(ref rc, (uint)Native.GetWindowLongPtrW(hwnd, -16 /* GWL_STYLE */), false);
|
||||
WinAPI.AdjustWindowRect(ref rc, (uint)WinAPI.GetWindowLong(hwnd, -16 /* GWL_STYLE */), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
662
mpv.net/Native/TaskDialog.cs
Normal file
@@ -0,0 +1,662 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
public class Msg
|
||||
{
|
||||
static string ShownMessages;
|
||||
|
||||
public static string SupportURL { get; set; }
|
||||
|
||||
public static void Show(string mainInstruction, string content = null)
|
||||
{
|
||||
Msg.Show(mainInstruction, content, MsgIcon.Info, MsgButtons.Ok, MsgResult.None);
|
||||
}
|
||||
|
||||
public static void ShowError(string mainInstruction, string content = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TaskDialog<string> td = new TaskDialog<string>())
|
||||
{
|
||||
td.AllowCancel = false;
|
||||
|
||||
if (string.IsNullOrEmpty(content))
|
||||
{
|
||||
if (mainInstruction.Length < 80)
|
||||
td.MainInstruction = mainInstruction;
|
||||
else
|
||||
td.Content = mainInstruction;
|
||||
}
|
||||
else
|
||||
{
|
||||
td.MainInstruction = mainInstruction;
|
||||
td.Content = content;
|
||||
}
|
||||
|
||||
td.MainIcon = MsgIcon.Error;
|
||||
td.Footer = "[Copy Message](copymsg)";
|
||||
|
||||
if (!string.IsNullOrEmpty(Msg.SupportURL))
|
||||
td.Footer += $" [Contact Support]({SupportURL})";
|
||||
|
||||
td.Show();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(e.GetType().Name + "\n\n" + e.Message + "\n\n" + e,
|
||||
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowException(Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TaskDialog<string> td = new TaskDialog<string>())
|
||||
{
|
||||
td.MainInstruction = exception.GetType().Name;
|
||||
td.Content = exception.Message;
|
||||
td.MainIcon = MsgIcon.Error;
|
||||
td.ExpandedInformation = exception.StackTrace;
|
||||
td.Footer = "[Copy Message](copymsg)";
|
||||
|
||||
if (!string.IsNullOrEmpty(Msg.SupportURL))
|
||||
td.Footer += $" [Contact Support]({SupportURL})";
|
||||
|
||||
td.Show();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowWarning(string mainInstruction,
|
||||
string content = null,
|
||||
bool onlyOnce = false)
|
||||
{
|
||||
if (onlyOnce && Msg.ShownMessages != null &&
|
||||
Msg.ShownMessages.Contains(mainInstruction + content))
|
||||
return;
|
||||
|
||||
Msg.Show(mainInstruction, content, MsgIcon.Warning, MsgButtons.Ok, MsgResult.None);
|
||||
if (!onlyOnce) return;
|
||||
Msg.ShownMessages += mainInstruction + content;
|
||||
}
|
||||
|
||||
public static MsgResult ShowQuestion(
|
||||
string mainInstruction, MsgButtons buttons = MsgButtons.OkCancel)
|
||||
{
|
||||
return Msg.Show(mainInstruction, null, MsgIcon.None, buttons, MsgResult.None);
|
||||
}
|
||||
|
||||
public static MsgResult ShowQuestion(
|
||||
string mainInstruction, string content, MsgButtons buttons = MsgButtons.OkCancel)
|
||||
{
|
||||
return Msg.Show(mainInstruction, content, MsgIcon.None, buttons, MsgResult.None);
|
||||
}
|
||||
|
||||
public static MsgResult Show(
|
||||
string mainInstruction,
|
||||
string content,
|
||||
MsgIcon icon,
|
||||
MsgButtons buttons,
|
||||
MsgResult defaultButton = MsgResult.None)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TaskDialog<MsgResult> td = new TaskDialog<MsgResult>())
|
||||
{
|
||||
td.AllowCancel = false;
|
||||
td.DefaultButton = defaultButton;
|
||||
td.MainIcon = icon;
|
||||
|
||||
if (content == null)
|
||||
{
|
||||
if (mainInstruction.Length < 80)
|
||||
td.MainInstruction = mainInstruction;
|
||||
else
|
||||
td.Content = mainInstruction;
|
||||
}
|
||||
else
|
||||
{
|
||||
td.MainInstruction = mainInstruction;
|
||||
td.Content = content;
|
||||
}
|
||||
if (buttons == MsgButtons.OkCancel)
|
||||
{
|
||||
td.AddButton("OK", MsgResult.OK);
|
||||
td.AddButton("Cancel", MsgResult.Cancel);
|
||||
}
|
||||
else
|
||||
td.CommonButtons = buttons;
|
||||
return td.Show();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return (MsgResult)MessageBox.Show(e.GetType().Name + "\n\n" + e.Message + "\n\n" + e,
|
||||
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TaskDialog<T> : TaskDialogNative, IDisposable
|
||||
{
|
||||
Dictionary<int, T> IdValueDic;
|
||||
Dictionary<int, string> IdTextDic;
|
||||
List<int> CommandLinkShieldList;
|
||||
IntPtr ButtonArray;
|
||||
IntPtr RadioButtonArray;
|
||||
T SelectedValueValue;
|
||||
string SelectedTextValue;
|
||||
int TimeoutValue;
|
||||
int ExitTickCount;
|
||||
bool Disposed;
|
||||
List<TaskDialogNative.TASKDIALOG_BUTTON> Buttons;
|
||||
List<TaskDialogNative.TASKDIALOG_BUTTON> RadioButtons;
|
||||
TaskDialogNative.TASKDIALOGCONFIG Config;
|
||||
|
||||
const int TDE_CONTENT = 0;
|
||||
const int TDE_EXPANDED_INFORMATION = 1;
|
||||
const int TDE_FOOTER = 2;
|
||||
const int TDE_MAIN_INSTRUCTION = 3;
|
||||
const int TDN_CREATED = 0;
|
||||
const int TDN_NAVIGATED = 1;
|
||||
const int TDN_BUTTON_CLICKED = 2;
|
||||
const int TDN_HYPERLINK_CLICKED = 3;
|
||||
const int TDN_TIMER = 4;
|
||||
const int TDN_DESTROYED = 5;
|
||||
const int TDN_RADIO_BUTTON_CLICKED = 6;
|
||||
const int TDN_DIALOG_CONSTRUCTED = 7;
|
||||
const int TDN_VERIFICATION_CLICKED = 8;
|
||||
const int TDN_HELP = 9;
|
||||
const int TDN_EXPANDO_BUTTON_CLICKED = 10;
|
||||
const int TDM_NAVIGATE_PAGE = 1125;
|
||||
const int TDM_CLICK_BUTTON = 1126;
|
||||
const int TDM_SET_MARQUEE_PROGRESS_BAR = 1127;
|
||||
const int TDM_SET_PROGRESS_BAR_STATE = 1128;
|
||||
const int TDM_SET_PROGRESS_BAR_RANGE = 1129;
|
||||
const int TDM_SET_PROGRESS_BAR_POS = 1130;
|
||||
const int TDM_SET_PROGRESS_BAR_MARQUEE = 1131;
|
||||
const int TDM_SET_ELEMENT_TEXT = 1132;
|
||||
const int TDM_CLICK_RADIO_BUTTON = 1134;
|
||||
const int TDM_ENABLE_BUTTON = 1135;
|
||||
const int TDM_ENABLE_RADIO_BUTTON = 1136;
|
||||
const int TDM_CLICK_VERIFICATION = 1137;
|
||||
const int TDM_UPDATE_ELEMENT_TEXT = 1138;
|
||||
const int TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = 1139;
|
||||
const int TDM_UPDATE_ICON = 1140;
|
||||
|
||||
public TaskDialog()
|
||||
{
|
||||
IdValueDic = new Dictionary<int, T>();
|
||||
IdTextDic = new Dictionary<int, string>();
|
||||
CommandLinkShieldList = new List<int>();
|
||||
Buttons = new List<TaskDialogNative.TASKDIALOG_BUTTON>();
|
||||
RadioButtons = new List<TaskDialogNative.TASKDIALOG_BUTTON>();
|
||||
_SelectedID = -1;
|
||||
Config = new TaskDialogNative.TASKDIALOGCONFIG();
|
||||
Config.cbSize = (uint)Marshal.SizeOf(Config);
|
||||
Config.hwndParent = GetHandle();
|
||||
Config.hInstance = IntPtr.Zero;
|
||||
Config.dwFlags = TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
|
||||
Config.dwCommonButtons = MsgButtons.None;
|
||||
Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0);
|
||||
Config.FooterIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0);
|
||||
Config.cxWidth = 0U;
|
||||
Config.cButtons = 0U;
|
||||
Config.cRadioButtons = 0U;
|
||||
Config.pButtons = IntPtr.Zero;
|
||||
Config.pRadioButtons = IntPtr.Zero;
|
||||
Config.nDefaultButton = 0;
|
||||
Config.nDefaultRadioButton = 0;
|
||||
Config.pszWindowTitle = ((AssemblyProductAttribute)Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0]).Product;
|
||||
Config.pszMainInstruction = "";
|
||||
Config.pszContent = "";
|
||||
Config.pfCallback = new PFTASKDIALOGCALLBACK(this.DialogProc);
|
||||
}
|
||||
|
||||
public IntPtr GetHandle()
|
||||
{
|
||||
StringBuilder lpszFileName = new StringBuilder(260);
|
||||
IntPtr foregroundWindow = TaskDialogNative.GetForegroundWindow();
|
||||
TaskDialogNative.GetWindowModuleFileName(foregroundWindow, lpszFileName, 260U);
|
||||
|
||||
if (Path.GetFileName(lpszFileName.ToString().Replace(".vshost", "")) ==
|
||||
Path.GetFileName(Assembly.GetEntryAssembly().Location))
|
||||
|
||||
return foregroundWindow;
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public bool AllowCancel {
|
||||
set {
|
||||
if (value)
|
||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
|
||||
else
|
||||
Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
|
||||
}
|
||||
}
|
||||
|
||||
public string MainInstruction {
|
||||
get => Config.pszMainInstruction;
|
||||
set => Config.pszMainInstruction = value;
|
||||
}
|
||||
|
||||
public string Content {
|
||||
get => Config.pszContent;
|
||||
set => Config.pszContent = ExpandMarkdownMarkup(value);
|
||||
}
|
||||
|
||||
public string ExpandedInformation {
|
||||
get => Config.pszExpandedInformation;
|
||||
set => Config.pszExpandedInformation = ExpandMarkdownMarkup(value);
|
||||
}
|
||||
|
||||
public string VerificationText {
|
||||
get => Config.pszVerificationText;
|
||||
set => Config.pszVerificationText = value;
|
||||
}
|
||||
|
||||
public MsgResult DefaultButton {
|
||||
get => (MsgResult)Config.nDefaultButton;
|
||||
set => Config.nDefaultButton = (int)value;
|
||||
}
|
||||
|
||||
public string Footer {
|
||||
get => Config.pszFooter;
|
||||
set => Config.pszFooter = ExpandMarkdownMarkup(value);
|
||||
}
|
||||
|
||||
public MsgIcon MainIcon {
|
||||
set => Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION((int)value);
|
||||
}
|
||||
|
||||
int _SelectedID;
|
||||
|
||||
public int SelectedID {
|
||||
get => _SelectedID;
|
||||
set {
|
||||
foreach (var i in IdValueDic)
|
||||
if (i.Key == value)
|
||||
_SelectedID = value;
|
||||
}
|
||||
}
|
||||
|
||||
public T SelectedValue {
|
||||
get {
|
||||
if (IdValueDic.ContainsKey(SelectedID))
|
||||
return IdValueDic[SelectedID];
|
||||
|
||||
return SelectedValueValue;
|
||||
}
|
||||
set => SelectedValueValue = value;
|
||||
}
|
||||
|
||||
public string SelectedText {
|
||||
get {
|
||||
if (IdTextDic.ContainsKey(SelectedID))
|
||||
return IdTextDic[SelectedID];
|
||||
|
||||
return SelectedTextValue;
|
||||
}
|
||||
set => SelectedTextValue = value;
|
||||
}
|
||||
|
||||
public bool CheckBoxChecked {
|
||||
get => (Config.dwFlags & TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED)
|
||||
== TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
||||
set {
|
||||
if (value)
|
||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
||||
else
|
||||
Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
||||
}
|
||||
}
|
||||
|
||||
public MsgButtons CommonButtons {
|
||||
get => Config.dwCommonButtons;
|
||||
set => Config.dwCommonButtons = value;
|
||||
}
|
||||
|
||||
public int Timeout {
|
||||
get => Convert.ToInt32(TimeoutValue / 1000.0);
|
||||
set {
|
||||
TimeoutValue = value * 1000;
|
||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddButton(string text, T value)
|
||||
{
|
||||
int n = 1000 + IdValueDic.Count + 1;
|
||||
IdValueDic[n] = value;
|
||||
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
||||
}
|
||||
|
||||
public string ExpandMarkdownMarkup(string value)
|
||||
{
|
||||
if (value.Contains("["))
|
||||
{
|
||||
Regex regex = new Regex(@"\[(.+)\]\((.+)\)");
|
||||
|
||||
if (regex.Match(value).Success)
|
||||
{
|
||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS;
|
||||
value = regex.Replace(value, "<a href=\"$2\">$1</a>");
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public void AddCommand(string text, T value)
|
||||
{
|
||||
int n = 1000 + IdValueDic.Count + 1;
|
||||
IdValueDic[n] = value;
|
||||
IdTextDic[n] = text;
|
||||
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
|
||||
}
|
||||
|
||||
public void AddCommand(string text, string description, T value, bool setShield = false)
|
||||
{
|
||||
int n = 1000 + IdValueDic.Count + 1;
|
||||
IdValueDic[n] = value;
|
||||
|
||||
if (setShield)
|
||||
CommandLinkShieldList.Add(n);
|
||||
|
||||
if (!string.IsNullOrEmpty(description))
|
||||
text += "\n" + description;
|
||||
|
||||
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
|
||||
}
|
||||
|
||||
public void AddRadioButton(string text, T value)
|
||||
{
|
||||
int n = 1000 + IdValueDic.Count + 1;
|
||||
IdValueDic[n] = value;
|
||||
RadioButtons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
||||
}
|
||||
|
||||
public T Show()
|
||||
{
|
||||
MarshalDialogControlStructs();
|
||||
TaskDialogNative.TASKDIALOGCONFIG config = Config;
|
||||
int hr = TaskDialogNative.TaskDialogIndirect(
|
||||
config, out int dummy1, out int dummy2, out bool isChecked);
|
||||
|
||||
if (hr < 0)
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
|
||||
CheckBoxChecked = isChecked;
|
||||
|
||||
if (SelectedValue is MsgResult)
|
||||
SelectedValue = (T)(object)SelectedID;
|
||||
|
||||
return SelectedValue;
|
||||
}
|
||||
|
||||
public int DialogProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, IntPtr lpRefData)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case 0: //TDN_CREATED
|
||||
foreach (var i in CommandLinkShieldList)
|
||||
SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, new IntPtr(i), new IntPtr(1));
|
||||
break;
|
||||
case 2: //TDN_BUTTON_CLICKED
|
||||
case 6: //TDN_RADIO_BUTTON_CLICKED
|
||||
if (SelectedValue is MsgResult)
|
||||
_SelectedID = wParam.ToInt32();
|
||||
else
|
||||
SelectedID = wParam.ToInt32();
|
||||
break;
|
||||
case 3: //TDN_HYPERLINK_CLICKED
|
||||
string stringUni = Marshal.PtrToStringUni(lParam);
|
||||
|
||||
if (stringUni.StartsWith("mailto") || stringUni.StartsWith("http"))
|
||||
Process.Start(stringUni);
|
||||
|
||||
if (stringUni == "copymsg")
|
||||
{
|
||||
Thread thread = new Thread((ThreadStart)(() => {
|
||||
Clipboard.SetText(MainInstruction + "\r\n\r\n" + Content + "\r\n\r\n" + ExpandedInformation);
|
||||
MessageBox.Show("Message was copied to clipboard.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}));
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.Start();
|
||||
}
|
||||
break;
|
||||
case 4: //TDN_TIMER
|
||||
if (ExitTickCount == 0) ExitTickCount = Environment.TickCount + Timeout * 1000;
|
||||
if (Environment.TickCount > ExitTickCount)
|
||||
TaskDialogNative.SendMessage(hwnd, 1126, new IntPtr(1), IntPtr.Zero);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void MarshalDialogControlStructs()
|
||||
{
|
||||
if (Buttons != null && Buttons.Count > 0)
|
||||
{
|
||||
ButtonArray = TaskDialog<T>.AllocateAndMarshalButtons(Buttons);
|
||||
Config.pButtons = ButtonArray;
|
||||
Config.cButtons = (uint)Buttons.Count;
|
||||
}
|
||||
|
||||
if (RadioButtons == null || RadioButtons.Count <= 0) return;
|
||||
RadioButtonArray = TaskDialog<T>.AllocateAndMarshalButtons(RadioButtons);
|
||||
Config.pRadioButtons = RadioButtonArray;
|
||||
Config.cRadioButtons = (uint)RadioButtons.Count;
|
||||
}
|
||||
|
||||
public static IntPtr AllocateAndMarshalButtons(List<TaskDialogNative.TASKDIALOG_BUTTON> structs)
|
||||
{
|
||||
var initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TASKDIALOG_BUTTON)) * structs.Count);
|
||||
var currentPtr = initialPtr;
|
||||
|
||||
foreach (var button in structs)
|
||||
{
|
||||
Marshal.StructureToPtr(button, currentPtr, false);
|
||||
currentPtr = (IntPtr)(currentPtr.ToInt64() + Marshal.SizeOf(button));
|
||||
}
|
||||
|
||||
return initialPtr;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~TaskDialog()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (Disposed)
|
||||
return;
|
||||
|
||||
Disposed = true;
|
||||
|
||||
if (ButtonArray != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(ButtonArray);
|
||||
ButtonArray = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (RadioButtonArray != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(RadioButtonArray);
|
||||
RadioButtonArray = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public delegate int PFTASKDIALOGCALLBACK(
|
||||
IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, IntPtr lpRefData);
|
||||
|
||||
public class TaskDialogNative
|
||||
{
|
||||
[DllImport("comctl32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int TaskDialogIndirect(
|
||||
TaskDialogNative.TASKDIALOGCONFIG pTaskConfig,
|
||||
out int pnButton,
|
||||
out int pnRadioButton,
|
||||
out bool pVerificationFlagChecked);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern uint GetWindowModuleFileName(
|
||||
IntPtr hwnd, StringBuilder lpszFileName, uint cchFileNameMax);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr SendMessage(
|
||||
IntPtr handle, int message, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
|
||||
public class TASKDIALOGCONFIG
|
||||
{
|
||||
public uint cbSize;
|
||||
public IntPtr hwndParent;
|
||||
public IntPtr hInstance;
|
||||
public TaskDialogNative.TASKDIALOG_FLAGS dwFlags;
|
||||
public MsgButtons dwCommonButtons;
|
||||
public string pszWindowTitle;
|
||||
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION MainIcon;
|
||||
public string pszMainInstruction;
|
||||
public string pszContent;
|
||||
public uint cButtons;
|
||||
public IntPtr pButtons;
|
||||
public int nDefaultButton;
|
||||
public uint cRadioButtons;
|
||||
public IntPtr pRadioButtons;
|
||||
public int nDefaultRadioButton;
|
||||
public string pszVerificationText;
|
||||
public string pszExpandedInformation;
|
||||
public string pszExpandedControlText;
|
||||
public string pszCollapsedControlText;
|
||||
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION FooterIcon;
|
||||
public string pszFooter;
|
||||
public PFTASKDIALOGCALLBACK pfCallback;
|
||||
public IntPtr lpCallbackData;
|
||||
public uint cxWidth;
|
||||
}
|
||||
|
||||
public enum TASKDIALOG_FLAGS
|
||||
{
|
||||
NONE = 0,
|
||||
TDF_ENABLE_HYPERLINKS = 1,
|
||||
TDF_USE_HICON_MAIN = 2,
|
||||
TDF_USE_HICON_FOOTER = 4,
|
||||
TDF_ALLOW_DIALOG_CANCELLATION = 8,
|
||||
TDF_USE_COMMAND_LINKS = 16,
|
||||
TDF_USE_COMMAND_LINKS_NO_ICON = 32,
|
||||
TDF_EXPAND_FOOTER_AREA = 64,
|
||||
TDF_EXPANDED_BY_DEFAULT = 128,
|
||||
TDF_VERIFICATION_FLAG_CHECKED = 256,
|
||||
TDF_SHOW_PROGRESS_BAR = 512,
|
||||
TDF_SHOW_MARQUEE_PROGRESS_BAR = 1024,
|
||||
TDF_CALLBACK_TIMER = 2048,
|
||||
TDF_POSITION_RELATIVE_TO_WINDOW = 4096,
|
||||
TDF_RTL_LAYOUT = 8192,
|
||||
TDF_NO_DEFAULT_RADIO_BUTTON = 16384,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
|
||||
public struct TASKDIALOGCONFIG_ICON_UNION
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public int hMainIcon;
|
||||
[FieldOffset(0)]
|
||||
public int pszIcon;
|
||||
[FieldOffset(0)]
|
||||
public IntPtr spacer;
|
||||
|
||||
public TASKDIALOGCONFIG_ICON_UNION(int i)
|
||||
{
|
||||
this = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION();
|
||||
spacer = IntPtr.Zero;
|
||||
pszIcon = 0;
|
||||
hMainIcon = i;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
|
||||
public struct TASKDIALOG_BUTTON
|
||||
{
|
||||
public int nButtonID;
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pszButtonText;
|
||||
|
||||
public TASKDIALOG_BUTTON(int n, string txt)
|
||||
{
|
||||
this = new TaskDialogNative.TASKDIALOG_BUTTON();
|
||||
nButtonID = n;
|
||||
pszButtonText = txt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MsgButtons
|
||||
{
|
||||
None = 0,
|
||||
Ok = 1,
|
||||
Yes = 2,
|
||||
No = 4,
|
||||
YesNo = 6,
|
||||
Cancel = 8,
|
||||
OkCancel = 9,
|
||||
YesNoCancel = 14,
|
||||
Retry = 16,
|
||||
RetryCancel = 24,
|
||||
Close = 32,
|
||||
}
|
||||
|
||||
public enum MsgResult
|
||||
{
|
||||
None,
|
||||
OK,
|
||||
Cancel,
|
||||
Abort,
|
||||
Retry,
|
||||
Ignore,
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
public enum MsgIcon
|
||||
{
|
||||
None = 0,
|
||||
SecurityShieldGray = 65527,
|
||||
SecuritySuccess = 65528,
|
||||
SecurityError = 65529,
|
||||
SecurityWarning = 65530,
|
||||
SecurityShieldBlue = 65531,
|
||||
Shield = 65532,
|
||||
Info = 65533,
|
||||
Error = 65534,
|
||||
Warning = 65535,
|
||||
}
|
||||
55
mpv.net/Native/Taskbar.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class Taskbar
|
||||
{
|
||||
public IntPtr Handle { get; set; }
|
||||
|
||||
public Taskbar(IntPtr handle) => Handle = handle;
|
||||
|
||||
ITaskbarList3 Instance = (ITaskbarList3)new TaskBarCommunication();
|
||||
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[Guid("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF")]
|
||||
interface ITaskbarList3
|
||||
{
|
||||
// ITaskbarList
|
||||
[PreserveSig] void HrInit();
|
||||
[PreserveSig] void AddTab(IntPtr hwnd);
|
||||
[PreserveSig] void DeleteTab(IntPtr hwnd);
|
||||
[PreserveSig] void ActivateTab(IntPtr hwnd);
|
||||
[PreserveSig] void SetActiveAlt(IntPtr hwnd);
|
||||
// ITaskbarList2
|
||||
[PreserveSig] void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
|
||||
// ITaskbarList3
|
||||
[PreserveSig] void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
|
||||
[PreserveSig] void SetProgressState(IntPtr hwnd, TaskbarStates state);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
|
||||
class TaskBarCommunication
|
||||
{
|
||||
}
|
||||
|
||||
public void SetState(TaskbarStates taskbarState)
|
||||
{
|
||||
Instance.SetProgressState(Handle, taskbarState);
|
||||
}
|
||||
|
||||
public void SetValue(double progressValue, double progressMax)
|
||||
{
|
||||
Instance.SetProgressValue(Handle, (UInt64)progressValue, (UInt64)progressMax);
|
||||
}
|
||||
}
|
||||
|
||||
public enum TaskbarStates
|
||||
{
|
||||
NoProgress = 0,
|
||||
Indeterminate = 0x1,
|
||||
Normal = 0x2,
|
||||
Error = 0x4,
|
||||
Paused = 0x8
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using VBNET;
|
||||
|
||||
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 (Exception ex2)
|
||||
{
|
||||
Msg.ShowError("PowerShell Setup Problem\n\nEnsure you have at least PowerShell 5.1 installed.", ex2.ToString());
|
||||
return null;
|
||||
}
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
|
||||
if (args.Length == 3 && args[1] == "--reg-file-assoc")
|
||||
{
|
||||
if (args[2] == "audio") FileAssociation.Register(FileAssociation.AudioTypes);
|
||||
if (args[2] == "video") FileAssociation.Register(FileAssociation.VideoTypes);
|
||||
if (args[2] == "unregister") FileAssociation.Unregister();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("libmpv based media player")]
|
||||
[assembly: AssemblyDescription("mpv based media player")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
||||
[assembly: AssemblyProduct("mpv.net")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017-2019 stax76")]
|
||||
[assembly: AssemblyCopyright("Copyright (C) 2017-2020 Frank Skare (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("3.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.0.0")]
|
||||
[assembly: AssemblyVersion("5.4.8.0")]
|
||||
[assembly: AssemblyFileVersion("5.4.8.0")]
|
||||
|
||||
100
mpv.net/Properties/Resources.Designer.cs
generated
@@ -62,19 +62,36 @@ namespace mpvnet.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
/// # This file defines the input (keys and mouse) bindings of mpv and mpv.net
|
||||
/// # and it also defines the context menu of mpv.net. mpv.net has an input
|
||||
/// # editor and an conf editor as alternatives to editing conf text files.
|
||||
/// # The input and conf editors can be found in mpv.net's context menu at:
|
||||
///[[settings]]
|
||||
///name = "hwdec"
|
||||
///file = "mpv"
|
||||
///default = "no"
|
||||
///filter = "Video"
|
||||
///url = "https://mpv.io/manual/master/#options-hwdec"
|
||||
///help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
|
||||
///options = [{ name = "no", help = "always use software decoding" },
|
||||
/// { name = "auto", h [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string editor_toml {
|
||||
get {
|
||||
return ResourceManager.GetString("editor_toml", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
/// # This file defines the key and mouse bindings and the context menu
|
||||
/// # of mpv.net. A input and config editor can be found in mpv.nets
|
||||
/// # context menu under 'Settings'. The defaults of this file can be found at:
|
||||
///
|
||||
/// # Settings > Show Config Editor
|
||||
/// # Settings > Show Input Editor
|
||||
/// # https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt
|
||||
///
|
||||
/// # The defaults of this file can be found at:
|
||||
/// # The defaults of mpv can be found at:
|
||||
///
|
||||
/// # https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt
|
||||
/// # https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||
///
|
||||
/// # the [rest of string was truncated]";.
|
||||
/// # mpv.net's defaults of mpv.conf contain: 'input-default-bindings = no'
|
||||
/// # which disables mpv's i [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string input_conf {
|
||||
get {
|
||||
@@ -84,24 +101,71 @@ namespace mpvnet.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
///# 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-default-bindings = no
|
||||
///input-ar-delay = 500
|
||||
///input-ar-rate = 20
|
||||
///volume = 50
|
||||
///hwdec = yes
|
||||
///keep-open = yes
|
||||
///keep-open-pause = no
|
||||
///osd-playing-msg = ${filename}
|
||||
///screenshot-directory = ~~desktop/
|
||||
///input-default-bindings = no.
|
||||
///osd-duration = 2000
|
||||
///osd-playing-msg = '${filename}'
|
||||
///script-opts = osc-scalewindowed=1.5,osc-hidetimeout=2000,console-scale=1
|
||||
///screenshot-directory = '~~desktop/'
|
||||
///hwdec = yes
|
||||
///
|
||||
///[protocol.https]
|
||||
///osd-playing-msg = '${media-title}'
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string mpv_conf {
|
||||
get {
|
||||
return ResourceManager.GetString("mpv_conf", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap mpvnet {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("mpvnet", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
///[dark]
|
||||
///
|
||||
///heading = #3C8CC8
|
||||
///foreground = #DDDDDD
|
||||
///foreground2 = #AAAAAA
|
||||
///background = #323232
|
||||
///
|
||||
///menu-foreground = #DDDDDD
|
||||
///menu-background = #323232
|
||||
///menu-highlight = #505050
|
||||
///menu-border = #FFFFFF
|
||||
///menu-checked = #5A5A5A
|
||||
///
|
||||
///
|
||||
///[light]
|
||||
///
|
||||
///heading = #0068B2
|
||||
///foreground = #000000
|
||||
///foreground2 = #4C4C4C
|
||||
///background = #F7F7F7
|
||||
///
|
||||
///menu-foreground = #000000
|
||||
///menu-background = #DFDFDF
|
||||
///menu-highlight = #BFBFBF
|
||||
///menu-border = #6A6A6A
|
||||
///menu-checked = #AAAAAA
|
||||
///.
|
||||
/// </summary>
|
||||
internal static string theme {
|
||||
get {
|
||||
return ResourceManager.GetString("theme", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,10 +118,19 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="editor_toml" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\editor.toml.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<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>
|
||||
</data>
|
||||
<data name="mpvnet" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\mpvnet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</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>
|
||||
<data name="theme" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\theme.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
</root>
|
||||
2
mpv.net/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace mpvnet.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using IronPython.Hosting;
|
||||
using Microsoft.Scripting.Hosting;
|
||||
using VBNET;
|
||||
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)
|
||||
{
|
||||
Msg.ShowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
587
mpv.net/Resources/editor.toml.txt
Normal file
@@ -0,0 +1,587 @@
|
||||
|
||||
[[settings]]
|
||||
name = "hwdec"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
url = "https://mpv.io/manual/master/#options-hwdec"
|
||||
help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
|
||||
options = [{ name = "no", help = "always use software decoding" },
|
||||
{ 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 = "gpu-api"
|
||||
file = "mpv"
|
||||
default = "auto"
|
||||
filter = "Video"
|
||||
help = "Controls which type of graphics APIs will be accepted. Auto uses d3d11, it should only be changed in case of problems, Vulkan is not recommended."
|
||||
options = [{ name = "auto", help = "Use any available API" },
|
||||
{ name = "opengl", help = "Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)" },
|
||||
{ name = "vulkan", help = "Allow only Vulkan (not recommended). " },
|
||||
{ name = "d3d11", help = "Allow only gpu-context=d3d11" }]
|
||||
|
||||
[[settings]]
|
||||
name = "gpu-context"
|
||||
file = "mpv"
|
||||
default = "auto"
|
||||
filter = "Video"
|
||||
options = [{ name = "auto", help = "auto-select" },
|
||||
{ name = "win", help = "Win32/WGL" },
|
||||
{ name = "winvk", help = "VK_KHR_win32_surface" },
|
||||
{ name = "angle", help = "Direct3D11 through the OpenGL ES translation layer ANGLE. This supports almost everything the win backend does (if the ANGLE build is new enough)." },
|
||||
{ name = "dxinterop", help = "(experimental) Win32, using WGL for rendering and Direct3D 9Ex for presentation. Works on Nvidia and AMD. Newer Intel chips with the latest drivers may also work." },
|
||||
{ name = "d3d11", help = "Win32, with native Direct3D 11 rendering." }]
|
||||
|
||||
[[settings]]
|
||||
name = "vo"
|
||||
file = "mpv"
|
||||
default = "gpu"
|
||||
filter = "Video"
|
||||
help = "Video output drivers to be used.\n\nFor more information visit:"
|
||||
url = "https://mpv.io/manual/master/#video-output-drivers-vo"
|
||||
options = [{ name = "gpu", help = "General purpose, customizable, GPU-accelerated video output driver. It supports extended scaling methods, dithering, color management, custom shaders, HDR, and more." },
|
||||
{ name = "direct3d", help = "Video output driver that uses the Direct3D interface" }]
|
||||
|
||||
[[settings]]
|
||||
name = "video-sync"
|
||||
file = "mpv"
|
||||
default = "audio"
|
||||
filter = "Video"
|
||||
help = "How the player synchronizes audio and video.\n\nFor more information visit:"
|
||||
url = "https://mpv.io/manual/master/#options-video-sync"
|
||||
options = [{ name = "audio" },
|
||||
{ name = "display-resample" },
|
||||
{ name = "display-resample-vdrop" },
|
||||
{ name = "display-resample-desync" },
|
||||
{ name = "display-vdrop" },
|
||||
{ name = "display-adrop" },
|
||||
{ name = "display-desync" },
|
||||
{ name = "desync" }]
|
||||
|
||||
[[settings]]
|
||||
name = "scale"
|
||||
file = "mpv"
|
||||
default = "bilinear"
|
||||
filter = "Video"
|
||||
help = "The GPU renderer filter function to use when upscaling video. There are some more filters, but most are not as useful. For a complete list, pass help as value, e.g.: mpv --scale=help"
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
|
||||
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
|
||||
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
|
||||
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
|
||||
{ name = "ewa_lanczossharp", help = "A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default." },
|
||||
{ name = "mitchell", help = "Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale)." },
|
||||
{ name = "oversample", help = "A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as \"smoothmotion\" (see tscale)." },
|
||||
{ name = "linear", help = "A tscale filter." }]
|
||||
|
||||
[[settings]]
|
||||
name = "cscale"
|
||||
file = "mpv"
|
||||
default = "bilinear"
|
||||
filter = "Video"
|
||||
help = "As scale, but for interpolating chroma information. If the image is not subsampled, this option is ignored entirely."
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
|
||||
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
|
||||
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
|
||||
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
|
||||
{ name = "ewa_lanczossharp", help = "A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default." },
|
||||
{ name = "mitchell", help = "Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale)." },
|
||||
{ name = "oversample", help = "A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as \"smoothmotion\" (see tscale)." },
|
||||
{ name = "linear", help = "A tscale filter." }]
|
||||
|
||||
[[settings]]
|
||||
name = "dscale"
|
||||
file = "mpv"
|
||||
default = "bilinear"
|
||||
filter = "Video"
|
||||
help = "Like scale, but apply these filters on downscaling instead. If this option is unset, the filter implied by scale will be applied."
|
||||
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
|
||||
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
|
||||
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
|
||||
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
|
||||
{ name = "ewa_lanczossharp", help = "A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default." },
|
||||
{ name = "mitchell", help = "Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale)." },
|
||||
{ name = "oversample", help = "A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as \"smoothmotion\" (see tscale)." },
|
||||
{ name = "linear", help = "A tscale filter." }]
|
||||
|
||||
[[settings]]
|
||||
name = "dither-depth"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
help = "Set dither target depth to N. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output."
|
||||
options = [{ name = "no", help = "Disable any dithering done by mpv." },
|
||||
{ name = "auto", help = "Automatic selection. If output bit depth cannot be detected, 8 bits per component are assumed." },
|
||||
{ name = "8", help = "Dither to 8 bit output." }]
|
||||
|
||||
[[settings]]
|
||||
name = "correct-downscaling"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
help = "When using convolution based filters, extend the filter size when downscaling. Increases quality, but reduces performance while downscaling.\n\nThis will perform slightly sub-optimally for anamorphic video (but still better than without it) since it will extend the size to match only the milder of the scale factors between the axes."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "sigmoid-upscaling"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
help = "When upscaling, use a sigmoidal color transform to avoid emphasizing ringing artifacts. This also implies linear-scaling."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "deband"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
help = "Enable the debanding algorithm. This greatly reduces the amount of visible banding, blocking and other quantization artifacts, at the expense of very slightly blurring some of the finest details. In practice, it's virtually always an improvement - the only reason to disable it would be for performance."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "d3d11va-zero-copy"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Video"
|
||||
help = "By default, when using hardware decoding with --gpu-api=d3d11, the video image will be copied (GPU-to-GPU) from the decoder surface to a shader resource. Set this option to avoid that copy by sampling directly from the decoder image. This may increase performance and reduce power usage, but can cause the image to be sampled incorrectly on the bottom and right edges due to padding, and may invoke driver bugs, since Direct3D 11 technically does not allow sampling from a decoder surface (though most drivers support it.)"
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "hdr-compute-peak"
|
||||
file = "mpv"
|
||||
default = "auto"
|
||||
filter = "Video"
|
||||
help = "Compute the HDR peak and frame average brightness per-frame instead of relying on tagged metadata. These values are averaged over local regions as well as over several frames to prevent the value from jittering around too much. This option basically gives you dynamic, per-scene tone mapping. Requires compute shaders, which is a fairly recent OpenGL feature, and will probably also perform horribly on some drivers, so enable at your own risk. The special value auto (default) will enable HDR peak computation automatically if compute shaders and SSBOs are supported."
|
||||
options = [{ name = "auto" },
|
||||
{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "volume"
|
||||
file = "mpv"
|
||||
filter = "Audio"
|
||||
help = "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\"). Default: 100"
|
||||
|
||||
[[settings]]
|
||||
name = "remember-volume"
|
||||
file = "mpvnet"
|
||||
default = "yes"
|
||||
filter = "Audio"
|
||||
help = "Save volume and mute on exit and restore it on start. (mpv.net specific setting)"
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "alang"
|
||||
file = "mpv"
|
||||
filter = "Audio"
|
||||
type = "string"
|
||||
help = "Specify a priority list of audio languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two-letter language codes, Matroska, MPEG-TS and NUT use ISO 639-2 three-letter language codes, while OGM uses a free-form identifier. See also aid.\n\nExamples\n\nmpv dvd://1 alang=hu,en chooses the Hungarian language track on a DVD and falls back on English if Hungarian is not available.\n\nmpv alang=jpn example.mkv plays a Matroska file with Japanese audio."
|
||||
|
||||
[[settings]]
|
||||
name = "audio-file-auto"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Audio"
|
||||
help = "Load additional audio files matching the video filename. The parameter specifies how external audio files are matched."
|
||||
options = [{ name = "no", help = "Don't automatically load external audio files." },
|
||||
{ name = "exact", help = "Load the media filename with audio file extension." },
|
||||
{ name = "fuzzy", help = "Load all audio files containing media filename." },
|
||||
{ name = "all", help = "Load all audio files in the current and audio-file-paths directories." }]
|
||||
|
||||
[[settings]]
|
||||
name = "slang"
|
||||
file = "mpv"
|
||||
filter = "Subtitle"
|
||||
type = "string"
|
||||
help = "Specify a priority list of subtitle languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two letter language codes, Matroska uses ISO 639-2 three letter language codes while OGM uses a free-form identifier. See also sid."
|
||||
|
||||
[[settings]]
|
||||
name = "sub-auto"
|
||||
file = "mpv"
|
||||
default = "exact"
|
||||
filter = "Subtitle"
|
||||
help = "Load additional subtitle files matching the video filename. The parameter specifies how external subtitle files are matched. exact is enabled by default."
|
||||
options = [{ name = "no", help = "Don't automatically load external subtitle files." },
|
||||
{ name = "exact", help = "Load the media filename with subtitle file extension." },
|
||||
{ name = "fuzzy", help = "Load all subs containing media filename." },
|
||||
{ name = "all", help = "Load all subs in the current and sub-file-paths directories." }]
|
||||
|
||||
[[settings]]
|
||||
name = "sub-font"
|
||||
file = "mpv"
|
||||
filter = "Subtitle"
|
||||
type = "string"
|
||||
help = "Specify font to use for subtitles that do not themselves specify a particular font. The default is sans-serif."
|
||||
|
||||
[[settings]]
|
||||
name = "sub-font-size"
|
||||
file = "mpv"
|
||||
filter = "Subtitle"
|
||||
help = "Specify the sub font size. The unit is the size in scaled pixels at a window height of 720. The actual pixel size is scaled with the window height: if the window height is larger or smaller than 720, the actual size of the text increases or decreases as well. Default: 55"
|
||||
|
||||
[[settings]]
|
||||
name = "sub-color"
|
||||
file = "mpv"
|
||||
type = "color"
|
||||
filter = "Subtitle"
|
||||
help = "Specify the color used for unstyled text subtitles.\n\nThe color is specified in the form r/g/b, where each color component is specified as number in the range 0.0 to 1.0. It's also possible to specify the transparency by using r/g/b/a, where the alpha value 0 means fully transparent, and 1.0 means opaque. If the alpha component is not given, the color is 100% opaque.\n\nPassing a single number to the option sets the sub to gray, and the form gray/a lets you specify alpha additionally.\n\nExamples\n\n1.0/0.0/0.0 set sub to opaque red\n1.0/0.0/0.0/0.75 set sub to opaque red with 75% alpha\n0.5/0.75 set sub to 50% gray with 75% alpha\n\nAlternatively, the color can be specified as a RGB hex triplet in the form #RRGGBB, where each 2-digit group expresses a color value in the range 0 (00) to 255 (FF). For example, #FF0000 is red. This is similar to web colors. Alpha is given with #AARRGGBB.\n\nExamples\n\n#FF0000 set sub to opaque red\n#C0808080 set sub to 50% gray with 75% alpha"
|
||||
|
||||
[[settings]]
|
||||
name = "sub-border-color"
|
||||
file = "mpv"
|
||||
type = "color"
|
||||
filter = "Subtitle"
|
||||
help = "See sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent)."
|
||||
|
||||
[[settings]]
|
||||
name = "sub-back-color"
|
||||
file = "mpv"
|
||||
type = "color"
|
||||
filter = "Subtitle"
|
||||
help = "See sub-color. Color used for sub text background. You can use sub-shadow-offset to change its size relative to the text."
|
||||
|
||||
[[settings]]
|
||||
name = "fullscreen"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Screen"
|
||||
help = "Start the player in fullscreen mode."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "border"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Screen"
|
||||
help = "Show window with decoration (titlebar, border)."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screen"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<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."
|
||||
|
||||
[[settings]]
|
||||
name = "osd-playing-msg"
|
||||
file = "mpv"
|
||||
width = 300
|
||||
filter = "Screen"
|
||||
type = "string"
|
||||
help = "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. For more information visit:"
|
||||
url = "https://mpv.io/manual/master/#property-expansion"
|
||||
|
||||
[[settings]]
|
||||
name = "osd-font-size"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "Specify the OSD font size. See sub-font-size for details. Default: 55"
|
||||
|
||||
[[settings]]
|
||||
name = "osd-duration"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "Set the duration of the OSD messages in ms. Default: 1000"
|
||||
|
||||
[[settings]]
|
||||
name = "osd-scale-by-window"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Screen"
|
||||
help = "Whether to scale the OSD with the window size. If this is disabled, osd-font-size and other OSD options that use scaled pixels are always in actual pixels. The effect is that changing the window size won't change the OSD font size."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "autofit"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<int> Initial window height in percent. Default: 60"
|
||||
|
||||
[[settings]]
|
||||
name = "autofit-smaller"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<int> Minimum window height in percent. Default: 30"
|
||||
|
||||
[[settings]]
|
||||
name = "autofit-larger"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<int> Maximum window height in percent. Default: 80"
|
||||
|
||||
[[settings]]
|
||||
name = "start-size"
|
||||
file = "mpvnet"
|
||||
default = "previous"
|
||||
filter = "Screen"
|
||||
help = "Setting to remember the window height. (mpv.net specific setting)"
|
||||
options = [{ name = "video", help = "Window size is set to video resolution" },
|
||||
{ name = "previous", help = "Window size is remembered but only in the current session" },
|
||||
{ name = "always", help = "Window size is always remembered"}]
|
||||
|
||||
[[settings]]
|
||||
name = "start-threshold"
|
||||
file = "mpvnet"
|
||||
filter = "Screen"
|
||||
help = "Threshold in milliseconds to wait for libmpv returning the video resolution before the window is shown, otherwise default dimensions are used as defined by autofit and start-size. Default: 1500 (mpv.net specific setting)"
|
||||
|
||||
[[settings]]
|
||||
name = "minimum-aspect-ratio"
|
||||
file = "mpvnet"
|
||||
filter = "Screen"
|
||||
help = "<float> Minimum aspect ratio, if the AR is smaller than the defined value then the window AR is set to 16/9. This avoids a square window for Music with cover art. Default: 1.2 (mpv.net specific setting)"
|
||||
|
||||
[[settings]]
|
||||
name = "remember-position"
|
||||
file = "mpvnet"
|
||||
default = "no"
|
||||
filter = "Screen"
|
||||
help = "Save the window position on exit. (mpv.net specific setting)"
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "window-maximized"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Screen"
|
||||
help = "Start with a maximized window."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-directory"
|
||||
file = "mpv"
|
||||
width = 500
|
||||
type = "folder"
|
||||
filter = "Screen"
|
||||
help = "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."
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-format"
|
||||
file = "mpv"
|
||||
default = "jpg"
|
||||
filter = "Screen"
|
||||
help = "Set the image file type used for saving screenshots."
|
||||
options = [{ name = "jpg" },
|
||||
{ name = "png" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-tag-colorspace"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Screen"
|
||||
help = "Tag screenshots with the appropriate colorspace. Note that not all formats are supported."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-high-bit-depth"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Screen"
|
||||
help = "If possible, write screenshots with a bit depth similar to the source video. This is interesting in particular for PNG, as this sometimes triggers writing 16 bit PNGs with huge file sizes. This will also include an unused alpha channel in the resulting files if 16 bit is used."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-jpeg-source-chroma"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Screen"
|
||||
help = "Write JPEG files with the same chroma subsampling as the video. If disabled, the libjpeg default is used."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-template"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
type = "string"
|
||||
help = "Specify the filename template used to save screenshots. The template specifies the filename without file extension, and can contain format specifiers, which will be substituted when taking a screenshot. By default, the template is mpv-shot%n, which results in filenames like mpv-shot0012.png for example.\n\nFind the full documentation here:"
|
||||
url = "https://mpv.io/manual/master/#options-screenshot-template"
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-jpeg-quality"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<0-100> Set the JPEG quality level. Higher means better quality. The default is 90."
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-png-compression"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<0-9> Set the PNG compression level. Higher means better compression. This will affect the file size of the written screenshot file and the time it takes to write a screenshot. Too high compression might occupy enough CPU time to interrupt playback. The default is 7."
|
||||
|
||||
[[settings]]
|
||||
name = "screenshot-png-filter"
|
||||
file = "mpv"
|
||||
filter = "Screen"
|
||||
help = "<0-5> Set the filter applied prior to PNG compression. 0 is none, 1 is 'sub', 2 is 'up', 3 is 'average', 4 is 'Paeth', and 5 is 'mixed'. This affects the level of compression that can be achieved. For most images, 'mixed' achieves the best compression ratio, hence it is the default."
|
||||
|
||||
[[settings]]
|
||||
name = "taskbar-progress"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "Show progress in taskbar."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "keep-open-pause"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "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."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "keep-open"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Playback"
|
||||
help = "Using no, mpv would terminate after the last file but mpv.net never terminates automatically."
|
||||
options = [{ name = "yes", help = "If the current file ends, go to the next file, keep the last file open."},
|
||||
{ name = "no", help = "If the current file ends, go to the next file." },
|
||||
{ name = "always", help = "Playback will never automatically advance to the next file."}]
|
||||
|
||||
[[settings]]
|
||||
name = "loop-file"
|
||||
file = "mpv"
|
||||
filter = "Playback"
|
||||
help = "<N|inf|no> Loop a single file N times. inf means forever, no means normal playback.\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. loop is an alias for this option."
|
||||
|
||||
[[settings]]
|
||||
name = "save-position-on-quit"
|
||||
file = "mpv"
|
||||
default = "no"
|
||||
filter = "Playback"
|
||||
help = "Always save the current playback position on quit. When this file is played again later, the player will seek to the old playback position on start. This does not happen if playback of a file is stopped in any other way than quitting. For example, going to the next file in the playlist will not save the position, and start playback at beginning the next time the file is played.\n\nThis behavior is disabled by default, but is always available when quitting the player with Shift+Q."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "hr-seek"
|
||||
file = "mpv"
|
||||
default = "absolute"
|
||||
filter = "Playback"
|
||||
help = "Select when to use precise seeks that are not limited to keyframes. Such seeks require decoding video from the previous keyframe up to the target position and so can take some time depending on decoding performance. For some video formats, precise seeks are disabled. This option selects the default choice to use for seeks; it is possible to explicitly override that default in the definition of key bindings and in input commands."
|
||||
options = [{ name = "yes", help = "Use precise seeks whenever possible." },
|
||||
{ name = "no", help = "Never use precise seeks." },
|
||||
{ name = "absolute", help = "Use precise seeks if the seek is to an absolute position in the file, such as a chapter seek, but not for relative seeks like the default behavior of arrow keys." },
|
||||
{ name = "always", help = "Same as yes (for compatibility)." }]
|
||||
|
||||
[[settings]]
|
||||
name = "track-auto-selection"
|
||||
file = "mpv"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "Enable the default track auto-selection. Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected."
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "loop-playlist"
|
||||
file = "mpv"
|
||||
filter = "Playback"
|
||||
help = "<N|inf|force|no> Loops playback N times. A value of 1 plays it one time (default), 2 two times, etc. inf means forever. no is the same as 1 and disables looping. If several files are specified on command line, the entire playlist is looped. The force mode is like inf, but does not skip playlist entries which have been marked as failing. This means the player might waste CPU time trying to loop a file that doesn't exist. But it might be useful for playing webradios under very bad network conditions."
|
||||
|
||||
[[settings]]
|
||||
name = "auto-load-folder"
|
||||
file = "mpvnet"
|
||||
default = "yes"
|
||||
filter = "Playback"
|
||||
help = "For single files automatically load the entire directory into the playlist. Can be suppressed via shift key. (mpv.net specific setting)"
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "input-ar-delay"
|
||||
file = "mpv"
|
||||
filter = "Input"
|
||||
help = "Delay in milliseconds before we start to autorepeat a key (0 to disable)."
|
||||
|
||||
[[settings]]
|
||||
name = "input-ar-rate"
|
||||
file = "mpv"
|
||||
filter = "Input"
|
||||
help = "Number of key presses to generate per second on autorepeat."
|
||||
|
||||
[[settings]]
|
||||
name = "update-check"
|
||||
file = "mpvnet"
|
||||
default = "no"
|
||||
filter = "General"
|
||||
help = "Daily check for new version. (requires PowerShell 5 and curl. mpv.net specific setting)"
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "process-instance"
|
||||
file = "mpvnet"
|
||||
default = "single"
|
||||
filter = "General"
|
||||
help = "Defines if more then one mpv.net process is allowed. (mpv.net specific setting)\n\nTip: Whenever the control key is pressed when files or URLs are opened, the playlist is not cleared but the files or URLs are appended to the playlist. This not only works on process startup but in all mpv.net features that open files and URLs."
|
||||
options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" },
|
||||
{ name = "single", help = "Force a single process everytime the shell starts mpv.net" },
|
||||
{ name = "queue", help = "Force a single process and add files to playlist" }]
|
||||
|
||||
[[settings]]
|
||||
name = "recent-count"
|
||||
file = "mpvnet"
|
||||
filter = "General"
|
||||
help = "<int> Amount of recent files to be remembered. Default: 15 (mpv.net specific setting)"
|
||||
|
||||
[[settings]]
|
||||
name = "debug-mode"
|
||||
file = "mpvnet"
|
||||
default = "no"
|
||||
filter = "General"
|
||||
help = "Enable this only when a developer asks for it. (mpv.net specific setting)"
|
||||
options = [{ name = "yes" },
|
||||
{ name = "no" }]
|
||||
|
||||
[[settings]]
|
||||
name = "dark-mode"
|
||||
file = "mpvnet"
|
||||
default = "always"
|
||||
filter = "UI"
|
||||
help = "Enables a dark theme. (mpv.net specific setting)"
|
||||
options = [{ name = "always" },
|
||||
{ name = "system" , help = "Available on Windows 10 or higher" },
|
||||
{ name = "never" }]
|
||||
|
||||
[[settings]]
|
||||
name = "dark-theme"
|
||||
file = "mpvnet"
|
||||
filter = "UI"
|
||||
url = "https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme"
|
||||
help = "Color theme used in dark mode. Default: dark"
|
||||
|
||||
[[settings]]
|
||||
name = "light-theme"
|
||||
file = "mpvnet"
|
||||
filter = "UI"
|
||||
url = "https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme"
|
||||
help = "Color theme used in light mode. Default: light"
|
||||
@@ -1,34 +1,43 @@
|
||||
|
||||
# This file defines the input (keys and mouse) bindings of mpv and mpv.net
|
||||
# and it also defines the context menu of mpv.net. mpv.net has an input
|
||||
# editor and an conf editor as alternatives to editing conf text files.
|
||||
# The input and conf editors can be found in mpv.net's context menu at:
|
||||
# This file defines the key and mouse bindings and the context menu of mpv.net.
|
||||
|
||||
# A convenient input and config editor can be found in the context menu of mpv.net
|
||||
# under 'Settings'.
|
||||
|
||||
# The mpv.conf defaults of mpv.net contain: 'input-default-bindings = no'
|
||||
# which disables the input defaults of mpv. Every line in this file begins with a
|
||||
# space character to make it easier to do a text search, so if you want to know
|
||||
# if 'o' has already a binding you can do a text search on ' o '.
|
||||
|
||||
# Settings > Show Config Editor
|
||||
# Settings > Show Input Editor
|
||||
# input test mode:
|
||||
# mpvnet --input-test
|
||||
|
||||
# The defaults of this file can be found at:
|
||||
# input key list:
|
||||
# mpv --input-keylist
|
||||
|
||||
# mpv.net input.conf defaults:
|
||||
# https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt
|
||||
|
||||
# the defaults of mpv can be found at:
|
||||
|
||||
# mpv input.conf defaults:
|
||||
# https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||
|
||||
# mpv.net's defaults of mpv.conf contain: 'input-default-bindings = no'
|
||||
# which disables mpv's input defaults. Every line in this file begins with a
|
||||
# space character to make it easier to do a text search, so if you want to know
|
||||
# if 'o' has already a binding you can make a text search on ' o '.
|
||||
# mpv input commands:
|
||||
# https://mpv.io/manual/master/#list-of-input-commands
|
||||
|
||||
# mpv input commands: https://github.com/stax76/mpv.net/wiki/mpv-input-commands
|
||||
# mpv input options:
|
||||
# https://mpv.io/manual/master/#input
|
||||
|
||||
# mpv input keys: https://github.com/stax76/mpv.net/wiki/mpv-input-keys
|
||||
|
||||
o script-message mpv.net open-files #menu: Open > Open Files...
|
||||
u script-message mpv.net open-url #menu: Open > Open URL...
|
||||
_ ignore #menu: Open > -
|
||||
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
|
||||
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
|
||||
o script-message mpv.net open-files #menu: Open > Open Files...
|
||||
u script-message mpv.net open-url #menu: Open > Open URL or file path from clipboard
|
||||
_ script-message mpv.net open-optical-media #menu: Open > Open DVD/Blu-ray Drive/Folder...
|
||||
_ ignore #menu: Open > -
|
||||
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
|
||||
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
|
||||
_ ignore #menu: Open > -
|
||||
_ script-message mpv.net open-files append #menu: Open > Add files to playlist...
|
||||
F3 script-message mpv.net show-media-search #menu: Open > Show media search...
|
||||
_ ignore #menu: Open > -
|
||||
_ ignore #menu: Open > Recent
|
||||
|
||||
_ ignore #menu: -
|
||||
Space cycle pause #menu: Play/Pause
|
||||
@@ -36,8 +45,11 @@
|
||||
_ ignore #menu: -
|
||||
Enter cycle fullscreen #menu: Toggle Fullscreen
|
||||
|
||||
F11 playlist-prev #menu: Navigate > Previous
|
||||
F12 playlist-next #menu: Navigate > Next
|
||||
F11 playlist-prev #menu: Navigate > Previous File
|
||||
F12 playlist-next #menu: Navigate > Next File
|
||||
_ ignore #menu: Navigate > -
|
||||
Home script-message mpv.net playlist-first #menu: Navigate > First File
|
||||
End script-message mpv.net playlist-last #menu: Navigate > Last File
|
||||
_ ignore #menu: Navigate > -
|
||||
PGUP add chapter 1 #menu: Navigate > Next Chapter
|
||||
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
|
||||
@@ -45,14 +57,14 @@
|
||||
. frame-step #menu: Navigate > Jump Next Frame
|
||||
, frame-back-step #menu: Navigate > Jump Previous Frame
|
||||
_ ignore #menu: Navigate > -
|
||||
Right no-osd seek 7 #menu: Navigate > Jump 7 sec forward
|
||||
Left no-osd seek -7 #menu: Navigate > Jump 7 sec backward
|
||||
Right seek 7 #menu: Navigate > Jump 7 sec forward
|
||||
Left seek -7 #menu: Navigate > Jump 7 sec backward
|
||||
_ ignore #menu: Navigate > -
|
||||
Up no-osd seek 40 #menu: Navigate > Jump 40 sec forward
|
||||
Down no-osd seek -40 #menu: Navigate > Jump 40 sec backward
|
||||
Up seek 40 #menu: Navigate > Jump 40 sec forward
|
||||
Down seek -40 #menu: Navigate > Jump 40 sec backward
|
||||
_ ignore #menu: Navigate > -
|
||||
Ctrl+Right no-osd seek 300 #menu: Navigate > Jump 5 min forward
|
||||
Ctrl+Left no-osd seek -300 #menu: Navigate > Jump 5 min backward
|
||||
Ctrl+Right seek 300 #menu: Navigate > Jump 5 min forward
|
||||
Ctrl+Left seek -300 #menu: Navigate > Jump 5 min backward
|
||||
_ ignore #menu: Navigate > -
|
||||
_ ignore #menu: Navigate > Chapters
|
||||
|
||||
@@ -71,7 +83,7 @@
|
||||
Ctrl+BS set video-zoom 0; set video-pan-x 0; set video-pan-y 0 #menu: Pan & Scan > Reset
|
||||
|
||||
Ctrl+1 add contrast -1 #menu: Video > Decrease Contrast
|
||||
Ctrl+2 add contrast #menu: Video > Increase Contrast
|
||||
Ctrl+2 add contrast 1 #menu: Video > Increase Contrast
|
||||
_ ignore #menu: Video > -
|
||||
Ctrl+3 add brightness -1 #menu: Video > Decrease Brightness
|
||||
Ctrl+4 add brightness 1 #menu: Video > Increase Brightness
|
||||
@@ -88,8 +100,8 @@
|
||||
|
||||
KP7 script-message mpv.net cycle-audio #menu: Audio > Cycle/Next
|
||||
_ ignore #menu: Audio > -
|
||||
KP6 add audio-delay 0.100 #menu: Audio > Delay +0.1
|
||||
KP9 add audio-delay -0.100 #menu: Audio > Delay -0.1
|
||||
KP6 add audio-delay 0.1 #menu: Audio > Delay +0.1
|
||||
KP9 add audio-delay -0.1 #menu: Audio > Delay -0.1
|
||||
|
||||
KP8 cycle sub #menu: Subtitle > Cycle/Next
|
||||
v cycle sub-visibility #menu: Subtitle > Toggle Visibility
|
||||
@@ -110,7 +122,7 @@
|
||||
_ ignore #menu: Volume > -
|
||||
m cycle mute #menu: Volume > Mute
|
||||
|
||||
[ multiply speed 0.9 #menu: Speed > -10%
|
||||
[ multiply speed 1/1.1 #menu: Speed > -10%
|
||||
] multiply speed 1.1 #menu: Speed > +10%
|
||||
_ ignore #menu: Speed > -
|
||||
{ multiply speed 0.5 #menu: Speed > Half
|
||||
@@ -124,47 +136,71 @@
|
||||
KP3 script-message rate-file 3 #menu: Extensions > Rating > 3stars
|
||||
KP4 script-message rate-file 4 #menu: Extensions > Rating > 4stars
|
||||
KP5 script-message rate-file 5 #menu: Extensions > Rating > 5stars
|
||||
_ ignore #menu: Extensions > Rating > -
|
||||
_ script-message rate-file about #menu: Extensions > Rating > About
|
||||
|
||||
Ctrl+t set ontop yes #menu: View > On Top > Enable
|
||||
Ctrl+T set ontop no #menu: View > On Top > Disable
|
||||
i script-message mpv.net show-info #menu: View > File Info
|
||||
t script-binding stats/display-stats #menu: View > Show Statistics
|
||||
T script-binding stats/display-stats-toggle #menu: View > Toggle Statistics
|
||||
Del script-binding osc/visibility #menu: View > Toggle OSC Visibility
|
||||
F8 show-text ${playlist} 5000 #menu: View > Show Playlist
|
||||
F9 show-text ${track-list} 5000 #menu: View > Show Audio/Video/Subtitle List
|
||||
Ctrl+t set ontop yes #menu: View > On Top > Enable
|
||||
Ctrl+T set ontop no #menu: View > On Top > Disable
|
||||
Alt++ no-osd set window-scale 1.2 #menu: View > Window Size > Enlarge
|
||||
Alt+- no-osd set window-scale 0.8 #menu: View > Window Size > Shrink
|
||||
b cycle border #menu: View > Toggle Border
|
||||
i script-message mpv.net show-info #menu: View > File/Stream Info
|
||||
t script-binding stats/display-stats #menu: View > Show Statistics
|
||||
T script-binding stats/display-stats-toggle #menu: View > Toggle Statistics
|
||||
Del script-binding osc/visibility #menu: View > Toggle OSC Visibility
|
||||
F8 script-binding show-playlist #menu: View > Show Playlist
|
||||
F9 show-text ${track-list} 5000 #menu: View > Show Audio/Video/Subtitle List
|
||||
p show-progress #menu: View > Show Progress
|
||||
Ctrl+p script-message mpv.net show-profiles #menu: View > Show Profiles
|
||||
Shift+p script-message mpv.net show-properties #menu: View > Show Properties
|
||||
Shift+c script-message mpv.net show-commands #menu: View > Show Commands
|
||||
` script-binding console/enable #menu: View > Show Console
|
||||
|
||||
Ctrl+c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
|
||||
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor
|
||||
Ctrl+f script-message mpv.net open-conf-folder #menu: Settings > Open Config Folder
|
||||
c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
|
||||
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor
|
||||
Ctrl+f script-message mpv.net open-conf-folder #menu: Settings > Open Config Folder
|
||||
|
||||
h script-message mpv.net show-history #menu: Tools > Show History
|
||||
l ab-loop #menu: Tools > Set/clear A-B loop points
|
||||
L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping
|
||||
Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Cycle Hardware Decoding
|
||||
_ script-message mpv.net execute-mpv-command #menu: Tools > Execute mpv command...
|
||||
F1 script-message mpv.net show-command-palette #menu: Tools > Show All Commands
|
||||
h script-message mpv.net show-history #menu: Tools > Show History
|
||||
l ab-loop #menu: Tools > Set/clear A-B loop points
|
||||
L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping
|
||||
_ cycle shuffle #menu: Tools > Toggle Shuffle
|
||||
Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Toggle Hardware Decoding
|
||||
_ script-message mpv.net show-setup-dialog #menu: Tools > Setup...
|
||||
|
||||
_ 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
|
||||
_ script-message mpv.net shell-execute https://mpv.io #menu: Help > Website mpv
|
||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net #menu: Help > Website mpv.net
|
||||
_ ignore #menu: Help > -
|
||||
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Manual mpv
|
||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/Manual.md #menu: Help > Manual mpv.net
|
||||
_ ignore #menu: Help > -
|
||||
_ script-message mpv.net update-check #menu: Help > Check for Updates
|
||||
_ script-message mpv.net show-about #menu: Help > About mpv.net
|
||||
|
||||
_ ignore #menu: -
|
||||
Esc quit #menu: Exit
|
||||
Q quit-watch-later #menu: Exit Watch Later
|
||||
> playlist-next
|
||||
< playlist-prev
|
||||
Power quit
|
||||
Play cycle pause
|
||||
Pause cycle pause
|
||||
PlayPause cycle pause
|
||||
Stop stop
|
||||
Forward seek 60
|
||||
Rewind seek -60
|
||||
Mute cycle mute
|
||||
Volume_Up add volume 10
|
||||
Volume_Down add volume -10
|
||||
Wheel_Up add volume 10
|
||||
Wheel_Down add volume -10
|
||||
Prev playlist-prev
|
||||
Next playlist-next
|
||||
|
||||
Power quit
|
||||
Play cycle pause
|
||||
Pause cycle pause
|
||||
PlayPause cycle pause
|
||||
MBTN_Mid cycle pause
|
||||
Stop stop
|
||||
Forward seek 60
|
||||
Rewind seek -60
|
||||
Wheel_Up add volume 10
|
||||
Wheel_Down add volume -10
|
||||
Wheel_Left add volume -10
|
||||
Wheel_Right add volume 10
|
||||
Prev playlist-prev
|
||||
Next playlist-next
|
||||
MBTN_Forward playlist-next
|
||||
MBTN_Back playlist-prev
|
||||
> playlist-next
|
||||
< playlist-prev
|
||||
Ctrl+Wheel_Up no-osd seek 7
|
||||
Ctrl+Wheel_Down no-osd seek -7
|
||||
MBTN_Left_DBL cycle fullscreen
|
||||
KP_Enter cycle fullscreen
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
|
||||
# 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-default-bindings = no
|
||||
input-ar-delay = 500
|
||||
input-ar-rate = 20
|
||||
volume = 50
|
||||
hwdec = yes
|
||||
keep-open = yes
|
||||
keep-open-pause = no
|
||||
osd-playing-msg = ${filename}
|
||||
screenshot-directory = ~~desktop/
|
||||
input-default-bindings = no
|
||||
osd-duration = 2000
|
||||
osd-playing-msg = '${filename}'
|
||||
script-opts = osc-scalewindowed=1.5,osc-hidetimeout=2000,console-scale=1
|
||||
screenshot-directory = '~~desktop/'
|
||||
hwdec = yes
|
||||
|
||||
[protocol.https]
|
||||
osd-playing-msg = '${media-title}'
|
||||
|
||||
BIN
mpv.net/Resources/mpvnet.ico
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
mpv.net/Resources/mpvnet.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
27
mpv.net/Resources/theme.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
[dark]
|
||||
|
||||
heading = #3C8CC8
|
||||
foreground = #DDDDDD
|
||||
foreground2 = #AAAAAA
|
||||
background = #323232
|
||||
|
||||
menu-foreground = #DDDDDD
|
||||
menu-background = #323232
|
||||
menu-highlight = #505050
|
||||
menu-border = #FFFFFF
|
||||
menu-checked = #5A5A5A
|
||||
|
||||
|
||||
[light]
|
||||
|
||||
heading = #0068B2
|
||||
foreground = #000000
|
||||
foreground2 = #4C4C4C
|
||||
background = #F7F7F7
|
||||
|
||||
menu-foreground = #000000
|
||||
menu-background = #DFDFDF
|
||||
menu-highlight = #BFBFBF
|
||||
menu-border = #6A6A6A
|
||||
menu-checked = #AAAAAA
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace mpvnet
|
||||
{
|
||||
public class CursorHelp
|
||||
{
|
||||
static bool IsVisible = true;
|
||||
|
||||
public static void Show()
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
Cursor.Show();
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Hide()
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
Cursor.Hide();
|
||||
IsVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPosDifferent(Point screenPos)
|
||||
{
|
||||
return
|
||||
Math.Abs(screenPos.X - Control.MousePosition.X) > 10 ||
|
||||
Math.Abs(screenPos.Y - Control.MousePosition.Y) > 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
mpv.net/Update.ps1
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if ($args.Length -ne 2) {
|
||||
Write-Host 'Invalid arguments' -ForegroundColor Red
|
||||
exit
|
||||
}
|
||||
|
||||
if (-not (Get-Command curl.exe)) {
|
||||
Write-Host 'Error using curl.exe' -ForegroundColor Red
|
||||
exit
|
||||
}
|
||||
|
||||
if ($PSVersionTable.PSVersion.Major -lt 5) {
|
||||
Write-Host 'PowerShell 5.1 not found' -ForegroundColor Red
|
||||
exit
|
||||
}
|
||||
|
||||
Add-Type -AssemblyName Microsoft.VisualBasic
|
||||
|
||||
# Delete directory using recycle bin
|
||||
function Remove-Directory($directory) {
|
||||
if (Test-Path $directory) {
|
||||
[Microsoft.VisualBasic.FileIO.FileSystem]::
|
||||
DeleteDirectory($directory, 'OnlyErrorDialogs', 'SendToRecycleBin')
|
||||
}
|
||||
}
|
||||
|
||||
$currentDir = $args[1];
|
||||
|
||||
$targetDir = (Split-Path $currentDir) + "\new version"
|
||||
Remove-Directory $targetDir
|
||||
$targetFile = $targetDir + '.7z'
|
||||
Remove-Item $targetFile -Force -ErrorAction Ignore
|
||||
|
||||
Write-Host 'Download new version' -ForegroundColor Green
|
||||
curl.exe $args[0] --location --output $targetFile
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
Write-Host 'Unpack new version' -ForegroundColor Green
|
||||
& ($currentDir + '\7z\7za.exe') x -y $targetFile -o"$targetDir"
|
||||
if ($LastExitCode) { throw $LastExitCode }
|
||||
|
||||
Write-Host 'Delete downloaded file' -ForegroundColor Green
|
||||
Remove-Item $targetFile -Force -Recurse
|
||||
|
||||
$portableConfigDir = $currentDir + '\portable_config'
|
||||
$portableConfigTempDir = (Split-Path $currentDir) + '\portable config dir temp'
|
||||
Remove-Item $portableConfigTempDir -Force -ErrorAction Ignore
|
||||
|
||||
if (Test-Path $portableConfigDir) {
|
||||
Write-Host 'Backup portable config' -ForegroundColor Green
|
||||
Copy-Item $portableConfigDir $portableConfigTempDir -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Host 'Delete current version' -ForegroundColor Green
|
||||
Remove-Directory $currentDir
|
||||
|
||||
Write-Host 'Rename directory' -ForegroundColor Green
|
||||
Rename-Item $targetDir (Split-Path $currentDir -Leaf)
|
||||
|
||||
if (Test-Path $portableConfigTempDir) {
|
||||
Write-Host 'Restore portable config' -ForegroundColor Green
|
||||
Move-Item $portableConfigTempDir $portableConfigDir -Force
|
||||
}
|
||||
|
||||
Write-Host 'Update is complete' -ForegroundColor Green
|
||||