Compare commits
168 Commits
v6.0.3.0
...
v7.0.0.5-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17e25619da | ||
|
|
a4376b1492 | ||
|
|
d41faad9d9 | ||
|
|
0e6116b478 | ||
|
|
789127e8ff | ||
|
|
6ef9f32d4f | ||
|
|
1048dbed40 | ||
|
|
86c823bfde | ||
|
|
764f00ed3a | ||
|
|
3e4ea03437 | ||
|
|
0ef679e00d | ||
|
|
7f2bf2e905 | ||
|
|
ab8a8d5a35 | ||
|
|
a3b9c653fa | ||
|
|
ed48f5c559 | ||
|
|
d328f6b7ec | ||
|
|
16ba94d67d | ||
|
|
7978170133 | ||
|
|
ab313eb442 | ||
|
|
f40008d94a | ||
|
|
75e19d8d18 | ||
|
|
9bb978f612 | ||
|
|
7ea3fbc917 | ||
|
|
3af5b458ba | ||
|
|
b23542d681 | ||
|
|
e0616dee76 | ||
|
|
cd54e67b87 | ||
|
|
9d4779fd96 | ||
|
|
d4d147e5fc | ||
|
|
35b17bc620 | ||
|
|
3eb4af5e75 | ||
|
|
49f22a1f81 | ||
|
|
7cd5686488 | ||
|
|
0d63feec57 | ||
|
|
0ee8318ca4 | ||
|
|
8e45cdb47d | ||
|
|
a61a0506fd | ||
|
|
b3877492dd | ||
|
|
090f15fc47 | ||
|
|
d57692c5d1 | ||
|
|
60dfbee16d | ||
|
|
74f586744f | ||
|
|
9b93eaa9e9 | ||
|
|
a4eed2d939 | ||
|
|
34a3855941 | ||
|
|
dfd9abeba4 | ||
|
|
f937273fe3 | ||
|
|
8d601525b5 | ||
|
|
5dd3716012 | ||
|
|
a4709de918 | ||
|
|
c24b9b2c83 | ||
|
|
3686231cf2 | ||
|
|
4c12097063 | ||
|
|
da7f877f2a | ||
|
|
1dbb1e4af9 | ||
|
|
abea225b54 | ||
|
|
2053042e19 | ||
|
|
a3046258d4 | ||
|
|
207da8d0a6 | ||
|
|
f7ed3bf01f | ||
|
|
3c8cd407e1 | ||
|
|
ea56b6d06c | ||
|
|
d4c4296196 | ||
|
|
1b4be52ce6 | ||
|
|
286686f8c4 | ||
|
|
146852ca19 | ||
|
|
3f6181f77b | ||
|
|
8997a2eacb | ||
|
|
a6642a4db8 | ||
|
|
8a8ac75b29 | ||
|
|
1cc2422117 | ||
|
|
0fa3feef1f | ||
|
|
3ae923ba0e | ||
|
|
11e150b0f9 | ||
|
|
1ed8c234a3 | ||
|
|
948e600f96 | ||
|
|
1050e7d25f | ||
|
|
2ff1b07449 | ||
|
|
4466217063 | ||
|
|
01adf213bc | ||
|
|
c1308434b1 | ||
|
|
e854598cd2 | ||
|
|
f6ca5a3b96 | ||
|
|
8fe196bf8a | ||
|
|
3abb3c32f0 | ||
|
|
867c9c2989 | ||
|
|
c1c8e08c9d | ||
|
|
bdcfa4e722 | ||
|
|
7879bda5c1 | ||
|
|
ef062d1b10 | ||
|
|
8b6204ed2b | ||
|
|
f14d1a98f9 | ||
|
|
9ec518a952 | ||
|
|
8ee67f832c | ||
|
|
684e103e12 | ||
|
|
1d3fe0a924 | ||
|
|
b41ca3cd89 | ||
|
|
aa0e88129b | ||
|
|
4baa26d7a0 | ||
|
|
4c4088b28a | ||
|
|
ea8944c1cc | ||
|
|
d7e1e32654 | ||
|
|
9878e6da46 | ||
|
|
37320fb975 | ||
|
|
0148a71281 | ||
|
|
9f4baa9d99 | ||
|
|
5706d7b66d | ||
|
|
fb27bb8727 | ||
|
|
80c827974a | ||
|
|
d2e7d4551f | ||
|
|
308e3ed044 | ||
|
|
f563342eb5 | ||
|
|
16d6e4d471 | ||
|
|
030aa930a1 | ||
|
|
3a6df857da | ||
|
|
7d9340d9d5 | ||
|
|
9dca27c941 | ||
|
|
6f2b30f762 | ||
|
|
89be723132 | ||
|
|
ec1dde650f | ||
|
|
dbf1a32580 | ||
|
|
a81ed58983 | ||
|
|
33df960d04 | ||
|
|
337bee9f28 | ||
|
|
e57c41a254 | ||
|
|
62d06c65ab | ||
|
|
e70a935d7a | ||
|
|
c8e6ce678a | ||
|
|
22960af78b | ||
|
|
95e31a1d3f | ||
|
|
06ff83b75c | ||
|
|
1f6025a10f | ||
|
|
00bfa20fac | ||
|
|
1475d5ee66 | ||
|
|
b73d2e7107 | ||
|
|
a7fa76d63a | ||
|
|
e2c720346a | ||
|
|
01a853e865 | ||
|
|
6510de2bd8 | ||
|
|
7fc1de2ce3 | ||
|
|
b0d399e9ee | ||
|
|
7f680829ef | ||
|
|
603f956261 | ||
|
|
6d06df9004 | ||
|
|
5ea086d05b | ||
|
|
1ad819fa9d | ||
|
|
f2dd6205b5 | ||
|
|
b2a3c231ff | ||
|
|
f6c223a411 | ||
|
|
e7a2ba6805 | ||
|
|
5a08d9ccd6 | ||
|
|
5714a5e62a | ||
|
|
def7e5ac5a | ||
|
|
601bb20492 | ||
|
|
59600df977 | ||
|
|
e1b9730e9b | ||
|
|
e378551938 | ||
|
|
a82b2ef571 | ||
|
|
6157a01701 | ||
|
|
ec17ae8ce9 | ||
|
|
f719528017 | ||
|
|
966b45eb65 | ||
|
|
eeae6994a2 | ||
|
|
07809d882f | ||
|
|
e970f0b4e4 | ||
|
|
a36b6a3fdf | ||
|
|
4febca257f | ||
|
|
9d493b4d08 |
1
.github/FUNDING.yml
vendored
@@ -1,3 +1,2 @@
|
|||||||
github: stax76
|
github: stax76
|
||||||
patreon: stax76
|
|
||||||
ko_fi: stax76
|
ko_fi: stax76
|
||||||
|
|||||||
30
.github/ISSUE_TEMPLATE/ask-a-question.md
vendored
@@ -8,3 +8,33 @@ assignees: stax76
|
|||||||
---
|
---
|
||||||
|
|
||||||
This template is meant for usage questions of mpv.net.
|
This template is meant for usage questions of mpv.net.
|
||||||
|
|
||||||
|
Some type of questions like questions about a problem require filling out an issue template:
|
||||||
|
|
||||||
|
**Describe the problem**
|
||||||
|
A clear and concise description of what the problem is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
To reproduce, try the last beta version using the CLI option `--config=no`.
|
||||||
|
|
||||||
|
In case of an audio or video problem, try to reproduce the problem using mpv instead of mpv.net.
|
||||||
|
If it can be reproduced with mpv, use the [mpv issue tracker](https://github.com/mpv-player/mpv/issues).
|
||||||
|
|
||||||
|
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.
|
||||||
|
1. mpv.net version
|
||||||
|
2. Windows version
|
||||||
|
3. GPU name
|
||||||
|
4. Media info
|
||||||
|
|||||||
9
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
@@ -11,6 +11,11 @@ assignees: stax76
|
|||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
|
To reproduce, try the last beta version using the CLI option `--config=no`.
|
||||||
|
|
||||||
|
In case of an audio or video issue, try to reproduce the issue using mpv instead of mpv.net.
|
||||||
|
If it can be reproduced with mpv, use the [mpv issue tracker](https://github.com/mpv-player/mpv/issues).
|
||||||
|
|
||||||
Steps to reproduce the behavior:
|
Steps to reproduce the behavior:
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
@@ -25,3 +30,7 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
1. mpv.net version
|
||||||
|
2. Windows version
|
||||||
|
3. GPU name
|
||||||
|
4. Media info
|
||||||
|
|||||||
75
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
name: mpvnet build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- ci
|
||||||
|
paths-ignore:
|
||||||
|
- '*.md'
|
||||||
|
- 'LICENSE'
|
||||||
|
- '.gitignore'
|
||||||
|
- '.gitattributes'
|
||||||
|
- 'docs/**'
|
||||||
|
- '.github/**'
|
||||||
|
- 'src/Extensions/**'
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
paths-ignore:
|
||||||
|
- '*.md'
|
||||||
|
- 'LICENSE'
|
||||||
|
- '.gitignore'
|
||||||
|
- '.gitattributes'
|
||||||
|
- 'docs/**'
|
||||||
|
- '.github/**'
|
||||||
|
- 'src/Extensions/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
windows:
|
||||||
|
name: Windows build
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Add msbuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: mingw64
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
base-devel
|
||||||
|
wget
|
||||||
|
p7zip
|
||||||
|
- name: Build
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd src
|
||||||
|
nuget restore
|
||||||
|
msbuild -restore
|
||||||
|
msbuild MpvNet.sln /m /p:Configuration=Debug
|
||||||
|
- name: Create .mo files for localization
|
||||||
|
shell: pwsh
|
||||||
|
run: Install-Package Gettext.Tools -Force; .\lang\create-mo-files.ps1
|
||||||
|
- name: Download libmpv # In principle, only update this binary file when significant feature changes occur in mpv/mpv.net
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
wget -nv -O libmpv.7z https://downloads.sourceforge.net/mpv-player-windows/mpv-dev-x86_64-20231203-git-f551a9d.7z
|
||||||
|
7z x -y libmpv.7z -olibmpv
|
||||||
|
cp -f libmpv/libmpv-2.dll src/MpvNet.Windows/bin/Debug/ || true
|
||||||
|
- name: Download MediaInfo
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
wget -nv -O MediaInfo.7z https://mediaarea.net/download/binary/libmediainfo0/23.11/MediaInfo_DLL_23.11_Windows_x64_WithoutInstaller.7z
|
||||||
|
7z x -y MediaInfo.7z -oMediaInfo
|
||||||
|
cp -f MediaInfo/MediaInfo.dll src/MpvNet.Windows/bin/Debug/ || true
|
||||||
|
- name: Download mpvnet.com file
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
wget -nv -O mpvnet.com https://github.com/mpvnet-player/file-host/releases/download/tag/mpvnet.com.txt
|
||||||
|
cp -f mpvnet.com src/MpvNet.Windows/bin/Debug/ || true
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: "mpv.net-win64"
|
||||||
|
path: src/MpvNet.Windows/bin/Debug/
|
||||||
9
.tx/config
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
[main]
|
||||||
|
host = https://app.transifex.com
|
||||||
|
|
||||||
|
[o:stax76:p:mpvnet:r:mpvnet]
|
||||||
|
file_filter = lang/po/<lang>.po
|
||||||
|
source_file = lang/source.pot
|
||||||
|
source_lang = en
|
||||||
|
type = PO
|
||||||
64
README.md
@@ -6,19 +6,12 @@
|
|||||||
🎞 mpv.net
|
🎞 mpv.net
|
||||||
==========
|
==========
|
||||||
|
|
||||||
mpv.net is a modern desktop media player for Windows based on the popular [mpv](https://mpv.io) player.
|
mpv.net is a media player for Windows that has a modern GUI.
|
||||||
|
|
||||||
mpv.net is designed to be mpv compatible, almost all mpv features are available
|
The player is based on the popular [mpv](https://mpv.io) media player.
|
||||||
because they are all contained in libmpv, this means the official
|
mpv.net is designed to be mpv compatible, almost all mpv features are available,
|
||||||
[mpv manual](https://mpv.io/manual/master/) applies to mpv.net.
|
this means the official [mpv manual](https://mpv.io/manual/master/) applies to mpv.net,
|
||||||
|
differences are documented in the [mpv.net manual](docs/manual.md#differences-compared-to-mpv).
|
||||||
mpv focuses on the usage of the command line and the terminal,
|
|
||||||
mpv.net retains the ability to be used from the command line and
|
|
||||||
the terminal and adds a modern Windows GUI on top of it.
|
|
||||||
|
|
||||||
Like mpv, mpv.net is designed for power users, for regular users there is a
|
|
||||||
[mpv.net-next](https://github.com/mpv-net-player/mpv.net-next)
|
|
||||||
project under construction.
|
|
||||||
|
|
||||||
#### Graphical User Interface
|
#### Graphical User Interface
|
||||||
|
|
||||||
@@ -47,11 +40,6 @@ Play controls with a modern flat design.
|
|||||||
Leverages the FFmpeg hwaccel APIs to support DXVA2 video decoding acceleration.
|
Leverages the FFmpeg hwaccel APIs to support DXVA2 video decoding acceleration.
|
||||||
|
|
||||||
|
|
||||||
#### Active development
|
|
||||||
|
|
||||||
mpv.net is under active development.
|
|
||||||
|
|
||||||
|
|
||||||
#### Based on libmpv
|
#### Based on libmpv
|
||||||
|
|
||||||
mpv.net is based on libmpv which offers a straightforward C API that
|
mpv.net is based on libmpv which offers a straightforward C API that
|
||||||
@@ -73,11 +61,10 @@ Table of contents
|
|||||||
Features that mpv and mpv.net have in common
|
Features that mpv and mpv.net have in common
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
- Lua and JavaScript Scripting
|
- Lua and JavaScript Scripting ([awesome-mpv lists a large collection of available user scripts](https://github.com/stax76/awesome-mpv))
|
||||||
- Hundreds available user scripts make mpv the most feature rich desktop video player
|
|
||||||
- Simple config files that are easy to read and edit
|
- Simple config files that are easy to read and edit
|
||||||
- JSON IPC to control the player with a external programs
|
- JSON IPC to control the player with a external programs
|
||||||
- On Screen Controler (OSC, play control buttons) with modern flat design
|
- On Screen Controller (OSC, play control buttons) with modern flat design
|
||||||
- Command Line Interface
|
- Command Line Interface
|
||||||
- Started from a terminal status, error and debug output is printed on the terminal
|
- Started from a terminal status, error and debug output is printed on the terminal
|
||||||
- DXVA2 video decoding acceleration
|
- DXVA2 video decoding acceleration
|
||||||
@@ -90,10 +77,10 @@ Features that mpv and mpv.net have in common
|
|||||||
- Build-in media streaming (requires yt-dlp being installed)
|
- Build-in media streaming (requires yt-dlp being installed)
|
||||||
- External audio and subtitle files can be loaded manually or automatically
|
- External audio and subtitle files can be loaded manually or automatically
|
||||||
- Screenshot feature
|
- Screenshot feature
|
||||||
- Watch later feature to save the video position
|
- Internationalization using gettext and transifex
|
||||||
|
|
||||||
|
|
||||||
Features exclusiv to mpv.net
|
Features exclusive to mpv.net
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
- Very high degree of mpv compatibility, almost all mpv features are available
|
- Very high degree of mpv compatibility, almost all mpv features are available
|
||||||
@@ -103,26 +90,25 @@ Features exclusiv to mpv.net
|
|||||||
- Searchable input (shorcut keys) editor
|
- Searchable input (shorcut keys) editor
|
||||||
- C# and PowerShell Scripting
|
- C# and PowerShell Scripting
|
||||||
- Global keyboard shortcuts
|
- Global keyboard shortcuts
|
||||||
- Command palette to quickly and easily find commands and keys
|
|
||||||
- Extension API for .NET languages (C#, VB.NET and F#)
|
- Extension API for .NET languages (C#, VB.NET and F#)
|
||||||
- Portable, MS Store or WinGet download and installation
|
- Portable, MS Store or WinGet download and installation
|
||||||
- File history feature to log time and filename
|
- File history feature to log time and filename
|
||||||
- Files can be enqueued from File Explorer
|
- Files can be enqueued from File Explorer
|
||||||
|
|
||||||
|
|
||||||
## [Support](docs/Manual.md#support)
|
## [Support](docs/manual.md#support)
|
||||||
|
|
||||||
[Support section of the manual.](docs/Manual.md#support)
|
[Support section of the manual.](docs/manual.md#support)
|
||||||
|
|
||||||
|
|
||||||
## [Download](docs/Manual.md#download)
|
## [Download](docs/manual.md#download)
|
||||||
|
|
||||||
[Download section of the manual.](docs/Manual.md#download)
|
[Download section of the manual.](docs/manual.md#download)
|
||||||
|
|
||||||
|
|
||||||
## [Manual](docs/Manual.md)
|
## [Manual](docs/manual.md)
|
||||||
|
|
||||||
[The mpv.net documentation.](docs/Manual.md)
|
[The mpv.net documentation.](docs/manual.md)
|
||||||
|
|
||||||
|
|
||||||
Screenshots
|
Screenshots
|
||||||
@@ -159,23 +145,3 @@ OSD console and status printed on the terminal.
|
|||||||
Searchable key and mouse binding editor.
|
Searchable key and mouse binding editor.
|
||||||
|
|
||||||

|

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

|
|
||||||
|
|
||||||
|
|
||||||
#### Playlist
|
|
||||||
|
|
||||||
The command palette based playlist showing my favorite artist of the stax record label.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
List of my apps
|
|
||||||
---------------
|
|
||||||
|
|
||||||
https://stax76.github.io/frankskare
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
@@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layout>
|
|
||||||
<row>
|
|
||||||
<button text="PLAY" ontap="play" />
|
|
||||||
<button text="PREV" ontap="prev" />
|
|
||||||
<button text="NEXT" ontap="next" />
|
|
||||||
<button text="Enter" ontap="enter" />
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<button text="LEFT" ontap="left" />
|
|
||||||
<button text="RIGHT" ontap="right" />
|
|
||||||
<button text="UP" ontap="up" />
|
|
||||||
<button text="DOWN" ontap="down" />
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<button text="VOL-" ontap="vol_minus" />
|
|
||||||
<button text="VOL+" ontap="vol_plus" />
|
|
||||||
<button text="MUTE" ontap="mute" />
|
|
||||||
<button text="INFO" ontap="info" />
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<button text="KP0" ontap="KP0" />
|
|
||||||
<button text="KP1" ontap="KP1" />
|
|
||||||
<button text="KP2" ontap="KP2" />
|
|
||||||
<button text="KP3" ontap="KP3" />
|
|
||||||
<button text="KP4" ontap="KP4" />
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<button text="KP5" ontap="KP5" />
|
|
||||||
<button text="KP6" ontap="KP6" />
|
|
||||||
<button text="KP7" ontap="KP7" />
|
|
||||||
<button text="KP8" ontap="KP8" />
|
|
||||||
<button text="KP9" ontap="KP9" />
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<button text="Cycle Audio" ontap="KP7" />
|
|
||||||
<button text="Cycle Subtitle" ontap="KP8" />
|
|
||||||
<button text="AB LOOP" ontap="ab_loop" />
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<button text="ZOOM IN" ontap="zoom_in" />
|
|
||||||
<button text="ZOOM OUT" ontap="zoom_out" />
|
|
||||||
</row>
|
|
||||||
</layout>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
meta.name: custom keys
|
|
||||||
meta.author: stax76
|
|
||||||
meta.description: custom keys
|
|
||||||
meta.tags: mpv
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
|
|
||||||
-- https://github.com/unifiedremote/Docs/blob/master/libs/keyboard.md
|
|
||||||
|
|
||||||
-- https://github.com/unifiedremote/Docs/blob/master/res/keys.md
|
|
||||||
|
|
||||||
local kb = libs.keyboard;
|
|
||||||
|
|
||||||
actions.play = function ()
|
|
||||||
kb.stroke("space");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.next = function ()
|
|
||||||
kb.stroke("F12");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.prev = function ()
|
|
||||||
kb.stroke("F11");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.enter = function ()
|
|
||||||
kb.stroke("enter");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.left = function ()
|
|
||||||
kb.stroke("left");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.right = function ()
|
|
||||||
kb.stroke("right");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.up = function ()
|
|
||||||
kb.stroke("up");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.down = function ()
|
|
||||||
kb.stroke("down");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.vol_minus = function ()
|
|
||||||
kb.text("-");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.vol_plus = function ()
|
|
||||||
kb.text("+");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.mute = function ()
|
|
||||||
kb.stroke("m");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.info = function ()
|
|
||||||
kb.stroke("i");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP0 = function ()
|
|
||||||
kb.stroke("num0");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP1 = function ()
|
|
||||||
kb.stroke("num1");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP2 = function ()
|
|
||||||
kb.stroke("num2");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP3 = function ()
|
|
||||||
kb.stroke("num3");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP4 = function ()
|
|
||||||
kb.stroke("num4");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP5 = function ()
|
|
||||||
kb.stroke("num5");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP6 = function ()
|
|
||||||
kb.stroke("num6");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP7 = function ()
|
|
||||||
kb.stroke("num7");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP8 = function ()
|
|
||||||
kb.stroke("num8");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.KP9 = function ()
|
|
||||||
kb.stroke("num9");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.ab_loop = function ()
|
|
||||||
kb.stroke("l");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.zoom_in = function ()
|
|
||||||
kb.stroke("ctrl", "oem_plus");
|
|
||||||
end
|
|
||||||
|
|
||||||
actions.zoom_out = function ()
|
|
||||||
kb.stroke("ctrl", "oem_minus");
|
|
||||||
end
|
|
||||||
@@ -1,4 +1,156 @@
|
|||||||
|
|
||||||
|
# v7.0.0.5 Beta (2023-12-28)
|
||||||
|
|
||||||
|
- Fix mpv.net option `language` not working from command line.
|
||||||
|
- Chinese and German translation updated.
|
||||||
|
- More libplacebo options added.
|
||||||
|
- Support of the mpv option `title-bar`.
|
||||||
|
- Video being less often rendered with black line at the bottom.
|
||||||
|
- The conf file reader/writer detects if the user prefers space before and after the equal sign.
|
||||||
|
- The portable download includes like the installer debug symbols.
|
||||||
|
- Setup questions on startup removed.
|
||||||
|
- Pressing shift while drag and drop appends instead of replaces
|
||||||
|
files in the playlist. mpv supports this as well.
|
||||||
|
- New menu item and binding: `File > Add files to playlist from clipboard` `Ctrl+Shift+v`.
|
||||||
|
- All list operation suffixes are available on the command line.
|
||||||
|
- Improved layout in conf editor.
|
||||||
|
- New zhongfly libmpv build.
|
||||||
|
|
||||||
|
|
||||||
|
# v7.0.0.4 Beta (2023-12-19)
|
||||||
|
|
||||||
|
- When mpv.net is started for the first time from a new startup location,
|
||||||
|
it asks if file associations should be registered.
|
||||||
|
- Setup supports installing per user in non admin mode.
|
||||||
|
- Command line parser supports list options with `-add` suffix.
|
||||||
|
- Fix window sometimes shown with wrong size.
|
||||||
|
- Limited support for the mpv option `geometry`, it supports location in percent,
|
||||||
|
for size use `autofit`. Read the instructions in the mpv.net manual or in the conf editor.
|
||||||
|
- Improved manual.
|
||||||
|
- Improved bindings.
|
||||||
|
- Conf editor reorganized according to options categories used in mpv manual.
|
||||||
|
- mpv.net is available via command line package manager winget.
|
||||||
|
- New libplacebo config editor options added.
|
||||||
|
- The conf editor uses a newly developed combo box control (dropdown menu)
|
||||||
|
instead of radio buttons whenever an option has more than 3 items,
|
||||||
|
this improves the look and feel, usability and performance.
|
||||||
|
The navigation tree view was improved.
|
||||||
|
- New zhongfly libmpv build.
|
||||||
|
|
||||||
|
|
||||||
|
# v7.0.0.3 Beta (2023-12-15)
|
||||||
|
|
||||||
|
- New conf editor option `Video/libplacebo/preset`.
|
||||||
|
- New conf editor option `Video/libplacebo/Scaling/upscaler`.
|
||||||
|
- New menu item `Settings/Setup/Add mpv.net to Path environment variable' added.
|
||||||
|
- New menu item `Settings/Edit mpv.conf` added for opening mpv.conf with a text editor. Default binding `c`.
|
||||||
|
- New menu item `Settings/Edit input.conf` added for opening input.conf with a text editor. Default binding `k`.
|
||||||
|
- mpv.net can no longer be downloaded from the Microsoft store due
|
||||||
|
to a general very poor experience with the package creation and submission.
|
||||||
|
I've submitted mpv.net to the winget package repository, it's not yet processed.
|
||||||
|
- Improved conf file reader/writer.
|
||||||
|
- Conf editor support added for the mpv options:
|
||||||
|
`reset-on-next-file`, `input-ipc-server`, `background`, `title`
|
||||||
|
- Conf editor crash fixed.
|
||||||
|
- When mpv.net is started for the first time from a new startup location,
|
||||||
|
it asks if mpv.net should be added to the Path environment variable.
|
||||||
|
|
||||||
|
# v7.0.0.2 Beta (2023-12-13)
|
||||||
|
|
||||||
|
- Besides a portable download there is now again a setup installer.
|
||||||
|
- Fix dynamic menu items missing in context menu.
|
||||||
|
- Fix certain binding setups shown poorly or incorrectly in the main menu.
|
||||||
|
- Fix conf editor not remembering the search text.
|
||||||
|
- Fix quit-watch-later not working.
|
||||||
|
- New option `menu-syntax`. Default: `#menu:`
|
||||||
|
- New zhongfly libmpv build.
|
||||||
|
|
||||||
|
# v7.0.0.1 Beta (2023-12-11)
|
||||||
|
|
||||||
|
- [.NET 6 is a new requirement](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
|
||||||
|
(Windows 7 is still supported)
|
||||||
|
- The command palette was removed because of a compatibility problem with
|
||||||
|
the .NET 6 platform. There are user scripts with similar functionality:
|
||||||
|
- [command_palette](https://github.com/stax76/mpv-scripts#command_palette)
|
||||||
|
- [search_menu](https://github.com/stax76/mpv-scripts#search_menu)
|
||||||
|
- [uosc](https://github.com/tomasklaen/uosc)
|
||||||
|
- The blue mpv.net logo was removed for better OSC compatibility.
|
||||||
|
- Fix message box exceding working area size.
|
||||||
|
- C# and PowerShell scripting was removed because of a compatibility problem
|
||||||
|
with the .NET 6 platform. .NET extensions are supported with a new host
|
||||||
|
(not backward compatible). An example extension is available under \src\MpvNet.Extension\ExampleExtension
|
||||||
|
- Redesigned bindings and context menu.
|
||||||
|
- auto-play option removed, mpv supports it with the option reset-on-next-file.
|
||||||
|
- Dark mode title bar enabled on Windows 10.0.18985 or higher.
|
||||||
|
- The navigation bar on the left side of the config editor was changed
|
||||||
|
from a simple list to a tree view.
|
||||||
|
- Support of the MPVNET_HOME environment variable that allows
|
||||||
|
customizing the conf directory location.
|
||||||
|
- Improved support for third party osc scripts like uosc.
|
||||||
|
- Support of the mpv property `focused`.
|
||||||
|
- Various improvements and fixes in the input bindings editor.
|
||||||
|
- Automated nightly portable builds (thx to dyphire).
|
||||||
|
- Various new or changed default bindings.
|
||||||
|
- Context menu and message boxes are available in the languages Chinese and German.
|
||||||
|
Interested joining our translation team?: https://app.transifex.com/stax76/teams/
|
||||||
|
- Support for encoding mode and thumbfast.
|
||||||
|
- For script authors, the following info is available in user-data:
|
||||||
|
user-data/frontend/name=mpv.net
|
||||||
|
user-data/frontend/version=version name
|
||||||
|
user-data/frontend/process-path=the process path
|
||||||
|
- MediaInfo 23.11
|
||||||
|
- libmpv zhongfly 2023-11-03.
|
||||||
|
|
||||||
|
# v6.0.3.2 Beta (2022-10-14)
|
||||||
|
|
||||||
|
- Support multiple folders input (regression fix).
|
||||||
|
- Relative file input paths are converted to absolute paths.
|
||||||
|
- New history-filter option added to define paths to be excluded from the history log feature.
|
||||||
|
- New command to move the Window to the screen edge (Alt+Arrow) or center (Alt+BS).
|
||||||
|
- Smaller OSD media info font size and more duplicated and obvious info removed from titles.
|
||||||
|
- Improved mouse cursor auto hide behavior.
|
||||||
|
- Fix severe bug causing termination before scripts having a chance reacting to shutdown event.
|
||||||
|
- mediainfo v22.09.
|
||||||
|
- libmpv shinchiro 2022-10-14, fixes a severe bug causing hangs:
|
||||||
|
https://github.com/mpv-player/mpv/pull/10569
|
||||||
|
|
||||||
|
input.conf changes:
|
||||||
|
|
||||||
|
New:
|
||||||
|
|
||||||
|
```
|
||||||
|
Alt+Left script-message-to mpvnet move-window left #menu: View > Move > Left
|
||||||
|
Alt+Right script-message-to mpvnet move-window right #menu: View > Move > Right
|
||||||
|
Alt+Up script-message-to mpvnet move-window top #menu: View > Move > Top
|
||||||
|
Alt+Down script-message-to mpvnet move-window bottom #menu: View > Move > Bottom
|
||||||
|
Alt+BS script-message-to mpvnet move-window center #menu: View > Move > Center
|
||||||
|
```
|
||||||
|
|
||||||
|
# 6.0.3.1 (2022-07-30)
|
||||||
|
|
||||||
|
- Creating a playlist from a folder uses absolute normalized paths, non-media files are ignored.
|
||||||
|
- The show-info command shows directly an advanced view, which was enhanced with a General section and the filename.
|
||||||
|
- Media info titles are shortened if they contain duplicated or obvious information.
|
||||||
|
- Support of shortcuts (.lnk files) with media file target.
|
||||||
|
- Support --audio-file and --sub-file aliases.
|
||||||
|
- playlist-random (F9 key) command jumps to a random playlist entry.
|
||||||
|
- Fix OSC hide behavior on mouse move.
|
||||||
|
- New binding (e key) to show the current file in File Explorer.
|
||||||
|
- Shift key enables process-instance=multi.
|
||||||
|
- Command line syntax (preceding double hyphen) is supported in mpv.conf for options implemented by mpv.net.
|
||||||
|
- MediaInfo v22.06
|
||||||
|
- libmpv shinchiro 2022-07-30
|
||||||
|
|
||||||
|
input.conf changes:
|
||||||
|
|
||||||
|
New:
|
||||||
|
|
||||||
|
```
|
||||||
|
e run powershell -command "explorer.exe '/select,' ( \"${path}\" -replace '/', '\\' )" #menu: Tools > Show current file in File Explorer
|
||||||
|
F9 script-message-to mpvnet playlist-random #menu: Navigate > Random File
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# 6.0.3.0 (2022-07-03)
|
# 6.0.3.0 (2022-07-03)
|
||||||
|
|
||||||
- Fix the rare occasion of duplicated playlist entries produced by the auto-load-folder feature.
|
- Fix the rare occasion of duplicated playlist entries produced by the auto-load-folder feature.
|
||||||
@@ -11,7 +163,7 @@
|
|||||||
|
|
||||||
# 6.0.1.0 (2022-06-30)
|
# 6.0.1.0 (2022-06-30)
|
||||||
|
|
||||||
- New tutorial: [Extending mpv and mpv.net via Lua scripting](https://github.com/stax76/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting)
|
- New tutorial: [Extending mpv and mpv.net via Lua scripting](https://github.com/mpvnet-player/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting)
|
||||||
- New options `autofit-image` and `autofit-audio`, like autofit, but used for image and audio files.
|
- New options `autofit-image` and `autofit-audio`, like autofit, but used for image and audio files.
|
||||||
- New [auto-mode](https://github.com/stax76/mpv-scripts) script to use mpv and mpv.net as image viewer and audio player.
|
- New [auto-mode](https://github.com/stax76/mpv-scripts) script to use mpv and mpv.net as image viewer and audio player.
|
||||||
- New [smart-volume](https://github.com/stax76/mpv-scripts) script. Records the volume per file in order to restore it
|
- New [smart-volume](https://github.com/stax76/mpv-scripts) script. Records the volume per file in order to restore it
|
||||||
@@ -118,11 +270,11 @@ All occurrences of `script-message mpv.net` were changed to `script-message-to m
|
|||||||
- Media Info isn't shown directly, instead the command palette
|
- Media Info isn't shown directly, instead the command palette
|
||||||
shows several choices. The command palette can be bypassed
|
shows several choices. The command palette can be bypassed
|
||||||
using the arguments: msgbox, editor, full, raw.
|
using the arguments: msgbox, editor, full, raw.
|
||||||
https://github.com/stax76/mpv.net/blob/master/docs/Manual.md#show-media-info-flags
|
https://github.com/mpvnet-player/mpv.net/blob/main/docs/manual.md#show-media-info-flags
|
||||||
- mpv.net specific commands, the command palette, auto-play property
|
- mpv.net specific commands, the command palette, auto-play property
|
||||||
and various other things are documented in the manual.
|
and various other things are documented in the manual.
|
||||||
- The action used for the right mouse button can be configured.
|
- The action used for the right mouse button can be configured.
|
||||||
https://github.com/stax76/mpv.net/blob/master/docs/Manual.md#show-menu
|
https://github.com/mpvnet-player/mpv.net/blob/main/docs/manual.md#show-menu
|
||||||
- Workaround not reproducible logo drawing crash.
|
- Workaround not reproducible logo drawing crash.
|
||||||
- Info command shows the length.
|
- Info command shows the length.
|
||||||
- New mpv.net specific option `show-logo` that allows to disable
|
- New mpv.net specific option `show-logo` that allows to disable
|
||||||
@@ -152,10 +304,10 @@ All occurrences of `script-message mpv.net` were changed to `script-message-to m
|
|||||||
- Fix script-opts files being ignored.
|
- Fix script-opts files being ignored.
|
||||||
- Showing the recent list in the command palette,
|
- Showing the recent list in the command palette,
|
||||||
the top item gets auto selected.
|
the top item gets auto selected.
|
||||||
https://github.com/stax76/mpv.net/issues/328#issuecomment-1057296054
|
https://github.com/mpvnet-player/mpv.net/issues/328#issuecomment-1057296054
|
||||||
- If the play list is empty, the most recent file
|
- If the play list is empty, the most recent file
|
||||||
gets loaded when pressing space.
|
gets loaded when pressing space.
|
||||||
https://github.com/stax76/mpv.net/issues/328#issuecomment-1057296054
|
https://github.com/mpvnet-player/mpv.net/issues/328#issuecomment-1057296054
|
||||||
- Ctrl+v (previously u) opens files (or URLs) from the clipboard,
|
- Ctrl+v (previously u) opens files (or URLs) from the clipboard,
|
||||||
previously it had to be a file path (format string) and now
|
previously it had to be a file path (format string) and now
|
||||||
it can also be the clipboard format of type file.
|
it can also be the clipboard format of type file.
|
||||||
@@ -524,27 +676,27 @@ stable release, no changes since the last beta
|
|||||||
https://mpv.io/manual/master/#legacy-option-syntax
|
https://mpv.io/manual/master/#legacy-option-syntax
|
||||||
- new: PowerShell script host was completely rewritten, events can be assigned
|
- new: PowerShell script host was completely rewritten, events can be assigned
|
||||||
by using `Register-ObjectEvent`, the scripting wiki page was updated
|
by using `Register-ObjectEvent`, the scripting wiki page was updated
|
||||||
https://github.com/stax76/mpv.net/wiki/Scripting#powershell
|
https://github.com/mpvnet-player/mpv.net/wiki/Scripting#powershell
|
||||||
- new: Context Menu > View > Show Profiles
|
- new: Context Menu > View > Show Profiles
|
||||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L147
|
https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L147
|
||||||
- new: Context Menu > View > Show Properties
|
- new: Context Menu > View > Show Properties
|
||||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L148
|
https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L148
|
||||||
- new: Context Menu > View > Show Commands
|
- new: Context Menu > View > Show Commands
|
||||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149
|
https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L149
|
||||||
- new: config editor tab is now remembered
|
- new: config editor tab is now remembered
|
||||||
- new: osd-duration setting added to config editor and default mpv.conf
|
- 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
|
- new: external console replaced with internal console, in case mpv.conf is missing it's
|
||||||
generated with correct Hight DPI font size scale settings.
|
generated with correct Hight DPI font size scale settings.
|
||||||
`script-opts=console-scale=<dpiscale>`
|
`script-opts=console-scale=<dpiscale>`
|
||||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L150
|
https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L150
|
||||||
https://mpv.io/manual/master/#console
|
https://mpv.io/manual/master/#console
|
||||||
- new: blue color in dark theme is now less intense
|
- new: blue color in dark theme is now less intense
|
||||||
https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme
|
https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#color-theme
|
||||||
- new: menu item 'View > Show Progress' (p key) to show progress bar
|
- 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
|
https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L146
|
||||||
- new: `script-message mpv.net playlist-first`, unlike mpv does not
|
- new: `script-message mpv.net playlist-first`, unlike mpv does not
|
||||||
restart if the first file is already active
|
restart if the first file is already active
|
||||||
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L44
|
https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L44
|
||||||
- new: if mpv.net is started from the terminal and an error happens then the error
|
- 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
|
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: update routine did only work when mpv.net was located in 'Program Files'
|
||||||
@@ -561,7 +713,7 @@ stable release, no changes since the last beta
|
|||||||
- new: update check, it must be enabled first in the conf editor under General
|
- new: update check, it must be enabled first in the conf editor under General
|
||||||
- new: update feature, requires PowerShell 5 and curl,
|
- new: update feature, requires PowerShell 5 and curl,
|
||||||
an up to date Windows 10 system has both included.
|
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))
|
Main menu (input.conf) must be reset or updated manually ([defaults](https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt))
|
||||||
|
|
||||||
- update: libmpv shinchiro 2019-11-10
|
- update: libmpv shinchiro 2019-11-10
|
||||||
|
|
||||||
@@ -570,17 +722,17 @@ stable release, no changes since the last beta
|
|||||||
- fix: the file association routine uses no longer 'Play with mpv.net' for the
|
- 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,
|
default open verb caption because it doesn't support multi selection,
|
||||||
it shows now only Open, the manual explains how to get 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)
|
in File Explorer, read about it [here](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#open-with)
|
||||||
- fix: x86 builds had an older version included because
|
- fix: x86 builds had an older version included because
|
||||||
of a misconfiguration in the solution file
|
of a misconfiguration in the solution file
|
||||||
|
|
||||||
### 5.4.3.0
|
### 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: the color themes can now be customized ([manual](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#color-theme))
|
||||||
- new: three new sections were added to the [manual](https://github.com/stax76/mpv.net/blob/master/Manual.md):
|
- new: three new sections were added to the [manual](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md):
|
||||||
1. [Color Theme](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme)
|
1. [Color Theme](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#color-theme)
|
||||||
2. [Hidden and secret features](https://github.com/stax76/mpv.net/blob/master/Manual.md#hidden-and-secret-features)
|
2. [Hidden and secret features](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#hidden-and-secret-features)
|
||||||
3. [External Tools](https://github.com/stax76/mpv.net/blob/master/Manual.md#external-tools)
|
3. [External Tools](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#external-tools)
|
||||||
|
|
||||||
- fix: window restore from maximized and from minimized was broken
|
- fix: window restore from maximized and from minimized was broken
|
||||||
- fix: it's possible to multi select files in File Explorer and press
|
- fix: it's possible to multi select files in File Explorer and press
|
||||||
@@ -600,13 +752,13 @@ stable release, no changes since the last beta
|
|||||||
context menu item in explorer with multi selection support use my
|
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
|
[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
|
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))
|
- window-size mpv property support added ([default bindings](https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L137))
|
||||||
- the config editor keeps profiles and comments in mpv.conf intact!
|
- the config editor keeps profiles and comments in mpv.conf intact!
|
||||||
- the options in the config editor are better organized
|
- the options in the config editor are better organized
|
||||||
|
|
||||||
### 5.4.2
|
### 5.4.2
|
||||||
|
|
||||||
- new: the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting#powershell) was improved
|
- new: the [scripting wiki page](https://github.com/mpvnet-player/mpv.net/wiki/Scripting#powershell) was improved
|
||||||
- new: Toggle Shuffle has been added to the menu defaults
|
- 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
|
- 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
|
instead of displaying the URL, mpv.conf defaults were changed to use
|
||||||
@@ -674,7 +826,7 @@ stable release, no changes since the last beta
|
|||||||
|
|
||||||
### 5.1
|
### 5.1
|
||||||
|
|
||||||
- many [wiki pages](https://github.com/stax76/mpv.net/wiki) were improved
|
- many [wiki pages](https://github.com/mpvnet-player/mpv.net/wiki) were improved
|
||||||
- the logo/icon had a very small cosmetic change
|
- the logo/icon had a very small cosmetic change
|
||||||
- the help in the context menu was improved,
|
- the help in the context menu was improved,
|
||||||
for quick access consider the command palette (F1 key)
|
for quick access consider the command palette (F1 key)
|
||||||
@@ -708,7 +860,7 @@ stable release, no changes since the last beta
|
|||||||
|
|
||||||
### 5.0
|
### 5.0
|
||||||
|
|
||||||
- [changed icon design](https://github.com/stax76/mpv.net/blob/master/img/mpvnet.png)
|
- [changed icon design](https://github.com/mpvnet-player/mpv.net/blob/main/img/mpvnet.png)
|
||||||
- libmpv was updated to shinchiro 2019-07-14
|
- libmpv was updated to shinchiro 2019-07-14
|
||||||
- new or improved config editor settings: screenshot-directory,
|
- new or improved config editor settings: screenshot-directory,
|
||||||
screenshot-format, screenshot-tag-colorspace, screenshot-high-bit-depth,
|
screenshot-format, screenshot-tag-colorspace, screenshot-high-bit-depth,
|
||||||
@@ -727,7 +879,7 @@ stable release, no changes since the last beta
|
|||||||
the script is located at startup/scripts
|
the script is located at startup/scripts
|
||||||
- terminal support added using mpvnet.com !
|
- terminal support added using mpvnet.com !
|
||||||
- script engine performance and error handling was improved
|
- script engine performance and error handling was improved
|
||||||
- the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting) was improved
|
- the [scripting wiki page](https://github.com/mpvnet-player/mpv.net/wiki/Scripting) was improved
|
||||||
- the C# scripting host extension was converted from VB to C# because it's not
|
- 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
|
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
|
- there was a copy paste bug in the file association feature resulting in keys
|
||||||
@@ -797,7 +949,7 @@ stable release, no changes since the last beta
|
|||||||
pressed, the files are opened as selected, the order is random though
|
pressed, the files are opened as selected, the order is random though
|
||||||
because Explorer starts multiple mpv.net processes concurrently
|
because Explorer starts multiple mpv.net processes concurrently
|
||||||
- libmpv was updated to shinchiro 2019-06-30
|
- 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
|
- the [mpv.conf defaults](https://github.com/mpvnet-player/mpv.net/blob/main/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
|
- 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
|
the window size will use a aspect ratio of 1.8
|
||||||
- new JavaScript script osc-visibility.js included in the distribution
|
- new JavaScript script osc-visibility.js included in the distribution
|
||||||
@@ -815,7 +967,7 @@ stable release, no changes since the last beta
|
|||||||
- invalid command-line arguments were ignored, now an error message is shown
|
- 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
|
- 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
|
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)
|
description [here](https://github.com/mpvnet-player/mpv.net/blob/main/Manual.md#chrome-extension)
|
||||||
- new config setting remember-height added to remember the window height,
|
- new config setting remember-height added to remember the window height,
|
||||||
otherwise the video's native resolution is used
|
otherwise the video's native resolution is used
|
||||||
- support for protocols other then http added
|
- support for protocols other then http added
|
||||||
@@ -830,13 +982,13 @@ stable release, no changes since the last beta
|
|||||||
- the playlist is never cleared whenever the control key is down but
|
- the playlist is never cleared whenever the control key is down but
|
||||||
files and URLs are appended instead
|
files and URLs are appended instead
|
||||||
- powershell script hosting bugs were fixed and a new powershell example script
|
- 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)
|
was added to the [scripting wiki page](https://github.com/mpvnet-player/mpv.net/wiki/Scripting#powershell)
|
||||||
- the menu entry for the command palette was renamed to 'Show All Commands' and
|
- 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 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
|
- 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
|
- 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
|
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))
|
key binding (b) was added as well ([Default Binding](https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L135))
|
||||||
|
|
||||||
### 4.3.1
|
### 4.3.1
|
||||||
|
|
||||||
@@ -851,7 +1003,7 @@ stable release, no changes since the last beta
|
|||||||
- the help and layout in the config editor was improved
|
- the help and layout in the config editor was improved
|
||||||
- clipboard monitoring for URLs can be disabled in the settings
|
- clipboard monitoring for URLs can be disabled in the settings
|
||||||
- the context menu has a new feature: Open > Add files to playlist,
|
- 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)
|
it appends files to the playlist [(Default binding)](https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L33)
|
||||||
- a setting was added to force using a single mpv.net process instance
|
- a setting was added to force using a single mpv.net process instance
|
||||||
|
|
||||||
### 4.1
|
### 4.1
|
||||||
@@ -865,8 +1017,7 @@ stable release, no changes since the last beta
|
|||||||
### 4.0
|
### 4.0
|
||||||
|
|
||||||
- on the start screen the mpv.NET icon is shown instead of the mpv icon,
|
- 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
|
feedback and contributions regarding the icon are welcome!
|
||||||
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
|
- everytime only one file is opened the complete folder is loaded in the playlist
|
||||||
- the info command (i key) shows the audio format
|
- the info command (i key) shows the audio format
|
||||||
- new options osd-font-size, sub-font, sub-font-size
|
- new options osd-font-size, sub-font, sub-font-size
|
||||||
@@ -893,7 +1044,7 @@ stable release, no changes since the last beta
|
|||||||
- there was a bug that caused underscores beeing removed from input like MBTN_LEFT_DBL
|
- 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
|
- 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
|
- 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)
|
[Everything](https://www.voidtools.com) to be installed. [Default Binding](https://github.com/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L29)
|
||||||
|
|
||||||
### 3.5
|
### 3.5
|
||||||
|
|
||||||
@@ -906,6 +1057,6 @@ stable release, no changes since the last beta
|
|||||||
|
|
||||||
### 3.4
|
### 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 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/mpvnet-player/mpv.net/blob/main/mpv.net/Resources/input.conf.txt#L149)
|
||||||
- new zip download option added
|
- new zip download option added
|
||||||
- new x86 download option added
|
- new x86 download option added
|
||||||
|
Before Width: | Height: | Size: 672 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
@@ -2,7 +2,7 @@
|
|||||||
mpv.net manual
|
mpv.net manual
|
||||||
==============
|
==============
|
||||||
|
|
||||||
**ENGLISH** | **[简体中文](Manual_chs.md)**
|
**ENGLISH** | **[简体中文](manual_chs.md)**
|
||||||
|
|
||||||
Table of contents
|
Table of contents
|
||||||
-----------------
|
-----------------
|
||||||
@@ -13,7 +13,6 @@ Table of contents
|
|||||||
* [Support](#support)
|
* [Support](#support)
|
||||||
* [Settings](#settings)
|
* [Settings](#settings)
|
||||||
* [Input and context menu](#input-and-context-menu)
|
* [Input and context menu](#input-and-context-menu)
|
||||||
* [Command Palette](#command-palette)
|
|
||||||
* [Command Line Interface](#command-line-interface)
|
* [Command Line Interface](#command-line-interface)
|
||||||
* [Terminal](#terminal)
|
* [Terminal](#terminal)
|
||||||
* [mpv.net specific commands](#mpvnet-specific-commands)
|
* [mpv.net specific commands](#mpvnet-specific-commands)
|
||||||
@@ -25,56 +24,50 @@ Table of contents
|
|||||||
* [Advanced Features](#advanced-features)
|
* [Advanced Features](#advanced-features)
|
||||||
* [Hidden Features](#hidden-features)
|
* [Hidden Features](#hidden-features)
|
||||||
* [Differences compared to mpv](#differences-compared-to-mpv)
|
* [Differences compared to mpv](#differences-compared-to-mpv)
|
||||||
* [Technical Overview](#technical-overview)
|
* [Environment Variables](#environment-variables)
|
||||||
|
* [user-data](#user-data)
|
||||||
* [Context Menu Commands](#context-menu)
|
* [Context Menu Commands](#context-menu)
|
||||||
|
|
||||||
|
|
||||||
About
|
About
|
||||||
-----
|
-----
|
||||||
|
|
||||||
mpv.net is a modern desktop media player for Windows based on the popular mpv player.
|
mpv.net is a media player for Windows that has a modern GUI.
|
||||||
|
|
||||||
mpv.net is designed to be mpv compatible, almost all mpv features are available
|
The player is based on the popular [mpv](https://mpv.io) media player.
|
||||||
because they are all contained in libmpv, this means the official
|
mpv.net is designed to be mpv compatible, almost all mpv features are available,
|
||||||
[mpv manual](https://mpv.io/manual/master/) applies to mpv.net.
|
this means the official [mpv manual](https://mpv.io/manual/master/) applies to mpv.net,
|
||||||
|
differences are documented in this manual under [Differences compared to mpv](#differences-compared-to-mpv).
|
||||||
mpv focuses on the usage of the command line and the terminal,
|
|
||||||
mpv.net retains the ability to be used from the command line and
|
|
||||||
the terminal and adds a modern Windows GUI on top of it.
|
|
||||||
|
|
||||||
Like mpv, mpv.net is designed for power users, for regular users there is a
|
|
||||||
[mpv.net-next](https://github.com/mpv-net-player/mpv.net-next)
|
|
||||||
project under construction.
|
|
||||||
|
|
||||||
|
|
||||||
Download
|
Download
|
||||||
--------
|
--------
|
||||||
|
|
||||||
1. [Stable via Microsoft Store](https://www.microsoft.com/store/productId/9N64SQZTB3LM)
|
1. [Stable and beta portable and setup via GitHub download](../../../releases)
|
||||||
|
2. Stable via command line with winget: `winget install mpv.net`
|
||||||
|
3. [Automated nightly portable builds](https://github.com/mpvnet-player/mpv.net/actions)
|
||||||
|
|
||||||
2. [Stable and beta via GitHub download](../../../releases)
|
[Changelog](changelog.md)
|
||||||
|
|
||||||
3. `winget install mpv.net`
|
|
||||||
|
|
||||||
[Changelog](Changelog.md)
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
mpv.net requires the .NET Framework 4.8 and Windows 7 or higher and a modern graphics card.
|
1. Windows 10 or higher.
|
||||||
|
2. [.NET Desktop Runtime 6.0](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
|
||||||
|
|
||||||
Internet streaming requires:
|
Internet streaming requires:
|
||||||
|
|
||||||
- Downloading [yt-dlp](https://github.com/yt-dlp/yt-dlp) and adding its folder
|
- Downloading [yt-dlp](https://github.com/yt-dlp/yt-dlp) and adding its folder
|
||||||
to the [user environment variable PATH](https://www.google.com/search?q=user+environment+variable+PATH).
|
to the [user environment variable PATH](https://www.google.com/search?q=user+environment+variable+PATH).
|
||||||
- In case of proxy server usage, [manual configuration](https://github.com/stax76/mpv.net/issues/401).
|
- In case of proxy server usage, [manual configuration](https://github.com/mpvnet-player/mpv.net/issues/401).
|
||||||
|
|
||||||
#### File Associations
|
#### File Associations
|
||||||
|
|
||||||
File Associations can be registered using the context menu under 'Settings > Setup'.
|
File Associations can be registered using the context menu under 'Settings > Setup'.
|
||||||
|
|
||||||
After the file associations were registered, it might be necessary to change the
|
After the file associations were registered, it might still be necessary to change the
|
||||||
default app in the Windows settings (Win+I, ms-settings:defaultapps).
|
default app in the Windows settings.
|
||||||
|
|
||||||
Another way to register file associations is using Windows File Explorer,
|
Another way to register file associations is using Windows File Explorer,
|
||||||
select a media file and select 'Open with > Choose another app' in the context menu.
|
select a media file and select 'Open with > Choose another app' in the context menu.
|
||||||
@@ -86,16 +79,30 @@ to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlus
|
|||||||
When multiple files are selected in File Explorer and enter is pressed then
|
When multiple files are selected in File Explorer and enter is pressed then
|
||||||
the files are opened in mpv.net in random order, this works with maximum 15 files.
|
the files are opened in mpv.net in random order, this works with maximum 15 files.
|
||||||
|
|
||||||
|
#### Path environment variable
|
||||||
|
|
||||||
|
In order to use mpv.net in a terminal for advanced use cases,
|
||||||
|
mpv.net must be added to the Path environment variable,
|
||||||
|
this can be achieved with the context menu (Settings/Setup).
|
||||||
|
|
||||||
Support
|
Support
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Before making a support request, please try the newest version first.
|
Before making a support request, please try the newest [beta version](../../../releases) first.
|
||||||
|
|
||||||
Bugs and feature requests can be made on the github [issue tracker](../../../issues),
|
Support can be requested here:
|
||||||
feel free to use for anything mpv.net related, usage questions are welcome.
|
|
||||||
|
|
||||||
Or use the [support thread](https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows) in the VideoHelp forum.
|
mpv.net bug reports, feature requests and advanced questions:
|
||||||
|
|
||||||
|
https://github.com/mpvnet-player/mpv.net/issues
|
||||||
|
|
||||||
|
Beginner mpv questions:
|
||||||
|
|
||||||
|
https://www.reddit.com/r/mpv
|
||||||
|
|
||||||
|
Advanced mpv questions:
|
||||||
|
|
||||||
|
https://github.com/mpv-player/mpv/issues
|
||||||
|
|
||||||
|
|
||||||
Settings
|
Settings
|
||||||
@@ -103,8 +110,9 @@ Settings
|
|||||||
|
|
||||||
mpv.net searches the config folder at:
|
mpv.net searches the config folder at:
|
||||||
|
|
||||||
1. startup\portable_config
|
1. Folder defined via MPVNET_HOME environment variable.
|
||||||
2. %APPDATA%\mpv.net (`C:\Users\%USERNAME%\AppData\Roaming\mpv.net`)
|
2. startup\portable_config (startup means the directory containing mpvnet.exe)
|
||||||
|
3. `%APPDATA%\mpv.net` (`C:\Users\Username\AppData\Roaming\mpv.net`)
|
||||||
|
|
||||||
mpv options are stored in the file mpv.conf,
|
mpv options are stored in the file mpv.conf,
|
||||||
mpv.net options are stored in the file mpvnet.conf,
|
mpv.net options are stored in the file mpvnet.conf,
|
||||||
@@ -114,15 +122,7 @@ mpv.net options are documented [here](#mpvnet-specific-options).
|
|||||||
Input and context menu
|
Input and context menu
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
The input (key/mouse) bindings and the context menu definitions are stored in the
|
Global keyboard shortcuts are supported via `global-input.conf` file.
|
||||||
input.conf file, if it's missing mpv.net generates it with default values.
|
|
||||||
|
|
||||||
Please be aware that once input.conf exists, mpv.net cannot update it, this means
|
|
||||||
the menu becomes outdated when mpv.net is updated with new or changed default menu
|
|
||||||
items. The only way to get an up-to-date menu is either resetting the menu by
|
|
||||||
deleting input.conf or updating it by manually editing input.conf.
|
|
||||||
|
|
||||||
Global keyboard shortcuts are supported via global-input.conf file.
|
|
||||||
|
|
||||||
The config folder can be opened from the context menu: `Settings > Open Config Folder`
|
The config folder can be opened from the context menu: `Settings > Open Config Folder`
|
||||||
|
|
||||||
@@ -130,50 +130,42 @@ A input and config editor can be found in the context menu under 'Settings'.
|
|||||||
|
|
||||||
The input test mode can be started via command line: --input-test
|
The input test mode can be started via command line: --input-test
|
||||||
|
|
||||||
The input key list can be printed with --input-keylist or
|
The input key list can be printed with --input-keylist
|
||||||
shown from the context menu under: View > Advanced > Show Keys
|
|
||||||
|
|
||||||
mpv.net input.conf defaults:
|
mpv input.conf defaults:
|
||||||
https://github.com/stax76/mpv.net/blob/master/src/Resources/input.conf.txt
|
|
||||||
|
|
||||||
mpv input.conf defaults:
|
|
||||||
https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||||
|
|
||||||
mpv input commands:
|
mpv input commands:
|
||||||
https://mpv.io/manual/master/#list-of-input-commands
|
https://mpv.io/manual/master/#list-of-input-commands
|
||||||
|
|
||||||
mpv input options:
|
mpv input options:
|
||||||
https://mpv.io/manual/master/#input
|
https://mpv.io/manual/master/#input
|
||||||
|
|
||||||
|
Before version v7 all bindings and the context menu definition
|
||||||
|
were defined in the input.conf file, which mpv.net created
|
||||||
|
in case it didn't exist. This had the disadvantage that mpv.net
|
||||||
|
lost control over all default bindings and context menu
|
||||||
|
defaults. This was unfortunate, v7 introduces a new bindings
|
||||||
|
and context menu design fixing it.
|
||||||
|
|
||||||
Command Palette
|
In v7 no input.conf file is created, the default bindings and
|
||||||
---------------
|
context menu is defined internally. input.conf only contains
|
||||||
|
what is different from the internally defined defaults,
|
||||||
|
so it works the same it work with mpv.
|
||||||
|
|
||||||
The command palette is designed to quickly find,
|
For backward compatibility the old input.conf context menu
|
||||||
select and execute commands.
|
format with the menu definition using `#menu: ` is still
|
||||||
|
supported. The new design also allows for a menu customization,
|
||||||
|
in a sub section called `Custom`. In input.conf it can be
|
||||||
|
defined like so:
|
||||||
|
|
||||||
It can also be used to easily find shortcut keys.
|
`Ctrl+a show-text Test #custom-menu: Test > Test`
|
||||||
|
|
||||||
The following functionality is presented with the Command Palette:
|
Users that have their bindings and context menu customized
|
||||||
|
before v7 can easily migrate to the new design by deleting
|
||||||
- Show media info in different ways.
|
bindings they don't use and remember the shortcut and remove
|
||||||
- Show and select audio tracks.
|
`#menu:` everywhere, it's important to remove `#menu:`
|
||||||
- Show and select subtitle tracks.
|
everywhere in order to enable the new mode/design.
|
||||||
- Show and select playlist files.
|
|
||||||
- Show and select recent files.
|
|
||||||
- Show available mpv properties.
|
|
||||||
- Show available decoders.
|
|
||||||
- Show available demuxers.
|
|
||||||
- Show available keys.
|
|
||||||
- Show available protocols.
|
|
||||||
|
|
||||||
| Key | Action |
|
|
||||||
| ------ | --------------------------- |
|
|
||||||
| F1 | Shows the command palette. |
|
|
||||||
| Escape | Hides the command palette. |
|
|
||||||
| Enter | Executes the selected item. |
|
|
||||||
| Up | Moves the selection up. |
|
|
||||||
| Down | Moves the selection down. |
|
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
Command Line Interface
|
||||||
@@ -201,11 +193,6 @@ Supported are all mpv properties, they are documented here:
|
|||||||
https://mpv.io/manual/master/#properties
|
https://mpv.io/manual/master/#properties
|
||||||
|
|
||||||
|
|
||||||
mpv.net has a feature to list all available properties:
|
|
||||||
|
|
||||||
_Context Menu > View > Advanced > Show Properties_
|
|
||||||
|
|
||||||
|
|
||||||
mpv has a few non property based switches which are generally not supported in mpv.net.
|
mpv has a few non property based switches which are generally not supported in mpv.net.
|
||||||
|
|
||||||
|
|
||||||
@@ -215,8 +202,6 @@ Terminal
|
|||||||
When mpv.net is started from a terminal it will output status,
|
When mpv.net is started from a terminal it will output status,
|
||||||
error and debug messages to the terminal and accept input keys from the terminal.
|
error and debug messages to the terminal and accept input keys from the terminal.
|
||||||
|
|
||||||
A common task for the terminal is debugging scripts.
|
|
||||||
|
|
||||||
|
|
||||||
mpv.net specific commands
|
mpv.net specific commands
|
||||||
-------------------------
|
-------------------------
|
||||||
@@ -225,8 +210,11 @@ mpv.net specific commands
|
|||||||
|
|
||||||
mpv.net commands are used when mpv commands don't exist or lack a feature.
|
mpv.net commands are used when mpv commands don't exist or lack a feature.
|
||||||
|
|
||||||
### cycle-audio
|
### add-to-path
|
||||||
Switches to the next audio track and shows info about that track.
|
Adds mpv.net to the Path environment variable.
|
||||||
|
|
||||||
|
### edit-conf-file [mpv.conf|input.conf]
|
||||||
|
Opens mpv.conf or input.conf in a text editor.
|
||||||
|
|
||||||
### load-audio
|
### load-audio
|
||||||
Shows a file browser dialog to open external audio files.
|
Shows a file browser dialog to open external audio files.
|
||||||
@@ -234,6 +222,9 @@ Shows a file browser dialog to open external audio files.
|
|||||||
### load-sub
|
### load-sub
|
||||||
Shows a file browser dialog to open external subtitle files.
|
Shows a file browser dialog to open external subtitle files.
|
||||||
|
|
||||||
|
### move-window [left|top|right|bottom|center]
|
||||||
|
Moves the Window to the screen edge (Alt+Arrow) or center (Alt+BS).
|
||||||
|
|
||||||
### open-conf-folder
|
### open-conf-folder
|
||||||
Opens the config folder with Windows File Explorer.
|
Opens the config folder with Windows File Explorer.
|
||||||
|
|
||||||
@@ -250,41 +241,23 @@ Shows a folder browser dialog to open a DVD or BD folder.
|
|||||||
ISO images don't have to be mounted, but instead can be
|
ISO images don't have to be mounted, but instead can be
|
||||||
opened directly with the open-files command.
|
opened directly with the open-files command.
|
||||||
|
|
||||||
### open-clipboard
|
### open-clipboard [\<flags\>]
|
||||||
Opens a single URL or filepath from the clipboard,
|
Opens a single URL or filepath from the clipboard,
|
||||||
or multiple files in the file clipboard format.
|
or multiple files in the file clipboard format.
|
||||||
|
|
||||||
|
**append**
|
||||||
|
Appends files/URLs to the playlist.
|
||||||
|
|
||||||
### play-pause
|
### play-pause
|
||||||
Cycles the pause property. In case the playlist is empty,
|
Cycles the pause property. In case the playlist is empty,
|
||||||
the most recent file from the recent files list is loaded.
|
the most recent file from the recent files list is loaded.
|
||||||
|
|
||||||
### playlist-add \<integer\>
|
|
||||||
Changes the playlist position by adding the supplied integer value.
|
|
||||||
If the position goes out of range, it jumpes to the opposite end.
|
|
||||||
|
|
||||||
### playlist-first
|
|
||||||
Jumps to the first playlist entry, if the loaded file is
|
|
||||||
already the first entry, nothing happens.
|
|
||||||
|
|
||||||
### playlist-last
|
|
||||||
Jumps to the last playlist entry, if the loaded file is
|
|
||||||
already the last entry, nothing happens.
|
|
||||||
|
|
||||||
### quick-bookmark
|
|
||||||
|
|
||||||
On the first press a bookmark is saved, on the second
|
|
||||||
press it is restored and removed. When a new file is
|
|
||||||
loaded the bookmark is removed.
|
|
||||||
|
|
||||||
### reg-file-assoc \<audio|video|image\>
|
### reg-file-assoc \<audio|video|image\>
|
||||||
Registers the file associations.
|
Registers the file associations.
|
||||||
|
|
||||||
### scale-window \<factor\>
|
### scale-window \<factor\>
|
||||||
Decreases or increases the Window size.
|
Decreases or increases the Window size.
|
||||||
|
|
||||||
### select-profile
|
|
||||||
Shows the command palette to select a profile.
|
|
||||||
|
|
||||||
### shell-execute \<file|URL\>
|
### shell-execute \<file|URL\>
|
||||||
Shell executes a single file or URL.
|
Shell executes a single file or URL.
|
||||||
|
|
||||||
@@ -294,50 +267,24 @@ Shows the about dialog.
|
|||||||
### show-audio-devices
|
### show-audio-devices
|
||||||
Shows available audio devices in a message box.
|
Shows available audio devices in a message box.
|
||||||
|
|
||||||
### show-audio-tracks
|
|
||||||
Shows available audio tracks in the command palette
|
|
||||||
and allows to load the selected audio track.
|
|
||||||
|
|
||||||
### show-chapters
|
|
||||||
Shows chapters in the command palette.
|
|
||||||
|
|
||||||
### show-command-palette
|
|
||||||
Shows the command palette.
|
|
||||||
|
|
||||||
### show-commands
|
### show-commands
|
||||||
Shows available mpv imput commands.
|
Shows available [mpv input commands](https://mpv.io/manual/master/#list-of-input-commands).
|
||||||
|
|
||||||
### show-conf-editor
|
### show-conf-editor
|
||||||
Shows the conf editor.
|
Shows the conf editor.
|
||||||
|
|
||||||
### show-decoders
|
|
||||||
Shows available decoders.
|
|
||||||
|
|
||||||
### show-demuxers
|
|
||||||
Shows available demuxers.
|
|
||||||
|
|
||||||
### show-history
|
|
||||||
|
|
||||||
Shows the history file when existing.
|
|
||||||
|
|
||||||
### show-info
|
|
||||||
Shows media info on screen, a second key press shows more detailed media info.
|
|
||||||
|
|
||||||
### show-input-editor
|
### show-input-editor
|
||||||
Shows the input editor.
|
Shows the input editor.
|
||||||
|
|
||||||
### show-keys
|
|
||||||
Shows available keys (as shown with `--input-keylist`) in the command palette.
|
|
||||||
|
|
||||||
### show-media-info [\<flags\>]
|
### show-media-info [\<flags\>]
|
||||||
**msgbox**
|
**msgbox**
|
||||||
Shows media info in a messsge box.
|
Shows media info in a messsage box.
|
||||||
|
|
||||||
**editor**
|
**editor**
|
||||||
Shows media info in the text editor.
|
Shows media info in a text editor.
|
||||||
|
|
||||||
**osd**
|
**osd**
|
||||||
Displays media info on screen.
|
Shows media info on screen.
|
||||||
|
|
||||||
**full**
|
**full**
|
||||||
Shows fully detailed media info.
|
Shows fully detailed media info.
|
||||||
@@ -349,30 +296,17 @@ Shows media info with raw property names.
|
|||||||
Shows the context menu.
|
Shows the context menu.
|
||||||
|
|
||||||
### show-playlist
|
### show-playlist
|
||||||
Shows the playlist in the command palette
|
Shows the playlist in a message box. For a playlist menu
|
||||||
and allows to play the selected entry.
|
the following user scripts exist:
|
||||||
|
|
||||||
|
- https://github.com/stax76/mpv-scripts#command_palette
|
||||||
|
- https://github.com/stax76/mpv-scripts#search_menu
|
||||||
|
- https://github.com/tomasklaen/uosc
|
||||||
|
- https://github.com/jonniek/mpv-playlistmanager
|
||||||
|
|
||||||
### show-profiles
|
### show-profiles
|
||||||
Shows available profiles with a message box.
|
Shows available profiles with a message box.
|
||||||
|
|
||||||
### show-progress
|
|
||||||
Shows a simple OSD progress message with time and date.
|
|
||||||
|
|
||||||
### show-properties
|
|
||||||
Shows available properties in the command palette and
|
|
||||||
allows to display the property value of the selected property.
|
|
||||||
|
|
||||||
### show-protocols
|
|
||||||
Shows available protocols in the command palette.
|
|
||||||
|
|
||||||
### show-recent
|
|
||||||
Shows recently played files and URLs in the
|
|
||||||
command palette and allows to select and play entries.
|
|
||||||
|
|
||||||
### show-subtitle-tracks
|
|
||||||
Shows available subtitles in the command palette
|
|
||||||
and allows to activate the selected subtitle.
|
|
||||||
|
|
||||||
### show-text \<text\> \<duration\> \<font-size\>
|
### show-text \<text\> \<duration\> \<font-size\>
|
||||||
Shows a OSD message with given text, duration and font size.
|
Shows a OSD message with given text, duration and font size.
|
||||||
|
|
||||||
@@ -461,24 +395,24 @@ are used as defined by autofit and start-size. Default: 1500
|
|||||||
#### --auto-load-folder=\<yes|no\>
|
#### --auto-load-folder=\<yes|no\>
|
||||||
|
|
||||||
For single files automatically load the entire directory into the playlist.
|
For single files automatically load the entire directory into the playlist.
|
||||||
Can be suppressed via shift key. Default: yes
|
|
||||||
|
|
||||||
#### --auto-play=\<yes|no\>
|
|
||||||
|
|
||||||
If the player is paused and another file is loaded,
|
|
||||||
playback automatically resumes.
|
|
||||||
|
|
||||||
|
|
||||||
### General
|
### General
|
||||||
|
|
||||||
|
#### --menu-syntax=\<value\>
|
||||||
|
|
||||||
|
Used menu syntax for defining the context menu in input.conf.\nmpv.net by default uses `#menu:`, uosc uses `#!` by default.
|
||||||
|
|
||||||
#### --process-instance=\<value\>
|
#### --process-instance=\<value\>
|
||||||
|
|
||||||
Defines if more then one mpv.net process is allowed.
|
Defines if more then one mpv.net process is allowed.
|
||||||
|
|
||||||
Tip: Whenever the CTRL key is pressed when files or URLs are opened,
|
Whenever the CTRL key is pressed when files or URLs are opened,
|
||||||
the playlist is not cleared but the files or URLs are appended to the playlist.
|
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.
|
This not only works on process startup but in all mpv.net features that open files and URLs.
|
||||||
|
|
||||||
|
Multi can alternatively be enabled by pressing the SHIFT key.
|
||||||
|
|
||||||
**multi**
|
**multi**
|
||||||
Create a new process everytime the shell starts mpv.net.
|
Create a new process everytime the shell starts mpv.net.
|
||||||
|
|
||||||
@@ -515,6 +449,14 @@ Enable this only when a developer asks for it. Default: no
|
|||||||
|
|
||||||
### UI
|
### UI
|
||||||
|
|
||||||
|
#### --language=\<value\>
|
||||||
|
|
||||||
|
User interface display language.
|
||||||
|
mpv.net must be restarted after a change.
|
||||||
|
|
||||||
|
Interested joining our translation team?:
|
||||||
|
https://app.transifex.com/stax76/teams/
|
||||||
|
|
||||||
#### --dark-mode=\<value\>
|
#### --dark-mode=\<value\>
|
||||||
|
|
||||||
Enables a dark theme.
|
Enables a dark theme.
|
||||||
@@ -539,14 +481,6 @@ Color theme used in light mode. Default: light
|
|||||||
|
|
||||||
[Color Themes](#color-theme)
|
[Color Themes](#color-theme)
|
||||||
|
|
||||||
#### --show-logo=\<yes|no\>
|
|
||||||
|
|
||||||
Draws the blue mpv.net logo ontop of the native OSC logo. Default: yes
|
|
||||||
|
|
||||||
#### --show-santa-logo=\<yes|no\>
|
|
||||||
|
|
||||||
Draws the blue mpv.net logo with a santa hat in december,
|
|
||||||
the option is called greenandgrumpy in mpv. Default: yes
|
|
||||||
|
|
||||||
External Tools
|
External Tools
|
||||||
--------------
|
--------------
|
||||||
@@ -572,31 +506,6 @@ Alternatively the Chrome/Firefox extension [Open With](../../../issues/119) can
|
|||||||
[Open with++](https://github.com/stax76/OpenWithPlusPlus) can be used to extend the File Explorer context menu to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) and [Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist).
|
[Open with++](https://github.com/stax76/OpenWithPlusPlus) can be used to extend the File Explorer context menu to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) and [Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist).
|
||||||
|
|
||||||
|
|
||||||
### Universal Remote Android app
|
|
||||||
|
|
||||||
Universal Remote is Android remote control app which costs 5 €.
|
|
||||||
|
|
||||||
https://www.unifiedremote.com
|
|
||||||
|
|
||||||
https://play.google.com/store/apps/details?id=com.Relmtech.Remote
|
|
||||||
|
|
||||||
https://play.google.com/store/apps/details?id=com.Relmtech.RemotePaid
|
|
||||||
|
|
||||||
https://www.unifiedremote.com/tutorials/how-to-create-a-custom-keyboard-shortcuts-remote
|
|
||||||
|
|
||||||
https://www.unifiedremote.com/tutorials/how-to-install-a-custom-remote
|
|
||||||
|
|
||||||
[My config](./Universal%20Remote)
|
|
||||||
|
|
||||||
Very useful is the Universal Remote File Browser feature.
|
|
||||||
|
|
||||||
|
|
||||||
### One For All Contour URC1210 and FLIRC USB
|
|
||||||
|
|
||||||
My primary remote control solution however is a One For All Contour URC1210
|
|
||||||
using Philips code 0556 together with FLIRC USB (gen2).
|
|
||||||
|
|
||||||
|
|
||||||
### External Application Button
|
### External Application Button
|
||||||
|
|
||||||
Videos can be streamed or downloaded easily with the Chrome extension
|
Videos can be streamed or downloaded easily with the Chrome extension
|
||||||
@@ -612,95 +521,33 @@ Scripting
|
|||||||
|
|
||||||
#### Lua
|
#### Lua
|
||||||
|
|
||||||
A very large collection of Lua user scripts can be found in the mpv wiki [here](https://github.com/mpv-player/mpv/wiki/User-Scripts).
|
A very large collection of user scripts can be found in the GitHub repository
|
||||||
|
[awesome-mpv](https://github.com/stax76/awesome-mpv).
|
||||||
|
|
||||||
Lua scripting is documented in the mpv.net wiki [here](https://github.com/stax76/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting).
|
Lua scripting is documented in the mpv.net wiki [here](https://github.com/mpvnet-player/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting).
|
||||||
|
|
||||||
#### JavaScript
|
#### JavaScript
|
||||||
|
|
||||||
[mpv JavaScript documentation](https://mpv.io/manual/master/#javascript)
|
[mpv JavaScript documentation](https://mpv.io/manual/master/#javascript)
|
||||||
|
|
||||||
#### PowerShell
|
|
||||||
|
|
||||||
Location: `<config folder>\scripts-ps`
|
.NET Extensions
|
||||||
|
---------------
|
||||||
|
|
||||||
The PowerShell scripting host is not initialized before media files are loaded.
|
.NET Extensions are located in a subfolder _extensions_ in the config folder,
|
||||||
|
the filename must have the same name as the directory:
|
||||||
[Example Scripts](../../../tree/master/src/Scripts)
|
|
||||||
|
|
||||||
|
|
||||||
#### C#
|
|
||||||
|
|
||||||
Location: `<config folder>\scripts-cs`
|
|
||||||
|
|
||||||
There are no compatibility guaranties.
|
|
||||||
|
|
||||||
Script code can be written within a C# [extension](../../../tree/master/src/Extensions),
|
|
||||||
that way full code completion and debugger support is available.
|
|
||||||
Once the code was developed and debugged, it can be moved
|
|
||||||
from the extension to a lightweight standalone script.
|
|
||||||
The script host uses an old C# version, modern features
|
|
||||||
like string interpolation are not available.
|
|
||||||
|
|
||||||
There are synchronous and asynchronous events, prefer asynchronous events
|
|
||||||
and don't block synchronous events and observed properties, as it would
|
|
||||||
block the main event loop.
|
|
||||||
|
|
||||||
The C# scripting host is like [extensions](../../../tree/master/src/Extensions)
|
|
||||||
not initialized before media files are loaded.
|
|
||||||
|
|
||||||
[Example Scripts](../../../tree/master/src/Scripts)
|
|
||||||
|
|
||||||
|
|
||||||
Extensions
|
|
||||||
----------
|
|
||||||
|
|
||||||
Extensions are located in a subfolder _extensions_ in the config folder
|
|
||||||
and the filename must have the same name as the directory:
|
|
||||||
|
|
||||||
```Text
|
```Text
|
||||||
<config folder>\extensions\ExampleExtension\ExampleExtension.dll
|
<config folder>\extensions\ExampleExtension\ExampleExtension.dll
|
||||||
```
|
```
|
||||||
|
|
||||||
There are synchronous and asynchronous events, prefer asynchronous events
|
|
||||||
and don't block synchronous events and observed properties, as it would
|
|
||||||
block the main event loop.
|
|
||||||
|
|
||||||
### Walkthrough creating an extension
|
|
||||||
|
|
||||||
- Download and install [Visual Studio Community](https://visualstudio.microsoft.com).
|
|
||||||
- Create a new project of type **Class Library .NET Framework**
|
|
||||||
and ensure the project name ends with **Extension**.
|
|
||||||
- Add a reference to **System.ComponentModel.Composition**.
|
|
||||||
- Add a reference to mpvnet.exe, select the mpvnet reference
|
|
||||||
in the Solution Explorer, open the Properties window and set
|
|
||||||
**Copy Local** to false to prevent mpvnet.exe being copied
|
|
||||||
to the output directory when the project is built.
|
|
||||||
- Now open the project properties and set the output path in the Build tab,
|
|
||||||
extensions are like scripts located in your config folder, example:
|
|
||||||
`<config folder>\extensions\ExampleExtension\ExampleExtension.dll`
|
|
||||||
- Also in the project properties choose the option **Start external program**
|
|
||||||
in the Debug tab and define the path to mpvnet.exe. In the Debug tab you may also
|
|
||||||
define command line arguments like a video file to be played when you start debugging.
|
|
||||||
|
|
||||||
|
|
||||||
### Sample Code
|
|
||||||
|
|
||||||
#### RatingExtension
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
[Source Code](../../../tree/master/src/Extensions)
|
|
||||||
|
|
||||||
|
|
||||||
Color Theme
|
Color Theme
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
mpv.net supports custom color themes, the definition of the built-in themes can be found at:
|
mpv.net supports custom color themes, the definition of the built-in themes can be found at:
|
||||||
|
|
||||||
[theme.txt](../../../tree/master/src/Resources/theme.txt)
|
[theme.txt](../../../tree/main/src/Resources/theme.txt)
|
||||||
|
|
||||||
|
|
||||||
Custom themes can be saved at:
|
Custom themes can be saved at:
|
||||||
@@ -735,21 +582,18 @@ Selecting multiple files in File Explorer and pressing enter will
|
|||||||
open the files in mpv.net. Explorer restricts this to maximum 15 files
|
open the files in mpv.net. Explorer restricts this to maximum 15 files
|
||||||
and the order will be random.
|
and the order will be random.
|
||||||
|
|
||||||
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 works in all mpv.net features that open files or URLs.
|
|
||||||
|
|
||||||
Pressing the shift key while opening a single file will suppress loading
|
|
||||||
all files of the folder into the playlist.
|
|
||||||
|
|
||||||
In fullscreen mode clicking the top right corner closes the player.
|
In fullscreen mode clicking the top right corner closes the player.
|
||||||
|
|
||||||
|
|
||||||
Differences compared to mpv
|
Differences compared to mpv
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
mpv.net is designed to work exactly like mpv, there are a few limitations:
|
mpv.net is designed to work exactly like mpv, there are a few
|
||||||
|
differences and limitations:
|
||||||
|
|
||||||
|
The settings folder is named `mpv.net` instead of `mpv`:
|
||||||
|
|
||||||
|
`C:\Users\username\AppData\Roaming\mpv.net`
|
||||||
|
|
||||||
### Window Limitations
|
### Window Limitations
|
||||||
|
|
||||||
@@ -759,6 +603,18 @@ features are supported that have an own implementation in mpv.net.
|
|||||||
A window free mode is currently not supported, the main window is always
|
A window free mode is currently not supported, the main window is always
|
||||||
visible, even when mpv.net is started from the terminal and music is played.
|
visible, even when mpv.net is started from the terminal and music is played.
|
||||||
|
|
||||||
|
For mpv.net it's currently not possible to find out where OSC menus are located,
|
||||||
|
but there are 3 features that require this information, therefore mpv.net
|
||||||
|
makes the assumption that near the window borders might be OSC menus. As a result
|
||||||
|
the following three features, work only when invoked from the center of the window:
|
||||||
|
|
||||||
|
1. Window dragging (moving the window with the mouse).
|
||||||
|
2. Showing the context menu.
|
||||||
|
3. Auto hiding the mouse cursor.
|
||||||
|
|
||||||
|
When the mouse is near a window border, these 3 features are not available.
|
||||||
|
The dead zone sizes are 10% left, top, right and 22% bottom.
|
||||||
|
|
||||||
The documentation of mpv's window features can be found here:
|
The documentation of mpv's window features can be found here:
|
||||||
|
|
||||||
https://mpv.io/manual/master/#window
|
https://mpv.io/manual/master/#window
|
||||||
@@ -772,20 +628,42 @@ https://mpv.io/manual/master/#window
|
|||||||
- [ontop](https://mpv.io/manual/master/#options-ontop)
|
- [ontop](https://mpv.io/manual/master/#options-ontop)
|
||||||
- [screen](https://mpv.io/manual/master/#options-screen)
|
- [screen](https://mpv.io/manual/master/#options-screen)
|
||||||
- [snap-window](https://mpv.io/manual/master/#options-snap-window)
|
- [snap-window](https://mpv.io/manual/master/#options-snap-window)
|
||||||
|
- [title-bar](https://mpv.io/manual/master/#options-title-bar)
|
||||||
- [title](https://mpv.io/manual/master/#options-title)
|
- [title](https://mpv.io/manual/master/#options-title)
|
||||||
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
|
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
|
||||||
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized)
|
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized)
|
||||||
- [window-scale](https://mpv.io/manual/master/#options-window-scale)
|
- [window-scale](https://mpv.io/manual/master/#options-window-scale)
|
||||||
|
|
||||||
|
|
||||||
**Partly implemented are:**
|
**Partly implemented or modified:**
|
||||||
|
|
||||||
- [autofit-larger](https://mpv.io/manual/master/#options-autofit-larger)
|
#### --autofit=\<int\>
|
||||||
Supported is a single integer value in the range 0-100.
|
|
||||||
- [autofit-smaller](https://mpv.io/manual/master/#options-autofit-smaller)
|
\<int\> Initial window height in percent. Default: 60
|
||||||
Supported is a single integer value in the range 0-100.
|
|
||||||
- [autofit](https://mpv.io/manual/master/#options-autofit)
|
#### --autofit-smaller=\<int\>
|
||||||
Supported is a single integer value in the range 0-100.
|
|
||||||
|
\<int\> Minimum window height in percent. Default: 10
|
||||||
|
|
||||||
|
#### --autofit-larger=\<int\>
|
||||||
|
|
||||||
|
\<int\> Maximum window height in percent. Default: 80
|
||||||
|
|
||||||
|
#### --geometry\<x:y\>
|
||||||
|
|
||||||
|
Initial window location in percent. Default: 50:50 (centered)
|
||||||
|
|
||||||
|
x=0 docks the window to the left side.
|
||||||
|
x=100 docks the window to the right side.
|
||||||
|
|
||||||
|
y=0 docks the window to the top side.
|
||||||
|
y=100 docks the window to the bottom side.
|
||||||
|
|
||||||
|
#### --title-bar=\<yes|no\>
|
||||||
|
|
||||||
|
Shows the window title bar. Default: yes
|
||||||
|
|
||||||
|
**mpv.net specific window features:**
|
||||||
|
|
||||||
mpv.net specific window features are documented in the [screen section](#screen).
|
mpv.net specific window features are documented in the [screen section](#screen).
|
||||||
|
|
||||||
@@ -823,36 +701,28 @@ mpv.net specific options are saved in the file mpvnet.conf and are just
|
|||||||
as mpv properties available on the command line.
|
as mpv properties available on the command line.
|
||||||
|
|
||||||
|
|
||||||
Technical Overview
|
Environment Variables
|
||||||
------------------
|
---------------------
|
||||||
|
|
||||||
mpv.net is written in C# 7 and runs on the .NET Framework 4.8.
|
### MPVNET_HOME
|
||||||
|
|
||||||
The Extension implementation is based on the
|
Directory where mpv.net looks for user settings.
|
||||||
[Managed Extensibility Framework](https://docs.microsoft.com/en-us/dotnet/framework/mef/).
|
|
||||||
|
|
||||||
The main window is WinForms based because WinForms allows better libmpv integration
|
|
||||||
compared to WPF, all other windows are WPF based.
|
|
||||||
|
|
||||||
Third party components are:
|
|
||||||
|
|
||||||
- [libmpv provides the core functionality](https://mpv.io/)
|
|
||||||
- [MediaInfo](https://mediaarea.net/en/MediaInfo)
|
|
||||||
|
|
||||||
|
|
||||||
Context Menu
|
user-data
|
||||||
------------
|
---------
|
||||||
|
|
||||||
The context menu of mpv.net is defined in the file input.conf which is
|
Script authors can access the following
|
||||||
located in the config directory.
|
[user-data](https://mpv.io/manual/master/#command-interface-user-data) properties:
|
||||||
|
|
||||||
If the input.conf file does not exists mpv.net generates it with the following defaults:
|
```
|
||||||
|
user-data/frontend/name
|
||||||
<https://github.com/stax76/mpv.net/tree/master/src/Resources/input.conf.txt>
|
user-data/frontend/version
|
||||||
|
user-data/frontend/process-path
|
||||||
input.conf defines mpv's key and mouse bindings and mpv.net uses
|
```
|
||||||
comments to define the context menu.
|
|
||||||
|
|
||||||
|
Context Menu Commands
|
||||||
|
---------------------
|
||||||
|
|
||||||
### Open > Open Files
|
### Open > Open Files
|
||||||
|
|
||||||
@@ -863,19 +733,13 @@ File Explorer for existing associations.
|
|||||||
|
|
||||||
A third way is to drag and drop files on the main window.
|
A third way is to drag and drop files on the main window.
|
||||||
|
|
||||||
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 works in all mpv.net features that open files or URLs.
|
|
||||||
|
|
||||||
Pressing the shift key while opening a single file will suppress loading all files in the folder.
|
|
||||||
|
|
||||||
Blu-ray and DVD ISO image files are supported.
|
Blu-ray and DVD ISO image files are supported.
|
||||||
|
|
||||||
|
|
||||||
### Open > Open URL or file path from clipboard
|
### Open > Open URL or file path from clipboard
|
||||||
|
|
||||||
Opens files and URLs from the clipboard. How to open URLs directly
|
Opens files and URLs from the clipboard. Shift key appends to the playlist.
|
||||||
from the browser from sites like YouTube is described in the
|
How to open URLs directly from the browser from sites like YouTube is described in the
|
||||||
[External Tools section](#external-tools).
|
[External Tools section](#external-tools).
|
||||||
|
|
||||||
|
|
||||||
@@ -1209,7 +1073,7 @@ Cycles the aspect ratio using the following command:
|
|||||||
[video-aspect property](https://mpv.io/manual/master/#command-interface-video-aspect)
|
[video-aspect property](https://mpv.io/manual/master/#command-interface-video-aspect)
|
||||||
|
|
||||||
|
|
||||||
### Audio > Cycle/Next
|
### Audio > Next
|
||||||
|
|
||||||
This uses a mpv.net command that shows better info then the mpv preset
|
This uses a mpv.net command that shows better info then the mpv preset
|
||||||
and also has the advantage of not showing no audio.
|
and also has the advantage of not showing no audio.
|
||||||
@@ -1237,17 +1101,6 @@ Adds a negative audio delay using the following command:
|
|||||||
[audio-delay property](https://mpv.io/manual/master/#options-audio-delay)
|
[audio-delay property](https://mpv.io/manual/master/#options-audio-delay)
|
||||||
|
|
||||||
|
|
||||||
### Subtitle > Cycle/Next
|
|
||||||
|
|
||||||
Shows the next subtitle track using the following command:
|
|
||||||
|
|
||||||
`cycle sub`
|
|
||||||
|
|
||||||
[cycle command](https://mpv.io/manual/master/#command-interface-cycle-%3Cname%3E-[%3Cvalue%3E])
|
|
||||||
|
|
||||||
[sub/sid property](https://mpv.io/manual/master/#options-sid)
|
|
||||||
|
|
||||||
|
|
||||||
### Subtitle > Toggle Visibility
|
### Subtitle > Toggle Visibility
|
||||||
|
|
||||||
Cycles the subtitle visibility using the following command:
|
Cycles the subtitle visibility using the following command:
|
||||||
@@ -1329,7 +1182,7 @@ Increases the subtitle font size using the following command:
|
|||||||
|
|
||||||
Increases the volume using the following command:
|
Increases the volume using the following command:
|
||||||
|
|
||||||
`add volume 10`
|
`add volume 2`
|
||||||
|
|
||||||
[add command](https://mpv.io/manual/master/#command-interface-add-%3Cname%3E-[%3Cvalue%3E])
|
[add command](https://mpv.io/manual/master/#command-interface-add-%3Cname%3E-[%3Cvalue%3E])
|
||||||
|
|
||||||
@@ -1340,7 +1193,7 @@ Increases the volume using the following command:
|
|||||||
|
|
||||||
Decreases the volume using the following command:
|
Decreases the volume using the following command:
|
||||||
|
|
||||||
`add volume -10`
|
`add volume -2`
|
||||||
|
|
||||||
[add command](https://mpv.io/manual/master/#command-interface-add-%3Cname%3E-[%3Cvalue%3E])
|
[add command](https://mpv.io/manual/master/#command-interface-add-%3Cname%3E-[%3Cvalue%3E])
|
||||||
|
|
||||||
@@ -1413,11 +1266,6 @@ Resets the speed using the following command:
|
|||||||
[speed property](https://mpv.io/manual/master/#options-speed)
|
[speed property](https://mpv.io/manual/master/#options-speed)
|
||||||
|
|
||||||
|
|
||||||
### Extensions > Rating > 0stars
|
|
||||||
|
|
||||||
A plugin the writes the rating to the filename.
|
|
||||||
|
|
||||||
|
|
||||||
### View > On Top > Enable
|
### View > On Top > Enable
|
||||||
|
|
||||||
Forces the player to stay on top of other windows using the following command:
|
Forces the player to stay on top of other windows using the following command:
|
||||||
@@ -1472,24 +1320,6 @@ Toggles OSC Visibility using the following command:
|
|||||||
[script-binding command](https://mpv.io/manual/master/#command-interface-script-binding)
|
[script-binding command](https://mpv.io/manual/master/#command-interface-script-binding)
|
||||||
|
|
||||||
|
|
||||||
### View > Show Playlist
|
|
||||||
|
|
||||||
Shows the playlist for 5 seconds using the following command:
|
|
||||||
|
|
||||||
`show-text ${playlist} 5000`
|
|
||||||
|
|
||||||
[show-text command](https://mpv.io/manual/master/#command-interface-show-text)
|
|
||||||
|
|
||||||
|
|
||||||
### View > Show Audio/Video/Subtitle List
|
|
||||||
|
|
||||||
Shows the Audio/Video/Subtitle list for 5 seconds using the following command:
|
|
||||||
|
|
||||||
`show-text ${track-list} 5000`
|
|
||||||
|
|
||||||
[show-text command](https://mpv.io/manual/master/#command-interface-show-text)
|
|
||||||
|
|
||||||
|
|
||||||
### Settings > Show Config Editor
|
### Settings > Show Config Editor
|
||||||
|
|
||||||
Shows mpv.net's config editor.
|
Shows mpv.net's config editor.
|
||||||
@@ -1512,23 +1342,6 @@ input.conf containing mpv key and mouse bindings
|
|||||||
|
|
||||||
User scripts and user extensions
|
User scripts and user extensions
|
||||||
|
|
||||||
|
|
||||||
### Tools > Command Palette
|
|
||||||
|
|
||||||
Shows the command palette window which allows to quickly find and execute commands and key shortcuts.
|
|
||||||
|
|
||||||
|
|
||||||
### Tools > Show History
|
|
||||||
|
|
||||||
Shows a text file that contains the file history. If the file don't exist
|
|
||||||
it asks if the file should be created in the settings folder. Once the file
|
|
||||||
exist then the history is logged. It logges the playback history containing
|
|
||||||
the time and filename.
|
|
||||||
|
|
||||||
To ignore certain paths:
|
|
||||||
|
|
||||||
script-opt = history-discard=path1;path2
|
|
||||||
|
|
||||||
### Tools > Set/clear A-B loop points
|
### Tools > Set/clear A-B loop points
|
||||||
|
|
||||||
Enables to set loop start and end points using the following command:
|
Enables to set loop start and end points using the following command:
|
||||||
@@ -1572,12 +1385,12 @@ Shows the [mpv manual](https://mpv.io/manual/stable/).
|
|||||||
|
|
||||||
### Help > Show mpv.net web site
|
### Help > Show mpv.net web site
|
||||||
|
|
||||||
Shows the [mpv.net web site](https://mpv-net.github.io/mpv.net-web-site/).
|
Shows the [mpv.net web site](https://github.com/mpvnet-player/mpv.net).
|
||||||
|
|
||||||
|
|
||||||
### Help > Show mpv.net manual
|
### Help > Show mpv.net manual
|
||||||
|
|
||||||
Shows the [mpv.net manual](https://github.com/stax76/mpv.net/blob/master/Manual.md).
|
Shows the [mpv.net manual](https://github.com/mpvnet-player/mpv.net/blob/main/manual.md).
|
||||||
|
|
||||||
|
|
||||||
### Help > About mpv.net
|
### Help > About mpv.net
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
mpv.net手册
|
mpv.net手册
|
||||||
==============
|
==============
|
||||||
|
|
||||||
适配版本 [v6.0.0.0-beta](https://github.com/stax76/mpv.net/releases/tag/v6.0.0.0-beta)
|
适配版本 [Master_commit_220819](https://github.com/mpvnet-player/mpv.net/commit/22960af78b7e1b7255954d845b3d378330aa449b)
|
||||||
|
|
||||||
**[ENGLISH](Manual.md)** | **简体中文**
|
**[ENGLISH](Manual.md)** | **简体中文**
|
||||||
|
|
||||||
@@ -36,13 +36,11 @@ mpv.net手册
|
|||||||
|
|
||||||
mpv.net是基于受欢迎的mpv的Windows现代媒体播放器。
|
mpv.net是基于受欢迎的mpv的Windows现代媒体播放器。
|
||||||
|
|
||||||
mpv.net出于兼容mpv而设计,几乎所有mpv的功能都可用,因为它们都包含在libmpv中,
|
mpv.net出于兼容mpv而设计,几乎所有mpv的功能都可用,因为它们都包含在libmpv中,这意味着[mpv官方手册](https://mpv.io/manual/master/) 也适用于mpv.net。
|
||||||
这意味着[mpv官方手册](https://mpv.io/manual/master/) 也适用于mpv.net。
|
|
||||||
|
|
||||||
mpv专注命令行与终端的使用,而mpv.net保留了这些并加入了现代化的图形界面。
|
mpv专注命令行与终端的使用,而mpv.net保留了这些并加入了现代化的图形界面。
|
||||||
|
|
||||||
与mpv一样,mpv.net也是为高级用户设计的,对于普通用户,
|
与mpv一样,mpv.net也是为高级用户设计的。
|
||||||
有一个正在建设中的 [mpv.net-next](https://github.com/mpv-net-player/mpv.net-next) 项目。
|
|
||||||
|
|
||||||
|
|
||||||
下载
|
下载
|
||||||
@@ -65,36 +63,39 @@ mpv.net需要.NET Framework 4.8运行库和高于win7版本的系统以及一张
|
|||||||
互联网流媒体需要:
|
互联网流媒体需要:
|
||||||
|
|
||||||
- 下载[yt-dlp](https://github.com/yt-dlp/yt-dlp)并将其添加到[用户环境变量PATH](https://www.google.com/search?q=user+environment+variable+PATH);
|
- 下载[yt-dlp](https://github.com/yt-dlp/yt-dlp)并将其添加到[用户环境变量PATH](https://www.google.com/search?q=user+environment+variable+PATH);
|
||||||
- 在使用代理服务器的情况下,需要[手动配置](https://github.com/stax76/mpv.net/issues/401)。
|
- 在使用代理服务器的情况下,需要[手动配置](https://github.com/mpvnet-player/mpv.net/issues/401)。
|
||||||
|
|
||||||
#### 文件关联
|
#### 文件关联
|
||||||
|
|
||||||
可以使用上下文菜单注册文件关联。 'Settings > Setup'
|
可以使用上下文菜单注册文件关联。 'Settings > Setup'
|
||||||
|
|
||||||
注册完文件关联后,进入 "Windows设置 > 应用 > 默认应用" (Win+I, ms-settings:defaultapps)
|
注册完文件关联后,进入 "Windows设置 > 应用 > 默认应用" (Win+I, ms-settings:defaultapps) 然后选择mpv. net作为视频/音频/图像的默认程序。
|
||||||
然后选择mpv. net作为视频/音频/图像的默认程序。
|
|
||||||
|
|
||||||
另一种注册文件关联的方式是使用文件资源管理器,选中媒体文件后,
|
另一种注册文件关联的方式是使用文件资源管理器,选中媒体文件后,选择上下文菜单的 '打开方式 > 选择其它应用' 。
|
||||||
选择上下文菜单的 '打开方式 > 选择其它应用' 。
|
|
||||||
|
|
||||||
[Open with++](#open-with) 可用来扩展资源管理器的上下文菜单
|
[Open with++](#open-with) 可用来扩展资源管理器的上下文菜单。[Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) 和 [Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist) 可用来获取 'Play with mpv.net' 和 'Add to mpv.net playlist' 的菜单子项
|
||||||
[Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) 和
|
|
||||||
[Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist).
|
|
||||||
可用来获取 'Play with mpv.net' 和 'Add to mpv.net playlist' 的菜单子项
|
|
||||||
|
|
||||||
当在资源管理器中选择多个文件并按 enter 键时,文件会在mpv.net随机排序打开,
|
当在资源管理器中选择多个文件并按 enter 键时,文件会在mpv.net随机排序打开,最多限制15个文件。
|
||||||
最多限制15个文件。
|
|
||||||
|
|
||||||
|
|
||||||
支持
|
支持
|
||||||
-------
|
-------
|
||||||
|
|
||||||
在提出支持请求之前,先尝试最新的测试版。
|
在提出支持请求之前,先尝试最新的 [测试版](../../../releases)。
|
||||||
|
|
||||||
程序错误和功能请求可以在github的 [问题追踪](../../../issues) 上提出,
|
可以在这些地方请求支持:
|
||||||
任何与mpv. net相关的东西都可以使用,欢迎提交使用上出现的问题。
|
|
||||||
|
|
||||||
或者浏览VideoHelp论坛的 [讨论帖](https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows)
|
初学者提问:
|
||||||
|
|
||||||
|
https://www.reddit.com/r/mpv
|
||||||
|
|
||||||
|
mpv.net的错误报告、功能请求和高级问题:
|
||||||
|
|
||||||
|
https://github.com/mpvnet-player/mpv.net/issues
|
||||||
|
|
||||||
|
高级的mpv问题:
|
||||||
|
|
||||||
|
https://github.com/mpv-player/mpv/issues
|
||||||
|
|
||||||
|
|
||||||
设置
|
设置
|
||||||
@@ -105,20 +106,15 @@ mpv.net在以下路径寻找设置文件夹:
|
|||||||
1. <程序启动目录>\portable_config
|
1. <程序启动目录>\portable_config
|
||||||
2. %APPDATA%\mpv.net (`C:\Users\%USERNAME%\AppData\Roaming\mpv.net`)
|
2. %APPDATA%\mpv.net (`C:\Users\%USERNAME%\AppData\Roaming\mpv.net`)
|
||||||
|
|
||||||
mpv的选项保存在mpv.conf文件中,
|
mpv的选项保存在mpv.conf文件中,mpv.net的专属选项保存在 mpvnet.conf 文件中,参数解释请参阅 [此处](#mpvnet的专属选项)
|
||||||
mpv.net的专属选项保存在 mpvnet.conf 文件中,
|
|
||||||
参数解释请参阅 [此处](#mpvnet的专属选项)
|
|
||||||
|
|
||||||
|
|
||||||
快捷键和上下文菜单
|
快捷键和上下文菜单
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
键鼠的快捷键和上下文菜单的操作保存在 input.conf 文件中,
|
键鼠的快捷键和上下文菜单的操作保存在 input.conf 文件中,如果设置目录中不存在,mpv.net会用默认值生成它。
|
||||||
如果设置目录中不存在,mpv.net会用默认值生成它。
|
|
||||||
|
|
||||||
请注意,一旦 input.conf 存在, mpv.net 就不能更新它,这意味着当 mpv.net 升级了
|
请注意,一旦 input.conf 存在, mpv.net 就不能更新它,这意味着当 mpv.net 升级了新的版本或改变了的默认菜单项时,菜单条目就会过时。获得最新菜单的唯一方法是通过删除 input.conf 来重置菜单,或者通过手动编辑 input.conf 来更新它。
|
||||||
新的版本或改变了的默认菜单项时,菜单条目就会过时。获得最新菜单的唯一方法是
|
|
||||||
通过删除 input.conf 来重置菜单,或者通过手动编辑 input.conf 来更新它。
|
|
||||||
|
|
||||||
通过 global-input.conf 文件支持全局热键。
|
通过 global-input.conf 文件支持全局热键。
|
||||||
|
|
||||||
@@ -128,11 +124,10 @@ input 和 config editor 可以在上下文菜单的该条目中找到 'Settings'
|
|||||||
|
|
||||||
输入测试模式可以通过命令行启动: --input-test
|
输入测试模式可以通过命令行启动: --input-test
|
||||||
|
|
||||||
输入的键位列表可由该参数输出 --input-keylist
|
输入的键位列表可由该参数输出 --input-keylist 或从上下文菜单的该条目获取 `View > Advanced > Show Keys`
|
||||||
或从上下文菜单的该条目获取 `View > Advanced > Show Keys`
|
|
||||||
|
|
||||||
mpv.net的默认input.conf文件:
|
mpv.net的默认input.conf文件:
|
||||||
https://github.com/stax76/mpv.net/blob/master/src/Resources/input.conf.txt
|
https://github.com/mpvnet-player/mpv.net/blob/master/src/Resources/input.conf.txt
|
||||||
|
|
||||||
mpv的默认input.conf文件:
|
mpv的默认input.conf文件:
|
||||||
https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||||
@@ -230,6 +225,9 @@ mpv.net命令可在mpv命令不存在或缺乏某种功能时使用。
|
|||||||
### load-sub
|
### load-sub
|
||||||
显示一个资源管理器的对话框来加载外部字幕文件。
|
显示一个资源管理器的对话框来加载外部字幕文件。
|
||||||
|
|
||||||
|
### move-window [left|top|right|bottom|center]
|
||||||
|
将窗口移动到屏幕边缘 (Alt+方向键) 或中心 (Alt+Backspace)。
|
||||||
|
|
||||||
### open-conf-folder
|
### open-conf-folder
|
||||||
用Windows资源管理器打开配置文件夹。
|
用Windows资源管理器打开配置文件夹。
|
||||||
|
|
||||||
@@ -237,12 +235,10 @@ mpv.net命令可在mpv命令不存在或缺乏某种功能时使用。
|
|||||||
**append**
|
**append**
|
||||||
追加文件到播放列表中。
|
追加文件到播放列表中。
|
||||||
|
|
||||||
打开一个资源管理器的对话框,以便选择要打开的文件。资源管理器的对话框
|
打开一个资源管理器的对话框,以便选择要打开的文件。资源管理器的对话框支持多选以一次性加载多个文件。按住CTRL键可以将这些文件追加到播放列表中。
|
||||||
支持多选以一次性加载多个文件。按住CTRL键可以将这些文件追加到播放列表中。
|
|
||||||
|
|
||||||
### open-optical-media
|
### open-optical-media
|
||||||
显示一个资源管理器的对话框来打开一个DVD或BD文件夹。ISO镜像不需要被挂载,
|
显示一个资源管理器的对话框来打开一个DVD或BD文件夹。ISO镜像不需要被挂载,但可以直接用 open-files 命令打开。
|
||||||
但可以直接用 open-files 命令打开。
|
|
||||||
|
|
||||||
### open-clipboard
|
### open-clipboard
|
||||||
从剪贴板打开单个的URL或文件路径,或以文件剪贴板中的格式打开多个文件。
|
从剪贴板打开单个的URL或文件路径,或以文件剪贴板中的格式打开多个文件。
|
||||||
@@ -259,9 +255,11 @@ mpv.net命令可在mpv命令不存在或缺乏某种功能时使用。
|
|||||||
### playlist-last
|
### playlist-last
|
||||||
跳转到播放列表的最后一个条目,如果加载的文件已经是最后一个条目,则无动作。
|
跳转到播放列表的最后一个条目,如果加载的文件已经是最后一个条目,则无动作。
|
||||||
|
|
||||||
|
### playlist-random
|
||||||
|
跳转到播放列表的任一条目。
|
||||||
|
|
||||||
### quick-bookmark
|
### quick-bookmark
|
||||||
第一次触发时,书签被保存,第二次触发时,它被恢复并移除。当加载新文件时,
|
第一次触发时,书签被保存,第二次触发时,它被恢复并移除。当加载新文件时,书签也会被移除。
|
||||||
书签也会被移除。
|
|
||||||
|
|
||||||
### reg-file-assoc \<audio|video|image\>
|
### reg-file-assoc \<audio|video|image\>
|
||||||
注册文件关联。
|
注册文件关联。
|
||||||
@@ -269,6 +267,9 @@ mpv.net命令可在mpv命令不存在或缺乏某种功能时使用。
|
|||||||
### scale-window \<factor\>
|
### scale-window \<factor\>
|
||||||
减小或增大窗口的尺寸。
|
减小或增大窗口的尺寸。
|
||||||
|
|
||||||
|
### select-profile
|
||||||
|
显示命令面板以选择一个profile。
|
||||||
|
|
||||||
### shell-execute \<file|URL\>
|
### shell-execute \<file|URL\>
|
||||||
Shell执行单个文件或URL。
|
Shell执行单个文件或URL。
|
||||||
|
|
||||||
@@ -281,6 +282,9 @@ Shell执行单个文件或URL。
|
|||||||
### show-audio-tracks
|
### show-audio-tracks
|
||||||
在命令面板中显示可用的音轨,并允许加载选中的音轨。
|
在命令面板中显示可用的音轨,并允许加载选中的音轨。
|
||||||
|
|
||||||
|
### show-chapters
|
||||||
|
在命令面板中显示章节。
|
||||||
|
|
||||||
### show-command-palette
|
### show-command-palette
|
||||||
显示命令面板。
|
显示命令面板。
|
||||||
|
|
||||||
@@ -299,9 +303,6 @@ Shell执行单个文件或URL。
|
|||||||
### show-history
|
### show-history
|
||||||
显示已有的历史文件。
|
显示已有的历史文件。
|
||||||
|
|
||||||
### show-info
|
|
||||||
在屏幕上显示mediainfo,第二次触发可显示更详细的媒体信息。
|
|
||||||
|
|
||||||
### show-input-editor
|
### show-input-editor
|
||||||
显示器快捷键编辑器。
|
显示器快捷键编辑器。
|
||||||
|
|
||||||
@@ -362,15 +363,19 @@ mpv.net的专属选项
|
|||||||
|
|
||||||
这些专属选项被修改后被保存在 mpvnet.conf 文件中。
|
这些专属选项被修改后被保存在 mpvnet.conf 文件中。
|
||||||
|
|
||||||
|
#### --autofit-audio \<integer\>
|
||||||
|
音频文件的初始窗口高度,以百分比为单位。默认:70
|
||||||
|
|
||||||
|
#### --autofit-image \<integer\>
|
||||||
|
图片文件的初始窗口高度,以百分比为单位。默认:80
|
||||||
|
|
||||||
#### --queue \<files\>
|
#### --queue \<files\>
|
||||||
|
|
||||||
添加文件到播放列表,需要设置 [--process-instance=single](#--process-instancevalue) 。
|
添加文件到播放列表,需要设置 [--process-instance=single](#--process-instancevalue) 。也可以在资源管理器中使用 [Open with++](#open-with) 添加文件。
|
||||||
也可以在资源管理器中使用 [Open with++](#open-with) 添加文件。
|
|
||||||
|
|
||||||
#### --command=\<input command\>
|
#### --command=\<input command\>
|
||||||
|
|
||||||
通过命令行向正在运行的mpv.net实例发送输入命令,例如使用 AutoHotkey 创建
|
通过命令行向正在运行的mpv.net实例发送输入命令,例如使用 AutoHotkey 创建全局热键,必须设置 [process-instance=single](#--process-instancevalue) 。
|
||||||
全局热键,必须设置 [process-instance=single](#--process-instancevalue) 。
|
|
||||||
|
|
||||||
### Audio
|
### Audio
|
||||||
|
|
||||||
@@ -407,16 +412,14 @@ mpv.net的专属选项
|
|||||||
始终记住大小。
|
始终记住大小。
|
||||||
|
|
||||||
|
|
||||||
#### --start-threshold=\<milliseconds\>
|
|
||||||
|
|
||||||
在显示窗口之前等待libmpv返回视频分辨率的阈值(毫秒),
|
|
||||||
否则将使用由 --autofit 和 --start-size 定义的初始大小。默认:1500
|
|
||||||
|
|
||||||
|
|
||||||
#### --minimum-aspect-ratio=\<float\>
|
#### --minimum-aspect-ratio=\<float\>
|
||||||
|
|
||||||
最小宽高比,如果窗口宽高比小于定义的值,那么将窗口宽高比设置为16/9。
|
最小宽高比,如果窗口宽高比小于定义的值,那么将窗口的宽高比将被强制设为该值。
|
||||||
这避免了音乐封面的方形窗口。默认:1.2
|
|
||||||
|
|
||||||
|
#### --minimum-aspect-ratio-audio=\<float\>
|
||||||
|
|
||||||
|
同上但仅用于音频文件。
|
||||||
|
|
||||||
|
|
||||||
#### --remember-window-position=\<yes|no\>
|
#### --remember-window-position=\<yes|no\>
|
||||||
@@ -424,6 +427,11 @@ mpv.net的专属选项
|
|||||||
在退出时保存窗口的位置。默认:no
|
在退出时保存窗口的位置。默认:no
|
||||||
|
|
||||||
|
|
||||||
|
#### --start-threshold=\<milliseconds\>
|
||||||
|
|
||||||
|
在显示窗口之前等待libmpv返回视频分辨率的阈值(毫秒),否则将使用由 --autofit 和 --start-size 定义的初始大小。默认:1500
|
||||||
|
|
||||||
|
|
||||||
### Playback
|
### Playback
|
||||||
|
|
||||||
#### --auto-load-folder=\<yes|no\>
|
#### --auto-load-folder=\<yes|no\>
|
||||||
@@ -442,8 +450,9 @@ mpv.net的专属选项
|
|||||||
|
|
||||||
定义是否允许多个 mpv.net 进程。
|
定义是否允许多个 mpv.net 进程。
|
||||||
|
|
||||||
提示:当打开文件或 url 时,只要按下CTRL键,就不会清除当前的播放列表,
|
当打开文件或 url 时,只要按下CTRL键,就不会清除当前的播放列表,而只将文件或 url 追加到列表中。这不仅适用于进程启动,也适用于所有打开文件和 url 的功能。
|
||||||
而只将文件或 url 追加到列表中。这不仅适用于进程启动,也适用于所有打开文件和 url 的功能。
|
|
||||||
|
也可以通过按住SHIFT键来启动多个进程。
|
||||||
|
|
||||||
**multi**
|
**multi**
|
||||||
每次从 shell 启动 mpv.net 时创建一个新进程。
|
每次从 shell 启动 mpv.net 时创建一个新进程。
|
||||||
@@ -464,6 +473,9 @@ mpv.net的专属选项
|
|||||||
|
|
||||||
使用MediaInfo而不是mpv来访问媒体信息。默认:yes
|
使用MediaInfo而不是mpv来访问媒体信息。默认:yes
|
||||||
|
|
||||||
|
#### --history-filter
|
||||||
|
|
||||||
|
要从历史日志功能中排除的路径的分号分隔列表。
|
||||||
|
|
||||||
#### --video-file-extensions=\<string\>
|
#### --video-file-extensions=\<string\>
|
||||||
|
|
||||||
@@ -530,17 +542,13 @@ mpv.net的专属选项
|
|||||||
|
|
||||||
### Play with mpv
|
### Play with mpv
|
||||||
|
|
||||||
[Play with mpv](https://chrome.google.com/webstore/detail/play-with-mpv/hahklcmnfgffdlchjigehabfbiigleji)
|
[Play with mpv](https://chrome.google.com/webstore/detail/play-with-mpv/hahklcmnfgffdlchjigehabfbiigleji) 是一个支持调用mpv播放YouTube等网站视频的谷歌浏览器的扩展。
|
||||||
是一个支持调用mpv播放YouTube等网站视频的谷歌浏览器的扩展。
|
|
||||||
|
|
||||||
由于Chrome扩展无法启动一个应用程序,需要另一个与扩展程序通信的应用程序,该程序可以从
|
由于Chrome扩展无法启动一个应用程序,需要另一个与扩展程序通信的应用程序,该程序可以从[此处](http://www.mediafire.com/file/lezj8lwqt5zf75v/play-with-mpvnet-server.7z/file)下载。只有当该程序运行时扩展才能正常工作,为了让应用程序始终运行,应将其放在系统自启动目录中:
|
||||||
[此处](http://www.mediafire.com/file/lezj8lwqt5zf75v/play-with-mpvnet-server.7z/file)下载。
|
|
||||||
只有当该程序运行时扩展才能正常工作,为了让应用程序始终运行,应将其放在系统自启动目录中:
|
|
||||||
|
|
||||||
`C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`
|
`C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`
|
||||||
|
|
||||||
这将使该程序随系统共同启动,并在后台运行。当mpv.net的文件关联注册被执行后,
|
这将使该程序随系统共同启动,并在后台运行。当mpv.net的文件关联注册被执行后,该程序应该会找到mpv.net的位置,或者将mpv.net文件夹添加到环境变量PATH。
|
||||||
该程序应该会找到mpv.net的位置,或者将mpv.net文件夹添加到环境变量PATH。
|
|
||||||
|
|
||||||
|
|
||||||
### Open With
|
### Open With
|
||||||
@@ -550,35 +558,7 @@ mpv.net的专属选项
|
|||||||
|
|
||||||
### Open with++
|
### Open with++
|
||||||
|
|
||||||
[Open with++](#open-with) 可用来扩展资源管理器的上下文菜单
|
[Open with++](#open-with) 可用来扩展资源管理器的上下文菜单。[Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) 和 [Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist) 可用来获取 'Play with mpv.net' 和 'Add to mpv.net playlist' 的菜单子项
|
||||||
[Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) 和
|
|
||||||
[Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist).
|
|
||||||
可用来获取 'Play with mpv.net' 和 'Add to mpv.net playlist' 的菜单子项
|
|
||||||
|
|
||||||
|
|
||||||
### Universal Remote 安卓应用
|
|
||||||
|
|
||||||
Universal Remote 是一个收费的安卓远程控制APP。
|
|
||||||
|
|
||||||
https://www.unifiedremote.com
|
|
||||||
|
|
||||||
https://play.google.com/store/apps/details?id=com.Relmtech.Remote
|
|
||||||
|
|
||||||
https://play.google.com/store/apps/details?id=com.Relmtech.RemotePaid
|
|
||||||
|
|
||||||
https://www.unifiedremote.com/tutorials/how-to-create-a-custom-keyboard-shortcuts-remote
|
|
||||||
|
|
||||||
https://www.unifiedremote.com/tutorials/how-to-install-a-custom-remote
|
|
||||||
|
|
||||||
[我的配置](./Universal%20Remote)
|
|
||||||
|
|
||||||
Universal Remote 的 File Browser 功能十分有用。
|
|
||||||
|
|
||||||
|
|
||||||
### One For All Contour URC1210 and FLIRC USB
|
|
||||||
|
|
||||||
然而我的主要远程控制解决方案适用于所有人,
|
|
||||||
Philips code 0556 和 FLIRC USB (gen2) 一同被使用。
|
|
||||||
|
|
||||||
|
|
||||||
### External Application Button
|
### External Application Button
|
||||||
@@ -595,67 +575,34 @@ args: `-- pwsh -NoLogo -Command "yt-dlp --ignore-errors --download-archive 'C:\E
|
|||||||
|
|
||||||
#### Lua
|
#### Lua
|
||||||
|
|
||||||
文件类型: `lua`
|
可以在 [mpv wiki](https://github.com/mpv-player/mpv/wiki/User-Scripts) 中找到一个庞大的用户Lua脚本的集合。
|
||||||
|
|
||||||
文件位置: `<config folder>\scripts`
|
Lua脚本在 [mpv.net wiki](https://github.com/mpvnet-player/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting) 上有进一步记录。
|
||||||
|
|
||||||
Lua脚本的host由libmpv内建。
|
|
||||||
|
|
||||||
错误和调试消息输出在终端上。
|
|
||||||
|
|
||||||
Lua脚本在第一个媒体文件打开之前加载。
|
|
||||||
|
|
||||||
[mpv Lua 文档](https://mpv.io/manual/master/#lua-scripting)
|
|
||||||
|
|
||||||
[mpv 用户脚本 wiki](https://github.com/mpv-player/mpv/wiki/User-Scripts)
|
|
||||||
|
|
||||||
[mpv 用户脚本 GitHub](https://github.com/topics/mpv-script)
|
|
||||||
|
|
||||||
[mpv 用户脚本 Google](https://www.google.com/search?q=mpv+script)
|
|
||||||
|
|
||||||
|
|
||||||
#### JavaScript
|
#### JavaScript
|
||||||
|
|
||||||
文件类型: `js`
|
|
||||||
|
|
||||||
文件位置: `<config folder>\scripts`
|
|
||||||
|
|
||||||
JavaScriptLua脚本的host由libmpv内建。
|
|
||||||
|
|
||||||
错误和调试消息输出在终端上。
|
|
||||||
|
|
||||||
JavaScript脚本在第一个媒体文件打开之前加载。
|
|
||||||
|
|
||||||
[mpv JavaScript 文档](https://mpv.io/manual/master/#javascript)
|
[mpv JavaScript 文档](https://mpv.io/manual/master/#javascript)
|
||||||
|
|
||||||
[mpv用户脚本](https://github.com/mpv-player/mpv/wiki/User-Scripts)
|
|
||||||
|
|
||||||
|
|
||||||
#### PowerShell
|
#### PowerShell
|
||||||
|
|
||||||
文件类型: `ps1`
|
|
||||||
|
|
||||||
文件位置: `<config folder>\scripts-ps`
|
文件位置: `<config folder>\scripts-ps`
|
||||||
|
|
||||||
PS脚本的host类似于扩展,在打开媒体文件前尚未初始化。
|
PS脚本在打开媒体文件前尚未初始化。
|
||||||
|
|
||||||
mpv.net没有定义脚本接口,而是公开了它的完整内部,没有兼容性保证。
|
|
||||||
|
|
||||||
[示例脚本](../../../tree/master/src/Scripts)
|
[示例脚本](../../../tree/master/src/Scripts)
|
||||||
|
|
||||||
|
|
||||||
#### C#
|
#### C#
|
||||||
|
|
||||||
文件类型: `cs`
|
|
||||||
|
|
||||||
文件位置: `<config folder>\scripts-cs`
|
文件位置: `<config folder>\scripts-cs`
|
||||||
|
|
||||||
mpv.net没有定义脚本接口,而是公开了它的完整内部,没有兼容性保证。
|
没有兼容性保证。
|
||||||
|
|
||||||
脚本代码可以在C#[扩展](../../../tree/master/src/Extensions)中编写,这样
|
脚本代码可以在C#[扩展](../../../tree/master/src/Extensions)中编写,这样就可以获得完整的代码和调试器支持。一旦代码被调试和开发完成,就可以将其从扩展转移到轻量级的独立脚本。脚本host使用的是旧的C#版本,像字符串插值这样的现代功能是不存在的。
|
||||||
就可以获得完整的代码和调试器支持。一旦代码被调试和开发完成,就可以将其
|
|
||||||
从扩展转移到轻量级的独立脚本。脚本host使用的是旧的C#版本,像字符串插值
|
有同步事件和异步事件,更偏好异步事件,不要阻断同步事件和观察到的属性,因为这样会阻断主事件循环。
|
||||||
这样的现代功能是不存在的。
|
|
||||||
|
|
||||||
C#脚本的host类似于[扩展](../../../tree/master/src/Extensions),在打开媒体文件前尚未初始化。
|
C#脚本的host类似于[扩展](../../../tree/master/src/Extensions),在打开媒体文件前尚未初始化。
|
||||||
|
|
||||||
@@ -671,7 +618,7 @@ C#脚本的host类似于[扩展](../../../tree/master/src/Extensions),在打
|
|||||||
<config folder>\extensions\ExampleExtension\ExampleExtension.dll
|
<config folder>\extensions\ExampleExtension\ExampleExtension.dll
|
||||||
```
|
```
|
||||||
|
|
||||||
mpv.net没有定义脚本接口,而是公开了它的完整内部,没有兼容性保证。
|
有同步事件和异步事件,更偏好异步事件,不要阻断同步事件和观察到的属性,因为这样会阻断主事件循环。
|
||||||
|
|
||||||
|
|
||||||
### 创建扩展演示
|
### 创建扩展演示
|
||||||
@@ -679,14 +626,9 @@ mpv.net没有定义脚本接口,而是公开了它的完整内部,没有兼
|
|||||||
- 下载安装 [Visual Studio Community](https://visualstudio.microsoft.com) 。
|
- 下载安装 [Visual Studio Community](https://visualstudio.microsoft.com) 。
|
||||||
- 创建新的项目类型 **Class Library .NET Framework** 并确保项目名称以 **Extension** 作结尾。
|
- 创建新的项目类型 **Class Library .NET Framework** 并确保项目名称以 **Extension** 作结尾。
|
||||||
- 增加一个 reference 到 **System.ComponentModel.Composition**.
|
- 增加一个 reference 到 **System.ComponentModel.Composition**.
|
||||||
- 增加一个 reference 到 mpvnet.exe ,在 Solution Explorer 中选择 mpvnet 的 reference ,
|
- 增加一个 reference 到 mpvnet.exe ,在 Solution Explorer 中选择 mpvnet 的 reference ,打开 Properties 窗口并设置 **Copy Local** 为 false 来阻止在项目编译时 mpvnet.exe 被复制到输出目录。
|
||||||
打开 Properties 窗口并设置 **Copy Local** 为 false 来阻止在项目编译时 mpvnet.exe 被复制到输出目录。
|
- 现在打开 project properties 并在 Build 标签页设置 output path ,扩展类似于位于配置文件夹中的脚本,例如: `<config folder>\extensions\ExampleExtension\ExampleExtension.dll`
|
||||||
- 现在打开 project properties 并在 Build 标签页设置 output path ,
|
- 同样在 project properties 的 Debug 标签页中选择选项 **Start external program** 并且定义到 mpvnet.exe 的路径。在 Debug 标签页中你还可以定义 command line arguments ,例如开始调试时要播放的视频文件。
|
||||||
扩展类似于位于配置文件夹中的脚本,例如:
|
|
||||||
`<config folder>\extensions\ExampleExtension\ExampleExtension.dll`
|
|
||||||
- 同样在 project properties 的 Debug 标签页中选择选项 **Start external program**
|
|
||||||
并且定义到 mpvnet.exe 的路径。
|
|
||||||
在 Debug 标签页中你还可以定义 command line arguments ,例如开始调试时要播放的视频文件。
|
|
||||||
|
|
||||||
|
|
||||||
### 代码样本
|
### 代码样本
|
||||||
@@ -735,11 +677,9 @@ Python和VapourSynth必须在环境变量PATH中。
|
|||||||
隐藏功能
|
隐藏功能
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
使用mpv.net在资源管理器中选择多个文件并按下回车键打开。
|
使用mpv.net在资源管理器中选择多个文件并按下回车键打开。资源管理器将此限制为最多15个并且顺序将是随机的。
|
||||||
资源管理器将此限制为最多15个并且顺序将是随机的。
|
|
||||||
|
|
||||||
当打开文件或url时,只要按下CTRL键,就不会清除播放列表,而是将文件或url附加到播放列表中。
|
当打开文件或url时,只要按下CTRL键,就不会清除播放列表,而是将文件或url附加到播放列表中。这适用于mpv.net的所有打开文件或url的功能。
|
||||||
这适用于mpv.net的所有打开文件或url的功能。
|
|
||||||
|
|
||||||
在打开单个文件时按下SHIFT键将禁止该文件夹的其它文件添加到播放列表中。
|
在打开单个文件时按下SHIFT键将禁止该文件夹的其它文件添加到播放列表中。
|
||||||
|
|
||||||
@@ -770,6 +710,7 @@ https://mpv.io/manual/master/#window
|
|||||||
- [keepaspect-window](https://mpv.io/manual/master/#options-keepaspect-window)
|
- [keepaspect-window](https://mpv.io/manual/master/#options-keepaspect-window)
|
||||||
- [ontop](https://mpv.io/manual/master/#options-ontop)
|
- [ontop](https://mpv.io/manual/master/#options-ontop)
|
||||||
- [screen](https://mpv.io/manual/master/#options-screen)
|
- [screen](https://mpv.io/manual/master/#options-screen)
|
||||||
|
- [snap-window](https://mpv.io/manual/master/#options-snap-window)
|
||||||
- [title](https://mpv.io/manual/master/#options-title)
|
- [title](https://mpv.io/manual/master/#options-title)
|
||||||
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
|
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
|
||||||
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized)
|
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized)
|
||||||
@@ -779,8 +720,11 @@ https://mpv.io/manual/master/#window
|
|||||||
**部分支持的属性:**
|
**部分支持的属性:**
|
||||||
|
|
||||||
- [autofit](https://mpv.io/manual/master/#options-autofit)
|
- [autofit](https://mpv.io/manual/master/#options-autofit)
|
||||||
|
仅支持0-100范围内的整数
|
||||||
- [autofit-smaller](https://mpv.io/manual/master/#options-autofit-smaller)
|
- [autofit-smaller](https://mpv.io/manual/master/#options-autofit-smaller)
|
||||||
|
同上
|
||||||
- [autofit-larger](https://mpv.io/manual/master/#options-autofit-larger)
|
- [autofit-larger](https://mpv.io/manual/master/#options-autofit-larger)
|
||||||
|
同上
|
||||||
|
|
||||||
|
|
||||||
mpv.net的专属窗口功能在 [屏幕设置](#screen) 部分。
|
mpv.net的专属窗口功能在 [屏幕设置](#screen) 部分。
|
||||||
@@ -802,9 +746,7 @@ mpv.net支持基于属性的mpv命令行选项,这意味着它支持mpv几乎
|
|||||||
|
|
||||||
### 其它限制
|
### 其它限制
|
||||||
|
|
||||||
mpv的属性 [idle](https://mpv.io/manual/master/#options-idle) 在mpv.net中
|
mpv的属性 [idle](https://mpv.io/manual/master/#options-idle) 在mpv.net中也会相应的发挥作用,但是LUA脚本获取到的值始终是 `yes` ,因为mpv.net必须设置它才能正常工作,这是一个难以攻克的来自libmpv的限制。
|
||||||
也会相应的发挥作用,但是LUA脚本获取到的值始终是 `yes` ,因为mpv.net必须
|
|
||||||
设置它才能正常工作,这是一个难以攻克的来自libmpv的限制。
|
|
||||||
|
|
||||||
|
|
||||||
### mpv.net的专属选项
|
### mpv.net的专属选项
|
||||||
@@ -819,8 +761,7 @@ mpv.net的专属选项保存在 mpvnet.conf 文件中,与mpv一样可由命令
|
|||||||
|
|
||||||
mpv.net使用 C#7 编写并且需要 .NET Framework 4.8 来运行。
|
mpv.net使用 C#7 编写并且需要 .NET Framework 4.8 来运行。
|
||||||
|
|
||||||
扩展的实现基于
|
扩展的实现基于 [Managed Extensibility Framework](https://docs.microsoft.com/en-us/dotnet/framework/mef/)
|
||||||
[Managed Extensibility Framework](https://docs.microsoft.com/en-us/dotnet/framework/mef/).
|
|
||||||
|
|
||||||
主窗口基于WinForms,与WPF相比对libmpv集成的更友好,所有其他窗口都是基于WPF的。
|
主窗口基于WinForms,与WPF相比对libmpv集成的更友好,所有其他窗口都是基于WPF的。
|
||||||
|
|
||||||
@@ -837,7 +778,7 @@ mpv.net的上下文菜单由设置目录中的文件 input.conf 定义。
|
|||||||
|
|
||||||
如果 input.conf 文件不存在,mpv.net由以下文件生成默认:
|
如果 input.conf 文件不存在,mpv.net由以下文件生成默认:
|
||||||
|
|
||||||
<https://github.com/stax76/mpv.net/tree/master/src/Resources/input.conf.txt>
|
<https://github.com/mpvnet-player/mpv.net/tree/master/src/Resources/input.conf.txt>
|
||||||
|
|
||||||
input.conf 定义mpv的快捷键,同时mpv.net使用注释定义上下文菜单。
|
input.conf 定义mpv的快捷键,同时mpv.net使用注释定义上下文菜单。
|
||||||
|
|
||||||
@@ -850,8 +791,7 @@ input.conf 定义mpv的快捷键,同时mpv.net使用注释定义上下文菜
|
|||||||
|
|
||||||
第三种方法是拖放文件到主窗口上。
|
第三种方法是拖放文件到主窗口上。
|
||||||
|
|
||||||
每当打开文件或URL时按下控制键时,播放列表不会被清除,但文件或URL会追加到播放列表中。
|
每当打开文件或URL时按下控制键时,播放列表不会被清除,但文件或URL会追加到播放列表中。这适用于所有打开文件或URL的mpv.net的功能。
|
||||||
这适用于所有打开文件或URL的mpv.net的功能。
|
|
||||||
|
|
||||||
在打开单个文件时按shift键将临时禁止加载文件夹中的其它文件。
|
在打开单个文件时按shift键将临时禁止加载文件夹中的其它文件。
|
||||||
|
|
||||||
@@ -870,14 +810,12 @@ input.conf 定义mpv的快捷键,同时mpv.net使用注释定义上下文菜
|
|||||||
|
|
||||||
### Open > Load external audio files
|
### Open > Load external audio files
|
||||||
|
|
||||||
允许加载外部音轨文件。也可以根据文件名自动检测,该选项可在下面的设置中找到
|
允许加载外部音轨文件。也可以根据文件名自动检测,该选项可在下面的设置中找到 'Settings > Show Config Editor > Audio > audio-file-auto'
|
||||||
'Settings > Show Config Editor > Audio > audio-file-auto' 。
|
|
||||||
|
|
||||||
|
|
||||||
### Open > Load external subtitle files
|
### Open > Load external subtitle files
|
||||||
|
|
||||||
允许加载外部字幕文件。也可以根据文件名自动检测,该选项可在下面的设置中找到
|
允许加载外部字幕文件。也可以根据文件名自动检测,该选项可在下面的设置中找到 'Settings > Show Config Editor > Subtitles > sub-auto'
|
||||||
'Settings > Show Config Editor > Subtitles > sub-auto' 。
|
|
||||||
|
|
||||||
|
|
||||||
### Play/Pause
|
### Play/Pause
|
||||||
@@ -975,8 +913,7 @@ input.conf 定义mpv的快捷键,同时mpv.net使用注释定义上下文菜
|
|||||||
|
|
||||||
`no-osd seek sec`
|
`no-osd seek sec`
|
||||||
|
|
||||||
sec是跳转的相对秒数,使用no osd前缀是因为mpv.net包含一个脚本,
|
sec是跳转的相对秒数,使用no osd前缀是因为mpv.net包含一个脚本,该脚本显示执行寻道操作时的位置,该脚本使用更简单的时间格式。
|
||||||
该脚本显示执行寻道操作时的位置,该脚本使用更简单的时间格式。
|
|
||||||
|
|
||||||
[no-osd command prefix](https://mpv.io/manual/master/#command-interface-no-osd)
|
[no-osd command prefix](https://mpv.io/manual/master/#command-interface-no-osd)
|
||||||
|
|
||||||
@@ -1220,7 +1157,7 @@ sec是跳转的相对秒数,使用no osd前缀是因为mpv.net包含一个脚
|
|||||||
|
|
||||||
使用以下命令改变到下一个可用的字幕轨:
|
使用以下命令改变到下一个可用的字幕轨:
|
||||||
|
|
||||||
`cycle sub`
|
`script-message-to mpvnet cycle-subtitles`
|
||||||
|
|
||||||
[cycle command](https://mpv.io/manual/master/#command-interface-cycle-%3Cname%3E-[%3Cvalue%3E])
|
[cycle command](https://mpv.io/manual/master/#command-interface-cycle-%3Cname%3E-[%3Cvalue%3E])
|
||||||
|
|
||||||
@@ -1499,8 +1436,7 @@ input.conf 文件内涵mpv的键鼠绑定
|
|||||||
|
|
||||||
### Tools > Show History
|
### Tools > Show History
|
||||||
|
|
||||||
显示包含历史记录的文本文件。如果文件不存在,则会询问是否在设置文件夹中
|
显示包含历史记录的文本文件。如果文件不存在,则会询问是否在设置文件夹中创建该文件。一旦文件存在,则写入历史记录(包括时间和文件名)
|
||||||
创建该文件。一旦文件存在,则写入历史记录(包括时间和文件名)
|
|
||||||
|
|
||||||
屏蔽部分路径的参数:
|
屏蔽部分路径的参数:
|
||||||
|
|
||||||
@@ -1554,7 +1490,7 @@ script-opt = history-discard=path1;path2
|
|||||||
|
|
||||||
### Help > Show mpv.net manual
|
### Help > Show mpv.net manual
|
||||||
|
|
||||||
显示 [mpv.net手册](https://github.com/stax76/mpv.net/blob/master/Manual.md).
|
显示 [mpv.net手册](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md).
|
||||||
|
|
||||||
|
|
||||||
### Help > About mpv.net
|
### Help > About mpv.net
|
||||||
35
lang/create-mo-files.ps1
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$PoFiles = Get-ChildItem $PSScriptRoot/po
|
||||||
|
$ExeFolder = "$PSScriptRoot/../src/MpvNet.Windows/bin/Debug"
|
||||||
|
|
||||||
|
function CreateFolder
|
||||||
|
{
|
||||||
|
param($path)
|
||||||
|
|
||||||
|
if (-not (Test-Path $path))
|
||||||
|
{
|
||||||
|
mkdir $path
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $path))
|
||||||
|
{
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($it in $PoFiles)
|
||||||
|
{
|
||||||
|
$folder = "$ExeFolder/Locale/$($it.BaseName)/LC_MESSAGES"
|
||||||
|
|
||||||
|
if (-not (Test-Path $folder))
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Path $folder
|
||||||
|
}
|
||||||
|
|
||||||
|
$moPath = "$folder/mpvnet.mo"
|
||||||
|
msgfmt --output-file=$moPath $it.FullName
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
$moPath
|
||||||
|
}
|
||||||
114
lang/cs-files.txt
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\App.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\AppInfo.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Binding.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Chapter.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Command.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\CommandLine.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\ExtensionLoader.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\FileTypes.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Folder.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Global.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\GlobalUsings.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\InputConf.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\MediaTrack.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\MpvClient.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Player.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Settings.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\StringPair.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Terminal.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Translator.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\ExtensionMethod\ObjectExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\ExtensionMethod\PathStringExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\ExtensionMethod\StringExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Help\FileHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Help\MpvHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Help\ProcessHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Help\StringHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Help\TaskHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\MVVM\Messages.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Native\LibMpv.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Native\MediaInfo.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet\Native\StringLogicalComparer.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Extension\ExampleExtension\ExampleExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Conf.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\FileAssociation.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\GlobalUsings.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Program.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Settings.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Help\RegistryHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Help\WinApiHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Native\StockIcon.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Native\Taskbar.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Native\WinApi.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\UI\CommandPalette.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\UI\CommandPaletteItem.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\UI\GlobalHotkey.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\UI\Theme.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\UI\TreeNode.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.Designer.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\SnapManager.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\BindingProxy.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\ComboBoxTemplateSelector.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\ConfWindow.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\InputWindow.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\ISettingControl.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\LearnWindow.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MenuHelp.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Msg.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\WpfApplication.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\WpfTranslator.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Controls\ComboBoxSettingControl.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Controls\CommandPaletteControl.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Controls\HyperlinkEx.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Controls\OptionSettingControl.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Controls\SearchControl.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Controls\StringSettingControl.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Controls\ScrollViewer.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Controls\SimplePanel.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Controls\Attach\BorderElement.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Controls\Attach\IconElement.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Controls\Attach\MenuTopLineAttach.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Controls\Attach\ScrollViewerAttach.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Data\ValueBoxes.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\AnimationHelper.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\RegexPatterns.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Converter\BorderCircularConverter.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Extension\StringExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Helper\ScreenHelper.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Helper\VisualHelper.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Interop\InteropMethods.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Interop\InteropValues.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Interop\Handle\BitmapHandle.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Interop\Handle\CommonHandles.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Interop\Handle\HandleCollector.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\HandyControl\Tools\Interop\Handle\WpfSafeHandle.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MessageBoxEx.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MsgBoxExCheckBoxData.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MsgBoxExDelegate.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MsgBoxExStatic.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MsgBoxExtendedFunctionality.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MsgBoxUrl.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\MsgBox\MsgEnum.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\ViewModels\AboutViewModel.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\ViewModels\NodeViewModel.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\ViewModels\ViewModelBase.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\Views\AboutWindow.xaml.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\ChangeCultureCommand.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\CompositionRoot.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\CultureEventArgs.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\CultureTracker.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\GettextExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\GettextFormatConverterExtension.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\IWeakCultureObserver.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\Localizer.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\TrackCurrentCultureBehavior.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\Translation.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\Common\GettextStringFormatConverter.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\EnumTranslation\EnumLocalizer.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\EnumTranslation\EnumMsgIdAttribute.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\EnumTranslation\LocalizeEnumConverter.cs
|
||||||
|
D:\Projects\CS\mpv.net\src\NGettext.Wpf\Properties\AssemblyInfo.cs
|
||||||
823
lang/po/de.po
Normal file
@@ -0,0 +1,823 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# Frank Skare, 2023
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-12-26 10:28+0100\n"
|
||||||
|
"PO-Revision-Date: 2023-12-08 00:34+0000\n"
|
||||||
|
"Last-Translator: Frank Skare, 2023\n"
|
||||||
|
"Language-Team: German (https://app.transifex.com/stax76/teams/179964/de/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: de\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:12
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:13
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:14
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:15
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:16
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:17
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:18
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:19
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:20
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:21
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:22
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:23
|
||||||
|
msgid "File"
|
||||||
|
msgstr "Datei"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:12
|
||||||
|
msgid "Open Files..."
|
||||||
|
msgstr "Dateien öffnen..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:13
|
||||||
|
msgid "Open URL or file from clipboard"
|
||||||
|
msgstr "URL oder Datei aus der Zwischenablage öffnen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:14
|
||||||
|
msgid "Open DVD/Blu-ray Drive/Folder..."
|
||||||
|
msgstr "DVD/Blu-ray-Laufwerk/Ordner öffnen..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:16
|
||||||
|
msgid "Add external audio files..."
|
||||||
|
msgstr "Externe Audiodateien hinzufügen..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:17
|
||||||
|
msgid "Add external subtitle files..."
|
||||||
|
msgstr "Externe Untertiteldateien hinzufügen..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:19
|
||||||
|
msgid "Add files to playlist..."
|
||||||
|
msgstr "Dateien zur Wiedergabeliste hinzufügen..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:20
|
||||||
|
msgid "Add files/URLs to playlist from clipboard"
|
||||||
|
msgstr "Dateien/URLs zur Wiedergabeliste aus der Zwischenablage hinzufügen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:22
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:380
|
||||||
|
msgid "Recent Files"
|
||||||
|
msgstr "Zuletzt geöffnete Dateien"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:23
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:179
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:213
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "Beenden"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:25
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:26
|
||||||
|
msgid "Playback"
|
||||||
|
msgstr "Wiedergabe"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:25
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:181
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:182
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:183
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:184
|
||||||
|
msgid "Play/Pause"
|
||||||
|
msgstr "Wiedergabe/Pause"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:26
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:185
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "Stopp"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:28
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:29
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:30
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:31
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:32
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:34
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:35
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:36
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:37
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:38
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:39
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:40
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:41
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:42
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:43
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:44
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:45
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:46
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:47
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:48
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:49
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:50
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:51
|
||||||
|
msgid "Navigate"
|
||||||
|
msgstr "Navigieren"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:28
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:192
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:194
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:196
|
||||||
|
msgid "Previous File"
|
||||||
|
msgstr "Vorherige Datei"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:29
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:193
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:195
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:197
|
||||||
|
msgid "Next File"
|
||||||
|
msgstr "Nächste Datei"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:31
|
||||||
|
msgid "First File"
|
||||||
|
msgstr "Erste Datei"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:32
|
||||||
|
msgid "Last File"
|
||||||
|
msgstr "Letzte Datei"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:35
|
||||||
|
msgid "Next Chapter"
|
||||||
|
msgstr "Nächstes Kapitel"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:36
|
||||||
|
msgid "Previous Chapter"
|
||||||
|
msgstr "Vorheriges Kapitel"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:38
|
||||||
|
msgid "Jump To Next Frame"
|
||||||
|
msgstr "Zum nächsten Bild springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:39
|
||||||
|
msgid "Jump To Previous Frame"
|
||||||
|
msgstr "Zum vorherigen Bild springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:41
|
||||||
|
msgid "Jump 5 sec forward"
|
||||||
|
msgstr "5 Sekunden vorwärts springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:42
|
||||||
|
msgid "Jump 5 sec backward"
|
||||||
|
msgstr "5 Sekunden rückwärts springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:44
|
||||||
|
msgid "Jump 30 sec forward"
|
||||||
|
msgstr "30 Sekunden vorwärts springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:45
|
||||||
|
msgid "Jump 30 sec backward"
|
||||||
|
msgstr "30 Sekunden rückwärts springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:47
|
||||||
|
msgid "Jump 5 min forward"
|
||||||
|
msgstr "5 Minuten vorwärts springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:48
|
||||||
|
msgid "Jump 5 min backward"
|
||||||
|
msgstr "5 Minuten rückwärts springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:50
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:402
|
||||||
|
msgid "Title"
|
||||||
|
msgstr "Titel"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:51
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:359
|
||||||
|
msgid "Chapter"
|
||||||
|
msgstr "Kapitel"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:53
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:54
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:55
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:56
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:57
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:58
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:59
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:60
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:61
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:62
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:63
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:64
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:65
|
||||||
|
msgid "Pan & Scan"
|
||||||
|
msgstr "Pan & Scan"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:53
|
||||||
|
msgid "Decrease Size"
|
||||||
|
msgstr "Größe verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:54
|
||||||
|
msgid "Increase Size"
|
||||||
|
msgstr "Größe erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:56
|
||||||
|
msgid "Move Left"
|
||||||
|
msgstr "Nach links bewegen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:57
|
||||||
|
msgid "Move Right"
|
||||||
|
msgstr "Nach rechts bewegen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:59
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:96
|
||||||
|
msgid "Move Up"
|
||||||
|
msgstr "Nach oben bewegen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:60
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:97
|
||||||
|
msgid "Move Down"
|
||||||
|
msgstr "Nach unten bewegen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:62
|
||||||
|
msgid "Decrease Height"
|
||||||
|
msgstr "Höhe verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:63
|
||||||
|
msgid "Increase Height"
|
||||||
|
msgstr "Höhe erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:65
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:117
|
||||||
|
msgid "Reset"
|
||||||
|
msgstr "Zurücksetzen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:67
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:68
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:69
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:70
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:71
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:72
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:73
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:74
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:75
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:76
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:77
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:78
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:79
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:80
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:81
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:82
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:83
|
||||||
|
msgid "Video"
|
||||||
|
msgstr "Video"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:67
|
||||||
|
msgid "Decrease Contrast"
|
||||||
|
msgstr "Kontrast verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:68
|
||||||
|
msgid "Increase Contrast"
|
||||||
|
msgstr "Kontrast erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:70
|
||||||
|
msgid "Decrease Brightness"
|
||||||
|
msgstr "Helligkeit verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:71
|
||||||
|
msgid "Increase Brightness"
|
||||||
|
msgstr "Helligkeit erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:73
|
||||||
|
msgid "Decrease Gamma"
|
||||||
|
msgstr "Gamma verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:74
|
||||||
|
msgid "Increase Gamma"
|
||||||
|
msgstr "Gamma erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:76
|
||||||
|
msgid "Decrease Saturation"
|
||||||
|
msgstr "Sättigung verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:77
|
||||||
|
msgid "Increase Saturation"
|
||||||
|
msgstr "Sättigung erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:79
|
||||||
|
msgid "Take Screenshot"
|
||||||
|
msgstr "Bildschirmfoto machen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:80
|
||||||
|
msgid "Take Screenshot without subtitles"
|
||||||
|
msgstr "Bildschirmfoto ohne Untertitel machen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:81
|
||||||
|
msgid "Toggle Deinterlace"
|
||||||
|
msgstr "Deinterlace umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:82
|
||||||
|
msgid "Change Aspect Ratio"
|
||||||
|
msgstr "Seitenverhältnis ändern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:83
|
||||||
|
msgid "Rotate Video"
|
||||||
|
msgstr "Video drehen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:85
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:86
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:87
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:88
|
||||||
|
msgid "Audio"
|
||||||
|
msgstr "Audio"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:85
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:90
|
||||||
|
msgid "Next Track"
|
||||||
|
msgstr "Nächster Titel"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:87
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:94
|
||||||
|
msgid "Delay +0.1"
|
||||||
|
msgstr "Verzögerung +0.1"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:88
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:93
|
||||||
|
msgid "Delay -0.1"
|
||||||
|
msgstr "Verzögerung -0.1"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:90
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:91
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:92
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:93
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:94
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:95
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:96
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:97
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:98
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:99
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:100
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:101
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
msgid "Subtitle"
|
||||||
|
msgstr "Untertitel"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:91
|
||||||
|
msgid "Toggle Visibility"
|
||||||
|
msgstr "Sichtbarkeit umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:99
|
||||||
|
msgid "Decrease Font Size"
|
||||||
|
msgstr "Schriftgröße verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:100
|
||||||
|
msgid "Increase Font Size"
|
||||||
|
msgstr "Schriftgröße erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "More"
|
||||||
|
msgstr "Mehr"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
msgid "Toggle overriding SSA/ASS styles with normal styles"
|
||||||
|
msgstr "Überschreiben von SSA/ASS-Stilen mit normalen Stilen umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:104
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:297
|
||||||
|
msgid "Track"
|
||||||
|
msgstr "Spur"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:106
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:107
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:108
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:109
|
||||||
|
msgid "Volume"
|
||||||
|
msgstr "Lautstärke"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:106
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
msgid "Up"
|
||||||
|
msgstr "Hoch"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:107
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
msgid "Down"
|
||||||
|
msgstr "Runter"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:109
|
||||||
|
msgid "Mute"
|
||||||
|
msgstr "Stumm"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:111
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:112
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:113
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:114
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:115
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:116
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:117
|
||||||
|
msgid "Speed"
|
||||||
|
msgstr "Geschwindigkeit"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:111
|
||||||
|
msgid "-10%"
|
||||||
|
msgstr "-10%"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:112
|
||||||
|
msgid "+10%"
|
||||||
|
msgstr "+10%"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:114
|
||||||
|
msgid "Half"
|
||||||
|
msgstr "Halb"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:115
|
||||||
|
msgid "Double"
|
||||||
|
msgstr "Doppelt"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:119
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:120
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:121
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:122
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:123
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:124
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:125
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "View"
|
||||||
|
msgstr "Ansicht"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:119
|
||||||
|
msgid "Show Playlist"
|
||||||
|
msgstr "Wiedergabeliste anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:120
|
||||||
|
msgid "Show Profiles"
|
||||||
|
msgstr "Profile anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:121
|
||||||
|
msgid "Toggle Statistics"
|
||||||
|
msgstr "Statistiken umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:122
|
||||||
|
msgid "Toggle OSC Visibility"
|
||||||
|
msgstr "Bildschirmschaltflächen-Sichtbarkeit umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:123
|
||||||
|
msgid "Show Media Info On-Screen"
|
||||||
|
msgstr "Medieninformationen auf dem Bildschirm anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:124
|
||||||
|
msgid "Show Media Info Message Box"
|
||||||
|
msgstr "Medieninformation in Nachrichtenbox anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:125
|
||||||
|
msgid "Show Progress"
|
||||||
|
msgstr "Fortschritt anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
msgid "Show Console"
|
||||||
|
msgstr "Konsole anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
msgid "Show Audio Devices"
|
||||||
|
msgstr "Audio-Geräte anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
msgid "Show Commands"
|
||||||
|
msgstr "Befehle anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "Show Bindings"
|
||||||
|
msgstr "Tastenkombinationen anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:131
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:134
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:144
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:145
|
||||||
|
msgid "Window"
|
||||||
|
msgstr "Fenster"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:131
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:199
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:200
|
||||||
|
msgid "Fullscreen"
|
||||||
|
msgstr "Vollbild"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:134
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
msgid "Zoom"
|
||||||
|
msgstr "Zoom"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
msgid "Enlarge"
|
||||||
|
msgstr "Vergrößern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
msgid "Shrink"
|
||||||
|
msgstr "Verkleinern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
msgid "50 %"
|
||||||
|
msgstr "50 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
msgid "100 %"
|
||||||
|
msgstr "100 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
msgid "200 %"
|
||||||
|
msgstr "200 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
msgid "300 %"
|
||||||
|
msgstr "300 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
msgid "Move"
|
||||||
|
msgstr "Verschieben"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
msgid "Left"
|
||||||
|
msgstr "Links"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
msgid "Right"
|
||||||
|
msgstr "Rechts"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
msgid "Center"
|
||||||
|
msgstr "Mitte"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:144
|
||||||
|
msgid "Toggle Border"
|
||||||
|
msgstr "Rahmen umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:145
|
||||||
|
msgid "Toggle On Top"
|
||||||
|
msgstr "Fenster im Vordergrund umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:147
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:435
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr "Profil"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:149
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:150
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:151
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:152
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:153
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:154
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:155
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:149
|
||||||
|
msgid "Show Config Editor"
|
||||||
|
msgstr "Konfigurationseditor anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:150
|
||||||
|
msgid "Show Input Editor"
|
||||||
|
msgstr "Tastenkombinationeneditor anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:152
|
||||||
|
msgid "Edit mpv.conf"
|
||||||
|
msgstr "mpv.conf bearbeiten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:153
|
||||||
|
msgid "Edit input.conf"
|
||||||
|
msgstr "input.conf bearbeiten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:155
|
||||||
|
msgid "Open Config Folder"
|
||||||
|
msgstr "Konfigurationsordner öffnen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Setup"
|
||||||
|
msgstr "Einrichten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
msgid "Register video file associations"
|
||||||
|
msgstr "Video-Dateizuordnungen registrieren"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
msgid "Register audio file associations"
|
||||||
|
msgstr "Audio-Dateizuordnungen registrieren"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
msgid "Register image file associations"
|
||||||
|
msgstr "Bild-Dateizuordnungen registrieren"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
msgid "Unregister file associations"
|
||||||
|
msgstr "Dateizuordnungen entfernen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Add mpv.net to Path environment variable"
|
||||||
|
msgstr "mpv.net zur Umgebungsvariable Path hinzufügen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:162
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:163
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:164
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:165
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:166
|
||||||
|
msgid "Tools"
|
||||||
|
msgstr "Werkzeuge"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:162
|
||||||
|
msgid "Set/clear A-B loop points"
|
||||||
|
msgstr "Setzen/Löschen von A-B Schleifenpunkten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:163
|
||||||
|
msgid "Toggle infinite file looping"
|
||||||
|
msgstr "Unendliche Dateischleife umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:164
|
||||||
|
msgid "Shuffle Playlist"
|
||||||
|
msgstr "Wiedergabeliste mischen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:165
|
||||||
|
msgid "Toggle Hardware Decoding"
|
||||||
|
msgstr "Hardware-Decodierung umschalten"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:166
|
||||||
|
msgid "Exit Watch Later"
|
||||||
|
msgstr "Beenden und später anschauen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:168
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:457
|
||||||
|
msgid "Custom"
|
||||||
|
msgstr "Benutzerdefiniert"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:170
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:171
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:172
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:173
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:174
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:175
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:176
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:177
|
||||||
|
msgid "Help"
|
||||||
|
msgstr "Hilfe"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:170
|
||||||
|
msgid "Website mpv"
|
||||||
|
msgstr "Webseite mpv"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:171
|
||||||
|
msgid "Website mpv.net"
|
||||||
|
msgstr "Webseite mpv.net"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:173
|
||||||
|
msgid "Manual mpv"
|
||||||
|
msgstr "Handbuch mpv"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:174
|
||||||
|
msgid "Manual mpv.net"
|
||||||
|
msgstr "Handbuch mpv.net"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:176
|
||||||
|
msgid "awesome-mpv"
|
||||||
|
msgstr "awesome-mpv"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:177
|
||||||
|
msgid "About mpv.net"
|
||||||
|
msgstr "Über mpv.net"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:180
|
||||||
|
msgid "Show Menu"
|
||||||
|
msgstr "Menü anzeigen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:186
|
||||||
|
msgid "Forward"
|
||||||
|
msgstr "Vorwärts"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:187
|
||||||
|
msgid "Backward"
|
||||||
|
msgstr "Rückwärts"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:188
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:190
|
||||||
|
msgid "Volume Up"
|
||||||
|
msgstr "Lautstärke erhöhen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:189
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:191
|
||||||
|
msgid "Volume Down"
|
||||||
|
msgstr "Lautstärke verringern"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:198
|
||||||
|
msgid "Ignore left mouse butten"
|
||||||
|
msgstr "Ignoriere die linke Maustaste"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:201
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:203
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:209
|
||||||
|
msgid "Seek Forward"
|
||||||
|
msgstr "Suchen vorwärts"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:202
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:204
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:210
|
||||||
|
msgid "Seek Backward"
|
||||||
|
msgstr "Suchen rückwärts"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:205
|
||||||
|
msgid "Undo previous (or marked) seek"
|
||||||
|
msgstr "Rückgängig machen vorherige (oder markierte) Suche"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:206
|
||||||
|
msgid "Mark position for revert-seek"
|
||||||
|
msgstr "Markieren der Position für die Rückwärtssuche"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:207
|
||||||
|
msgid "Seek to previous subtitle"
|
||||||
|
msgstr "Zum vorherigen Untertitel springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:208
|
||||||
|
msgid "Seek to next subtitle"
|
||||||
|
msgstr "Zum nächsten Untertitel springen"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:211
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:212
|
||||||
|
msgid "Quit encoding"
|
||||||
|
msgstr "Enkodierung beenden"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:164
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:184
|
||||||
|
msgid "Files/URLs were added to the playlist"
|
||||||
|
msgstr "Dateien/URLs wurden zur Wiedergabeliste hinzugefügt"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:177
|
||||||
|
msgid "The clipboard does not contain a valid URL or file."
|
||||||
|
msgstr "Die Zwischenablage enthält keine gültige URL oder Datei."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:228
|
||||||
|
msgid "File Explorer icons will refresh after process restart."
|
||||||
|
msgstr ""
|
||||||
|
"Datei-Explorer-Symbole werden nach dem Neustart des Prozesses aktualisiert."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:231
|
||||||
|
msgid "File associations were successfully removed."
|
||||||
|
msgstr "Dateizuordnungen wurden erfolgreich entfernt."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:233
|
||||||
|
msgid "File associations were successfully created."
|
||||||
|
msgstr "Dateizuordnungen wurden erfolgreich erstellt."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:236
|
||||||
|
msgid "Error creating file associations."
|
||||||
|
msgstr "Fehler beim Erstellen von Dateizuordnungen."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:333
|
||||||
|
msgid "mpv.net is already in Path."
|
||||||
|
msgstr "mpv.net ist bereits in Path enthalten."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:341
|
||||||
|
msgid "mpv.net successfully was added to Path."
|
||||||
|
msgstr "mpv.net wurde erfolgreich zu Path hinzugefügt."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs:79
|
||||||
|
msgid "editor_conf"
|
||||||
|
msgstr "editor_conf"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs:114
|
||||||
|
msgid "theme"
|
||||||
|
msgstr "theme"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:1396
|
||||||
|
msgid "Shutdown thread failed to complete within 10 seconds."
|
||||||
|
msgstr ""
|
||||||
|
"Shutdown-Thread konnte nicht innerhalb von 10 Sekunden abgeschlossen werden."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\InputWindow.xaml.cs:116
|
||||||
|
msgid "Changes will be available on next startup."
|
||||||
|
msgstr "Änderungen werden beim nächsten Start verfügbar sein."
|
||||||
822
lang/po/zh_CN.po
Normal file
@@ -0,0 +1,822 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
# Translators:
|
||||||
|
# dyphire, 2023
|
||||||
|
# nkh0472 <nkh0472@hotmail.com>, 2023
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-12-26 10:28+0100\n"
|
||||||
|
"PO-Revision-Date: 2023-12-08 00:34+0000\n"
|
||||||
|
"Last-Translator: nkh0472 <nkh0472@hotmail.com>, 2023\n"
|
||||||
|
"Language-Team: Chinese (China) (https://app.transifex.com/stax76/teams/179964/zh_CN/)\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: zh_CN\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:12
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:13
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:14
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:15
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:16
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:17
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:18
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:19
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:20
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:21
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:22
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:23
|
||||||
|
msgid "File"
|
||||||
|
msgstr "文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:12
|
||||||
|
msgid "Open Files..."
|
||||||
|
msgstr "打开文件..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:13
|
||||||
|
msgid "Open URL or file from clipboard"
|
||||||
|
msgstr "从剪贴板打开 URL 或文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:14
|
||||||
|
msgid "Open DVD/Blu-ray Drive/Folder..."
|
||||||
|
msgstr "打开 DVD/蓝光驱动器/文件夹..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:16
|
||||||
|
msgid "Add external audio files..."
|
||||||
|
msgstr "添加外部音频文件..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:17
|
||||||
|
msgid "Add external subtitle files..."
|
||||||
|
msgstr "添加外部字幕文件..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:19
|
||||||
|
msgid "Add files to playlist..."
|
||||||
|
msgstr "添加文件到播放列表..."
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:20
|
||||||
|
msgid "Add files/URLs to playlist from clipboard"
|
||||||
|
msgstr "将 文件/URL 从剪贴板添加到播放列表"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:22
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:380
|
||||||
|
msgid "Recent Files"
|
||||||
|
msgstr "近期文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:23
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:179
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:213
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "退出"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:25
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:26
|
||||||
|
msgid "Playback"
|
||||||
|
msgstr "回放"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:25
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:181
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:182
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:183
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:184
|
||||||
|
msgid "Play/Pause"
|
||||||
|
msgstr "播放/暂停"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:26
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:185
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr "停止"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:28
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:29
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:30
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:31
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:32
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:34
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:35
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:36
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:37
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:38
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:39
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:40
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:41
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:42
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:43
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:44
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:45
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:46
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:47
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:48
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:49
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:50
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:51
|
||||||
|
msgid "Navigate"
|
||||||
|
msgstr "导航"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:28
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:192
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:194
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:196
|
||||||
|
msgid "Previous File"
|
||||||
|
msgstr "上一个文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:29
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:193
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:195
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:197
|
||||||
|
msgid "Next File"
|
||||||
|
msgstr "下一个文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:31
|
||||||
|
msgid "First File"
|
||||||
|
msgstr "第一个文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:32
|
||||||
|
msgid "Last File"
|
||||||
|
msgstr "最后一个文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:35
|
||||||
|
msgid "Next Chapter"
|
||||||
|
msgstr "下一个章节"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:36
|
||||||
|
msgid "Previous Chapter"
|
||||||
|
msgstr "上一个章节"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:38
|
||||||
|
msgid "Jump To Next Frame"
|
||||||
|
msgstr "跳至下一帧"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:39
|
||||||
|
msgid "Jump To Previous Frame"
|
||||||
|
msgstr "跳至上一帧"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:41
|
||||||
|
msgid "Jump 5 sec forward"
|
||||||
|
msgstr "快进 5 秒"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:42
|
||||||
|
msgid "Jump 5 sec backward"
|
||||||
|
msgstr "快退 5 秒"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:44
|
||||||
|
msgid "Jump 30 sec forward"
|
||||||
|
msgstr "快进 30 秒"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:45
|
||||||
|
msgid "Jump 30 sec backward"
|
||||||
|
msgstr "快退 30 秒"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:47
|
||||||
|
msgid "Jump 5 min forward"
|
||||||
|
msgstr "快进 5 分钟"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:48
|
||||||
|
msgid "Jump 5 min backward"
|
||||||
|
msgstr "快退 5 分钟"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:50
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:402
|
||||||
|
msgid "Title"
|
||||||
|
msgstr "标题"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:51
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:359
|
||||||
|
msgid "Chapter"
|
||||||
|
msgstr "章节"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:53
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:54
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:55
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:56
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:57
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:58
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:59
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:60
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:61
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:62
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:63
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:64
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:65
|
||||||
|
msgid "Pan & Scan"
|
||||||
|
msgstr "平移&扫描"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:53
|
||||||
|
msgid "Decrease Size"
|
||||||
|
msgstr "缩减大小"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:54
|
||||||
|
msgid "Increase Size"
|
||||||
|
msgstr "增加大小"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:56
|
||||||
|
msgid "Move Left"
|
||||||
|
msgstr "左移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:57
|
||||||
|
msgid "Move Right"
|
||||||
|
msgstr "右移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:59
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:96
|
||||||
|
msgid "Move Up"
|
||||||
|
msgstr "上移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:60
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:97
|
||||||
|
msgid "Move Down"
|
||||||
|
msgstr "下移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:62
|
||||||
|
msgid "Decrease Height"
|
||||||
|
msgstr "降低高度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:63
|
||||||
|
msgid "Increase Height"
|
||||||
|
msgstr "增加高度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:65
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:117
|
||||||
|
msgid "Reset"
|
||||||
|
msgstr "重置"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:67
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:68
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:69
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:70
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:71
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:72
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:73
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:74
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:75
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:76
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:77
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:78
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:79
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:80
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:81
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:82
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:83
|
||||||
|
msgid "Video"
|
||||||
|
msgstr "视频"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:67
|
||||||
|
msgid "Decrease Contrast"
|
||||||
|
msgstr "降低对比度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:68
|
||||||
|
msgid "Increase Contrast"
|
||||||
|
msgstr "增加对比度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:70
|
||||||
|
msgid "Decrease Brightness"
|
||||||
|
msgstr "降低亮度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:71
|
||||||
|
msgid "Increase Brightness"
|
||||||
|
msgstr "增加亮度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:73
|
||||||
|
msgid "Decrease Gamma"
|
||||||
|
msgstr "降低伽马"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:74
|
||||||
|
msgid "Increase Gamma"
|
||||||
|
msgstr "增加伽马"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:76
|
||||||
|
msgid "Decrease Saturation"
|
||||||
|
msgstr "降低饱和度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:77
|
||||||
|
msgid "Increase Saturation"
|
||||||
|
msgstr "增加饱和度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:79
|
||||||
|
msgid "Take Screenshot"
|
||||||
|
msgstr "截屏"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:80
|
||||||
|
msgid "Take Screenshot without subtitles"
|
||||||
|
msgstr "截图(无字幕)"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:81
|
||||||
|
msgid "Toggle Deinterlace"
|
||||||
|
msgstr "切换 去隔行"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:82
|
||||||
|
msgid "Change Aspect Ratio"
|
||||||
|
msgstr "更改纵横比"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:83
|
||||||
|
msgid "Rotate Video"
|
||||||
|
msgstr "旋转视频"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:85
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:86
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:87
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:88
|
||||||
|
msgid "Audio"
|
||||||
|
msgstr "音频"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:85
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:90
|
||||||
|
msgid "Next Track"
|
||||||
|
msgstr "下一个轨道"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:87
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:94
|
||||||
|
msgid "Delay +0.1"
|
||||||
|
msgstr "延迟 +0.1"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:88
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:93
|
||||||
|
msgid "Delay -0.1"
|
||||||
|
msgstr "延迟 -0.1"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:90
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:91
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:92
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:93
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:94
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:95
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:96
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:97
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:98
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:99
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:100
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:101
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
msgid "Subtitle"
|
||||||
|
msgstr "字幕"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:91
|
||||||
|
msgid "Toggle Visibility"
|
||||||
|
msgstr "切换 可见性"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:99
|
||||||
|
msgid "Decrease Font Size"
|
||||||
|
msgstr "减小字体大小"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:100
|
||||||
|
msgid "Increase Font Size"
|
||||||
|
msgstr "增加字体大小"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "More"
|
||||||
|
msgstr "更多"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
msgid "Toggle overriding SSA/ASS styles with normal styles"
|
||||||
|
msgstr "切换 使用常规样式覆盖 SSA/ASS 样式"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:104
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:297
|
||||||
|
msgid "Track"
|
||||||
|
msgstr "轨道"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:106
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:107
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:108
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:109
|
||||||
|
msgid "Volume"
|
||||||
|
msgstr "音量"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:106
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
msgid "Up"
|
||||||
|
msgstr "上移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:107
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
msgid "Down"
|
||||||
|
msgstr "下移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:109
|
||||||
|
msgid "Mute"
|
||||||
|
msgstr "静音"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:111
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:112
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:113
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:114
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:115
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:116
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:117
|
||||||
|
msgid "Speed"
|
||||||
|
msgstr "速度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:111
|
||||||
|
msgid "-10%"
|
||||||
|
msgstr "-10%"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:112
|
||||||
|
msgid "+10%"
|
||||||
|
msgstr "+10%"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:114
|
||||||
|
msgid "Half"
|
||||||
|
msgstr "减半"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:115
|
||||||
|
msgid "Double"
|
||||||
|
msgstr "翻倍"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:119
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:120
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:121
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:122
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:123
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:124
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:125
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "View"
|
||||||
|
msgstr "查看"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:119
|
||||||
|
msgid "Show Playlist"
|
||||||
|
msgstr "显示播放列表"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:120
|
||||||
|
msgid "Show Profiles"
|
||||||
|
msgstr "显示配置文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:121
|
||||||
|
msgid "Toggle Statistics"
|
||||||
|
msgstr "切换 统计信息"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:122
|
||||||
|
msgid "Toggle OSC Visibility"
|
||||||
|
msgstr "切换 OSC 可见性"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:123
|
||||||
|
msgid "Show Media Info On-Screen"
|
||||||
|
msgstr "在 OSD 上显示媒体信息"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:124
|
||||||
|
msgid "Show Media Info Message Box"
|
||||||
|
msgstr "显示媒体信息消息框"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:125
|
||||||
|
msgid "Show Progress"
|
||||||
|
msgstr "显示进度"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
msgid "Show Console"
|
||||||
|
msgstr "显示控制台"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
msgid "Show Audio Devices"
|
||||||
|
msgstr "显示音频设备"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
msgid "Show Commands"
|
||||||
|
msgstr "显示命令"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "Show Bindings"
|
||||||
|
msgstr "显示键位绑定"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:131
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:134
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:144
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:145
|
||||||
|
msgid "Window"
|
||||||
|
msgstr "窗口"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:131
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:199
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:200
|
||||||
|
msgid "Fullscreen"
|
||||||
|
msgstr "全屏"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:134
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
msgid "Zoom"
|
||||||
|
msgstr "缩放"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
msgid "Enlarge"
|
||||||
|
msgstr "放大"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
msgid "Shrink"
|
||||||
|
msgstr "缩小"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
msgid "50 %"
|
||||||
|
msgstr "50 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
msgid "100 %"
|
||||||
|
msgstr "100 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
msgid "200 %"
|
||||||
|
msgstr "200 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
msgid "300 %"
|
||||||
|
msgstr "300 %"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
msgid "Move"
|
||||||
|
msgstr "移动"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
msgid "Left"
|
||||||
|
msgstr "左移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
msgid "Right"
|
||||||
|
msgstr "右移"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
msgid "Center"
|
||||||
|
msgstr "居中"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:144
|
||||||
|
msgid "Toggle Border"
|
||||||
|
msgstr "切换 边框"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:145
|
||||||
|
msgid "Toggle On Top"
|
||||||
|
msgstr "切换 置顶"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:147
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:435
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr "配置文件"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:149
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:150
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:151
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:152
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:153
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:154
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:155
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "设置"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:149
|
||||||
|
msgid "Show Config Editor"
|
||||||
|
msgstr "显示配置编辑器"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:150
|
||||||
|
msgid "Show Input Editor"
|
||||||
|
msgstr "显示输入编辑器"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:152
|
||||||
|
msgid "Edit mpv.conf"
|
||||||
|
msgstr "编辑 mpv.conf"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:153
|
||||||
|
msgid "Edit input.conf"
|
||||||
|
msgstr "编辑 input.conf"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:155
|
||||||
|
msgid "Open Config Folder"
|
||||||
|
msgstr "打开配置文件夹"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Setup"
|
||||||
|
msgstr "设置"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
msgid "Register video file associations"
|
||||||
|
msgstr "注册视频文件关联"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
msgid "Register audio file associations"
|
||||||
|
msgstr "注册音频文件关联"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
msgid "Register image file associations"
|
||||||
|
msgstr "注册图像文件关联"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
msgid "Unregister file associations"
|
||||||
|
msgstr "注销文件关联"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Add mpv.net to Path environment variable"
|
||||||
|
msgstr "将 mpv.net 添加到环境变量"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:162
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:163
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:164
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:165
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:166
|
||||||
|
msgid "Tools"
|
||||||
|
msgstr "工具"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:162
|
||||||
|
msgid "Set/clear A-B loop points"
|
||||||
|
msgstr "设置/清除 A-B 循环点"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:163
|
||||||
|
msgid "Toggle infinite file looping"
|
||||||
|
msgstr "切换 无限文件循环"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:164
|
||||||
|
msgid "Shuffle Playlist"
|
||||||
|
msgstr "随机播放列表"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:165
|
||||||
|
msgid "Toggle Hardware Decoding"
|
||||||
|
msgstr "切换 硬件解码"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:166
|
||||||
|
msgid "Exit Watch Later"
|
||||||
|
msgstr "退出(稍后观看)"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:168
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:457
|
||||||
|
msgid "Custom"
|
||||||
|
msgstr "自定义"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:170
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:171
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:172
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:173
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:174
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:175
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:176
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:177
|
||||||
|
msgid "Help"
|
||||||
|
msgstr "帮助"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:170
|
||||||
|
msgid "Website mpv"
|
||||||
|
msgstr "mpv 网址"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:171
|
||||||
|
msgid "Website mpv.net"
|
||||||
|
msgstr "mpv.net 网址"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:173
|
||||||
|
msgid "Manual mpv"
|
||||||
|
msgstr "mpv 手册"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:174
|
||||||
|
msgid "Manual mpv.net"
|
||||||
|
msgstr "mpv.net 手册"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:176
|
||||||
|
msgid "awesome-mpv"
|
||||||
|
msgstr "awesome-mpv"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:177
|
||||||
|
msgid "About mpv.net"
|
||||||
|
msgstr "关于 mpv.net"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:180
|
||||||
|
msgid "Show Menu"
|
||||||
|
msgstr "显示菜单"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:186
|
||||||
|
msgid "Forward"
|
||||||
|
msgstr "前进"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:187
|
||||||
|
msgid "Backward"
|
||||||
|
msgstr "后退"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:188
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:190
|
||||||
|
msgid "Volume Up"
|
||||||
|
msgstr "增加 音量"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:189
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:191
|
||||||
|
msgid "Volume Down"
|
||||||
|
msgstr "降低 音量"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:198
|
||||||
|
msgid "Ignore left mouse butten"
|
||||||
|
msgstr "忽略左键"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:201
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:203
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:209
|
||||||
|
msgid "Seek Forward"
|
||||||
|
msgstr "向前跳转"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:202
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:204
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:210
|
||||||
|
msgid "Seek Backward"
|
||||||
|
msgstr "向后跳转"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:205
|
||||||
|
msgid "Undo previous (or marked) seek"
|
||||||
|
msgstr "撤销之前(或标记的)跳转"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:206
|
||||||
|
msgid "Mark position for revert-seek"
|
||||||
|
msgstr "标记回退查找的位置"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:207
|
||||||
|
msgid "Seek to previous subtitle"
|
||||||
|
msgstr "跳至上一条字幕"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:208
|
||||||
|
msgid "Seek to next subtitle"
|
||||||
|
msgstr "跳至下一条字幕"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:211
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:212
|
||||||
|
msgid "Quit encoding"
|
||||||
|
msgstr "退出编码"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:164
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:184
|
||||||
|
msgid "Files/URLs were added to the playlist"
|
||||||
|
msgstr "已添加 文件/URL 到播放列表"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:177
|
||||||
|
msgid "The clipboard does not contain a valid URL or file."
|
||||||
|
msgstr "剪贴板中未包含有效的 URL 或文件。"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:228
|
||||||
|
msgid "File Explorer icons will refresh after process restart."
|
||||||
|
msgstr "文件资源管理器图标将在进程重新启动后刷新"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:231
|
||||||
|
msgid "File associations were successfully removed."
|
||||||
|
msgstr "文件关联已成功删除"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:233
|
||||||
|
msgid "File associations were successfully created."
|
||||||
|
msgstr "文件关联已成功创建"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:236
|
||||||
|
msgid "Error creating file associations."
|
||||||
|
msgstr "创建文件关联时出错"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:333
|
||||||
|
msgid "mpv.net is already in Path."
|
||||||
|
msgstr "mpv.net 已存在于环境变量"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:341
|
||||||
|
msgid "mpv.net successfully was added to Path."
|
||||||
|
msgstr "成功添加 mpv.net 到环境变量"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs:79
|
||||||
|
msgid "editor_conf"
|
||||||
|
msgstr "editor_conf"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs:114
|
||||||
|
msgid "theme"
|
||||||
|
msgstr "主题"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:1396
|
||||||
|
msgid "Shutdown thread failed to complete within 10 seconds."
|
||||||
|
msgstr "线程关闭未能在 10 秒内完成"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\InputWindow.xaml.cs:116
|
||||||
|
msgid "Changes will be available on next startup."
|
||||||
|
msgstr "更改将在下次启动时应用"
|
||||||
817
lang/source.pot
Normal file
@@ -0,0 +1,817 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-12-26 10:28+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:12
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:13
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:14
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:15
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:16
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:17
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:18
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:19
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:20
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:21
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:22
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:23
|
||||||
|
msgid "File"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:12
|
||||||
|
msgid "Open Files..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:13
|
||||||
|
msgid "Open URL or file from clipboard"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:14
|
||||||
|
msgid "Open DVD/Blu-ray Drive/Folder..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:16
|
||||||
|
msgid "Add external audio files..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:17
|
||||||
|
msgid "Add external subtitle files..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:19
|
||||||
|
msgid "Add files to playlist..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:20
|
||||||
|
msgid "Add files/URLs to playlist from clipboard"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:22
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:380
|
||||||
|
msgid "Recent Files"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:23
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:179
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:213
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:25
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:26
|
||||||
|
msgid "Playback"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:25
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:181
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:182
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:183
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:184
|
||||||
|
msgid "Play/Pause"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:26
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:185
|
||||||
|
msgid "Stop"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:28
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:29
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:30
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:31
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:32
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:34
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:35
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:36
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:37
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:38
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:39
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:40
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:41
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:42
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:43
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:44
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:45
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:46
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:47
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:48
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:49
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:50
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:51
|
||||||
|
msgid "Navigate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:28
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:192
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:194
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:196
|
||||||
|
msgid "Previous File"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:29
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:193
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:195
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:197
|
||||||
|
msgid "Next File"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:31
|
||||||
|
msgid "First File"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:32
|
||||||
|
msgid "Last File"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:35
|
||||||
|
msgid "Next Chapter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:36
|
||||||
|
msgid "Previous Chapter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:38
|
||||||
|
msgid "Jump To Next Frame"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:39
|
||||||
|
msgid "Jump To Previous Frame"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:41
|
||||||
|
msgid "Jump 5 sec forward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:42
|
||||||
|
msgid "Jump 5 sec backward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:44
|
||||||
|
msgid "Jump 30 sec forward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:45
|
||||||
|
msgid "Jump 30 sec backward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:47
|
||||||
|
msgid "Jump 5 min forward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:48
|
||||||
|
msgid "Jump 5 min backward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:50
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:402
|
||||||
|
msgid "Title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:51
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:359
|
||||||
|
msgid "Chapter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:53
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:54
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:55
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:56
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:57
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:58
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:59
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:60
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:61
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:62
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:63
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:64
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:65
|
||||||
|
msgid "Pan & Scan"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:53
|
||||||
|
msgid "Decrease Size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:54
|
||||||
|
msgid "Increase Size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:56
|
||||||
|
msgid "Move Left"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:57
|
||||||
|
msgid "Move Right"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:59
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:96
|
||||||
|
msgid "Move Up"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:60
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:97
|
||||||
|
msgid "Move Down"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:62
|
||||||
|
msgid "Decrease Height"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:63
|
||||||
|
msgid "Increase Height"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:65
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:117
|
||||||
|
msgid "Reset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:67
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:68
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:69
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:70
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:71
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:72
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:73
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:74
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:75
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:76
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:77
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:78
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:79
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:80
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:81
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:82
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:83
|
||||||
|
msgid "Video"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:67
|
||||||
|
msgid "Decrease Contrast"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:68
|
||||||
|
msgid "Increase Contrast"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:70
|
||||||
|
msgid "Decrease Brightness"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:71
|
||||||
|
msgid "Increase Brightness"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:73
|
||||||
|
msgid "Decrease Gamma"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:74
|
||||||
|
msgid "Increase Gamma"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:76
|
||||||
|
msgid "Decrease Saturation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:77
|
||||||
|
msgid "Increase Saturation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:79
|
||||||
|
msgid "Take Screenshot"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:80
|
||||||
|
msgid "Take Screenshot without subtitles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:81
|
||||||
|
msgid "Toggle Deinterlace"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:82
|
||||||
|
msgid "Change Aspect Ratio"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:83
|
||||||
|
msgid "Rotate Video"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:85
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:86
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:87
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:88
|
||||||
|
msgid "Audio"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:85
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:90
|
||||||
|
msgid "Next Track"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:87
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:94
|
||||||
|
msgid "Delay +0.1"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:88
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:93
|
||||||
|
msgid "Delay -0.1"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:90
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:91
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:92
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:93
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:94
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:95
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:96
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:97
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:98
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:99
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:100
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:101
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
msgid "Subtitle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:91
|
||||||
|
msgid "Toggle Visibility"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:99
|
||||||
|
msgid "Decrease Font Size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:100
|
||||||
|
msgid "Increase Font Size"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "More"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:102
|
||||||
|
msgid "Toggle overriding SSA/ASS styles with normal styles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:104
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:297
|
||||||
|
msgid "Track"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:106
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:107
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:108
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:109
|
||||||
|
msgid "Volume"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:106
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
msgid "Up"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:107
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
msgid "Down"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:109
|
||||||
|
msgid "Mute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:111
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:112
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:113
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:114
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:115
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:116
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:117
|
||||||
|
msgid "Speed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:111
|
||||||
|
msgid "-10%"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:112
|
||||||
|
msgid "+10%"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:114
|
||||||
|
msgid "Half"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:115
|
||||||
|
msgid "Double"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:119
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:120
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:121
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:122
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:123
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:124
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:125
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "View"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:119
|
||||||
|
msgid "Show Playlist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:120
|
||||||
|
msgid "Show Profiles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:121
|
||||||
|
msgid "Toggle Statistics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:122
|
||||||
|
msgid "Toggle OSC Visibility"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:123
|
||||||
|
msgid "Show Media Info On-Screen"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:124
|
||||||
|
msgid "Show Media Info Message Box"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:125
|
||||||
|
msgid "Show Progress"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:126
|
||||||
|
msgid "Show Console"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:127
|
||||||
|
msgid "Show Audio Devices"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:128
|
||||||
|
msgid "Show Commands"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:129
|
||||||
|
msgid "Show Bindings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:131
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:134
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:144
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:145
|
||||||
|
msgid "Window"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:131
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:199
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:200
|
||||||
|
msgid "Fullscreen"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:134
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
msgid "Zoom"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:132
|
||||||
|
msgid "Enlarge"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:133
|
||||||
|
msgid "Shrink"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:135
|
||||||
|
msgid "50 %"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:136
|
||||||
|
msgid "100 %"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:137
|
||||||
|
msgid "200 %"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:138
|
||||||
|
msgid "300 %"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:141
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:142
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
msgid "Move"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:139
|
||||||
|
msgid "Left"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:140
|
||||||
|
msgid "Right"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:143
|
||||||
|
msgid "Center"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:144
|
||||||
|
msgid "Toggle Border"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:145
|
||||||
|
msgid "Toggle On Top"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:147
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:435
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:149
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:150
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:151
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:152
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:153
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:154
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:155
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:149
|
||||||
|
msgid "Show Config Editor"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:150
|
||||||
|
msgid "Show Input Editor"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:152
|
||||||
|
msgid "Edit mpv.conf"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:153
|
||||||
|
msgid "Edit input.conf"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:155
|
||||||
|
msgid "Open Config Folder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Setup"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:156
|
||||||
|
msgid "Register video file associations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:157
|
||||||
|
msgid "Register audio file associations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:158
|
||||||
|
msgid "Register image file associations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:159
|
||||||
|
msgid "Unregister file associations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:160
|
||||||
|
msgid "Add mpv.net to Path environment variable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:162
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:163
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:164
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:165
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:166
|
||||||
|
msgid "Tools"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:162
|
||||||
|
msgid "Set/clear A-B loop points"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:163
|
||||||
|
msgid "Toggle infinite file looping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:164
|
||||||
|
msgid "Shuffle Playlist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:165
|
||||||
|
msgid "Toggle Hardware Decoding"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:166
|
||||||
|
msgid "Exit Watch Later"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:168
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:457
|
||||||
|
msgid "Custom"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:170
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:171
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:172
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:173
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:174
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:175
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:176
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:177
|
||||||
|
msgid "Help"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:170
|
||||||
|
msgid "Website mpv"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:171
|
||||||
|
msgid "Website mpv.net"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:173
|
||||||
|
msgid "Manual mpv"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:174
|
||||||
|
msgid "Manual mpv.net"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:176
|
||||||
|
msgid "awesome-mpv"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:177
|
||||||
|
msgid "About mpv.net"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:180
|
||||||
|
msgid "Show Menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:186
|
||||||
|
msgid "Forward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:187
|
||||||
|
msgid "Backward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:188
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:190
|
||||||
|
msgid "Volume Up"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:189
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:191
|
||||||
|
msgid "Volume Down"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:198
|
||||||
|
msgid "Ignore left mouse butten"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:201
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:203
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:209
|
||||||
|
msgid "Seek Forward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:202
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:204
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:210
|
||||||
|
msgid "Seek Backward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:205
|
||||||
|
msgid "Undo previous (or marked) seek"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:206
|
||||||
|
msgid "Mark position for revert-seek"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:207
|
||||||
|
msgid "Seek to previous subtitle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:208
|
||||||
|
msgid "Seek to next subtitle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:211
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet\InputHelp.cs:212
|
||||||
|
msgid "Quit encoding"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:164
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:184
|
||||||
|
msgid "Files/URLs were added to the playlist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:177
|
||||||
|
msgid "The clipboard does not contain a valid URL or file."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:228
|
||||||
|
msgid "File Explorer icons will refresh after process restart."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:231
|
||||||
|
msgid "File associations were successfully removed."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:233
|
||||||
|
msgid "File associations were successfully created."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:236
|
||||||
|
msgid "Error creating file associations."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:333
|
||||||
|
msgid "mpv.net is already in Path."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\GuiCommand.cs:341
|
||||||
|
msgid "mpv.net successfully was added to Path."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs:79
|
||||||
|
msgid "editor_conf"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\Properties\Resources.Designer.cs:114
|
||||||
|
msgid "theme"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WinForms\MainForm.cs:1396
|
||||||
|
msgid "Shutdown thread failed to complete within 10 seconds."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: D:\Projects\CS\mpv.net\src\MpvNet.Windows\WPF\InputWindow.xaml.cs:116
|
||||||
|
msgid "Changes will be available on next startup."
|
||||||
|
msgstr ""
|
||||||
23
lang/update-po-and-pot-files.ps1
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
# Write list of .cs files into cs-files.txt file
|
||||||
|
Get-ChildItem $PSScriptRoot/.. -Recurse -File -Filter '*.cs' |
|
||||||
|
Where-Object { $_ -notmatch '[/\\]obj[/\\]' } |
|
||||||
|
ForEach-Object { $_.FullName } |
|
||||||
|
Out-File $PSScriptRoot/cs-files.txt
|
||||||
|
|
||||||
|
# Create .pot file
|
||||||
|
xgettext --force-po --from-code=UTF-8 '--language=c#' -o $PSScriptRoot/source.pot --files-from=$PSScriptRoot/cs-files.txt --keyword=_
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
# Backup .po files
|
||||||
|
$BackupTargetFolder = $env:TEMP + '/mpv.net po backup ' + (Get-Date -Format 'yyyy-MM-dd HH_mm_ss')
|
||||||
|
Copy-Item $PSScriptRoot/po $BackupTargetFolder -Force -Recurse
|
||||||
|
'PO file backup: ' + (Resolve-Path $BackupTargetFolder)
|
||||||
|
|
||||||
|
# Update .po files
|
||||||
|
(Get-ChildItem $PSScriptRoot/PO -Filter '*.po').FullName |
|
||||||
|
ForEach-Object { msgmerge --sort-output --backup=none --update $_ $PSScriptRoot/source.pot }
|
||||||
|
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
@@ -1,22 +1,7 @@
|
|||||||
[*.cs]
|
[*.cs]
|
||||||
|
|
||||||
# IDE0058: Expression value is never used
|
# IDE0090: Use 'new(...)'
|
||||||
dotnet_diagnostic.IDE0058.severity = none
|
csharp_style_implicit_object_creation_when_type_is_apparent = true
|
||||||
|
|
||||||
# IDE0055: Fix formatting
|
# IDE0090: Use 'new(...)'
|
||||||
dotnet_diagnostic.IDE0055.severity = none
|
dotnet_diagnostic.IDE0090.severity = silent
|
||||||
|
|
||||||
# IDE0022: Use block body for methods
|
|
||||||
dotnet_diagnostic.IDE0022.severity = none
|
|
||||||
|
|
||||||
# IDE0040: Add accessibility modifiers
|
|
||||||
dotnet_diagnostic.IDE0040.severity = none
|
|
||||||
|
|
||||||
# IDE0011: Add braces
|
|
||||||
dotnet_diagnostic.IDE0011.severity = none
|
|
||||||
|
|
||||||
# IDE0010: Add missing cases
|
|
||||||
dotnet_diagnostic.IDE0010.severity = none
|
|
||||||
|
|
||||||
# IDE0044: Add readonly modifier
|
|
||||||
dotnet_diagnostic.IDE0044.severity = silent
|
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
|
|
||||||
// This extension writes a rating to the filename of rated videos when mpv.net shuts down.
|
|
||||||
|
|
||||||
// The input.conf setup:
|
|
||||||
|
|
||||||
// KP0 script-message rate-file 0 #menu: Extensions > Rating > 0stars
|
|
||||||
// KP1 script-message rate-file 1 #menu: Extensions > Rating > 1stars
|
|
||||||
// KP2 script-message rate-file 2 #menu: Extensions > Rating > 2stars
|
|
||||||
// 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
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.Composition;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
using Microsoft.VisualBasic.FileIO;
|
|
||||||
|
|
||||||
using mpvnet;
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace RatingExtension // the assembly name must end with 'Extension'!
|
|
||||||
{
|
|
||||||
[Export(typeof(IExtension))]
|
|
||||||
public class RatingExtension : IExtension
|
|
||||||
{
|
|
||||||
//Script script = new Script();
|
|
||||||
|
|
||||||
// dictionory to store the filename and the rating
|
|
||||||
Dictionary<string, int> Dic = new Dictionary<string, int>();
|
|
||||||
|
|
||||||
string FileToDelete;
|
|
||||||
DateTime DeleteTime;
|
|
||||||
|
|
||||||
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.GetPropertyString("path");
|
|
||||||
|
|
||||||
if (!File.Exists(path))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (rating == 0 || rating == 1)
|
|
||||||
Delete(rating);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Dic[path] = rating;
|
|
||||||
Core.CommandV("show-text", $"Rating: {rating}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args[1] == "about")
|
|
||||||
MessageBox.Show($"This extension writes a rating to the filename of rated videos " +
|
|
||||||
"when mpv.net shuts down." + BR2 +
|
|
||||||
"The input.conf defaults contain key bindings for this extension to set ratings.",
|
|
||||||
"Rating Extension");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Delete(int rating)
|
|
||||||
{
|
|
||||||
if (rating == 0)
|
|
||||||
{
|
|
||||||
FileToDelete = Core.GetPropertyString("path");
|
|
||||||
DeleteTime = DateTime.Now;
|
|
||||||
Core.CommandV("show-text", "Press 1 to delete file", "5000");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TimeSpan ts = DateTime.Now - DeleteTime;
|
|
||||||
string path = Core.GetPropertyString("path");
|
|
||||||
|
|
||||||
if (FileToDelete == path && ts.TotalSeconds < 5 && File.Exists(FileToDelete))
|
|
||||||
{
|
|
||||||
Core.Command("playlist-remove current");
|
|
||||||
int pos = Core.GetPropertyInt("playlist-pos");
|
|
||||||
|
|
||||||
if (pos == -1)
|
|
||||||
{
|
|
||||||
int count = Core.GetPropertyInt("playlist-count");
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
Core.SetPropertyInt("playlist-pos", count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
|
||||||
FileSystem.DeleteFile(FileToDelete, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +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>{55C88710-539D-4402-84C8-31694841C731}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>RatingExtension</RootNamespace>
|
|
||||||
<AssemblyName>RatingExtension</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Microsoft.VisualBasic" />
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.ComponentModel.Composition" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Drawing" />
|
|
||||||
<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="RatingExtension.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="ScriptDevelopment.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\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>
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
|
|
||||||
//// This script adds dynamic menu items for profile switching.
|
|
||||||
|
|
||||||
//// In input.conf add a menu item called 'Profiles'
|
|
||||||
|
|
||||||
//using mpvnet;
|
|
||||||
//using System.ComponentModel;
|
|
||||||
//using System.Linq;
|
|
||||||
|
|
||||||
//class Script
|
|
||||||
//{
|
|
||||||
// MainForm MainForm;
|
|
||||||
// CorePlayer Core;
|
|
||||||
|
|
||||||
// public Script()
|
|
||||||
// {
|
|
||||||
// Core = Global.Core;
|
|
||||||
// MainForm = MainForm.Instance;
|
|
||||||
// MainForm.ContextMenu.Opening += ContextMenu_Opening;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void ContextMenu_Opening(object sender, CancelEventArgs e)
|
|
||||||
// {
|
|
||||||
// MenuItem menuItem = MainForm.FindMenuItem("My Menu");
|
|
||||||
|
|
||||||
// if (menuItem == null)
|
|
||||||
// {
|
|
||||||
// Terminal.WriteError("Profiles menu item not found.", "switch-profile-context-menu.cs");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// menuItem.DropDownItems.Clear();
|
|
||||||
// var editionTracks = Core.MediaTracks.Where(track => track.Type == "e");
|
|
||||||
|
|
||||||
// foreach (int i in new[] {1, 2, 3})
|
|
||||||
// {
|
|
||||||
// MenuItem mi = new MenuItem(i.ToString());
|
|
||||||
// mi.Action = () => { Core.commandv("show-text", i.ToString()); };
|
|
||||||
// menuItem.DropDownItems.Add(mi);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
294
src/Misc/App.cs
@@ -1,294 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public static class App
|
|
||||||
{
|
|
||||||
public static List<string> TempFiles { get; } = new List<string>();
|
|
||||||
|
|
||||||
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; } = "height-session";
|
|
||||||
|
|
||||||
public static bool AutoLoadFolder { get; set; } = true;
|
|
||||||
public static bool AutoPlay { get; set; }
|
|
||||||
public static bool DebugMode { get; set; }
|
|
||||||
public static bool Exit { get; set; }
|
|
||||||
public static bool IsTerminalAttached { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
|
|
||||||
public static bool MediaInfo { get; set; } = true;
|
|
||||||
public static bool Queue { get; set; }
|
|
||||||
public static bool RememberVolume { get; set; } = true;
|
|
||||||
public static bool RememberWindowPosition { get; set; }
|
|
||||||
public static bool ShowLogo { get; set; } = true;
|
|
||||||
public static bool ShowSantaLogo { get; set; } = true;
|
|
||||||
|
|
||||||
public static int StartThreshold { get; set; } = 1500;
|
|
||||||
public static int RecentCount { get; set; } = 15;
|
|
||||||
|
|
||||||
public static float AutofitAudio { get; set; } = 0.7f;
|
|
||||||
public static float AutofitImage { get; set; } = 0.8f;
|
|
||||||
public static float MinimumAspectRatio { get; set; }
|
|
||||||
public static float MinimumAspectRatioAudio { get; set; }
|
|
||||||
public static float QuickBookmark { get; set; }
|
|
||||||
|
|
||||||
public static Extension Extension { get; set; }
|
|
||||||
|
|
||||||
public static bool IsDarkMode => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
|
|
||||||
|
|
||||||
static AppSettings _Settings;
|
|
||||||
|
|
||||||
public static AppSettings Settings {
|
|
||||||
get {
|
|
||||||
if (_Settings == null)
|
|
||||||
_Settings = SettingsManager.Load();
|
|
||||||
|
|
||||||
return _Settings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Init()
|
|
||||||
{
|
|
||||||
var useless1 = Core.ConfigFolder;
|
|
||||||
var useless2 = Core.Conf;
|
|
||||||
|
|
||||||
foreach (var i in Conf)
|
|
||||||
ProcessProperty(i.Key, i.Value, true);
|
|
||||||
|
|
||||||
if (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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InitTheme();
|
|
||||||
|
|
||||||
Core.Shutdown += Core_Shutdown;
|
|
||||||
Core.Initialized += Core_Initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InitTheme()
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UpdateWpfColors()
|
|
||||||
{
|
|
||||||
var dic = System.Windows.Application.Current.Resources;
|
|
||||||
|
|
||||||
dic.Remove("BorderColor");
|
|
||||||
dic.Add("BorderColor", Theme.Current.GetColor("menu-highlight"));
|
|
||||||
|
|
||||||
dic.Remove("RegionColor");
|
|
||||||
dic.Add("RegionColor", Theme.Current.GetColor("menu-background"));
|
|
||||||
|
|
||||||
dic.Remove("SecondaryRegionColor");
|
|
||||||
dic.Add("SecondaryRegionColor", Theme.Current.GetColor("menu-highlight"));
|
|
||||||
|
|
||||||
dic.Remove("PrimaryTextColor");
|
|
||||||
dic.Add("PrimaryTextColor", Theme.Current.GetColor("menu-foreground"));
|
|
||||||
|
|
||||||
dic.Remove("HighlightColor");
|
|
||||||
dic.Add("HighlightColor", Theme.Current.GetColor("highlight"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RunTask(Action action)
|
|
||||||
{
|
|
||||||
Task.Run(() => {
|
|
||||||
try {
|
|
||||||
action.Invoke();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
ShowException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Version => "Copyright (C) 2000-2022 mpv.net/mpv/mplayer\n" +
|
|
||||||
$"mpv.net {Application.ProductVersion}" + GetLastWriteTime(Application.ExecutablePath) + "\n" +
|
|
||||||
$"{Core.GetPropertyString("mpv-version")}" + GetLastWriteTime(Folder.Startup + "mpv-2.dll") + "\n" +
|
|
||||||
$"ffmpeg {Core.GetPropertyString("ffmpeg-version")}\n" +
|
|
||||||
$"MediaInfo {FileVersionInfo.GetVersionInfo(Path.Combine(Application.StartupPath, "MediaInfo.dll")).FileVersion}" +
|
|
||||||
GetLastWriteTime(Path.Combine(Application.StartupPath , "MediaInfo.dll")) + "\nGPL v2 License";
|
|
||||||
|
|
||||||
static string GetLastWriteTime(string path)
|
|
||||||
{
|
|
||||||
if (IsStoreVrsion)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return $" ({File.GetLastWriteTime(path).ToShortDateString()})";
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsStoreVrsion => Application.StartupPath.Contains("FrankSkare.mpv.net");
|
|
||||||
|
|
||||||
public static void ShowException(object obj)
|
|
||||||
{
|
|
||||||
if (IsTerminalAttached)
|
|
||||||
Terminal.WriteError(obj.ToString());
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (obj is Exception e)
|
|
||||||
InvokeOnMainThread(() => Msg.ShowException(e));
|
|
||||||
else
|
|
||||||
InvokeOnMainThread(() => Msg.ShowError(obj.ToString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InvokeOnMainThread(Action action)
|
|
||||||
{
|
|
||||||
if (action == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (MainForm.Instance == null)
|
|
||||||
action.Invoke();
|
|
||||||
else
|
|
||||||
MainForm.Instance.BeginInvoke(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowInfo(string msg)
|
|
||||||
{
|
|
||||||
if (IsTerminalAttached)
|
|
||||||
{
|
|
||||||
if (msg != null)
|
|
||||||
Terminal.Write(msg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
InvokeOnMainThread(() => Msg.ShowInfo(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowError(string msg)
|
|
||||||
{
|
|
||||||
if (IsTerminalAttached)
|
|
||||||
{
|
|
||||||
if (msg != null)
|
|
||||||
Terminal.WriteError(msg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
InvokeOnMainThread(() => Msg.ShowError(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Core_Initialized()
|
|
||||||
{
|
|
||||||
if (RememberVolume)
|
|
||||||
{
|
|
||||||
Core.SetPropertyInt("volume", Settings.Volume);
|
|
||||||
Core.SetPropertyString("mute", Settings.Mute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Core_Shutdown()
|
|
||||||
{
|
|
||||||
Settings.Volume = Core.GetPropertyInt("volume");
|
|
||||||
Settings.Mute = Core.GetPropertyString("mute");
|
|
||||||
|
|
||||||
SettingsManager.Save(Settings);
|
|
||||||
|
|
||||||
foreach (string file in TempFiles)
|
|
||||||
FileHelp.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 "audio-file-extensions": CorePlayer.AudioTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
|
|
||||||
case "auto-load-folder": AutoLoadFolder = value == "yes"; return true;
|
|
||||||
case "auto-play": AutoPlay = value == "yes"; return true;
|
|
||||||
case "autofit-image": AutofitImage = value.Trim('%').ToInt() / 100f; return true;
|
|
||||||
case "autofit-audio": AutofitAudio = value.Trim('%').ToInt() / 100f; return true;
|
|
||||||
case "dark-mode": DarkMode = value; return true;
|
|
||||||
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
|
|
||||||
case "debug-mode": DebugMode = value == "yes"; return true;
|
|
||||||
case "image-file-extensions": CorePlayer.ImageTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
|
|
||||||
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
|
|
||||||
case "media-info": MediaInfo = value == "yes"; return true;
|
|
||||||
case "minimum-aspect-ratio": MinimumAspectRatio = value.ToFloat(); return true;
|
|
||||||
case "minimum-aspect-ratio-audio": MinimumAspectRatioAudio = value.ToFloat(); return true;
|
|
||||||
case "process-instance": ProcessInstance = value; return true;
|
|
||||||
case "queue": Queue = value == "yes"; return true;
|
|
||||||
case "recent-count": RecentCount = value.ToInt(); return true;
|
|
||||||
case "remember-volume": RememberVolume = value == "yes"; return true;
|
|
||||||
case "remember-window-position": RememberWindowPosition = value == "yes"; return true;
|
|
||||||
case "show-logo": ShowLogo = value == "yes"; return true;
|
|
||||||
case "show-santa-logo": ShowSantaLogo = value == "yes"; return true;
|
|
||||||
case "start-size": StartSize = value; return true;
|
|
||||||
case "start-threshold": StartThreshold = value.ToInt(); return true;
|
|
||||||
case "video-file-extensions": CorePlayer.VideoTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
|
|
||||||
default:
|
|
||||||
if (writeError)
|
|
||||||
Terminal.WriteError($"unknown mpvnet.conf property: {name}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CopyMpvnetCom()
|
|
||||||
{
|
|
||||||
string dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData).AddSep() +
|
|
||||||
"Microsoft\\WindowsApps\\";
|
|
||||||
|
|
||||||
if (File.Exists(dir + "mpvnet.exe") && !File.Exists(dir + "mpvnet.com"))
|
|
||||||
File.Copy(Folder.Startup + "mpvnet.com", dir + "mpvnet.com");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (string Title, string Path) GetTitleAndPath(string input)
|
|
||||||
{
|
|
||||||
if (input.Contains("|"))
|
|
||||||
{
|
|
||||||
var a = input.Split('|');
|
|
||||||
return (a[1], a[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (input, input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using Microsoft.CSharp;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
class CSharpScriptHost
|
|
||||||
{
|
|
||||||
static List<object> References = new List<object>();
|
|
||||||
|
|
||||||
public static void ExecuteScriptsInFolder(string folder)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(folder))
|
|
||||||
foreach (string file in Directory.GetFiles(folder, "*.cs"))
|
|
||||||
App.RunTask(() => Execute(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Execute(string file)
|
|
||||||
{
|
|
||||||
string code = File.ReadAllText(file);
|
|
||||||
string filename = Path.GetFileNameWithoutExtension(file) + " " + StringHelp.GetMD5Hash(code) + "-v6.dll";
|
|
||||||
string outputFile = Path.Combine(Path.GetTempPath(), filename);
|
|
||||||
|
|
||||||
if (!File.Exists(outputFile))
|
|
||||||
Compile(outputFile, file);
|
|
||||||
|
|
||||||
if (File.Exists(outputFile))
|
|
||||||
{
|
|
||||||
object instance = Assembly.LoadFile(outputFile).CreateInstance("Script");
|
|
||||||
|
|
||||||
if (instance != null)
|
|
||||||
References.Add(instance);
|
|
||||||
else
|
|
||||||
Terminal.WriteError("Failed to initialize script.", outputFile.FileName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Compile(string outputFile, string file)
|
|
||||||
{
|
|
||||||
CSharpCodeProvider provider = new CSharpCodeProvider();
|
|
||||||
CompilerParameters parameters = new CompilerParameters();
|
|
||||||
|
|
||||||
string[] dependencies = {
|
|
||||||
Folder.Startup + "mpvnet.exe",
|
|
||||||
"Microsoft.VisualBasic.dll",
|
|
||||||
"System.Core.dll", "System.Data.dll", "System.dll", "System.Drawing.dll", "System.Web.dll",
|
|
||||||
"System.Windows.Forms.dll", "System.Xaml.dll", "System.Xml.dll", "System.Xml.Linq.dll",
|
|
||||||
"WPF\\PresentationCore.dll", "WPF\\PresentationFramework.dll", "WPF\\WindowsBase.dll"
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (string i in dependencies)
|
|
||||||
parameters.ReferencedAssemblies.Add(i);
|
|
||||||
|
|
||||||
parameters.OutputAssembly = outputFile;
|
|
||||||
CompilerResults results = provider.CompileAssemblyFromFile(parameters, file);
|
|
||||||
|
|
||||||
var errors = results.Errors.Cast<CompilerError>().Select(i => "Line Number " +
|
|
||||||
i.Line + "\n" + "Error Number: " + i.ErrorNumber + "\n" + i.ErrorText);
|
|
||||||
|
|
||||||
if (errors.Count() > 0)
|
|
||||||
Terminal.WriteError(string.Join(BR2, errors), Path.GetFileName(file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,720 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Windows.Interop;
|
|
||||||
using System.Windows.Media;
|
|
||||||
|
|
||||||
using WinForms = System.Windows.Forms;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class Commands
|
|
||||||
{
|
|
||||||
public static void Execute(string id, string[] args)
|
|
||||||
{
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case "add-files-to-playlist": OpenFiles("append"); break; // deprecated 2019
|
|
||||||
case "cycle-audio": CycleAudio(); break;
|
|
||||||
case "execute-mpv-command": Msg.ShowError("The command was removed, reset input.conf by deleting it, in the new menu use the on screen console."); break; // deprecated 2020
|
|
||||||
case "load-audio": LoadAudio(); break;
|
|
||||||
case "load-sub": LoadSubtitle(); break;
|
|
||||||
case "open-clipboard": OpenFromClipboard(); break;
|
|
||||||
case "open-conf-folder": ProcessHelp.ShellExecute(Core.ConfigFolder); break;
|
|
||||||
case "open-files": OpenFiles(args); break;
|
|
||||||
case "open-optical-media": Open_DVD_Or_BD_Folder(); break;
|
|
||||||
case "open-url": OpenFromClipboard(); break; // deprecated 2022
|
|
||||||
case "play-pause": PlayPause(); break;
|
|
||||||
case "playlist-add": PlaylistAdd(Convert.ToInt32(args[0])); break;
|
|
||||||
case "playlist-first": PlaylistFirst(); break;
|
|
||||||
case "playlist-last": PlaylistLast(); break;
|
|
||||||
case "quick-bookmark": QuickBookmark(); break;
|
|
||||||
case "reg-file-assoc": RegisterFileAssociations(args[0]); break;
|
|
||||||
case "scale-window": ScaleWindow(float.Parse(args[0], CultureInfo.InvariantCulture)); break;
|
|
||||||
case "select-profile": SelectProfile(); break;
|
|
||||||
case "shell-execute": ProcessHelp.ShellExecute(args[0]); break;
|
|
||||||
case "show-about": ShowDialog(typeof(AboutWindow)); break;
|
|
||||||
case "show-audio-devices": Msg.ShowInfo(Core.GetPropertyOsdString("audio-device-list")); break;
|
|
||||||
case "show-audio-tracks": ShowAudioTracks(); break;
|
|
||||||
case "show-chapters": ShowChapters(); break;
|
|
||||||
case "show-command-palette": ShowCommandPalette(); break;
|
|
||||||
case "show-commands": ShowCommands(); break;
|
|
||||||
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
|
|
||||||
case "show-decoders": ShowStrings(mpvHelp.GetDecoders().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); break;
|
|
||||||
case "show-demuxers": ShowStrings(mpvHelp.GetDemuxers().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); break;
|
|
||||||
case "show-history": ShowHistory(); break;
|
|
||||||
case "show-info": ShowInfo(); break;
|
|
||||||
case "show-input-editor": ShowDialog(typeof(InputWindow)); break;
|
|
||||||
case "show-keys": ShowStrings(Core.GetPropertyString("input-key-list").Split(',')); break;
|
|
||||||
case "show-media-info": ShowMediaInfo(args); break;
|
|
||||||
case "show-menu": ShowMenu(); break;
|
|
||||||
case "show-playlist": ShowPlaylist(); break;
|
|
||||||
case "show-profiles": Msg.ShowInfo(mpvHelp.GetProfiles()); break;
|
|
||||||
case "show-progress": ShowProgress(); break;
|
|
||||||
case "show-properties": ShowProperties(); break;
|
|
||||||
case "show-protocols": ShowStrings(mpvHelp.GetProtocols().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); break;
|
|
||||||
case "show-recent": ShowRecent(); break;
|
|
||||||
case "show-setup-dialog": ShowSetupDialog(); break; // deprecated 2022
|
|
||||||
case "show-subtitle-tracks": ShowSubtitleTracks(); break;
|
|
||||||
case "show-text": ShowText(args[0], Convert.ToInt32(args[1]), Convert.ToInt32(args[2])); break;
|
|
||||||
case "window-scale": WindowScale(float.Parse(args[0], CultureInfo.InvariantCulture)); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowTextWithEditor(string name, string text)
|
|
||||||
{
|
|
||||||
string file = Path.Combine(Path.GetTempPath(), name + ".txt");
|
|
||||||
App.TempFiles.Add(file);
|
|
||||||
File.WriteAllText(file, BR + text.Trim() + BR);
|
|
||||||
ProcessHelp.ShellExecute(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowDialog(Type winType) => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
foreach (string arg in args)
|
|
||||||
if (arg == "append")
|
|
||||||
append = true;
|
|
||||||
|
|
||||||
App.InvokeOnMainThread(new Action(() => {
|
|
||||||
using (var d = new OpenFileDialog() { Multiselect = true })
|
|
||||||
if (d.ShowDialog() == DialogResult.OK)
|
|
||||||
Core.LoadFiles(d.FileNames, true, append);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Open_DVD_Or_BD_Folder() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
var dialog = new FolderBrowser();
|
|
||||||
|
|
||||||
if (dialog.Show())
|
|
||||||
Core.LoadDiskFolder(dialog.SelectedPath);
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void PlaylistFirst()
|
|
||||||
{
|
|
||||||
if (Core.PlaylistPos != 0)
|
|
||||||
Core.SetPropertyInt("playlist-pos", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void PlaylistLast()
|
|
||||||
{
|
|
||||||
int count = Core.GetPropertyInt("playlist-count");
|
|
||||||
|
|
||||||
if (Core.PlaylistPos < count - 1)
|
|
||||||
Core.SetPropertyInt("playlist-pos", count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void PlayPause()
|
|
||||||
{
|
|
||||||
int count = Core.GetPropertyInt("playlist-count");
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
Core.Command("cycle pause");
|
|
||||||
else if (App.Settings.RecentFiles.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (string i in App.Settings.RecentFiles)
|
|
||||||
{
|
|
||||||
if (i.Contains("://") || File.Exists(i))
|
|
||||||
{
|
|
||||||
Core.LoadFiles(new[] { i }, true, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowHistory()
|
|
||||||
{
|
|
||||||
if (File.Exists(Core.ConfigFolder + "history.txt"))
|
|
||||||
ProcessHelp.ShellExecute(Core.ConfigFolder + "history.txt");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Msg.ShowQuestion("Create history.txt file in config folder?" + BR2 +
|
|
||||||
"mpv.net will write the date, time and filename of opened files to it.") == MessageBoxResult.OK)
|
|
||||||
|
|
||||||
File.WriteAllText(Core.ConfigFolder + "history.txt", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int LastShowInfo;
|
|
||||||
|
|
||||||
public static void ShowInfo()
|
|
||||||
{
|
|
||||||
if (Core.PlaylistPos == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Environment.TickCount - LastShowInfo < 5000)
|
|
||||||
{
|
|
||||||
Core.Command("script-message-to mpvnet show-media-info osd");
|
|
||||||
LastShowInfo = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LastShowInfo = Environment.TickCount;
|
|
||||||
|
|
||||||
string text;
|
|
||||||
long fileSize = 0;
|
|
||||||
string path = Core.GetPropertyString("path");
|
|
||||||
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
fileSize = new FileInfo(path).Length;
|
|
||||||
|
|
||||||
if (CorePlayer.AudioTypes.Contains(path.Ext()))
|
|
||||||
{
|
|
||||||
text = Core.GetPropertyOsdString("filtered-metadata");
|
|
||||||
Core.CommandV("show-text", text, "5000");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (CorePlayer.ImageTypes.Contains(path.Ext()))
|
|
||||||
{
|
|
||||||
text = "Width: " + Core.GetPropertyInt("width") + "\n" +
|
|
||||||
"Height: " + Core.GetPropertyInt("height") + "\n" +
|
|
||||||
"Size: " + Convert.ToInt32(fileSize / 1024.0) + " KB\n" +
|
|
||||||
"Type: " + path.Ext().ToUpper();
|
|
||||||
|
|
||||||
Core.CommandV("show-text", text, "5000");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.Contains("://")) path = Core.GetPropertyString("media-title");
|
|
||||||
string videoFormat = Core.GetPropertyString("video-format").ToUpper();
|
|
||||||
string audioCodec = Core.GetPropertyString("audio-codec-name").ToUpper();
|
|
||||||
int width = Core.GetPropertyInt("video-params/w");
|
|
||||||
int height = Core.GetPropertyInt("video-params/h");
|
|
||||||
TimeSpan len = TimeSpan.FromSeconds(Core.GetPropertyDouble("duration"));
|
|
||||||
text = path.FileName() + "\n";
|
|
||||||
text += FormatTime(len.TotalMinutes) + ":" + FormatTime(len.Seconds) + "\n";
|
|
||||||
if (fileSize > 0) text += Convert.ToInt32(fileSize / 1024.0 / 1024.0) + " MB\n";
|
|
||||||
text += $"{width} x {height}\n";
|
|
||||||
text += $"{videoFormat}\n{audioCodec}";
|
|
||||||
Core.CommandV("show-text", text, "5000");
|
|
||||||
}
|
|
||||||
|
|
||||||
static string FormatTime(double value) => ((int)value).ToString("00");
|
|
||||||
|
|
||||||
public static void ShowProgress()
|
|
||||||
{
|
|
||||||
TimeSpan position = TimeSpan.FromSeconds(Core.GetPropertyDouble("time-pos"));
|
|
||||||
TimeSpan duration = TimeSpan.FromSeconds(Core.GetPropertyDouble("duration"));
|
|
||||||
|
|
||||||
string text = FormatTime(position.TotalMinutes) + ":" +
|
|
||||||
FormatTime(position.Seconds) + " / " +
|
|
||||||
FormatTime(duration.TotalMinutes) + ":" +
|
|
||||||
FormatTime(duration.Seconds) + " " +
|
|
||||||
DateTime.Now.ToString("H:mm dddd d MMMM", CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
Core.CommandV("show-text", text, "5000");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void OpenFromClipboard() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
if (WinForms.Clipboard.ContainsFileDropList())
|
|
||||||
{
|
|
||||||
string[] files = WinForms.Clipboard.GetFileDropList().Cast<string>().ToArray();
|
|
||||||
Core.LoadFiles(files, false, Control.ModifierKeys.HasFlag(Keys.Control));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string clipboard = WinForms.Clipboard.GetText();
|
|
||||||
List<string> files = new List<string>();
|
|
||||||
|
|
||||||
foreach (string i in clipboard.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
if (i.Contains("://") || File.Exists(i))
|
|
||||||
files.Add(i);
|
|
||||||
|
|
||||||
if (files.Count == 0)
|
|
||||||
{
|
|
||||||
App.ShowError("The clipboard does not contain a valid URL or file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Core.LoadFiles(files.ToArray(), false, Control.ModifierKeys.HasFlag(Keys.Control));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void LoadSubtitle() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
using (var d = new OpenFileDialog())
|
|
||||||
{
|
|
||||||
string path = Core.GetPropertyString("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() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
using (var d = new OpenFileDialog())
|
|
||||||
{
|
|
||||||
string path = Core.GetPropertyString("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()
|
|
||||||
{
|
|
||||||
Core.UpdateExternalTracks();
|
|
||||||
|
|
||||||
lock (Core.MediaTracksLock)
|
|
||||||
{
|
|
||||||
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
|
|
||||||
|
|
||||||
if (tracks.Length < 1)
|
|
||||||
{
|
|
||||||
Core.CommandV("show-text", "No audio tracks");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int aid = Core.GetPropertyInt("aid");
|
|
||||||
|
|
||||||
if (tracks.Length > 1)
|
|
||||||
{
|
|
||||||
if (++aid > tracks.Length)
|
|
||||||
aid = 1;
|
|
||||||
|
|
||||||
Core.CommandV("set", "aid", aid.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Core.CommandV("show-text", aid + "/" + tracks.Length + ": " + tracks[aid - 1].Text.Substring(3), "5000");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowCommands()
|
|
||||||
{
|
|
||||||
string jsonString = Core.GetPropertyString("command-list");
|
|
||||||
var jsonObject = jsonString.FromJson<List<Dictionary<string, object>>>().OrderBy(i => i["name"]);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (Dictionary<string, object> dic in jsonObject)
|
|
||||||
{
|
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine(dic["name"].ToString());
|
|
||||||
|
|
||||||
foreach (Dictionary<string, object> i2 in dic["args"] as List<object>)
|
|
||||||
{
|
|
||||||
string value = i2["name"].ToString() + " <" + i2["type"].ToString().ToLower() + ">";
|
|
||||||
|
|
||||||
if ((bool)i2["optional"] == true)
|
|
||||||
value = "[" + value + "]";
|
|
||||||
|
|
||||||
sb.AppendLine(" " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowTextWithEditor("command-list", sb.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ScaleWindow(float factor) => Core.RaiseScaleWindow(factor);
|
|
||||||
|
|
||||||
public static void WindowScale(float value) => Core.RaiseWindowScaleNET(value);
|
|
||||||
|
|
||||||
public static void ShowText(string text, int duration = 0, int fontSize = 0)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(text))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (duration == 0)
|
|
||||||
duration = Core.GetPropertyInt("osd-duration");
|
|
||||||
|
|
||||||
if (fontSize == 0)
|
|
||||||
fontSize = Core.GetPropertyInt("osd-font-size");
|
|
||||||
|
|
||||||
Core.Command("show-text \"${osd-ass-cc/0}{\\\\fs" + fontSize +
|
|
||||||
"}${osd-ass-cc/1}" + text + "\" " + duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowMediaInfo(string[] args) => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
if (args == null || args.Length == 0)
|
|
||||||
{
|
|
||||||
(string Name, string Value)[] pairs = {
|
|
||||||
("Show text box", "script-message-to mpvnet show-media-info default"),
|
|
||||||
("Show text editor", "script-message-to mpvnet show-media-info editor"),
|
|
||||||
("Show on screen", "script-message-to mpvnet show-media-info osd"),
|
|
||||||
("Show full", "script-message-to mpvnet show-media-info editor full"),
|
|
||||||
("Show raw", "script-message-to mpvnet show-media-info editor full raw") };
|
|
||||||
|
|
||||||
var list = pairs.Select(i => new CommandPaletteItem(i.Name, () => Core.Command(i.Value)));
|
|
||||||
CommandPalette.Instance.SetItems(list);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string path = Core.GetPropertyString("path");
|
|
||||||
string text = "";
|
|
||||||
|
|
||||||
bool full = args.Contains("full");
|
|
||||||
bool raw = args.Contains("raw");
|
|
||||||
bool editor = args.Contains("editor");
|
|
||||||
bool osd = args.Contains("osd");
|
|
||||||
|
|
||||||
if (App.MediaInfo && !osd && File.Exists(path) && !path.Contains(@"\\.\pipe\"))
|
|
||||||
using (MediaInfo mediaInfo = new MediaInfo(path))
|
|
||||||
text = Regex.Replace(mediaInfo.GetSummary(full, raw), "Unique ID.+", "");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Core.UpdateExternalTracks();
|
|
||||||
lock (Core.MediaTracksLock)
|
|
||||||
foreach (MediaTrack track in Core.MediaTracks)
|
|
||||||
text += track.Text + BR;
|
|
||||||
}
|
|
||||||
|
|
||||||
text = text.TrimEx();
|
|
||||||
|
|
||||||
if (editor)
|
|
||||||
ShowTextWithEditor("media-info", text);
|
|
||||||
else if (osd)
|
|
||||||
ShowText(text.Replace("\r", ""), 5000, 17);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MsgBoxEx.MessageBoxEx.MsgFontFamily = new FontFamily("Consolas");
|
|
||||||
Msg.ShowInfo(text);
|
|
||||||
MsgBoxEx.MessageBoxEx.MsgFontFamily = new FontFamily("Segoe UI");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowCommandPalette() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
CommandPalette.Instance.SetItems(CommandPalette.GetItems());
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowAudioTracks() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
Core.UpdateExternalTracks();
|
|
||||||
|
|
||||||
lock (Core.MediaTracksLock)
|
|
||||||
{
|
|
||||||
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
|
|
||||||
|
|
||||||
if (tracks.Length < 1)
|
|
||||||
{
|
|
||||||
Core.CommandV("show-text", "No audio tracks");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
|
|
||||||
|
|
||||||
foreach (MediaTrack i in tracks)
|
|
||||||
{
|
|
||||||
MediaTrack track = i;
|
|
||||||
|
|
||||||
CommandPaletteItem item = new CommandPaletteItem()
|
|
||||||
{
|
|
||||||
Text = track.Text,
|
|
||||||
Action = () => {
|
|
||||||
Core.CommandV("set", "aid", track.ID.ToString());
|
|
||||||
Core.CommandV("show-text", track.ID + "/" + tracks.Length + ": " +
|
|
||||||
tracks[track.ID - 1].Text.Substring(3), "5000");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowSubtitleTracks() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
Core.UpdateExternalTracks();
|
|
||||||
|
|
||||||
lock (Core.MediaTracksLock)
|
|
||||||
{
|
|
||||||
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "s").ToArray();
|
|
||||||
|
|
||||||
if (tracks.Length < 1)
|
|
||||||
{
|
|
||||||
Core.CommandV("show-text", "No subtitle tracks");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
|
|
||||||
|
|
||||||
foreach (MediaTrack i in tracks)
|
|
||||||
{
|
|
||||||
MediaTrack track = i;
|
|
||||||
|
|
||||||
CommandPaletteItem item = new CommandPaletteItem()
|
|
||||||
{
|
|
||||||
Text = track.Text,
|
|
||||||
Action = () => {
|
|
||||||
Core.CommandV("set", "sid", track.ID.ToString());
|
|
||||||
Core.CommandV("show-text", track.ID + "/" + tracks.Length + ": " +
|
|
||||||
tracks[track.ID - 1].Text.Substring(3), "5000");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowPlaylist() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
int count = Core.GetPropertyInt("playlist-count");
|
|
||||||
string currentPath = Core.GetPropertyString("path");
|
|
||||||
CommandPaletteItem currentItem = null;
|
|
||||||
|
|
||||||
if (count < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
int index = i;
|
|
||||||
string file = Core.GetPropertyString($"playlist/{i}/filename");
|
|
||||||
|
|
||||||
CommandPaletteItem item = new CommandPaletteItem()
|
|
||||||
{
|
|
||||||
Text = file.FileName(),
|
|
||||||
Action = () => Core.SetPropertyInt("playlist-pos", index)
|
|
||||||
};
|
|
||||||
|
|
||||||
items.Add(item);
|
|
||||||
|
|
||||||
if (currentPath.ToLowerEx() == file.ToLowerEx())
|
|
||||||
currentItem = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
|
|
||||||
if (currentItem != null)
|
|
||||||
{
|
|
||||||
CommandPalette.Instance.MainListView.SelectedItem = currentItem;
|
|
||||||
CommandPalette.Instance.MainListView.ScrollIntoView(
|
|
||||||
CommandPalette.Instance.MainListView.SelectedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowProperties() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
var props = Core.GetPropertyString("property-list").Split(',').OrderBy(prop => prop);
|
|
||||||
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
|
|
||||||
|
|
||||||
foreach (string i in props)
|
|
||||||
{
|
|
||||||
string prop = i;
|
|
||||||
|
|
||||||
CommandPaletteItem item = new CommandPaletteItem()
|
|
||||||
{
|
|
||||||
Text = prop,
|
|
||||||
Action = () =>
|
|
||||||
{
|
|
||||||
string propValue = Core.GetPropertyString(prop);
|
|
||||||
|
|
||||||
if (propValue.ContainsEx("${"))
|
|
||||||
propValue += BR2 + Core.Expand(propValue);
|
|
||||||
|
|
||||||
App.ShowInfo(prop + "\n\n" + propValue);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowRecent() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
|
|
||||||
|
|
||||||
foreach (string path in App.Settings.RecentFiles)
|
|
||||||
{
|
|
||||||
var file = App.GetTitleAndPath(path);
|
|
||||||
|
|
||||||
CommandPaletteItem item = new CommandPaletteItem()
|
|
||||||
{
|
|
||||||
Text = file.Title.ShortPath(60),
|
|
||||||
Action = () => Core.LoadFiles(new[] { file.Path }, true, Control.ModifierKeys.HasFlag(Keys.Control))
|
|
||||||
};
|
|
||||||
|
|
||||||
items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void RegisterFileAssociations(string perceivedType)
|
|
||||||
{
|
|
||||||
string[] extensions = { };
|
|
||||||
|
|
||||||
switch (perceivedType)
|
|
||||||
{
|
|
||||||
case "video": extensions = CorePlayer.VideoTypes; break;
|
|
||||||
case "audio": extensions = CorePlayer.AudioTypes; break;
|
|
||||||
case "image": extensions = CorePlayer.ImageTypes; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (Process proc = new Process())
|
|
||||||
{
|
|
||||||
proc.StartInfo.FileName = WinForms.Application.ExecutablePath;
|
|
||||||
proc.StartInfo.Arguments = "--register-file-associations " +
|
|
||||||
perceivedType + " " + string.Join(" ", extensions);
|
|
||||||
proc.StartInfo.Verb = "runas";
|
|
||||||
proc.StartInfo.UseShellExecute = true;
|
|
||||||
proc.Start();
|
|
||||||
proc.WaitForExit();
|
|
||||||
|
|
||||||
if (proc.ExitCode == 0)
|
|
||||||
Msg.ShowInfo("File associations were successfully " +
|
|
||||||
(perceivedType == "unreg" ? "removed" : "created") +
|
|
||||||
".\n\nFile Explorer icons will refresh after process restart.");
|
|
||||||
else
|
|
||||||
Msg.ShowError("Error creating file associations.");
|
|
||||||
}
|
|
||||||
} catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowStrings(string[] strings) => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
|
|
||||||
|
|
||||||
foreach (string i in strings)
|
|
||||||
{
|
|
||||||
string str = i;
|
|
||||||
|
|
||||||
CommandPaletteItem item = new CommandPaletteItem()
|
|
||||||
{
|
|
||||||
Text = str,
|
|
||||||
Action = () => Msg.ShowInfo(str)
|
|
||||||
};
|
|
||||||
|
|
||||||
items.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowSetupDialog() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
(string Name, string Value)[] pairs = {
|
|
||||||
("Register video file associations", "script-message-to mpvnet reg-file-assoc video"),
|
|
||||||
("Register audio file associations", "script-message-to mpvnet reg-file-assoc audio"),
|
|
||||||
("Register image file associations", "script-message-to mpvnet reg-file-assoc image"),
|
|
||||||
("Unregister file associations", "script-message-to mpvnet reg-file-assoc unreg") };
|
|
||||||
|
|
||||||
var list = pairs.Select(i => new CommandPaletteItem(i.Name, () => Core.Command(i.Value)));
|
|
||||||
CommandPalette.Instance.SetItems(list);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void SelectProfile() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
var items = Core.ProfileNames.Where(i => !i.StartsWith("extension."))
|
|
||||||
.Select(i => new CommandPaletteItem(i, () => {
|
|
||||||
Core.CommandV("show-text", i);
|
|
||||||
Core.CommandV("apply-profile", i);
|
|
||||||
}));
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowChapters() => App.InvokeOnMainThread(() =>
|
|
||||||
{
|
|
||||||
var items = Core.GetChapters().Select(i => new CommandPaletteItem(i.Title, i.TimeDisplay, () =>
|
|
||||||
Core.CommandV("seek", i.Time.ToString(CultureInfo.InvariantCulture), "absolute")));
|
|
||||||
|
|
||||||
CommandPalette.Instance.SetItems(items);
|
|
||||||
MainForm.Instance.ShowCommandPalette();
|
|
||||||
CommandPalette.Instance.SelectFirst();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static void ShowMenu() => Core.RaiseShowMenu();
|
|
||||||
|
|
||||||
public static void PlaylistAdd(int value)
|
|
||||||
{
|
|
||||||
int pos = Core.PlaylistPos;
|
|
||||||
int count = Core.GetPropertyInt("playlist-count");
|
|
||||||
|
|
||||||
if (count < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pos = pos + value;
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
pos = count - 1;
|
|
||||||
|
|
||||||
if (pos > count - 1)
|
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
Core.SetPropertyInt("playlist-pos", pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void QuickBookmark()
|
|
||||||
{
|
|
||||||
if (App.QuickBookmark == 0)
|
|
||||||
{
|
|
||||||
App.QuickBookmark = (float)Core.GetPropertyDouble("time-pos");
|
|
||||||
|
|
||||||
if (App.QuickBookmark != 0)
|
|
||||||
Core.Command("show-text 'Bookmark Saved'");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Core.SetPropertyDouble("time-pos", App.QuickBookmark);
|
|
||||||
App.QuickBookmark = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class StringPair
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Value { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConfParser
|
|
||||||
{
|
|
||||||
public static List<ConfSection> Parse(string content)
|
|
||||||
{
|
|
||||||
string[] lines = content.Split("\r\n".ToCharArray());
|
|
||||||
var sections = new List<ConfSection>();
|
|
||||||
ConfSection currentGroup = null;
|
|
||||||
|
|
||||||
foreach (string i in lines)
|
|
||||||
{
|
|
||||||
string line = i.Trim();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(line))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (line.StartsWith("[") && line.EndsWith("]"))
|
|
||||||
{
|
|
||||||
currentGroup = new ConfSection() { Name = line.TrimStart('[').TrimEnd(']') };
|
|
||||||
sections.Add(currentGroup);
|
|
||||||
}
|
|
||||||
else if (line.Contains("="))
|
|
||||||
{
|
|
||||||
string name = line.Substring(0, line.IndexOf("=")).Trim();
|
|
||||||
string value = line.Substring(line.IndexOf("=") + 1).Trim();
|
|
||||||
|
|
||||||
currentGroup.Items.Add(new StringPair() { Name = name, Value = value });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sections;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConfSection
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public List<StringPair> Items { get; set; } = new List<StringPair>();
|
|
||||||
|
|
||||||
public bool HasName(string name)
|
|
||||||
{
|
|
||||||
foreach (var i in Items)
|
|
||||||
if (i.Name == name)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetValue(string name)
|
|
||||||
{
|
|
||||||
foreach (var i in Items)
|
|
||||||
if (i.Name == name)
|
|
||||||
return i.Value;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<StringPair> GetValues(string name) => Items.Where(i => i.Name == name).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
164
src/Misc/Conf.cs
@@ -1,164 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Navigation;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class Conf
|
|
||||||
{
|
|
||||||
public static List<SettingBase> LoadConf(string content)
|
|
||||||
{
|
|
||||||
List<SettingBase> settingsList = new List<SettingBase>();
|
|
||||||
|
|
||||||
foreach (ConfSection section in ConfParser.Parse(content))
|
|
||||||
{
|
|
||||||
SettingBase baseSetting = null;
|
|
||||||
|
|
||||||
if (section.HasName("option"))
|
|
||||||
{
|
|
||||||
OptionSetting optionSetting = new OptionSetting();
|
|
||||||
baseSetting = optionSetting;
|
|
||||||
optionSetting.Default = section.GetValue("default");
|
|
||||||
optionSetting.Value = optionSetting.Default;
|
|
||||||
|
|
||||||
foreach (var i in section.GetValues("option"))
|
|
||||||
{
|
|
||||||
var opt = new OptionSettingOption();
|
|
||||||
|
|
||||||
if (i.Value.Contains(" "))
|
|
||||||
{
|
|
||||||
opt.Name = i.Value.Substring(0, i.Value.IndexOf(" "));
|
|
||||||
opt.Help = i.Value.Substring(i.Value.IndexOf(" ")).Trim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
opt.Name = i.Value;
|
|
||||||
|
|
||||||
if (opt.Name == optionSetting.Default)
|
|
||||||
opt.Text = opt.Name + " (Default)";
|
|
||||||
|
|
||||||
opt.OptionSetting = optionSetting;
|
|
||||||
optionSetting.Options.Add(opt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StringSetting stringSetting = new StringSetting();
|
|
||||||
baseSetting = stringSetting;
|
|
||||||
stringSetting.Default = section.HasName("default") ? section.GetValue("default") : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
baseSetting.Name = section.GetValue("name");
|
|
||||||
baseSetting.File = section.GetValue("file");
|
|
||||||
baseSetting.Filter = section.GetValue("filter");
|
|
||||||
|
|
||||||
if (section.HasName("help")) baseSetting.Help = section.GetValue("help");
|
|
||||||
if (section.HasName("url")) baseSetting.URL = section.GetValue("url");
|
|
||||||
if (section.HasName("width")) baseSetting.Width = Convert.ToInt32(section.GetValue("width"));
|
|
||||||
if (section.HasName("type")) baseSetting.Type = section.GetValue("type");
|
|
||||||
|
|
||||||
if (baseSetting.Help.ContainsEx("\\n"))
|
|
||||||
baseSetting.Help = baseSetting.Help.Replace("\\n", "\n");
|
|
||||||
|
|
||||||
settingsList.Add(baseSetting);
|
|
||||||
}
|
|
||||||
|
|
||||||
return settingsList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConfItem
|
|
||||||
{
|
|
||||||
public string Comment { get; set; } = "";
|
|
||||||
public string File { get; set; } = "";
|
|
||||||
public string LineComment { get; set; } = "";
|
|
||||||
public string Name { get; set; } = "";
|
|
||||||
public string Section { get; set; } = "";
|
|
||||||
public string Value { get; set; } = "";
|
|
||||||
|
|
||||||
public bool IsSectionItem { get; set; }
|
|
||||||
public SettingBase SettingBase { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class SettingBase
|
|
||||||
{
|
|
||||||
public string Default { get; set; }
|
|
||||||
public string File { get; set; }
|
|
||||||
public string Filter { get; set; }
|
|
||||||
public string Help { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string StartValue { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string URL { get; set; }
|
|
||||||
public string Value { get; set; }
|
|
||||||
|
|
||||||
public int Width { get; set; }
|
|
||||||
public ConfItem ConfItem { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StringSetting : SettingBase
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OptionSetting : SettingBase
|
|
||||||
{
|
|
||||||
public List<OptionSettingOption> Options = new List<OptionSettingOption>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OptionSettingOption
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Help { get; set; }
|
|
||||||
|
|
||||||
public OptionSetting OptionSetting { get; set; }
|
|
||||||
|
|
||||||
string _Text;
|
|
||||||
|
|
||||||
public string Text
|
|
||||||
{
|
|
||||||
get => string.IsNullOrEmpty(_Text) ? Name : _Text;
|
|
||||||
set => _Text = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Checked
|
|
||||||
{
|
|
||||||
get => OptionSetting.Value == Name ;
|
|
||||||
set {
|
|
||||||
if (value)
|
|
||||||
OptionSetting.Value = Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Visibility Visibility
|
|
||||||
{
|
|
||||||
get => string.IsNullOrEmpty(Help) ? Visibility.Collapsed : Visibility.Visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ISettingControl
|
|
||||||
{
|
|
||||||
bool Contains(string searchString);
|
|
||||||
SettingBase SettingBase { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HyperlinkEx : Hyperlink
|
|
||||||
{
|
|
||||||
void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
|
||||||
{
|
|
||||||
ProcessHelp.ShellExecute(e.Uri.AbsoluteUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetURL(string url)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(url))
|
|
||||||
return;
|
|
||||||
|
|
||||||
NavigateUri = new Uri(url);
|
|
||||||
RequestNavigate += HyperLinkEx_RequestNavigate;
|
|
||||||
Inlines.Clear();
|
|
||||||
Inlines.Add(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.Composition;
|
|
||||||
using System.ComponentModel.Composition.Hosting;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class Extension
|
|
||||||
{
|
|
||||||
[ImportMany]
|
|
||||||
public IEnumerable<IExtension> Extensions = null;
|
|
||||||
|
|
||||||
readonly CompositionContainer CompositionContainer;
|
|
||||||
|
|
||||||
public Extension()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AggregateCatalog catalog = new AggregateCatalog();
|
|
||||||
string 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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
public static class TestStringExtension
|
|
||||||
{
|
|
||||||
public static bool ContainsEx(this string instance, string value)
|
|
||||||
{
|
|
||||||
if (instance != null && value != null)
|
|
||||||
return instance.Contains(value);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool StartsWithEx(this string instance, string value)
|
|
||||||
{
|
|
||||||
if (instance != null && value != null)
|
|
||||||
return instance.StartsWith(value);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConvertToStringExtension
|
|
||||||
{
|
|
||||||
public static string ToUpperEx(this string instance)
|
|
||||||
{
|
|
||||||
if (instance != null)
|
|
||||||
return instance.ToUpperInvariant();
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ToLowerEx(this string instance)
|
|
||||||
{
|
|
||||||
if (instance != null)
|
|
||||||
return instance.ToLowerInvariant();
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string TrimEx(this string instance)
|
|
||||||
{
|
|
||||||
if (instance == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return instance.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConvertStringExtension
|
|
||||||
{
|
|
||||||
public static int ToInt(this string instance)
|
|
||||||
{
|
|
||||||
int.TryParse(instance, out int result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float ToFloat(this string instance)
|
|
||||||
{
|
|
||||||
float.TryParse(instance.Replace(",", "."), NumberStyles.Float,
|
|
||||||
CultureInfo.InvariantCulture, out float result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PathStringExtension
|
|
||||||
{
|
|
||||||
public static string Ext(this string filepath) => Ext(filepath, false);
|
|
||||||
|
|
||||||
public static string Ext(this string filepath, bool includeDot)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(filepath))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
char[] chars = filepath.ToCharArray();
|
|
||||||
|
|
||||||
for (int x = filepath.Length - 1; x >= 0; x--)
|
|
||||||
{
|
|
||||||
if (chars[x] == Path.DirectorySeparatorChar)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (chars[x] == '.')
|
|
||||||
return filepath.Substring(x + (includeDot ? 0 : 1)).ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string FileName(this string instance)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(instance))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
int index = instance.LastIndexOf('\\');
|
|
||||||
|
|
||||||
if (index > -1)
|
|
||||||
return instance.Substring(index + 1);
|
|
||||||
|
|
||||||
index = instance.LastIndexOf('/');
|
|
||||||
|
|
||||||
if (index > -1)
|
|
||||||
return instance.Substring(index + 1);
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ShortPath(this string instance, int maxLength)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(instance))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (instance.Length > maxLength && instance.Substring(1, 2) == ":\\")
|
|
||||||
instance = instance.Substring(0, 3) + "...\\" + instance.FileName();
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure trailing directory separator char
|
|
||||||
public static string AddSep(this string instance)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(instance))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (!instance.EndsWith(Path.DirectorySeparatorChar.ToString()))
|
|
||||||
instance = instance + Path.DirectorySeparatorChar;
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class FolderBrowser
|
|
||||||
{
|
|
||||||
public string SelectedPath { get; set; }
|
|
||||||
|
|
||||||
string _initialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
|
||||||
|
|
||||||
public string InitialDirectory {
|
|
||||||
get => _initialDirectory;
|
|
||||||
set {
|
|
||||||
if (Directory.Exists(value))
|
|
||||||
_initialDirectory = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Show() => Show(GetOwnerHandle());
|
|
||||||
|
|
||||||
public bool Show(IntPtr hWndOwner)
|
|
||||||
{
|
|
||||||
ShowDialogResult result = VistaDialog.Show(hWndOwner, InitialDirectory);
|
|
||||||
|
|
||||||
if (result.Result)
|
|
||||||
SelectedPath = result.FileName;
|
|
||||||
|
|
||||||
return result.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ShowDialogResult
|
|
||||||
{
|
|
||||||
public bool Result { get; set; }
|
|
||||||
public string FileName { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntPtr GetOwnerHandle()
|
|
||||||
{
|
|
||||||
IntPtr foregroundWindow = GetForegroundWindow();
|
|
||||||
GetWindowThreadProcessId(foregroundWindow, out var procID);
|
|
||||||
|
|
||||||
using (var proc = Process.GetCurrentProcess())
|
|
||||||
if (proc.Id == procID)
|
|
||||||
return foregroundWindow;
|
|
||||||
|
|
||||||
return IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern IntPtr GetForegroundWindow();
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
||||||
|
|
||||||
static class VistaDialog
|
|
||||||
{
|
|
||||||
const string foldersFilter = "Folders|\n";
|
|
||||||
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
|
||||||
static Assembly windowsFormsAssembly = typeof(FileDialog).Assembly;
|
|
||||||
static Type iFileDialogType = windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
|
|
||||||
static MethodInfo createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", flags);
|
|
||||||
static MethodInfo onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", flags);
|
|
||||||
static MethodInfo getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", flags);
|
|
||||||
static MethodInfo setOptionsMethodInfo = iFileDialogType.GetMethod("SetOptions", flags);
|
|
||||||
static uint fosPickFoldersBitFlag = (uint)windowsFormsAssembly
|
|
||||||
.GetType("System.Windows.Forms.FileDialogNative+FOS")
|
|
||||||
.GetField("FOS_PICKFOLDERS")
|
|
||||||
.GetValue(null);
|
|
||||||
static ConstructorInfo vistaDialogEventsConstructorInfo = windowsFormsAssembly
|
|
||||||
.GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
|
|
||||||
.GetConstructor(flags, null, new[] { typeof(FileDialog) }, null);
|
|
||||||
static MethodInfo adviseMethodInfo = iFileDialogType.GetMethod("Advise");
|
|
||||||
static MethodInfo unAdviseMethodInfo = iFileDialogType.GetMethod("Unadvise");
|
|
||||||
static MethodInfo showMethodInfo = iFileDialogType.GetMethod("Show");
|
|
||||||
|
|
||||||
public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory)
|
|
||||||
{
|
|
||||||
var openFileDialog = new OpenFileDialog
|
|
||||||
{
|
|
||||||
AddExtension = false,
|
|
||||||
CheckFileExists = false,
|
|
||||||
DereferenceLinks = true,
|
|
||||||
Filter = foldersFilter,
|
|
||||||
InitialDirectory = initialDirectory,
|
|
||||||
Multiselect = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
var iFileDialog = createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
|
|
||||||
onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
|
|
||||||
setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint)getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | fosPickFoldersBitFlag });
|
|
||||||
var adviseParametersWithOutputConnectionToken = new[] { vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
|
|
||||||
adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int retVal = (int)showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
|
|
||||||
|
|
||||||
return new ShowDialogResult
|
|
||||||
{
|
|
||||||
Result = retVal == 0,
|
|
||||||
FileName = openFileDialog.FileName
|
|
||||||
};
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WindowWrapper : IWin32Window
|
|
||||||
{
|
|
||||||
IntPtr _handle;
|
|
||||||
public WindowWrapper(IntPtr handle) { _handle = handle; }
|
|
||||||
public IntPtr Handle => _handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class Global
|
|
||||||
{
|
|
||||||
public static string BR = Environment.NewLine;
|
|
||||||
public static string BR2 = Environment.NewLine + Environment.NewLine;
|
|
||||||
|
|
||||||
public static CorePlayer Core { get; } = new CorePlayer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
class GlobalHotkey
|
|
||||||
{
|
|
||||||
public static Dictionary<int, string> Commands { get; set; }
|
|
||||||
static int ID;
|
|
||||||
static IntPtr HWND;
|
|
||||||
|
|
||||||
public static void RegisterGlobalHotkeys(IntPtr hwnd)
|
|
||||||
{
|
|
||||||
HWND = hwnd;
|
|
||||||
string path = Core.ConfigFolder + "global-input.conf";
|
|
||||||
|
|
||||||
if (!File.Exists(path))
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (string i in File.ReadAllLines(path))
|
|
||||||
{
|
|
||||||
string line = i.Trim();
|
|
||||||
|
|
||||||
if (line.StartsWith("#") || !line.Contains(" "))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ProcessGlobalHotkeyLine(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ProcessGlobalHotkeyLine(string line)
|
|
||||||
{
|
|
||||||
string key = line.Substring(0, line.IndexOf(" "));
|
|
||||||
string command = line.Substring(line.IndexOf(" ") + 1);
|
|
||||||
string[] parts = key.Split('+');
|
|
||||||
KeyModifiers mod = KeyModifiers.None;
|
|
||||||
int vk;
|
|
||||||
|
|
||||||
for (int i = 0; i < parts.Length - 1; i++)
|
|
||||||
{
|
|
||||||
string umod = parts[i].ToUpper();
|
|
||||||
|
|
||||||
if (umod == "ALT") mod |= KeyModifiers.Alt;
|
|
||||||
if (umod == "CTRL") mod |= KeyModifiers.Ctrl;
|
|
||||||
if (umod == "SHIFT") mod |= KeyModifiers.Shift;
|
|
||||||
if (umod == "WIN") mod |= KeyModifiers.Win;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = parts[parts.Length - 1];
|
|
||||||
|
|
||||||
if (key.Length == 1)
|
|
||||||
{
|
|
||||||
short result = VkKeyScanEx(key[0], GetKeyboardLayout(0));
|
|
||||||
|
|
||||||
int hi = result >> 8;
|
|
||||||
int lo = result & 0xFF;
|
|
||||||
|
|
||||||
vk = lo;
|
|
||||||
|
|
||||||
if ((hi & 1) == 1) mod |= KeyModifiers.Shift;
|
|
||||||
if ((hi & 2) == 2) mod |= KeyModifiers.Ctrl;
|
|
||||||
if ((hi & 4) == 4) mod |= KeyModifiers.Alt;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vk = mpv_to_VK(key);
|
|
||||||
|
|
||||||
if (Commands == null)
|
|
||||||
Commands = new Dictionary<int, string>();
|
|
||||||
|
|
||||||
if (vk > 0)
|
|
||||||
{
|
|
||||||
Commands[ID] = command.Trim();
|
|
||||||
bool success = RegisterHotKey(HWND, ID++, mod, vk);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
Terminal.WriteError(line + ": " + new Win32Exception().Message + "\n", "global-input.conf");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Execute(int id)
|
|
||||||
{
|
|
||||||
if (Commands.ContainsKey(id))
|
|
||||||
Core.Command(Commands[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mpv_to_VK(string value)
|
|
||||||
{
|
|
||||||
switch (value.ToUpperEx())
|
|
||||||
{
|
|
||||||
case "NEXT" : return 0xB0; // VK_MEDIA_NEXT_TRACK
|
|
||||||
case "PREV" : return 0xB1; // VK_MEDIA_PREV_TRACK
|
|
||||||
case "STOP" : return 0xB2; // VK_MEDIA_STOP
|
|
||||||
case "PLAYPAUSE" : return 0xB3; // VK_MEDIA_PLAY_PAUSE
|
|
||||||
case "SLEEP" : return 0x5F; // VK_SLEEP
|
|
||||||
case "RIGHT" : return 0x27; // VK_RIGHT
|
|
||||||
case "UP" : return 0x26; // VK_UP
|
|
||||||
case "LEFT" : return 0x25; // VK_LEFT
|
|
||||||
case "DOWN" : return 0x28; // VK_DOWN
|
|
||||||
case "PGUP" : return 0x21; // VK_PRIOR
|
|
||||||
case "PGDWN" : return 0x22; // VK_NEXT
|
|
||||||
case "PAUSE" : return 0x13; // VK_PAUSE
|
|
||||||
case "PRINT" : return 0x2A; // VK_PRINT
|
|
||||||
case "HOME" : return 0x24; // VK_HOME
|
|
||||||
case "INS" : return 0x2D; // VK_INSERT
|
|
||||||
case "KP_INS" : return 0x2D; // VK_INSERT
|
|
||||||
case "DEL" : return 0x2E; // VK_DELETE
|
|
||||||
case "KP_DEL" : return 0x2E; // VK_DELETE
|
|
||||||
case "END" : return 0x23; // VK_END
|
|
||||||
case "F1" : return 0x70; // VK_F1
|
|
||||||
case "F2" : return 0x71; // VK_F2
|
|
||||||
case "F3" : return 0x72; // VK_F3
|
|
||||||
case "F4" : return 0x73; // VK_F4
|
|
||||||
case "F5" : return 0x74; // VK_F5
|
|
||||||
case "F6" : return 0x75; // VK_F6
|
|
||||||
case "F7" : return 0x76; // VK_F7
|
|
||||||
case "F8" : return 0x77; // VK_F8
|
|
||||||
case "F9" : return 0x78; // VK_F9
|
|
||||||
case "F10" : return 0x79; // VK_F10
|
|
||||||
case "F11" : return 0x7A; // VK_F11
|
|
||||||
case "F12" : return 0x7B; // VK_F12
|
|
||||||
case "F13" : return 0x7C; // VK_F13
|
|
||||||
case "F14" : return 0x7D; // VK_F14
|
|
||||||
case "F15" : return 0x7E; // VK_F15
|
|
||||||
case "F16" : return 0x7F; // VK_F16
|
|
||||||
case "F17" : return 0x80; // VK_F17
|
|
||||||
case "F18" : return 0x81; // VK_F18
|
|
||||||
case "F19" : return 0x82; // VK_F19
|
|
||||||
case "F20" : return 0x83; // VK_F20
|
|
||||||
case "F21" : return 0x84; // VK_F21
|
|
||||||
case "F22" : return 0x85; // VK_F22
|
|
||||||
case "F23" : return 0x86; // VK_F23
|
|
||||||
case "F24" : return 0x87; // VK_F24
|
|
||||||
case "ENTER" : return 0x0D; // VK_RETURN
|
|
||||||
case "KP_ENTER" : return 0x0D; // VK_RETURN
|
|
||||||
case "TAB" : return 0x09; // VK_TAB
|
|
||||||
case "MENU" : return 0x5D; // VK_APPS
|
|
||||||
case "CANCEL" : return 0x03; // VK_CANCEL
|
|
||||||
case "BS" : return 0x08; // VK_BACK
|
|
||||||
case "KP_DEC" : return 0x6E; // VK_DECIMAL
|
|
||||||
case "ESC" : return 0x1B; // VK_ESCAPE
|
|
||||||
case "KP0" : return 0x60; // VK_NUMPAD0
|
|
||||||
case "KP1" : return 0x61; // VK_NUMPAD1
|
|
||||||
case "KP2" : return 0x62; // VK_NUMPAD2
|
|
||||||
case "KP3" : return 0x63; // VK_NUMPAD3
|
|
||||||
case "KP4" : return 0x64; // VK_NUMPAD4
|
|
||||||
case "KP5" : return 0x65; // VK_NUMPAD5
|
|
||||||
case "KP6" : return 0x66; // VK_NUMPAD6
|
|
||||||
case "KP7" : return 0x67; // VK_NUMPAD7
|
|
||||||
case "KP8" : return 0x68; // VK_NUMPAD8
|
|
||||||
case "KP9" : return 0x69; // VK_NUMPAD9
|
|
||||||
case "FAVORITES" : return 0xAB; // VK_BROWSER_FAVORITES
|
|
||||||
case "SEARCH" : return 0xAA; // VK_BROWSER_SEARCH
|
|
||||||
case "MAIL" : return 0xB4; // VK_LAUNCH_MAIL
|
|
||||||
case "VOLUME_UP" : return 0xAF; // VK_VOLUME_UP
|
|
||||||
case "VOLUME_DOWN": return 0xAE; // VK_VOLUME_DOWN
|
|
||||||
case "MUTE" : return 0xAD; // VK_VOLUME_MUTE
|
|
||||||
case "SPACE" : return 0x20; // VK_SPACE
|
|
||||||
case "IDEOGRAPHIC_SPACE": return 0x20; // VK_SPACE
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
||||||
static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
static extern IntPtr GetKeyboardLayout(uint idThread);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
||||||
static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, int vk);
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
enum KeyModifiers
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Alt = 1,
|
|
||||||
Ctrl = 2,
|
|
||||||
Shift = 4,
|
|
||||||
Win = 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
217
src/Misc/Help.cs
@@ -1,217 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
using Microsoft.Win32;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public static class StringHelp
|
|
||||||
{
|
|
||||||
public static string GetMD5Hash(string txt)
|
|
||||||
{
|
|
||||||
using (MD5 md5 = MD5.Create())
|
|
||||||
{
|
|
||||||
byte[] inputBuffer = Encoding.UTF8.GetBytes(txt);
|
|
||||||
byte[] hashBuffer = md5.ComputeHash(inputBuffer);
|
|
||||||
return BitConverter.ToString(md5.ComputeHash(inputBuffer)).Replace("-", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FileHelp
|
|
||||||
{
|
|
||||||
public static void Delete(string path)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (File.Exists(path))
|
|
||||||
File.Delete(path);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Terminal.WriteError("Failed to delete file:" + BR + path + BR + ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ProcessHelp
|
|
||||||
{
|
|
||||||
public static void Execute(string file, string arguments = null)
|
|
||||||
{
|
|
||||||
using (Process proc = new Process())
|
|
||||||
{
|
|
||||||
proc.StartInfo.FileName = file;
|
|
||||||
proc.StartInfo.Arguments = arguments;
|
|
||||||
proc.StartInfo.UseShellExecute = false;
|
|
||||||
proc.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShellExecute(string file, string arguments = null)
|
|
||||||
{
|
|
||||||
using (Process proc = new Process())
|
|
||||||
{
|
|
||||||
proc.StartInfo.FileName = file;
|
|
||||||
proc.StartInfo.Arguments = arguments;
|
|
||||||
proc.StartInfo.UseShellExecute = true;
|
|
||||||
proc.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 GetProfiles()
|
|
||||||
{
|
|
||||||
string json = Core.GetPropertyString("profile-list");
|
|
||||||
var o = json.FromJson<List<Dictionary<string, object>>>().OrderBy(i => i["name"]);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (Dictionary<string, object> i in o)
|
|
||||||
{
|
|
||||||
sb.Append(i["name"].ToString() + BR2);
|
|
||||||
|
|
||||||
foreach (Dictionary<string, object> i2 in i["options"] as List<object>)
|
|
||||||
sb.AppendLine(" " + i2["key"] + " = " + i2["value"]);
|
|
||||||
|
|
||||||
sb.Append(BR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDecoders()
|
|
||||||
{
|
|
||||||
string json = Core.GetPropertyString("decoder-list");
|
|
||||||
var o = json.FromJson<List<Dictionary<string, object>>>().OrderBy(i => i["codec"]);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (Dictionary<string, object> i in o)
|
|
||||||
sb.AppendLine(i["codec"] + " - " + i["description"]);
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetProtocols()
|
|
||||||
{
|
|
||||||
string list = Core.GetPropertyString("protocol-list");
|
|
||||||
return string.Join(BR, list.Split(',').OrderBy(a => a));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDemuxers()
|
|
||||||
{
|
|
||||||
string list = Core.GetPropertyString("demuxer-lavf-list");
|
|
||||||
return string.Join(BR, list.Split(',').OrderBy(a => a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegistryHelp
|
|
||||||
{
|
|
||||||
public static string ApplicationKey { get; } = @"HKCU\Software\" + Application.ProductName;
|
|
||||||
|
|
||||||
public static void SetInt(string name, object value)
|
|
||||||
{
|
|
||||||
SetValue(ApplicationKey, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetString(string name, string value)
|
|
||||||
{
|
|
||||||
SetValue(ApplicationKey, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetValue(string name, object value)
|
|
||||||
{
|
|
||||||
using (RegistryKey regKey = GetRootKey(ApplicationKey).CreateSubKey(ApplicationKey.Substring(5), RegistryKeyPermissionCheck.ReadWriteSubTree))
|
|
||||||
regKey.SetValue(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 name, string defaultValue = "")
|
|
||||||
{
|
|
||||||
object value = GetValue(ApplicationKey, name, defaultValue);
|
|
||||||
return !(value is string) ? defaultValue : value.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetInt(string name, int defaultValue = 0)
|
|
||||||
{
|
|
||||||
object value = GetValue(ApplicationKey, name, defaultValue);
|
|
||||||
return !(value is int) ? defaultValue : (int)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object GetValue(string name) => GetValue(ApplicationKey, name, null);
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,415 +0,0 @@
|
|||||||
|
|
||||||
// https://github.com/zanders3/json
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public static class JSONParser
|
|
||||||
{
|
|
||||||
[ThreadStatic] static Stack<List<string>> splitArrayPool;
|
|
||||||
[ThreadStatic] static StringBuilder stringBuilder;
|
|
||||||
[ThreadStatic] static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfoCache;
|
|
||||||
[ThreadStatic] static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyInfoCache;
|
|
||||||
|
|
||||||
public static T FromJson<T>(this string json)
|
|
||||||
{
|
|
||||||
// Initialize, if needed, the ThreadStatic variables
|
|
||||||
if (propertyInfoCache == null)
|
|
||||||
propertyInfoCache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
|
|
||||||
|
|
||||||
if (fieldInfoCache == null)
|
|
||||||
fieldInfoCache = new Dictionary<Type, Dictionary<string, FieldInfo>>();
|
|
||||||
|
|
||||||
if (stringBuilder == null)
|
|
||||||
stringBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
if (splitArrayPool == null)
|
|
||||||
splitArrayPool = new Stack<List<string>>();
|
|
||||||
|
|
||||||
//Remove all whitespace not within strings to make parsing simpler
|
|
||||||
stringBuilder.Length = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < json.Length; i++)
|
|
||||||
{
|
|
||||||
char c = json[i];
|
|
||||||
|
|
||||||
if (c == '"')
|
|
||||||
{
|
|
||||||
i = AppendUntilStringEnd(true, i, json);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (char.IsWhiteSpace(c))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
stringBuilder.Append(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Parse the thing!
|
|
||||||
return (T)ParseValue(typeof(T), stringBuilder.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
|
|
||||||
{
|
|
||||||
stringBuilder.Append(json[startIdx]);
|
|
||||||
|
|
||||||
for (int i = startIdx + 1; i < json.Length; i++)
|
|
||||||
{
|
|
||||||
if (json[i] == '\\')
|
|
||||||
{
|
|
||||||
if (appendEscapeCharacter)
|
|
||||||
stringBuilder.Append(json[i]);
|
|
||||||
stringBuilder.Append(json[i + 1]);
|
|
||||||
i++;//Skip next character as it is escaped
|
|
||||||
}
|
|
||||||
else if (json[i] == '"')
|
|
||||||
{
|
|
||||||
stringBuilder.Append(json[i]);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stringBuilder.Append(json[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings
|
|
||||||
static List<string> Split(string json)
|
|
||||||
{
|
|
||||||
List<string> splitArray = splitArrayPool.Count > 0 ? splitArrayPool.Pop() : new List<string>();
|
|
||||||
splitArray.Clear();
|
|
||||||
|
|
||||||
if (json.Length == 2)
|
|
||||||
return splitArray;
|
|
||||||
|
|
||||||
int parseDepth = 0;
|
|
||||||
stringBuilder.Length = 0;
|
|
||||||
|
|
||||||
for (int i = 1; i < json.Length - 1; i++)
|
|
||||||
{
|
|
||||||
switch (json[i])
|
|
||||||
{
|
|
||||||
case '[':
|
|
||||||
case '{':
|
|
||||||
parseDepth++;
|
|
||||||
break;
|
|
||||||
case ']':
|
|
||||||
case '}':
|
|
||||||
parseDepth--;
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
i = AppendUntilStringEnd(true, i, json);
|
|
||||||
continue;
|
|
||||||
case ',':
|
|
||||||
case ':':
|
|
||||||
if (parseDepth == 0)
|
|
||||||
{
|
|
||||||
splitArray.Add(stringBuilder.ToString());
|
|
||||||
stringBuilder.Length = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
stringBuilder.Append(json[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
splitArray.Add(stringBuilder.ToString());
|
|
||||||
|
|
||||||
return splitArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static object ParseValue(Type type, string json)
|
|
||||||
{
|
|
||||||
if (type == typeof(string))
|
|
||||||
{
|
|
||||||
if (json.Length <= 2)
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
StringBuilder parseStringBuilder = new StringBuilder(json.Length);
|
|
||||||
|
|
||||||
for (int i = 1; i < json.Length - 1; ++i)
|
|
||||||
{
|
|
||||||
if (json[i] == '\\' && i + 1 < json.Length - 1)
|
|
||||||
{
|
|
||||||
int j = "\"\\nrtbf/".IndexOf(json[i + 1]);
|
|
||||||
|
|
||||||
if (j >= 0)
|
|
||||||
{
|
|
||||||
parseStringBuilder.Append("\"\\\n\r\t\b\f/"[j]);
|
|
||||||
++i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (json[i + 1] == 'u' && i + 5 < json.Length - 1)
|
|
||||||
{
|
|
||||||
uint c = 0;
|
|
||||||
|
|
||||||
if (uint.TryParse(json.Substring(i + 2, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out c))
|
|
||||||
{
|
|
||||||
parseStringBuilder.Append((char)c);
|
|
||||||
i += 5;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parseStringBuilder.Append(json[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parseStringBuilder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.IsPrimitive)
|
|
||||||
{
|
|
||||||
var result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == typeof(decimal))
|
|
||||||
{
|
|
||||||
decimal result;
|
|
||||||
decimal.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == "null")
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (type.IsEnum)
|
|
||||||
{
|
|
||||||
if (json[0] == '"')
|
|
||||||
json = json.Substring(1, json.Length - 2);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Enum.Parse(type, json, false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.IsArray)
|
|
||||||
{
|
|
||||||
Type arrayType = type.GetElementType();
|
|
||||||
|
|
||||||
if (json[0] != '[' || json[json.Length - 1] != ']')
|
|
||||||
return null;
|
|
||||||
|
|
||||||
List<string> elems = Split(json);
|
|
||||||
Array newArray = Array.CreateInstance(arrayType, elems.Count);
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.Count; i++)
|
|
||||||
newArray.SetValue(ParseValue(arrayType, elems[i]), i);
|
|
||||||
|
|
||||||
splitArrayPool.Push(elems);
|
|
||||||
return newArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
|
|
||||||
{
|
|
||||||
Type listType = type.GetGenericArguments()[0];
|
|
||||||
|
|
||||||
if (json[0] != '[' || json[json.Length - 1] != ']')
|
|
||||||
return null;
|
|
||||||
|
|
||||||
List<string> elems = Split(json);
|
|
||||||
var list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count });
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.Count; i++)
|
|
||||||
list.Add(ParseValue(listType, elems[i]));
|
|
||||||
|
|
||||||
splitArrayPool.Push(elems);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
|
||||||
{
|
|
||||||
Type keyType, valueType;
|
|
||||||
{
|
|
||||||
Type[] args = type.GetGenericArguments();
|
|
||||||
keyType = args[0];
|
|
||||||
valueType = args[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Refuse to parse dictionary keys that aren't of type string
|
|
||||||
if (keyType != typeof(string))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
//Must be a valid dictionary element
|
|
||||||
if (json[0] != '{' || json[json.Length - 1] != '}')
|
|
||||||
return null;
|
|
||||||
|
|
||||||
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
|
|
||||||
List<string> elems = Split(json);
|
|
||||||
|
|
||||||
if (elems.Count % 2 != 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 });
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.Count; i += 2)
|
|
||||||
{
|
|
||||||
if (elems[i].Length <= 2)
|
|
||||||
continue;
|
|
||||||
string keyValue = elems[i].Substring(1, elems[i].Length - 2);
|
|
||||||
object val = ParseValue(valueType, elems[i + 1]);
|
|
||||||
dictionary[keyValue] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == typeof(object))
|
|
||||||
return ParseAnonymousValue(json);
|
|
||||||
|
|
||||||
if (json[0] == '{' && json[json.Length - 1] == '}')
|
|
||||||
return ParseObject(type, json);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static object ParseAnonymousValue(string json)
|
|
||||||
{
|
|
||||||
if (json.Length == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (json[0] == '{' && json[json.Length - 1] == '}')
|
|
||||||
{
|
|
||||||
List<string> elems = Split(json);
|
|
||||||
|
|
||||||
if (elems.Count % 2 != 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var dict = new Dictionary<string, object>(elems.Count / 2);
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.Count; i += 2)
|
|
||||||
dict[elems[i].Substring(1, elems[i].Length - 2)] = ParseAnonymousValue(elems[i + 1]);
|
|
||||||
|
|
||||||
return dict;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json[0] == '[' && json[json.Length - 1] == ']')
|
|
||||||
{
|
|
||||||
List<string> items = Split(json);
|
|
||||||
var finalList = new List<object>(items.Count);
|
|
||||||
|
|
||||||
for (int i = 0; i < items.Count; i++)
|
|
||||||
finalList.Add(ParseAnonymousValue(items[i]));
|
|
||||||
|
|
||||||
return finalList;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json[0] == '"' && json[json.Length - 1] == '"')
|
|
||||||
{
|
|
||||||
string str = json.Substring(1, json.Length - 2);
|
|
||||||
return str.Replace("\\", string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (char.IsDigit(json[0]) || json[0] == '-')
|
|
||||||
{
|
|
||||||
if (json.Contains("."))
|
|
||||||
{
|
|
||||||
double result;
|
|
||||||
double.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
int.TryParse(json, out result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == "true")
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (json == "false")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// handles json == "null" as well as invalid JSON
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Dictionary<string, T> CreateMemberNameDictionary<T>(T[] members) where T : MemberInfo
|
|
||||||
{
|
|
||||||
Dictionary<string, T> nameToMember = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
for (int i = 0; i < members.Length; i++)
|
|
||||||
{
|
|
||||||
T member = members[i];
|
|
||||||
|
|
||||||
if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
string name = member.Name;
|
|
||||||
|
|
||||||
if (member.IsDefined(typeof(DataMemberAttribute), true))
|
|
||||||
{
|
|
||||||
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
|
|
||||||
name = dataMemberAttribute.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
nameToMember.Add(name, member);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nameToMember;
|
|
||||||
}
|
|
||||||
|
|
||||||
static object ParseObject(Type type, string json)
|
|
||||||
{
|
|
||||||
object instance = FormatterServices.GetUninitializedObject(type);
|
|
||||||
|
|
||||||
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
|
|
||||||
List<string> elems = Split(json);
|
|
||||||
|
|
||||||
if (elems.Count % 2 != 0)
|
|
||||||
return instance;
|
|
||||||
|
|
||||||
Dictionary<string, FieldInfo> nameToField;
|
|
||||||
Dictionary<string, PropertyInfo> nameToProperty;
|
|
||||||
|
|
||||||
if (!fieldInfoCache.TryGetValue(type, out nameToField))
|
|
||||||
{
|
|
||||||
nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
|
|
||||||
fieldInfoCache.Add(type, nameToField);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!propertyInfoCache.TryGetValue(type, out nameToProperty))
|
|
||||||
{
|
|
||||||
nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
|
|
||||||
propertyInfoCache.Add(type, nameToProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.Count; i += 2)
|
|
||||||
{
|
|
||||||
if (elems[i].Length <= 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
string key = elems[i].Substring(1, elems[i].Length - 2);
|
|
||||||
string value = elems[i + 1];
|
|
||||||
|
|
||||||
FieldInfo fieldInfo;
|
|
||||||
PropertyInfo propertyInfo;
|
|
||||||
|
|
||||||
if (nameToField.TryGetValue(key, out fieldInfo))
|
|
||||||
fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value));
|
|
||||||
else if (nameToProperty.TryGetValue(key, out propertyInfo))
|
|
||||||
propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
315
src/Misc/Misc.cs
@@ -1,315 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
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.Global;
|
|
||||||
|
|
||||||
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 Input
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FileAssociation
|
|
||||||
{
|
|
||||||
static string ExePath = Application.ExecutablePath;
|
|
||||||
static string ExeFilename = Path.GetFileName(Application.ExecutablePath);
|
|
||||||
static string ExeFilenameNoExt = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
|
|
||||||
|
|
||||||
public static void Register(string perceivedType, string[] extensions)
|
|
||||||
{
|
|
||||||
string[] protocols = { "ytdl", "rtsp", "srt", "srtp" };
|
|
||||||
|
|
||||||
if (perceivedType != "unreg")
|
|
||||||
{
|
|
||||||
foreach (string i in protocols)
|
|
||||||
{
|
|
||||||
RegistryHelp.SetValue($@"HKCR\{i}", $"{i.ToUpper()} Protocol", "");
|
|
||||||
RegistryHelp.SetValue($@"HKCR\{i}\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
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(@"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");
|
|
||||||
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");
|
|
||||||
|
|
||||||
foreach (string ext in extensions)
|
|
||||||
{
|
|
||||||
RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename + @"\SupportedTypes", "." + ext, "");
|
|
||||||
RegistryHelp.SetValue(@"HKCR\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
|
|
||||||
RegistryHelp.SetValue(@"HKCR\" + "." + ext + @"\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
|
|
||||||
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", perceivedType);
|
|
||||||
RegistryHelp.SetValue(@"HKCR\" + ExeFilenameNoExt + "." + ext + @"\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
|
|
||||||
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (string i in protocols)
|
|
||||||
RegistryHelp.RemoveKey($@"HKCR\{i}");
|
|
||||||
|
|
||||||
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 int ID { get; set; }
|
|
||||||
public bool External { get; set; }
|
|
||||||
public string Text { get; set; } = "";
|
|
||||||
public string Type { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandItem : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
public string Path { get; set; } = "";
|
|
||||||
public string Command { get; set; } = "";
|
|
||||||
|
|
||||||
public string Display {
|
|
||||||
get {
|
|
||||||
if (string.IsNullOrEmpty(Path))
|
|
||||||
{
|
|
||||||
if (Command.Length > 47)
|
|
||||||
return Command.Substring(0, 47) + "...";
|
|
||||||
return Command;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return Path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 string Alias {
|
|
||||||
get {
|
|
||||||
if (Input.Contains("SHARP") || Input.Contains("sharp") || Input.Contains("Sharp"))
|
|
||||||
return "#";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.AddSep();
|
|
||||||
public static string AppData { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).AddSep();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandPaletteItem
|
|
||||||
{
|
|
||||||
public CommandPaletteItem() {}
|
|
||||||
|
|
||||||
public CommandPaletteItem(string text, Action action)
|
|
||||||
{
|
|
||||||
Text = text;
|
|
||||||
Action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandPaletteItem(string text, string secondaryText, Action action)
|
|
||||||
{
|
|
||||||
Text = text;
|
|
||||||
Action = action;
|
|
||||||
SecondaryText = secondaryText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Text { get; set; } = "";
|
|
||||||
public string SecondaryText { get; set; } = "";
|
|
||||||
public Action Action { get; set; }
|
|
||||||
public CommandItem CommandItem { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandPalette
|
|
||||||
{
|
|
||||||
public static CommandPaletteControl Instance { get; } = new CommandPaletteControl();
|
|
||||||
|
|
||||||
public static IEnumerable<CommandPaletteItem> GetItems()
|
|
||||||
{
|
|
||||||
return CommandItem.Items
|
|
||||||
.Where(i => i.Command != "")
|
|
||||||
.Select(i => new CommandPaletteItem() {
|
|
||||||
Text = i.Display,
|
|
||||||
SecondaryText = i.Input,
|
|
||||||
Action = () => Core.Command(i.Command),
|
|
||||||
CommandItem = i
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Chapter
|
|
||||||
{
|
|
||||||
public string Title { get; set; }
|
|
||||||
public double Time { get; set; }
|
|
||||||
|
|
||||||
string _TimeDisplay;
|
|
||||||
|
|
||||||
public string TimeDisplay {
|
|
||||||
get {
|
|
||||||
if (_TimeDisplay == null)
|
|
||||||
{
|
|
||||||
_TimeDisplay = TimeSpan.FromSeconds(Time).ToString();
|
|
||||||
|
|
||||||
if (_TimeDisplay.ContainsEx("."))
|
|
||||||
_TimeDisplay = _TimeDisplay.Substring(0, _TimeDisplay.LastIndexOf("."));
|
|
||||||
}
|
|
||||||
|
|
||||||
return _TimeDisplay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1721
src/Misc/Player.cs
@@ -1,243 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Management.Automation;
|
|
||||||
using System.Management.Automation.Runspaces;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
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[] Arguments { 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> References { 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 (Arguments != null)
|
|
||||||
foreach (string param in Arguments)
|
|
||||||
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)
|
|
||||||
Terminal.Write(output.Read(), Module);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Error_DataReady(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var output = sender as PipelineReader<object>;
|
|
||||||
|
|
||||||
while (output.Count > 0)
|
|
||||||
Terminal.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 GetPropertyBool(string name) => Core.GetPropertyBool(name);
|
|
||||||
|
|
||||||
public void SetPropertyBool(string name, bool value) => Core.SetPropertyBool(name, value);
|
|
||||||
|
|
||||||
public int GetPropertyInt(string name) => Core.GetPropertyInt(name);
|
|
||||||
|
|
||||||
public void SetPropertyInt(string name, int value) => Core.SetPropertyInt(name, value);
|
|
||||||
|
|
||||||
public double GetPropertyDouble(string name) => Core.GetPropertyDouble(name);
|
|
||||||
|
|
||||||
public void SetPropertyDouble(string name, double value) => Core.SetPropertyDouble(name, value);
|
|
||||||
|
|
||||||
public string GetPropertyString(string name) => Core.GetPropertyString(name);
|
|
||||||
|
|
||||||
public void SetPropertyString(string name, string value) => Core.SetPropertyString(name, value);
|
|
||||||
|
|
||||||
public void ObserveProperty(string name, string type, ScriptBlock sb)
|
|
||||||
{
|
|
||||||
PropChangedHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case "bool": case "boolean":
|
|
||||||
Core.ObservePropertyBool(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "string":
|
|
||||||
Core.ObservePropertyString(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "int": case "integer":
|
|
||||||
Core.ObservePropertyInt(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "float": case "double":
|
|
||||||
Core.ObservePropertyDouble(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "nil": case "none": case "native":
|
|
||||||
Core.ObserveProperty(name, () => App.RunTask(() => 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 RegisterEvent(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 "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>;
|
|
||||||
Terminal.Write(output[e.Index], Module);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Error_DataAdded(object sender, DataAddedEventArgs e)
|
|
||||||
{
|
|
||||||
var error = sender as PSDataCollection<ErrorRecord>;
|
|
||||||
Terminal.WriteError(error[e.Index], Module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PowerShellException : Exception
|
|
||||||
{
|
|
||||||
public PowerShellException(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
static class Program
|
|
||||||
{
|
|
||||||
[STAThread]
|
|
||||||
static void Main()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Application.EnableVisualStyles();
|
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
|
||||||
|
|
||||||
if (App.IsTerminalAttached)
|
|
||||||
Native.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
|
|
||||||
|
|
||||||
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
|
||||||
|
|
||||||
if (args.Length > 0 && args[0] == "--register-file-associations")
|
|
||||||
{
|
|
||||||
FileAssociation.Register(args[1], args.Skip(1).ToArray());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
App.Init();
|
|
||||||
Mutex mutex = new Mutex(true, StringHelp.GetMD5Hash(App.ConfPath), out bool isFirst);
|
|
||||||
|
|
||||||
if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst)
|
|
||||||
{
|
|
||||||
List<string> args2 = new List<string>();
|
|
||||||
args2.Add(App.ProcessInstance);
|
|
||||||
|
|
||||||
foreach (string arg in args)
|
|
||||||
{
|
|
||||||
if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") ||
|
|
||||||
arg.Contains(":\\") || arg.StartsWith("\\\\")))
|
|
||||||
|
|
||||||
args2.Add(arg);
|
|
||||||
else if (arg == "--queue")
|
|
||||||
args2[0] = "queue";
|
|
||||||
else if (arg.StartsWith("--command="))
|
|
||||||
{
|
|
||||||
args2[0] = "command";
|
|
||||||
args2.Add(arg.Substring(10));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process[] procs = Process.GetProcessesByName("mpvnet");
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
foreach (Process proc in procs)
|
|
||||||
{
|
|
||||||
if (proc.MainWindowHandle != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Native.AllowSetForegroundWindow(proc.Id);
|
|
||||||
var data = new Native.COPYDATASTRUCT();
|
|
||||||
data.lpData = string.Join("\n", args2.ToArray());
|
|
||||||
data.cbData = data.lpData.Length * 2 + 1;
|
|
||||||
Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data);
|
|
||||||
mutex.Dispose();
|
|
||||||
|
|
||||||
if (App.IsTerminalAttached)
|
|
||||||
Native.FreeConsole();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex.Dispose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Application.Run(new MainForm());
|
|
||||||
|
|
||||||
if (App.IsTerminalAttached)
|
|
||||||
Native.FreeConsole();
|
|
||||||
|
|
||||||
mutex.Dispose();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Msg.ShowException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
using System.Xml;
|
|
||||||
|
|
||||||
using static mpvnet.Global;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
[Serializable()]
|
|
||||||
public class AppSettings
|
|
||||||
{
|
|
||||||
public bool InputDefaultBindingsFixApplied;
|
|
||||||
public bool ShowMenuFixApplied;
|
|
||||||
public int Volume = 70;
|
|
||||||
public List<string> RecentFiles = new List<string>();
|
|
||||||
public Point WindowLocation;
|
|
||||||
public Point WindowPosition;
|
|
||||||
public Size WindowSize;
|
|
||||||
public string ConfigEditorSearch = "Video:";
|
|
||||||
public string Mute = "no";
|
|
||||||
}
|
|
||||||
|
|
||||||
class SettingsManager
|
|
||||||
{
|
|
||||||
public static string SettingsFile => Core.ConfigFolder + "settings.xml";
|
|
||||||
|
|
||||||
public static AppSettings Load()
|
|
||||||
{
|
|
||||||
if (!File.Exists(SettingsFile))
|
|
||||||
return new AppSettings();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
XmlSerializer serializer = new XmlSerializer(typeof(AppSettings));
|
|
||||||
|
|
||||||
using (FileStream fs = new FileStream(SettingsFile, FileMode.Open))
|
|
||||||
return (AppSettings)serializer.Deserialize(fs);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Terminal.WriteError(ex.ToString());
|
|
||||||
return new AppSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Save(object obj)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (XmlTextWriter writer = new XmlTextWriter(SettingsFile, Encoding.UTF8))
|
|
||||||
{
|
|
||||||
writer.Formatting = Formatting.Indented;
|
|
||||||
writer.Indentation = 4;
|
|
||||||
XmlSerializer serializer = new XmlSerializer(obj.GetType());
|
|
||||||
serializer.Serialize(writer, obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Terminal.WriteError(ex.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public static class Terminal
|
|
||||||
{
|
|
||||||
static int Padding { get; } = 60;
|
|
||||||
|
|
||||||
public static void WriteError(object obj, string module = "mpv.net")
|
|
||||||
{
|
|
||||||
Write(obj, module, ConsoleColor.DarkRed, 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, 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 (value.Length < Padding)
|
|
||||||
value = value.PadRight(Padding);
|
|
||||||
|
|
||||||
if (color == ConsoleColor.Red || color == ConsoleColor.DarkRed)
|
|
||||||
Console.Error.WriteLine(value);
|
|
||||||
else
|
|
||||||
Console.WriteLine(value);
|
|
||||||
|
|
||||||
Console.ResetColor();
|
|
||||||
Trace.WriteLine(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
|
|
||||||
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 Brush Background { get; set; }
|
|
||||||
public Brush Foreground { get; set; }
|
|
||||||
public Brush Foreground2 { get; set; }
|
|
||||||
public Brush Heading { get; set; }
|
|
||||||
public Brush MenuBackground { get; set; }
|
|
||||||
public Brush MenuHighlight { get; set; }
|
|
||||||
|
|
||||||
public Brush GetBrush(string key)
|
|
||||||
{
|
|
||||||
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color GetColor(string key) => (Color)ColorConverter.ConvertFromString(Dictionary[key]);
|
|
||||||
|
|
||||||
public static void Init(string customContent, string defaultContent, string activeTheme)
|
|
||||||
{
|
|
||||||
Current = null;
|
|
||||||
|
|
||||||
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;
|
|
||||||
Terminal.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];
|
|
||||||
|
|
||||||
Current.Background = Current.GetBrush("background");
|
|
||||||
Current.Foreground = Current.GetBrush("foreground");
|
|
||||||
Current.Foreground2 = Current.GetBrush("foreground2");
|
|
||||||
Current.Heading = Current.GetBrush("heading");
|
|
||||||
Current.MenuBackground = Current.GetBrush("menu-background");
|
|
||||||
Current.MenuHighlight = Current.GetBrush("menu-highlight");
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
24
src/MpvNet.Extension/ExampleExtension/ExampleExtension.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
namespace MpvNet.Extension.ExampleExtension;
|
||||||
|
|
||||||
|
public class Extension : IExtension
|
||||||
|
{
|
||||||
|
public MpvClient Player { get; set; }
|
||||||
|
|
||||||
|
public Extension()
|
||||||
|
{
|
||||||
|
Player = Global.Player.CreateNewPlayer("example");
|
||||||
|
Player.ObservePropertyBool("fullscreen", FullscreenChange);
|
||||||
|
Player.FileLoaded += Player_FileLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player_FileLoaded()
|
||||||
|
{
|
||||||
|
Terminal.Write("File loaded: " + Player.GetPropertyString("path"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullscreenChange(bool value)
|
||||||
|
{
|
||||||
|
Player.CommandV("show-text", "fullscreen: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
<OutputPath>C:\Users\frank\AppData\Roaming\mpv.net-experimental\extensions\ExampleExtension</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\MpvNet\MpvNet.csproj">
|
||||||
|
<Private>False</Private>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
25
src/MpvNet.Extension/ExampleExtension/ExampleExtension.sln
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.7.34018.315
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExampleExtension", "ExampleExtension.csproj", "{4D6623A0-E890-44E5-956F-D5A5A24A6619}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4D6623A0-E890-44E5-956F-D5A5A24A6619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4D6623A0-E890-44E5-956F-D5A5A24A6619}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4D6623A0-E890-44E5-956F-D5A5A24A6619}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4D6623A0-E890-44E5-956F-D5A5A24A6619}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {47E1F7E3-3833-4E05-841B-4683C1DEA133}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
34
src/MpvNet.Windows/.editorconfig
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[*.cs]
|
||||||
|
|
||||||
|
# IDE0058: Expression value is never used
|
||||||
|
dotnet_diagnostic.IDE0058.severity = none
|
||||||
|
|
||||||
|
# IDE0055: Fix formatting
|
||||||
|
dotnet_diagnostic.IDE0055.severity = none
|
||||||
|
|
||||||
|
# IDE0022: Use block body for methods
|
||||||
|
dotnet_diagnostic.IDE0022.severity = none
|
||||||
|
|
||||||
|
# IDE0040: Add accessibility modifiers
|
||||||
|
dotnet_diagnostic.IDE0040.severity = none
|
||||||
|
|
||||||
|
# IDE0011: Add braces
|
||||||
|
dotnet_diagnostic.IDE0011.severity = none
|
||||||
|
|
||||||
|
# IDE0010: Add missing cases
|
||||||
|
dotnet_diagnostic.IDE0010.severity = none
|
||||||
|
|
||||||
|
# IDE0044: Add readonly modifier
|
||||||
|
dotnet_diagnostic.IDE0044.severity = silent
|
||||||
|
|
||||||
|
# Member does not access instance data and can be marked as static
|
||||||
|
dotnet_diagnostic.CA1822.severity = none
|
||||||
|
|
||||||
|
# IDE0057: Use range operator
|
||||||
|
csharp_style_prefer_range_operator = false
|
||||||
|
|
||||||
|
# CA1401: P/Invokes should not be visible
|
||||||
|
dotnet_diagnostic.CA1401.severity = none
|
||||||
|
|
||||||
|
# IDE0017: Simplify object initialization
|
||||||
|
dotnet_style_object_initializer = false
|
||||||
@@ -2,7 +2,4 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<configSections>
|
<configSections>
|
||||||
</configSections>
|
</configSections>
|
||||||
<startup>
|
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
|
||||||
</startup>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
138
src/MpvNet.Windows/Conf.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
|
||||||
|
using MpvNet.ExtensionMethod;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows;
|
||||||
|
|
||||||
|
public class Conf
|
||||||
|
{
|
||||||
|
public static List<Setting> LoadConf(string content)
|
||||||
|
{
|
||||||
|
List<Setting> settingsList = new List<Setting>();
|
||||||
|
|
||||||
|
foreach (ConfSection? section in ConfParser.Parse(content))
|
||||||
|
{
|
||||||
|
Setting? baseSetting = null;
|
||||||
|
|
||||||
|
if (section.HasName("option"))
|
||||||
|
{
|
||||||
|
OptionSetting optionSetting = new OptionSetting();
|
||||||
|
baseSetting = optionSetting;
|
||||||
|
optionSetting.Default = section.GetValue("default");
|
||||||
|
optionSetting.Value = optionSetting.Default;
|
||||||
|
|
||||||
|
foreach (var it in section.GetValues("option"))
|
||||||
|
{
|
||||||
|
var opt = new OptionSettingOption();
|
||||||
|
|
||||||
|
if (it.Value.ContainsEx(" "))
|
||||||
|
{
|
||||||
|
opt.Name = it.Value![..it.Value!.IndexOf(" ")];
|
||||||
|
opt.Help = it.Value[it.Value.IndexOf(" ")..].Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
opt.Name = it.Value;
|
||||||
|
|
||||||
|
if (opt.Name == optionSetting.Default)
|
||||||
|
opt.Text = opt.Name + " (Default)";
|
||||||
|
|
||||||
|
opt.OptionSetting = optionSetting;
|
||||||
|
optionSetting.Options.Add(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringSetting stringSetting = new StringSetting();
|
||||||
|
baseSetting = stringSetting;
|
||||||
|
stringSetting.Default = section.HasName("default") ? section.GetValue("default") : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
baseSetting.Name = section.GetValue("name");
|
||||||
|
baseSetting.File = section.GetValue("file");
|
||||||
|
baseSetting.Directory = section.GetValue("directory");
|
||||||
|
|
||||||
|
if (section.HasName("help")) baseSetting.Help = section.GetValue("help");
|
||||||
|
if (section.HasName("url")) baseSetting.URL = section.GetValue("url");
|
||||||
|
if (section.HasName("width")) baseSetting.Width = Convert.ToInt32(section.GetValue("width"));
|
||||||
|
if (section.HasName("option-name-width")) baseSetting.OptionNameWidth = Convert.ToInt32(section.GetValue("option-name-width"));
|
||||||
|
if (section.HasName("type")) baseSetting.Type = section.GetValue("type");
|
||||||
|
|
||||||
|
if (baseSetting.Help.ContainsEx("\\n"))
|
||||||
|
baseSetting.Help = baseSetting.Help?.Replace("\\n", "\n");
|
||||||
|
|
||||||
|
settingsList.Add(baseSetting);
|
||||||
|
}
|
||||||
|
|
||||||
|
return settingsList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfItem
|
||||||
|
{
|
||||||
|
public string Comment { get; set; } = "";
|
||||||
|
public string File { get; set; } = "";
|
||||||
|
public string LineComment { get; set; } = "";
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Section { get; set; } = "";
|
||||||
|
public string Value { get; set; } = "";
|
||||||
|
|
||||||
|
public bool IsSectionItem { get; set; }
|
||||||
|
public Setting? SettingBase { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfParser
|
||||||
|
{
|
||||||
|
public static List<ConfSection> Parse(string content)
|
||||||
|
{
|
||||||
|
string[] lines = content.Split('\n');
|
||||||
|
var sections = new List<ConfSection>();
|
||||||
|
ConfSection? currentGroup = null;
|
||||||
|
|
||||||
|
foreach (string it in lines)
|
||||||
|
{
|
||||||
|
string line = it.Trim();
|
||||||
|
|
||||||
|
if (line.StartsWith('#'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line == "")
|
||||||
|
{
|
||||||
|
currentGroup = new ConfSection();
|
||||||
|
sections.Add(currentGroup);
|
||||||
|
}
|
||||||
|
else if (line.Contains('='))
|
||||||
|
{
|
||||||
|
string name = line[..line.IndexOf("=")].Trim();
|
||||||
|
string value = line[(line.IndexOf("=") + 1)..].Trim();
|
||||||
|
|
||||||
|
currentGroup?.Items.Add(new StringPair(name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfSection
|
||||||
|
{
|
||||||
|
public List<StringPair> Items { get; set; } = new List<StringPair>();
|
||||||
|
|
||||||
|
public bool HasName(string name)
|
||||||
|
{
|
||||||
|
foreach (var i in Items)
|
||||||
|
if (i.Name == name)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? GetValue(string name)
|
||||||
|
{
|
||||||
|
foreach (var i in Items)
|
||||||
|
if (i.Name == name)
|
||||||
|
return i.Value;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<StringPair> GetValues(string name) => Items.Where(i => i.Name == name).ToList();
|
||||||
|
}
|
||||||
68
src/MpvNet.Windows/FileAssociation.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
using MpvNet.Windows.Help;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows;
|
||||||
|
|
||||||
|
public static class FileAssociation
|
||||||
|
{
|
||||||
|
public static void Register(string perceivedType, string[] extensions)
|
||||||
|
{
|
||||||
|
string exePath = Environment.ProcessPath!;
|
||||||
|
string exeFilename = Path.GetFileName(exePath);
|
||||||
|
string exeFilenameNoExt = Path.GetFileNameWithoutExtension(exePath);
|
||||||
|
|
||||||
|
string[] protocols = { "ytdl", "rtsp", "srt", "srtp" };
|
||||||
|
|
||||||
|
if (perceivedType != "unreg")
|
||||||
|
{
|
||||||
|
foreach (string it in protocols)
|
||||||
|
{
|
||||||
|
RegistryHelp.SetValue($@"HKCR\{it}", $"{it.ToUpper()} Protocol", "");
|
||||||
|
RegistryHelp.SetValue($@"HKCR\{it}\shell\open\command", "", $"\"{exePath}\" \"%1\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
RegistryHelp.SetValue(@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + exeFilename, "", exePath);
|
||||||
|
RegistryHelp.SetValue(@"HKCR\Applications\" + exeFilename, "FriendlyAppName", "mpv.net media player");
|
||||||
|
RegistryHelp.SetValue(@"HKCR\Applications\" + exeFilename + @"\shell\open\command", "", $"\"{exePath}\" \"%1\"");
|
||||||
|
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\video\OpenWithList\" + exeFilename, "", "");
|
||||||
|
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\audio\OpenWithList\" + exeFilename, "", "");
|
||||||
|
RegistryHelp.SetValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net", @"SOFTWARE\Clients\Media\mpv.net\Capabilities");
|
||||||
|
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");
|
||||||
|
|
||||||
|
foreach (string ext in extensions)
|
||||||
|
{
|
||||||
|
RegistryHelp.SetValue(@"HKCR\Applications\" + exeFilename + @"\SupportedTypes", "." + ext, "");
|
||||||
|
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "", exeFilenameNoExt + "." + ext);
|
||||||
|
RegistryHelp.SetValue(@"HKCR\" + "." + ext + @"\OpenWithProgIDs", exeFilenameNoExt + "." + ext, "");
|
||||||
|
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", perceivedType);
|
||||||
|
RegistryHelp.SetValue(@"HKCR\" + exeFilenameNoExt + "." + ext + @"\shell\open\command", "", $"\"{exePath}\" \"%1\"");
|
||||||
|
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, exeFilenameNoExt + "." + ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (string i in protocols)
|
||||||
|
RegistryHelp.RemoveKey($@"HKCR\{i}");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/MpvNet.Windows/GlobalUsings.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
global using System;
|
||||||
|
global using System.Collections.Generic;
|
||||||
|
global using System.Diagnostics;
|
||||||
|
global using System.IO;
|
||||||
|
global using System.Linq;
|
||||||
|
|
||||||
|
global using static MpvNet.Global;
|
||||||
400
src/MpvNet.Windows/GuiCommand.cs
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
using MpvNet.ExtensionMethod;
|
||||||
|
using MpvNet.Windows.WinForms;
|
||||||
|
using MpvNet.Windows.WPF.Views;
|
||||||
|
using MpvNet.Windows.WPF;
|
||||||
|
using MpvNet.Windows.WPF.MsgBox;
|
||||||
|
using MpvNet.Help;
|
||||||
|
using System.Text.Json;
|
||||||
|
using MpvNet.Windows.Help;
|
||||||
|
|
||||||
|
namespace MpvNet;
|
||||||
|
|
||||||
|
public class GuiCommand
|
||||||
|
{
|
||||||
|
Dictionary<string, Action<IList<string>>>? _commands;
|
||||||
|
|
||||||
|
public event Action<float>? ScaleWindow;
|
||||||
|
public event Action<string>? MoveWindow;
|
||||||
|
public event Action<float>? WindowScaleNet;
|
||||||
|
public event Action? ShowMenu;
|
||||||
|
|
||||||
|
public static GuiCommand Current { get; } = new();
|
||||||
|
|
||||||
|
public Dictionary<string, Action<IList<string>>> Commands => _commands ??= new()
|
||||||
|
{
|
||||||
|
["show-about"] = args => ShowDialog(typeof(AboutWindow)),
|
||||||
|
["show-conf-editor"] = args => ShowDialog(typeof(ConfWindow)),
|
||||||
|
["show-input-editor"] = args => ShowDialog(typeof(InputWindow)),
|
||||||
|
["show-audio-devices"] = args => Msg.ShowInfo(Player.GetPropertyOsdString("audio-device-list")),
|
||||||
|
["show-profiles"] = args => Msg.ShowInfo(Player.GetProfiles()),
|
||||||
|
["load-sub"] = LoadSubtitle,
|
||||||
|
["open-files"] = OpenFiles,
|
||||||
|
["open-optical-media"] = Open_DVD_Or_BD_Folder,
|
||||||
|
["load-audio"] = LoadAudio,
|
||||||
|
["open-clipboard"] = OpenFromClipboard,
|
||||||
|
["reg-file-assoc"] = RegisterFileAssociations,
|
||||||
|
["scale-window"] = args => ScaleWindow?.Invoke(float.Parse(args[0], CultureInfo.InvariantCulture)),
|
||||||
|
["show-media-info"] = ShowMediaInfo,
|
||||||
|
["move-window"] = args => MoveWindow?.Invoke(args[0]),
|
||||||
|
["window-scale"] = args => WindowScaleNet?.Invoke(float.Parse(args[0], CultureInfo.InvariantCulture)),
|
||||||
|
["show-menu"] = args => ShowMenu?.Invoke(),
|
||||||
|
["show-bindings"] = args => ShowBindings(),
|
||||||
|
["show-playlist"] = args => ShowPlaylist(),
|
||||||
|
["add-to-path"] = args => AddToPath(),
|
||||||
|
["edit-conf-file"] = EditCongFile,
|
||||||
|
["show-commands"] = args => ShowCommands(),
|
||||||
|
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
["show-info"] = args => ShowMediaInfo(new[] { "osd" }), // deprecated
|
||||||
|
["quick-bookmark"] = args => QuickBookmark(), // deprecated
|
||||||
|
["show-history"] = args => ShowHistory(), // deprecated
|
||||||
|
["show-command-palette"] = args => ShowCommandPalette(), // deprecated
|
||||||
|
};
|
||||||
|
|
||||||
|
public void ShowDialog(Type winType)
|
||||||
|
{
|
||||||
|
Window? win = Activator.CreateInstance(winType) as Window;
|
||||||
|
new WindowInteropHelper(win).Owner = MainForm.Instance!.Handle;
|
||||||
|
win?.ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadSubtitle(IList<string> args)
|
||||||
|
{
|
||||||
|
using var dialog = new OpenFileDialog();
|
||||||
|
string path = Player.GetPropertyString("path");
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
dialog.InitialDirectory = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
|
dialog.Multiselect = true;
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
|
foreach (string filename in dialog.FileNames)
|
||||||
|
Player.CommandV("sub-add", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenFiles(IList<string> args)
|
||||||
|
{
|
||||||
|
bool append = false;
|
||||||
|
|
||||||
|
foreach (string arg in args)
|
||||||
|
if (arg == "append")
|
||||||
|
append = true;
|
||||||
|
|
||||||
|
using var dialog = new OpenFileDialog() { Multiselect = true };
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
|
Player.LoadFiles(dialog.FileNames, true, append);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Open_DVD_Or_BD_Folder(IList<string> args)
|
||||||
|
{
|
||||||
|
var dialog = new FolderBrowserDialog();
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
|
Player.LoadDiskFolder(dialog.SelectedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EditCongFile(IList<string> args)
|
||||||
|
{
|
||||||
|
string file = Player.ConfigFolder + args[0];
|
||||||
|
|
||||||
|
if (File.Exists(file))
|
||||||
|
ProcessHelp.ShellExecute(WinApiHelp.GetAppPathForExtension("txt"), "\"" + file + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowTextWithEditor(string name, string text)
|
||||||
|
{
|
||||||
|
string file = Path.Combine(Path.GetTempPath(), name + ".txt");
|
||||||
|
App.TempFiles.Add(file);
|
||||||
|
File.WriteAllText(file, BR + text.Trim() + BR);
|
||||||
|
ProcessHelp.ShellExecute(WinApiHelp.GetAppPathForExtension("txt"), "\"" + file + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowCommands()
|
||||||
|
{
|
||||||
|
string json = Core.GetPropertyString("command-list");
|
||||||
|
var enumerator = JsonDocument.Parse(json).RootElement.EnumerateArray();
|
||||||
|
var commands = enumerator.OrderBy(it => it.GetProperty("name").GetString());
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (var cmd in commands)
|
||||||
|
{
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine(cmd.GetProperty("name").GetString());
|
||||||
|
|
||||||
|
foreach (var args in cmd.GetProperty("args").EnumerateArray())
|
||||||
|
{
|
||||||
|
string value = args.GetProperty("name").GetString() + " <" +
|
||||||
|
args.GetProperty("type").GetString()!.ToLower() + ">";
|
||||||
|
|
||||||
|
if (args.GetProperty("optional").GetBoolean())
|
||||||
|
value = "[" + value + "]";
|
||||||
|
|
||||||
|
sb.AppendLine(" " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string header = BR +
|
||||||
|
"https://mpv.io/manual/master/#list-of-input-commands" + BR2 +
|
||||||
|
"https://github.com/stax76/mpv-scripts#command_palette" + BR;
|
||||||
|
|
||||||
|
ShowTextWithEditor("Input Commands", header + sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenFromClipboard(IList<string> args)
|
||||||
|
{
|
||||||
|
bool append = args.Count == 1 && args[0] == "append";
|
||||||
|
|
||||||
|
if (System.Windows.Forms.Clipboard.ContainsFileDropList())
|
||||||
|
{
|
||||||
|
string[] files = System.Windows.Forms.Clipboard.GetFileDropList().Cast<string>().ToArray();
|
||||||
|
Player.LoadFiles(files, false, append);
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
Player.CommandV("show-text", _("Files/URLs were added to the playlist"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string clipboard = System.Windows.Forms.Clipboard.GetText();
|
||||||
|
List<string> files = new List<string>();
|
||||||
|
|
||||||
|
foreach (string i in clipboard.Split(BR.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
if (i.Contains("://") || File.Exists(i))
|
||||||
|
files.Add(i);
|
||||||
|
|
||||||
|
if (files.Count == 0)
|
||||||
|
{
|
||||||
|
Terminal.WriteError(_("The clipboard does not contain a valid URL or file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.LoadFiles(files.ToArray(), false, append);
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
Player.CommandV("show-text", _("Files/URLs were added to the playlist"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadAudio(IList<string> args)
|
||||||
|
{
|
||||||
|
using var dialog = new OpenFileDialog();
|
||||||
|
string path = Player.GetPropertyString("path");
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
dialog.InitialDirectory = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
|
dialog.Multiselect = true;
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
|
foreach (string i in dialog.FileNames)
|
||||||
|
Player.CommandV("audio-add", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterFileAssociations(IList<string> args)
|
||||||
|
{
|
||||||
|
string perceivedType = args[0];
|
||||||
|
string[] extensions = Array.Empty<string>();
|
||||||
|
|
||||||
|
switch (perceivedType)
|
||||||
|
{
|
||||||
|
case "video": extensions = FileTypes.Video; break;
|
||||||
|
case "audio": extensions = FileTypes.Audio; break;
|
||||||
|
case "image": extensions = FileTypes.Image; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using Process proc = new Process();
|
||||||
|
proc.StartInfo.FileName = Environment.ProcessPath;
|
||||||
|
proc.StartInfo.Arguments = "--register-file-associations " +
|
||||||
|
perceivedType + " " + string.Join(" ", extensions);
|
||||||
|
proc.StartInfo.Verb = "runas";
|
||||||
|
proc.StartInfo.UseShellExecute = true;
|
||||||
|
proc.Start();
|
||||||
|
proc.WaitForExit();
|
||||||
|
|
||||||
|
if (proc.ExitCode == 0)
|
||||||
|
{
|
||||||
|
string msgRestart = _("File Explorer icons will refresh after process restart.");
|
||||||
|
|
||||||
|
if (perceivedType == "unreg")
|
||||||
|
Msg.ShowInfo(_("File associations were successfully removed.") + BR2 + msgRestart);
|
||||||
|
else
|
||||||
|
Msg.ShowInfo(_("File associations were successfully created.") + BR2 + msgRestart);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Msg.ShowError(_("Error creating file associations."));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowMediaInfo(IList<string> args)
|
||||||
|
{
|
||||||
|
if (Player.PlaylistPos == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool full = args.Contains("full");
|
||||||
|
bool raw = args.Contains("raw");
|
||||||
|
bool editor = args.Contains("editor");
|
||||||
|
bool osd = args.Contains("osd") || args == null || args.Count == 0;
|
||||||
|
|
||||||
|
long fileSize = 0;
|
||||||
|
|
||||||
|
string text = "";
|
||||||
|
string path = Player.GetPropertyString("path");
|
||||||
|
|
||||||
|
if (File.Exists(path) && osd)
|
||||||
|
{
|
||||||
|
if (FileTypes.Audio.Contains(path.Ext()))
|
||||||
|
{
|
||||||
|
text = Player.GetPropertyOsdString("filtered-metadata");
|
||||||
|
Player.CommandV("show-text", text, "5000");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (FileTypes.Image.Contains(path.Ext()))
|
||||||
|
{
|
||||||
|
fileSize = new FileInfo(path).Length;
|
||||||
|
|
||||||
|
text = "Width: " + Player.GetPropertyInt("width") + "\n" +
|
||||||
|
"Height: " + Player.GetPropertyInt("height") + "\n" +
|
||||||
|
"Size: " + Convert.ToInt32(fileSize / 1024.0) + " KB\n" +
|
||||||
|
"Type: " + path.Ext().ToUpper();
|
||||||
|
|
||||||
|
Player.CommandV("show-text", text, "5000");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.Contains("://"))
|
||||||
|
{
|
||||||
|
if (path.Contains("://"))
|
||||||
|
path = Player.GetPropertyString("media-title");
|
||||||
|
string videoFormat = Player.GetPropertyString("video-format").ToUpper();
|
||||||
|
string audioCodec = Player.GetPropertyString("audio-codec-name").ToUpper();
|
||||||
|
int width = Player.GetPropertyInt("video-params/w");
|
||||||
|
int height = Player.GetPropertyInt("video-params/h");
|
||||||
|
TimeSpan len = TimeSpan.FromSeconds(Player.GetPropertyDouble("duration"));
|
||||||
|
text = path.FileName() + "\n";
|
||||||
|
text += FormatTime(len.TotalMinutes) + ":" + FormatTime(len.Seconds) + "\n";
|
||||||
|
if (fileSize > 0)
|
||||||
|
text += Convert.ToInt32(fileSize / 1024.0 / 1024.0) + " MB\n";
|
||||||
|
text += $"{width} x {height}\n";
|
||||||
|
text += $"{videoFormat}\n{audioCodec}";
|
||||||
|
Player.CommandV("show-text", text, "5000");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (App.MediaInfo && !osd && File.Exists(path) && !path.Contains(@"\\.\pipe\"))
|
||||||
|
using (MediaInfo mediaInfo = new MediaInfo(path))
|
||||||
|
text = Regex.Replace(mediaInfo.GetSummary(full, raw), "Unique ID.+", "");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Player.UpdateExternalTracks();
|
||||||
|
text = "N: " + Player.GetPropertyString("filename") + BR;
|
||||||
|
lock (Player.MediaTracksLock)
|
||||||
|
foreach (MediaTrack track in Player.MediaTracks)
|
||||||
|
text += track.Text + BR;
|
||||||
|
}
|
||||||
|
|
||||||
|
text = text.TrimEx();
|
||||||
|
|
||||||
|
if (editor)
|
||||||
|
ShowTextWithEditor("media-info", text);
|
||||||
|
else if (osd)
|
||||||
|
Command.ShowText(text.Replace("\r", ""), 5000, 16);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxEx.SetFont("Consolas");
|
||||||
|
Msg.ShowInfo(text);
|
||||||
|
MessageBoxEx.SetFont("Segoe UI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatTime(double value) => ((int)value).ToString("00");
|
||||||
|
|
||||||
|
public void ShowBindings() => ShowTextWithEditor("Bindings", Player.UsedInputConfContent);
|
||||||
|
|
||||||
|
public void AddToPath()
|
||||||
|
{
|
||||||
|
string path = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.User)!;
|
||||||
|
|
||||||
|
if (path.ToLower().Contains(Folder.Startup.TrimEnd(Path.DirectorySeparatorChar).ToLower()))
|
||||||
|
{
|
||||||
|
Msg.ShowWarning(_("mpv.net is already in Path."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable("Path",
|
||||||
|
Folder.Startup.TrimEnd(Path.DirectorySeparatorChar) + ";" + path,
|
||||||
|
EnvironmentVariableTarget.User);
|
||||||
|
|
||||||
|
Msg.ShowInfo(_("mpv.net was successfully added to Path."));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowPlaylist()
|
||||||
|
{
|
||||||
|
var count = Player.GetPropertyInt("playlist-count");
|
||||||
|
|
||||||
|
if (count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
string name = Player.GetPropertyString($"playlist/{i}/title");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
name = Player.GetPropertyString($"playlist/{i}/filename").FileName();
|
||||||
|
|
||||||
|
sb.AppendLine(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
string header = BR + "For a playlist menu the following user scripts exist:" + BR2 +
|
||||||
|
"https://github.com/stax76/mpv-scripts#command_palette" + BR +
|
||||||
|
"https://github.com/stax76/mpv-scripts#search_menu" + BR +
|
||||||
|
"https://github.com/tomasklaen/uosc" + BR +
|
||||||
|
"https://github.com/jonniek/mpv-playlistmanager" + BR2;
|
||||||
|
|
||||||
|
Msg.ShowInfo(header + sb.ToString().TrimEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
public void QuickBookmark() =>
|
||||||
|
Msg.ShowInfo("This feature was moved to a user script,\nwhich can be found here:\n\n" +
|
||||||
|
"https://github.com/stax76/mpv-scripts/blob/main/misc.lua");
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
public void ShowHistory() =>
|
||||||
|
Msg.ShowInfo("This feature was moved to a user script,\nwhich can be found here:\n\n" +
|
||||||
|
"https://github.com/stax76/mpv-scripts/blob/main/history.lua");
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
public void ShowCommandPalette() =>
|
||||||
|
Msg.ShowInfo(
|
||||||
|
"This feature was removed but is still available in the form of user scripts:" + BR2 +
|
||||||
|
"https://github.com/stax76/mpv-scripts#command_palette" + BR +
|
||||||
|
"https://github.com/stax76/mpv-scripts#search_menu" + BR +
|
||||||
|
"https://github.com/tomasklaen/uosc");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//public void ShowCommandPalette()
|
||||||
|
//{
|
||||||
|
// MainForm.Instance?.BeginInvoke(() => {
|
||||||
|
// CommandPalette.Instance.SetItems(CommandPalette.GetItems());
|
||||||
|
// MainForm.Instance.ShowCommandPalette();
|
||||||
|
// CommandPalette.Instance.SelectFirst();
|
||||||
|
// });
|
||||||
|
//}
|
||||||
74
src/MpvNet.Windows/Help/RegistryHelp.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.Help;
|
||||||
|
|
||||||
|
public static class RegistryHelp
|
||||||
|
{
|
||||||
|
static string? _appKey;
|
||||||
|
|
||||||
|
public static string? ProductName { get; set; }
|
||||||
|
|
||||||
|
public static string AppKey {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (ProductName == null)
|
||||||
|
throw new Exception("ProductName cannot be null.");
|
||||||
|
|
||||||
|
return _appKey ??= @"HKCU\Software\" + ProductName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetInt(string name, object value) => SetValue(AppKey, name, value);
|
||||||
|
|
||||||
|
public static void SetString(string name, string value) => SetValue(AppKey, name, value);
|
||||||
|
|
||||||
|
public static void SetValue(string name, object value)
|
||||||
|
{
|
||||||
|
using RegistryKey regKey = GetRootKey(AppKey).CreateSubKey(AppKey[5..], RegistryKeyPermissionCheck.ReadWriteSubTree);
|
||||||
|
regKey.SetValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetValue(string path, string name, object value)
|
||||||
|
{
|
||||||
|
using RegistryKey regKey = GetRootKey(path).CreateSubKey(path[5..], RegistryKeyPermissionCheck.ReadWriteSubTree);
|
||||||
|
regKey.SetValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetString(string name, string defaultValue = "") =>
|
||||||
|
GetValue(AppKey, name, defaultValue)?.ToString() ?? defaultValue;
|
||||||
|
|
||||||
|
public static int GetInt(string name, int defaultValue = 0) =>
|
||||||
|
GetValue(AppKey, name, defaultValue) is int i ? i : defaultValue;
|
||||||
|
|
||||||
|
public static object? GetValue(string name) => GetValue(AppKey, name, null);
|
||||||
|
|
||||||
|
public static object? GetValue(string path, string name, object? defaultValue = null)
|
||||||
|
{
|
||||||
|
using RegistryKey? regKey = GetRootKey(path).OpenSubKey(path[5..]);
|
||||||
|
return regKey?.GetValue(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveKey(string path)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
GetRootKey(path).DeleteSubKeyTree(path[5..], false);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveValue(string path, string name)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
using RegistryKey? regKey = GetRootKey(path).OpenSubKey(path[5..], true);
|
||||||
|
regKey?.DeleteValue(name, false);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegistryKey GetRootKey(string path) => path[..4] switch
|
||||||
|
{
|
||||||
|
"HKLM" => Registry.LocalMachine,
|
||||||
|
"HKCU" => Registry.CurrentUser,
|
||||||
|
"HKCR" => Registry.ClassesRoot,
|
||||||
|
_ => throw new Exception(),
|
||||||
|
};
|
||||||
|
}
|
||||||
130
src/MpvNet.Windows/Help/WinApiHelp.cs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using static MpvNet.Windows.Native.WinApi;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.Help;
|
||||||
|
|
||||||
|
public static class WinApiHelp
|
||||||
|
{
|
||||||
|
public static Version WindowsTen1607 { get; } = new Version(10, 0, 14393); // Windows 10 1607
|
||||||
|
|
||||||
|
public static int GetResizeBorder(int v)
|
||||||
|
{
|
||||||
|
switch (v)
|
||||||
|
{
|
||||||
|
case 1 /* WMSZ_LEFT */ : return 3;
|
||||||
|
case 3 /* WMSZ_TOP */ : return 2;
|
||||||
|
case 2 /* WMSZ_RIGHT */ : return 3;
|
||||||
|
case 6 /* WMSZ_BOTTOM */ : return 2;
|
||||||
|
case 4 /* WMSZ_TOPLEFT */ : return 1;
|
||||||
|
case 5 /* WMSZ_TOPRIGHT */ : return 1;
|
||||||
|
case 7 /* WMSZ_BOTTOMLEFT */ : return 3;
|
||||||
|
case 8 /* WMSZ_BOTTOMRIGHT */ : return 3;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AdjustWindowRect(IntPtr hwnd, ref RECT rc, int dpi)
|
||||||
|
{
|
||||||
|
uint style = (uint)GetWindowLongPtr(hwnd, -16); // GWL_STYLE
|
||||||
|
uint styleEx = (uint)GetWindowLongPtr(hwnd, -20); // GWL_EXSTYLE
|
||||||
|
|
||||||
|
if (Environment.OSVersion.Version >= WindowsTen1607)
|
||||||
|
AdjustWindowRectExForDpi(ref rc, style, false, styleEx, (uint)dpi);
|
||||||
|
else
|
||||||
|
Native.WinApi.AdjustWindowRect(ref rc, style, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddWindowBorders(IntPtr hwnd, ref RECT rc, int dpi, bool changeTop)
|
||||||
|
{
|
||||||
|
RECT win = rc;
|
||||||
|
AdjustWindowRect(hwnd, ref rc, dpi);
|
||||||
|
|
||||||
|
if (changeTop)
|
||||||
|
{
|
||||||
|
int top = rc.Top;
|
||||||
|
top -= rc.Top - win.Top;
|
||||||
|
rc = new RECT(rc.Left, top, rc.Right, rc.Bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SubtractWindowBorders(IntPtr hwnd, ref RECT rc, int dpi, bool changeTop)
|
||||||
|
{
|
||||||
|
RECT r = new RECT();
|
||||||
|
AddWindowBorders(hwnd, ref r, dpi, changeTop);
|
||||||
|
rc.Left -= r.Left;
|
||||||
|
rc.Top -= r.Top;
|
||||||
|
rc.Right -= r.Right;
|
||||||
|
rc.Bottom -= r.Bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetTitleBarHeight(IntPtr hwnd, int dpi)
|
||||||
|
{
|
||||||
|
RECT rect = new RECT();
|
||||||
|
AdjustWindowRect(hwnd, ref rect, dpi);
|
||||||
|
return -rect.Top;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Rectangle GetWorkingArea(IntPtr handle, Rectangle workingArea)
|
||||||
|
{
|
||||||
|
if (handle != IntPtr.Zero && GetDwmWindowRect(handle, out RECT dwmRect) &&
|
||||||
|
GetWindowRect(handle, out RECT rect))
|
||||||
|
{
|
||||||
|
int left = workingArea.Left;
|
||||||
|
int top = workingArea.Top;
|
||||||
|
int right = workingArea.Right;
|
||||||
|
int bottom = workingArea.Bottom;
|
||||||
|
|
||||||
|
left += rect.Left - dwmRect.Left;
|
||||||
|
top -= rect.Top - dwmRect.Top;
|
||||||
|
right -= dwmRect.Right - rect.Right;
|
||||||
|
bottom -= dwmRect.Bottom - rect.Bottom;
|
||||||
|
|
||||||
|
return new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
return workingArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool GetDwmWindowRect(IntPtr handle, out RECT rect)
|
||||||
|
{
|
||||||
|
const uint DWMWA_EXTENDED_FRAME_BOUNDS = 9;
|
||||||
|
|
||||||
|
return 0 == DwmGetWindowAttribute(handle, DWMWA_EXTENDED_FRAME_BOUNDS,
|
||||||
|
out rect, (uint)Marshal.SizeOf<RECT>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetAppPathForExtension(params string[] extensions)
|
||||||
|
{
|
||||||
|
foreach (string it in extensions)
|
||||||
|
{
|
||||||
|
string extension = it;
|
||||||
|
|
||||||
|
if (!extension.StartsWith("."))
|
||||||
|
extension = "." + extension;
|
||||||
|
|
||||||
|
uint c = 0U;
|
||||||
|
|
||||||
|
if (AssocQueryString(0x40, 2, extension, null, null, ref c) == 1)
|
||||||
|
{
|
||||||
|
if (c > 0L)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder((int)c);
|
||||||
|
|
||||||
|
if (0 == AssocQueryString(0x40, 2, extension, default, sb, ref c))
|
||||||
|
{
|
||||||
|
string ret = sb.ToString();
|
||||||
|
|
||||||
|
if (File.Exists(ret))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/MpvNet.Windows/MpvNet.Windows.csproj
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
|
<RootNamespace>MpvNet.Windows</RootNamespace>
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
<AssemblyName>mpvnet</AssemblyName>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<ApplicationIcon>mpv-icon.ico</ApplicationIcon>
|
||||||
|
<Product>mpv.net</Product>
|
||||||
|
<FileVersion>7.0.0.5</FileVersion>
|
||||||
|
<AssemblyVersion>7.0.0.5</AssemblyVersion>
|
||||||
|
<InformationalVersion>7.0.0.5</InformationalVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Misc\**" />
|
||||||
|
<EmbeddedResource Remove="Misc\**" />
|
||||||
|
<None Remove="Misc\**" />
|
||||||
|
<Page Remove="Misc\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="mpv-icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MpvNet\MpvNet.csproj" />
|
||||||
|
<ProjectReference Include="..\NGettext.Wpf\NGettext.Wpf.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="WPF\Views\AboutWindow.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<XamlRuntime>Wpf</XamlRuntime>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
public class StockIcon
|
public class StockIcon
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
public class Taskbar
|
public class Taskbar
|
||||||
@@ -52,4 +51,4 @@ public enum TaskbarStates
|
|||||||
Normal = 0x2,
|
Normal = 0x2,
|
||||||
Error = 0x4,
|
Error = 0x4,
|
||||||
Paused = 0x8
|
Paused = 0x8
|
||||||
}
|
}
|
||||||
138
src/MpvNet.Windows/Native/WinApi.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using static HandyControl.Tools.Interop.InteropValues;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.Native;
|
||||||
|
|
||||||
|
public static 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")]
|
||||||
|
public static extern uint ActivateKeyboardLayout(IntPtr hkl, uint flags);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
|
||||||
|
|
||||||
|
[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 int GetDpiForWindow(IntPtr hwnd);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool AdjustWindowRectExForDpi(
|
||||||
|
ref RECT lpRect, uint dwStyle, bool bMenu, uint dwExStyle, uint dpi);
|
||||||
|
|
||||||
|
[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")]
|
||||||
|
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport("gdi32.dll")]
|
||||||
|
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||||
|
|
||||||
|
[DllImport("shlwapi", CharSet = CharSet.Auto)]
|
||||||
|
public static extern uint AssocQueryString(
|
||||||
|
uint flags, uint str, string? pszAssoc, string? pszExtra, [Out] StringBuilder? pszOut, ref uint pcchOut);
|
||||||
|
|
||||||
|
[DllImport("dwmapi.dll")]
|
||||||
|
public static extern int DwmGetWindowAttribute(
|
||||||
|
IntPtr hwnd, uint dwAttribute, out RECT pvAttribute, uint cbAttribute);
|
||||||
|
|
||||||
|
[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;
|
||||||
|
|
||||||
|
public static RECT FromRectangle(Rectangle rect)
|
||||||
|
{
|
||||||
|
return new RECT(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "{Left=" + Left + ",Top=" + Top + ",Right=" + Right + ",Bottom=" + Bottom + "}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NCCALCSIZE_PARAMS
|
||||||
|
{
|
||||||
|
public NCCALCSIZE_PARAMS(RECT[] r, WINDOWPOS wp)
|
||||||
|
{
|
||||||
|
rgrc = r;
|
||||||
|
lppos = wp;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||||
|
public RECT[] rgrc;
|
||||||
|
public WINDOWPOS lppos;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct CopyDataStruct
|
||||||
|
{
|
||||||
|
public IntPtr dwData;
|
||||||
|
public int cbData;
|
||||||
|
[MarshalAs(UnmanagedType.LPTStr)]
|
||||||
|
public string lpData;
|
||||||
|
}
|
||||||
|
}
|
||||||
168
src/MpvNet.Windows/Program.cs
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using MpvNet.Windows.Native;
|
||||||
|
using MpvNet.Help;
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
using MpvNet.Windows.Help;
|
||||||
|
using MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows;
|
||||||
|
|
||||||
|
static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RegistryHelp.ProductName = AppInfo.Product;
|
||||||
|
Translator.Current = new WpfTranslator();
|
||||||
|
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += (sender, e) => Terminal.WriteError(e.ExceptionObject);
|
||||||
|
Application.ThreadException += (sender, e) => Terminal.WriteError(e.Exception);
|
||||||
|
|
||||||
|
if (App.IsTerminalAttached)
|
||||||
|
WinApi.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
|
||||||
|
|
||||||
|
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
||||||
|
|
||||||
|
if (args.Length > 0 && args[0] == "--register-file-associations")
|
||||||
|
{
|
||||||
|
FileAssociation.Register(args[1], args.Skip(1).ToArray());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
App.Init();
|
||||||
|
Theme.Init();
|
||||||
|
Mutex mutex = new Mutex(true, StringHelp.GetMD5Hash(App.ConfPath), out bool isFirst);
|
||||||
|
|
||||||
|
if (Control.ModifierKeys == Keys.Shift ||
|
||||||
|
App.CommandLine.Contains("--process-instance=multi") ||
|
||||||
|
App.CommandLine.Contains("--o="))
|
||||||
|
{
|
||||||
|
App.ProcessInstance = "multi";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst)
|
||||||
|
{
|
||||||
|
List<string> args2 = new List<string> { App.ProcessInstance };
|
||||||
|
|
||||||
|
foreach (string arg in args)
|
||||||
|
{
|
||||||
|
if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") ||
|
||||||
|
arg.Contains(":\\") || arg.StartsWith("\\\\")))
|
||||||
|
|
||||||
|
args2.Add(arg);
|
||||||
|
else if (arg == "--queue")
|
||||||
|
args2[0] = "queue";
|
||||||
|
else if (arg.StartsWith("--command="))
|
||||||
|
{
|
||||||
|
args2[0] = "command";
|
||||||
|
args2.Add(arg[10..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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", args2.ToArray());
|
||||||
|
data.cbData = data.lpData.Length * 2 + 1;
|
||||||
|
WinApi.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data);
|
||||||
|
mutex.Dispose();
|
||||||
|
|
||||||
|
if (App.IsTerminalAttached)
|
||||||
|
WinApi.FreeConsole();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex.Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProcessCommandLineArguments())
|
||||||
|
Environment.GetCommandLineArgs();
|
||||||
|
else if (App.CommandLine.Contains("--o="))
|
||||||
|
{
|
||||||
|
App.AutoLoadFolder = false;
|
||||||
|
Player.Init(IntPtr.Zero);
|
||||||
|
Player.ProcessCommandLineArgsPost();
|
||||||
|
Player.ProcessCommandLineFiles();
|
||||||
|
Player.SetPropertyString("idle", "no");
|
||||||
|
Player.EventLoop();
|
||||||
|
Player.Destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Application.Run(new WinForms.MainForm());
|
||||||
|
|
||||||
|
if (App.IsTerminalAttached)
|
||||||
|
WinApi.FreeConsole();
|
||||||
|
|
||||||
|
mutex.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Terminal.WriteError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ProcessCommandLineArguments()
|
||||||
|
{
|
||||||
|
foreach (string arg in Environment.GetCommandLineArgs().Skip(1))
|
||||||
|
{
|
||||||
|
if (arg == "--profile=help")
|
||||||
|
{
|
||||||
|
Player.Init(IntPtr.Zero, false);
|
||||||
|
Console.WriteLine(Player.GetProfiles());
|
||||||
|
Player.Destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (arg == "--vd=help" || arg == "--ad=help")
|
||||||
|
{
|
||||||
|
Player.Init(IntPtr.Zero, false);
|
||||||
|
Console.WriteLine(Player.GetDecoders());
|
||||||
|
Player.Destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (arg == "--audio-device=help")
|
||||||
|
{
|
||||||
|
Player.Init(IntPtr.Zero, false);
|
||||||
|
Console.WriteLine(Player.GetPropertyOsdString("audio-device-list"));
|
||||||
|
Player.Destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (arg == "--input-keylist")
|
||||||
|
{
|
||||||
|
Player.Init(IntPtr.Zero, false);
|
||||||
|
Console.WriteLine(Player.GetPropertyString("input-key-list").Replace(",", BR));
|
||||||
|
Player.Destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (arg == "--version")
|
||||||
|
{
|
||||||
|
Player.Init(IntPtr.Zero, false);
|
||||||
|
Console.WriteLine(AppClass.About);
|
||||||
|
Player.Destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace mpvnet.Properties {
|
namespace MpvNet.Windows.Properties {
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ namespace mpvnet.Properties {
|
|||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// with the /str option, or rebuild your VS project.
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[DebuggerNonUserCode()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
internal class Resources {
|
internal class Resources {
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ namespace mpvnet.Properties {
|
|||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
get {
|
get {
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("mpvnet.Properties.Resources", typeof(Resources).Assembly);
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MpvNet.Windows.Properties.Resources", typeof(Resources).Assembly);
|
||||||
resourceMan = temp;
|
resourceMan = temp;
|
||||||
}
|
}
|
||||||
return resourceMan;
|
return resourceMan;
|
||||||
@@ -79,48 +79,7 @@ namespace mpvnet.Properties {
|
|||||||
return ResourceManager.GetString("editor_conf", resourceCulture);
|
return ResourceManager.GetString("editor_conf", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to
|
|
||||||
///# This file defines the key and mouse bindings and also the context menu of mpv.net.
|
|
||||||
///
|
|
||||||
///# A input and config editor can be found in the context menu under 'Settings'.
|
|
||||||
///
|
|
||||||
///# The mpv.conf defaults of mpv.net contain input-default-bindings=yes and
|
|
||||||
///# input-builtin-bindings=no which disables the input defaults of mpv.
|
|
||||||
///
|
|
||||||
///# The input test mode can be started via command line: --input-test
|
|
||||||
///
|
|
||||||
///# The input key list can be printed with --input-keylist or
|
|
||||||
///# shown from the context menu under: View > Show Keys
|
|
||||||
///
|
|
||||||
///# m [rest of string was truncated]";.
|
|
||||||
/// </summary>
|
|
||||||
internal static string input_conf {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("input_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 resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap mpvnet_santa {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("mpvnet_santa", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to
|
/// Looks up a localized string similar to
|
||||||
@@ -121,15 +121,6 @@
|
|||||||
<data name="editor_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="editor_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\editor_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
<value>..\Resources\editor_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||||
</data>
|
</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="mpvnet_santa" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\mpvnet-santa.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="theme" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<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>
|
<value>..\Resources\theme.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
</data>
|
</data>
|
||||||
7
src/MpvNet.Windows/Properties/launchSettings.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"MpvNet.Windows": {
|
||||||
|
"commandName": "Project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1173
src/MpvNet.Windows/Resources/editor_conf.txt
Normal file
63
src/MpvNet.Windows/Settings.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows;
|
||||||
|
|
||||||
|
public abstract class Setting
|
||||||
|
{
|
||||||
|
public string? Default { get; set; }
|
||||||
|
public string? File { get; set; }
|
||||||
|
public string? Directory { get; set; }
|
||||||
|
public string? Help { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? StartValue { get; set; }
|
||||||
|
public string? Type { get; set; }
|
||||||
|
public string? URL { get; set; }
|
||||||
|
public string? Value { get; set; }
|
||||||
|
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int OptionNameWidth { get; set; } = 100;
|
||||||
|
|
||||||
|
public ConfItem? ConfItem { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StringSetting : Setting
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OptionSetting : Setting
|
||||||
|
{
|
||||||
|
public List<OptionSettingOption> Options { get; } = new List<OptionSettingOption>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OptionSettingOption
|
||||||
|
{
|
||||||
|
string? _text;
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Help { get; set; }
|
||||||
|
public int OptionWidth { get => OptionSetting!.OptionNameWidth; }
|
||||||
|
|
||||||
|
public OptionSetting? OptionSetting { get; set; }
|
||||||
|
|
||||||
|
public string? Text
|
||||||
|
{
|
||||||
|
get => _text ?? Name;
|
||||||
|
set => _text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Checked
|
||||||
|
{
|
||||||
|
get => OptionSetting?.Value == Name;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
OptionSetting!.Value = Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Visibility Visibility
|
||||||
|
{
|
||||||
|
get => string.IsNullOrEmpty(Help) ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/MpvNet.Windows/UI/CommandPalette.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
using MpvNet.Windows.WPF.Controls;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
public class CommandPalette
|
||||||
|
{
|
||||||
|
public static CommandPaletteControl Instance { get; } = new CommandPaletteControl();
|
||||||
|
|
||||||
|
public static IEnumerable<CommandPaletteItem> GetItems()
|
||||||
|
{
|
||||||
|
return InputHelp.GetBindingsFromContent(App.InputConf.GetContent())
|
||||||
|
.Where(i => i.Command != "")
|
||||||
|
.Select(i => new CommandPaletteItem()
|
||||||
|
{
|
||||||
|
Text = i.Comment,
|
||||||
|
SecondaryText = i.Input,
|
||||||
|
Action = () => Core.Command(i.Command),
|
||||||
|
Binding = i
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/MpvNet.Windows/UI/CommandPaletteItem.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
namespace MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
public class CommandPaletteItem
|
||||||
|
{
|
||||||
|
public CommandPaletteItem() { }
|
||||||
|
|
||||||
|
public CommandPaletteItem(string text, Action action)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
Action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandPaletteItem(string text, string secondaryText, Action action)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
Action = action;
|
||||||
|
SecondaryText = secondaryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text { get; set; } = "";
|
||||||
|
public string SecondaryText { get; set; } = "";
|
||||||
|
public Action? Action { get; set; }
|
||||||
|
public Binding? Binding { get; set; }
|
||||||
|
}
|
||||||
183
src/MpvNet.Windows/UI/GlobalHotkey.cs
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using MpvNet.ExtensionMethod;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
class GlobalHotkey
|
||||||
|
{
|
||||||
|
public static Dictionary<int, string>? Commands { get; set; }
|
||||||
|
static int ID;
|
||||||
|
static IntPtr HWND;
|
||||||
|
|
||||||
|
public static void RegisterGlobalHotkeys(IntPtr hwnd)
|
||||||
|
{
|
||||||
|
HWND = hwnd;
|
||||||
|
string path = Player.ConfigFolder + "global-input.conf";
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (string i in File.ReadAllLines(path))
|
||||||
|
{
|
||||||
|
string line = i.Trim();
|
||||||
|
|
||||||
|
if (line.StartsWith("#") || !line.Contains(' '))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ProcessGlobalHotkeyLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ProcessGlobalHotkeyLine(string line)
|
||||||
|
{
|
||||||
|
string key = line[..line.IndexOf(" ")];
|
||||||
|
string command = line[(line.IndexOf(" ") + 1)..];
|
||||||
|
string[] parts = key.Split('+');
|
||||||
|
KeyModifiers mod = KeyModifiers.None;
|
||||||
|
int vk;
|
||||||
|
|
||||||
|
for (int i = 0; i < parts.Length - 1; i++)
|
||||||
|
{
|
||||||
|
string umod = parts[i].ToUpper();
|
||||||
|
|
||||||
|
if (umod == "ALT") mod |= KeyModifiers.Alt;
|
||||||
|
if (umod == "CTRL") mod |= KeyModifiers.Ctrl;
|
||||||
|
if (umod == "SHIFT") mod |= KeyModifiers.Shift;
|
||||||
|
if (umod == "WIN") mod |= KeyModifiers.Win;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = parts[^1];
|
||||||
|
|
||||||
|
if (key.Length == 1)
|
||||||
|
{
|
||||||
|
short result = VkKeyScanEx(key[0], GetKeyboardLayout(0));
|
||||||
|
|
||||||
|
int hi = result >> 8;
|
||||||
|
int lo = result & 0xFF;
|
||||||
|
|
||||||
|
vk = lo;
|
||||||
|
|
||||||
|
if ((hi & 1) == 1) mod |= KeyModifiers.Shift;
|
||||||
|
if ((hi & 2) == 2) mod |= KeyModifiers.Ctrl;
|
||||||
|
if ((hi & 4) == 4) mod |= KeyModifiers.Alt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vk = Mpv_to_VK(key);
|
||||||
|
|
||||||
|
Commands ??= new Dictionary<int, string>();
|
||||||
|
|
||||||
|
if (vk > 0)
|
||||||
|
{
|
||||||
|
Commands[ID] = command.Trim();
|
||||||
|
bool success = RegisterHotKey(HWND, ID++, mod, vk);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
Terminal.WriteError(line + ": " + new Win32Exception().Message + "\n", "global-input.conf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Execute(int id)
|
||||||
|
{
|
||||||
|
if (Commands!.ContainsKey(id))
|
||||||
|
Player.Command(Commands[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Mpv_to_VK(string value)
|
||||||
|
{
|
||||||
|
return value.ToUpperEx() switch
|
||||||
|
{
|
||||||
|
"NEXT" => 0xB0,// VK_MEDIA_NEXT_TRACK
|
||||||
|
"PREV" => 0xB1,// VK_MEDIA_PREV_TRACK
|
||||||
|
"STOP" => 0xB2,// VK_MEDIA_STOP
|
||||||
|
"PLAYPAUSE" => 0xB3,// VK_MEDIA_PLAY_PAUSE
|
||||||
|
"SLEEP" => 0x5F,// VK_SLEEP
|
||||||
|
"RIGHT" => 0x27,// VK_RIGHT
|
||||||
|
"UP" => 0x26,// VK_UP
|
||||||
|
"LEFT" => 0x25,// VK_LEFT
|
||||||
|
"DOWN" => 0x28,// VK_DOWN
|
||||||
|
"PGUP" => 0x21,// VK_PRIOR
|
||||||
|
"PGDWN" => 0x22,// VK_NEXT
|
||||||
|
"PAUSE" => 0x13,// VK_PAUSE
|
||||||
|
"PRINT" => 0x2A,// VK_PRINT
|
||||||
|
"HOME" => 0x24,// VK_HOME
|
||||||
|
"INS" => 0x2D,// VK_INSERT
|
||||||
|
"KP_INS" => 0x2D,// VK_INSERT
|
||||||
|
"DEL" => 0x2E,// VK_DELETE
|
||||||
|
"KP_DEL" => 0x2E,// VK_DELETE
|
||||||
|
"END" => 0x23,// VK_END
|
||||||
|
"F1" => 0x70,// VK_F1
|
||||||
|
"F2" => 0x71,// VK_F2
|
||||||
|
"F3" => 0x72,// VK_F3
|
||||||
|
"F4" => 0x73,// VK_F4
|
||||||
|
"F5" => 0x74,// VK_F5
|
||||||
|
"F6" => 0x75,// VK_F6
|
||||||
|
"F7" => 0x76,// VK_F7
|
||||||
|
"F8" => 0x77,// VK_F8
|
||||||
|
"F9" => 0x78,// VK_F9
|
||||||
|
"F10" => 0x79,// VK_F10
|
||||||
|
"F11" => 0x7A,// VK_F11
|
||||||
|
"F12" => 0x7B,// VK_F12
|
||||||
|
"F13" => 0x7C,// VK_F13
|
||||||
|
"F14" => 0x7D,// VK_F14
|
||||||
|
"F15" => 0x7E,// VK_F15
|
||||||
|
"F16" => 0x7F,// VK_F16
|
||||||
|
"F17" => 0x80,// VK_F17
|
||||||
|
"F18" => 0x81,// VK_F18
|
||||||
|
"F19" => 0x82,// VK_F19
|
||||||
|
"F20" => 0x83,// VK_F20
|
||||||
|
"F21" => 0x84,// VK_F21
|
||||||
|
"F22" => 0x85,// VK_F22
|
||||||
|
"F23" => 0x86,// VK_F23
|
||||||
|
"F24" => 0x87,// VK_F24
|
||||||
|
"ENTER" => 0x0D,// VK_RETURN
|
||||||
|
"KP_ENTER" => 0x0D,// VK_RETURN
|
||||||
|
"TAB" => 0x09,// VK_TAB
|
||||||
|
"MENU" => 0x5D,// VK_APPS
|
||||||
|
"CANCEL" => 0x03,// VK_CANCEL
|
||||||
|
"BS" => 0x08,// VK_BACK
|
||||||
|
"KP_DEC" => 0x6E,// VK_DECIMAL
|
||||||
|
"ESC" => 0x1B,// VK_ESCAPE
|
||||||
|
"KP0" => 0x60,// VK_NUMPAD0
|
||||||
|
"KP1" => 0x61,// VK_NUMPAD1
|
||||||
|
"KP2" => 0x62,// VK_NUMPAD2
|
||||||
|
"KP3" => 0x63,// VK_NUMPAD3
|
||||||
|
"KP4" => 0x64,// VK_NUMPAD4
|
||||||
|
"KP5" => 0x65,// VK_NUMPAD5
|
||||||
|
"KP6" => 0x66,// VK_NUMPAD6
|
||||||
|
"KP7" => 0x67,// VK_NUMPAD7
|
||||||
|
"KP8" => 0x68,// VK_NUMPAD8
|
||||||
|
"KP9" => 0x69,// VK_NUMPAD9
|
||||||
|
"FAVORITES" => 0xAB,// VK_BROWSER_FAVORITES
|
||||||
|
"SEARCH" => 0xAA,// VK_BROWSER_SEARCH
|
||||||
|
"MAIL" => 0xB4,// VK_LAUNCH_MAIL
|
||||||
|
"VOLUME_UP" => 0xAF,// VK_VOLUME_UP
|
||||||
|
"VOLUME_DOWN" => 0xAE,// VK_VOLUME_DOWN
|
||||||
|
"MUTE" => 0xAD,// VK_VOLUME_MUTE
|
||||||
|
"SPACE" => 0x20,// VK_SPACE
|
||||||
|
"IDEOGRAPHIC_SPACE" => 0x20,// VK_SPACE
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||||
|
static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
static extern IntPtr GetKeyboardLayout(uint idThread);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, int vk);
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum KeyModifiers
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Alt = 1,
|
||||||
|
Ctrl = 2,
|
||||||
|
Shift = 4,
|
||||||
|
Win = 8
|
||||||
|
}
|
||||||
|
}
|
||||||
155
src/MpvNet.Windows/UI/Theme.cs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
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 Brush? Background { get; set; }
|
||||||
|
public Brush? Foreground { get; set; }
|
||||||
|
public Brush? Foreground2 { get; set; }
|
||||||
|
public Brush? Heading { get; set; }
|
||||||
|
public Brush? MenuBackground { get; set; }
|
||||||
|
public Brush? MenuHighlight { get; set; }
|
||||||
|
|
||||||
|
public Color BackgroundColor { get; set; }
|
||||||
|
public Color ForegroundColor { get; set; }
|
||||||
|
public Color Foreground2Color { get; set; }
|
||||||
|
public Color HeadingColor { get; set; }
|
||||||
|
public Color MenuBackgroundColor { get; set; }
|
||||||
|
public Color MenuHighlightColor { get; set; }
|
||||||
|
|
||||||
|
public Brush GetBrush(string key)
|
||||||
|
{
|
||||||
|
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetColor(string key) => (Color)ColorConverter.ConvertFromString(Dictionary[key]);
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
string? themeContent = null;
|
||||||
|
|
||||||
|
if (File.Exists(Player.ConfigFolder + "theme.conf"))
|
||||||
|
themeContent = File.ReadAllText(Player.ConfigFolder + "theme.conf");
|
||||||
|
|
||||||
|
Init(themeContent, Properties.Resources.theme, DarkMode ? App.DarkTheme : App.LightTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Init(string? customContent, string defaultContent, string activeTheme)
|
||||||
|
{
|
||||||
|
Current = null;
|
||||||
|
|
||||||
|
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;
|
||||||
|
Terminal.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];
|
||||||
|
|
||||||
|
Current.Background = Current.GetBrush("background");
|
||||||
|
Current.Foreground = Current.GetBrush("foreground");
|
||||||
|
Current.Foreground2 = Current.GetBrush("foreground2");
|
||||||
|
Current.Heading = Current.GetBrush("heading");
|
||||||
|
Current.MenuBackground = Current.GetBrush("menu-background");
|
||||||
|
Current.MenuHighlight = Current.GetBrush("menu-highlight");
|
||||||
|
|
||||||
|
Current.BackgroundColor = Current.GetColor("background");
|
||||||
|
Current.ForegroundColor = Current.GetColor("foreground");
|
||||||
|
Current.Foreground2Color = Current.GetColor("foreground2");
|
||||||
|
Current.HeadingColor = Current.GetColor("heading");
|
||||||
|
Current.MenuBackgroundColor = Current.GetColor("menu-background");
|
||||||
|
Current.MenuHighlightColor = Current.GetColor("menu-highlight");
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Theme> Load(string? content)
|
||||||
|
{
|
||||||
|
List<Theme> list = new List<Theme>();
|
||||||
|
Theme? theme = null;
|
||||||
|
|
||||||
|
foreach (string currentLine in (content ?? "").Split('\r', '\n'))
|
||||||
|
{
|
||||||
|
string line = currentLine.Trim();
|
||||||
|
|
||||||
|
if (line.StartsWith("[") && line.EndsWith("]"))
|
||||||
|
list.Add(theme = new Theme() { Name = line[1..^1].Trim() });
|
||||||
|
|
||||||
|
if (line.Contains('=') && theme != null)
|
||||||
|
{
|
||||||
|
string left = line[..line.IndexOf("=")].Trim();
|
||||||
|
theme.Dictionary[left] = line[(line.IndexOf("=") + 1)..].Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateWpfColors()
|
||||||
|
{
|
||||||
|
var dic = Application.Current.Resources;
|
||||||
|
|
||||||
|
dic.Remove("BorderColor");
|
||||||
|
dic.Add("BorderColor", Current!.GetColor("menu-highlight"));
|
||||||
|
|
||||||
|
dic.Remove("RegionColor");
|
||||||
|
dic.Add("RegionColor", Current.GetColor("menu-background"));
|
||||||
|
|
||||||
|
dic.Remove("SecondaryRegionColor");
|
||||||
|
dic.Add("SecondaryRegionColor", Current.GetColor("menu-highlight"));
|
||||||
|
|
||||||
|
dic.Remove("PrimaryTextColor");
|
||||||
|
dic.Add("PrimaryTextColor", Current.GetColor("menu-foreground"));
|
||||||
|
|
||||||
|
dic.Remove("HighlightColor");
|
||||||
|
dic.Add("HighlightColor", Current.GetColor("highlight"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DarkModeSystem
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string key = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
|
||||||
|
return (int)(Registry.GetValue(key, "AppsUseLightTheme", 1) ?? 1) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool DarkMode => App.DarkMode == "system" && DarkModeSystem || App.DarkMode == "always";
|
||||||
|
}
|
||||||
11
src/MpvNet.Windows/UI/TreeNode.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
namespace MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
public class TreeNode
|
||||||
|
{
|
||||||
|
readonly List<TreeNode> _children = new List<TreeNode>();
|
||||||
|
|
||||||
|
public IList<TreeNode> Children => _children;
|
||||||
|
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
}
|
||||||
20
src/MpvNet.Windows/WPF/BindingProxy.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public class BindingProxy : Freezable
|
||||||
|
{
|
||||||
|
protected override Freezable CreateInstanceCore() => new BindingProxy();
|
||||||
|
|
||||||
|
public object Data
|
||||||
|
{
|
||||||
|
get { return GetValue(DataProperty); }
|
||||||
|
set { SetValue(DataProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a DependencyProperty as the backing store for Data.
|
||||||
|
// This enables animation, styling, binding, etc...
|
||||||
|
public static readonly DependencyProperty DataProperty =
|
||||||
|
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
|
||||||
|
}
|
||||||
18
src/MpvNet.Windows/WPF/ComboBoxTemplateSelector.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public class ComboBoxTemplateSelector : DataTemplateSelector
|
||||||
|
{
|
||||||
|
public override DataTemplate SelectTemplate(object item, DependencyObject container)
|
||||||
|
{
|
||||||
|
ContentPresenter presenter = (ContentPresenter)container;
|
||||||
|
|
||||||
|
if (presenter.TemplatedParent is ComboBox)
|
||||||
|
return (DataTemplate)presenter.FindResource("ComboBoxCollapsedDataTemplate");
|
||||||
|
else // Templated parent is ComboBoxItem
|
||||||
|
return (DataTemplate)presenter.FindResource("ComboBoxExpandedDataTemplate");
|
||||||
|
}
|
||||||
|
}
|
||||||
163
src/MpvNet.Windows/WPF/ConfWindow.xaml
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<Window
|
||||||
|
x:Name="ConfWindow1"
|
||||||
|
x:Class="MpvNet.Windows.WPF.ConfWindow"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||||
|
xmlns:controls="clr-namespace:MpvNet.Windows.WPF.Controls"
|
||||||
|
xmlns:wpf="clr-namespace:MpvNet.Windows.WPF"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
|
||||||
|
Title="Config Editor"
|
||||||
|
Height="550"
|
||||||
|
Width="800"
|
||||||
|
Foreground="{Binding Theme.Foreground}"
|
||||||
|
Background="{Binding Theme.Background}"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
WindowStartupLocation="CenterScreen"
|
||||||
|
Loaded="ConfWindow1_Loaded"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Window.Resources>
|
||||||
|
<wpf:BindingProxy x:Key="BindingProxy" Data="{Binding}" />
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
<Window.InputBindings>
|
||||||
|
<KeyBinding Key="n" Modifiers="Ctrl" Command="{Binding ShowMpvNetSpecificSettingsCommand}"/>
|
||||||
|
<KeyBinding Key="F5" Command="{Binding PreviewMpvConfFileCommand}"/>
|
||||||
|
<KeyBinding Key="F6" Command="{Binding PreviewMpvNetConfFileCommand}"/>
|
||||||
|
<KeyBinding Key="F1" Modifiers="Ctrl" Command="{Binding ShowMpvManualCommand}"/>
|
||||||
|
<KeyBinding Key="F2" Modifiers="Ctrl" Command="{Binding ShowMpvNetManualCommand}"/>
|
||||||
|
</Window.InputBindings>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<controls:SearchControl
|
||||||
|
x:Name="SearchControl"
|
||||||
|
HintText="Find a setting (Ctrl+F)"
|
||||||
|
Margin="20,20,0,10"
|
||||||
|
MaxWidth="190"
|
||||||
|
Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ScrollViewer
|
||||||
|
Name="MainScrollViewer"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
Grid.RowSpan="3"
|
||||||
|
Grid.Column="2"
|
||||||
|
Margin="0,0,0,10"
|
||||||
|
>
|
||||||
|
|
||||||
|
<StackPanel x:Name="MainStackPanel"></StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<TreeView
|
||||||
|
x:Name="TreeView"
|
||||||
|
ItemsSource="{Binding Nodes}"
|
||||||
|
Margin="20,0,0,0"
|
||||||
|
Grid.Row="1"
|
||||||
|
BorderThickness="0"
|
||||||
|
Foreground="{Binding Theme.Foreground}"
|
||||||
|
Background="{Binding Theme.Background}"
|
||||||
|
SelectedItemChanged="TreeView_SelectedItemChanged"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TreeView.Resources>
|
||||||
|
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Theme.Background}" />
|
||||||
|
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Theme.Background}" />
|
||||||
|
</TreeView.Resources>
|
||||||
|
|
||||||
|
<TreeView.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type TreeViewItem}">
|
||||||
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
|
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
|
||||||
|
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
|
||||||
|
<Setter Property="FontWeight" Value="Normal" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Theme.Foreground2}" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter Property="FontWeight" Value="Bold" />
|
||||||
|
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Theme.Background2}" />
|
||||||
|
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Theme.Foreground}" />
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TreeView.ItemContainerStyle>
|
||||||
|
|
||||||
|
<TreeView.ItemTemplate>
|
||||||
|
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
|
||||||
|
<TextBlock Text="{Binding Name}" />
|
||||||
|
</HierarchicalDataTemplate>
|
||||||
|
</TreeView.ItemTemplate>
|
||||||
|
</TreeView>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Name="MenuTextBlock"
|
||||||
|
Text="Menu"
|
||||||
|
Cursor="Hand"
|
||||||
|
Foreground="LightGray"
|
||||||
|
TextDecorations="Underline"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Margin="20,5,10,10"
|
||||||
|
Grid.Row="2"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextBlock.ContextMenu>
|
||||||
|
<ContextMenu Name="MainContextMenu">
|
||||||
|
<MenuItem
|
||||||
|
Header="Show mpv.net options"
|
||||||
|
InputGestureText="Ctrl+n"
|
||||||
|
Command="{Binding Data.ShowMpvNetSpecificSettingsCommand, Source={StaticResource BindingProxy}}"
|
||||||
|
/>
|
||||||
|
<Separator />
|
||||||
|
<MenuItem
|
||||||
|
Header="Preview mpv.conf"
|
||||||
|
InputGestureText="F5"
|
||||||
|
Command="{Binding Data.PreviewMpvConfFileCommand, Source={StaticResource BindingProxy}}"
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
Header="Preview mpvnet.conf"
|
||||||
|
InputGestureText="F6"
|
||||||
|
Command="{Binding Data.PreviewMpvNetConfFileCommand, Source={StaticResource BindingProxy}}"
|
||||||
|
/>
|
||||||
|
<Separator />
|
||||||
|
<MenuItem
|
||||||
|
Header="Show mpv manual"
|
||||||
|
InputGestureText="Ctrl+F1"
|
||||||
|
Command="{Binding Data.ShowMpvManualCommand, Source={StaticResource BindingProxy}}"
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
Header="Show mpv.net manual"
|
||||||
|
InputGestureText="Ctrl+F2"
|
||||||
|
Command="{Binding Data.ShowMpvNetManualCommand, Source={StaticResource BindingProxy}}"
|
||||||
|
/>
|
||||||
|
</ContextMenu>
|
||||||
|
</TextBlock.ContextMenu>
|
||||||
|
|
||||||
|
<b:Interaction.Triggers>
|
||||||
|
<b:EventTrigger EventName="MouseLeftButtonDown">
|
||||||
|
<b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=MenuTextBlock}"
|
||||||
|
PropertyName="PlacementTarget"
|
||||||
|
Value="{Binding ElementName=MenuTextBlock, Mode=OneWay}"/>
|
||||||
|
<b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=MenuTextBlock}"
|
||||||
|
PropertyName="IsOpen"
|
||||||
|
Value="True"/>
|
||||||
|
</b:EventTrigger>
|
||||||
|
</b:Interaction.Triggers>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
550
src/MpvNet.Windows/WPF/ConfWindow.xaml.cs
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
|
using MpvNet.Help;
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
using MpvNet.Windows.WPF.Controls;
|
||||||
|
using MpvNet.Windows.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public partial class ConfWindow : Window, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
List<Setting> _settings = Conf.LoadConf(Properties.Resources.editor_conf.TrimEnd());
|
||||||
|
List<ConfItem> _confItems = new List<ConfItem>();
|
||||||
|
string _initialContent;
|
||||||
|
string _themeConf = GetThemeConf();
|
||||||
|
string? _searchText;
|
||||||
|
List<NodeViewModel>? _nodes;
|
||||||
|
bool _shown;
|
||||||
|
int _useSpace;
|
||||||
|
int _useNoSpace;
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
public ConfWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
LoadConf(Player.ConfPath);
|
||||||
|
LoadConf(App.ConfPath);
|
||||||
|
LoadLibplaceboConf();
|
||||||
|
LoadSettings();
|
||||||
|
_initialContent = GetCompareString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(App.Settings.ConfigEditorSearch))
|
||||||
|
SearchText = "General:";
|
||||||
|
else
|
||||||
|
SearchText = App.Settings.ConfigEditorSearch;
|
||||||
|
|
||||||
|
foreach (var node in Nodes)
|
||||||
|
SelectNodeFromSearchText(node);
|
||||||
|
|
||||||
|
foreach (var node in Nodes)
|
||||||
|
node.IsExpanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<string> FilterStrings { get; } = new();
|
||||||
|
|
||||||
|
public Theme? Theme => Theme.Current;
|
||||||
|
|
||||||
|
public string SearchText
|
||||||
|
{
|
||||||
|
get => _searchText ?? "";
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_searchText = value;
|
||||||
|
SearchTextChanged();
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NodeViewModel> Nodes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_nodes == null)
|
||||||
|
{
|
||||||
|
var rootNode = new TreeNode();
|
||||||
|
|
||||||
|
foreach (Setting setting in _settings)
|
||||||
|
AddNode(rootNode.Children, setting.Directory!);
|
||||||
|
|
||||||
|
_nodes = new NodeViewModel(rootNode).Children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TreeNode? AddNode(IList<TreeNode> nodes, string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string[] parts = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
for (int x = 0; x < parts.Length; x++)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
foreach (var node in nodes)
|
||||||
|
{
|
||||||
|
if (x < parts.Length - 1)
|
||||||
|
{
|
||||||
|
if (node.Name == parts[x])
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
nodes = node.Children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (x == parts.Length - 1 && node.Name == parts[x])
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
if (x == parts.Length - 1)
|
||||||
|
{
|
||||||
|
var item = new TreeNode() { Name = parts[x] };
|
||||||
|
nodes?.Add(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadSettings()
|
||||||
|
{
|
||||||
|
foreach (Setting setting in _settings)
|
||||||
|
{
|
||||||
|
setting.StartValue = setting.Value;
|
||||||
|
|
||||||
|
if (!FilterStrings.Contains(setting.Directory!))
|
||||||
|
FilterStrings.Add(setting.Directory!);
|
||||||
|
|
||||||
|
foreach (ConfItem item in _confItems)
|
||||||
|
{
|
||||||
|
if (setting.Name == item.Name &&
|
||||||
|
setting.File == item.File &&
|
||||||
|
item.Section == "" && !item.IsSectionItem)
|
||||||
|
{
|
||||||
|
setting.Value = item.Value;
|
||||||
|
setting.StartValue = setting.Value;
|
||||||
|
setting.ConfItem = item;
|
||||||
|
item.SettingBase = setting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (setting)
|
||||||
|
{
|
||||||
|
case StringSetting s:
|
||||||
|
MainStackPanel.Children.Add(new StringSettingControl(s) { Visibility = Visibility.Collapsed });
|
||||||
|
break;
|
||||||
|
case OptionSetting s:
|
||||||
|
if (s.Options.Count > 3)
|
||||||
|
MainStackPanel.Children.Add(new ComboBoxSettingControl(s) { Visibility = Visibility.Collapsed });
|
||||||
|
else
|
||||||
|
MainStackPanel.Children.Add(new OptionSettingControl(s) { Visibility = Visibility.Collapsed });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetThemeConf() => Theme.DarkMode + App.DarkTheme + App.LightTheme;
|
||||||
|
|
||||||
|
string GetCompareString() => string.Join("", _settings.Select(item => item.Name + item.Value).ToArray());
|
||||||
|
|
||||||
|
void LoadConf(string file)
|
||||||
|
{
|
||||||
|
if (!File.Exists(file))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string comment = "";
|
||||||
|
string section = "";
|
||||||
|
|
||||||
|
bool isSectionItem = false;
|
||||||
|
|
||||||
|
foreach (string it in File.ReadAllLines(file))
|
||||||
|
{
|
||||||
|
string line = it.Trim();
|
||||||
|
|
||||||
|
if (line.StartsWith("-"))
|
||||||
|
line = line.TrimStart('-');
|
||||||
|
|
||||||
|
if (line == "")
|
||||||
|
comment += "\r\n";
|
||||||
|
else if (line.StartsWith("#"))
|
||||||
|
comment += line.Trim() + "\r\n";
|
||||||
|
else if (line.StartsWith("[") && line.Contains(']'))
|
||||||
|
{
|
||||||
|
if (!isSectionItem && comment != "" && comment != "\r\n")
|
||||||
|
_confItems.Add(new ConfItem() {
|
||||||
|
Comment = comment, File = Path.GetFileNameWithoutExtension(file)});
|
||||||
|
|
||||||
|
section = line.Substring(0, line.IndexOf("]") + 1);
|
||||||
|
comment = "";
|
||||||
|
isSectionItem = true;
|
||||||
|
}
|
||||||
|
else if (line.Contains('=') || Regex.Match(line, "^[\\w-]+$").Success)
|
||||||
|
{
|
||||||
|
if (!line.Contains('='))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("no-"))
|
||||||
|
{
|
||||||
|
line = line.Substring(3);
|
||||||
|
line += "=no";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
line += "=yes";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.Contains(" =") || line.Contains("= "))
|
||||||
|
_useSpace += 1;
|
||||||
|
else
|
||||||
|
_useNoSpace += 1;
|
||||||
|
|
||||||
|
ConfItem item = new();
|
||||||
|
item.File = Path.GetFileNameWithoutExtension(file);
|
||||||
|
item.IsSectionItem = isSectionItem;
|
||||||
|
item.Comment = comment;
|
||||||
|
comment = "";
|
||||||
|
item.Section = section;
|
||||||
|
section = "";
|
||||||
|
|
||||||
|
if (line.Contains('#') && !line.Contains('\'') && !line.Contains('"'))
|
||||||
|
{
|
||||||
|
item.LineComment = line.Substring(line.IndexOf("#")).Trim();
|
||||||
|
line = line.Substring(0, line.IndexOf("#")).Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = line.IndexOf("=");
|
||||||
|
string left = line.Substring(0, pos).Trim().ToLower().TrimStart('-');
|
||||||
|
string right = line.Substring(pos + 1).Trim();
|
||||||
|
|
||||||
|
if (right.StartsWith('\'') && right.EndsWith('\''))
|
||||||
|
right = right.Trim('\'');
|
||||||
|
|
||||||
|
if (right.StartsWith('"') && right.EndsWith('"'))
|
||||||
|
right = right.Trim('"');
|
||||||
|
|
||||||
|
if (left == "fs")
|
||||||
|
left = "fullscreen";
|
||||||
|
|
||||||
|
if (left == "loop")
|
||||||
|
left = "loop-file";
|
||||||
|
|
||||||
|
item.Name = left;
|
||||||
|
item.Value = right;
|
||||||
|
_confItems.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetKeyValueContent(string filename)
|
||||||
|
{
|
||||||
|
List<string> pairs = new();
|
||||||
|
|
||||||
|
foreach (Setting setting in _settings)
|
||||||
|
{
|
||||||
|
if (filename != setting.File)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((setting.Value ?? "") != setting.Default)
|
||||||
|
pairs.Add(setting.Name + "=" + EscapeValue(setting.Value!));
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(',', pairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadLibplaceboConf()
|
||||||
|
{
|
||||||
|
foreach (ConfItem item in _confItems.ToArray())
|
||||||
|
if (item.Name == "libplacebo-opts")
|
||||||
|
LoadKeyValueList(item.Value, "libplacebo");
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadKeyValueList(string options, string file)
|
||||||
|
{
|
||||||
|
string[] optionStrings = options.Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
foreach (string pair in optionStrings)
|
||||||
|
{
|
||||||
|
if (!pair.Contains('='))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int pos = pair.IndexOf("=");
|
||||||
|
string left = pair.Substring(0, pos).Trim().ToLower();
|
||||||
|
string right = pair.Substring(pos + 1).Trim();
|
||||||
|
|
||||||
|
ConfItem item = new();
|
||||||
|
item.Name = left;
|
||||||
|
item.Value = right;
|
||||||
|
item.File = file;
|
||||||
|
_confItems.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string EscapeValue(string value)
|
||||||
|
{
|
||||||
|
if (value.Contains('\''))
|
||||||
|
return '"' + value + '"';
|
||||||
|
|
||||||
|
if (value.Contains('"'))
|
||||||
|
return '\'' + value + '\'';
|
||||||
|
|
||||||
|
if (value.Contains('"') || value.Contains('#') || value.StartsWith("%") ||
|
||||||
|
value.StartsWith(" ") || value.EndsWith(" "))
|
||||||
|
{
|
||||||
|
return '\'' + value + '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetContent(string filename)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
List<string> namesWritten = new List<string>();
|
||||||
|
string equalString = _useSpace > _useNoSpace ? " = " : "=";
|
||||||
|
|
||||||
|
foreach (ConfItem item in _confItems)
|
||||||
|
{
|
||||||
|
if (filename != item.File || item.Section != "" || item.IsSectionItem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (item.Comment != "")
|
||||||
|
sb.Append(item.Comment);
|
||||||
|
|
||||||
|
if (item.SettingBase == null)
|
||||||
|
{
|
||||||
|
if (item.Name != "")
|
||||||
|
{
|
||||||
|
sb.Append(item.Name + equalString + EscapeValue(item.Value));
|
||||||
|
|
||||||
|
if (item.LineComment != "")
|
||||||
|
sb.Append(" " + item.LineComment);
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
namesWritten.Add(item.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((item.SettingBase.Value ?? "") != item.SettingBase.Default)
|
||||||
|
{
|
||||||
|
sb.Append(item.Name + equalString + EscapeValue(item.SettingBase.Value!));
|
||||||
|
|
||||||
|
if (item.LineComment != "")
|
||||||
|
sb.Append(" " + item.LineComment);
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
namesWritten.Add(item.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Setting setting in _settings)
|
||||||
|
{
|
||||||
|
if (filename != setting.File || namesWritten.Contains(setting.Name!))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((setting.Value ?? "") != setting.Default)
|
||||||
|
sb.AppendLine(setting.Name + equalString + EscapeValue(setting.Value!));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ConfItem item in _confItems)
|
||||||
|
{
|
||||||
|
if (filename != item.File || (item.Section == "" && !item.IsSectionItem))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (item.Section != "")
|
||||||
|
{
|
||||||
|
if (!sb.ToString().EndsWith("\r\n\r\n"))
|
||||||
|
sb.AppendLine();
|
||||||
|
|
||||||
|
sb.AppendLine(item.Section);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Comment != "")
|
||||||
|
sb.Append(item.Comment);
|
||||||
|
|
||||||
|
sb.Append(item.Name + equalString + EscapeValue(item.Value));
|
||||||
|
|
||||||
|
if (item.LineComment != "")
|
||||||
|
sb.Append(" " + item.LineComment);
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
namesWritten.Add(item.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "\r\n" + sb.ToString().Trim() + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchTextChanged()
|
||||||
|
{
|
||||||
|
string activeFilter = "";
|
||||||
|
|
||||||
|
foreach (string i in FilterStrings)
|
||||||
|
if (SearchText == i + ":")
|
||||||
|
activeFilter = i;
|
||||||
|
|
||||||
|
if (activeFilter == "")
|
||||||
|
{
|
||||||
|
foreach (UIElement i in MainStackPanel.Children)
|
||||||
|
if ((i as ISettingControl)!.Contains(SearchText) && SearchText.Length > 1)
|
||||||
|
i.Visibility = Visibility.Visible;
|
||||||
|
else
|
||||||
|
i.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
foreach (var node in Nodes)
|
||||||
|
UnselectNode(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
foreach (UIElement i in MainStackPanel.Children)
|
||||||
|
if ((i as ISettingControl)!.Setting.Directory == activeFilter)
|
||||||
|
i.Visibility = Visibility.Visible;
|
||||||
|
else
|
||||||
|
i.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
MainScrollViewer.ScrollToTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfWindow1_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SearchControl.SearchTextBox.SelectAll();
|
||||||
|
Keyboard.Focus(SearchControl.SearchTextBox);
|
||||||
|
|
||||||
|
foreach (var i in MainStackPanel.Children.OfType<StringSettingControl>())
|
||||||
|
i.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClosed(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnClosed(e);
|
||||||
|
App.Settings.ConfigEditorSearch = SearchText;
|
||||||
|
|
||||||
|
if (_initialContent == GetCompareString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (Setting setting in _settings)
|
||||||
|
{
|
||||||
|
if (setting.Name == "libplacebo-opts")
|
||||||
|
{
|
||||||
|
setting.Value = GetKeyValueContent("libplacebo");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(Player.ConfPath, GetContent("mpv"));
|
||||||
|
File.WriteAllText(App.ConfPath, GetContent("mpvnet"));
|
||||||
|
|
||||||
|
foreach (Setting it in _settings)
|
||||||
|
{
|
||||||
|
if (it.Value != it.StartValue)
|
||||||
|
{
|
||||||
|
if (it.File == "mpv")
|
||||||
|
{
|
||||||
|
Player.ProcessProperty(it.Name, it.Value);
|
||||||
|
Player.SetPropertyString(it.Name!, it.Value!);
|
||||||
|
}
|
||||||
|
else if (it.File == "mpvnet")
|
||||||
|
App.ProcessProperty(it.Name ?? "", it.Value ?? "", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Theme.Init();
|
||||||
|
Theme.UpdateWpfColors();
|
||||||
|
|
||||||
|
if (_themeConf != GetThemeConf())
|
||||||
|
MessageBox.Show("Changed theme settings require mpv.net being restarted.", "Info");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnKeyDown(e);
|
||||||
|
|
||||||
|
if (e.Key == Key.Escape)
|
||||||
|
Close();
|
||||||
|
|
||||||
|
if (e.Key == Key.F3 || e.Key == Key.F6 || (e.Key == Key.F && Keyboard.Modifiers == ModifierKeys.Control))
|
||||||
|
{
|
||||||
|
Keyboard.Focus(SearchControl.SearchTextBox);
|
||||||
|
SearchControl.SearchTextBox.SelectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnPropertyChanged([CallerMemberName] string? name = null) =>
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||||
|
|
||||||
|
protected override void OnContentRendered(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnContentRendered(e);
|
||||||
|
|
||||||
|
if (_shown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_shown = true;
|
||||||
|
|
||||||
|
Application.Current.Dispatcher.BeginInvoke(() => {
|
||||||
|
SearchControl.SearchTextBox.SelectAll();
|
||||||
|
},
|
||||||
|
DispatcherPriority.Background);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||||
|
{
|
||||||
|
var node = TreeView.SelectedItem as NodeViewModel;
|
||||||
|
|
||||||
|
if (node == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Application.Current.Dispatcher.BeginInvoke(() => {
|
||||||
|
SearchText = node!.Path + ":";
|
||||||
|
},
|
||||||
|
DispatcherPriority.Background);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectNodeFromSearchText(NodeViewModel node)
|
||||||
|
{
|
||||||
|
if (node.Path + ":" == SearchText)
|
||||||
|
{
|
||||||
|
node.IsSelected = true;
|
||||||
|
node.IsExpanded = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var it in node.Children)
|
||||||
|
SelectNodeFromSearchText(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnselectNode(NodeViewModel node)
|
||||||
|
{
|
||||||
|
if (node.IsSelected)
|
||||||
|
node.IsSelected = false;
|
||||||
|
|
||||||
|
foreach (var it in node.Children)
|
||||||
|
UnselectNode(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand] void ShowMpvNetSpecificSettings() => SearchText = "mpv.net";
|
||||||
|
|
||||||
|
[RelayCommand] void PreviewMpvConfFile() => Msg.ShowInfo(GetContent("mpv"));
|
||||||
|
|
||||||
|
[RelayCommand] void PreviewMpvNetConfFile() => Msg.ShowInfo(GetContent("mpvnet"));
|
||||||
|
|
||||||
|
[RelayCommand] void ShowMpvManual() => ProcessHelp.ShellExecute("https://mpv.io/manual/master/");
|
||||||
|
|
||||||
|
[RelayCommand] void ShowMpvNetManual() => ProcessHelp.ShellExecute("https://github.com/mpvnet-player/mpv.net/blob/main/docs/manual.md");
|
||||||
|
}
|
||||||
72
src/MpvNet.Windows/WPF/Controls/ComboBoxSettingControl.xaml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Name="ComboBoxSettingControl1"
|
||||||
|
x:Class="MpvNet.Windows.WPF.ComboBoxSettingControl"
|
||||||
|
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:MpvNet.Windows.WPF"
|
||||||
|
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="{Binding Theme.Heading}"
|
||||||
|
Background="{Binding Theme.Background}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ComboBox
|
||||||
|
Name="ComboBoxControl"
|
||||||
|
Width="200"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
MaxDropDownHeight="2000"
|
||||||
|
Foreground="{Binding Theme.Foreground}"
|
||||||
|
Background="{Binding Theme.Background}"
|
||||||
|
|
||||||
|
SelectionChanged="ComboBoxControl_SelectionChanged"
|
||||||
|
>
|
||||||
|
<ComboBox.ItemTemplateSelector>
|
||||||
|
<local:ComboBoxTemplateSelector/>
|
||||||
|
</ComboBox.ItemTemplateSelector>
|
||||||
|
|
||||||
|
<ComboBox.ItemContainerStyle>
|
||||||
|
<Style TargetType="ComboBoxItem">
|
||||||
|
<Style.Resources>
|
||||||
|
<Style TargetType="Border">
|
||||||
|
<Setter Property="CornerRadius" Value="3"/>
|
||||||
|
</Style>
|
||||||
|
</Style.Resources>
|
||||||
|
</Style>
|
||||||
|
</ComboBox.ItemContainerStyle>
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
x:Name="HelpTextBox"
|
||||||
|
TextWrapping="WrapWithOverflow"
|
||||||
|
BorderThickness="0"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Margin="0,10,0,0"
|
||||||
|
Foreground="{Binding Theme.Foreground}"
|
||||||
|
Background="{Binding Theme.Background}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
x:Name="LinkTextBlock"
|
||||||
|
Margin="2,0"
|
||||||
|
>
|
||||||
|
<local:HyperlinkEx
|
||||||
|
x:Name="Link"
|
||||||
|
Foreground="{Binding Theme.Heading}"
|
||||||
|
/>
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public partial class ComboBoxSettingControl : UserControl, ISettingControl
|
||||||
|
{
|
||||||
|
OptionSetting OptionSetting;
|
||||||
|
|
||||||
|
public ComboBoxSettingControl(OptionSetting optionSetting)
|
||||||
|
{
|
||||||
|
OptionSetting = optionSetting;
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
TitleTextBox.Text = optionSetting.Name;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(optionSetting.Help))
|
||||||
|
HelpTextBox.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
HelpTextBox.Text = optionSetting.Help;
|
||||||
|
ComboBoxControl.ItemsSource = optionSetting.Options;
|
||||||
|
|
||||||
|
foreach (var item in optionSetting.Options)
|
||||||
|
if (item.Name == optionSetting.Value)
|
||||||
|
ComboBoxControl.SelectedItem = item;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(optionSetting.URL))
|
||||||
|
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
Link.SetURL(optionSetting.URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme? Theme => Theme.Current;
|
||||||
|
|
||||||
|
public Setting Setting => OptionSetting;
|
||||||
|
|
||||||
|
public bool Contains(string searchString) => ContainsInternal(searchString.ToLower());
|
||||||
|
|
||||||
|
public bool ContainsInternal(string search)
|
||||||
|
{
|
||||||
|
if (TitleTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (HelpTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (var i in OptionSetting.Options)
|
||||||
|
{
|
||||||
|
if (i.Text?.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (i.Help?.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (i.Name?.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComboBoxControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
OptionSetting.Value = (ComboBoxControl.SelectedItem as OptionSettingOption)?.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
x:Class="mpvnet.CommandPaletteControl"
|
x:Class="MpvNet.Windows.WPF.Controls.CommandPaletteControl"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:mpvnet"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:controls="clr-namespace:MpvNet.Windows.WPF.Controls"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
|
|
||||||
FontSize="13"
|
FontSize="13"
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Margin="7"
|
Margin="7"
|
||||||
>
|
>
|
||||||
|
|
||||||
<local:SearchTextBoxUserControl
|
<controls:SearchControl
|
||||||
HintText="Search"
|
HintText="Search"
|
||||||
x:Name="SearchControl"
|
x:Name="SearchControl"
|
||||||
Grid.ColumnSpan="2"
|
Grid.ColumnSpan="2"
|
||||||
@@ -46,15 +46,16 @@
|
|||||||
/>
|
/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<ListView Name="MainListView"
|
<ListView
|
||||||
Grid.Row="1"
|
Name="MainListView"
|
||||||
Foreground="{Binding Theme.Foreground}"
|
Grid.Row="1"
|
||||||
Background="{Binding Theme.Background}"
|
Foreground="{Binding Theme.Foreground}"
|
||||||
BorderThickness="0"
|
Background="{Binding Theme.Background}"
|
||||||
MaxHeight="202"
|
BorderThickness="0"
|
||||||
SizeChanged="MainListView_SizeChanged"
|
MaxHeight="202"
|
||||||
MouseUp="MainListView_MouseUp"
|
SizeChanged="MainListView_SizeChanged"
|
||||||
>
|
MouseUp="MainListView_MouseUp"
|
||||||
|
>
|
||||||
|
|
||||||
<ListView.ItemContainerStyle>
|
<ListView.ItemContainerStyle>
|
||||||
<Style TargetType="ListBoxItem">
|
<Style TargetType="ListBoxItem">
|
||||||
150
src/MpvNet.Windows/WPF/Controls/CommandPaletteControl.xaml.cs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
using MpvNet.Windows.WinForms;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF.Controls;
|
||||||
|
|
||||||
|
public partial class CommandPaletteControl : UserControl
|
||||||
|
{
|
||||||
|
public ICollectionView CollectionView { get; set; }
|
||||||
|
public CollectionViewSource CollectionViewSource { get; }
|
||||||
|
public ObservableCollection<CommandPaletteItem> Items { get; } = new ObservableCollection<CommandPaletteItem>();
|
||||||
|
|
||||||
|
public CommandPaletteControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
CollectionViewSource = new CollectionViewSource() { Source = Items };
|
||||||
|
CollectionView = CollectionViewSource.View;
|
||||||
|
CollectionView.Filter = new Predicate<object>(item => Filter((CommandPaletteItem)item));
|
||||||
|
MainListView.ItemsSource = CollectionView;
|
||||||
|
|
||||||
|
SearchControl.SearchTextBox.PreviewKeyDown += SearchTextBox_PreviewKeyDown;
|
||||||
|
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
||||||
|
SearchControl.HideClearButton = true;
|
||||||
|
|
||||||
|
if (Environment.OSVersion.Version < new Version(10, 0))
|
||||||
|
MainBorder.CornerRadius = new CornerRadius(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
CollectionView.Refresh();
|
||||||
|
SelectFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.Key)
|
||||||
|
{
|
||||||
|
case Key.Up:
|
||||||
|
{
|
||||||
|
int index = MainListView.SelectedIndex;
|
||||||
|
index -= 1;
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
MainListView.SelectedIndex = index;
|
||||||
|
MainListView.ScrollIntoView(MainListView.SelectedItem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Key.Down:
|
||||||
|
{
|
||||||
|
int index = MainListView.SelectedIndex;
|
||||||
|
|
||||||
|
if (++index > MainListView.Items.Count - 1)
|
||||||
|
index = MainListView.Items.Count - 1;
|
||||||
|
|
||||||
|
MainListView.SelectedIndex = index;
|
||||||
|
MainListView.ScrollIntoView(MainListView.SelectedItem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainListView_SizeChanged(object sender, SizeChangedEventArgs e) => AdjustHeight();
|
||||||
|
|
||||||
|
void MainListView_MouseUp(object sender, MouseButtonEventArgs e) => ExecuteInternal();
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
void Escape(object param) => MainForm.Instance?.HideCommandPalette();
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
void Execute() => ExecuteInternal();
|
||||||
|
|
||||||
|
void OnLoaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox);
|
||||||
|
|
||||||
|
public Theme Theme => Theme.Current!;
|
||||||
|
|
||||||
|
bool Filter(CommandPaletteItem item)
|
||||||
|
{
|
||||||
|
string filter = SearchControl.SearchTextBox.Text.ToLower();
|
||||||
|
|
||||||
|
if (item.Binding != null)
|
||||||
|
{
|
||||||
|
//if (item.CommandItem.Alias.ContainsEx(filter))
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
if (filter.Length == 1)
|
||||||
|
return item.Binding.Input.ToLower()
|
||||||
|
.Replace("ctrl+", "")
|
||||||
|
.Replace("shift+", "")
|
||||||
|
.Replace("alt+", "") == filter.ToLower();
|
||||||
|
|
||||||
|
if (item.Binding.Command.ToLower().Contains(filter))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter == "" || item.Text.ToLower().Contains(filter) ||
|
||||||
|
item.SecondaryText.ToLower().Contains(filter))
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectFirst()
|
||||||
|
{
|
||||||
|
if (MainListView.Items.Count > 0)
|
||||||
|
{
|
||||||
|
MainListView.SelectedIndex = 0;
|
||||||
|
MainListView.ScrollIntoView(MainListView.SelectedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecuteInternal()
|
||||||
|
{
|
||||||
|
if (MainListView.SelectedItem != null)
|
||||||
|
{
|
||||||
|
CommandPaletteItem? item = MainListView.SelectedItem as CommandPaletteItem;
|
||||||
|
MainForm.Instance?.HideCommandPalette();
|
||||||
|
item?.Action?.Invoke();
|
||||||
|
//MainForm.Instance.Voodoo(); //TODO: Voodoo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetItems(IEnumerable<CommandPaletteItem> items)
|
||||||
|
{
|
||||||
|
Items.Clear();
|
||||||
|
|
||||||
|
foreach (var i in items)
|
||||||
|
Items.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AdjustHeight()
|
||||||
|
{
|
||||||
|
double actualHeight = SearchControl.ActualHeight + MainListView.ActualHeight + 5 + 16;
|
||||||
|
int dpi = MainForm.GetDpi(MainForm.Instance!.Handle);
|
||||||
|
MainForm.Instance.CommandPaletteHost.Height = (int)(actualHeight / 96.0 * dpi);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/MpvNet.Windows/WPF/Controls/HyperlinkEx.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
|
||||||
|
using MpvNet.Help;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public class HyperlinkEx : Hyperlink
|
||||||
|
{
|
||||||
|
void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e) =>
|
||||||
|
ProcessHelp.ShellExecute(e.Uri.AbsoluteUri);
|
||||||
|
|
||||||
|
public void SetURL(string? url)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(url))
|
||||||
|
return;
|
||||||
|
|
||||||
|
NavigateUri = new Uri(url);
|
||||||
|
RequestNavigate += HyperLinkEx_RequestNavigate;
|
||||||
|
Inlines.Clear();
|
||||||
|
Inlines.Add("Manual");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
x:Name="OptionSettingControl1" x:Class="DynamicGUI.OptionSettingControl"
|
x:Name="OptionSettingControl1"
|
||||||
|
x:Class="MpvNet.Windows.WPF.OptionSettingControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:mpvnet"
|
xmlns:local="clr-namespace:MpvNet.Windows.WPF"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
|
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
@@ -64,9 +65,15 @@
|
|||||||
Foreground="{Binding Theme.Foreground}"
|
Foreground="{Binding Theme.Foreground}"
|
||||||
Background="{Binding Theme.Background}"
|
Background="{Binding Theme.Background}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
<TextBlock
|
||||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
x:Name="LinkTextBlock"
|
||||||
|
Margin="2,0,0,0"
|
||||||
|
>
|
||||||
|
<local:HyperlinkEx
|
||||||
|
x:Name="Link"
|
||||||
|
Foreground="{Binding Theme.Heading}"
|
||||||
|
/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
64
src/MpvNet.Windows/WPF/Controls/OptionSettingControl.xaml.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public partial class OptionSettingControl : UserControl, ISettingControl
|
||||||
|
{
|
||||||
|
OptionSetting OptionSetting;
|
||||||
|
|
||||||
|
public OptionSettingControl(OptionSetting optionSetting)
|
||||||
|
{
|
||||||
|
OptionSetting = optionSetting;
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
TitleTextBox.Text = optionSetting.Name;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(optionSetting.Help))
|
||||||
|
HelpTextBox.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
HelpTextBox.Text = optionSetting.Help;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(optionSetting.Help))
|
||||||
|
LinkTextBlock.Margin = new Thickness(2, 6, 0, 0);
|
||||||
|
|
||||||
|
ItemsControl.ItemsSource = optionSetting.Options;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(optionSetting.URL))
|
||||||
|
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
Link.SetURL(optionSetting.URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme? Theme => Theme.Current;
|
||||||
|
|
||||||
|
public Setting Setting => OptionSetting;
|
||||||
|
|
||||||
|
public bool Contains(string searchString) => ContainsInternal(searchString.ToLower());
|
||||||
|
|
||||||
|
public bool ContainsInternal(string search)
|
||||||
|
{
|
||||||
|
if (TitleTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (HelpTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (var i in OptionSetting.Options)
|
||||||
|
{
|
||||||
|
if (i.Text?.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (i.Help?.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (i.Name?.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,20 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
x:Class="mpvnet.SearchTextBoxUserControl"
|
x:Class="MpvNet.Windows.WPF.Controls.SearchControl"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:controls="clr-namespace:MpvNet.Windows.WPF.Controls"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
>
|
>
|
||||||
|
|
||||||
<Grid
|
<Grid Background="{Binding Theme.Background}">
|
||||||
Name="SearchTextBoxUserControl1"
|
|
||||||
Background="{Binding Theme.Background}"
|
|
||||||
>
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Name="HintTextBlock"
|
Name="HintTextBlock"
|
||||||
Padding="6,1"
|
Padding="6,1"
|
||||||
Text="Find a setting"
|
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Foreground="{Binding Theme.Foreground2}"
|
Foreground="{Binding Theme.Foreground2}"
|
||||||
Background="{Binding Theme.Background}"
|
Background="{Binding Theme.Background}"
|
||||||
@@ -27,11 +24,16 @@
|
|||||||
Name="SearchTextBox"
|
Name="SearchTextBox"
|
||||||
Height="25"
|
Height="25"
|
||||||
BorderThickness="2"
|
BorderThickness="2"
|
||||||
Padding="2"
|
Padding="2,2,20,2"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
TextChanged="SearchTextBox_TextChanged"
|
|
||||||
Foreground="{Binding Theme.Foreground}"
|
Foreground="{Binding Theme.Foreground}"
|
||||||
CaretBrush="{Binding Theme.Foreground}"
|
CaretBrush="{Binding Theme.Foreground}"
|
||||||
|
GotFocus="SearchTextBox_GotFocus"
|
||||||
|
PreviewMouseUp="SearchTextBox_PreviewMouseUp"
|
||||||
|
PreviewKeyDown="SearchTextBox_PreviewKeyDown"
|
||||||
|
Text="{Binding RelativeSource={RelativeSource FindAncestor,
|
||||||
|
AncestorType={x:Type controls:SearchControl}},
|
||||||
|
Path=Text, UpdateSourceTrigger=PropertyChanged}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -44,7 +46,8 @@
|
|||||||
Height="17"
|
Height="17"
|
||||||
Margin="2,0,4,0"
|
Margin="2,0,4,0"
|
||||||
Visibility="Hidden"
|
Visibility="Hidden"
|
||||||
Click="SearchClearButton_Click"
|
Command="{Binding RelativeSource={RelativeSource FindAncestor,
|
||||||
|
AncestorType={x:Type controls:SearchControl}}, Path=ClearCommand}"
|
||||||
>r
|
>r
|
||||||
|
|
||||||
<Button.Resources>
|
<Button.Resources>
|
||||||
87
src/MpvNet.Windows/WPF/Controls/SearchControl.xaml.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF.Controls;
|
||||||
|
|
||||||
|
public partial class SearchControl : UserControl
|
||||||
|
{
|
||||||
|
string? _hintText;
|
||||||
|
bool _gotFocus;
|
||||||
|
|
||||||
|
public bool HideClearButton { get; set; }
|
||||||
|
|
||||||
|
public SearchControl() => InitializeComponent();
|
||||||
|
|
||||||
|
public Theme? Theme => Theme.Current;
|
||||||
|
|
||||||
|
public string HintText {
|
||||||
|
get => _hintText ??= "";
|
||||||
|
set {
|
||||||
|
_hintText = value;
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
Text = "";
|
||||||
|
Keyboard.Focus(SearchTextBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateControls()
|
||||||
|
{
|
||||||
|
HintTextBlock.Text = string.IsNullOrEmpty(Text) ? HintText : "";
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(Text) || HideClearButton || Text.Length > 30)
|
||||||
|
{
|
||||||
|
SearchTextBox.Padding = new Thickness(2);
|
||||||
|
SearchClearButton.Visibility = Visibility.Hidden;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SearchTextBox.Padding = new Thickness(2, 2, 20, 2);
|
||||||
|
SearchClearButton.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get => (string)GetValue(TextProperty);
|
||||||
|
set => SetValue(TextProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TextProperty =
|
||||||
|
DependencyProperty.Register("Text", typeof(string),
|
||||||
|
typeof(SearchControl), new PropertyMetadata(OnCustomerChangedCallBack));
|
||||||
|
|
||||||
|
static void OnCustomerChangedCallBack(
|
||||||
|
DependencyObject sender, DependencyPropertyChangedEventArgs e) =>
|
||||||
|
(sender as SearchControl)?.UpdateControls();
|
||||||
|
|
||||||
|
void SearchTextBox_GotFocus(object sender, RoutedEventArgs e) => _gotFocus = true;
|
||||||
|
|
||||||
|
void SearchTextBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if (_gotFocus)
|
||||||
|
{
|
||||||
|
SearchTextBox?.SelectAll();
|
||||||
|
_gotFocus = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Escape && !string.IsNullOrEmpty(Text))
|
||||||
|
{
|
||||||
|
Text = "";
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
x:Name="StringSettingControl1" x:Class="DynamicGUI.StringSettingControl"
|
x:Name="StringSettingControl1"
|
||||||
|
x:Class="MpvNet.Windows.WPF.StringSettingControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:mpvnet"
|
xmlns:local="clr-namespace:MpvNet.Windows.WPF"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800">
|
d:DesignWidth="800">
|
||||||
@@ -59,8 +60,14 @@
|
|||||||
Background="{Binding Theme.Background}"
|
Background="{Binding Theme.Background}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
<TextBlock
|
||||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
x:Name="LinkTextBlock"
|
||||||
|
Margin="2,0"
|
||||||
|
>
|
||||||
|
<local:HyperlinkEx
|
||||||
|
x:Name="Link"
|
||||||
|
Foreground="{Binding Theme.Heading}"
|
||||||
|
/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
131
src/MpvNet.Windows/WPF/Controls/StringSettingControl.xaml.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
using Forms = System.Windows.Forms;
|
||||||
|
|
||||||
|
using MpvNet.Windows.UI;
|
||||||
|
|
||||||
|
namespace MpvNet.Windows.WPF;
|
||||||
|
|
||||||
|
public partial class StringSettingControl : UserControl, ISettingControl
|
||||||
|
{
|
||||||
|
StringSetting StringSetting;
|
||||||
|
|
||||||
|
public StringSettingControl(StringSetting stringSetting)
|
||||||
|
{
|
||||||
|
StringSetting = stringSetting;
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(stringSetting.Help))
|
||||||
|
HelpTextBox.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme? Theme => Theme.Current;
|
||||||
|
|
||||||
|
public bool Contains(string search)
|
||||||
|
{
|
||||||
|
if (TitleTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (HelpTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ValueTextBox.Text.IndexOf(search, StringComparison.InvariantCultureIgnoreCase) > -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Setting Setting => StringSetting;
|
||||||
|
|
||||||
|
public string? Text
|
||||||
|
{
|
||||||
|
get => StringSetting.Value;
|
||||||
|
set => StringSetting.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (StringSetting.Type)
|
||||||
|
{
|
||||||
|
case "folder":
|
||||||
|
{
|
||||||
|
var dialog = new Forms.FolderBrowserDialog { InitialDirectory = ValueTextBox.Text };
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == Forms.DialogResult.OK)
|
||||||
|
ValueTextBox.Text = dialog.SelectedPath;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "color":
|
||||||
|
using (var dialog = new Forms.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() == Forms.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 color = Colors.Transparent;
|
||||||
|
|
||||||
|
if (ValueTextBox.Text != "")
|
||||||
|
try {
|
||||||
|
color = GetColor(ValueTextBox.Text);
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
ValueTextBox.Background = new SolidColorBrush(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
@@ -65,7 +64,7 @@ namespace HandyControl.Controls
|
|||||||
|
|
||||||
var positionLeftTop = menuItem.PointToScreen(new Point());
|
var positionLeftTop = menuItem.PointToScreen(new Point());
|
||||||
var positionRightBottom = menuItem.PointToScreen(new Point(menuItem.ActualWidth, menuItem.ActualHeight));
|
var positionRightBottom = menuItem.PointToScreen(new Point(menuItem.ActualWidth, menuItem.ActualHeight));
|
||||||
ScreenHelper.FindMonitorRectsFromPoint(InteropMethods.GetCursorPos(), out _, out var workAreaRect);
|
ScreenHelper.FindMonitorRectsFromPoint(InteropMethods.GetCursorPos(), out Rect monitorRect, out var workAreaRect);
|
||||||
var panel = VisualHelper.GetParent<Panel>(topLine);
|
var panel = VisualHelper.GetParent<Panel>(topLine);
|
||||||
|
|
||||||
if (positionLeftTop.X < 0)
|
if (positionLeftTop.X < 0)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||