Compare commits
173 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51f9e17380 | ||
|
|
28045ad33e | ||
|
|
e1bd44cd00 | ||
|
|
27d6026213 | ||
|
|
c67d5f10f8 | ||
|
|
5f73be07e8 | ||
|
|
0cad09d2bb | ||
|
|
54b2612bb8 | ||
|
|
82b4d19282 | ||
|
|
23a587c819 | ||
|
|
d69eecd494 | ||
|
|
0d4cc59f9a | ||
|
|
a394536a8c | ||
|
|
ebcd20ceb5 | ||
|
|
964c2f4dd2 | ||
|
|
e985047a54 | ||
|
|
bafc09a948 | ||
|
|
14a172b78b | ||
|
|
2eb324bf41 | ||
|
|
afe9ad5128 | ||
|
|
cc657d4ec2 | ||
|
|
1270dd474e | ||
|
|
e9ea70838d | ||
|
|
e7fde60150 | ||
|
|
2028113d58 | ||
|
|
4d55423fc7 | ||
|
|
d82874409d | ||
|
|
930ba2b0e7 | ||
|
|
4743f365a1 | ||
|
|
194ff5d62b | ||
|
|
5a726a01e0 | ||
|
|
fee13353ec | ||
|
|
cd3543fff4 | ||
|
|
c54f240346 | ||
|
|
7f55ad908a | ||
|
|
d586a82e37 | ||
|
|
722e06a02b | ||
|
|
2f76d2b775 | ||
|
|
7519977124 | ||
|
|
2e65b9ceb8 | ||
|
|
04bffca206 | ||
|
|
ff5a164c69 | ||
|
|
26b391a8d9 | ||
|
|
32eed33c82 | ||
|
|
639893f2e7 | ||
|
|
42b0cc1a64 | ||
|
|
6f7fa6c9d6 | ||
|
|
e6fb775dcd | ||
|
|
ece15ca9bb | ||
|
|
6b3c2788df | ||
|
|
067bdd20d7 | ||
|
|
97ce08c4c7 | ||
|
|
fbb9cbdc33 | ||
|
|
815adca198 | ||
|
|
ce3d5792ad | ||
|
|
74fc0b3ed7 | ||
|
|
604a1e8499 | ||
|
|
56ade0a0d1 | ||
|
|
6294a96aea | ||
|
|
9a95953a04 | ||
|
|
8d9c0c9092 | ||
|
|
e399ca672f | ||
|
|
660345d18a | ||
|
|
3844db6e79 | ||
|
|
5374e20757 | ||
|
|
bc6167c4ee | ||
|
|
7979f77284 | ||
|
|
71b90ed5cb | ||
|
|
9d2e236b3e | ||
|
|
d42657a3f0 | ||
|
|
e4818fae18 | ||
|
|
7b39bfcbc4 | ||
|
|
fd6f3c94dd | ||
|
|
dd10c07fb5 | ||
|
|
3bbfdcffdd | ||
|
|
6b7c4e1724 | ||
|
|
d3ad1091ec | ||
|
|
65177c448b | ||
|
|
1cdecb3810 | ||
|
|
20ea755a93 | ||
|
|
3b7bc95869 | ||
|
|
5380daad53 | ||
|
|
a5f4d848d4 | ||
|
|
cf0f9bfa01 | ||
|
|
68461e05da | ||
|
|
397b988851 | ||
|
|
eddb95e791 | ||
|
|
fa1183710b | ||
|
|
f468fd9c56 | ||
|
|
22f2aa93a8 | ||
|
|
c2c0a8f190 | ||
|
|
da3e6655c6 | ||
|
|
856959a4d1 | ||
|
|
9053ecb4ee | ||
|
|
33fd7fc09b | ||
|
|
d005f19755 | ||
|
|
1081007009 | ||
|
|
e6c0a67483 | ||
|
|
265e18985d | ||
|
|
8dc204e81a | ||
|
|
b9b604bfe3 | ||
|
|
05027cd458 | ||
|
|
9bbde49a5c | ||
|
|
cfca7786f3 | ||
|
|
be57edf2c5 | ||
|
|
f48901355a | ||
|
|
ca153fecfc | ||
|
|
e3227de8b4 | ||
|
|
4a202245b5 | ||
|
|
b94f9de582 | ||
|
|
7371949730 | ||
|
|
857926696c | ||
|
|
4451a6c185 | ||
|
|
ea6a71b7c3 | ||
|
|
625dddcfbb | ||
|
|
0cd769fc0c | ||
|
|
f5e0c92824 | ||
|
|
327a097bcf | ||
|
|
68626fa536 | ||
|
|
8935101058 | ||
|
|
6947c925b9 | ||
|
|
4562131078 | ||
|
|
21188f0942 | ||
|
|
1316559ebc | ||
|
|
cd576f9211 | ||
|
|
1bac8e8937 | ||
|
|
e6d0449f8f | ||
|
|
e0e40b7918 | ||
|
|
b59f16a425 | ||
|
|
46b110d93b | ||
|
|
7e8a654ada | ||
|
|
c2c33228a0 | ||
|
|
0a28f13d51 | ||
|
|
9f3a1da931 | ||
|
|
05874ad6be | ||
|
|
078e8046bd | ||
|
|
b07901485e | ||
|
|
a37cbef8a8 | ||
|
|
8debcc171c | ||
|
|
e230f0f474 | ||
|
|
558bd67591 | ||
|
|
a7e4892acf | ||
|
|
a0ba69c1aa | ||
|
|
1e7e80577d | ||
|
|
2177308b02 | ||
|
|
a8c2409ed1 | ||
|
|
1ef9e64a41 | ||
|
|
f0546485cf | ||
|
|
032e91e4b4 | ||
|
|
1447636eb7 | ||
|
|
966f96a02b | ||
|
|
954c014708 | ||
|
|
ad30dc5ae2 | ||
|
|
3f74344b99 | ||
|
|
96d8d88d09 | ||
|
|
8626b8283f | ||
|
|
d90025e8fe | ||
|
|
a572bd8553 | ||
|
|
0f5146e58c | ||
|
|
9c6c0f3506 | ||
|
|
8c36cc8b8c | ||
|
|
44435057d7 | ||
|
|
135bdeb638 | ||
|
|
93c93b620d | ||
|
|
247aefbf07 | ||
|
|
0a8397652f | ||
|
|
ecd5b01161 | ||
|
|
1e9893977d | ||
|
|
4fd6b13e0f | ||
|
|
d21d36c196 | ||
|
|
fbffbea641 | ||
|
|
9899c2cd27 | ||
|
|
10370e9ae2 |
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: stax76
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: stax76
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
291
Changelog.md
@@ -1,3 +1,272 @@
|
|||||||
|
|
||||||
|
5.4.5.2 Beta (not yet released)
|
||||||
|
============
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
5.4.6.0
|
||||||
|
=======
|
||||||
|
|
||||||
|
- youtube-dl update
|
||||||
|
- auto update routine fix
|
||||||
|
|
||||||
|
|
||||||
|
5.4.5.1 Beta
|
||||||
|
============
|
||||||
|
|
||||||
|
- extensions no longer need to end with *Extension.dll but rather
|
||||||
|
the file name and the directory name must be identical
|
||||||
|
- text encoding exception fix
|
||||||
|
- the PowerShell script host is more feature complete, easier to use
|
||||||
|
and more efficient, there were however many PowerShell and C# breaking
|
||||||
|
changes requrired to make the core more robust and efficient
|
||||||
|
- Python 2 script host removed, Python 3 support is planned for summer
|
||||||
|
|
||||||
|
|
||||||
|
5.4.5.0
|
||||||
|
=======
|
||||||
|
|
||||||
|
stable release, no changes since the last beta
|
||||||
|
|
||||||
|
|
||||||
|
5.4.4.6 Beta
|
||||||
|
============
|
||||||
|
|
||||||
|
- using start-size=video the window size was not remembered
|
||||||
|
after fullscreen mode was left.
|
||||||
|
- using start-size=video the window can now use the entire
|
||||||
|
working area using autofit-larger=100
|
||||||
|
|
||||||
|
|
||||||
|
5.4.4.5 Beta
|
||||||
|
============
|
||||||
|
|
||||||
|
- overhaul of the [webpage](README.md) and the [manual](Manual.md).
|
||||||
|
- change that possibly could fix a multimedia keyboard volume issue.
|
||||||
|
|
||||||
|
|
||||||
|
5.4.4.4 Beta
|
||||||
|
============
|
||||||
|
|
||||||
|
- with `border=no` the OSC top bar window buttons min, max and close are fully supported.
|
||||||
|
- anamorphic videos are shown without black bars, the window is resized according to the ascpect ratio.
|
||||||
|
- PowerShell 5.1 was made optional.
|
||||||
|
- full implementation for `window-minimized` and `window-maximized`,
|
||||||
|
scripts that depend on this like pause-when-minimize.lua are now fully supported.
|
||||||
|
- fix cycling from maximized to fullscreen and back.
|
||||||
|
|
||||||
|
|
||||||
|
5.4.4.3 Beta
|
||||||
|
============
|
||||||
|
|
||||||
|
- update MediaInfo 20.03
|
||||||
|
- update libmpv 2020-04-12, it supports vpy playback, read manual or ask in forum
|
||||||
|
- mpv property `window-maximized` support added, cycling it from input.conf
|
||||||
|
is not recommended, use native Windows shortcuts Win+Up, Win+Down
|
||||||
|
- the mpv.net `start-size` option supports `always` to always remember the window height
|
||||||
|
- if the window was maximized before fullscreen was entered, it's now set to
|
||||||
|
maximized after fullscreen was left
|
||||||
|
- with `border=no` the OSC did not auto hide after the mouse curser left the window
|
||||||
|
- the script that modified the seek OSD was removed, it still can be found in the mpv wiki
|
||||||
|
- certain videos were showed with black bars
|
||||||
|
|
||||||
|
|
||||||
|
### 5.4.4.2
|
||||||
|
|
||||||
|
- update: libmpv shinchiro 0.32.0-258-g281f5c63c1
|
||||||
|
- update: youtube-dl
|
||||||
|
|
||||||
|
- new: d3d11va-zero-copy setting added to conf editor
|
||||||
|
- new: hdr-compute-peak setting added to conf editor
|
||||||
|
- new: flag cli switches support now `--no-flag` in addition to `--flag=no`
|
||||||
|
https://mpv.io/manual/master/#usage
|
||||||
|
- new: cli switches can also start with single `-` instead of double `--`
|
||||||
|
https://mpv.io/manual/master/#legacy-option-syntax
|
||||||
|
- new: PowerShell script host was completely rewritten, events can be assigned
|
||||||
|
by using `Register-ObjectEvent`, the scripting wiki page was updated
|
||||||
|
https://github.com/stax76/mpv.net/wiki/Scripting#powershell
|
||||||
|
- new: Context Menu > View > Show Profiles
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L147
|
||||||
|
- new: Context Menu > View > Show Properties
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L148
|
||||||
|
- new: Context Menu > View > Show Commands
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149
|
||||||
|
- new: config editor tab is now remembered
|
||||||
|
- new: osd-duration setting added to config editor and default mpv.conf
|
||||||
|
- new: external console replaced with internal console, in case mpv.conf is missing it's
|
||||||
|
generated with correct Hight DPI font size scale settings.
|
||||||
|
`script-opts=console-scale=<dpiscale>`
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L150
|
||||||
|
https://mpv.io/manual/master/#console
|
||||||
|
- new: blue color in dark theme is now less intense
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme
|
||||||
|
- new: menu item 'View > Show Progress' (p key) to show progress bar
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L146
|
||||||
|
- new: `script-message mpv.net playlist-first`, unlike mpv does not
|
||||||
|
restart if the first file is already active
|
||||||
|
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L44
|
||||||
|
- new: if mpv.net is started from the terminal and an error happens then the error
|
||||||
|
is printed to the terminal instead of shown with a message box
|
||||||
|
- fix: update routine did only work when mpv.net was located in 'Program Files'
|
||||||
|
- fix: fatal errors were ignored and only seen in the terminal, now a message box is shown
|
||||||
|
- fix: when start-size=video was used then enlarging or shrinking the window size was broken
|
||||||
|
|
||||||
|
### 5.4.4.0
|
||||||
|
|
||||||
|
- new: forecolors in the dark theme are slightly darker now
|
||||||
|
- new: readme/website and manual were improved
|
||||||
|
- new: source code includes now the release script to build the archives and setup files
|
||||||
|
- new: the history feature now uses the full path
|
||||||
|
- new: install via Scoop and Chocolatey added to readme/website (Restia666Ashdoll)
|
||||||
|
- new: update check, it must be enabled first in the conf editor under General
|
||||||
|
- new: update feature, requires PowerShell 5 and curl,
|
||||||
|
an up to date Windows 10 system has both included.
|
||||||
|
Main menu (input.conf) must be reset or updated manually ([defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt))
|
||||||
|
|
||||||
|
- update: libmpv shinchiro 2019-11-10
|
||||||
|
|
||||||
|
- fix: often the OSC was shown when fullscreen was entered
|
||||||
|
or on app startup, this is now suppressed
|
||||||
|
- fix: the file association routine uses no longer 'Play with mpv.net' for the
|
||||||
|
default open verb caption because it doesn't support multi selection,
|
||||||
|
it shows now only Open, the manual explains how to get multi selection
|
||||||
|
in File Explorer, read about it [here](https://github.com/stax76/mpv.net/blob/master/Manual.md#open-with)
|
||||||
|
- fix: x86 builds had an older version included because
|
||||||
|
of a misconfiguration in the solution file
|
||||||
|
|
||||||
|
### 5.4.3.0
|
||||||
|
|
||||||
|
- new: the color themes can now be customized ([manual](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme))
|
||||||
|
- new: three new sections were added to the [manual](https://github.com/stax76/mpv.net/blob/master/Manual.md):
|
||||||
|
1. [Color Theme](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme)
|
||||||
|
2. [Hidden and secret features](https://github.com/stax76/mpv.net/blob/master/Manual.md#hidden-and-secret-features)
|
||||||
|
3. [External Tools](https://github.com/stax76/mpv.net/blob/master/Manual.md#external-tools)
|
||||||
|
|
||||||
|
- fix: window restore from maximized and from minimized was broken
|
||||||
|
- fix: it's possible to multi select files in File Explorer and press
|
||||||
|
enter to open the files, this did however only work when the
|
||||||
|
auto load folder feature was disabled or the shift key was
|
||||||
|
pressed (blocks auto load folder). Now it should also work
|
||||||
|
without shift key and with auto load folder being enabled
|
||||||
|
|
||||||
|
- update: libmpv shinchiro 2019-10-27
|
||||||
|
- update: youtube-dl 2019-10-31
|
||||||
|
|
||||||
|
### 5.4.2.1 Beta
|
||||||
|
|
||||||
|
- pressing shift key suppresses auto-load-folder
|
||||||
|
- switch --queue added, this will not clear the playlist but append
|
||||||
|
and it will suppress auto-load-folder. To get a 'Add to mpv.net playlist'
|
||||||
|
context menu item in explorer with multi selection support use my
|
||||||
|
[Open with++](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist) shell extension, as far as I know multi selection
|
||||||
|
can not be done using the Registry but only via shell extension
|
||||||
|
- window-size mpv property support added ([default bindings](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L137))
|
||||||
|
- the config editor keeps profiles and comments in mpv.conf intact!
|
||||||
|
- the options in the config editor are better organized
|
||||||
|
|
||||||
|
### 5.4.2
|
||||||
|
|
||||||
|
- new: the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting#powershell) was improved
|
||||||
|
- new: Toggle Shuffle has been added to the menu defaults
|
||||||
|
- new: for URLs the media title is shown in the title bar and in the info command
|
||||||
|
instead of displaying the URL, mpv.conf defaults were changed to use
|
||||||
|
[protocol.https] osd-playing-msg = '${media-title}'
|
||||||
|
|
||||||
|
- fix: on the very first start volume was set to 0 and mute was set to yes
|
||||||
|
- fix: there was a sound when closed from taskbar
|
||||||
|
- fix: the log feature was not working
|
||||||
|
- fix: clipboard monitoring removed because it was causing to many issues
|
||||||
|
- fix: restore resulted in collapsed window when maximized = yes was used
|
||||||
|
|
||||||
|
- update: libmpv shinchiro 2019-10-06
|
||||||
|
- update: youtube-dl 2019-10-01
|
||||||
|
|
||||||
|
### 5.4.1.1
|
||||||
|
|
||||||
|
- a issue with the taskbar-progress feature was fixed
|
||||||
|
- improved PowerShell scrip host
|
||||||
|
|
||||||
|
### 5.4.1
|
||||||
|
|
||||||
|
- fix ArgumentOutOfRangeException
|
||||||
|
|
||||||
|
### 5.4
|
||||||
|
|
||||||
|
- added taskbar-progress implementation
|
||||||
|
- added new setting to start with maximized window
|
||||||
|
- long file paths work now even if not enabled by the OS
|
||||||
|
- fixed history being written even when history file wasn't created prior
|
||||||
|
- libmpv updated to shinchiro 2019-08-31
|
||||||
|
|
||||||
|
### 5.3
|
||||||
|
|
||||||
|
- added new feature: Open > Open DVD/Blu-ray Drive/Folder...
|
||||||
|
- the default of remember-volume has been set to yes
|
||||||
|
- scale, cscale, dscale defaults have been set to spline36,
|
||||||
|
profile=gpu-hq is not used in the defaults because it starts very slow
|
||||||
|
- new menu items have been added to navigate to the first and
|
||||||
|
last playlist position, key bindings: Home, End
|
||||||
|
- new config setting recent-count added, amount of menu items
|
||||||
|
shown under 'Open > Recent'
|
||||||
|
- in the config dialog the description for keep-open was corrected
|
||||||
|
because unlike mpv, mpv.net will never terminate automatically
|
||||||
|
- there was a rare occasion where the mpv.net logo wasn't shown
|
||||||
|
- fix excessive memory usage using `osd-scale-by-window = no`
|
||||||
|
- mpv setting osd-scale-by-window added to config dialog
|
||||||
|
|
||||||
|
### 5.2.1
|
||||||
|
|
||||||
|
- fixed race condition causing various features to fail
|
||||||
|
|
||||||
|
### 5.2
|
||||||
|
|
||||||
|
- bug fix for single-instance not working with unicode filenames
|
||||||
|
- bug fix for logo not shown on start
|
||||||
|
- osd-visibility.js script was removed because the OSC uses too much memory
|
||||||
|
- youtube-dl was updated
|
||||||
|
- libmpv was updated to shinchiro 2019-08-04
|
||||||
|
- in case mpv.net was started from a terminal it sets now the mpv property input-terminal to yes,
|
||||||
|
this means mpv.net will now receive and handle input keys from the terminal
|
||||||
|
- certain command line properties didn't work (input-terminal, terminal, input-file,
|
||||||
|
config, config-dir, input-conf, load-scripts, script, scripts, player-operation-mode)
|
||||||
|
- the about dialog shows now the mpv version and build date
|
||||||
|
- the dialog that asks for a config folder has now a cancel option
|
||||||
|
|
||||||
|
### 5.1
|
||||||
|
|
||||||
|
- many [wiki pages](https://github.com/stax76/mpv.net/wiki) were improved
|
||||||
|
- the logo/icon had a very small cosmetic change
|
||||||
|
- the help in the context menu was improved,
|
||||||
|
for quick access consider the command palette (F1 key)
|
||||||
|
- config options specific to mpv.net are now available from the command line
|
||||||
|
- the input editor no longer has known limitations, 'alt gr' and ctrl+alt are working now
|
||||||
|
- the help in the input editor was simplified and the filter logic was improved
|
||||||
|
- fixed issue in file associations causing mpv.net not to appear in OS default apps
|
||||||
|
- 'Tools > Manage File Associations' was replaced by 'Tools > OS Setup',
|
||||||
|
it has now a feature to add and remove mpv.net to and from the Path
|
||||||
|
environment variable and the OS default apps settings can be opened (Win 10 only)
|
||||||
|
- startup folder and config folder being identical was causing a critical issue
|
||||||
|
as mpv.net was loading extensions twice and scripts four times, now identical
|
||||||
|
folders are no longer permitted
|
||||||
|
- error messages are shown when unknown scripts and extensions are found in the startup folder
|
||||||
|
because user scripts and extensions are supposed to be located in the config folder instead
|
||||||
|
- changing from maximized to fullscreen did not work
|
||||||
|
- the search field in the config editor was not always remembered
|
||||||
|
- new setting remember-volume added, saves volume and mute on exit
|
||||||
|
and restores it on start.
|
||||||
|
- it's now enforced that mpv properties on the command line and in
|
||||||
|
the mpv.conf config file are lowercase, if not a error is shown
|
||||||
|
- gpu-api vulkan was not working if media files were opened via
|
||||||
|
command line (that included Explorer)
|
||||||
|
- new setting minimum-aspect-ratio added, minimum aspect ratio for the window,
|
||||||
|
this was previously hard coded to 1.3
|
||||||
|
- new setting auto-load-folder added, for single files automatically load
|
||||||
|
the entire directory into the playlist, previously this was forced,
|
||||||
|
now it can be disabled
|
||||||
|
- new setting themed-menu added, follow theme color in context menu,
|
||||||
|
default: no. UI related settings have now a separate UI tab in the config editor
|
||||||
|
|
||||||
### 5.0
|
### 5.0
|
||||||
|
|
||||||
- [changed icon design](https://github.com/stax76/mpv.net/blob/master/img/mpvnet.png)
|
- [changed icon design](https://github.com/stax76/mpv.net/blob/master/img/mpvnet.png)
|
||||||
@@ -12,13 +281,13 @@
|
|||||||
change is that there exist too many different terms, addons, addins,
|
change is that there exist too many different terms, addons, addins,
|
||||||
extensions, modules, packages etc.. mpv.net follows Google Chrome as the worlds
|
extensions, modules, packages etc.. mpv.net follows Google Chrome as the worlds
|
||||||
most popular extendable app, Chrome uses the term Extension.
|
most popular extendable app, Chrome uses the term Extension.
|
||||||
- a thread synchronisation bug was fixed, the shutdown thread was aborted
|
- a thread synchronization bug was fixed, the shutdown thread was aborted
|
||||||
if it was running more then 3 seconds, this caused the rating extension
|
if it was running more than 3 seconds, this caused the rating extension
|
||||||
to fail if it was waiting for a drive to wakeup
|
to fail if it was waiting for a drive to wake up
|
||||||
- a new JavaScript was included to show the playlist with a smaller font size,
|
- a new JavaScript was included to show the playlist with a smaller font size,
|
||||||
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 performence 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/stax76/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
|
||||||
@@ -85,11 +354,11 @@
|
|||||||
- fix for middle mouse button not working
|
- fix for middle mouse button not working
|
||||||
- fix of logo overlay using a huge amount of memory (thx for the [ghacks article](https://www.ghacks.net/2019/07/05/a-look-at-mpv-net-a-mpv-frontend-with-everything-integration/))
|
- fix of logo overlay using a huge amount of memory (thx for the [ghacks article](https://www.ghacks.net/2019/07/05/a-look-at-mpv-net-a-mpv-frontend-with-everything-integration/))
|
||||||
- fix config dialog showing a message about app restart without reason
|
- fix config dialog showing a message about app restart without reason
|
||||||
- when multiple files are selected in Windows File Explorer and enter is
|
- when multiple files are selected in File Explorer and enter is
|
||||||
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/mpvConf.txt) were changed to show a larger OSC
|
- the [mpv.conf defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt) were changed to show a larger OSC
|
||||||
- in case a file is opened that has a aspect ratio smaller then 1.2 then
|
- 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
|
||||||
@@ -100,7 +369,7 @@
|
|||||||
|
|
||||||
- opening a URL manually no longer uses a input box but uses the clipboard directly
|
- opening a URL manually no longer uses a input box but uses the clipboard directly
|
||||||
- the manifest was missing the company attribute which caused
|
- the manifest was missing the company attribute which caused
|
||||||
mpv.net not appearing in the 'Open with' menu of the Windows File Explorer,
|
mpv.net not appearing in the 'Open with' menu of the File Explorer,
|
||||||
thanks to 44vince44 for pointing this out!!!
|
thanks to 44vince44 for pointing this out!!!
|
||||||
- new Python and C# script examples were added to the wiki and the scripting and
|
- new Python and C# script examples were added to the wiki and the scripting and
|
||||||
extension documentation was improved
|
extension documentation was improved
|
||||||
@@ -128,7 +397,7 @@
|
|||||||
- 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/inputConf.txt#L135))
|
key binding (b) was added as well ([Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L135))
|
||||||
|
|
||||||
### 4.3.1
|
### 4.3.1
|
||||||
|
|
||||||
@@ -143,7 +412,7 @@
|
|||||||
- 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/inputConf.txt#L33)
|
it appends files to the playlist [(Default binding)](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L33)
|
||||||
- a setting was added to force using a single mpv.net process instance
|
- a setting was added to force using a single mpv.net process instance
|
||||||
|
|
||||||
### 4.1
|
### 4.1
|
||||||
@@ -185,7 +454,7 @@
|
|||||||
- 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/inputConf.txt#L29)
|
[Everything](https://www.voidtools.com) to be installed. [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L29)
|
||||||
|
|
||||||
### 3.5
|
### 3.5
|
||||||
|
|
||||||
@@ -198,6 +467,6 @@
|
|||||||
|
|
||||||
### 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/inputConf.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/stax76/mpv.net/blob/master/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
|
||||||
31
LICENSE.txt
@@ -1,21 +1,24 @@
|
|||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017-2019 Frank Skare (stax76)
|
Copyright (C) 2017-2020 Frank Skare (stax76)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person
|
||||||
a copy of this software and ssociated documentation files (the "Software"),
|
obtaining a copy of this software and ssociated documentation
|
||||||
to deal in the Software without restriction, including without limitation
|
files (the "Software"), to deal in the Software without restriction,
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
including without limitation the rights to use, copy, modify, merge,
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
Software is furnished to do so, subject to the following conditions:
|
and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be
|
||||||
in all copies or substantial portions of the Software.
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||||
|
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
313
README.md
@@ -1,261 +1,148 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
# 🎞 mpv.net
|
    
|
||||||
|
|
||||||
mpv.net is a modern media player for Windows that works just like [mpv](https://mpv.io).
|
🎞 mpv.net
|
||||||
|
==========
|
||||||
|
|
||||||
#### Based on libmpv
|
mpv.net is a modern media player for Windows based on the popular [mpv](https://mpv.io) player.
|
||||||
|
|
||||||
|
|
||||||
|
#### Graphical User Interface
|
||||||
|
|
||||||
|
Modern GUI with customizable color themes.
|
||||||
|
|
||||||
mpv.net is based on libmpv which offers a straightforward C API that was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications. mpv is like vlc not based on DirectShow or Media Foundation.
|
|
||||||
|
|
||||||
#### Command Line Interface
|
#### Command Line Interface
|
||||||
|
|
||||||
mpv.net has the [CLI of mpv](https://mpv.io/manual/master/#options).
|
mpv.net supports mpvs property based command line switches.
|
||||||
|
|
||||||
|
|
||||||
#### High quality video output
|
#### High quality video output
|
||||||
|
|
||||||
libmpv has an OpenGL based video output that is capable of many features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more.
|
Video output that is capable of many features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more.
|
||||||
|
|
||||||
|
|
||||||
#### On Screen Controller
|
#### On Screen Controller
|
||||||
|
|
||||||
The OSC of libmpv offers play controls with a modern flat design. ([Screenshot](#main-window-screenshot))
|
Play controls with a modern flat design.
|
||||||
|
|
||||||
|
|
||||||
#### GPU video decoding
|
#### GPU video decoding
|
||||||
|
|
||||||
libmpv leverages the FFmpeg hwaccel APIs to support DXVA2 video decoding acceleration.
|
Leverages the FFmpeg hwaccel APIs to support DXVA2 video decoding acceleration.
|
||||||
|
|
||||||
|
|
||||||
#### Active development
|
#### Active development
|
||||||
|
|
||||||
mpv.net is under active development. Want a feature? Post a [patch](https://github.com/stax76/mpv.net/pulls) or [request it](https://github.com/stax76/mpv.net/issues)!
|
mpv.net is under active development.
|
||||||
|
|
||||||
|
|
||||||
|
#### Based on libmpv
|
||||||
|
|
||||||
|
mpv.net is based on libmpv which offers a straightforward C API that was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications. mpv is like VLC not based on DirectShow or Media Foundation.
|
||||||
|
|
||||||
|
|
||||||
Table of contents
|
Table of contents
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
- [Screenshots](#screenshots)
|
|
||||||
- [Manual](#manual)
|
|
||||||
- [Context Menu](#context-menu)
|
|
||||||
- [Settings](#settings)
|
|
||||||
- [Scripting](#scripting)
|
|
||||||
- [Extensions](#extensions)
|
|
||||||
- [Architecture](#architecture)
|
|
||||||
- [Support](#support)
|
- [Support](#support)
|
||||||
- [Links](#links)
|
|
||||||
- [Changelog](#changelog)
|
|
||||||
- [Download](#download)
|
- [Download](#download)
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
- Very high degree of mpv compatibility, almost all mpv features are available
|
|
||||||
- Great usability due to everything in the application being searchable
|
|
||||||
- Open source built with modern tools
|
|
||||||
- Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt))
|
|
||||||
- Searchable config dialog ([Screenshot](#config-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt))
|
|
||||||
- Searchable input (key/mouse) binding editor ([Screenshot](#input-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt))
|
|
||||||
- Configuration files that are easy to read and edit
|
|
||||||
- Searchable command palette to quickly launch commands and look for keys ([Screenshot](#command-palette-screenshot))
|
|
||||||
- Modern WPF based graphical user interface with dark mode ([Screenshot](#config-editor-screenshot))
|
|
||||||
- Extension API for .NET languages
|
|
||||||
- Scripting API for Python, C#, Lua, JavaScript and PowerShell ([Wiki](https://github.com/stax76/mpv.net/wiki/Scripting))
|
|
||||||
- Language agnostic JSON IPC to control the player with a external programs
|
|
||||||
- On Screen Controler (OSC, play control buttons)
|
|
||||||
- [Command Line Interface](https://mpv.io/manual/master/#options)
|
|
||||||
- DXVA2 video decoding acceleration
|
|
||||||
- OpenGL based video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more
|
|
||||||
- Search feature powered by [Everything](https://www.voidtools.com) to find and play media ([Screenshot](#media-search-screenshot))
|
|
||||||
- Extension to start mpv.net from Google Chrome ([Manual](Manual.md#chrome-extension))
|
|
||||||
- Extremely fast seek performance
|
|
||||||
- Very fast startup performance, video is usally ready to play in less then a second
|
|
||||||
- Usable as video player, audio player and image viewer with a wide range of supported formats
|
|
||||||
- All decoders are built-in, no external codecs have to be installed
|
|
||||||
- Setup and portable download options, setup is recommended but not required
|
|
||||||
- Build-in media streaming via youtube-dl
|
|
||||||
- x64 and x86 Support (64-bit and 32-bit)
|
|
||||||
- File associations can be created by the setup and from the player
|
|
||||||
- External audio and subtitle files can either be loaded manually or automatically
|
|
||||||
- Screenshot feature with many options
|
|
||||||
- File history feature to log time and filename
|
|
||||||
- A-B loop feature
|
|
||||||
- watch later feature to save the position
|
|
||||||
- [Manual](#manual)
|
- [Manual](#manual)
|
||||||
|
- [Screenshots](#screenshots)
|
||||||
|
|
||||||
### Screenshots
|
|
||||||
|
|
||||||
#### Main Window Screenshot
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
- High degree of mpv compatibility, almost all mpv features are available
|
||||||
|
- Customizable context menu defined in the same file as the key bindings
|
||||||
|
- Config dialog
|
||||||
|
- Shorcut key editor
|
||||||
|
- Many features like the config editor and shortcut key editor are fully searchable
|
||||||
|
- Configuration files that are easy to read and edit
|
||||||
|
- Command palette to quickly find commands and keys
|
||||||
|
- Modern graphical user interface with customizable color themes
|
||||||
|
- Extension API for .NET languages (C#, VB.NET and F#)
|
||||||
|
- Scripting API for C#, Lua, JavaScript and PowerShell
|
||||||
|
- JSON IPC to control the player with a external programs
|
||||||
|
- On Screen Controler (OSC, play control buttons) with modern flat design
|
||||||
|
- Command Line Interface
|
||||||
|
- Started from a terminal status and debug output is printed on the terminal
|
||||||
|
- DXVA2 video decoding acceleration
|
||||||
|
- Video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more
|
||||||
|
- File search feature powered by the popular search and index tool Everything
|
||||||
|
- Browser extensions to start mpv.net from the browser
|
||||||
|
- Fast seek performance
|
||||||
|
- Fast startup performance
|
||||||
|
- Usable as video player, audio player and image viewer with a wide range of supported formats
|
||||||
|
- Built-in decoders, no external codecs have to be installed
|
||||||
|
- Setup as x64, x86, installer, portable, Chocolatey and Scoop
|
||||||
|
- Build-in media streaming via youtube-dl
|
||||||
|
- File associations can be created by the setup and from the player
|
||||||
|
- External audio and subtitle files can be loaded manually or automatically
|
||||||
|
- Screenshot feature
|
||||||
|
- File history feature to log time and filename
|
||||||
|
- Watch later feature to save the position
|
||||||
|
- Files can be enqueued from File Explorer
|
||||||
|
- Update check and update routine
|
||||||
|
|
||||||
|
|
||||||
|
## [Support](Manual.md#support)
|
||||||
|
|
||||||
|
[Support section of the manual.](Manual.md#support)
|
||||||
|
|
||||||
|
|
||||||
|
## [Download](Manual.md#download)
|
||||||
|
|
||||||
|
[Download section of the manual.](Manual.md#download)
|
||||||
|
|
||||||
|
|
||||||
|
## [Manual](Manual.md)
|
||||||
|
|
||||||
|
[The mpv.net documentation.](Manual.md)
|
||||||
|
|
||||||
|
|
||||||
|
Screenshots
|
||||||
|
-----------
|
||||||
|
|
||||||
|
#### Main Window
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Context Menu Screenshot
|
|
||||||
|
|
||||||
Context menu defined in the input.conf file with dark mode support.
|
#### Context Menu
|
||||||
|
|
||||||
|
Context menu using dark mode.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Config Editor Screenshot
|
|
||||||
|
|
||||||
A searchable config editor as alternative to edit the mpv.conf file manually.
|
#### Config Editor
|
||||||
|
|
||||||
|
Searchable config editor as alternative to edit the conf file manually.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Input Editor Screenshot
|
|
||||||
|
|
||||||
A searchable key and mouse binding editor.
|
#### Terminal
|
||||||
|
|
||||||
|
OSD console and status printed on the terminal.
|
||||||
|
|
||||||
|

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

|

|
||||||
|
|
||||||
#### Command Palette Screenshot
|
|
||||||
|
|
||||||
Forgot where a command in the menu is located or what shortcut key it has?
|
#### Command Palette
|
||||||
Just press F1 and find it easily in the searchable command palette.
|
|
||||||
|
Command Palette to find commands and shortcut keys easily.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Media Search Screenshot
|
|
||||||
|
|
||||||
Media search feature powered by [Everything](https://www.voidtools.com) to find and play media.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Manual
|
|
||||||
|
|
||||||
[Manual](Manual.md)
|
|
||||||
|
|
||||||
### Context Menu
|
|
||||||
|
|
||||||
The context menu can be customized via input.conf file located in the config directory:
|
|
||||||
|
|
||||||
```Text
|
|
||||||
C:\Users\%username%\AppData\Roaming\mpv\input.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
if it's missing mpv.net generates it with the following defaults:
|
|
||||||
|
|
||||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt>
|
|
||||||
|
|
||||||
input.conf defines mpv's key and mouse bindings and mpv.net uses comments to define the context menu.
|
|
||||||
|
|
||||||
### Settings
|
|
||||||
|
|
||||||
When mpv.net finds no config folder on startup it will ask for a location.
|
|
||||||
|
|
||||||
If a folder named portable_config next to the mpvnet.exe exists,
|
|
||||||
all config will be loaded from this folder only.
|
|
||||||
|
|
||||||
```Text
|
|
||||||
<startup>\portable_config\
|
|
||||||
```
|
|
||||||
|
|
||||||
mpv specific settings are stored in the file mpv.conf, if no mpv.conf file exists
|
|
||||||
mpv.net generates it with the following defaults:
|
|
||||||
|
|
||||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt>
|
|
||||||
|
|
||||||
mpv.net specific settings are stored in the file mpvnet.conf
|
|
||||||
|
|
||||||
The input (key/mouse) bindings and the context menu definitions are stored in the
|
|
||||||
input.conf file, if it's missing mpv.net generates it with the following defaults:
|
|
||||||
|
|
||||||
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt>
|
|
||||||
|
|
||||||
mpv.net supports almost all mpv settings and features,
|
|
||||||
[limitations are listed in the wiki](https://github.com/stax76/mpv.net/wiki/Limitations).
|
|
||||||
|
|
||||||
The config folder can be opened from the context menu.
|
|
||||||
|
|
||||||
### Scripting
|
|
||||||
|
|
||||||
[Scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting)
|
|
||||||
|
|
||||||
### Extensions
|
|
||||||
|
|
||||||
[Extensions wiki page](https://github.com/stax76/mpv.net/wiki/Extensions)
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
Coding mpv.net was great fun because libmpv is such a awesome
|
|
||||||
library with a very clever design, I'm having a great experience
|
|
||||||
with libmpv.
|
|
||||||
|
|
||||||
The player does not contain any feature that was more work than 1-2 days or
|
|
||||||
was difficult to build, the hard parts are totally covered by libmpv.
|
|
||||||
|
|
||||||
mpv.net is written in C# 7 and runs on .NET 4.7, I've not yet decided
|
|
||||||
if I will port it to C# 8 and .NET 5 once available.
|
|
||||||
|
|
||||||
The Extension implementation is based on the [Managed Extensibility Framework](https://docs.microsoft.com/en-us/dotnet/framework/mef/).
|
|
||||||
|
|
||||||
There are no specific extension or scripting interfaces but instead everyting
|
|
||||||
is accessible for .NET compatible languages (C#, VB.NET, F#, Python, PowerShell),
|
|
||||||
this decision was made to keep the code simple and lightweight.
|
|
||||||
|
|
||||||
Python scripting is implemented with IronPython which uses Python 2.7.
|
|
||||||
|
|
||||||
The main window is WinForms based and uses less than 600 lines of code,
|
|
||||||
all other windows are WPF based and use even less code.
|
|
||||||
|
|
||||||
The config editor adds it's controls dynamically and uses [TOML](https://en.wikipedia.org/wiki/TOML) to define it's
|
|
||||||
content, there are only two simple types, StringSetting and OptionSetting.
|
|
||||||
|
|
||||||
mpv.net was started 2017 and consists of about 6000 lines of code and markup.
|
|
||||||
|
|
||||||
IDE, Editor: Visual Studio, Visual Studio Code.
|
|
||||||
|
|
||||||
Due to mpv.net being my first WPF app and mpv.net never meant to be a large
|
|
||||||
application best practices and design pattern are not always applied.
|
|
||||||
|
|
||||||
Third party components:
|
|
||||||
|
|
||||||
- [libmpv, the heard and soul of mpv.net](https://mpv.io/)
|
|
||||||
- [MediaInfo, no media related project could do without](https://mediaarea.net/en/MediaInfo)
|
|
||||||
- [Tommy, a single file TOML parser](https://github.com/dezhidki/Tommy)
|
|
||||||
- [IronPython, bringing Python to dotnet](https://ironpython.net/)
|
|
||||||
- [CS-Script, scripting with C#](http://www.csscript.net/)
|
|
||||||
- [Everything, a blazing fast file search service](https://www.voidtools.com)
|
|
||||||
|
|
||||||
### Support
|
|
||||||
|
|
||||||
[Support thread in Doom9 forum](https://forum.doom9.org/showthread.php?t=174841)
|
|
||||||
|
|
||||||
[Support thread in VideoHelp forum](https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows)
|
|
||||||
|
|
||||||
[Issue tracker to report bugs and request features](https://github.com/stax76/mpv.net/issues)
|
|
||||||
|
|
||||||
[frank.skare.de@gmail.com](mailto:frank.skare.de@gmail.com?Subject=mpv.net%20support)
|
|
||||||
|
|
||||||
Please click on the star at the top of the page and like mpv.net at [alternativeto.net](https://alternativeto.net/software/mpv-net/).
|
|
||||||
|
|
||||||
If you like you can express your appreciation for my player by sending little beer money with paypal.
|
|
||||||
|
|
||||||
<https://www.paypal.me/stax76>
|
|
||||||
|
|
||||||
### Links
|
|
||||||
|
|
||||||
mpv manual: <https://mpv.io/manual/master/>
|
|
||||||
|
|
||||||
mpv wiki: <https://github.com/mpv-player/mpv/wiki>
|
|
||||||
|
|
||||||
mpv.net wiki: <https://github.com/stax76/mpv.net/wiki>
|
|
||||||
|
|
||||||
mpv apps: <https://github.com/mpv-player/mpv/wiki/Applications-using-mpv>
|
|
||||||
|
|
||||||
mpv user scripts: <https://github.com/mpv-player/mpv/wiki/User-Scripts>
|
|
||||||
|
|
||||||
mpv default key bindings: <https://github.com/mpv-player/mpv/blob/master/etc/input.conf>
|
|
||||||
|
|
||||||
mpv.net default key bindings: <https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt>
|
|
||||||
|
|
||||||
mpv download: <https://mpv.io/installation/>
|
|
||||||
|
|
||||||
mpv.net download: <https://github.com/stax76/mpv.net/releases>
|
|
||||||
|
|
||||||
mpv bugs and requests: <https://mpv.io/bug-reports/>
|
|
||||||
|
|
||||||
mpv.net bugs and requests: <https://github.com/stax76/mpv.net/issues>
|
|
||||||
|
|
||||||
### Changelog
|
|
||||||
|
|
||||||
[Changelog](Changelog.md)
|
|
||||||
|
|
||||||
### Download
|
|
||||||
|
|
||||||
<https://github.com/stax76/mpv.net/releases>
|
|
||||||
113
Release.ps1
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$include = @(
|
||||||
|
'*.cs',
|
||||||
|
'*.csproj',
|
||||||
|
'*.iss',
|
||||||
|
'*.js',
|
||||||
|
'*.lua',
|
||||||
|
'*.ps1',
|
||||||
|
'*.resx',
|
||||||
|
'*.sln',
|
||||||
|
'*.txt',
|
||||||
|
'*.xaml'
|
||||||
|
)
|
||||||
|
|
||||||
|
$files = Get-ChildItem -Path $PSScriptRoot -Recurse -File -Include $include
|
||||||
|
|
||||||
|
foreach ($file in $files)
|
||||||
|
{
|
||||||
|
$lines = Get-Content $file
|
||||||
|
|
||||||
|
foreach ($line in $lines)
|
||||||
|
{
|
||||||
|
foreach ($char in $line.ToCharArray())
|
||||||
|
{
|
||||||
|
$codePoint = [int]$char
|
||||||
|
|
||||||
|
if ($codePoint -gt 127)
|
||||||
|
{
|
||||||
|
throw "Non ASCII char $char in file '$($file.FullName)' in line: $line"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$desktopDir = [Environment]::GetFolderPath('Desktop')
|
||||||
|
$exePath = $PSScriptRoot + '\mpv.net\bin\x64\mpvnet.exe'
|
||||||
|
$versionInfo = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath)
|
||||||
|
$vsDir = 'C:\Program Files (x86)\Microsoft Visual Studio\2019'
|
||||||
|
$msBuild = $vsDir + '\Community\MSBuild\Current\Bin\MSBuild.exe'
|
||||||
|
$inno = 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe'
|
||||||
|
$7z = 'C:\Program Files\7-Zip\7z.exe'
|
||||||
|
|
||||||
|
if ($versionInfo.FilePrivatePart -eq 0)
|
||||||
|
{
|
||||||
|
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x64
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x86
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
& $inno /Darch=x64 setup.iss
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
& $inno /Darch=x86 setup.iss
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
$targetDir = $desktopDir + "\mpv.net-portable-x64-$($versionInfo.FileVersion)"
|
||||||
|
Copy-Item .\mpv.net\bin\x64 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||||
|
|
||||||
|
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
$targetDir = $desktopDir + "\mpv.net-portable-x86-$($versionInfo.FileVersion)"
|
||||||
|
Copy-Item .\mpv.net\bin\x86 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||||
|
|
||||||
|
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
& $msBuild mpv.net.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x64
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
$targetDir = "$desktopDir\mpv.net-portable-x64-$($versionInfo.FileVersion)-beta"
|
||||||
|
Copy-Item .\mpv.net\bin\x64 $targetDir -Recurse -Exclude System.Management.Automation.xml
|
||||||
|
& $7z a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
$cloudDirectories = 'C:\Users\frank\OneDrive\Public\mpv.net\',
|
||||||
|
'C:\Users\frank\Dropbox\Public\mpv.net\'
|
||||||
|
|
||||||
|
foreach ($cloudDirectory in $cloudDirectories)
|
||||||
|
{
|
||||||
|
if (-not (Test-Path $cloudDirectory))
|
||||||
|
{
|
||||||
|
throw $cloudDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetFile = $cloudDirectory + (Split-Path $targetDir -Leaf) + '.7z'
|
||||||
|
|
||||||
|
if (Test-Path $targetFile)
|
||||||
|
{
|
||||||
|
throw $targetFile
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item ($targetDir + '.7z') $targetFile
|
||||||
|
Invoke-Item $cloudDirectory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-Clipboard ($versionInfo.FileVersion + "`n`n" +
|
||||||
|
'https://github.com/stax76/mpv.net/blob/master/Changelog.md' + "`n`n" +
|
||||||
|
'https://github.com/stax76/mpv.net#download')
|
||||||
|
|
||||||
|
Write-Host 'successfully finished' -ForegroundColor Green
|
||||||
@@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
|
|||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("RatingExtension")]
|
[assembly: AssemblyTitle("RatingExtension")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("RatingExtension")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
||||||
[assembly: AssemblyProduct("RatingExtension")]
|
[assembly: AssemblyProduct("RatingExtension")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2017-2019 Frank Skare (stax76)")]
|
[assembly: AssemblyCopyright("Copyright (C) 2017-2020 Frank Skare (stax76)")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
using System;
|
// This extension writes a rating to the filename of rated videos when mpv.net shuts down.
|
||||||
|
|
||||||
|
// The input.conf defaults contain key bindings for this extension to set ratings.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using mpvnet;
|
using mpvnet;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace RatingExtension // the assembly name must end with 'Extension'
|
namespace RatingExtension // the assembly name must end with 'Extension'
|
||||||
{
|
{
|
||||||
@@ -15,8 +20,8 @@ namespace RatingExtension // the assembly name must end with 'Extension'
|
|||||||
|
|
||||||
public RatingExtension() // plugin initialization
|
public RatingExtension() // plugin initialization
|
||||||
{
|
{
|
||||||
mp.ClientMessage += ClientMessage; //handles keys defined in input.conf
|
core.ClientMessage += ClientMessage; //handles keys defined in input.conf
|
||||||
mp.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN
|
core.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
// handles MPV_EVENT_SHUTDOWN
|
// handles MPV_EVENT_SHUTDOWN
|
||||||
@@ -26,13 +31,13 @@ namespace RatingExtension // the assembly name must end with 'Extension'
|
|||||||
{
|
{
|
||||||
string filepath = i.Key;
|
string filepath = i.Key;
|
||||||
int rating = i.Value;
|
int rating = i.Value;
|
||||||
if (String.IsNullOrEmpty(filepath) || ! File.Exists(filepath))
|
if (String.IsNullOrEmpty(filepath) || !File.Exists(filepath))
|
||||||
return;
|
return;
|
||||||
string basename = Path.GetFileNameWithoutExtension(filepath);
|
string basename = Path.GetFileNameWithoutExtension(filepath);
|
||||||
|
|
||||||
for (int x = 0; x < 6; x++)
|
for (int x = 0; x < 6; x++)
|
||||||
if (basename.Contains(" (" + x.ToString() + "stars)"))
|
if (basename.Contains(" (" + x + "stars)"))
|
||||||
basename = basename.Replace(" (" + x.ToString() + "stars)", "");
|
basename = basename.Replace(" (" + x + "stars)", "");
|
||||||
|
|
||||||
basename += $" ({rating}stars)";
|
basename += $" ({rating}stars)";
|
||||||
string newPath = Path.Combine(Path.GetDirectoryName(filepath), basename + Path.GetExtension(filepath));
|
string newPath = Path.Combine(Path.GetDirectoryName(filepath), basename + Path.GetExtension(filepath));
|
||||||
@@ -49,10 +54,10 @@ namespace RatingExtension // the assembly name must end with 'Extension'
|
|||||||
|
|
||||||
if (int.TryParse(args[1], out int rating))
|
if (int.TryParse(args[1], out int rating))
|
||||||
{
|
{
|
||||||
string path = mp.get_property_string("path");
|
string path = core.get_property_string("path");
|
||||||
if (!File.Exists(path)) return;
|
if (!File.Exists(path)) return;
|
||||||
Dic[path] = rating;
|
Dic[path] = rating;
|
||||||
mp.commandv("show-text", $"Rating: {rating}");
|
core.commandv("show-text", $"Rating: {rating}");
|
||||||
}
|
}
|
||||||
else if (args[1] == "about")
|
else if (args[1] == "about")
|
||||||
Msg.Show("Rating Extension", "This extension writes a rating to the filename of rated videos when mpv.net shuts down.\n\nThe input.conf defaults contain key bindings for this extension to set ratings.");
|
Msg.Show("Rating Extension", "This extension writes a rating to the filename of rated videos when mpv.net shuts down.\n\nThe input.conf defaults contain key bindings for this extension to set ratings.");
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>RatingExtension</RootNamespace>
|
<RootNamespace>RatingExtension</RootNamespace>
|
||||||
<AssemblyName>RatingExtension</AssemblyName>
|
<AssemblyName>RatingExtension</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
|
|||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("RatingExtension")]
|
[assembly: AssemblyTitle("RatingExtension")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("RatingExtension")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
||||||
[assembly: AssemblyProduct("RatingExtension")]
|
[assembly: AssemblyProduct("RatingExtension")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2017-2019 Frank Skare (stax76)")]
|
[assembly: AssemblyCopyright("Copyright (C) 2017-2020 Frank Skare (stax76)")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,54 @@
|
|||||||
//'This extension implements the C# scripting feature of mpv.net which
|
|
||||||
|
// This extension implements the C# scripting feature of mpv.net which
|
||||||
// is based on CS-Script (https://www.cs-script.net).
|
// is based on CS-Script (https://www.cs-script.net).
|
||||||
|
|
||||||
// Furthermore the extension is used to code and debug scripts
|
// I also use this extension to code scripts in order to have full
|
||||||
// because writing script code without debugger is not an option :-)
|
// code completion and debugger support, once the script code is
|
||||||
|
// finished I move it from the extension to a standalone script.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
using mpvnet;
|
using mpvnet;
|
||||||
using CSScriptLibrary;
|
using CSScriptLibrary;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace ScriptingExtension // the file name of extensions must end with 'Extension'
|
// the file name of extensions must end with 'Extension'
|
||||||
|
namespace ScriptingExtension
|
||||||
{
|
{
|
||||||
[Export(typeof(IExtension))]
|
[Export(typeof(IExtension))]
|
||||||
public class ScriptingExtension : IExtension
|
public class ScriptingExtension : IExtension
|
||||||
{
|
{
|
||||||
Script Script;
|
//Script Script;
|
||||||
|
|
||||||
public ScriptingExtension()
|
public ScriptingExtension()
|
||||||
{
|
{
|
||||||
//Script = new Script();
|
//Script = new Script();
|
||||||
List<string> scriptFiles = new List<string>();
|
List<string> files = new List<string>();
|
||||||
|
|
||||||
if (Directory.Exists(mp.ConfigFolder + "scripts"))
|
if (Directory.Exists(core.ConfigFolder + "scripts-cs"))
|
||||||
scriptFiles.AddRange(Directory.GetFiles(mp.ConfigFolder + "scripts", "*.cs"));
|
files.AddRange(Directory.GetFiles(core.ConfigFolder + "scripts-cs", "*.cs"));
|
||||||
|
|
||||||
if (Directory.Exists(Application.StartupPath + "\\scripts"))
|
if (Directory.Exists(Folder.Startup + "scripts"))
|
||||||
scriptFiles.AddRange(Directory.GetFiles(Application.StartupPath + "\\scripts", "*.cs"));
|
foreach (string path in Directory.GetFiles(Folder.Startup + "scripts", "*.cs"))
|
||||||
|
files.AddRange(Directory.GetFiles(Folder.Startup + "scripts", "*.cs"));
|
||||||
|
|
||||||
|
if (files.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (scriptFiles.Count == 0) return;
|
|
||||||
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;
|
CSScriptLibrary.CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;
|
||||||
|
|
||||||
foreach (var i in scriptFiles)
|
foreach (string file in files)
|
||||||
{
|
{
|
||||||
try {
|
try
|
||||||
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(i));
|
{
|
||||||
} catch (Exception e) {
|
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(file));
|
||||||
Msg.ShowException(e);
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
App.ShowException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>ScriptingExtension</RootNamespace>
|
<RootNamespace>ScriptingExtension</RootNamespace>
|
||||||
<AssemblyName>ScriptingExtension</AssemblyName>
|
<AssemblyName>ScriptingExtension</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,40 +1,19 @@
|
|||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
using System.IO;
|
||||||
|
|
||||||
using mpvnet;
|
using mpvnet;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
class Script
|
class Script
|
||||||
{
|
{
|
||||||
MainForm Form;
|
|
||||||
|
|
||||||
bool WasPlaying;
|
|
||||||
bool WasPaused;
|
|
||||||
|
|
||||||
public Script()
|
public Script()
|
||||||
{
|
{
|
||||||
Form = MainForm.Instance;
|
core.Shutdown += Shutdown;
|
||||||
Form.Resize += Form_Resize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Form_Resize(object sender, EventArgs e)
|
void Shutdown()
|
||||||
{
|
{
|
||||||
if (Form.WindowState == FormWindowState.Minimized)
|
foreach (string file in Directory.GetFiles(@"C:\Users\frank\Desktop\aaa"))
|
||||||
{
|
File.Delete(file);
|
||||||
WasPlaying = mp.get_property_string("pause") == "no";
|
|
||||||
|
|
||||||
if (WasPlaying)
|
|
||||||
{
|
|
||||||
mp.command("set pause yes");
|
|
||||||
WasPaused = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (WasPaused)
|
|
||||||
{
|
|
||||||
mp.command("set pause no");
|
|
||||||
WasPaused = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BIN
img/Avatar.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 628 KiB |
BIN
img/Terminal.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
img/mpvnet.ico
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
BIN
img/mpvnet.pdn
BIN
img/mpvnet.png
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
@@ -11,40 +11,32 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingExtension", "exten
|
|||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.ActiveCfg = Debug|x64
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.Build.0 = Debug|x64
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.Build.0 = Debug|x64
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.ActiveCfg = Debug|x86
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.Build.0 = Debug|x86
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.Build.0 = Debug|x86
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.ActiveCfg = Release|x64
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.ActiveCfg = Release|x64
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.Build.0 = Release|x64
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.Build.0 = Release|x64
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.ActiveCfg = Release|x86
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.ActiveCfg = Release|x86
|
||||||
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.Build.0 = Release|x86
|
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.Build.0 = Release|x86
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.ActiveCfg = Debug|x64
|
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.Build.0 = Debug|x64
|
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.Build.0 = Debug|x64
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.ActiveCfg = Debug|x86
|
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.Build.0 = Debug|x86
|
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.Build.0 = Debug|x86
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.ActiveCfg = Release|x64
|
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.ActiveCfg = Release|x64
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.Build.0 = Release|x64
|
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.Build.0 = Release|x64
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.ActiveCfg = Release|x86
|
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.ActiveCfg = Release|x86
|
||||||
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.Build.0 = Release|x86
|
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.Build.0 = Release|x86
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x64.ActiveCfg = Debug|x64
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x64.Build.0 = Debug|x64
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x64.Build.0 = Debug|x64
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x86.ActiveCfg = Debug|x86
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x86.Build.0 = Debug|x86
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Debug|x86.Build.0 = Debug|x86
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x64.ActiveCfg = Release|x64
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x64.Build.0 = Release|x64
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x64.Build.0 = Release|x64
|
||||||
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x86.ActiveCfg = Release|x86
|
{94255EF2-C823-4D82-9017-0E993CC0F5A1}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
<configSections>
|
<configSections>
|
||||||
</configSections>
|
</configSections>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||||
</startup>
|
</startup>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
<UserControl x:Class="Controls.SearchTextBoxUserControl"
|
|
||||||
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"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
<Grid x:Name="SearchTextBoxUserControl1" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
|
|
||||||
<TextBlock x:Name="HintTextBlock" Margin="5,2" Text="Find a setting" Foreground="LightSteelBlue" VerticalAlignment="Center" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
|
|
||||||
<TextBox Name="SearchTextBox" Height="25" Padding="1,2,0,0" BorderThickness="2" Background="Transparent" TextChanged="SearchTextBox_TextChanged" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CaretBrush="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
|
|
||||||
<Button x:Name="SearchClearButton" Background="Transparent" HorizontalAlignment="Right" Margin="2,0,4,0" FontSize="10" Width="17" Height="17" Visibility="Hidden" Click="SearchClearButton_Click" FontFamily="Marlett" Foreground="{Binding Path=Foreground2, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">r</Button>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -15,8 +16,10 @@ namespace DynamicGUI
|
|||||||
public static List<SettingBase> LoadSettings(string content)
|
public static List<SettingBase> LoadSettings(string content)
|
||||||
{
|
{
|
||||||
TomlTable table;
|
TomlTable table;
|
||||||
|
|
||||||
using (StringReader reader = new StringReader(content))
|
using (StringReader reader = new StringReader(content))
|
||||||
table = TOML.Parse(reader);
|
table = TOML.Parse(reader);
|
||||||
|
|
||||||
List<SettingBase> settingsList = new List<SettingBase>();
|
List<SettingBase> settingsList = new List<SettingBase>();
|
||||||
|
|
||||||
foreach (TomlTable setting in table["settings"])
|
foreach (TomlTable setting in table["settings"])
|
||||||
@@ -34,12 +37,15 @@ namespace DynamicGUI
|
|||||||
{
|
{
|
||||||
var opt = new OptionSettingOption();
|
var opt = new OptionSettingOption();
|
||||||
opt.Name = option["name"];
|
opt.Name = option["name"];
|
||||||
|
|
||||||
if (option.HasKey("help"))
|
if (option.HasKey("help"))
|
||||||
opt.Help = option["help"];
|
opt.Help = option["help"];
|
||||||
|
|
||||||
if (option.HasKey("text"))
|
if (option.HasKey("text"))
|
||||||
opt.Text = option["text"];
|
opt.Text = option["text"];
|
||||||
else if (opt.Name == optionSetting.Default)
|
else if (opt.Name == optionSetting.Default)
|
||||||
opt.Text = opt.Name + " (Default)";
|
opt.Text = opt.Name + " (Default)";
|
||||||
|
|
||||||
opt.OptionSetting = optionSetting;
|
opt.OptionSetting = optionSetting;
|
||||||
optionSetting.Options.Add(opt);
|
optionSetting.Options.Add(opt);
|
||||||
}
|
}
|
||||||
@@ -52,6 +58,7 @@ namespace DynamicGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
baseSetting.Name = setting["name"];
|
baseSetting.Name = setting["name"];
|
||||||
|
baseSetting.File = setting["file"];
|
||||||
baseSetting.Filter = setting["filter"];
|
baseSetting.Filter = setting["filter"];
|
||||||
|
|
||||||
if (setting.HasKey("help")) baseSetting.Help = setting["help"];
|
if (setting.HasKey("help")) baseSetting.Help = setting["help"];
|
||||||
@@ -65,9 +72,22 @@ namespace DynamicGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ConfItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Value { get; set; } = "";
|
||||||
|
public string Comment { get; set; } = "";
|
||||||
|
public string LineComment { get; set; } = "";
|
||||||
|
public string Section { get; set; } = "";
|
||||||
|
public string File { get; set; } = "";
|
||||||
|
public bool IsSectionItem { get; set; }
|
||||||
|
public SettingBase SettingBase { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class SettingBase
|
public abstract class SettingBase
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
public string File { get; set; }
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
public string Help { get; set; }
|
public string Help { get; set; }
|
||||||
public string Default { get; set; }
|
public string Default { get; set; }
|
||||||
@@ -75,6 +95,7 @@ namespace DynamicGUI
|
|||||||
public string Filter { get; set; }
|
public string Filter { get; set; }
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
public int Width { get; set; }
|
public int Width { get; set; }
|
||||||
|
public ConfItem ConfItem { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StringSetting : SettingBase
|
public class StringSetting : SettingBase
|
||||||
@@ -93,7 +114,7 @@ namespace DynamicGUI
|
|||||||
|
|
||||||
public OptionSetting OptionSetting { get; set; }
|
public OptionSetting OptionSetting { get; set; }
|
||||||
|
|
||||||
private string _Text;
|
string _Text;
|
||||||
|
|
||||||
public string Text
|
public string Text
|
||||||
{
|
{
|
||||||
@@ -104,7 +125,10 @@ namespace DynamicGUI
|
|||||||
public bool Checked
|
public bool Checked
|
||||||
{
|
{
|
||||||
get => OptionSetting.Value == Name ;
|
get => OptionSetting.Value == Name ;
|
||||||
set { if (value) OptionSetting.Value = Name; }
|
set {
|
||||||
|
if (value)
|
||||||
|
OptionSetting.Value = Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Visibility Visibility
|
public Visibility Visibility
|
||||||
@@ -121,7 +145,7 @@ namespace DynamicGUI
|
|||||||
|
|
||||||
public class HyperlinkEx : Hyperlink
|
public class HyperlinkEx : Hyperlink
|
||||||
{
|
{
|
||||||
private void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
void HyperLinkEx_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||||
{
|
{
|
||||||
Process.Start(e.Uri.AbsoluteUri);
|
Process.Start(e.Uri.AbsoluteUri);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,22 +4,58 @@
|
|||||||
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:DynamicGUI"
|
xmlns:local="clr-namespace:DynamicGUI"
|
||||||
|
xmlns:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
|
d:DesignHeight="450"
|
||||||
|
d:DesignWidth="800">
|
||||||
|
|
||||||
<Grid Margin="20,0">
|
<Grid Margin="20,0">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBox x:Name="TitleTextBox" FontSize="24" Margin="0,10" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
<TextBox x:Name="TitleTextBox"
|
||||||
|
FontSize="24"
|
||||||
|
Margin="0,10"
|
||||||
|
BorderThickness="0"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Foreground="{x:Static UI:Theme.Heading}"
|
||||||
|
Background="{x:Static UI:Theme.Background}" />
|
||||||
|
|
||||||
<ItemsControl x:Name="ItemsControl">
|
<ItemsControl x:Name="ItemsControl">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<WrapPanel Orientation="Vertical">
|
<WrapPanel Orientation="Vertical">
|
||||||
<RadioButton x:Name="RadioButton" VerticalContentAlignment="Center" IsChecked="{Binding Checked}" GroupName="{Binding OptionSetting.Name}" Content="{Binding Text}" FontSize="16" FontWeight="Normal" VerticalAlignment="Top" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></RadioButton>
|
<RadioButton x:Name="RadioButton"
|
||||||
<TextBox x:Name="ItemHelpTextBox" TextWrapping="WrapWithOverflow" Text="{Binding Help}" Visibility="{Binding Visibility}" Margin="10,0,0,0" BorderThickness="0" IsReadOnly="True" Padding="7,0,0,0" MinHeight="0" Foreground="{Binding Path=Foreground2, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
VerticalContentAlignment="Center"
|
||||||
|
IsChecked="{Binding Checked}"
|
||||||
|
GroupName="{Binding OptionSetting.Name}"
|
||||||
|
Content="{Binding Text}"
|
||||||
|
FontSize="16"
|
||||||
|
FontWeight="Normal"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"/>
|
||||||
|
|
||||||
|
<TextBox x:Name="ItemHelpTextBox"
|
||||||
|
TextWrapping="WrapWithOverflow"
|
||||||
|
Text="{Binding Help}"
|
||||||
|
Visibility="{Binding Visibility}"
|
||||||
|
Margin="10,0,0,0" BorderThickness="0"
|
||||||
|
IsReadOnly="True" Padding="7,0,0,0"
|
||||||
|
MinHeight="0"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground2}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"/>
|
||||||
|
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Margin="0,10,0,0" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"></TextBox>
|
|
||||||
|
<TextBox x:Name="HelpTextBox"
|
||||||
|
TextWrapping="WrapWithOverflow"
|
||||||
|
BorderThickness="0"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Margin="0,10,0,0"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"/>
|
||||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|||||||
@@ -1,35 +1,42 @@
|
|||||||
using System.Windows;
|
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
namespace DynamicGUI
|
namespace DynamicGUI
|
||||||
{
|
{
|
||||||
public partial class OptionSettingControl : UserControl, ISettingControl
|
public partial class OptionSettingControl : UserControl, ISettingControl
|
||||||
{
|
{
|
||||||
private OptionSetting OptionSetting;
|
OptionSetting OptionSetting;
|
||||||
|
|
||||||
public OptionSettingControl(OptionSetting optionSetting)
|
public OptionSettingControl(OptionSetting optionSetting)
|
||||||
{
|
{
|
||||||
OptionSetting = optionSetting;
|
OptionSetting = optionSetting;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
TitleTextBox.Text = optionSetting.Name;
|
TitleTextBox.Text = optionSetting.Name;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(optionSetting.Help))
|
if (string.IsNullOrEmpty(optionSetting.Help))
|
||||||
HelpTextBox.Visibility = Visibility.Collapsed;
|
HelpTextBox.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
HelpTextBox.Text = optionSetting.Help;
|
HelpTextBox.Text = optionSetting.Help;
|
||||||
ItemsControl.ItemsSource = optionSetting.Options;
|
ItemsControl.ItemsSource = optionSetting.Options;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(optionSetting.URL))
|
if (string.IsNullOrEmpty(optionSetting.URL))
|
||||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
Link.SetURL(optionSetting.URL);
|
Link.SetURL(optionSetting.URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _SearchableText;
|
string _SearchableText;
|
||||||
|
|
||||||
public string SearchableText {
|
public string SearchableText {
|
||||||
get {
|
get {
|
||||||
if (_SearchableText is null)
|
if (_SearchableText is null)
|
||||||
{
|
{
|
||||||
_SearchableText = TitleTextBox.Text + HelpTextBox.Text;
|
_SearchableText = TitleTextBox.Text + HelpTextBox.Text;
|
||||||
|
|
||||||
foreach (var i in OptionSetting.Options)
|
foreach (var i in OptionSetting.Options)
|
||||||
_SearchableText += i.Text + i.Help + i.Name;
|
_SearchableText += i.Text + i.Help + i.Name;
|
||||||
|
|
||||||
_SearchableText = _SearchableText.ToLower();
|
_SearchableText = _SearchableText.ToLower();
|
||||||
}
|
}
|
||||||
return _SearchableText;
|
return _SearchableText;
|
||||||
|
|||||||
@@ -4,21 +4,52 @@
|
|||||||
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:DynamicGUI"
|
xmlns:local="clr-namespace:DynamicGUI"
|
||||||
|
xmlns:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800">
|
d:DesignWidth="800">
|
||||||
|
|
||||||
<Grid Margin="20,0">
|
<Grid Margin="20,0">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBox x:Name="TitleTextBox" FontSize="24" Margin="0,10" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
<TextBox x:Name="TitleTextBox"
|
||||||
|
FontSize="24"
|
||||||
|
Margin="0,10"
|
||||||
|
BorderThickness="0"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Foreground="{x:Static UI:Theme.Heading}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"/>
|
||||||
|
|
||||||
<Grid Margin="0,0,0,10">
|
<Grid Margin="0,0,0,10">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBox x:Name="ValueTextBox" Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="150" HorizontalAlignment="Left" Height="20" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CaretBrush="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" TextChanged="ValueTextBox_TextChanged"/>
|
<TextBox x:Name="ValueTextBox"
|
||||||
<Button x:Name="Button" Height="20" Grid.Column="1" Visibility="{Binding Path=Text, ElementName=StringSettingControl1}" Margin="5,0,0,0" Width="20" Click="Button_Click">...</Button>
|
Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Width="150"
|
||||||
|
Height="20"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
CaretBrush="{x:Static UI:Theme.Foreground}"
|
||||||
|
TextChanged="ValueTextBox_TextChanged"/>
|
||||||
|
|
||||||
|
<Button x:Name="Button"
|
||||||
|
Height="20"
|
||||||
|
Grid.Column="1"
|
||||||
|
Visibility="{Binding Path=Text, ElementName=StringSettingControl1}"
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
Width="20"
|
||||||
|
Click="Button_Click">...</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>
|
|
||||||
|
<TextBox x:Name="HelpTextBox"
|
||||||
|
TextWrapping="WrapWithOverflow"
|
||||||
|
BorderThickness="0"
|
||||||
|
IsReadOnly="True"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"/>
|
||||||
|
|
||||||
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
<TextBlock x:Name="LinkTextBlock" Margin="0,10">
|
||||||
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
<local:HyperlinkEx x:Name="Link"></local:HyperlinkEx>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -10,7 +10,7 @@ namespace DynamicGUI
|
|||||||
{
|
{
|
||||||
public partial class StringSettingControl : UserControl, ISettingControl
|
public partial class StringSettingControl : UserControl, ISettingControl
|
||||||
{
|
{
|
||||||
private StringSetting StringSetting;
|
StringSetting StringSetting;
|
||||||
|
|
||||||
public StringSettingControl(StringSetting stringSetting)
|
public StringSettingControl(StringSetting stringSetting)
|
||||||
{
|
{
|
||||||
@@ -19,21 +19,26 @@ namespace DynamicGUI
|
|||||||
TitleTextBox.Text = stringSetting.Name;
|
TitleTextBox.Text = stringSetting.Name;
|
||||||
HelpTextBox.Text = stringSetting.Help;
|
HelpTextBox.Text = stringSetting.Help;
|
||||||
ValueTextBox.Text = StringSetting.Value;
|
ValueTextBox.Text = StringSetting.Value;
|
||||||
|
|
||||||
if (StringSetting.Width > 0)
|
if (StringSetting.Width > 0)
|
||||||
ValueTextBox.Width = StringSetting.Width;
|
ValueTextBox.Width = StringSetting.Width;
|
||||||
|
|
||||||
if (StringSetting.Type != "folder" && StringSetting.Type != "color")
|
if (StringSetting.Type != "folder" && StringSetting.Type != "color")
|
||||||
Button.Visibility = Visibility.Hidden;
|
Button.Visibility = Visibility.Hidden;
|
||||||
|
|
||||||
Link.SetURL(StringSetting.URL);
|
Link.SetURL(StringSetting.URL);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(stringSetting.URL))
|
if (string.IsNullOrEmpty(stringSetting.URL))
|
||||||
LinkTextBlock.Visibility = Visibility.Collapsed;
|
LinkTextBlock.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _SearchableText;
|
string _SearchableText;
|
||||||
|
|
||||||
public string SearchableText {
|
public string SearchableText {
|
||||||
get {
|
get {
|
||||||
if (_SearchableText is null)
|
if (_SearchableText is null)
|
||||||
_SearchableText = (TitleTextBox.Text + HelpTextBox.Text +ValueTextBox.Text).ToLower();
|
_SearchableText = (TitleTextBox.Text + HelpTextBox.Text +ValueTextBox.Text).ToLower();
|
||||||
|
|
||||||
return _SearchableText;
|
return _SearchableText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,7 +52,7 @@ namespace DynamicGUI
|
|||||||
set => StringSetting.Value = value;
|
set => StringSetting.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Button_Click(object sender, RoutedEventArgs e)
|
void Button_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
switch (StringSetting.Type)
|
switch (StringSetting.Type)
|
||||||
{
|
{
|
||||||
@@ -56,29 +61,33 @@ namespace DynamicGUI
|
|||||||
{
|
{
|
||||||
d.Description = "Choose a folder.";
|
d.Description = "Choose a folder.";
|
||||||
d.SelectedPath = ValueTextBox.Text;
|
d.SelectedPath = ValueTextBox.Text;
|
||||||
|
|
||||||
if (d.ShowDialog() == WinForms.DialogResult.OK)
|
if (d.ShowDialog() == WinForms.DialogResult.OK)
|
||||||
ValueTextBox.Text = d.SelectedPath;
|
ValueTextBox.Text = d.SelectedPath;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "color":
|
case "color":
|
||||||
using (var d = new WinForms.ColorDialog())
|
using (var dialog = new WinForms.ColorDialog())
|
||||||
|
{
|
||||||
|
dialog.FullOpen = true;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
d.FullOpen = true;
|
|
||||||
try {
|
|
||||||
if (!string.IsNullOrEmpty(ValueTextBox.Text))
|
if (!string.IsNullOrEmpty(ValueTextBox.Text))
|
||||||
{
|
{
|
||||||
Color col = GetColor(ValueTextBox.Text);
|
Color col = GetColor(ValueTextBox.Text);
|
||||||
d.Color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B);
|
dialog.Color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
if (d.ShowDialog() == WinForms.DialogResult.OK)
|
|
||||||
ValueTextBox.Text = "#" + d.Color.ToArgb().ToString("X8");
|
if (dialog.ShowDialog() == WinForms.DialogResult.OK)
|
||||||
|
ValueTextBox.Text = "#" + dialog.Color.ToArgb().ToString("X8");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValueTextBox_TextChanged(object sender, TextChangedEventArgs e) => Update();
|
void ValueTextBox_TextChanged(object sender, TextChangedEventArgs e) => Update();
|
||||||
|
|
||||||
Color GetColor(string value)
|
Color GetColor(string value)
|
||||||
{
|
{
|
||||||
@@ -102,7 +111,10 @@ namespace DynamicGUI
|
|||||||
if (StringSetting.Type == "color")
|
if (StringSetting.Type == "color")
|
||||||
{
|
{
|
||||||
Color c = Colors.Transparent;
|
Color c = Colors.Transparent;
|
||||||
if (ValueTextBox.Text != "") try { c = GetColor(ValueTextBox.Text); } catch {}
|
|
||||||
|
if (ValueTextBox.Text != "")
|
||||||
|
try { c = GetColor(ValueTextBox.Text); } catch {}
|
||||||
|
|
||||||
ValueTextBox.Background = new SolidColorBrush(c);
|
ValueTextBox.Background = new SolidColorBrush(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
205
mpv.net/Misc/App.cs
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
using UI;
|
||||||
|
|
||||||
|
using static libmpv;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace mpvnet
|
||||||
|
{
|
||||||
|
public static class App
|
||||||
|
{
|
||||||
|
public static string[] VideoTypes { get; } = "264 265 asf avc avi avs flv h264 h265 hevc m2ts m2v m4v mkv mov mp4 mpeg mpg mpv mts ts vob vpy webm wmv y4m".Split(' ');
|
||||||
|
public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(' ');
|
||||||
|
public static string[] ImageTypes { get; } = {"jpg", "bmp", "gif", "png"};
|
||||||
|
public static string[] SubtitleTypes { get; } = { "srt", "ass", "idx", "sup", "ttxt", "ssa", "smi" };
|
||||||
|
|
||||||
|
public static string RegPath { get; } = @"HKCU\Software\" + Application.ProductName;
|
||||||
|
public static string ConfPath { get => core.ConfigFolder + "mpvnet.conf"; }
|
||||||
|
public static string ProcessInstance { get; set; } = "single";
|
||||||
|
public static string DarkMode { get; set; } = "always";
|
||||||
|
public static string DarkTheme { get; set; } = "dark";
|
||||||
|
public static string LightTheme { get; set; } = "light";
|
||||||
|
public static string StartSize { get; set; } = "previous";
|
||||||
|
|
||||||
|
public static bool RememberPosition { get; set; }
|
||||||
|
public static bool DebugMode { get; set; }
|
||||||
|
public static bool IsStartedFromTerminal { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
|
||||||
|
public static bool RememberVolume { get; set; } = true;
|
||||||
|
public static bool AutoLoadFolder { get; set; } = true;
|
||||||
|
public static bool Queue { get; set; }
|
||||||
|
public static bool UpdateCheck { get; set; }
|
||||||
|
|
||||||
|
public static int StartThreshold { get; set; } = 1500;
|
||||||
|
public static int RecentCount { get; set; } = 15;
|
||||||
|
|
||||||
|
public static float MinimumAspectRatio { get; set; } = 1.2f;
|
||||||
|
|
||||||
|
public static Extension Extension { get; set; }
|
||||||
|
|
||||||
|
public static bool IsDarkMode {
|
||||||
|
get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
string dummy = core.ConfigFolder;
|
||||||
|
var dummy2 = core.Conf;
|
||||||
|
|
||||||
|
foreach (var i in Conf)
|
||||||
|
ProcessProperty(i.Key, i.Value, true);
|
||||||
|
|
||||||
|
if (App.DebugMode)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string filePath = core.ConfigFolder + "mpvnet-debug.log";
|
||||||
|
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
File.Delete(filePath);
|
||||||
|
|
||||||
|
Trace.Listeners.Add(new TextWriterTraceListener(filePath));
|
||||||
|
Trace.AutoFlush = true;
|
||||||
|
|
||||||
|
//if (App.DebugMode)
|
||||||
|
// Trace.WriteLine("");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Msg.ShowException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string themeContent = null;
|
||||||
|
|
||||||
|
if (File.Exists(core.ConfigFolder + "theme.conf"))
|
||||||
|
themeContent = File.ReadAllText(core.ConfigFolder + "theme.conf");
|
||||||
|
|
||||||
|
Theme.Init(
|
||||||
|
themeContent,
|
||||||
|
Properties.Resources.theme,
|
||||||
|
IsDarkMode ? DarkTheme : LightTheme);
|
||||||
|
|
||||||
|
core.Shutdown += Shutdown;
|
||||||
|
core.Initialized += Initialized;
|
||||||
|
core.LogMessage += ShowFatalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowFatalError(mpv_log_level level, string msg)
|
||||||
|
{
|
||||||
|
if (!App.IsStartedFromTerminal && level == mpv_log_level.MPV_LOG_LEVEL_FATAL)
|
||||||
|
Msg.ShowError(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RunAction(Action action)
|
||||||
|
{
|
||||||
|
Task.Run(() => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action.Invoke();
|
||||||
|
Debug.WriteLine(Environment.TickCount);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ShowException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowException(object obj)
|
||||||
|
{
|
||||||
|
if (obj is Exception e)
|
||||||
|
{
|
||||||
|
if (App.IsStartedFromTerminal)
|
||||||
|
ConsoleHelp.WriteError(e.ToString());
|
||||||
|
else
|
||||||
|
Msg.ShowException(e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (App.IsStartedFromTerminal)
|
||||||
|
ConsoleHelp.WriteError(obj.ToString());
|
||||||
|
else
|
||||||
|
Msg.ShowError(obj.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowError(string title, string msg)
|
||||||
|
{
|
||||||
|
if (App.IsStartedFromTerminal)
|
||||||
|
{
|
||||||
|
ConsoleHelp.WriteError(title);
|
||||||
|
ConsoleHelp.WriteError(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Msg.ShowError(title, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Initialized()
|
||||||
|
{
|
||||||
|
if (RememberVolume)
|
||||||
|
{
|
||||||
|
core.set_property_int("volume", RegistryHelp.GetInt(App.RegPath, "Volume", 70));
|
||||||
|
core.set_property_string("mute", RegistryHelp.GetString(App.RegPath, "Mute", "no"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Shutdown()
|
||||||
|
{
|
||||||
|
if (RememberVolume)
|
||||||
|
{
|
||||||
|
RegistryHelp.SetValue(App.RegPath, "Volume", core.get_property_int("volume"));
|
||||||
|
RegistryHelp.SetValue(App.RegPath, "Mute", core.get_property_string("mute"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<string, string> _Conf;
|
||||||
|
|
||||||
|
public static Dictionary<string, string> Conf {
|
||||||
|
get {
|
||||||
|
if (_Conf == null)
|
||||||
|
{
|
||||||
|
_Conf = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
if (File.Exists(ConfPath))
|
||||||
|
foreach (string i in File.ReadAllLines(ConfPath))
|
||||||
|
if (i.Contains("=") && !i.StartsWith("#"))
|
||||||
|
_Conf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
||||||
|
}
|
||||||
|
return _Conf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ProcessProperty(string name, string value, bool writeError = false)
|
||||||
|
{
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "remember-position": RememberPosition = value == "yes"; return true;
|
||||||
|
case "debug-mode": DebugMode = value == "yes"; return true;
|
||||||
|
case "remember-volume": RememberVolume = value == "yes"; return true;
|
||||||
|
case "queue": Queue = value == "yes"; return true;
|
||||||
|
case "auto-load-folder": AutoLoadFolder = value == "yes"; return true;
|
||||||
|
case "update-check": UpdateCheck = value == "yes"; return true;
|
||||||
|
case "start-size": StartSize = value; return true;
|
||||||
|
case "process-instance": ProcessInstance = value; return true;
|
||||||
|
case "dark-mode": DarkMode = value; return true;
|
||||||
|
case "start-threshold": StartThreshold = value.Int(); return true;
|
||||||
|
case "recent-count": RecentCount = value.Int(); return true;
|
||||||
|
case "minimum-aspect-ratio": MinimumAspectRatio = value.Float(); return true;
|
||||||
|
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
|
||||||
|
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
|
||||||
|
default:
|
||||||
|
if (writeError)
|
||||||
|
ConsoleHelp.WriteError($"unknown mpvnet.conf property: {name}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -8,19 +9,26 @@ using System.Windows.Interop;
|
|||||||
|
|
||||||
using VB = Microsoft.VisualBasic;
|
using VB = Microsoft.VisualBasic;
|
||||||
|
|
||||||
|
using static NewLine;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
public class Command
|
public class Commands
|
||||||
{
|
{
|
||||||
public static void Execute(string id, string[] args)
|
public static void Execute(string id, string[] args)
|
||||||
{
|
{
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case "manage-file-associations": ManageFileAssociations(); break;
|
case "open-files": OpenFiles(args); break;
|
||||||
|
case "update-check": UpdateCheck.CheckOnline(true); break;
|
||||||
|
case "open-url": OpenURL(); break;
|
||||||
|
case "open-optical-media": Open_DVD_Or_BD_Folder(); break;
|
||||||
|
case "manage-file-associations": // deprecated 2019
|
||||||
|
case "show-setup-dialog": ShowDialog(typeof(SetupWindow)); break;
|
||||||
case "cycle-audio": CycleAudio(); break;
|
case "cycle-audio": CycleAudio(); break;
|
||||||
case "load-audio": LoadAudio(); break;
|
case "load-audio": LoadAudio(); break;
|
||||||
case "load-sub": LoadSubtitle(); break;
|
case "load-sub": LoadSubtitle(); break;
|
||||||
case "open-url": OpenURL(); break;
|
|
||||||
case "execute-mpv-command": ExecuteMpvCommand(); break;
|
case "execute-mpv-command": ExecuteMpvCommand(); break;
|
||||||
case "show-history": ShowHistory(); break;
|
case "show-history": ShowHistory(); break;
|
||||||
case "show-media-search": ShowDialog(typeof(EverythingWindow)); break;
|
case "show-media-search": ShowDialog(typeof(EverythingWindow)); break;
|
||||||
@@ -28,16 +36,20 @@ namespace mpvnet
|
|||||||
case "show-about": ShowDialog(typeof(AboutWindow)); break;
|
case "show-about": ShowDialog(typeof(AboutWindow)); break;
|
||||||
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
|
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
|
||||||
case "show-input-editor": ShowDialog(typeof(InputWindow)); break;
|
case "show-input-editor": ShowDialog(typeof(InputWindow)); break;
|
||||||
case "open-conf-folder": Process.Start(mp.ConfigFolder); break;
|
case "open-conf-folder": Process.Start(core.ConfigFolder); break;
|
||||||
case "open-files": OpenFiles(args); break;
|
|
||||||
case "shell-execute": Process.Start(args[0]); break;
|
case "shell-execute": Process.Start(args[0]); break;
|
||||||
case "show-info": ShowInfo(); break;
|
case "show-info": ShowInfo(); break;
|
||||||
|
case "playlist-first": PlaylistFirst(); break;
|
||||||
|
case "playlist-last": PlaylistLast(); break;
|
||||||
|
case "show-profiles": ShowProfiles(); break;
|
||||||
|
case "show-properties": ShowProperties(); break;
|
||||||
|
case "show-commands": ShowCommands(); break;
|
||||||
case "add-files-to-playlist": OpenFiles("append"); break; // deprecated 2019
|
case "add-files-to-playlist": OpenFiles("append"); break; // deprecated 2019
|
||||||
default: Msg.ShowError($"No command '{id}' found."); break;
|
default: Msg.ShowError($"No command '{id}' found."); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InvokeOnMainThread(Action action) => MainForm.Instance.Invoke(action);
|
public static void InvokeOnMainThread(Action action) => MainForm.Instance.BeginInvoke(action);
|
||||||
|
|
||||||
public static void ShowDialog(Type winType)
|
public static void ShowDialog(Type winType)
|
||||||
{
|
{
|
||||||
@@ -62,20 +74,63 @@ namespace mpvnet
|
|||||||
InvokeOnMainThread(new Action(() => {
|
InvokeOnMainThread(new Action(() => {
|
||||||
using (var d = new OpenFileDialog() { Multiselect = true })
|
using (var d = new OpenFileDialog() { Multiselect = true })
|
||||||
if (d.ShowDialog() == DialogResult.OK)
|
if (d.ShowDialog() == DialogResult.OK)
|
||||||
mp.Load(d.FileNames, loadFolder, append);
|
core.LoadFiles(d.FileNames, loadFolder, append);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Open_DVD_Or_BD_Folder()
|
||||||
|
{
|
||||||
|
InvokeOnMainThread(new Action(() => {
|
||||||
|
using (var d = new FolderBrowserDialog())
|
||||||
|
{
|
||||||
|
d.Description = "Select a DVD or Blu-ray folder.";
|
||||||
|
d.ShowNewFolderButton = false;
|
||||||
|
|
||||||
|
if (d.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(d.SelectedPath + "\\BDMV"))
|
||||||
|
{
|
||||||
|
core.set_property_string("bluray-device", d.SelectedPath);
|
||||||
|
core.LoadFiles(new[] { @"bd://" }, false, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.set_property_string("dvd-device", d.SelectedPath);
|
||||||
|
core.LoadFiles(new[] { @"dvd://" }, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PlaylistFirst()
|
||||||
|
{
|
||||||
|
int pos = core.get_property_int("playlist-pos");
|
||||||
|
|
||||||
|
if (pos != 0)
|
||||||
|
core.set_property_int("playlist-pos", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PlaylistLast()
|
||||||
|
{
|
||||||
|
int pos = core.get_property_int("playlist-pos");
|
||||||
|
int count = core.get_property_int("playlist-count");
|
||||||
|
|
||||||
|
if (pos < count - 1)
|
||||||
|
core.set_property_int("playlist-pos", count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
public static void ShowHistory()
|
public static void ShowHistory()
|
||||||
{
|
{
|
||||||
var fp = mp.ConfigFolder + "history.txt";
|
if (File.Exists(core.ConfigFolder + "history.txt"))
|
||||||
|
Process.Start(core.ConfigFolder + "history.txt");
|
||||||
if (File.Exists(fp))
|
|
||||||
Process.Start(fp);
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
if (Msg.ShowQuestion("Create history.txt file in config folder?",
|
if (Msg.ShowQuestion("Create history.txt file in config folder?",
|
||||||
"mpv.net will write the date, time and filename of opened files to it.") == MsgResult.OK)
|
"mpv.net will write the date, time and filename of opened files to it.") == MsgResult.OK)
|
||||||
File.WriteAllText(fp, "");
|
|
||||||
|
File.WriteAllText(core.ConfigFolder + "history.txt", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowInfo()
|
public static void ShowInfo()
|
||||||
@@ -84,15 +139,19 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
string performer, title, album, genre, date, duration, text = "";
|
string performer, title, album, genre, date, duration, text = "";
|
||||||
long fileSize = 0;
|
long fileSize = 0;
|
||||||
string path = mp.get_property_string("path");
|
string path = core.get_property_string("path");
|
||||||
int width = mp.get_property_int("video-params/w");
|
|
||||||
int height = mp.get_property_int("video-params/h");
|
if (path.Contains("://"))
|
||||||
|
path = core.get_property_string("media-title");
|
||||||
|
|
||||||
|
int width = core.get_property_int("video-params/w");
|
||||||
|
int height = core.get_property_int("video-params/h");
|
||||||
|
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
{
|
{
|
||||||
fileSize = new FileInfo(path).Length;
|
fileSize = new FileInfo(path).Length;
|
||||||
|
|
||||||
if (App.AudioTypes.Contains(Path.GetExtension(path).ToLower().TrimStart('.')))
|
if (App.AudioTypes.Contains(path.ShortExt()))
|
||||||
{
|
{
|
||||||
using (MediaInfo mediaInfo = new MediaInfo(path))
|
using (MediaInfo mediaInfo = new MediaInfo(path))
|
||||||
{
|
{
|
||||||
@@ -110,13 +169,13 @@ namespace mpvnet
|
|||||||
if (date != "") text += "Year: " + date + "\n";
|
if (date != "") text += "Year: " + date + "\n";
|
||||||
if (duration != "") text += "Length: " + duration + "\n";
|
if (duration != "") text += "Length: " + duration + "\n";
|
||||||
text += "Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n";
|
text += "Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n";
|
||||||
text += "Type: " + Path.GetExtension(path).ToUpper().TrimStart('.');
|
text += "Type: " + path.ShortExt().ToUpper();
|
||||||
|
|
||||||
mp.commandv("show-text", text, "5000");
|
core.commandv("show-text", text, "5000");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (App.ImageTypes.Contains(Path.GetExtension(path).ToLower().TrimStart('.')))
|
else if (App.ImageTypes.Contains(path.ShortExt()))
|
||||||
{
|
{
|
||||||
using (MediaInfo mediaInfo = new MediaInfo(path))
|
using (MediaInfo mediaInfo = new MediaInfo(path))
|
||||||
{
|
{
|
||||||
@@ -124,20 +183,20 @@ namespace mpvnet
|
|||||||
"Width: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Width") + "\n" +
|
"Width: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Width") + "\n" +
|
||||||
"Height: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Height") + "\n" +
|
"Height: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Height") + "\n" +
|
||||||
"Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n" +
|
"Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n" +
|
||||||
"Type: " + Path.GetExtension(path).ToUpper().TrimStart('.');
|
"Type: " + path.ShortExt().ToUpper();
|
||||||
|
|
||||||
mp.commandv("show-text", text, "5000");
|
core.commandv("show-text", text, "5000");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeSpan position = TimeSpan.FromSeconds(mp.get_property_number("time-pos"));
|
TimeSpan position = TimeSpan.FromSeconds(core.get_property_number("time-pos"));
|
||||||
TimeSpan duration2 = TimeSpan.FromSeconds(mp.get_property_number("duration"));
|
TimeSpan duration2 = TimeSpan.FromSeconds(core.get_property_number("duration"));
|
||||||
string videoFormat = mp.get_property_string("video-format").ToUpper();
|
string videoFormat = core.get_property_string("video-format").ToUpper();
|
||||||
string audioCodec = mp.get_property_string("audio-codec-name").ToUpper();
|
string audioCodec = core.get_property_string("audio-codec-name").ToUpper();
|
||||||
|
|
||||||
text = PathHelp.GetFileName(path) + "\n" +
|
text = path.FileName() + "\n" +
|
||||||
FormatTime(position.TotalMinutes) + ":" +
|
FormatTime(position.TotalMinutes) + ":" +
|
||||||
FormatTime(position.Seconds) + " / " +
|
FormatTime(position.Seconds) + " / " +
|
||||||
FormatTime(duration2.TotalMinutes) + ":" +
|
FormatTime(duration2.TotalMinutes) + ":" +
|
||||||
@@ -145,26 +204,29 @@ namespace mpvnet
|
|||||||
$"{width} x {height}\n";
|
$"{width} x {height}\n";
|
||||||
|
|
||||||
if (fileSize > 0)
|
if (fileSize > 0)
|
||||||
text += Convert.ToInt32(fileSize / 1024.0 / 1024.0).ToString() + " MB\n";
|
text += Convert.ToInt32(fileSize / 1024.0 / 1024.0) + " MB\n";
|
||||||
|
|
||||||
text += $"{videoFormat}\n{audioCodec}";
|
text += $"{videoFormat}\n{audioCodec}";
|
||||||
|
|
||||||
mp.commandv("show-text", text, "5000");
|
core.commandv("show-text", text, "5000");
|
||||||
string FormatTime(double value) => ((int)value).ToString("00");
|
string FormatTime(double value) => ((int)value).ToString("00");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Msg.ShowException(e);
|
App.ShowException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ExecuteMpvCommand()
|
public static void ExecuteMpvCommand() // deprecated 2019
|
||||||
{
|
{
|
||||||
InvokeOnMainThread(new Action(() => {
|
InvokeOnMainThread(new Action(() => {
|
||||||
string command = VB.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegHelp.GetString(App.RegPath, "RecentExecutedCommand"));
|
string command = VB.Interaction.InputBox("Enter a mpv command to be executed.", "Execute Command", RegistryHelp.GetString(App.RegPath, "RecentExecutedCommand"));
|
||||||
if (string.IsNullOrEmpty(command)) return;
|
|
||||||
RegHelp.SetObject(App.RegPath, "RecentExecutedCommand", command);
|
if (string.IsNullOrEmpty(command))
|
||||||
mp.command(command, false);
|
return;
|
||||||
|
|
||||||
|
RegistryHelp.SetValue(App.RegPath, "RecentExecutedCommand", command);
|
||||||
|
core.command(command, false);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,12 +234,14 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
InvokeOnMainThread(new Action(() => {
|
InvokeOnMainThread(new Action(() => {
|
||||||
string clipboard = System.Windows.Forms.Clipboard.GetText();
|
string clipboard = System.Windows.Forms.Clipboard.GetText();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(clipboard) || (!clipboard.Contains("://") && !File.Exists(clipboard)) || clipboard.Contains("\n"))
|
if (string.IsNullOrEmpty(clipboard) || (!clipboard.Contains("://") && !File.Exists(clipboard)) || clipboard.Contains("\n"))
|
||||||
{
|
{
|
||||||
Msg.ShowError("The clipboard does not contain a valid URL or file, URLs have to contain :// and are not allowed to contain a newline character.");
|
App.ShowError("No URL found", "The clipboard does not contain a valid URL or file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mp.Load(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control));
|
|
||||||
|
core.LoadFiles(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,12 +250,16 @@ namespace mpvnet
|
|||||||
InvokeOnMainThread(new Action(() => {
|
InvokeOnMainThread(new Action(() => {
|
||||||
using (var d = new OpenFileDialog())
|
using (var d = new OpenFileDialog())
|
||||||
{
|
{
|
||||||
string path = mp.get_property_string("path");
|
string path = core.get_property_string("path");
|
||||||
if (File.Exists(path)) d.InitialDirectory = Path.GetDirectoryName(path);
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
d.InitialDirectory = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
d.Multiselect = true;
|
d.Multiselect = true;
|
||||||
|
|
||||||
if (d.ShowDialog() == DialogResult.OK)
|
if (d.ShowDialog() == DialogResult.OK)
|
||||||
foreach (string i in d.FileNames)
|
foreach (string filename in d.FileNames)
|
||||||
mp.commandv("sub-add", i);
|
core.commandv("sub-add", filename);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -201,60 +269,98 @@ namespace mpvnet
|
|||||||
InvokeOnMainThread(new Action(() => {
|
InvokeOnMainThread(new Action(() => {
|
||||||
using (var d = new OpenFileDialog())
|
using (var d = new OpenFileDialog())
|
||||||
{
|
{
|
||||||
string path = mp.get_property_string("path");
|
string path = core.get_property_string("path");
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
d.InitialDirectory = Path.GetDirectoryName(path);
|
d.InitialDirectory = Path.GetDirectoryName(path);
|
||||||
d.Multiselect = true;
|
d.Multiselect = true;
|
||||||
|
|
||||||
if (d.ShowDialog() == DialogResult.OK)
|
if (d.ShowDialog() == DialogResult.OK)
|
||||||
foreach (string i in d.FileNames)
|
foreach (string i in d.FileNames)
|
||||||
mp.commandv("audio-add", i);
|
core.commandv("audio-add", i);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CycleAudio()
|
public static void CycleAudio()
|
||||||
{
|
{
|
||||||
string path = mp.get_property_string("path");
|
string path = core.get_property_string("path");
|
||||||
if (!File.Exists(path)) return;
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
return;
|
||||||
|
|
||||||
using (MediaInfo mi = new MediaInfo(path))
|
using (MediaInfo mi = new MediaInfo(path))
|
||||||
{
|
{
|
||||||
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
|
MediaTrack[] audTracks = core.MediaTracks.Where(track => track.Type == "a").ToArray();
|
||||||
if (audTracks.Length < 2) return;
|
|
||||||
int aid = mp.get_property_int("aid");
|
if (audTracks.Length < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int aid = core.get_property_int("aid");
|
||||||
aid += 1;
|
aid += 1;
|
||||||
if (aid > audTracks.Length) aid = 1;
|
|
||||||
mp.commandv("set", "aid", aid.ToString());
|
if (aid > audTracks.Length)
|
||||||
mp.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
|
aid = 1;
|
||||||
|
|
||||||
|
core.commandv("set", "aid", aid.ToString());
|
||||||
|
core.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ManageFileAssociations()
|
static void ShowProfiles()
|
||||||
{
|
{
|
||||||
using (var td = new TaskDialog<string>())
|
string code = @"
|
||||||
|
foreach ($item in ($json | ConvertFrom-Json | foreach { $_ } | sort name))
|
||||||
{
|
{
|
||||||
td.MainInstruction = "Choose an option.";
|
$item.name
|
||||||
td.MainIcon = MsgIcon.Shield;
|
''
|
||||||
|
|
||||||
td.AddCommandLink("Register video file extensions", "video");
|
foreach ($option in $item.options)
|
||||||
td.AddCommandLink("Register audio file extensions", "audio");
|
|
||||||
td.AddCommandLink("Register image file extensions", "image");
|
|
||||||
td.AddCommandLink("Unregister file extensions", "unreg");
|
|
||||||
|
|
||||||
string result = td.Show();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(result))
|
|
||||||
{
|
{
|
||||||
using (var proc = new Process())
|
' ' + $option.key + ' = ' + $option.value
|
||||||
|
}
|
||||||
|
|
||||||
|
''
|
||||||
|
}";
|
||||||
|
|
||||||
|
string json = core.get_property_string("profile-list");
|
||||||
|
string file = Path.GetTempPath() + @"\mpv profile-list.txt";
|
||||||
|
File.WriteAllText(file, BR + PowerShell.InvokeAndReturnString(code, "json", json));
|
||||||
|
Process.Start(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowCommands()
|
||||||
{
|
{
|
||||||
proc.StartInfo.FileName = System.Windows.Forms.Application.ExecutablePath;
|
string code = @"
|
||||||
proc.StartInfo.Arguments = "--reg-file-assoc " + result;
|
foreach ($item in ($json | ConvertFrom-Json | foreach { $_ } | sort name))
|
||||||
proc.StartInfo.Verb = "runas";
|
{
|
||||||
try { proc.Start(); } catch { }
|
''
|
||||||
|
$item.name
|
||||||
|
|
||||||
|
foreach ($arg in $item.args)
|
||||||
|
{
|
||||||
|
$value = $arg.name + ' <' + $arg.type.ToLower() + '>'
|
||||||
|
|
||||||
|
if ($arg.optional -eq $true)
|
||||||
|
{
|
||||||
|
$value = '[' + $value + ']'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
' ' + $value
|
||||||
}
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
string json = core.get_property_string("command-list");
|
||||||
|
string file = Path.GetTempPath() + @"\mpv command-list.txt";
|
||||||
|
File.WriteAllText(file, PowerShell.InvokeAndReturnString(code, "json", json) + BR);
|
||||||
|
Process.Start(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ShowProperties()
|
||||||
|
{
|
||||||
|
string file = Path.GetTempPath() + @"\mpv property-list.txt";
|
||||||
|
var props = core.get_property_string("property-list").Split(',').OrderBy(prop => prop);
|
||||||
|
File.WriteAllText(file, BR + string.Join(BR, props) + BR);
|
||||||
|
Process.Start(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.ComponentModel.Composition.Hosting;
|
using System.ComponentModel.Composition.Hosting;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Forms;
|
using System.Linq;
|
||||||
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
@@ -19,18 +22,29 @@ namespace mpvnet
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
AggregateCatalog catalog = new AggregateCatalog();
|
AggregateCatalog catalog = new AggregateCatalog();
|
||||||
|
string dir = Folder.Startup + "Extensions";
|
||||||
string dir = Application.StartupPath + "\\Extensions";
|
|
||||||
|
|
||||||
if (Directory.Exists(dir))
|
if (Directory.Exists(dir))
|
||||||
foreach (string i in Directory.GetDirectories(dir))
|
{
|
||||||
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Extension.dll"));
|
string[] knownExtensions = { "RatingExtension", "ScriptingExtension" };
|
||||||
|
|
||||||
dir = mp.ConfigFolder + "\\Extensions";
|
foreach (string extDir in Directory.GetDirectories(dir))
|
||||||
|
{
|
||||||
|
if (knownExtensions.Contains(Path.GetFileName(extDir)))
|
||||||
|
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
|
||||||
|
else
|
||||||
|
ConsoleHelp.WriteError("Failed to load extension:\n\n" + extDir +
|
||||||
|
"\n\nOnly extensions that ship with mpv.net are allowed in <startup>\\extensions" +
|
||||||
|
"\n\nUser extensions have to use <config folder>\\extensions" +
|
||||||
|
"\n\nNever copy or install a new mpv.net version over a old mpv.net version.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = core.ConfigFolder + "extensions";
|
||||||
|
|
||||||
if (Directory.Exists(dir))
|
if (Directory.Exists(dir))
|
||||||
foreach (string i in Directory.GetDirectories(dir))
|
foreach (string extDir in Directory.GetDirectories(dir))
|
||||||
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Extension.dll"));
|
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
|
||||||
|
|
||||||
if (catalog.Catalogs.Count > 0)
|
if (catalog.Catalogs.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -40,7 +54,7 @@ namespace mpvnet
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Msg.ShowException(ex);
|
App.ShowException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
mpv.net/Misc/ExtensionMethods.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static string FileName(this string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path)) return "";
|
||||||
|
int index = path.LastIndexOf('\\');
|
||||||
|
if (index > -1) return path.Substring(index + 1);
|
||||||
|
index = path.LastIndexOf('/');
|
||||||
|
if (index > -1) return path.Substring(index + 1);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ShortExt(this string path)
|
||||||
|
{
|
||||||
|
return Path.GetExtension(path).ToLower().TrimStart('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Int(this string value)
|
||||||
|
{
|
||||||
|
int.TryParse(value, out int result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Float(this string value)
|
||||||
|
{
|
||||||
|
float.TryParse(value.Replace(",", "."), NumberStyles.Float, CultureInfo.InvariantCulture, out float result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
mpv.net/Misc/Help.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
public static class ConsoleHelp
|
||||||
|
{
|
||||||
|
public static int Padding { get; set; }
|
||||||
|
|
||||||
|
public static void WriteError(object obj, string module = "mpv.net")
|
||||||
|
{
|
||||||
|
Write(obj, module, ConsoleColor.Red, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(object obj, string module = "mpv.net")
|
||||||
|
{
|
||||||
|
Write(obj, module, ConsoleColor.Black, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(object obj, string module, ConsoleColor color)
|
||||||
|
{
|
||||||
|
Write(obj, module, color, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(object obj, string module, ConsoleColor color, bool useDefaultColor)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string value = obj.ToString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(module))
|
||||||
|
module = "[" + module + "] ";
|
||||||
|
|
||||||
|
if (useDefaultColor)
|
||||||
|
Console.ResetColor();
|
||||||
|
else
|
||||||
|
Console.ForegroundColor = color;
|
||||||
|
|
||||||
|
value = module + value;
|
||||||
|
|
||||||
|
if (Padding > 0 && value.Length < Padding)
|
||||||
|
value = value.PadRight(Padding);
|
||||||
|
|
||||||
|
Console.WriteLine(value);
|
||||||
|
Console.ResetColor();
|
||||||
|
Trace.WriteLine(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -14,146 +14,22 @@ using System.Windows.Forms;
|
|||||||
|
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
public class App
|
|
||||||
{
|
|
||||||
public static string RegPath { get; } = @"HKCU\Software\" + Application.ProductName;
|
|
||||||
public static string ConfPath { get; } = mp.ConfigFolder + "\\mpvnet.conf";
|
|
||||||
public static string DarkMode { get; set; } = "always";
|
|
||||||
public static string ProcessInstance { get; set; } = "single";
|
|
||||||
public static string DarkColor { get; set; }
|
|
||||||
public static string LightColor { get; set; }
|
|
||||||
|
|
||||||
public static string[] VideoTypes { get; } = "264 265 asf avc avi avs flv h264 h265 hevc m2ts m2v m4v mkv mov mp4 mpeg mpg mpv mts ts vob vpy webm webm wmv y4m".Split(' ');
|
|
||||||
public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(' ');
|
|
||||||
public static string[] ImageTypes { get; } = "jpg bmp gif png".Split(' ');
|
|
||||||
public static string[] SubtitleTypes { get; } = "srt ass idx sup ttxt ssa smi".Split(' ');
|
|
||||||
public static string[] UrlWhitelist { get; set; } = { "tube", "vimeo", "ard", "zdf" };
|
|
||||||
|
|
||||||
public static bool RememberHeight { get; set; } = true;
|
|
||||||
public static bool RememberPosition { get; set; }
|
|
||||||
public static bool DebugMode { get; set; }
|
|
||||||
public static bool IsStartedFromTerminal { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
|
|
||||||
|
|
||||||
public static int StartThreshold { get; set; } = 1500;
|
|
||||||
|
|
||||||
public static bool IsDarkMode {
|
|
||||||
get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Init()
|
|
||||||
{
|
|
||||||
string dummy = mp.ConfigFolder;
|
|
||||||
var dummy2 = mp.Conf;
|
|
||||||
|
|
||||||
foreach (var i in Conf)
|
|
||||||
ProcessProperty(i.Key, i.Value);
|
|
||||||
|
|
||||||
if (App.DebugMode)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string filePath = mp.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 void ProcessProperty(string name, string value)
|
|
||||||
{
|
|
||||||
switch (name)
|
|
||||||
{
|
|
||||||
case "remember-position": RememberPosition = value == "yes"; break;
|
|
||||||
case "start-size": RememberHeight = value == "previous"; break;
|
|
||||||
case "process-instance": ProcessInstance = value; break;
|
|
||||||
case "dark-mode": DarkMode = value; break;
|
|
||||||
case "debug-mode": DebugMode = value == "yes"; break;
|
|
||||||
case "dark-color": DarkColor = value.Trim('\'', '"'); break;
|
|
||||||
case "light-color": LightColor = value.Trim('\'', '"'); break;
|
|
||||||
case "url-whitelist":
|
|
||||||
UrlWhitelist = value.Split(' ', ',', ';');
|
|
||||||
break;
|
|
||||||
case "start-threshold":
|
|
||||||
int.TryParse(value, out int result);
|
|
||||||
StartThreshold = result;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ProcessCommandLineEarly()
|
|
||||||
{
|
|
||||||
var args = Environment.GetCommandLineArgs().Skip(1);
|
|
||||||
|
|
||||||
foreach (string i in args)
|
|
||||||
{
|
|
||||||
if (i.StartsWith("--"))
|
|
||||||
{
|
|
||||||
if (i.Contains("="))
|
|
||||||
{
|
|
||||||
string left = i.Substring(2, i.IndexOf("=") - 2);
|
|
||||||
string right = i.Substring(left.Length + 3);
|
|
||||||
mp.ProcessProperty(left, right);
|
|
||||||
ProcessProperty(left, right);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string name = i.Substring(2);
|
|
||||||
mp.ProcessProperty(name, "yes");
|
|
||||||
ProcessProperty(name, "yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Sys
|
public class Sys
|
||||||
{
|
{
|
||||||
public static bool IsDarkTheme {
|
public static bool IsDarkTheme {
|
||||||
get {
|
get {
|
||||||
object value = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
|
object value = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
|
||||||
if (value is null) value = 1;
|
|
||||||
|
if (value is null)
|
||||||
|
value = 1;
|
||||||
|
|
||||||
return (int)value == 0;
|
return (int)value == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsDirectoryWritable(string dirPath)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (FileStream fs = File.Create(Path.Combine(dirPath,
|
|
||||||
Path.GetRandomFileName()), 1, FileOptions.DeleteOnClose))
|
|
||||||
{ }
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{ }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StringLogicalComparer : IComparer, IComparer<string>
|
public class StringLogicalComparer : IComparer, IComparer<string>
|
||||||
@@ -178,105 +54,51 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
Types = types;
|
Types = types;
|
||||||
|
|
||||||
RegHelp.SetObject(@"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename, null, ExePath);
|
RegistryHelp.SetValue(@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename, null, ExePath);
|
||||||
RegHelp.SetObject($"HKCR\\Applications\\{ExeFilename}", "FriendlyAppName", "mpv.net media player");
|
RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename, "FriendlyAppName", "mpv.net media player");
|
||||||
RegHelp.SetObject($"HKCR\\Applications\\{ExeFilename}\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\"");
|
RegistryHelp.SetValue($@"HKCR\Applications\{ExeFilename}\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
|
||||||
RegHelp.SetObject(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationDescription", "mpv.net media player");
|
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationDescription", "mpv.net media player");
|
||||||
RegHelp.SetObject(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationName", "mpv.net");
|
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationName", "mpv.net");
|
||||||
RegHelp.SetObject($"HKCR\\SystemFileAssociations\\video\\OpenWithList\\{ExeFilename}", null, "");
|
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename, null, "");
|
||||||
RegHelp.SetObject($"HKCR\\SystemFileAssociations\\audio\\OpenWithList\\{ExeFilename}", null, "");
|
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename, null, "");
|
||||||
|
RegistryHelp.SetValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net", @"SOFTWARE\Clients\Media\mpv.net\Capabilities");
|
||||||
|
|
||||||
foreach (string ext in Types)
|
foreach (string ext in Types)
|
||||||
{
|
{
|
||||||
RegHelp.SetObject($"HKCR\\Applications\\{ExeFilename}\\SupportedTypes", "." + ext, "");
|
RegistryHelp.SetValue($@"HKCR\Applications\{ExeFilename}\SupportedTypes", "." + ext, "");
|
||||||
RegHelp.SetObject($"HKCR\\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
|
RegistryHelp.SetValue($@"HKCR\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
|
||||||
RegHelp.SetObject($"HKCR\\" + "." + ext + "\\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
|
RegistryHelp.SetValue($@"HKCR\" + "." + ext + @"\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
|
||||||
|
|
||||||
if (App.VideoTypes.Contains(ext))
|
if (App.VideoTypes.Contains(ext))
|
||||||
RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "video");
|
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "video");
|
||||||
|
|
||||||
if (App.AudioTypes.Contains(ext))
|
if (App.AudioTypes.Contains(ext))
|
||||||
RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "audio");
|
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "audio");
|
||||||
|
|
||||||
if (App.ImageTypes.Contains(ext))
|
if (App.ImageTypes.Contains(ext))
|
||||||
RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "image");
|
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "image");
|
||||||
RegHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open", null, "Play with " + Application.ProductName);
|
|
||||||
RegHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\"");
|
RegistryHelp.SetValue($@"HKCR\" + ExeFilenameNoExt + "." + ext + @"\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
|
||||||
RegHelp.SetObject(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);
|
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Unregister()
|
public static void Unregister()
|
||||||
{
|
{
|
||||||
RegHelp.RemoveKey(@"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename);
|
RegistryHelp.RemoveKey($@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename);
|
||||||
RegHelp.RemoveKey($"HKCR\\Applications\\{ExeFilename}");
|
RegistryHelp.RemoveKey($@"HKCR\Applications\" + ExeFilename);
|
||||||
RegHelp.RemoveKey(@"HKLM\SOFTWARE\Clients\Media\mpv.net");
|
RegistryHelp.RemoveKey($@"HKLM\SOFTWARE\Clients\Media\mpv.net");
|
||||||
RegHelp.RemoveKey($"HKCR\\SystemFileAssociations\\video\\OpenWithList\\{ExeFilename}");
|
RegistryHelp.RemoveKey($@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename);
|
||||||
RegHelp.RemoveKey($"HKCR\\SystemFileAssociations\\audio\\OpenWithList\\{ExeFilename}");
|
RegistryHelp.RemoveKey($@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename);
|
||||||
|
RegistryHelp.RemoveValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net");
|
||||||
|
|
||||||
foreach (string id in Registry.ClassesRoot.GetSubKeyNames())
|
foreach (string id in Registry.ClassesRoot.GetSubKeyNames())
|
||||||
{
|
{
|
||||||
if (id.StartsWith(ExeFilenameNoExt + "."))
|
if (id.StartsWith(ExeFilenameNoExt + "."))
|
||||||
Registry.ClassesRoot.DeleteSubKeyTree(id);
|
Registry.ClassesRoot.DeleteSubKeyTree(id);
|
||||||
|
|
||||||
RegHelp.RemoveValue($"HKCR\\Software\\Classes\\" + id + "\\OpenWithProgIDs", ExeFilenameNoExt + id);
|
RegistryHelp.RemoveValue($@"HKCR\Software\Classes\{id}\OpenWithProgIDs", ExeFilenameNoExt + id);
|
||||||
RegHelp.RemoveValue($"HKLM\\Software\\Classes\\" + id + "\\OpenWithProgIDs", ExeFilenameNoExt + id);
|
RegistryHelp.RemoveValue($@"HKLM\Software\Classes\{id}\OpenWithProgIDs", ExeFilenameNoExt + id);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegHelp
|
|
||||||
{
|
|
||||||
public static void SetObject(string path, string name, object value)
|
|
||||||
{
|
|
||||||
using (RegistryKey rk = GetRootKey(path).CreateSubKey(path.Substring(5), RegistryKeyPermissionCheck.ReadWriteSubTree))
|
|
||||||
rk.SetValue(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetString(string path, string name)
|
|
||||||
{
|
|
||||||
object val = GetObject(path, name);
|
|
||||||
if (val == null || !(val is string)) return "";
|
|
||||||
return val.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetInt(string path, string name)
|
|
||||||
{
|
|
||||||
object val = GetObject(path, name);
|
|
||||||
if (val == null || !(val is int)) return 0;
|
|
||||||
return (int)val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object GetObject(string path, string name)
|
|
||||||
{
|
|
||||||
using (RegistryKey rk = GetRootKey(path).OpenSubKey(path.Substring(5)))
|
|
||||||
if (rk != null)
|
|
||||||
return rk.GetValue(name, "");
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 rk = GetRootKey(path).OpenSubKey(path.Substring(5), true))
|
|
||||||
if (!(rk is null))
|
|
||||||
rk.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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,12 +121,12 @@ namespace mpvnet
|
|||||||
|
|
||||||
public CommandItem(SerializationInfo info, StreamingContext context) { }
|
public CommandItem(SerializationInfo info, StreamingContext context) { }
|
||||||
|
|
||||||
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
|
void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _Input = "";
|
string _Input = "";
|
||||||
|
|
||||||
public string Input {
|
public string Input {
|
||||||
get => _Input;
|
get => _Input;
|
||||||
@@ -323,59 +145,52 @@ namespace mpvnet
|
|||||||
foreach (string line in content.Split('\r', '\n'))
|
foreach (string line in content.Split('\r', '\n'))
|
||||||
{
|
{
|
||||||
string val = line.Trim();
|
string val = line.Trim();
|
||||||
if (val.StartsWith("#")) continue;
|
|
||||||
if (!val.Contains(" ")) continue;
|
if (val.StartsWith("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!val.Contains(" "))
|
||||||
|
continue;
|
||||||
|
|
||||||
CommandItem item = new CommandItem();
|
CommandItem item = new CommandItem();
|
||||||
item.Input = val.Substring(0, val.IndexOf(" "));
|
item.Input = val.Substring(0, val.IndexOf(" "));
|
||||||
if (item.Input == "_") item.Input = "";
|
|
||||||
|
if (item.Input == "_")
|
||||||
|
item.Input = "";
|
||||||
|
|
||||||
val = val.Substring(val.IndexOf(" ") + 1);
|
val = val.Substring(val.IndexOf(" ") + 1);
|
||||||
|
|
||||||
if (val.Contains("#menu:"))
|
if (val.Contains("#menu:"))
|
||||||
{
|
{
|
||||||
item.Path = val.Substring(val.IndexOf("#menu:") + 6).Trim();
|
item.Path = val.Substring(val.IndexOf("#menu:") + 6).Trim();
|
||||||
val = val.Substring(0, val.IndexOf("#menu:"));
|
val = val.Substring(0, val.IndexOf("#menu:"));
|
||||||
|
|
||||||
if (item.Path.Contains(";"))
|
if (item.Path.Contains(";"))
|
||||||
item.Path = item.Path.Substring(item.Path.IndexOf(";") + 1).Trim();
|
item.Path = item.Path.Substring(item.Path.IndexOf(";") + 1).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Command = val.Trim();
|
item.Command = val.Trim();
|
||||||
|
|
||||||
if (item.Command == "")
|
if (item.Command == "")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (item.Command.ToLower() == "ignore")
|
if (item.Command.ToLower() == "ignore")
|
||||||
item.Command = "";
|
item.Command = "";
|
||||||
MigrateCommands(item);
|
|
||||||
items.Add(item);
|
items.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ObservableCollection<CommandItem> _Items;
|
static ObservableCollection<CommandItem> _Items;
|
||||||
|
|
||||||
public static ObservableCollection<CommandItem> Items {
|
public static ObservableCollection<CommandItem> Items {
|
||||||
get {
|
get {
|
||||||
if (_Items is null)
|
if (_Items is null)
|
||||||
_Items = GetItems(File.ReadAllText(mp.InputConfPath));
|
_Items = GetItems(File.ReadAllText(core.InputConfPath));
|
||||||
return _Items;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void MigrateCommands(CommandItem item)
|
return _Items;
|
||||||
{
|
|
||||||
switch (item.Command)
|
|
||||||
{
|
|
||||||
case "script-message mpv.net show-prefs":
|
|
||||||
item.Command = "script-message mpv.net show-conf-editor";
|
|
||||||
break;
|
|
||||||
case "script-message mpv.net show-keys":
|
|
||||||
item.Command = "script-message mpv.net show-input-editor";
|
|
||||||
break;
|
|
||||||
case "script-message mpv.net history":
|
|
||||||
item.Command = "script-message mpv.net show-history";
|
|
||||||
break;
|
|
||||||
case "script-message mpv.net open-config-folder":
|
|
||||||
item.Command = "script-message open-conf-folder";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,16 +225,8 @@ namespace mpvnet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PathHelp
|
public class Folder
|
||||||
{
|
{
|
||||||
public static string GetFileName(string path)
|
public static string Startup { get; } = Application.StartupPath + @"\";
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(path)) return "";
|
|
||||||
int index = path.LastIndexOf('\\');
|
|
||||||
if (index > -1) return path.Substring(index + 1);
|
|
||||||
index = path.LastIndexOf('/');
|
|
||||||
if (index > -1) return path.Substring(index + 1);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
mpv.net/Misc/NewLine.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public static class NewLine
|
||||||
|
{
|
||||||
|
public static string BR = Environment.NewLine;
|
||||||
|
public static string BR2 = Environment.NewLine + Environment.NewLine;
|
||||||
|
}
|
||||||
244
mpv.net/Misc/PowerShell.cs
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Management.Automation;
|
||||||
|
using System.Management.Automation.Runspaces;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
using static NewLine;
|
||||||
|
|
||||||
|
namespace mpvnet
|
||||||
|
{
|
||||||
|
public class PowerShell
|
||||||
|
{
|
||||||
|
public Runspace Runspace { get; set; }
|
||||||
|
public Pipeline Pipeline { get; set; }
|
||||||
|
public string Module { get; set; }
|
||||||
|
public bool Print { get; set; }
|
||||||
|
public List<string> Scripts { get; } = new List<string>();
|
||||||
|
public List<KeyValuePair<string, object>> Variables = new List<KeyValuePair<string, object>>();
|
||||||
|
public string[] Parameters { get; }
|
||||||
|
public event Action<string, object[]> Event;
|
||||||
|
public event Action<string, object> PropertyChanged;
|
||||||
|
public List<KeyValuePair<string, ScriptBlock>> EventHandlers = new List<KeyValuePair<string, ScriptBlock>>();
|
||||||
|
public List<KeyValuePair<string, ScriptBlock>> PropChangedHandlers = new List<KeyValuePair<string, ScriptBlock>>();
|
||||||
|
|
||||||
|
public static List<PowerShell> Instances { get; } = new List<PowerShell>();
|
||||||
|
|
||||||
|
public object Invoke() => Invoke(null, null);
|
||||||
|
|
||||||
|
public object Invoke(string variable, object obj)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Runspace = RunspaceFactory.CreateRunspace();
|
||||||
|
Runspace.ApartmentState = ApartmentState.STA;
|
||||||
|
Runspace.Open();
|
||||||
|
Pipeline = Runspace.CreatePipeline();
|
||||||
|
|
||||||
|
foreach (string script in Scripts)
|
||||||
|
Pipeline.Commands.AddScript(script);
|
||||||
|
|
||||||
|
if (Parameters != null)
|
||||||
|
foreach (string param in Parameters)
|
||||||
|
foreach (Command command in Pipeline.Commands)
|
||||||
|
command.Parameters.Add(null, param);
|
||||||
|
|
||||||
|
Runspace.SessionStateProxy.SetVariable("mp", this);
|
||||||
|
|
||||||
|
foreach (var i in Variables)
|
||||||
|
Runspace.SessionStateProxy.SetVariable(i.Key, i.Value);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(variable))
|
||||||
|
Runspace.SessionStateProxy.SetVariable(variable, obj);
|
||||||
|
|
||||||
|
if (Print)
|
||||||
|
{
|
||||||
|
Pipeline.Output.DataReady += Output_DataReady;
|
||||||
|
Pipeline.Error.DataReady += Error_DataReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pipeline.Invoke();
|
||||||
|
}
|
||||||
|
catch (RuntimeException e)
|
||||||
|
{
|
||||||
|
string message = e.Message + BR + BR + e.ErrorRecord.ScriptStackTrace.Replace(
|
||||||
|
" <ScriptBlock>, <No file>", "") + BR + BR + Module + BR;
|
||||||
|
|
||||||
|
throw new PowerShellException(message);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string InvokeAndReturnString(string code, string varName, object varValue)
|
||||||
|
{
|
||||||
|
PowerShell ps = new PowerShell() { Print = false };
|
||||||
|
ps.Scripts.Add(code);
|
||||||
|
string ret = string.Join(Environment.NewLine, (ps.Invoke(varName, varValue)
|
||||||
|
as IEnumerable<object>).Select(item => item.ToString())).ToString();
|
||||||
|
ps.Runspace.Dispose();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Output_DataReady(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var output = sender as PipelineReader<PSObject>;
|
||||||
|
|
||||||
|
while (output.Count > 0)
|
||||||
|
ConsoleHelp.Write(output.Read(), Module);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Error_DataReady(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var output = sender as PipelineReader<Object>;
|
||||||
|
|
||||||
|
while (output.Count > 0)
|
||||||
|
ConsoleHelp.WriteError(output.Read(), Module);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RedirectStreams(PSEventJob job)
|
||||||
|
{
|
||||||
|
if (Print)
|
||||||
|
{
|
||||||
|
job.Output.DataAdded += Output_DataAdded;
|
||||||
|
job.Error.DataAdded += Error_DataAdded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commandv(params string[] args) => core.commandv(args);
|
||||||
|
|
||||||
|
public void command(string command) => core.command(command);
|
||||||
|
|
||||||
|
public bool get_property_bool(string name) => core.get_property_bool(name);
|
||||||
|
|
||||||
|
public void set_property_bool(string name, bool value) => core.set_property_bool(name, value);
|
||||||
|
|
||||||
|
public int get_property_int(string name) => core.get_property_int(name);
|
||||||
|
|
||||||
|
public void set_property_int(string name, int value) => core.set_property_int(name, value);
|
||||||
|
|
||||||
|
public double get_property_number(string name) => core.get_property_number(name);
|
||||||
|
|
||||||
|
public void set_property_number(string name, double value) => core.set_property_number(name, value);
|
||||||
|
|
||||||
|
public string get_property_string(string name) => core.get_property_string(name);
|
||||||
|
|
||||||
|
public void set_property_string(string name, string value) => core.set_property_string(name, value);
|
||||||
|
|
||||||
|
public void observe_property(string name, string type, ScriptBlock sb)
|
||||||
|
{
|
||||||
|
PropChangedHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "bool": case "boolean":
|
||||||
|
core.observe_property_bool(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
core.observe_property_string(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||||
|
break;
|
||||||
|
case "int": case "integer":
|
||||||
|
core.observe_property_int(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||||
|
break;
|
||||||
|
case "float": case "double":
|
||||||
|
core.observe_property_double(name, (value) => Task.Run(() => PropertyChanged.Invoke(name, value)));
|
||||||
|
break;
|
||||||
|
case "nil": case "none": case "native":
|
||||||
|
core.observe_property(name, () => Task.Run(() => PropertyChanged.Invoke(name, null)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
App.ShowError("Invalid Type", "Valid types are: bool or boolean, string, int or integer, float or double, nil or none or native");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register_event(string name, ScriptBlock sb)
|
||||||
|
{
|
||||||
|
EventHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
|
||||||
|
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "log-message":
|
||||||
|
core.LogMessageAsync += (level, msg) => Event.Invoke("log-message", new object[] { level, msg });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "end-file":
|
||||||
|
core.EndFileAsync += (reason) => Event.Invoke("end-file", new object[] { reason });
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "client-message":
|
||||||
|
core.ClientMessageAsync += (args) => Event.Invoke("client-message", args);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "shutdown":
|
||||||
|
core.Shutdown += () => Event.Invoke("shutdown", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "get-property-reply":
|
||||||
|
core.GetPropertyReplyAsync += () => Event.Invoke("get-property-reply", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "set-property-reply":
|
||||||
|
core.SetPropertyReplyAsync += () => Event.Invoke("set-property-reply", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "command-reply":
|
||||||
|
core.CommandReplyAsync += () => Event.Invoke("command-reply", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "start-file":
|
||||||
|
core.StartFileAsync += () => Event.Invoke("start-file", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "file-loaded":
|
||||||
|
core.FileLoadedAsync += () => Event.Invoke("file-loaded", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "idle":
|
||||||
|
core.IdleAsync += () => Event.Invoke("idle", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "video-reconfig":
|
||||||
|
core.VideoReconfigAsync += () => Event.Invoke("video-reconfig", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "audio-reconfig":
|
||||||
|
core.AudioReconfigAsync += () => Event.Invoke("audio-reconfig", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "seek":
|
||||||
|
core.SeekAsync += () => Event.Invoke("seek", null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "playback-restart":
|
||||||
|
core.PlaybackRestartAsync += () => Event.Invoke("playback-restart", null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Output_DataAdded(object sender, DataAddedEventArgs e)
|
||||||
|
{
|
||||||
|
var output = sender as PSDataCollection<PSObject>;
|
||||||
|
ConsoleHelp.Write(output[e.Index], Module);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Error_DataAdded(object sender, DataAddedEventArgs e)
|
||||||
|
{
|
||||||
|
var error = sender as PSDataCollection<ErrorRecord>;
|
||||||
|
ConsoleHelp.WriteError(error[e.Index], Module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PowerShellException : Exception
|
||||||
|
{
|
||||||
|
public PowerShellException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
@@ -18,6 +20,12 @@ namespace mpvnet
|
|||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
|
if (App.IsStartedFromTerminal)
|
||||||
|
WinAPI.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
|
||||||
|
|
||||||
|
if (core.ConfigFolder == "")
|
||||||
|
return;
|
||||||
|
|
||||||
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
||||||
|
|
||||||
if (args.Length == 2 && args[0] == "--reg-file-assoc")
|
if (args.Length == 2 && args[0] == "--reg-file-assoc")
|
||||||
@@ -38,8 +46,14 @@ namespace mpvnet
|
|||||||
files.Add(App.ProcessInstance);
|
files.Add(App.ProcessInstance);
|
||||||
|
|
||||||
foreach (string arg in args)
|
foreach (string arg in args)
|
||||||
if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") || File.Exists(arg)))
|
{
|
||||||
|
if (!arg.StartsWith("--") && (arg == "-" || arg.Contains("://") ||
|
||||||
|
arg.Contains(":\\") || arg.StartsWith("\\\\")))
|
||||||
|
|
||||||
files.Add(arg);
|
files.Add(arg);
|
||||||
|
else if (arg == "--queue")
|
||||||
|
files[0] = "queue";
|
||||||
|
}
|
||||||
|
|
||||||
Process[] procs = Process.GetProcessesByName("mpvnet");
|
Process[] procs = Process.GetProcessesByName("mpvnet");
|
||||||
|
|
||||||
@@ -49,24 +63,32 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
if (proc.MainWindowHandle != IntPtr.Zero)
|
if (proc.MainWindowHandle != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Native.AllowSetForegroundWindow(proc.Id);
|
WinAPI.AllowSetForegroundWindow(proc.Id);
|
||||||
var data = new Native.COPYDATASTRUCT();
|
var data = new WinAPI.COPYDATASTRUCT();
|
||||||
data.lpData = string.Join("\n", files.ToArray());
|
data.lpData = string.Join("\n", files.ToArray());
|
||||||
data.cbData = data.lpData.Length * 2 + 1;
|
data.cbData = data.lpData.Length * 2 + 1;
|
||||||
Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data);
|
WinAPI.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data);
|
||||||
mutex.Dispose();
|
mutex.Dispose();
|
||||||
|
|
||||||
|
if (App.IsStartedFromTerminal)
|
||||||
|
WinAPI.FreeConsole();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.Sleep(50);
|
Thread.Sleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex.Dispose();
|
mutex.Dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App.IsStartedFromTerminal) Native.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
|
|
||||||
Application.Run(new MainForm());
|
Application.Run(new MainForm());
|
||||||
if (App.IsStartedFromTerminal) Native.FreeConsole();
|
|
||||||
|
if (App.IsStartedFromTerminal)
|
||||||
|
WinAPI.FreeConsole();
|
||||||
|
|
||||||
mutex.Dispose();
|
mutex.Dispose();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
70
mpv.net/Misc/RegistryHelp.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
public class RegistryHelp
|
||||||
|
{
|
||||||
|
public static string ApplicationKey { get; } = @"HKCU\Software\" + Application.ProductName;
|
||||||
|
|
||||||
|
public static void SetValue(string path, string name, object value)
|
||||||
|
{
|
||||||
|
using (RegistryKey regKey = GetRootKey(path).CreateSubKey(path.Substring(5), RegistryKeyPermissionCheck.ReadWriteSubTree))
|
||||||
|
regKey.SetValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetString(string path, string name, string defaultValue = "")
|
||||||
|
{
|
||||||
|
object value = GetValue(path, name, defaultValue);
|
||||||
|
return !(value is string) ? defaultValue : value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetInt(string path, string name, int defaultValue = 0)
|
||||||
|
{
|
||||||
|
object value = GetValue(path, name, defaultValue);
|
||||||
|
return !(value is int) ? defaultValue : (int)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool GetBool(string path, string name, bool defaultValue = false)
|
||||||
|
{
|
||||||
|
object val = GetValue(path, name, defaultValue);
|
||||||
|
return val is bool ? (bool)val : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetValue(string path, string name, object defaultValue = null)
|
||||||
|
{
|
||||||
|
using (RegistryKey regKey = GetRootKey(path).OpenSubKey(path.Substring(5)))
|
||||||
|
return regKey == null ? null : regKey.GetValue(name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveKey(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GetRootKey(path).DeleteSubKeyTree(path.Substring(5), false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveValue(string path, string name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (RegistryKey regKey = GetRootKey(path).OpenSubKey(path.Substring(5), true))
|
||||||
|
if (regKey != null)
|
||||||
|
regKey.DeleteValue(name, false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegistryKey GetRootKey(string path)
|
||||||
|
{
|
||||||
|
switch (path.Substring(0, 4))
|
||||||
|
{
|
||||||
|
case "HKLM": return Registry.LocalMachine;
|
||||||
|
case "HKCU": return Registry.CurrentUser;
|
||||||
|
case "HKCR": return Registry.ClassesRoot;
|
||||||
|
default: throw new Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
mpv.net/Misc/Theme.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace 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 static Brush Foreground { get; set; }
|
||||||
|
public static Brush Foreground2 { get; set; }
|
||||||
|
public static Brush Background { get; set; }
|
||||||
|
public static Brush Heading { get; set; }
|
||||||
|
|
||||||
|
public System.Drawing.Color GetWinFormsColor(string key)
|
||||||
|
{
|
||||||
|
return System.Drawing.ColorTranslator.FromHtml(Dictionary[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Brush GetBrush(string key)
|
||||||
|
{
|
||||||
|
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Init(string customContent, string defaultContent, string activeTheme)
|
||||||
|
{
|
||||||
|
DefaultThemes = Load(defaultContent);
|
||||||
|
CustomThemes = Load(customContent);
|
||||||
|
|
||||||
|
foreach (Theme theme in CustomThemes)
|
||||||
|
{
|
||||||
|
if (theme.Name == activeTheme)
|
||||||
|
{
|
||||||
|
bool isKeyMissing = false;
|
||||||
|
|
||||||
|
foreach (string key in DefaultThemes[0].Dictionary.Keys)
|
||||||
|
{
|
||||||
|
if (!theme.Dictionary.ContainsKey(key))
|
||||||
|
{
|
||||||
|
isKeyMissing = true;
|
||||||
|
ConsoleHelp.WriteError($"Theme '{activeTheme}' misses '{key}'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isKeyMissing)
|
||||||
|
Current = theme;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Current == null)
|
||||||
|
foreach (Theme theme in DefaultThemes)
|
||||||
|
if (theme.Name == activeTheme)
|
||||||
|
Current = theme;
|
||||||
|
|
||||||
|
if (Current == null)
|
||||||
|
Current = DefaultThemes[0];
|
||||||
|
|
||||||
|
Foreground = Current.GetBrush("foreground");
|
||||||
|
Foreground2 = Current.GetBrush("foreground2");
|
||||||
|
Background = Current.GetBrush("background");
|
||||||
|
Heading = Current.GetBrush("heading");
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Theme> Load(string content)
|
||||||
|
{
|
||||||
|
List<Theme> list = new List<Theme>();
|
||||||
|
Theme theme = null;
|
||||||
|
|
||||||
|
foreach (string currentLine in (content ?? "").Split(new [] { '\r', '\n' }))
|
||||||
|
{
|
||||||
|
string line = currentLine.Trim();
|
||||||
|
|
||||||
|
if (line.StartsWith("[") && line.EndsWith("]"))
|
||||||
|
list.Add(theme = new Theme() { Name = line.Substring(1, line.Length - 2).Trim() });
|
||||||
|
|
||||||
|
if (line.Contains("=") && theme != null)
|
||||||
|
{
|
||||||
|
string left = line.Substring(0, line.IndexOf("=")).Trim();
|
||||||
|
theme.Dictionary[left] = line.Substring(line.IndexOf("=") + 1).Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
79
mpv.net/Misc/UpdateCheck.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
|
namespace mpvnet
|
||||||
|
{
|
||||||
|
class UpdateCheck
|
||||||
|
{
|
||||||
|
public static void DailyCheck()
|
||||||
|
{
|
||||||
|
if (App.UpdateCheck && RegistryHelp.GetInt(RegistryHelp.ApplicationKey, "UpdateCheckLast")
|
||||||
|
!= DateTime.Now.DayOfYear)
|
||||||
|
|
||||||
|
CheckOnline();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void CheckOnline(bool showUpToDateMessage = false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (HttpClient client = new HttpClient())
|
||||||
|
{
|
||||||
|
RegistryHelp.SetValue(RegistryHelp.ApplicationKey, "UpdateCheckLast", DateTime.Now.DayOfYear);
|
||||||
|
client.DefaultRequestHeaders.Add("User-Agent", "mpv.net");
|
||||||
|
var response = await client.GetAsync("https://api.github.com/repos/stax76/mpv.net/releases/latest");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
string content = await response.Content.ReadAsStringAsync();
|
||||||
|
Match match = Regex.Match(content, @"""mpv\.net-portable-x64-([\d\.]+)\.7z""");
|
||||||
|
Version onlineVersion = Version.Parse(match.Groups[1].Value);
|
||||||
|
Version currentVersion = Assembly.GetEntryAssembly().GetName().Version;
|
||||||
|
|
||||||
|
if (onlineVersion <= currentVersion)
|
||||||
|
{
|
||||||
|
if (showUpToDateMessage)
|
||||||
|
Msg.Show($"{Application.ProductName} is up to date.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((RegistryHelp.GetString(RegistryHelp.ApplicationKey, "UpdateCheckVersion")
|
||||||
|
!= onlineVersion.ToString() || showUpToDateMessage) && Msg.ShowQuestion(
|
||||||
|
$"New version {onlineVersion} is available, update now?") == MsgResult.OK)
|
||||||
|
{
|
||||||
|
string arch = IntPtr.Size == 8 ? "64" : "86";
|
||||||
|
string url = $"https://github.com/stax76/mpv.net/releases/download/{onlineVersion}/mpv.net-portable-x{arch}-{onlineVersion}.7z";
|
||||||
|
|
||||||
|
using (Process proc = new Process())
|
||||||
|
{
|
||||||
|
proc.StartInfo.UseShellExecute = true;
|
||||||
|
proc.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||||
|
proc.StartInfo.FileName = "PowerShell";
|
||||||
|
proc.StartInfo.Arguments = $"-NoLogo -NoExit -File \"{Folder.Startup + "Update.ps1"}\" \"{url}\" \"{Application.StartupPath.TrimEnd('\\')}\"";
|
||||||
|
|
||||||
|
if (Folder.Startup.Contains("Program Files"))
|
||||||
|
proc.StartInfo.Verb = "runas";
|
||||||
|
|
||||||
|
proc.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
core.command("quit");
|
||||||
|
}
|
||||||
|
|
||||||
|
RegistryHelp.SetValue(RegistryHelp.ApplicationKey, "UpdateCheckVersion", onlineVersion.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (showUpToDateMessage)
|
||||||
|
Msg.ShowException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,45 +1,44 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
public class MediaInfo : IDisposable
|
public class MediaInfo : IDisposable
|
||||||
{
|
{
|
||||||
IntPtr Handle;
|
IntPtr Handle;
|
||||||
static bool Loaded;
|
|
||||||
|
|
||||||
public MediaInfo(string sourcepath)
|
public MediaInfo(string file)
|
||||||
{
|
{
|
||||||
if (!Loaded)
|
if ((Handle = MediaInfo_New()) == IntPtr.Zero)
|
||||||
{
|
throw new Exception("Failed to call MediaInfo_New");
|
||||||
if (LoadLibrary("MediaInfo.dll") == IntPtr.Zero)
|
|
||||||
throw new Exception("Failed to load MediaInfo.dll.");
|
|
||||||
|
|
||||||
Loaded = true;
|
if (MediaInfo_Open(Handle, file) == 0)
|
||||||
|
throw new Exception("Error MediaInfo_Open");
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle = MediaInfo_New();
|
public string GetInfo(MediaInfoStreamKind kind, string parameter)
|
||||||
MediaInfo_Open(Handle, sourcepath);
|
{
|
||||||
|
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, kind, 0,
|
||||||
|
parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetInfo(MediaInfoStreamKind streamKind, string parameter)
|
public int GetCount(MediaInfoStreamKind kind) => MediaInfo_Count_Get(Handle, kind, -1);
|
||||||
|
|
||||||
|
public string GetVideo(int stream, string parameter)
|
||||||
{
|
{
|
||||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, 0, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video,
|
||||||
|
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetCount(MediaInfoStreamKind streamKind) => MediaInfo_Count_Get(Handle, streamKind, -1);
|
public string GetAudio(int stream, string parameter)
|
||||||
|
|
||||||
public string GetVideo(int streamNumber, string parameter)
|
|
||||||
{
|
{
|
||||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio,
|
||||||
|
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetAudio(int streamNumber, string parameter)
|
public string GetText(int stream, string parameter)
|
||||||
{
|
{
|
||||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text,
|
||||||
}
|
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
|
||||||
|
|
||||||
public string GetText(int streamNumber, string parameter)
|
|
||||||
{
|
|
||||||
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Disposed;
|
bool Disposed;
|
||||||
@@ -48,41 +47,45 @@ public class MediaInfo : IDisposable
|
|||||||
{
|
{
|
||||||
if (!Disposed)
|
if (!Disposed)
|
||||||
{
|
{
|
||||||
Disposed = true;
|
if (Handle != IntPtr.Zero)
|
||||||
|
{
|
||||||
MediaInfo_Close(Handle);
|
MediaInfo_Close(Handle);
|
||||||
MediaInfo_Delete(Handle);
|
MediaInfo_Delete(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Disposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~MediaInfo() { Dispose(); }
|
~MediaInfo()
|
||||||
|
{
|
||||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
Dispose();
|
||||||
static extern IntPtr LoadLibrary(string path);
|
}
|
||||||
|
|
||||||
[DllImport("MediaInfo.dll")]
|
[DllImport("MediaInfo.dll")]
|
||||||
static extern IntPtr MediaInfo_New();
|
static extern IntPtr MediaInfo_New();
|
||||||
|
|
||||||
|
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||||
|
static extern int MediaInfo_Open(IntPtr handle, string path);
|
||||||
|
|
||||||
|
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||||
|
static extern IntPtr MediaInfo_Option(IntPtr handle, string option, string value);
|
||||||
|
|
||||||
|
[DllImport("MediaInfo.dll")]
|
||||||
|
static extern IntPtr MediaInfo_Inform(IntPtr handle, int reserved);
|
||||||
|
|
||||||
|
[DllImport("MediaInfo.dll")]
|
||||||
|
static extern int MediaInfo_Close(IntPtr handle);
|
||||||
|
|
||||||
[DllImport("MediaInfo.dll")]
|
[DllImport("MediaInfo.dll")]
|
||||||
static extern void MediaInfo_Delete(IntPtr handle);
|
static extern void MediaInfo_Delete(IntPtr handle);
|
||||||
|
|
||||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||||
static extern int MediaInfo_Open(IntPtr handle, string fileName);
|
static extern IntPtr MediaInfo_Get(IntPtr handle, MediaInfoStreamKind kind,
|
||||||
|
int stream, string parameter, MediaInfoKind infoKind, MediaInfoKind searchKind);
|
||||||
[DllImport("MediaInfo.dll")]
|
|
||||||
static extern int MediaInfo_Close(IntPtr handle);
|
|
||||||
|
|
||||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
||||||
static extern IntPtr MediaInfo_Get(IntPtr handle,
|
static extern int MediaInfo_Count_Get(IntPtr handle, MediaInfoStreamKind streamKind, int stream);
|
||||||
MediaInfoStreamKind streamKind,
|
|
||||||
int streamNumber,
|
|
||||||
string parameter,
|
|
||||||
MediaInfoInfoKind kindOfInfo,
|
|
||||||
MediaInfoInfoKind kindOfSearch);
|
|
||||||
|
|
||||||
[DllImport("MediaInfo.dll", CharSet = CharSet.Unicode)]
|
|
||||||
static extern int MediaInfo_Count_Get(IntPtr handle,
|
|
||||||
MediaInfoStreamKind streamKind,
|
|
||||||
int streamNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MediaInfoStreamKind
|
public enum MediaInfoStreamKind
|
||||||
@@ -97,7 +100,7 @@ public enum MediaInfoStreamKind
|
|||||||
Max,
|
Max,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MediaInfoInfoKind
|
public enum MediaInfoKind
|
||||||
{
|
{
|
||||||
Name,
|
Name,
|
||||||
Text,
|
Text,
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace mpvnet
|
public class WinAPI
|
||||||
{
|
{
|
||||||
public class Native
|
|
||||||
{
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
public static extern bool AttachConsole(int dwProcessId);
|
public static extern bool AttachConsole(int dwProcessId);
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
[DllImport("kernel32.dll")]
|
||||||
public static extern bool FreeConsole();
|
public static extern bool FreeConsole();
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
public static extern IntPtr LoadLibrary(string dllToLoad);
|
public static extern IntPtr LoadLibrary(string path);
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||||
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
|
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
|
||||||
@@ -24,9 +23,12 @@ namespace mpvnet
|
|||||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
|
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||||
public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
|
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")]
|
[DllImport("user32.dll")]
|
||||||
public static extern bool AllowSetForegroundWindow(int dwProcessId);
|
public static extern bool AllowSetForegroundWindow(int dwProcessId);
|
||||||
|
|
||||||
@@ -36,14 +38,14 @@ namespace mpvnet
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
|
public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll")]
|
||||||
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
|
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
||||||
|
|
||||||
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
|
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
|
||||||
private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
|
static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
|
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
|
||||||
private static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);
|
static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
|
public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
|
||||||
{
|
{
|
||||||
@@ -53,6 +55,9 @@ namespace mpvnet
|
|||||||
return GetWindowLong32(hWnd, nIndex);
|
return GetWindowLong32(hWnd, nIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DllImport("gdi32.dll")]
|
||||||
|
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct RECT
|
public struct RECT
|
||||||
{
|
{
|
||||||
@@ -77,7 +82,7 @@ namespace mpvnet
|
|||||||
Bottom = bottom;
|
Bottom = bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle ToRectangle() { return Rectangle.FromLTRB(Left, Top, Right, Bottom); }
|
public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom);
|
||||||
public Size Size => new Size(Right - Left, Bottom - Top);
|
public Size Size => new Size(Right - Left, Bottom - Top);
|
||||||
public int Width => Right - Left;
|
public int Width => Right - Left;
|
||||||
public int Height => Bottom - Top;
|
public int Height => Bottom - Top;
|
||||||
@@ -88,8 +93,7 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
public IntPtr dwData;
|
public IntPtr dwData;
|
||||||
public int cbData;
|
public int cbData;
|
||||||
[MarshalAs(UnmanagedType.LPStr)]
|
[MarshalAs(UnmanagedType.LPTStr)]
|
||||||
public string lpData;
|
public string lpData;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -20,9 +20,9 @@ namespace mpvnet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SubtractWindowBorders(IntPtr hwnd, ref Native.RECT rc)
|
public static void SubtractWindowBorders(IntPtr hwnd, ref WinAPI.RECT rc)
|
||||||
{
|
{
|
||||||
var b = new Native.RECT(0, 0, 0, 0);
|
var b = new WinAPI.RECT(0, 0, 0, 0);
|
||||||
AddWindowBorders(hwnd, ref b);
|
AddWindowBorders(hwnd, ref b);
|
||||||
rc.Left -= b.Left;
|
rc.Left -= b.Left;
|
||||||
rc.Top -= b.Top;
|
rc.Top -= b.Top;
|
||||||
@@ -30,9 +30,9 @@ namespace mpvnet
|
|||||||
rc.Bottom -= b.Bottom;
|
rc.Bottom -= b.Bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddWindowBorders(IntPtr hwnd, ref Native.RECT rc)
|
public static void AddWindowBorders(IntPtr hwnd, ref WinAPI.RECT rc)
|
||||||
{
|
{
|
||||||
Native.AdjustWindowRect(ref rc, (uint)Native.GetWindowLong(hwnd, -16 /* GWL_STYLE */), false);
|
WinAPI.AdjustWindowRect(ref rc, (uint)WinAPI.GetWindowLong(hwnd, -16 /* GWL_STYLE */), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -11,7 +12,7 @@ using System.Windows.Forms;
|
|||||||
|
|
||||||
public class Msg
|
public class Msg
|
||||||
{
|
{
|
||||||
private static string ShownMessages;
|
static string ShownMessages;
|
||||||
|
|
||||||
public static string SupportURL { get; set; }
|
public static string SupportURL { get; set; }
|
||||||
|
|
||||||
@@ -50,23 +51,23 @@ public class Msg
|
|||||||
td.Show();
|
td.Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
|
MessageBox.Show(e.GetType().Name + "\n\n" + e.Message + "\n\n" + e,
|
||||||
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowException(Exception e)
|
public static void ShowException(Exception exception)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (TaskDialog<string> td = new TaskDialog<string>())
|
using (TaskDialog<string> td = new TaskDialog<string>())
|
||||||
{
|
{
|
||||||
td.MainInstruction = e.GetType().Name;
|
td.MainInstruction = exception.GetType().Name;
|
||||||
td.Content = e.Message;
|
td.Content = exception.Message;
|
||||||
td.MainIcon = MsgIcon.Error;
|
td.MainIcon = MsgIcon.Error;
|
||||||
td.ExpandedInformation = e.ToString();
|
td.ExpandedInformation = exception.StackTrace;
|
||||||
td.Footer = "[Copy Message](copymsg)";
|
td.Footer = "[Copy Message](copymsg)";
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Msg.SupportURL))
|
if (!string.IsNullOrEmpty(Msg.SupportURL))
|
||||||
@@ -75,10 +76,9 @@ public class Msg
|
|||||||
td.Show();
|
td.Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
|
MessageBox.Show(e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,20 +95,20 @@ public class Msg
|
|||||||
Msg.ShownMessages += mainInstruction + content;
|
Msg.ShownMessages += mainInstruction + content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MsgResult ShowQuestion(string mainInstruction,
|
public static MsgResult ShowQuestion(
|
||||||
MsgButtons buttons = MsgButtons.OkCancel)
|
string mainInstruction, MsgButtons buttons = MsgButtons.OkCancel)
|
||||||
{
|
{
|
||||||
return Msg.Show(mainInstruction, null, MsgIcon.None, buttons, MsgResult.None);
|
return Msg.Show(mainInstruction, null, MsgIcon.None, buttons, MsgResult.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MsgResult ShowQuestion(string mainInstruction,
|
public static MsgResult ShowQuestion(
|
||||||
string content,
|
string mainInstruction, string content, MsgButtons buttons = MsgButtons.OkCancel)
|
||||||
MsgButtons buttons = MsgButtons.OkCancel)
|
|
||||||
{
|
{
|
||||||
return Msg.Show(mainInstruction, content, MsgIcon.None, buttons, MsgResult.None);
|
return Msg.Show(mainInstruction, content, MsgIcon.None, buttons, MsgResult.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MsgResult Show(string mainInstruction,
|
public static MsgResult Show(
|
||||||
|
string mainInstruction,
|
||||||
string content,
|
string content,
|
||||||
MsgIcon icon,
|
MsgIcon icon,
|
||||||
MsgButtons buttons,
|
MsgButtons buttons,
|
||||||
@@ -144,9 +144,9 @@ public class Msg
|
|||||||
return td.Show();
|
return td.Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
return (MsgResult)MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
|
return (MsgResult)MessageBox.Show(e.GetType().Name + "\n\n" + e.Message + "\n\n" + e,
|
||||||
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,14 +154,20 @@ public class Msg
|
|||||||
|
|
||||||
public class TaskDialog<T> : TaskDialogNative, IDisposable
|
public class TaskDialog<T> : TaskDialogNative, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, T> IdValueDic;
|
Dictionary<int, T> IdValueDic;
|
||||||
private Dictionary<int, string> IdTextDic;
|
Dictionary<int, string> IdTextDic;
|
||||||
private List<int> CommandLinkShieldList;
|
List<int> CommandLinkShieldList;
|
||||||
private IntPtr ButtonArray;
|
IntPtr ButtonArray;
|
||||||
private IntPtr RadioButtonArray;
|
IntPtr RadioButtonArray;
|
||||||
private List<TaskDialogNative.TASKDIALOG_BUTTON> Buttons;
|
T SelectedValueValue;
|
||||||
private List<TaskDialogNative.TASKDIALOG_BUTTON> RadioButtons;
|
string SelectedTextValue;
|
||||||
private TaskDialogNative.TASKDIALOGCONFIG Config;
|
int TimeoutValue;
|
||||||
|
int ExitTickCount;
|
||||||
|
bool Disposed;
|
||||||
|
List<TaskDialogNative.TASKDIALOG_BUTTON> Buttons;
|
||||||
|
List<TaskDialogNative.TASKDIALOG_BUTTON> RadioButtons;
|
||||||
|
TaskDialogNative.TASKDIALOGCONFIG Config;
|
||||||
|
|
||||||
const int TDE_CONTENT = 0;
|
const int TDE_CONTENT = 0;
|
||||||
const int TDE_EXPANDED_INFORMATION = 1;
|
const int TDE_EXPANDED_INFORMATION = 1;
|
||||||
const int TDE_FOOTER = 2;
|
const int TDE_FOOTER = 2;
|
||||||
@@ -192,11 +198,6 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
const int TDM_UPDATE_ELEMENT_TEXT = 1138;
|
const int TDM_UPDATE_ELEMENT_TEXT = 1138;
|
||||||
const int TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = 1139;
|
const int TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = 1139;
|
||||||
const int TDM_UPDATE_ICON = 1140;
|
const int TDM_UPDATE_ICON = 1140;
|
||||||
private T SelectedValueValue;
|
|
||||||
private string SelectedTextValue;
|
|
||||||
private int TimeoutValue;
|
|
||||||
private int ExitTickCount;
|
|
||||||
private bool disposed;
|
|
||||||
|
|
||||||
public TaskDialog()
|
public TaskDialog()
|
||||||
{
|
{
|
||||||
@@ -235,6 +236,7 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
|
|
||||||
if (Path.GetFileName(lpszFileName.ToString().Replace(".vshost", "")) ==
|
if (Path.GetFileName(lpszFileName.ToString().Replace(".vshost", "")) ==
|
||||||
Path.GetFileName(Assembly.GetEntryAssembly().Location))
|
Path.GetFileName(Assembly.GetEntryAssembly().Location))
|
||||||
|
|
||||||
return foregroundWindow;
|
return foregroundWindow;
|
||||||
|
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
@@ -283,13 +285,14 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
set => Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION((int)value);
|
set => Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION((int)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _SelectedID;
|
int _SelectedID;
|
||||||
|
|
||||||
public int SelectedID {
|
public int SelectedID {
|
||||||
get => _SelectedID;
|
get => _SelectedID;
|
||||||
set {
|
set {
|
||||||
foreach (var i in IdValueDic)
|
foreach (var i in IdValueDic)
|
||||||
if (i.Key == value) _SelectedID = value;
|
if (i.Key == value)
|
||||||
|
_SelectedID = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,6 +300,7 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
get {
|
get {
|
||||||
if (IdValueDic.ContainsKey(SelectedID))
|
if (IdValueDic.ContainsKey(SelectedID))
|
||||||
return IdValueDic[SelectedID];
|
return IdValueDic[SelectedID];
|
||||||
|
|
||||||
return SelectedValueValue;
|
return SelectedValueValue;
|
||||||
}
|
}
|
||||||
set => SelectedValueValue = value;
|
set => SelectedValueValue = value;
|
||||||
@@ -306,13 +310,15 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
get {
|
get {
|
||||||
if (IdTextDic.ContainsKey(SelectedID))
|
if (IdTextDic.ContainsKey(SelectedID))
|
||||||
return IdTextDic[SelectedID];
|
return IdTextDic[SelectedID];
|
||||||
|
|
||||||
return SelectedTextValue;
|
return SelectedTextValue;
|
||||||
}
|
}
|
||||||
set => SelectedTextValue = value;
|
set => SelectedTextValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CheckBoxChecked {
|
public bool CheckBoxChecked {
|
||||||
get => (Config.dwFlags & TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) == TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
get => (Config.dwFlags & TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED)
|
||||||
|
== TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
||||||
set {
|
set {
|
||||||
if (value)
|
if (value)
|
||||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
|
||||||
@@ -353,24 +359,30 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
value = regex.Replace(value, "<a href=\"$2\">$1</a>");
|
value = regex.Replace(value, "<a href=\"$2\">$1</a>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCommandLink(string text, T value)
|
public void AddCommand(string text, T value)
|
||||||
{
|
{
|
||||||
int n = 1000 + IdValueDic.Count + 1;
|
int n = 1000 + IdValueDic.Count + 1;
|
||||||
IdValueDic[n] = value == null ? (T)(object)text : value;
|
IdValueDic[n] = value;
|
||||||
IdTextDic[n] = text;
|
IdTextDic[n] = text;
|
||||||
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
||||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
|
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCommandLink(string text, string description, T value, bool setShield = false)
|
public void AddCommand(string text, string description, T value, bool setShield = false)
|
||||||
{
|
{
|
||||||
int n = 1000 + IdValueDic.Count + 1;
|
int n = 1000 + IdValueDic.Count + 1;
|
||||||
IdValueDic[n] = value;
|
IdValueDic[n] = value;
|
||||||
if (setShield) CommandLinkShieldList.Add(n);
|
|
||||||
if (!string.IsNullOrEmpty(description)) text += "\n" + description;
|
if (setShield)
|
||||||
|
CommandLinkShieldList.Add(n);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(description))
|
||||||
|
text += "\n" + description;
|
||||||
|
|
||||||
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
|
||||||
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
|
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
|
||||||
}
|
}
|
||||||
@@ -386,10 +398,17 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
{
|
{
|
||||||
MarshalDialogControlStructs();
|
MarshalDialogControlStructs();
|
||||||
TaskDialogNative.TASKDIALOGCONFIG config = Config;
|
TaskDialogNative.TASKDIALOGCONFIG config = Config;
|
||||||
int errorCode = TaskDialogNative.TaskDialogIndirect(config, out int dummy1, out int dummy2, out bool isChecked);
|
int hr = TaskDialogNative.TaskDialogIndirect(
|
||||||
if (errorCode < 0) Marshal.ThrowExceptionForHR(errorCode);
|
config, out int dummy1, out int dummy2, out bool isChecked);
|
||||||
|
|
||||||
|
if (hr < 0)
|
||||||
|
Marshal.ThrowExceptionForHR(hr);
|
||||||
|
|
||||||
CheckBoxChecked = isChecked;
|
CheckBoxChecked = isChecked;
|
||||||
if (SelectedValue is MsgResult) SelectedValue = (T)(object)SelectedID;
|
|
||||||
|
if (SelectedValue is MsgResult)
|
||||||
|
SelectedValue = (T)(object)SelectedID;
|
||||||
|
|
||||||
return SelectedValue;
|
return SelectedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,8 +429,10 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
break;
|
break;
|
||||||
case 3: //TDN_HYPERLINK_CLICKED
|
case 3: //TDN_HYPERLINK_CLICKED
|
||||||
string stringUni = Marshal.PtrToStringUni(lParam);
|
string stringUni = Marshal.PtrToStringUni(lParam);
|
||||||
|
|
||||||
if (stringUni.StartsWith("mailto") || stringUni.StartsWith("http"))
|
if (stringUni.StartsWith("mailto") || stringUni.StartsWith("http"))
|
||||||
Process.Start(stringUni);
|
Process.Start(stringUni);
|
||||||
|
|
||||||
if (stringUni == "copymsg")
|
if (stringUni == "copymsg")
|
||||||
{
|
{
|
||||||
Thread thread = new Thread((ThreadStart)(() => {
|
Thread thread = new Thread((ThreadStart)(() => {
|
||||||
@@ -473,8 +494,10 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
|
|
||||||
protected void Dispose(bool disposing)
|
protected void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposed) return;
|
if (Disposed)
|
||||||
disposed = true;
|
return;
|
||||||
|
|
||||||
|
Disposed = true;
|
||||||
|
|
||||||
if (ButtonArray != IntPtr.Zero)
|
if (ButtonArray != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
@@ -491,36 +514,27 @@ public class TaskDialog<T> : TaskDialogNative, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public delegate int PFTASKDIALOGCALLBACK(
|
public delegate int PFTASKDIALOGCALLBACK(
|
||||||
IntPtr hwnd,
|
IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, IntPtr lpRefData);
|
||||||
uint msg,
|
|
||||||
IntPtr wParam,
|
|
||||||
IntPtr lParam,
|
|
||||||
IntPtr lpRefData);
|
|
||||||
|
|
||||||
public class TaskDialogNative
|
public class TaskDialogNative
|
||||||
{
|
{
|
||||||
[DllImport("comctl32", CharSet = CharSet.Unicode, SetLastError = true)]
|
[DllImport("comctl32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
public static extern int TaskDialogIndirect(
|
public static extern int TaskDialogIndirect(
|
||||||
[In] TaskDialogNative.TASKDIALOGCONFIG pTaskConfig,
|
TaskDialogNative.TASKDIALOGCONFIG pTaskConfig,
|
||||||
out int pnButton,
|
out int pnButton,
|
||||||
out int pnRadioButton,
|
out int pnRadioButton,
|
||||||
[MarshalAs(UnmanagedType.Bool)] out bool pVerificationFlagChecked);
|
out bool pVerificationFlagChecked);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr GetForegroundWindow();
|
public static extern IntPtr GetForegroundWindow();
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||||
public static extern uint GetWindowModuleFileName(
|
public static extern uint GetWindowModuleFileName(
|
||||||
IntPtr hwnd,
|
IntPtr hwnd, StringBuilder lpszFileName, uint cchFileNameMax);
|
||||||
StringBuilder lpszFileName,
|
|
||||||
uint cchFileNameMax);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr SendMessage(
|
public static extern IntPtr SendMessage(
|
||||||
IntPtr handle,
|
IntPtr handle, int message, IntPtr wParam, IntPtr lParam);
|
||||||
int message,
|
|
||||||
IntPtr wParam,
|
|
||||||
IntPtr lParam);
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
|
||||||
public class TASKDIALOGCONFIG
|
public class TASKDIALOGCONFIG
|
||||||
@@ -530,12 +544,9 @@ public class TaskDialogNative
|
|||||||
public IntPtr hInstance;
|
public IntPtr hInstance;
|
||||||
public TaskDialogNative.TASKDIALOG_FLAGS dwFlags;
|
public TaskDialogNative.TASKDIALOG_FLAGS dwFlags;
|
||||||
public MsgButtons dwCommonButtons;
|
public MsgButtons dwCommonButtons;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszWindowTitle;
|
public string pszWindowTitle;
|
||||||
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION MainIcon;
|
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION MainIcon;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszMainInstruction;
|
public string pszMainInstruction;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszContent;
|
public string pszContent;
|
||||||
public uint cButtons;
|
public uint cButtons;
|
||||||
public IntPtr pButtons;
|
public IntPtr pButtons;
|
||||||
@@ -543,16 +554,11 @@ public class TaskDialogNative
|
|||||||
public uint cRadioButtons;
|
public uint cRadioButtons;
|
||||||
public IntPtr pRadioButtons;
|
public IntPtr pRadioButtons;
|
||||||
public int nDefaultRadioButton;
|
public int nDefaultRadioButton;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszVerificationText;
|
public string pszVerificationText;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszExpandedInformation;
|
public string pszExpandedInformation;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszExpandedControlText;
|
public string pszExpandedControlText;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszCollapsedControlText;
|
public string pszCollapsedControlText;
|
||||||
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION FooterIcon;
|
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION FooterIcon;
|
||||||
[MarshalAs(UnmanagedType.LPWStr)]
|
|
||||||
public string pszFooter;
|
public string pszFooter;
|
||||||
public PFTASKDIALOGCALLBACK pfCallback;
|
public PFTASKDIALOGCALLBACK pfCallback;
|
||||||
public IntPtr lpCallbackData;
|
public IntPtr lpCallbackData;
|
||||||
|
|||||||
55
mpv.net/Native/Taskbar.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
public class Taskbar
|
||||||
|
{
|
||||||
|
public IntPtr Handle { get; set; }
|
||||||
|
|
||||||
|
public Taskbar(IntPtr handle) => Handle = handle;
|
||||||
|
|
||||||
|
ITaskbarList3 Instance = (ITaskbarList3)new TaskBarCommunication();
|
||||||
|
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF")]
|
||||||
|
interface ITaskbarList3
|
||||||
|
{
|
||||||
|
// ITaskbarList
|
||||||
|
[PreserveSig] void HrInit();
|
||||||
|
[PreserveSig] void AddTab(IntPtr hwnd);
|
||||||
|
[PreserveSig] void DeleteTab(IntPtr hwnd);
|
||||||
|
[PreserveSig] void ActivateTab(IntPtr hwnd);
|
||||||
|
[PreserveSig] void SetActiveAlt(IntPtr hwnd);
|
||||||
|
// ITaskbarList2
|
||||||
|
[PreserveSig] void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
|
||||||
|
// ITaskbarList3
|
||||||
|
[PreserveSig] void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
|
||||||
|
[PreserveSig] void SetProgressState(IntPtr hwnd, TaskbarStates state);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[ClassInterface(ClassInterfaceType.None)]
|
||||||
|
[Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
|
||||||
|
class TaskBarCommunication
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetState(TaskbarStates taskbarState)
|
||||||
|
{
|
||||||
|
Instance.SetProgressState(Handle, taskbarState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue(double progressValue, double progressMax)
|
||||||
|
{
|
||||||
|
Instance.SetProgressValue(Handle, (UInt64)progressValue, (UInt64)progressMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TaskbarStates
|
||||||
|
{
|
||||||
|
NoProgress = 0,
|
||||||
|
Indeterminate = 0x1,
|
||||||
|
Normal = 0x2,
|
||||||
|
Error = 0x4,
|
||||||
|
Paused = 0x8
|
||||||
|
}
|
||||||
@@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
|
|||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("mpv.net")]
|
[assembly: AssemblyTitle("mpv.net")]
|
||||||
[assembly: AssemblyDescription("media player")]
|
[assembly: AssemblyDescription("mpv based media player")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
[assembly: AssemblyCompany("Frank Skare (stax76)")]
|
||||||
[assembly: AssemblyProduct("mpv.net")]
|
[assembly: AssemblyProduct("mpv.net")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2017-2019 Frank Skare (stax76)")]
|
[assembly: AssemblyCopyright("Copyright (C) 2017-2020 Frank Skare (stax76)")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("5.0.0.0")]
|
[assembly: AssemblyVersion("5.4.6.0")]
|
||||||
[assembly: AssemblyFileVersion("5.0.0.0")]
|
[assembly: AssemblyFileVersion("5.4.6.0")]
|
||||||
|
|||||||
154
mpv.net/Properties/Resources.Designer.cs
generated
@@ -62,62 +62,63 @@ namespace mpvnet.Properties {
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to
|
/// Looks up a localized string similar to
|
||||||
/// # This file defines the input (keys and mouse) bindings of mpv and mpv.net
|
///[[settings]]
|
||||||
/// # and it also defines the context menu of mpv.net. mpv.net has an input
|
|
||||||
/// # editor and an config editor as alternative to editing conf text files.
|
|
||||||
/// # The input and config editor can be found in mpv.net's context menu at:
|
|
||||||
///
|
|
||||||
/// # Settings > Show Config Editor
|
|
||||||
/// # Settings > Show Input Editor
|
|
||||||
///
|
|
||||||
/// # The defaults of this file can be found at:
|
|
||||||
///
|
|
||||||
/// # https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt
|
|
||||||
///
|
|
||||||
/// # th [rest of string was truncated]";.
|
|
||||||
/// </summary>
|
|
||||||
internal static string inputConf {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("inputConf", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to
|
|
||||||
///# manual: https://mpv.io/manual/master/
|
|
||||||
///
|
|
||||||
///# defaults: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt
|
|
||||||
///
|
|
||||||
///input-ar-delay = 500
|
|
||||||
///input-ar-rate = 20
|
|
||||||
///volume = 50
|
|
||||||
///hwdec = yes
|
|
||||||
///keep-open = yes
|
|
||||||
///keep-open-pause = no
|
|
||||||
///osd-playing-msg = '${filename}'
|
|
||||||
///screenshot-directory = '~~desktop/'
|
|
||||||
///input-default-bindings = no
|
|
||||||
///script-opts=osc-scalewindowed=1.5.
|
|
||||||
/// </summary>
|
|
||||||
internal static string mpvConf {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("mpvConf", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to [[settings]]
|
|
||||||
///name = "hwdec"
|
///name = "hwdec"
|
||||||
|
///file = "mpv"
|
||||||
///default = "no"
|
///default = "no"
|
||||||
///filter = "Video"
|
///filter = "Video"
|
||||||
///url = "https://mpv.io/manual/master/#options-hwdec"
|
///url = "https://mpv.io/manual/master/#options-hwdec"
|
||||||
///help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
|
///help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
|
||||||
///options = [{ name = "no", help = "always use software decoding" },
|
///options = [{ name = "no", help = "always use software decoding" },
|
||||||
/// { name = "auto", help = "enable be [rest of string was truncated]";.
|
/// { name = "auto", h [rest of string was truncated]";.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string mpvConfToml {
|
internal static string editor_toml {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("mpvConfToml", resourceCulture);
|
return ResourceManager.GetString("editor_toml", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to
|
||||||
|
/// # This file defines the key and mouse bindings and the context menu
|
||||||
|
/// # of mpv.net. A input and config editor can be found in mpv.nets
|
||||||
|
/// # context menu under 'Settings'. The defaults of this file can be found at:
|
||||||
|
///
|
||||||
|
/// # https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt
|
||||||
|
///
|
||||||
|
/// # The defaults of mpv can be found at:
|
||||||
|
///
|
||||||
|
/// # https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||||
|
///
|
||||||
|
/// # mpv.net's defaults of mpv.conf contain: 'input-default-bindings = no'
|
||||||
|
/// # which disables mpv's i [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
internal static string input_conf {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("input_conf", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to
|
||||||
|
///input-default-bindings = no
|
||||||
|
///input-ar-delay = 500
|
||||||
|
///input-ar-rate = 20
|
||||||
|
///keep-open = yes
|
||||||
|
///keep-open-pause = no
|
||||||
|
///osd-duration = 2000
|
||||||
|
///osd-playing-msg = '${filename}'
|
||||||
|
///script-opts = osc-scalewindowed=1.5,osc-hidetimeout=2000,console-scale=1
|
||||||
|
///screenshot-directory = '~~desktop/'
|
||||||
|
///hwdec = yes
|
||||||
|
///
|
||||||
|
///[protocol.https]
|
||||||
|
///osd-playing-msg = '${media-title}'
|
||||||
|
///.
|
||||||
|
/// </summary>
|
||||||
|
internal static string mpv_conf {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("mpv_conf", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,39 +133,38 @@ namespace mpvnet.Properties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to dark-color = '#1E90FF'
|
/// Looks up a localized string similar to
|
||||||
///light-color = '#28394F'.
|
///[dark]
|
||||||
/// </summary>
|
|
||||||
internal static string mpvNetConf {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("mpvNetConf", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to [[settings]]
|
|
||||||
///name = "dark-mode"
|
|
||||||
///default = "always"
|
|
||||||
///filter = "General"
|
|
||||||
///help = "Enables a dark theme. (mpv.net specific setting)"
|
|
||||||
///options = [{ name = "always" },
|
|
||||||
/// { name = "system" , help = "Available on Windows 10 or higher" },
|
|
||||||
/// { name = "never" }]
|
|
||||||
///
|
///
|
||||||
///[[settings]]
|
///heading = #3C8CC8
|
||||||
///name = "dark-color"
|
///foreground = #DDDDDD
|
||||||
///type = "color"
|
///foreground2 = #AAAAAA
|
||||||
///filter = "General"
|
///background = #323232
|
||||||
///help = "Theme color used in dark-mode. Leave empty to use OS theme. (mpv.net specific setting)"
|
|
||||||
///
|
///
|
||||||
///[[settings]]
|
///menu-foreground = #DDDDDD
|
||||||
///name = "light-color"
|
///menu-background = #323232
|
||||||
///type = "color"
|
///menu-highlight = #505050
|
||||||
///filter = "General" [rest of string was truncated]";.
|
///menu-border = #FFFFFF
|
||||||
|
///menu-checked = #5A5A5A
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///[light]
|
||||||
|
///
|
||||||
|
///heading = #0068B2
|
||||||
|
///foreground = #000000
|
||||||
|
///foreground2 = #4C4C4C
|
||||||
|
///background = #F7F7F7
|
||||||
|
///
|
||||||
|
///menu-foreground = #000000
|
||||||
|
///menu-background = #DFDFDF
|
||||||
|
///menu-highlight = #BFBFBF
|
||||||
|
///menu-border = #6A6A6A
|
||||||
|
///menu-checked = #AAAAAA
|
||||||
|
///.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string mpvNetConfToml {
|
internal static string theme {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("mpvNetConfToml", resourceCulture);
|
return ResourceManager.GetString("theme", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,22 +118,19 @@
|
|||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
<data name="inputConf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="editor_toml" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\inputConf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
<value>..\Resources\editor.toml.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="mpvConf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="input_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\mpvConf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
<value>..\Resources\input.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||||
</data>
|
|
||||||
<data name="mpvConfToml" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\mpvConfToml.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="mpvnet" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<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>
|
<value>..\Resources\mpvnet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="mpvNetConf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="mpv_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\mpvNetConf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
<value>..\Resources\mpv.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="mpvNetConfToml" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="theme" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\mpvNetConfToml.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>
|
||||||
</root>
|
</root>
|
||||||
2
mpv.net/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace mpvnet.Properties {
|
|||||||
|
|
||||||
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
|
||||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
[[settings]]
|
|
||||||
|
[[settings]]
|
||||||
name = "hwdec"
|
name = "hwdec"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
url = "https://mpv.io/manual/master/#options-hwdec"
|
url = "https://mpv.io/manual/master/#options-hwdec"
|
||||||
@@ -21,16 +23,18 @@ options = [{ name = "no", help = "always use software decoding" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "gpu-api"
|
name = "gpu-api"
|
||||||
|
file = "mpv"
|
||||||
default = "auto"
|
default = "auto"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "Controls which type of graphics APIs will be accepted."
|
help = "Controls which type of graphics APIs will be accepted. Auto uses d3d11, it should only be changed in case of problems, Vulkan is not recommended."
|
||||||
options = [{ name = "auto", help = "Use any available API" },
|
options = [{ name = "auto", help = "Use any available API" },
|
||||||
{ name = "opengl", help = "Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)" },
|
{ name = "opengl", help = "Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)" },
|
||||||
{ name = "vulkan", help = "Allow only Vulkan (requires a valid/working spirv-compiler)" },
|
{ name = "vulkan", help = "Allow only Vulkan (not recommended). " },
|
||||||
{ name = "d3d11", help = "Allow only gpu-context=d3d11" }]
|
{ name = "d3d11", help = "Allow only gpu-context=d3d11" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "gpu-context"
|
name = "gpu-context"
|
||||||
|
file = "mpv"
|
||||||
default = "auto"
|
default = "auto"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
options = [{ name = "auto", help = "auto-select" },
|
options = [{ name = "auto", help = "auto-select" },
|
||||||
@@ -42,6 +46,7 @@ options = [{ name = "auto", help = "auto-select" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "vo"
|
name = "vo"
|
||||||
|
file = "mpv"
|
||||||
default = "gpu"
|
default = "gpu"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "Video output drivers to be used.\n\nFor more information visit:"
|
help = "Video output drivers to be used.\n\nFor more information visit:"
|
||||||
@@ -51,6 +56,7 @@ options = [{ name = "gpu", help = "General purpose, customizable, GPU-accel
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "video-sync"
|
name = "video-sync"
|
||||||
|
file = "mpv"
|
||||||
default = "audio"
|
default = "audio"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "How the player synchronizes audio and video.\n\nFor more information visit:"
|
help = "How the player synchronizes audio and video.\n\nFor more information visit:"
|
||||||
@@ -66,6 +72,7 @@ options = [{ name = "audio" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "scale"
|
name = "scale"
|
||||||
|
file = "mpv"
|
||||||
default = "bilinear"
|
default = "bilinear"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "The GPU renderer filter function to use when upscaling video. There are some more filters, but most are not as useful. For a complete list, pass help as value, e.g.: mpv --scale=help"
|
help = "The GPU renderer filter function to use when upscaling video. There are some more filters, but most are not as useful. For a complete list, pass help as value, e.g.: mpv --scale=help"
|
||||||
@@ -80,6 +87,7 @@ options = [{ name = "bilinear", help = "Bilinear hardware texture filter
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "cscale"
|
name = "cscale"
|
||||||
|
file = "mpv"
|
||||||
default = "bilinear"
|
default = "bilinear"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "As scale, but for interpolating chroma information. If the image is not subsampled, this option is ignored entirely."
|
help = "As scale, but for interpolating chroma information. If the image is not subsampled, this option is ignored entirely."
|
||||||
@@ -94,6 +102,7 @@ options = [{ name = "bilinear", help = "Bilinear hardware texture filter
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "dscale"
|
name = "dscale"
|
||||||
|
file = "mpv"
|
||||||
default = "bilinear"
|
default = "bilinear"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "Like scale, but apply these filters on downscaling instead. If this option is unset, the filter implied by scale will be applied."
|
help = "Like scale, but apply these filters on downscaling instead. If this option is unset, the filter implied by scale will be applied."
|
||||||
@@ -108,6 +117,7 @@ options = [{ name = "bilinear", help = "Bilinear hardware texture filter
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "dither-depth"
|
name = "dither-depth"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "Set dither target depth to N. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output."
|
help = "Set dither target depth to N. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output."
|
||||||
@@ -117,6 +127,7 @@ options = [{ name = "no", help = "Disable any dithering done by mpv." },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "correct-downscaling"
|
name = "correct-downscaling"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "When using convolution based filters, extend the filter size when downscaling. Increases quality, but reduces performance while downscaling.\n\nThis will perform slightly sub-optimally for anamorphic video (but still better than without it) since it will extend the size to match only the milder of the scale factors between the axes."
|
help = "When using convolution based filters, extend the filter size when downscaling. Increases quality, but reduces performance while downscaling.\n\nThis will perform slightly sub-optimally for anamorphic video (but still better than without it) since it will extend the size to match only the milder of the scale factors between the axes."
|
||||||
@@ -125,6 +136,7 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sigmoid-upscaling"
|
name = "sigmoid-upscaling"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "When upscaling, use a sigmoidal color transform to avoid emphasizing ringing artifacts. This also implies linear-scaling."
|
help = "When upscaling, use a sigmoidal color transform to avoid emphasizing ringing artifacts. This also implies linear-scaling."
|
||||||
@@ -133,26 +145,57 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "deband"
|
name = "deband"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Video"
|
filter = "Video"
|
||||||
help = "Enable the debanding algorithm. This greatly reduces the amount of visible banding, blocking and other quantization artifacts, at the expense of very slightly blurring some of the finest details. In practice, it's virtually always an improvement - the only reason to disable it would be for performance."
|
help = "Enable the debanding algorithm. This greatly reduces the amount of visible banding, blocking and other quantization artifacts, at the expense of very slightly blurring some of the finest details. In practice, it's virtually always an improvement - the only reason to disable it would be for performance."
|
||||||
options = [{ name = "yes" },
|
options = [{ name = "yes" },
|
||||||
{ name = "no" }]
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "d3d11va-zero-copy"
|
||||||
|
file = "mpv"
|
||||||
|
default = "no"
|
||||||
|
filter = "Video"
|
||||||
|
help = "By default, when using hardware decoding with --gpu-api=d3d11, the video image will be copied (GPU-to-GPU) from the decoder surface to a shader resource. Set this option to avoid that copy by sampling directly from the decoder image. This may increase performance and reduce power usage, but can cause the image to be sampled incorrectly on the bottom and right edges due to padding, and may invoke driver bugs, since Direct3D 11 technically does not allow sampling from a decoder surface (though most drivers support it.)"
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "hdr-compute-peak"
|
||||||
|
file = "mpv"
|
||||||
|
default = "auto"
|
||||||
|
filter = "Video"
|
||||||
|
help = "Compute the HDR peak and frame average brightness per-frame instead of relying on tagged metadata. These values are averaged over local regions as well as over several frames to prevent the value from jittering around too much. This option basically gives you dynamic, per-scene tone mapping. Requires compute shaders, which is a fairly recent OpenGL feature, and will probably also perform horribly on some drivers, so enable at your own risk. The special value auto (default) will enable HDR peak computation automatically if compute shaders and SSBOs are supported."
|
||||||
|
options = [{ name = "auto" },
|
||||||
|
{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "volume"
|
name = "volume"
|
||||||
default = "100"
|
file = "mpv"
|
||||||
filter = "Audio"
|
filter = "Audio"
|
||||||
help = "Set the startup volume. 0 means silence, 100 means no volume reduction or amplification. Negative values can be passed for compatibility, but are treated as 0. Since mpv 0.18.1, this always controls the internal mixer (aka \"softvol\"). Default: 100"
|
help = "Set the startup volume. 0 means silence, 100 means no volume reduction or amplification. Negative values can be passed for compatibility, but are treated as 0. Since mpv 0.18.1, this always controls the internal mixer (aka \"softvol\"). Default: 100"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "remember-volume"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "yes"
|
||||||
|
filter = "Audio"
|
||||||
|
help = "Save volume and mute on exit and restore it on start. (mpv.net specific setting)"
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "alang"
|
name = "alang"
|
||||||
|
file = "mpv"
|
||||||
filter = "Audio"
|
filter = "Audio"
|
||||||
type = "string"
|
type = "string"
|
||||||
help = "Specify a priority list of audio languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two-letter language codes, Matroska, MPEG-TS and NUT use ISO 639-2 three-letter language codes, while OGM uses a free-form identifier. See also aid.\n\nExamples\n\nmpv dvd://1 alang=hu,en chooses the Hungarian language track on a DVD and falls back on English if Hungarian is not available.\n\nmpv alang=jpn example.mkv plays a Matroska file with Japanese audio."
|
help = "Specify a priority list of audio languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two-letter language codes, Matroska, MPEG-TS and NUT use ISO 639-2 three-letter language codes, while OGM uses a free-form identifier. See also aid.\n\nExamples\n\nmpv dvd://1 alang=hu,en chooses the Hungarian language track on a DVD and falls back on English if Hungarian is not available.\n\nmpv alang=jpn example.mkv plays a Matroska file with Japanese audio."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "audio-file-auto"
|
name = "audio-file-auto"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Audio"
|
filter = "Audio"
|
||||||
help = "Load additional audio files matching the video filename. The parameter specifies how external audio files are matched."
|
help = "Load additional audio files matching the video filename. The parameter specifies how external audio files are matched."
|
||||||
@@ -163,12 +206,14 @@ options = [{ name = "no", help = "Don't automatically load external audio fil
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "slang"
|
name = "slang"
|
||||||
|
file = "mpv"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
type = "string"
|
type = "string"
|
||||||
help = "Specify a priority list of subtitle languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two letter language codes, Matroska uses ISO 639-2 three letter language codes while OGM uses a free-form identifier. See also sid."
|
help = "Specify a priority list of subtitle languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two letter language codes, Matroska uses ISO 639-2 three letter language codes while OGM uses a free-form identifier. See also sid."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sub-auto"
|
name = "sub-auto"
|
||||||
|
file = "mpv"
|
||||||
default = "exact"
|
default = "exact"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
help = "Load additional subtitle files matching the video filename. The parameter specifies how external subtitle files are matched. exact is enabled by default."
|
help = "Load additional subtitle files matching the video filename. The parameter specifies how external subtitle files are matched. exact is enabled by default."
|
||||||
@@ -179,35 +224,41 @@ options = [{ name = "no", help = "Don't automatically load external subtitle
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sub-font"
|
name = "sub-font"
|
||||||
|
file = "mpv"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
type = "string"
|
type = "string"
|
||||||
help = "Specify font to use for subtitles that do not themselves specify a particular font. The default is sans-serif."
|
help = "Specify font to use for subtitles that do not themselves specify a particular font. The default is sans-serif."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sub-font-size"
|
name = "sub-font-size"
|
||||||
|
file = "mpv"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
help = "Specify the sub font size. The unit is the size in scaled pixels at a window height of 720. The actual pixel size is scaled with the window height: if the window height is larger or smaller than 720, the actual size of the text increases or decreases as well. Default: 55"
|
help = "Specify the sub font size. The unit is the size in scaled pixels at a window height of 720. The actual pixel size is scaled with the window height: if the window height is larger or smaller than 720, the actual size of the text increases or decreases as well. Default: 55"
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sub-color"
|
name = "sub-color"
|
||||||
|
file = "mpv"
|
||||||
type = "color"
|
type = "color"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
help = "Specify the color used for unstyled text subtitles.\n\nThe color is specified in the form r/g/b, where each color component is specified as number in the range 0.0 to 1.0. It's also possible to specify the transparency by using r/g/b/a, where the alpha value 0 means fully transparent, and 1.0 means opaque. If the alpha component is not given, the color is 100% opaque.\n\nPassing a single number to the option sets the sub to gray, and the form gray/a lets you specify alpha additionally.\n\nExamples\n\n1.0/0.0/0.0 set sub to opaque red\n1.0/0.0/0.0/0.75 set sub to opaque red with 75% alpha\n0.5/0.75 set sub to 50% gray with 75% alpha\n\nAlternatively, the color can be specified as a RGB hex triplet in the form #RRGGBB, where each 2-digit group expresses a color value in the range 0 (00) to 255 (FF). For example, #FF0000 is red. This is similar to web colors. Alpha is given with #AARRGGBB.\n\nExamples\n\n#FF0000 set sub to opaque red\n#C0808080 set sub to 50% gray with 75% alpha"
|
help = "Specify the color used for unstyled text subtitles.\n\nThe color is specified in the form r/g/b, where each color component is specified as number in the range 0.0 to 1.0. It's also possible to specify the transparency by using r/g/b/a, where the alpha value 0 means fully transparent, and 1.0 means opaque. If the alpha component is not given, the color is 100% opaque.\n\nPassing a single number to the option sets the sub to gray, and the form gray/a lets you specify alpha additionally.\n\nExamples\n\n1.0/0.0/0.0 set sub to opaque red\n1.0/0.0/0.0/0.75 set sub to opaque red with 75% alpha\n0.5/0.75 set sub to 50% gray with 75% alpha\n\nAlternatively, the color can be specified as a RGB hex triplet in the form #RRGGBB, where each 2-digit group expresses a color value in the range 0 (00) to 255 (FF). For example, #FF0000 is red. This is similar to web colors. Alpha is given with #AARRGGBB.\n\nExamples\n\n#FF0000 set sub to opaque red\n#C0808080 set sub to 50% gray with 75% alpha"
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sub-border-color"
|
name = "sub-border-color"
|
||||||
|
file = "mpv"
|
||||||
type = "color"
|
type = "color"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
help = "See sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent)."
|
help = "See sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent)."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "sub-back-color"
|
name = "sub-back-color"
|
||||||
|
file = "mpv"
|
||||||
type = "color"
|
type = "color"
|
||||||
filter = "Subtitle"
|
filter = "Subtitle"
|
||||||
help = "See sub-color. Color used for sub text background. You can use sub-shadow-offset to change its size relative to the text."
|
help = "See sub-color. Color used for sub text background. You can use sub-shadow-offset to change its size relative to the text."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "fullscreen"
|
name = "fullscreen"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "Start the player in fullscreen mode."
|
help = "Start the player in fullscreen mode."
|
||||||
@@ -216,6 +267,7 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "border"
|
name = "border"
|
||||||
|
file = "mpv"
|
||||||
default = "yes"
|
default = "yes"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "Show window with decoration (titlebar, border)."
|
help = "Show window with decoration (titlebar, border)."
|
||||||
@@ -224,11 +276,13 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screen"
|
name = "screen"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<0-32> In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on."
|
help = "<0-32> In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "osd-playing-msg"
|
name = "osd-playing-msg"
|
||||||
|
file = "mpv"
|
||||||
width = 300
|
width = 300
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
type = "string"
|
type = "string"
|
||||||
@@ -237,27 +291,86 @@ url = "https://mpv.io/manual/master/#property-expansion"
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "osd-font-size"
|
name = "osd-font-size"
|
||||||
default = "55"
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "Specify the OSD font size. See sub-font-size for details. Default: 55"
|
help = "Specify the OSD font size. See sub-font-size for details. Default: 55"
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "autofit"
|
name = "osd-duration"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<int> Initial window height in percent. Default: 50%"
|
help = "Set the duration of the OSD messages in ms. Default: 1000"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "osd-scale-by-window"
|
||||||
|
file = "mpv"
|
||||||
|
default = "yes"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "Whether to scale the OSD with the window size. If this is disabled, osd-font-size and other OSD options that use scaled pixels are always in actual pixels. The effect is that changing the window size won't change the OSD font size."
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "autofit"
|
||||||
|
file = "mpv"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "<int> Initial window height in percent. Default: 50"
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "autofit-smaller"
|
name = "autofit-smaller"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<int> Minimum window height in percent. Default: 40%"
|
help = "<int> Minimum window height in percent. Default: 30"
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "autofit-larger"
|
name = "autofit-larger"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<int> Maximum window height in percent. Default: 75%"
|
help = "<int> Maximum window height in percent. Default: 80"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "start-size"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "previous"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "Setting to remember the window height. (mpv.net specific setting)"
|
||||||
|
options = [{ name = "video", help = "Window size is set to video resolution" },
|
||||||
|
{ name = "previous", help = "Window size is remembered but only in the current session" },
|
||||||
|
{ name = "always", help = "Window size is always remembered"}]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "start-threshold"
|
||||||
|
file = "mpvnet"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "Threshold in milliseconds to wait for libmpv returning the video resolution before the window is shown, otherwise default dimensions are used as defined by autofit and start-size. Default: 1500 (mpv.net specific setting)"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "minimum-aspect-ratio"
|
||||||
|
file = "mpvnet"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "<float> Minimum aspect ratio for the window. Default: 1.2 (mpv.net specific setting)"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "remember-position"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "no"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "Save the window position on exit. (mpv.net specific setting)"
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "window-maximized"
|
||||||
|
file = "mpv"
|
||||||
|
default = "no"
|
||||||
|
filter = "Screen"
|
||||||
|
help = "Start with a maximized window."
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-directory"
|
name = "screenshot-directory"
|
||||||
|
file = "mpv"
|
||||||
width = 500
|
width = 500
|
||||||
type = "folder"
|
type = "folder"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
@@ -265,6 +378,7 @@ help = "Store screenshots in this directory. This path is joined with the filena
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-format"
|
name = "screenshot-format"
|
||||||
|
file = "mpv"
|
||||||
default = "jpg"
|
default = "jpg"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "Set the image file type used for saving screenshots."
|
help = "Set the image file type used for saving screenshots."
|
||||||
@@ -273,6 +387,7 @@ options = [{ name = "jpg" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-tag-colorspace"
|
name = "screenshot-tag-colorspace"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "Tag screenshots with the appropriate colorspace. Note that not all formats are supported."
|
help = "Tag screenshots with the appropriate colorspace. Note that not all formats are supported."
|
||||||
@@ -281,22 +396,25 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-high-bit-depth"
|
name = "screenshot-high-bit-depth"
|
||||||
|
file = "mpv"
|
||||||
default = "yes"
|
default = "yes"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "If possible, write screenshots with a bit depth similar to the source video (default: yes). This is interesting in particular for PNG, as this sometimes triggers writing 16 bit PNGs with huge file sizes. This will also include an unused alpha channel in the resulting files if 16 bit is used."
|
help = "If possible, write screenshots with a bit depth similar to the source video. This is interesting in particular for PNG, as this sometimes triggers writing 16 bit PNGs with huge file sizes. This will also include an unused alpha channel in the resulting files if 16 bit is used."
|
||||||
options = [{ name = "yes" },
|
options = [{ name = "yes" },
|
||||||
{ name = "no" }]
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-jpeg-source-chroma"
|
name = "screenshot-jpeg-source-chroma"
|
||||||
|
file = "mpv"
|
||||||
default = "yes"
|
default = "yes"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "Write JPEG files with the same chroma subsampling as the video (default: yes). If disabled, the libjpeg default is used."
|
help = "Write JPEG files with the same chroma subsampling as the video. If disabled, the libjpeg default is used."
|
||||||
options = [{ name = "yes" },
|
options = [{ name = "yes" },
|
||||||
{ name = "no" }]
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-template"
|
name = "screenshot-template"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
type = "string"
|
type = "string"
|
||||||
help = "Specify the filename template used to save screenshots. The template specifies the filename without file extension, and can contain format specifiers, which will be substituted when taking a screenshot. By default, the template is mpv-shot%n, which results in filenames like mpv-shot0012.png for example.\n\nFind the full documentation here:"
|
help = "Specify the filename template used to save screenshots. The template specifies the filename without file extension, and can contain format specifiers, which will be substituted when taking a screenshot. By default, the template is mpv-shot%n, which results in filenames like mpv-shot0012.png for example.\n\nFind the full documentation here:"
|
||||||
@@ -304,21 +422,34 @@ url = "https://mpv.io/manual/master/#options-screenshot-template"
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-jpeg-quality"
|
name = "screenshot-jpeg-quality"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<0-100> Set the JPEG quality level. Higher means better quality. The default is 90."
|
help = "<0-100> Set the JPEG quality level. Higher means better quality. The default is 90."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-png-compression"
|
name = "screenshot-png-compression"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<0-9> Set the PNG compression level. Higher means better compression. This will affect the file size of the written screenshot file and the time it takes to write a screenshot. Too high compression might occupy enough CPU time to interrupt playback. The default is 7."
|
help = "<0-9> Set the PNG compression level. Higher means better compression. This will affect the file size of the written screenshot file and the time it takes to write a screenshot. Too high compression might occupy enough CPU time to interrupt playback. The default is 7."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "screenshot-png-filter"
|
name = "screenshot-png-filter"
|
||||||
|
file = "mpv"
|
||||||
filter = "Screen"
|
filter = "Screen"
|
||||||
help = "<0-5> Set the filter applied prior to PNG compression. 0 is none, 1 is 'sub', 2 is 'up', 3 is 'average', 4 is 'Paeth', and 5 is 'mixed'. This affects the level of compression that can be achieved. For most images, 'mixed' achieves the best compression ratio, hence it is the default."
|
help = "<0-5> Set the filter applied prior to PNG compression. 0 is none, 1 is 'sub', 2 is 'up', 3 is 'average', 4 is 'Paeth', and 5 is 'mixed'. This affects the level of compression that can be achieved. For most images, 'mixed' achieves the best compression ratio, hence it is the default."
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "taskbar-progress"
|
||||||
|
file = "mpv"
|
||||||
|
default = "yes"
|
||||||
|
filter = "Playback"
|
||||||
|
help = "Show progress in taskbar."
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "keep-open-pause"
|
name = "keep-open-pause"
|
||||||
|
file = "mpv"
|
||||||
default = "yes"
|
default = "yes"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "If set to no, instead of pausing when keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again."
|
help = "If set to no, instead of pausing when keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again."
|
||||||
@@ -327,38 +458,32 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "keep-open"
|
name = "keep-open"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "Do not terminate when playing or seeking beyond the end of the file, and there is not next file to be played (and loop is not used). Instead, pause the player. When trying to seek beyond end of the file, the player will attempt to seek to the last frame.\n\nNormally, this will act like set pause yes on EOF, unless the keep-open-pause=no option is set."
|
help = "Using no, mpv would terminate after the last file but mpv.net never terminates automatically."
|
||||||
options = [{ name = "yes", help = "Don't terminate if the current file is the last playlist entry. Equivalent to keep-open without arguments."},
|
options = [{ name = "yes", help = "If the current file ends, go to the next file, keep the last file open."},
|
||||||
{ name = "no", help = "If the current file ends, go to the next file or terminate." },
|
{ name = "no", help = "If the current file ends, go to the next file." },
|
||||||
{ name = "always", help = "Like yes, but also applies to files before the last playlist entry. This means playback will never automatically advance to the next file."}]
|
{ name = "always", help = "Playback will never automatically advance to the next file."}]
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "loop-file"
|
name = "loop-file"
|
||||||
|
file = "mpv"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "<N|inf|no> Loop a single file N times. inf means forever, no means normal playback.\n\nThe difference to loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file. loop is an alias for this option."
|
help = "<N|inf|no> Loop a single file N times. inf means forever, no means normal playback.\n\nThe difference to loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file. loop is an alias for this option."
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "save-position-on-quit"
|
name = "save-position-on-quit"
|
||||||
|
file = "mpv"
|
||||||
default = "no"
|
default = "no"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "Always save the current playback position on quit. When this file is played again later, the player will seek to the old playback position on start. This does not happen if playback of a file is stopped in any other way than quitting. For example, going to the next file in the playlist will not save the position, and start playback at beginning the next time the file is played.\n\nThis behavior is disabled by default, but is always available when quitting the player with Shift+Q."
|
help = "Always save the current playback position on quit. When this file is played again later, the player will seek to the old playback position on start. This does not happen if playback of a file is stopped in any other way than quitting. For example, going to the next file in the playlist will not save the position, and start playback at beginning the next time the file is played.\n\nThis behavior is disabled by default, but is always available when quitting the player with Shift+Q."
|
||||||
options = [{ name = "yes" },
|
options = [{ name = "yes" },
|
||||||
{ name = "no" }]
|
{ name = "no" }]
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "input-ar-delay"
|
|
||||||
filter = "Input"
|
|
||||||
help = "Delay in milliseconds before we start to autorepeat a key (0 to disable)."
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "input-ar-rate"
|
|
||||||
filter = "Input"
|
|
||||||
help = "Number of key presses to generate per second on autorepeat."
|
|
||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "hr-seek"
|
name = "hr-seek"
|
||||||
|
file = "mpv"
|
||||||
default = "absolute"
|
default = "absolute"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "Select when to use precise seeks that are not limited to keyframes. Such seeks require decoding video from the previous keyframe up to the target position and so can take some time depending on decoding performance. For some video formats, precise seeks are disabled. This option selects the default choice to use for seeks; it is possible to explicitly override that default in the definition of key bindings and in input commands."
|
help = "Select when to use precise seeks that are not limited to keyframes. Such seeks require decoding video from the previous keyframe up to the target position and so can take some time depending on decoding performance. For some video formats, precise seeks are disabled. This option selects the default choice to use for seeks; it is possible to explicitly override that default in the definition of key bindings and in input commands."
|
||||||
@@ -369,6 +494,7 @@ options = [{ name = "yes", help = "Use precise seeks whenever possible." },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "track-auto-selection"
|
name = "track-auto-selection"
|
||||||
|
file = "mpv"
|
||||||
default = "yes"
|
default = "yes"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "Enable the default track auto-selection. Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected."
|
help = "Enable the default track auto-selection. Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected."
|
||||||
@@ -377,5 +503,85 @@ options = [{ name = "yes" },
|
|||||||
|
|
||||||
[[settings]]
|
[[settings]]
|
||||||
name = "loop-playlist"
|
name = "loop-playlist"
|
||||||
|
file = "mpv"
|
||||||
filter = "Playback"
|
filter = "Playback"
|
||||||
help = "<N|inf|force|no> Loops playback N times. A value of 1 plays it one time (default), 2 two times, etc. inf means forever. no is the same as 1 and disables looping. If several files are specified on command line, the entire playlist is looped. The force mode is like inf, but does not skip playlist entries which have been marked as failing. This means the player might waste CPU time trying to loop a file that doesn't exist. But it might be useful for playing webradios under very bad network conditions."
|
help = "<N|inf|force|no> Loops playback N times. A value of 1 plays it one time (default), 2 two times, etc. inf means forever. no is the same as 1 and disables looping. If several files are specified on command line, the entire playlist is looped. The force mode is like inf, but does not skip playlist entries which have been marked as failing. This means the player might waste CPU time trying to loop a file that doesn't exist. But it might be useful for playing webradios under very bad network conditions."
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "auto-load-folder"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "yes"
|
||||||
|
filter = "Playback"
|
||||||
|
help = "For single files automatically load the entire directory into the playlist. Can be suppressed via shift key. (mpv.net specific setting)"
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "input-ar-delay"
|
||||||
|
file = "mpv"
|
||||||
|
filter = "Input"
|
||||||
|
help = "Delay in milliseconds before we start to autorepeat a key (0 to disable)."
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "input-ar-rate"
|
||||||
|
file = "mpv"
|
||||||
|
filter = "Input"
|
||||||
|
help = "Number of key presses to generate per second on autorepeat."
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "update-check"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "no"
|
||||||
|
filter = "General"
|
||||||
|
help = "Daily check for new version. (requires PowerShell 5 and curl. mpv.net specific setting)"
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "process-instance"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "single"
|
||||||
|
filter = "General"
|
||||||
|
help = "Defines if more then one mpv.net process is allowed. (mpv.net specific setting)\n\nTip: Whenever the control key is pressed when files or URLs are opened, the playlist is not cleared but the files or URLs are appended to the playlist. This not only works on process startup but in all mpv.net features that open files and URLs."
|
||||||
|
options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" },
|
||||||
|
{ name = "single", help = "Force a single process everytime the shell starts mpv.net" },
|
||||||
|
{ name = "queue", help = "Force a single process and add files to playlist" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "recent-count"
|
||||||
|
file = "mpvnet"
|
||||||
|
filter = "General"
|
||||||
|
help = "<int> Amount of recent files to be remembered. Default: 15 (mpv.net specific setting)"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "debug-mode"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "no"
|
||||||
|
filter = "General"
|
||||||
|
help = "Enable this only when a developer asks for it. (mpv.net specific setting)"
|
||||||
|
options = [{ name = "yes" },
|
||||||
|
{ name = "no" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "dark-mode"
|
||||||
|
file = "mpvnet"
|
||||||
|
default = "always"
|
||||||
|
filter = "UI"
|
||||||
|
help = "Enables a dark theme. (mpv.net specific setting)"
|
||||||
|
options = [{ name = "always" },
|
||||||
|
{ name = "system" , help = "Available on Windows 10 or higher" },
|
||||||
|
{ name = "never" }]
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "dark-theme"
|
||||||
|
file = "mpvnet"
|
||||||
|
filter = "UI"
|
||||||
|
url = "https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme"
|
||||||
|
help = "Color theme used in dark mode. Default: dark"
|
||||||
|
|
||||||
|
[[settings]]
|
||||||
|
name = "light-theme"
|
||||||
|
file = "mpvnet"
|
||||||
|
filter = "UI"
|
||||||
|
url = "https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme"
|
||||||
|
help = "Color theme used in light mode. Default: light"
|
||||||
@@ -1,33 +1,26 @@
|
|||||||
|
|
||||||
# This file defines the input (keys and mouse) bindings of mpv and mpv.net
|
# This file defines the key and mouse bindings and the context menu
|
||||||
# and it also defines the context menu of mpv.net. mpv.net has an input
|
# of mpv.net. A input and config editor can be found in mpv.nets
|
||||||
# editor and an config editor as alternative to editing conf text files.
|
# context menu under 'Settings'. The defaults of this file can be found at:
|
||||||
# The input and config editor can be found in mpv.net's context menu at:
|
|
||||||
|
|
||||||
# Settings > Show Config Editor
|
# https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt
|
||||||
# Settings > Show Input Editor
|
|
||||||
|
|
||||||
# The defaults of this file can be found at:
|
# The defaults of mpv can be found at:
|
||||||
|
|
||||||
# https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt
|
|
||||||
|
|
||||||
# the defaults of mpv can be found at:
|
|
||||||
|
|
||||||
# https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
# https://github.com/mpv-player/mpv/blob/master/etc/input.conf
|
||||||
|
|
||||||
# mpv.net's defaults of mpv.conf contain: 'input-default-bindings = no'
|
# mpv.net's defaults of mpv.conf contain: 'input-default-bindings = no'
|
||||||
# which disables mpv's input defaults. Every line in this file begins with a
|
# which disables mpv's input defaults. Every line in this file begins with a
|
||||||
# space character to make it easier to do a text search, so if you want to know
|
# space character to make it easier to do a text search, so if you want to know
|
||||||
# if 'o' has already a binding you can make a text search on ' o '.
|
# if 'o' has already a binding you can do a text search on ' o '.
|
||||||
|
|
||||||
# mpv input commands: https://github.com/stax76/mpv.net/wiki/mpv-input-commands
|
# mpv input commands: https://mpv.io/manual/master/#list-of-input-commands
|
||||||
|
|
||||||
# mpv input keys: https://github.com/stax76/mpv.net/wiki/mpv-input-keys
|
|
||||||
|
|
||||||
# run mpv.net in input test mode with: mpvnet --input-test
|
# run mpv.net in input test mode with: mpvnet --input-test
|
||||||
|
|
||||||
o script-message mpv.net open-files #menu: Open > Open Files...
|
o script-message mpv.net open-files #menu: Open > Open Files...
|
||||||
u script-message mpv.net open-url #menu: Open > Open URL or file path from clipboard
|
u script-message mpv.net open-url #menu: Open > Open URL or file path from clipboard
|
||||||
|
_ script-message mpv.net open-optical-media #menu: Open > Open DVD/Blu-ray Drive/Folder...
|
||||||
_ ignore #menu: Open > -
|
_ ignore #menu: Open > -
|
||||||
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
|
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
|
||||||
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
|
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
|
||||||
@@ -46,20 +39,23 @@
|
|||||||
F11 playlist-prev #menu: Navigate > Previous File
|
F11 playlist-prev #menu: Navigate > Previous File
|
||||||
F12 playlist-next #menu: Navigate > Next File
|
F12 playlist-next #menu: Navigate > Next File
|
||||||
_ ignore #menu: Navigate > -
|
_ ignore #menu: Navigate > -
|
||||||
|
Home script-message mpv.net playlist-first #menu: Navigate > First File
|
||||||
|
End script-message mpv.net playlist-last #menu: Navigate > Last File
|
||||||
|
_ ignore #menu: Navigate > -
|
||||||
PGUP add chapter 1 #menu: Navigate > Next Chapter
|
PGUP add chapter 1 #menu: Navigate > Next Chapter
|
||||||
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
|
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
|
||||||
_ ignore #menu: Navigate > -
|
_ ignore #menu: Navigate > -
|
||||||
. frame-step #menu: Navigate > Jump Next Frame
|
. frame-step #menu: Navigate > Jump Next Frame
|
||||||
, frame-back-step #menu: Navigate > Jump Previous Frame
|
, frame-back-step #menu: Navigate > Jump Previous Frame
|
||||||
_ ignore #menu: Navigate > -
|
_ ignore #menu: Navigate > -
|
||||||
Right no-osd seek 7 #menu: Navigate > Jump 7 sec forward
|
Right seek 7 #menu: Navigate > Jump 7 sec forward
|
||||||
Left no-osd seek -7 #menu: Navigate > Jump 7 sec backward
|
Left seek -7 #menu: Navigate > Jump 7 sec backward
|
||||||
_ ignore #menu: Navigate > -
|
_ ignore #menu: Navigate > -
|
||||||
Up no-osd seek 40 #menu: Navigate > Jump 40 sec forward
|
Up seek 40 #menu: Navigate > Jump 40 sec forward
|
||||||
Down no-osd seek -40 #menu: Navigate > Jump 40 sec backward
|
Down seek -40 #menu: Navigate > Jump 40 sec backward
|
||||||
_ ignore #menu: Navigate > -
|
_ ignore #menu: Navigate > -
|
||||||
Ctrl+Right no-osd seek 300 #menu: Navigate > Jump 5 min forward
|
Ctrl+Right seek 300 #menu: Navigate > Jump 5 min forward
|
||||||
Ctrl+Left no-osd seek -300 #menu: Navigate > Jump 5 min backward
|
Ctrl+Left seek -300 #menu: Navigate > Jump 5 min backward
|
||||||
_ ignore #menu: Navigate > -
|
_ ignore #menu: Navigate > -
|
||||||
_ ignore #menu: Navigate > Chapters
|
_ ignore #menu: Navigate > Chapters
|
||||||
|
|
||||||
@@ -136,6 +132,8 @@
|
|||||||
|
|
||||||
Ctrl+t set ontop yes #menu: View > On Top > Enable
|
Ctrl+t set ontop yes #menu: View > On Top > Enable
|
||||||
Ctrl+T set ontop no #menu: View > On Top > Disable
|
Ctrl+T set ontop no #menu: View > On Top > Disable
|
||||||
|
Alt++ no-osd set window-scale 1.2 #menu: View > Window Size > Enlarge
|
||||||
|
Alt+- no-osd set window-scale 0.8 #menu: View > Window Size > Shrink
|
||||||
b cycle border #menu: View > Toggle Border
|
b cycle border #menu: View > Toggle Border
|
||||||
i script-message mpv.net show-info #menu: View > File/Stream Info
|
i script-message mpv.net show-info #menu: View > File/Stream Info
|
||||||
t script-binding stats/display-stats #menu: View > Show Statistics
|
t script-binding stats/display-stats #menu: View > Show Statistics
|
||||||
@@ -143,6 +141,11 @@
|
|||||||
Del script-binding osc/visibility #menu: View > Toggle OSC Visibility
|
Del script-binding osc/visibility #menu: View > Toggle OSC Visibility
|
||||||
F8 script-binding show-playlist #menu: View > Show Playlist
|
F8 script-binding show-playlist #menu: View > Show Playlist
|
||||||
F9 show-text ${track-list} 5000 #menu: View > Show Audio/Video/Subtitle List
|
F9 show-text ${track-list} 5000 #menu: View > Show Audio/Video/Subtitle List
|
||||||
|
p show-progress #menu: View > Show Progress
|
||||||
|
Ctrl+p script-message mpv.net show-profiles #menu: View > Show Profiles
|
||||||
|
Shift+p script-message mpv.net show-properties #menu: View > Show Properties
|
||||||
|
Shift+c script-message mpv.net show-commands #menu: View > Show Commands
|
||||||
|
` script-binding console/enable #menu: View > Show Console
|
||||||
|
|
||||||
c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
|
c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
|
||||||
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor
|
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor
|
||||||
@@ -152,16 +155,17 @@
|
|||||||
h script-message mpv.net show-history #menu: Tools > Show History
|
h script-message mpv.net show-history #menu: Tools > Show History
|
||||||
l ab-loop #menu: Tools > Set/clear A-B loop points
|
l ab-loop #menu: Tools > Set/clear A-B loop points
|
||||||
L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping
|
L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping
|
||||||
|
_ cycle shuffle #menu: Tools > Toggle Shuffle
|
||||||
Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Toggle Hardware Decoding
|
Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Toggle Hardware Decoding
|
||||||
_ script-message mpv.net execute-mpv-command #menu: Tools > Execute mpv command...
|
_ script-message mpv.net show-setup-dialog #menu: Tools > Setup...
|
||||||
_ script-message mpv.net manage-file-associations #menu: Tools > Manage File Associations...
|
|
||||||
|
|
||||||
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Show mpv manual
|
_ script-message mpv.net shell-execute https://mpv.io #menu: Help > Website mpv
|
||||||
_ script-message mpv.net shell-execute https://github.com/mpv-player/mpv/blob/master/etc/input.conf #menu: Help > Show mpv default keys
|
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net #menu: Help > Website mpv.net
|
||||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt #menu: Help > Show mpv.net default keys
|
|
||||||
_ script-message mpv.net shell-execute https://mpv-net.github.io/mpv.net-web-site/ #menu: Help > Show mpv.net web site
|
|
||||||
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/Manual.md #menu: Help > Show mpv.net manual
|
|
||||||
_ ignore #menu: Help > -
|
_ ignore #menu: Help > -
|
||||||
|
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Manual mpv
|
||||||
|
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/Manual.md #menu: Help > Manual mpv.net
|
||||||
|
_ ignore #menu: Help > -
|
||||||
|
_ script-message mpv.net update-check #menu: Help > Check for Updates
|
||||||
_ script-message mpv.net show-about #menu: Help > About mpv.net
|
_ script-message mpv.net show-about #menu: Help > About mpv.net
|
||||||
|
|
||||||
_ ignore #menu: -
|
_ ignore #menu: -
|
||||||
@@ -181,6 +185,8 @@
|
|||||||
Volume_Down add volume -10
|
Volume_Down add volume -10
|
||||||
Wheel_Up add volume 10
|
Wheel_Up add volume 10
|
||||||
Wheel_Down add volume -10
|
Wheel_Down add volume -10
|
||||||
|
Wheel_Left add volume -10
|
||||||
|
Wheel_Right add volume 10
|
||||||
Prev playlist-prev
|
Prev playlist-prev
|
||||||
Next playlist-next
|
Next playlist-next
|
||||||
MBTN_Forward playlist-next
|
MBTN_Forward playlist-next
|
||||||
@@ -191,4 +197,4 @@
|
|||||||
Ctrl+Wheel_Down no-osd seek -7
|
Ctrl+Wheel_Down no-osd seek -7
|
||||||
MBTN_Left_DBL cycle fullscreen
|
MBTN_Left_DBL cycle fullscreen
|
||||||
KP_Enter cycle fullscreen
|
KP_Enter cycle fullscreen
|
||||||
MBTN_Left ignore
|
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
|
|
||||||
# manual: https://mpv.io/manual/master/
|
input-default-bindings = no
|
||||||
|
|
||||||
# defaults: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt
|
|
||||||
|
|
||||||
input-ar-delay = 500
|
input-ar-delay = 500
|
||||||
input-ar-rate = 20
|
input-ar-rate = 20
|
||||||
volume = 50
|
|
||||||
hwdec = yes
|
|
||||||
keep-open = yes
|
keep-open = yes
|
||||||
keep-open-pause = no
|
keep-open-pause = no
|
||||||
|
osd-duration = 2000
|
||||||
osd-playing-msg = '${filename}'
|
osd-playing-msg = '${filename}'
|
||||||
|
script-opts = osc-scalewindowed=1.5,osc-hidetimeout=2000,console-scale=1
|
||||||
screenshot-directory = '~~desktop/'
|
screenshot-directory = '~~desktop/'
|
||||||
input-default-bindings = no
|
hwdec = yes
|
||||||
script-opts=osc-scalewindowed=1.5
|
|
||||||
|
[protocol.https]
|
||||||
|
osd-playing-msg = '${media-title}'
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
dark-color = '#1E90FF'
|
|
||||||
light-color = '#28394F'
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
[[settings]]
|
|
||||||
name = "dark-mode"
|
|
||||||
default = "always"
|
|
||||||
filter = "General"
|
|
||||||
help = "Enables a dark theme. (mpv.net specific setting)"
|
|
||||||
options = [{ name = "always" },
|
|
||||||
{ name = "system" , help = "Available on Windows 10 or higher" },
|
|
||||||
{ name = "never" }]
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "dark-color"
|
|
||||||
type = "color"
|
|
||||||
filter = "General"
|
|
||||||
help = "Theme color used in dark-mode. Leave empty to use OS theme. (mpv.net specific setting)"
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "light-color"
|
|
||||||
type = "color"
|
|
||||||
filter = "General"
|
|
||||||
help = "Theme color used when dark-mode is disabled. Leave empty to use OS theme. (mpv.net specific setting)"
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "url-whitelist"
|
|
||||||
filter = "General"
|
|
||||||
type = "string"
|
|
||||||
help = "Whitelist setting to monitor the clipboard for URLs to play. (mpv.net specific setting)\n\nDefault: tube vimeo ard zdf"
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "process-instance"
|
|
||||||
default = "single"
|
|
||||||
filter = "General"
|
|
||||||
help = "Defines if more then one mpv.net process is allowed. (mpv.net specific setting)\n\nTip: Whenever the control key is pressed when files or URLs are opened, the playlist is not cleared but the files or URLs are appended to the playlist. This not only works on process startup but in all mpv.net features that open files."
|
|
||||||
options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" },
|
|
||||||
{ name = "single", help = "Force a single process everytime the shell starts mpv.net" },
|
|
||||||
{ name = "queue", help = "Force a single process and add files to playlist" }]
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "debug-mode"
|
|
||||||
default = "no"
|
|
||||||
filter = "General"
|
|
||||||
help = "Enable this only when a developer asks for it. (mpv.net specific setting)"
|
|
||||||
options = [{ name = "yes" },
|
|
||||||
{ name = "no" }]
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "start-size"
|
|
||||||
default = "previous"
|
|
||||||
filter = "Screen"
|
|
||||||
help = "Setting to remember the window height in the current session, otherwise the video's native resolution is used. (mpv.net specific setting)"
|
|
||||||
options = [{ name = "video", help = "Window size is set to native video resolution" },
|
|
||||||
{ name = "previous", help = "Window size is remembered but only from the current session" }]
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "start-threshold"
|
|
||||||
filter = "Screen"
|
|
||||||
help = "Threshold in milliseconds to wait for libmpv returning the video resolution before the window is shown, otherwise default dimensions are used as defined by autofit and start-size. (mpv.net specific setting) Default: 1500"
|
|
||||||
|
|
||||||
[[settings]]
|
|
||||||
name = "remember-position"
|
|
||||||
default = "no"
|
|
||||||
filter = "Screen"
|
|
||||||
help = "Setting to save the window position on exit. (mpv.net specific setting)"
|
|
||||||
options = [{ name = "yes" },
|
|
||||||
{ name = "no" }]
|
|
||||||
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
27
mpv.net/Resources/theme.txt
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
[dark]
|
||||||
|
|
||||||
|
heading = #3C8CC8
|
||||||
|
foreground = #DDDDDD
|
||||||
|
foreground2 = #AAAAAA
|
||||||
|
background = #323232
|
||||||
|
|
||||||
|
menu-foreground = #DDDDDD
|
||||||
|
menu-background = #323232
|
||||||
|
menu-highlight = #505050
|
||||||
|
menu-border = #FFFFFF
|
||||||
|
menu-checked = #5A5A5A
|
||||||
|
|
||||||
|
|
||||||
|
[light]
|
||||||
|
|
||||||
|
heading = #0068B2
|
||||||
|
foreground = #000000
|
||||||
|
foreground2 = #4C4C4C
|
||||||
|
background = #F7F7F7
|
||||||
|
|
||||||
|
menu-foreground = #000000
|
||||||
|
menu-background = #DFDFDF
|
||||||
|
menu-highlight = #BFBFBF
|
||||||
|
menu-border = #6A6A6A
|
||||||
|
menu-checked = #AAAAAA
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Management.Automation.Runspaces;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class PowerShellScript
|
|
||||||
{
|
|
||||||
public static object Execute(string code, string[] parameters)
|
|
||||||
{
|
|
||||||
using (Runspace runspace = RunspaceFactory.CreateRunspace())
|
|
||||||
{
|
|
||||||
runspace.ApartmentState = ApartmentState.STA;
|
|
||||||
runspace.Open();
|
|
||||||
|
|
||||||
using (Pipeline pipeline = runspace.CreatePipeline())
|
|
||||||
{
|
|
||||||
pipeline.Commands.AddScript(
|
|
||||||
"Using namespace mpvnet\n" +
|
|
||||||
"Using namespace System\n" +
|
|
||||||
"[System.Reflection.Assembly]::LoadWithPartialName(\"mpvnet\")\n");
|
|
||||||
|
|
||||||
pipeline.Commands.AddScript(code);
|
|
||||||
|
|
||||||
if (parameters != null)
|
|
||||||
foreach (var i in parameters)
|
|
||||||
pipeline.Commands[1].Parameters.Add(null, i);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ret = pipeline.Invoke();
|
|
||||||
if (ret.Count > 0) return ret[0];
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (Pipeline pipeline2 = runspace.CreatePipeline())
|
|
||||||
{
|
|
||||||
pipeline2.Commands.AddScript("$PSVersionTable.PSVersion.Major * 10 +" +
|
|
||||||
"$PSVersionTable.PSVersion.Minor");
|
|
||||||
|
|
||||||
if (Convert.ToInt32(pipeline2.Invoke()[0].ToString()) < 51)
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e2)
|
|
||||||
{
|
|
||||||
Msg.ShowError("PowerShell Setup Problem\n\nEnsure you have at least PowerShell 5.1 installed.", e2.ToString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Msg.ShowException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Init(string filePath)
|
|
||||||
{
|
|
||||||
foreach (var eventInfo in typeof(mp).GetEvents())
|
|
||||||
{
|
|
||||||
if (eventInfo.Name.ToLower() ==
|
|
||||||
Path.GetFileNameWithoutExtension(filePath).ToLower().Replace("-", ""))
|
|
||||||
{
|
|
||||||
PowerShellEventObject eventObject = new PowerShellEventObject();
|
|
||||||
MethodInfo mi;
|
|
||||||
eventObject.FilePath = filePath;
|
|
||||||
|
|
||||||
if (eventInfo.EventHandlerType == typeof(Action))
|
|
||||||
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.Invoke));
|
|
||||||
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
|
|
||||||
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.InvokeEndFileEventMode));
|
|
||||||
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
|
|
||||||
mi = eventObject.GetType().GetMethod(nameof(PowerShellEventObject.InvokeStrings));
|
|
||||||
else
|
|
||||||
throw new Exception();
|
|
||||||
|
|
||||||
eventObject.EventInfo = eventInfo;
|
|
||||||
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
|
|
||||||
eventObject.Delegate = handler;
|
|
||||||
eventInfo.AddEventHandler(eventObject, handler);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Task.Run(() => PowerShellScript.Execute(File.ReadAllText(filePath), null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PowerShellEventObject
|
|
||||||
{
|
|
||||||
public EventInfo EventInfo { get; set; }
|
|
||||||
public Delegate Delegate { get; set; }
|
|
||||||
public string FilePath { get; set; }
|
|
||||||
|
|
||||||
public void Invoke() => Task.Run(() => { PowerShellScript.Execute(File.ReadAllText(FilePath), null); });
|
|
||||||
|
|
||||||
public void InvokeEndFileEventMode(EndFileEventMode arg)
|
|
||||||
{
|
|
||||||
Task.Run(() => PowerShellScript.Execute(File.ReadAllText(FilePath), new [] { arg.ToString() }));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InvokeStrings(string[] args)
|
|
||||||
{
|
|
||||||
Task.Run(() => PowerShellScript.Execute(File.ReadAllText(FilePath), args));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using Microsoft.Scripting;
|
|
||||||
using Microsoft.Scripting.Hosting;
|
|
||||||
|
|
||||||
using IronPython.Hosting;
|
|
||||||
using IronPython.Runtime;
|
|
||||||
using IronPython.Runtime.Operations;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public class PythonScript
|
|
||||||
{
|
|
||||||
ScriptEngine engine;
|
|
||||||
ScriptScope scope;
|
|
||||||
|
|
||||||
public PythonScript(string code)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
engine = Python.CreateEngine();
|
|
||||||
scope = engine.CreateScope();
|
|
||||||
scope.ImportModule("clr");
|
|
||||||
engine.Execute("import clr", scope);
|
|
||||||
engine.Execute("clr.AddReference(\"mpvnet\")", scope);
|
|
||||||
engine.Execute("import mpvnet", scope);
|
|
||||||
engine.Execute("from mpvnet import *", scope);
|
|
||||||
engine.Execute(code, scope);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is SyntaxErrorException e)
|
|
||||||
Msg.ShowError($"{e.Line}, {e.Column}: " + ex.Message);
|
|
||||||
else
|
|
||||||
Msg.ShowException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PythonEventObject
|
|
||||||
{
|
|
||||||
public PythonFunction PythonFunction { get; set; }
|
|
||||||
public EventInfo EventInfo { get; set; }
|
|
||||||
public Delegate Delegate { get; set; }
|
|
||||||
|
|
||||||
public void Invoke() => PythonCalls.Call(PythonFunction);
|
|
||||||
|
|
||||||
public void InvokeEndFileEventMode(EndFileEventMode arg)
|
|
||||||
{
|
|
||||||
PythonCalls.Call(PythonFunction, new[] { arg });
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InvokeStrings(string[] arg)
|
|
||||||
{
|
|
||||||
PythonCalls.Call(PythonFunction, new[] { arg });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
67
mpv.net/Update.ps1
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
if ($args.Length -ne 2) {
|
||||||
|
Write-Host 'Invalid arguments' -ForegroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Get-Command curl.exe)) {
|
||||||
|
Write-Host 'Error using curl.exe' -ForegroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSVersionTable.PSVersion.Major -lt 5) {
|
||||||
|
Write-Host 'PowerShell 5.1 not found' -ForegroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Type -AssemblyName Microsoft.VisualBasic
|
||||||
|
|
||||||
|
# Delete directory using recycle bin
|
||||||
|
function Remove-Directory($directory) {
|
||||||
|
if (Test-Path $directory) {
|
||||||
|
[Microsoft.VisualBasic.FileIO.FileSystem]::
|
||||||
|
DeleteDirectory($directory, 'OnlyErrorDialogs', 'SendToRecycleBin')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentDir = $args[1];
|
||||||
|
|
||||||
|
$targetDir = (Split-Path $currentDir) + "\new version"
|
||||||
|
Remove-Directory $targetDir
|
||||||
|
$targetFile = $targetDir + '.7z'
|
||||||
|
Remove-Item $targetFile -Force -ErrorAction Ignore
|
||||||
|
|
||||||
|
Write-Host 'Download new version' -ForegroundColor Green
|
||||||
|
curl.exe $args[0] --location --output $targetFile
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
Write-Host 'Unpack new version' -ForegroundColor Green
|
||||||
|
& ($currentDir + '\7z\7za.exe') x -y $targetFile -o"$targetDir"
|
||||||
|
if ($LastExitCode) { throw $LastExitCode }
|
||||||
|
|
||||||
|
Write-Host 'Delete downloaded file' -ForegroundColor Green
|
||||||
|
Remove-Item $targetFile -Force -Recurse
|
||||||
|
|
||||||
|
$portableConfigDir = $currentDir + '\portable_config'
|
||||||
|
$portableConfigTempDir = (Split-Path $currentDir) + '\portable config dir temp'
|
||||||
|
Remove-Item $portableConfigTempDir -Force -ErrorAction Ignore
|
||||||
|
|
||||||
|
if (Test-Path $portableConfigDir) {
|
||||||
|
Write-Host 'Backup portable config' -ForegroundColor Green
|
||||||
|
Copy-Item $portableConfigDir $portableConfigTempDir -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host 'Delete current version' -ForegroundColor Green
|
||||||
|
Remove-Directory $currentDir
|
||||||
|
|
||||||
|
Write-Host 'Rename directory' -ForegroundColor Green
|
||||||
|
Rename-Item $targetDir (Split-Path $currentDir -Leaf)
|
||||||
|
|
||||||
|
if (Test-Path $portableConfigTempDir) {
|
||||||
|
Write-Host 'Restore portable config' -ForegroundColor Green
|
||||||
|
Move-Item $portableConfigTempDir $portableConfigDir -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host 'Update is complete' -ForegroundColor Green
|
||||||
@@ -3,14 +3,25 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="About mpv.net" Height="230" Width="420" FontSize="16" ShowInTaskbar="False"
|
|
||||||
WindowStartupLocation="CenterOwner" ResizeMode="NoResize">
|
Title="About mpv.net"
|
||||||
|
Height="230"
|
||||||
|
Width="400"
|
||||||
|
FontSize="16"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
<TextBlock FontSize="48" HorizontalAlignment="Center" Margin="0,0,0,10">mpv.net</TextBlock>
|
<TextBlock FontSize="48" HorizontalAlignment="Center" Margin="0,0,0,10">mpv.net</TextBlock>
|
||||||
<TextBlock HorizontalAlignment="Center">Copyright (c) 2017-2019 Frank Skare (stax76)</TextBlock>
|
<TextBlock HorizontalAlignment="Center">Copyright (C) 2017-2020 Frank Skare (stax76)</TextBlock>
|
||||||
<TextBlock Name="Version" HorizontalAlignment="Center" />
|
<TextBlock Name="Version" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Name="mpvVersion" HorizontalAlignment="Center" />
|
||||||
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,20">MIT License</TextBlock>
|
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,20">MIT License</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using System.Windows;
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
@@ -9,7 +12,8 @@ namespace mpvnet
|
|||||||
public AboutWindow()
|
public AboutWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Version.Text = $"Version {System.Windows.Forms.Application.ProductVersion}";
|
Version.Text = $"mpv.net Version {System.Windows.Forms.Application.ProductVersion} ({File.GetLastWriteTime(System.Windows.Forms.Application.ExecutablePath).ToShortDateString()})";
|
||||||
|
mpvVersion.Text = $"{core.get_property_string("mpv-version")} ({File.GetLastWriteTime(Folder.Startup + "mpv-1.dll").ToShortDateString()})";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPreviewKeyDown(KeyEventArgs e) => Close();
|
protected override void OnPreviewKeyDown(KeyEventArgs e) => Close();
|
||||||
|
|||||||
@@ -3,21 +3,41 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Command Palette" Height="295" Width="400" ResizeMode="NoResize"
|
|
||||||
WindowStartupLocation="CenterOwner" Loaded="Window_Loaded" FontSize="13">
|
Title="Command Palette"
|
||||||
|
Height="295"
|
||||||
|
Width="400"
|
||||||
|
FontSize="13"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Loaded="Window_Loaded">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition></RowDefinition>
|
<RowDefinition></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBox Name="FilterTextBox" PreviewKeyDown="FilterTextBox_PreviewKeyDown" TextChanged="FilterTextBox_TextChanged"></TextBox>
|
|
||||||
<ListView Name="ListView" Grid.Row="1" MouseUp="ListView_MouseUp">
|
<TextBox Name="FilterTextBox"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
PreviewKeyDown="FilterTextBox_PreviewKeyDown"
|
||||||
|
TextChanged="FilterTextBox_TextChanged"/>
|
||||||
|
|
||||||
|
<ListView Name="ListView"
|
||||||
|
Grid.Row="1"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
MouseUp="ListView_MouseUp">
|
||||||
|
|
||||||
<ListView.ItemContainerStyle>
|
<ListView.ItemContainerStyle>
|
||||||
<Style TargetType="ListBoxItem">
|
<Style TargetType="ListBoxItem">
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
|
||||||
</Style>
|
</Style>
|
||||||
</ListView.ItemContainerStyle>
|
</ListView.ItemContainerStyle>
|
||||||
|
|
||||||
<ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -25,8 +45,12 @@
|
|||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
<ColumnDefinition />
|
<ColumnDefinition />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Text="{Binding Path}"></TextBlock>
|
<TextBlock Text="{Binding Path}"></TextBlock>
|
||||||
<TextBlock Grid.Column="1" Text="{Binding Input}" HorizontalAlignment="Right"></TextBlock>
|
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
Text="{Binding Input}"
|
||||||
|
HorizontalAlignment="Right"></TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
@@ -23,30 +22,28 @@ namespace mpvnet
|
|||||||
var yourCostumFilter = new Predicate<object>(item => Filter((CommandItem)item));
|
var yourCostumFilter = new Predicate<object>(item => Filter((CommandItem)item));
|
||||||
CollectionView.Filter = yourCostumFilter;
|
CollectionView.Filter = yourCostumFilter;
|
||||||
ListView.ItemsSource = CollectionView;
|
ListView.ItemsSource = CollectionView;
|
||||||
|
|
||||||
if (App.IsDarkMode)
|
|
||||||
{
|
|
||||||
ListView.Foreground = Brushes.White;
|
|
||||||
ListView.Background = Brushes.Black;
|
|
||||||
FilterTextBox.Foreground = Brushes.White;
|
|
||||||
FilterTextBox.Background = Brushes.Black;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Filter(CommandItem item)
|
bool Filter(CommandItem item)
|
||||||
{
|
{
|
||||||
if (item.Command == "" || item.Path == "")
|
if (item.Command == "" || item.Path == "")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string filter = FilterTextBox.Text.ToLower();
|
string filter = FilterTextBox.Text.ToLower();
|
||||||
if (filter == "") return true;
|
|
||||||
|
if (filter == "")
|
||||||
|
return true;
|
||||||
|
|
||||||
if (item.Command.ToLower().Contains(filter) ||
|
if (item.Command.ToLower().Contains(filter) ||
|
||||||
item.Input.ToLower().Contains(filter) ||
|
item.Input.ToLower().Contains(filter) ||
|
||||||
item.Path.ToLower().Contains(filter))
|
item.Path.ToLower().Contains(filter))
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
||||||
source.AddHook(new HwndSourceHook(WndProc));
|
source.AddHook(new HwndSourceHook(WndProc));
|
||||||
@@ -60,14 +57,15 @@ namespace mpvnet
|
|||||||
ListView.SelectedIndex = 0;
|
ListView.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||||
{
|
{
|
||||||
if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed)
|
if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed)
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
switch (e.Key)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
@@ -75,7 +73,10 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
int index = ListView.SelectedIndex;
|
int index = ListView.SelectedIndex;
|
||||||
index -= 1;
|
index -= 1;
|
||||||
if (index < 0) index = 0;
|
|
||||||
|
if (index < 0)
|
||||||
|
index = 0;
|
||||||
|
|
||||||
ListView.SelectedIndex = index;
|
ListView.SelectedIndex = index;
|
||||||
ListView.ScrollIntoView(ListView.SelectedItem);
|
ListView.ScrollIntoView(ListView.SelectedItem);
|
||||||
}
|
}
|
||||||
@@ -84,7 +85,10 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
int index = ListView.SelectedIndex;
|
int index = ListView.SelectedIndex;
|
||||||
index += 1;
|
index += 1;
|
||||||
if (index > ListView.Items.Count - 1) index = ListView.Items.Count - 1;
|
|
||||||
|
if (index > ListView.Items.Count - 1)
|
||||||
|
index = ListView.Items.Count - 1;
|
||||||
|
|
||||||
ListView.SelectedIndex = index;
|
ListView.SelectedIndex = index;
|
||||||
ListView.ScrollIntoView(ListView.SelectedItem);
|
ListView.ScrollIntoView(ListView.SelectedItem);
|
||||||
}
|
}
|
||||||
@@ -104,16 +108,16 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
CommandItem item = ListView.SelectedItem as CommandItem;
|
CommandItem item = ListView.SelectedItem as CommandItem;
|
||||||
Close();
|
Close();
|
||||||
mp.command(item.Command);
|
core.command(item.Command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListView_MouseUp(object sender, MouseButtonEventArgs e)
|
void ListView_MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
Execute();
|
Execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
void FilterTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
||||||
{
|
{
|
||||||
CollectionView.Refresh();
|
CollectionView.Refresh();
|
||||||
SelectFirst();
|
SelectFirst();
|
||||||
|
|||||||
@@ -3,35 +3,64 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:WPF="clr-namespace:WPF"
|
xmlns:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Height="500" Width="700" Loaded="ConfWindow1_Loaded" ShowInTaskbar="False"
|
|
||||||
WindowStartupLocation="CenterScreen" Title="Config Editor">
|
Title="Config Editor"
|
||||||
|
Height="530"
|
||||||
|
Width="700"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
WindowStartupLocation="CenterScreen"
|
||||||
|
Loaded="ConfWindow1_Loaded">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="100" />
|
<ColumnDefinition Width="100" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Controls:SearchTextBoxUserControl HintText="Find a setting" x:Name="SearchControl" Width="250" Margin="0,20,0,0" Grid.ColumnSpan="2"/>
|
|
||||||
<ScrollViewer x:Name="MainScrollViewer" VerticalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="2" Margin="0,0,0,10">
|
<Controls:SearchTextBoxUserControl
|
||||||
|
x:Name="SearchControl"
|
||||||
|
HintText="Find a setting"
|
||||||
|
Width="250"
|
||||||
|
Margin="0,20,0,0"
|
||||||
|
Grid.ColumnSpan="2"/>
|
||||||
|
|
||||||
|
<ScrollViewer Name="MainScrollViewer"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="2"
|
||||||
|
Margin="0,0,0,10">
|
||||||
|
|
||||||
<StackPanel x:Name="MainStackPanel"></StackPanel>
|
<StackPanel x:Name="MainStackPanel"></StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
<StackPanel Margin="20,0,0,0" Grid.Row="1">
|
<StackPanel Margin="20,0,0,0" Grid.Row="1">
|
||||||
<ListBox x:Name="FilterListBox" ItemsSource="{Binding FilterStrings}" BorderThickness="0" SelectionChanged="ListBox_SelectionChanged" Foreground="{x:Static WPF:WPF.ThemeBrush}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
|
<ListBox Name="FilterListBox"
|
||||||
|
ItemsSource="{Binding FilterStrings}"
|
||||||
|
BorderThickness="0"
|
||||||
|
SelectionChanged="FilterListBox_SelectionChanged"
|
||||||
|
Foreground="{x:Static UI:Theme.Heading}"
|
||||||
|
Background="{x:Static UI:Theme.Background}">
|
||||||
|
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding}" FontSize="16" />
|
<TextBlock Text="{Binding}" FontSize="16" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
<TextBlock x:Name="OpenSettingsTextBlock" Margin="0,30,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static WPF:WPF.ThemeBrush}" MouseUp="OpenSettingsTextBlock_MouseUp">Open config folder</TextBlock>
|
|
||||||
<TextBlock x:Name="PreviewTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static WPF:WPF.ThemeBrush}" MouseUp="PreviewTextBlock_MouseUp">Preview mpv.conf</TextBlock>
|
<TextBlock Name="OpenSettingsTextBlock" Margin="0,30,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static UI:Theme.Heading}" MouseUp="OpenSettingsTextBlock_MouseUp">Open config folder</TextBlock>
|
||||||
<TextBlock x:Name="ShowManualTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static WPF:WPF.ThemeBrush}" MouseUp="ShowManualTextBlock_MouseUp">Show mpv manual</TextBlock>
|
<TextBlock Name="PreviewTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static UI:Theme.Heading}" MouseUp="PreviewTextBlock_MouseUp">Preview mpv.conf</TextBlock>
|
||||||
<TextBlock x:Name="SupportTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static WPF:WPF.ThemeBrush}" MouseUp="SupportTextBlock_MouseUp">Show support forum</TextBlock>
|
<TextBlock Name="ShowManualTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static UI:Theme.Heading}" MouseUp="ShowManualTextBlock_MouseUp">Show mpv manual</TextBlock>
|
||||||
|
<TextBlock Name="SupportTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{x:Static UI:Theme.Heading}" MouseUp="SupportTextBlock_MouseUp">Show support forum</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
using DynamicGUI;
|
using DynamicGUI;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
public partial class ConfWindow : Window
|
public partial class ConfWindow : Window
|
||||||
{
|
{
|
||||||
private List<SettingBase> SettingsDefinitions = Settings.LoadSettings(Properties.Resources.mpvConfToml);
|
List<SettingBase> SettingsDefinitions = Settings.LoadSettings(Properties.Resources.editor_toml);
|
||||||
private List<SettingBase> NetSettingsDefinitions = Settings.LoadSettings(Properties.Resources.mpvNetConfToml);
|
List<ConfItem> ConfItems = new List<ConfItem>();
|
||||||
public ObservableCollection<string> FilterStrings { get; } = new ObservableCollection<string>();
|
public ObservableCollection<string> FilterStrings { get; } = new ObservableCollection<string>();
|
||||||
string InitialContent;
|
string InitialContent;
|
||||||
|
|
||||||
@@ -25,41 +27,28 @@ namespace mpvnet
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
DataContext = this;
|
DataContext = this;
|
||||||
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
|
||||||
LoadSettings(SettingsDefinitions, Conf);
|
LoadConf(core.ConfPath);
|
||||||
LoadSettings(NetSettingsDefinitions, NetConf);
|
LoadConf(App.ConfPath);
|
||||||
InitialContent = GetContent(mp.ConfPath, Conf, SettingsDefinitions) +
|
LoadSettings();
|
||||||
GetContent(App.ConfPath, NetConf, NetSettingsDefinitions);
|
InitialContent = GetCompareString();
|
||||||
SearchControl.Text = RegHelp.GetString(App.RegPath, "config editor search");
|
SearchControl.Text = RegistryHelp.GetString(App.RegPath, "ConfigEditorSearch");
|
||||||
|
FilterListBox.SelectedItem = SearchControl.Text.TrimEnd(':');
|
||||||
|
}
|
||||||
|
|
||||||
if (App.IsDarkMode)
|
void LoadSettings()
|
||||||
{
|
{
|
||||||
Foreground = Brushes.White;
|
foreach (SettingBase setting in SettingsDefinitions)
|
||||||
Foreground2 = Brushes.Silver;
|
|
||||||
Background = Brushes.Black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Brush Foreground2 {
|
|
||||||
get { return (Brush)GetValue(Foreground2Property); }
|
|
||||||
set { SetValue(Foreground2Property, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty Foreground2Property =
|
|
||||||
DependencyProperty.Register("Foreground2", typeof(Brush), typeof(ConfWindow), new PropertyMetadata(Brushes.DarkSlateGray));
|
|
||||||
|
|
||||||
private void LoadSettings(List<SettingBase> settingsDefinitions,
|
|
||||||
Dictionary<string, string> confSettings)
|
|
||||||
{
|
|
||||||
foreach (SettingBase setting in settingsDefinitions)
|
|
||||||
{
|
{
|
||||||
if (!FilterStrings.Contains(setting.Filter))
|
if (!FilterStrings.Contains(setting.Filter))
|
||||||
FilterStrings.Add(setting.Filter);
|
FilterStrings.Add(setting.Filter);
|
||||||
|
|
||||||
foreach (var pair in confSettings)
|
foreach (ConfItem confItem in ConfItems)
|
||||||
{
|
{
|
||||||
if (setting.Name == pair.Key)
|
if (setting.Name == confItem.Name && confItem.Section == "" && !confItem.IsSectionItem)
|
||||||
{
|
{
|
||||||
setting.Value = pair.Value.Trim('\'', '"');
|
setting.Value = confItem.Value.Trim('\'', '"');
|
||||||
|
setting.ConfItem = confItem;
|
||||||
|
confItem.SettingBase = setting;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,101 +57,199 @@ namespace mpvnet
|
|||||||
{
|
{
|
||||||
case StringSetting s:
|
case StringSetting s:
|
||||||
var sc = new StringSettingControl(s);
|
var sc = new StringSettingControl(s);
|
||||||
sc.TitleTextBox.Foreground = WPF.WPF.ThemeBrush;
|
|
||||||
MainStackPanel.Children.Add(sc);
|
MainStackPanel.Children.Add(sc);
|
||||||
break;
|
break;
|
||||||
case OptionSetting s:
|
case OptionSetting s:
|
||||||
var oc = new OptionSettingControl(s);
|
var oc = new OptionSettingControl(s);
|
||||||
oc.TitleTextBox.Foreground = WPF.WPF.ThemeBrush;
|
|
||||||
MainStackPanel.Children.Add(oc);
|
MainStackPanel.Children.Add(oc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, string> _Conf;
|
|
||||||
|
|
||||||
public Dictionary<string, string> Conf {
|
|
||||||
get {
|
|
||||||
if (_Conf == null) _Conf = LoadConf(mp.ConfPath);
|
|
||||||
return _Conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, string> _NetConf;
|
|
||||||
|
|
||||||
public Dictionary<string, string> NetConf {
|
|
||||||
get {
|
|
||||||
if (_NetConf == null) _NetConf = LoadConf(App.ConfPath);
|
|
||||||
return _NetConf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, string> LoadConf(string filePath)
|
|
||||||
{
|
|
||||||
Dictionary<string, string> conf = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
if (File.Exists(filePath))
|
|
||||||
{
|
|
||||||
foreach (string i in File.ReadAllLines(filePath))
|
|
||||||
{
|
|
||||||
if (i.Contains("="))
|
|
||||||
{
|
|
||||||
int pos = i.IndexOf("=");
|
|
||||||
string left = i.Substring(0, pos).Trim().ToLower();
|
|
||||||
string right = i.Substring(pos + 1).Trim();
|
|
||||||
if (left.StartsWith("#")) continue;
|
|
||||||
if (left == "fs") left = "fullscreen";
|
|
||||||
if (left == "loop") left = "loop-file";
|
|
||||||
conf[left] = right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnClosed(EventArgs e)
|
protected override void OnClosed(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnClosed(e);
|
base.OnClosed(e);
|
||||||
string content = GetContent(mp.ConfPath, Conf, SettingsDefinitions);
|
RegistryHelp.SetValue(App.RegPath, "ConfigEditorSearch", SearchControl.Text);
|
||||||
string netContent = GetContent(App.ConfPath, NetConf, NetSettingsDefinitions);
|
|
||||||
if (InitialContent == content + netContent) return;
|
if (InitialContent == GetCompareString())
|
||||||
string header = "\r\n# manual: https://mpv.io/manual/master/\r\n\r\n# defaults: https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt\r\n\r\n";
|
return;
|
||||||
File.WriteAllText(mp.ConfPath, header + content);
|
|
||||||
File.WriteAllText(App.ConfPath, netContent);
|
File.WriteAllText(core.ConfPath, GetContent("mpv"));
|
||||||
|
File.WriteAllText(App.ConfPath, GetContent("mpvnet"));
|
||||||
Msg.Show("Changes will be available on next mpv.net startup.");
|
Msg.Show("Changes will be available on next mpv.net startup.");
|
||||||
RegHelp.SetObject(App.RegPath, "config editor search", SearchControl.Text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetContent(string filePath, Dictionary<string, string> confSettings, List<SettingBase> settings)
|
string GetCompareString()
|
||||||
{
|
{
|
||||||
string content = "";
|
return string.Join("", SettingsDefinitions.Select(item => item.Name + item.Value).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (SettingBase setting in settings)
|
void LoadConf(string file)
|
||||||
{
|
{
|
||||||
|
if (!File.Exists(file))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string comment = "";
|
||||||
|
string section = "";
|
||||||
|
bool isSectionItem = false;
|
||||||
|
|
||||||
|
foreach (string currentLine in File.ReadAllLines(file))
|
||||||
|
{
|
||||||
|
string line = currentLine.Trim();
|
||||||
|
|
||||||
|
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("="))
|
||||||
|
{
|
||||||
|
ConfItem item = new ConfItem();
|
||||||
|
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();
|
||||||
|
string right = line.Substring(pos + 1).Trim();
|
||||||
|
|
||||||
|
if (left == "fs")
|
||||||
|
left = "fullscreen";
|
||||||
|
|
||||||
|
if (left == "loop")
|
||||||
|
left = "loop-file";
|
||||||
|
|
||||||
|
item.Name = left;
|
||||||
|
item.Value = right;
|
||||||
|
ConfItems.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetContent(string filename)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
List<string> namesWritten = new List<string>();
|
||||||
|
|
||||||
|
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 + " = " + item.Value);
|
||||||
|
|
||||||
|
if (item.LineComment != "")
|
||||||
|
sb.Append(" " + item.LineComment);
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
namesWritten.Add(item.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((item.SettingBase.Value ?? "") != item.SettingBase.Default)
|
||||||
|
{
|
||||||
|
string value = "";
|
||||||
|
|
||||||
|
if (item.SettingBase.Type == "string" ||
|
||||||
|
item.SettingBase.Type == "folder" ||
|
||||||
|
item.SettingBase.Type == "color")
|
||||||
|
|
||||||
|
value = "'" + item.SettingBase.Value + "'";
|
||||||
|
else
|
||||||
|
value = item.SettingBase.Value;
|
||||||
|
|
||||||
|
sb.Append(item.Name + " = " + value);
|
||||||
|
|
||||||
|
if (item.LineComment != "")
|
||||||
|
sb.Append(" " + item.LineComment);
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
namesWritten.Add(item.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sb.ToString().Contains("# Editor"))
|
||||||
|
sb.AppendLine("# Editor");
|
||||||
|
|
||||||
|
foreach (SettingBase setting in SettingsDefinitions)
|
||||||
|
{
|
||||||
|
if (filename != setting.File || namesWritten.Contains(setting.Name))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((setting.Value ?? "") != setting.Default)
|
if ((setting.Value ?? "") != setting.Default)
|
||||||
|
{
|
||||||
|
string value = "";
|
||||||
|
|
||||||
if (setting.Type == "string" ||
|
if (setting.Type == "string" ||
|
||||||
setting.Type == "folder" ||
|
setting.Type == "folder" ||
|
||||||
setting.Type == "color")
|
setting.Type == "color")
|
||||||
|
|
||||||
confSettings[setting.Name] = "'" + setting.Value + "'";
|
value = "'" + setting.Value + "'";
|
||||||
else
|
else
|
||||||
confSettings[setting.Name] = setting.Value;
|
value = setting.Value;
|
||||||
|
|
||||||
if (confSettings.ContainsKey(setting.Name) &&
|
sb.AppendLine(setting.Name + " = " + value);
|
||||||
(setting.Value ?? "") == setting.Default ||
|
}
|
||||||
(setting.Value ?? "") == "")
|
|
||||||
|
|
||||||
confSettings.Remove(setting.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var i in confSettings)
|
foreach (ConfItem item in ConfItems)
|
||||||
content = content + $"{i.Key} = {i.Value}\r\n";
|
{
|
||||||
|
if (filename != item.File || (item.Section == "" && !item.IsSectionItem))
|
||||||
|
continue;
|
||||||
|
|
||||||
return content;
|
if (item.Section != "")
|
||||||
|
{
|
||||||
|
if (!sb.ToString().EndsWith("\r\n\r\n"))
|
||||||
|
sb.AppendLine();
|
||||||
|
|
||||||
|
sb.AppendLine(item.Section);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
if (item.Comment != "")
|
||||||
|
sb.Append(item.Comment);
|
||||||
|
|
||||||
|
sb.Append(item.Name + " = " + item.Value);
|
||||||
|
|
||||||
|
if (item.LineComment != "")
|
||||||
|
sb.Append(" " + item.LineComment);
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
namesWritten.Add(item.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "\r\n" + sb.ToString().Trim() + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
{
|
{
|
||||||
string activeFilter = "";
|
string activeFilter = "";
|
||||||
|
|
||||||
@@ -190,36 +277,37 @@ namespace mpvnet
|
|||||||
MainScrollViewer.ScrollToTop();
|
MainScrollViewer.ScrollToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfWindow1_Loaded(object sender, RoutedEventArgs e)
|
void ConfWindow1_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
SearchControl.SearchTextBox.SelectAll();
|
SearchControl.SearchTextBox.SelectAll();
|
||||||
Keyboard.Focus(SearchControl.SearchTextBox);
|
Keyboard.Focus(SearchControl.SearchTextBox);
|
||||||
|
|
||||||
foreach (var i in MainStackPanel.Children.OfType<StringSettingControl>())
|
foreach (var i in MainStackPanel.Children.OfType<StringSettingControl>())
|
||||||
i.Update();
|
i.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
void FilterListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.AddedItems.Count > 0)
|
if (e.AddedItems.Count > 0)
|
||||||
SearchControl.Text = e.AddedItems[0].ToString() + ":";
|
SearchControl.Text = e.AddedItems[0] + ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
Process.Start(Path.GetDirectoryName(mp.ConfPath));
|
Process.Start(Path.GetDirectoryName(core.ConfPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
Msg.Show("mpv.conf Preview", GetContent(mp.ConfPath, Conf, SettingsDefinitions));
|
Msg.Show("mpv.conf Preview", GetContent("mpv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
Process.Start("https://mpv.io/manual/master/");
|
Process.Start("https://mpv.io/manual/master/");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SupportTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
void SupportTextBlock_MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
Process.Start("https://github.com/stax76/mpv.net#Support");
|
Process.Start("https://github.com/stax76/mpv.net#Support");
|
||||||
}
|
}
|
||||||
@@ -227,6 +315,7 @@ namespace mpvnet
|
|||||||
protected override void OnKeyDown(KeyEventArgs e)
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnKeyDown(e);
|
base.OnKeyDown(e);
|
||||||
|
|
||||||
if (e.Key == Key.Escape)
|
if (e.Key == Key.Escape)
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,21 +3,42 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Media File Search" Height="300" Width="600" ResizeMode="NoResize"
|
|
||||||
WindowStartupLocation="CenterOwner" Loaded="Window_Loaded" FontSize="13">
|
Title="Media File Search"
|
||||||
|
FontSize="13"
|
||||||
|
Height="300"
|
||||||
|
Width="600"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Loaded="Window_Loaded">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition></RowDefinition>
|
<RowDefinition></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBox Name="FilterTextBox" PreviewKeyDown="FilterTextBox_PreviewKeyDown" TextChanged="FilterTextBox_TextChanged"></TextBox>
|
|
||||||
<ListView Name="ListView" Grid.Row="1" MouseUp="ListView_MouseUp" PreviewKeyDown="ListView_PreviewKeyDown">
|
<TextBox Name="FilterTextBox"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
PreviewKeyDown="FilterTextBox_PreviewKeyDown"
|
||||||
|
TextChanged="FilterTextBox_TextChanged"/>
|
||||||
|
|
||||||
|
<ListView Name="ListView"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
Grid.Row="1"
|
||||||
|
MouseUp="ListView_MouseUp"
|
||||||
|
PreviewKeyDown="ListView_PreviewKeyDown">
|
||||||
|
|
||||||
<ListView.ItemContainerStyle>
|
<ListView.ItemContainerStyle>
|
||||||
<Style TargetType="ListBoxItem">
|
<Style TargetType="ListBoxItem">
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
|
||||||
</Style>
|
</Style>
|
||||||
</ListView.ItemContainerStyle>
|
</ListView.ItemContainerStyle>
|
||||||
|
|
||||||
</ListView>
|
</ListView>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -9,7 +9,8 @@ using System.Windows;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
@@ -18,19 +19,10 @@ namespace mpvnet
|
|||||||
public EverythingWindow()
|
public EverythingWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
if (App.IsDarkMode)
|
|
||||||
{
|
|
||||||
ListView.Foreground = Brushes.White;
|
|
||||||
ListView.Background = Brushes.Black;
|
|
||||||
FilterTextBox.Foreground = Brushes.White;
|
|
||||||
FilterTextBox.Background = Brushes.Black;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int EVERYTHING_REQUEST_FILE_NAME = 0x00000001;
|
const int EVERYTHING_REQUEST_FILE_NAME = 0x00000001;
|
||||||
const int EVERYTHING_REQUEST_PATH = 0x00000002;
|
const int EVERYTHING_REQUEST_PATH = 0x00000002;
|
||||||
const int EVERYTHING_SORT_SIZE_DESCENDING = 6;
|
|
||||||
|
|
||||||
[DllImport("Everything.dll", CharSet = CharSet.Unicode)]
|
[DllImport("Everything.dll", CharSet = CharSet.Unicode)]
|
||||||
public static extern int Everything_SetSearch(string lpSearchString);
|
public static extern int Everything_SetSearch(string lpSearchString);
|
||||||
@@ -53,7 +45,7 @@ namespace mpvnet
|
|||||||
[DllImport("Everything.dll")]
|
[DllImport("Everything.dll")]
|
||||||
public static extern UInt32 Everything_GetNumResults();
|
public static extern UInt32 Everything_GetNumResults();
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
||||||
source.AddHook(new HwndSourceHook(WndProc));
|
source.AddHook(new HwndSourceHook(WndProc));
|
||||||
@@ -66,14 +58,15 @@ namespace mpvnet
|
|||||||
ListView.SelectedIndex = 0;
|
ListView.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||||
{
|
{
|
||||||
if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed)
|
if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed)
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
switch (e.Key)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
@@ -100,22 +93,26 @@ namespace mpvnet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListView_PreviewKeyDown(object sender, KeyEventArgs e)
|
void ListView_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Escape) Close();
|
if (e.Key == Key.Escape)
|
||||||
if (e.Key == Key.Enter) Execute();
|
Close();
|
||||||
|
|
||||||
|
if (e.Key == Key.Enter)
|
||||||
|
Execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute()
|
void Execute()
|
||||||
{
|
{
|
||||||
if (ListView.SelectedItem != null)
|
if (ListView.SelectedItem != null)
|
||||||
mp.Load(new[] { ListView.SelectedItem as string }, true, Keyboard.Modifiers == ModifierKeys.Control);
|
core.LoadFiles(new[] { ListView.SelectedItem as string }, true, Keyboard.Modifiers == ModifierKeys.Control);
|
||||||
|
|
||||||
Keyboard.Focus(FilterTextBox);
|
Keyboard.Focus(FilterTextBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListView_MouseUp(object sender, MouseButtonEventArgs e) => Execute();
|
void ListView_MouseUp(object sender, MouseButtonEventArgs e) => Execute();
|
||||||
|
|
||||||
private void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
{
|
{
|
||||||
string searchtext = FilterTextBox.Text;
|
string searchtext = FilterTextBox.Text;
|
||||||
Task.Run(() => Search(searchtext));
|
Task.Run(() => Search(searchtext));
|
||||||
@@ -135,20 +132,22 @@ namespace mpvnet
|
|||||||
StringBuilder buf = new StringBuilder(bufsize);
|
StringBuilder buf = new StringBuilder(bufsize);
|
||||||
Everything_SetSearch(searchtext);
|
Everything_SetSearch(searchtext);
|
||||||
Everything_SetRequestFlags(EVERYTHING_REQUEST_FILE_NAME | EVERYTHING_REQUEST_PATH);
|
Everything_SetRequestFlags(EVERYTHING_REQUEST_FILE_NAME | EVERYTHING_REQUEST_PATH);
|
||||||
Everything_SetSort(EVERYTHING_SORT_SIZE_DESCENDING);
|
|
||||||
Everything_Query(true);
|
Everything_Query(true);
|
||||||
|
|
||||||
for (i = 0; i < Everything_GetNumResults(); i++)
|
for (i = 0; i < Everything_GetNumResults(); i++)
|
||||||
{
|
{
|
||||||
Everything_GetResultFullPathName(i, buf, bufsize);
|
Everything_GetResultFullPathName(i, buf, bufsize);
|
||||||
string ext = Path.GetExtension(buf.ToString()).TrimStart('.').ToLower();
|
string ext = buf.ToString().ShortExt();
|
||||||
|
|
||||||
if (App.AudioTypes.Contains(ext) || App.VideoTypes.Contains(ext) ||
|
if (App.AudioTypes.Contains(ext) || App.VideoTypes.Contains(ext)
|
||||||
App.ImageTypes.Contains(ext))
|
|| App.ImageTypes.Contains(ext))
|
||||||
|
|
||||||
items.Add(buf.ToString());
|
items.Add(buf.ToString());
|
||||||
|
|
||||||
if (items.Count > 100) break;
|
if (items.Count > 100)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Application.Current.Dispatcher.Invoke(() => {
|
Application.Current.Dispatcher.Invoke(() => {
|
||||||
ListView.ItemsSource = items;
|
ListView.ItemsSource = items;
|
||||||
SelectFirst();
|
SelectFirst();
|
||||||
|
|||||||
@@ -3,9 +3,19 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Input Editor" Height="500" Width="750" FontSize="13"
|
|
||||||
Loaded="Window_Loaded" Closed="Window_Closed" ShowInTaskbar="False">
|
Title="Input Editor"
|
||||||
|
Height="500"
|
||||||
|
Width="750"
|
||||||
|
FontSize="13"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
Loaded="Window_Loaded"
|
||||||
|
Closed="Window_Closed">
|
||||||
|
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<Style x:Key="DataGrid_Font_Centering" TargetType="{x:Type DataGridCell}">
|
<Style x:Key="DataGrid_Font_Centering" TargetType="{x:Type DataGridCell}">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
@@ -19,15 +29,29 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Controls:SearchTextBoxUserControl HintText="Type ? to get help." x:Name="SearchControl" Width="300" Margin="0,20,0,20" Grid.ColumnSpan="2" />
|
|
||||||
<DataGrid Grid.Row="1" x:Name="DataGrid" CommandManager.PreviewCanExecute="DataGrid_PreviewCanExecute" AutoGenerateColumns="False" CellStyle="{StaticResource DataGrid_Font_Centering}">
|
<Controls:SearchTextBoxUserControl
|
||||||
|
HintText="Type ? to get help."
|
||||||
|
x:Name="SearchControl"
|
||||||
|
Width="300"
|
||||||
|
Margin="0,20,0,20"
|
||||||
|
Grid.ColumnSpan="2" />
|
||||||
|
|
||||||
|
<DataGrid x:Name="DataGrid"
|
||||||
|
Grid.Row="1"
|
||||||
|
CommandManager.PreviewCanExecute="DataGrid_PreviewCanExecute"
|
||||||
|
AutoGenerateColumns="False"
|
||||||
|
CellStyle="{StaticResource DataGrid_Font_Centering}" >
|
||||||
|
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
<DataGridTextColumn Header="Menu" Binding="{Binding Path}"/>
|
<DataGridTextColumn Header="Menu" Binding="{Binding Path}"/>
|
||||||
|
|
||||||
<DataGridTemplateColumn Header="Input">
|
<DataGridTemplateColumn Header="Input">
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
<DataGridTemplateColumn.CellTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
@@ -37,7 +61,9 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
</DataGridTemplateColumn.CellTemplate>
|
||||||
</DataGridTemplateColumn>
|
</DataGridTemplateColumn>
|
||||||
|
|
||||||
<DataGridTextColumn Header="Command" Binding="{Binding Command}" MaxWidth="330" />
|
<DataGridTextColumn Header="Command" Binding="{Binding Command}" MaxWidth="330" />
|
||||||
|
|
||||||
</DataGrid.Columns>
|
</DataGrid.Columns>
|
||||||
</DataGrid>
|
</DataGrid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -6,7 +7,8 @@ using System.Windows;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
@@ -26,38 +28,28 @@ namespace mpvnet
|
|||||||
var yourCostumFilter = new Predicate<object>(item => Filter((CommandItem)item));
|
var yourCostumFilter = new Predicate<object>(item => Filter((CommandItem)item));
|
||||||
CollectionView.Filter = yourCostumFilter;
|
CollectionView.Filter = yourCostumFilter;
|
||||||
DataGrid.ItemsSource = CollectionView;
|
DataGrid.ItemsSource = CollectionView;
|
||||||
|
|
||||||
if (App.IsDarkMode)
|
|
||||||
{
|
|
||||||
Foreground = Brushes.White;
|
|
||||||
Foreground2 = Brushes.Silver;
|
|
||||||
Background = Brushes.Black;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush Foreground2 {
|
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
get { return (Brush)GetValue(Foreground2Property); }
|
|
||||||
set { SetValue(Foreground2Property, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty Foreground2Property =
|
|
||||||
DependencyProperty.Register("Foreground2", typeof(Brush), typeof(InputWindow), new PropertyMetadata(Brushes.DarkSlateGray));
|
|
||||||
|
|
||||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
CollectionView.Refresh();
|
CollectionView.Refresh();
|
||||||
|
|
||||||
if (SearchControl.SearchTextBox.Text == "?")
|
if (SearchControl.SearchTextBox.Text == "?")
|
||||||
Msg.Show("Filtering works by searching in the Input, Menu and Command but it's possible to reduce the filter scope to either of Input, Menu or Command by prefixing as follows:\n\ni <input search>\ni: <input search>\n\nm <menu search>\nm: <menu search>\n\nc <command search>\nc: <command search>\n\nIf only one character is entered the search will be performed only in the input.", "Filtering");
|
{
|
||||||
|
SearchControl.SearchTextBox.Text = "";
|
||||||
|
Msg.Show("Filtering", "Reduce the filter scope with:\n\ni input\n\nm menu\n\nc command\n\nIf only one character is entered input search is performed.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Filter(CommandItem item)
|
bool Filter(CommandItem item)
|
||||||
{
|
{
|
||||||
if (item.Command == "") return false;
|
if (item.Command == "") return false;
|
||||||
string searchText = SearchControl.SearchTextBox.Text.ToLower();
|
string searchText = SearchControl.SearchTextBox.Text.ToLower();
|
||||||
if (searchText == "") return true;
|
if (searchText == "" || searchText == "?") return true;
|
||||||
|
|
||||||
if (searchText.StartsWith("i ") || searchText.StartsWith("i:") || searchText.Length == 1)
|
if (searchText.Length == 1)
|
||||||
|
return item.Input.ToLower().Replace("ctrl+", "").Replace("shift+", "").Replace("alt+", "") == searchText.ToLower();
|
||||||
|
else if (searchText.StartsWith("i ") || searchText.StartsWith("i:") || searchText.Length == 1)
|
||||||
{
|
{
|
||||||
if (searchText.Length > 1)
|
if (searchText.Length > 1)
|
||||||
searchText = searchText.Substring(2).Trim();
|
searchText = searchText.Substring(2).Trim();
|
||||||
@@ -80,7 +72,7 @@ namespace mpvnet
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ButtonClick(object sender, RoutedEventArgs e)
|
void ButtonClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
CommandItem item = ((Button)e.Source).DataContext as CommandItem;
|
CommandItem item = ((Button)e.Source).DataContext as CommandItem;
|
||||||
if (item is null) return;
|
if (item is null) return;
|
||||||
@@ -98,13 +90,13 @@ namespace mpvnet
|
|||||||
items[i.Input] = i;
|
items[i.Input] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox);
|
void Window_Loaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox);
|
||||||
|
|
||||||
string GetInputConfContent()
|
string GetInputConfContent()
|
||||||
{
|
{
|
||||||
string text = null;
|
string text = null;
|
||||||
|
|
||||||
foreach (string line in Properties.Resources.inputConf.Split(new[] { "\r\n" }, StringSplitOptions.None))
|
foreach (string line in Properties.Resources.input_conf.Split(new[] { "\r\n" }, StringSplitOptions.None))
|
||||||
{
|
{
|
||||||
string test = line.Trim();
|
string test = line.Trim();
|
||||||
if (test == "" || test.StartsWith("#")) text += test + "\r\n";
|
if (test == "" || test.StartsWith("#")) text += test + "\r\n";
|
||||||
@@ -130,14 +122,14 @@ namespace mpvnet
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Closed(object sender, EventArgs e)
|
void Window_Closed(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (InitialInputConfContent == GetInputConfContent()) return;
|
if (InitialInputConfContent == GetInputConfContent()) return;
|
||||||
File.WriteAllText(mp.InputConfPath, GetInputConfContent());
|
File.WriteAllText(core.InputConfPath, GetInputConfContent());
|
||||||
Msg.Show("Changes will be available on next mpv.net startup.");
|
Msg.Show("Changes will be available on next mpv.net startup.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DataGrid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
|
void DataGrid_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
DataGrid grid = (DataGrid)sender;
|
DataGrid grid = (DataGrid)sender;
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,47 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:UI="clr-namespace:UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Learn Input" Height="200" Width="400" WindowStartupLocation="CenterOwner"
|
|
||||||
ResizeMode="NoResize" Loaded="Window_Loaded" Background="Black" MouseWheel="Window_MouseWheel" MouseUp="Window_MouseUp" MouseDoubleClick="Window_MouseDoubleClick">
|
Title="Learn Input"
|
||||||
|
Height="200"
|
||||||
|
Width="400"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
Loaded="Window_Loaded"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
MouseWheel="Window_MouseWheel"
|
||||||
|
MouseUp="Window_MouseUp"
|
||||||
|
MouseDoubleClick="Window_MouseDoubleClick"
|
||||||
|
TextInput="Window_TextInput">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="40" />
|
<RowDefinition Height="40" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock x:Name="MenuTextBlock" Grid.ColumnSpan="2" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16"></TextBlock>
|
|
||||||
<TextBlock x:Name="KeyTextBlock" Grid.Row="1" Grid.ColumnSpan="2" Foreground="White" VerticalAlignment="Top" HorizontalAlignment="Center" FontSize="16"></TextBlock>
|
<TextBlock x:Name="MenuTextBlock"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontSize="16"></TextBlock>
|
||||||
|
|
||||||
|
<TextBlock x:Name="KeyTextBlock"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontSize="16" />
|
||||||
|
|
||||||
<Button x:Name="ConfirmButton" Grid.Row="2" Click="ConfirmButton_Click">Confirm</Button>
|
<Button x:Name="ConfirmButton" Grid.Row="2" Click="ConfirmButton_Click">Confirm</Button>
|
||||||
<Button x:Name="ClearButton" Grid.Row="2" Click="ClearButton_Click" Grid.Column="1">Clear</Button>
|
<Button x:Name="ClearButton" Grid.Row="2" Click="ClearButton_Click" Grid.Column="1">Clear</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,22 +1,26 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using WF = System.Windows.Forms;
|
|
||||||
|
using WinForms = System.Windows.Forms;
|
||||||
|
using static mpvnet.Core;
|
||||||
|
|
||||||
namespace mpvnet
|
namespace mpvnet
|
||||||
{
|
{
|
||||||
public partial class LearnWindow : Window
|
public partial class LearnWindow : Window
|
||||||
{
|
{
|
||||||
public CommandItem InputItem { get; set; }
|
public CommandItem InputItem { get; set; }
|
||||||
public string NewKey { get; set; } = "";
|
string NewKey = "";
|
||||||
|
string KeyChar = "";
|
||||||
|
|
||||||
public LearnWindow() => InitializeComponent();
|
public LearnWindow() => InitializeComponent();
|
||||||
|
|
||||||
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||||
{
|
{
|
||||||
WF.Message m = new WF.Message();
|
WinForms.Message m = new WinForms.Message();
|
||||||
m.HWnd = hwnd;
|
m.HWnd = hwnd;
|
||||||
m.Msg = msg;
|
m.Msg = msg;
|
||||||
m.WParam = wParam;
|
m.WParam = wParam;
|
||||||
@@ -25,10 +29,10 @@ namespace mpvnet
|
|||||||
return m.Result;
|
return m.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnKeyUp(WF.KeyEventArgs e)
|
void OnKeyUp(WinForms.KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.KeyCode == WF.Keys.ControlKey || e.KeyCode == WF.Keys.ShiftKey ||
|
if (e.KeyCode == WinForms.Keys.ControlKey || e.KeyCode == WinForms.Keys.ShiftKey ||
|
||||||
e.KeyCode == WF.Keys.Menu || e.KeyCode == WF.Keys.None)
|
e.KeyCode == WinForms.Keys.Menu || e.KeyCode == WinForms.Keys.None)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -43,95 +47,100 @@ namespace mpvnet
|
|||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
for (int i = 0; i < 13; i++)
|
for (int i = 0; i < 13; i++)
|
||||||
if ("D" + i.ToString() == text)
|
if ("D" + i == text)
|
||||||
text = text.Substring(1);
|
text = text.Substring(1);
|
||||||
|
|
||||||
switch (e.KeyCode)
|
switch (e.KeyCode)
|
||||||
{
|
{
|
||||||
case WF.Keys.NumPad0:
|
case WinForms.Keys.NumPad0:
|
||||||
case WF.Keys.NumPad1:
|
case WinForms.Keys.NumPad1:
|
||||||
case WF.Keys.NumPad2:
|
case WinForms.Keys.NumPad2:
|
||||||
case WF.Keys.NumPad3:
|
case WinForms.Keys.NumPad3:
|
||||||
case WF.Keys.NumPad4:
|
case WinForms.Keys.NumPad4:
|
||||||
case WF.Keys.NumPad5:
|
case WinForms.Keys.NumPad5:
|
||||||
case WF.Keys.NumPad6:
|
case WinForms.Keys.NumPad6:
|
||||||
case WF.Keys.NumPad7:
|
case WinForms.Keys.NumPad7:
|
||||||
case WF.Keys.NumPad8:
|
case WinForms.Keys.NumPad8:
|
||||||
case WF.Keys.NumPad9:
|
case WinForms.Keys.NumPad9:
|
||||||
text = "KP" + e.KeyCode.ToString()[6].ToString(); break;
|
text = "KP" + e.KeyCode.ToString()[6]; break;
|
||||||
case WF.Keys.Space:
|
case WinForms.Keys.Space:
|
||||||
text = "SPACE"; break;
|
text = "Space"; break;
|
||||||
case WF.Keys.Enter:
|
case WinForms.Keys.Enter:
|
||||||
text = "ENTER"; break;
|
text = "Enter"; break;
|
||||||
case WF.Keys.Tab:
|
case WinForms.Keys.Tab:
|
||||||
text = "TAB"; break;
|
text = "TAB"; break;
|
||||||
case WF.Keys.Back:
|
case WinForms.Keys.Back:
|
||||||
text = "BS"; break;
|
text = "BS"; break;
|
||||||
case WF.Keys.Delete:
|
case WinForms.Keys.Delete:
|
||||||
text = "DEL"; break;
|
text = "DEL"; break;
|
||||||
case WF.Keys.Insert:
|
case WinForms.Keys.Insert:
|
||||||
text = "INS"; break;
|
text = "INS"; break;
|
||||||
case WF.Keys.Home:
|
case WinForms.Keys.Home:
|
||||||
text = "HOME"; break;
|
text = "Home"; break;
|
||||||
case WF.Keys.End:
|
case WinForms.Keys.End:
|
||||||
text = "END"; break;
|
text = "END"; break;
|
||||||
case WF.Keys.PageUp:
|
case WinForms.Keys.PageUp:
|
||||||
text = "PGUP"; break;
|
text = "PGUP"; break;
|
||||||
case WF.Keys.PageDown:
|
case WinForms.Keys.PageDown:
|
||||||
text = "PGDWN"; break;
|
text = "PGDWN"; break;
|
||||||
case WF.Keys.Escape:
|
case WinForms.Keys.Escape:
|
||||||
text = "ESC"; break;
|
text = "ESC"; break;
|
||||||
case WF.Keys.PrintScreen:
|
case WinForms.Keys.PrintScreen:
|
||||||
text = "PRINT"; break;
|
text = "Print"; break;
|
||||||
case WF.Keys.Play:
|
case WinForms.Keys.Play:
|
||||||
text = "PLAY"; break;
|
text = "Play"; break;
|
||||||
case WF.Keys.Pause:
|
case WinForms.Keys.Pause:
|
||||||
text = "PAUSE"; break;
|
text = "Pause"; break;
|
||||||
case WF.Keys.MediaPlayPause:
|
case WinForms.Keys.MediaPlayPause:
|
||||||
text = "PLAYPAUSE"; break;
|
text = "PlayPause"; break;
|
||||||
case WF.Keys.MediaStop:
|
case WinForms.Keys.MediaStop:
|
||||||
text = "STOP"; break;
|
text = "Stop"; break;
|
||||||
case WF.Keys.MediaNextTrack:
|
case WinForms.Keys.MediaNextTrack:
|
||||||
text = "NEXT"; break;
|
text = "Next"; break;
|
||||||
case WF.Keys.MediaPreviousTrack:
|
case WinForms.Keys.MediaPreviousTrack:
|
||||||
text = "PREV"; break;
|
text = "Prev"; break;
|
||||||
case WF.Keys.VolumeUp:
|
case WinForms.Keys.VolumeUp:
|
||||||
text = "VOLUME_UP"; break;
|
text = "Volume_Up"; break;
|
||||||
case WF.Keys.VolumeDown:
|
case WinForms.Keys.VolumeDown:
|
||||||
text = "VOLUME_DOWN"; break;
|
text = "Volume_Down"; break;
|
||||||
case WF.Keys.VolumeMute:
|
case WinForms.Keys.VolumeMute:
|
||||||
text = "MUTE"; break;
|
text = "Mute"; break;
|
||||||
case WF.Keys.BrowserHome:
|
case WinForms.Keys.BrowserHome:
|
||||||
text = "HOMEPAGE"; break;
|
text = "Homepage"; break;
|
||||||
case WF.Keys.LaunchMail:
|
case WinForms.Keys.LaunchMail:
|
||||||
text = "MAIL"; break;
|
text = "Mail"; break;
|
||||||
case WF.Keys.BrowserFavorites:
|
case WinForms.Keys.BrowserFavorites:
|
||||||
text = "FAVORITES"; break;
|
text = "Favorites"; break;
|
||||||
case WF.Keys.BrowserSearch:
|
case WinForms.Keys.BrowserSearch:
|
||||||
text = "SEARCH"; break;
|
text = "Search"; break;
|
||||||
case WF.Keys.Sleep:
|
case WinForms.Keys.Sleep:
|
||||||
text = "SLEEP"; break;
|
text = "Sleep"; break;
|
||||||
case WF.Keys.Cancel:
|
case WinForms.Keys.Cancel:
|
||||||
text = "CANCEL"; break;
|
text = "Cancel"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shiftWasHandled = false;
|
bool wasModified = false;
|
||||||
|
|
||||||
bool isAlt = GetKeyState(18) < (short)0;
|
bool isAlt = GetKeyState(18) < (short)0;
|
||||||
bool isShift = GetKeyState(16) < (short)0;
|
bool isShift = GetKeyState(16) < (short)0;
|
||||||
bool isCtrl = GetKeyState(17) < (short)0;
|
bool isCtrl = GetKeyState(17) < (short)0;
|
||||||
|
|
||||||
if (text.Length == 1 && isShift && text[0] != GetModifiedKey(text[0]))
|
if (text.Length == 1 && KeyChar != text)
|
||||||
{
|
{
|
||||||
text = GetModifiedKey(text[0]).ToString();
|
text = KeyChar;
|
||||||
shiftWasHandled = true;
|
wasModified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text == "#") text = "Sharp";
|
if (text == "#") text = "SHARP";
|
||||||
|
|
||||||
if (isAlt) text = "Alt+" + text;
|
if (isAlt && !wasModified)
|
||||||
if (isShift && !shiftWasHandled) text = "Shift+" + text;
|
text = "ALT+" + text;
|
||||||
if (isCtrl) text = "Ctrl+" + text;
|
|
||||||
|
if (isShift && !wasModified)
|
||||||
|
text = "SHIFT+" + text;
|
||||||
|
|
||||||
|
if (isCtrl && !wasModified)
|
||||||
|
text = "CTRL+" + text;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(text))
|
if (!string.IsNullOrEmpty(text))
|
||||||
SetKey(text);
|
SetKey(text);
|
||||||
@@ -150,45 +159,34 @@ namespace mpvnet
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
static extern uint MapVirtualKey(uint uCode, uint uMapType);
|
static extern uint MapVirtualKey(uint uCode, uint uMapType);
|
||||||
|
|
||||||
public static WF.Keys ModifierKeys {
|
public static WinForms.Keys ModifierKeys {
|
||||||
get {
|
get {
|
||||||
WF.Keys keys = WF.Keys.None;
|
WinForms.Keys keys = WinForms.Keys.None;
|
||||||
|
|
||||||
if (GetKeyState(17) < (short)0)
|
if (GetKeyState(17) < (short)0)
|
||||||
keys |= WF.Keys.Control;
|
keys |= WinForms.Keys.Control;
|
||||||
|
|
||||||
if (GetKeyState(16) < (short)0)
|
if (GetKeyState(16) < (short)0)
|
||||||
keys |= WF.Keys.Shift;
|
keys |= WinForms.Keys.Shift;
|
||||||
|
|
||||||
if (GetKeyState(18) < (short)0)
|
if (GetKeyState(18) < (short)0)
|
||||||
keys |= WF.Keys.Alt;
|
keys |= WinForms.Keys.Alt;
|
||||||
|
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static char GetModifiedKey(char c)
|
void ProcessKeyEventArgs(ref WinForms.Message m)
|
||||||
{
|
|
||||||
short vkKeyScanResult = VkKeyScan(c);
|
|
||||||
|
|
||||||
if (vkKeyScanResult == -1)
|
|
||||||
return c;
|
|
||||||
|
|
||||||
uint code = (uint)vkKeyScanResult & 0xff;
|
|
||||||
byte[] b = new byte[256];
|
|
||||||
b[0x10] = 0x80;
|
|
||||||
uint r;
|
|
||||||
|
|
||||||
if (1 != ToAscii(code, code, b, out r, 0))
|
|
||||||
return c;
|
|
||||||
|
|
||||||
return (char)r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProcessKeyEventArgs(ref WF.Message m)
|
|
||||||
{
|
{
|
||||||
int WM_KEYUP = 0x0101, WM_SYSKEYUP = 0x0105, WM_APPCOMMAND = 0x0319;
|
int WM_KEYUP = 0x0101, WM_SYSKEYUP = 0x0105, WM_APPCOMMAND = 0x0319;
|
||||||
|
|
||||||
if (m.Msg == WM_KEYUP || m.Msg == WM_SYSKEYUP)
|
if (m.Msg == WM_KEYUP || m.Msg == WM_SYSKEYUP)
|
||||||
OnKeyUp(new WF.KeyEventArgs((WF.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys));
|
OnKeyUp(new WinForms.KeyEventArgs((WinForms.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys));
|
||||||
else if (m.Msg == WM_APPCOMMAND)
|
else if (m.Msg == WM_APPCOMMAND)
|
||||||
{
|
{
|
||||||
|
if (!core.get_property_bool("input-media-keys"))
|
||||||
|
return;
|
||||||
|
|
||||||
var value = (AppCommand)(m.LParam.ToInt64() >> 16 & ~0xf000);
|
var value = (AppCommand)(m.LParam.ToInt64() >> 16 & ~0xf000);
|
||||||
|
|
||||||
switch (value)
|
switch (value)
|
||||||
@@ -323,26 +321,26 @@ namespace mpvnet
|
|||||||
out uint lpChar,
|
out uint lpChar,
|
||||||
uint flags);
|
uint flags);
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
||||||
source.AddHook(new HwndSourceHook(WndProc));
|
source.AddHook(new HwndSourceHook(WndProc));
|
||||||
SetKey(InputItem.Input);
|
SetKey(InputItem.Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfirmButton_Click(object sender, RoutedEventArgs e)
|
void ConfirmButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
InputItem.Input = NewKey;
|
InputItem.Input = NewKey;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearButton_Click(object sender, RoutedEventArgs e)
|
void ClearButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
InputItem.Input = "_";
|
InputItem.Input = "_";
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
|
void Window_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Delta > 0)
|
if (e.Delta > 0)
|
||||||
SetKey("WHEEL_UP");
|
SetKey("WHEEL_UP");
|
||||||
@@ -350,7 +348,7 @@ namespace mpvnet
|
|||||||
SetKey("WHEEL_DOWN");
|
SetKey("WHEEL_DOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_MouseUp(object sender, MouseButtonEventArgs e)
|
void Window_MouseUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
switch (e.ChangedButton)
|
switch (e.ChangedButton)
|
||||||
{
|
{
|
||||||
@@ -374,7 +372,7 @@ namespace mpvnet
|
|||||||
|
|
||||||
bool BlockMBTN_LEFT;
|
bool BlockMBTN_LEFT;
|
||||||
|
|
||||||
private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.ChangedButton == MouseButton.Left)
|
if (e.ChangedButton == MouseButton.Left)
|
||||||
{
|
{
|
||||||
@@ -382,5 +380,10 @@ namespace mpvnet
|
|||||||
BlockMBTN_LEFT = true;
|
BlockMBTN_LEFT = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window_TextInput(object sender, TextCompositionEventArgs e)
|
||||||
|
{
|
||||||
|
KeyChar = e.Text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,23 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
<ResourceDictionary 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:WPF="clr-namespace:WPF">
|
xmlns:UI="clr-namespace:UI">
|
||||||
|
|
||||||
<Style TargetType="TextBox">
|
<Style TargetType="TextBox">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||||
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
|
<Border x:Name="border"
|
||||||
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
SnapsToDevicePixels="True">
|
||||||
|
|
||||||
|
<ScrollViewer x:Name="PART_ContentHost"
|
||||||
|
Focusable="false"
|
||||||
|
HorizontalScrollBarVisibility="Hidden"
|
||||||
|
VerticalScrollBarVisibility="Hidden"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<ControlTemplate.Triggers>
|
<ControlTemplate.Triggers>
|
||||||
<Trigger Property="IsEnabled" Value="false">
|
<Trigger Property="IsEnabled" Value="false">
|
||||||
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
|
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
|
||||||
@@ -17,7 +26,7 @@
|
|||||||
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
|
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<Trigger Property="IsFocused" Value="true">
|
<Trigger Property="IsFocused" Value="true">
|
||||||
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static WPF:WPF.ThemeBrush}"/>
|
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static UI:Theme.Heading}"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</ControlTemplate.Triggers>
|
</ControlTemplate.Triggers>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
@@ -34,13 +43,14 @@
|
|||||||
<ColumnDefinition x:Name="LeftCol" Width="18" />
|
<ColumnDefinition x:Name="LeftCol" Width="18" />
|
||||||
<ColumnDefinition x:Name="RightCol" Width="*" />
|
<ColumnDefinition x:Name="RightCol" Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Grid x:Name="PART_CHECKBOX">
|
<Grid x:Name="PART_CHECKBOX">
|
||||||
<Ellipse
|
<Ellipse
|
||||||
x:Name="normal"
|
x:Name="normal"
|
||||||
Width="18"
|
Width="18"
|
||||||
Height="18"
|
Height="18"
|
||||||
Fill="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
|
Fill="{x:Static UI:Theme.Background}"
|
||||||
Stroke="{x:Static WPF:WPF.ThemeBrush}"
|
Stroke="{x:Static UI:Theme.Heading}"
|
||||||
StrokeThickness="2" />
|
StrokeThickness="2" />
|
||||||
<Ellipse
|
<Ellipse
|
||||||
x:Name="Checked1"
|
x:Name="Checked1"
|
||||||
@@ -56,6 +66,7 @@
|
|||||||
Opacity="0"
|
Opacity="0"
|
||||||
StrokeThickness="{TemplateBinding BorderThickness}" />
|
StrokeThickness="{TemplateBinding BorderThickness}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<ContentPresenter
|
<ContentPresenter
|
||||||
x:Name="contentPresenter"
|
x:Name="contentPresenter"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
@@ -67,6 +78,7 @@
|
|||||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||||
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
|
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
|
||||||
RecognizesAccessKey="True" />
|
RecognizesAccessKey="True" />
|
||||||
|
|
||||||
<VisualStateManager.VisualStateGroups>
|
<VisualStateManager.VisualStateGroups>
|
||||||
<VisualStateGroup x:Name="CommonStates">
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
<VisualState x:Name="Normal" />
|
<VisualState x:Name="Normal" />
|
||||||
|
|||||||
68
mpv.net/WPF/SearchTextBoxUserControl.xaml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<UserControl x:Class="Controls.SearchTextBoxUserControl"
|
||||||
|
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:UI="clr-namespace:UI"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
d:DesignWidth="800">
|
||||||
|
|
||||||
|
<Grid Name="SearchTextBoxUserControl1"
|
||||||
|
Background="{x:Static UI:Theme.Background}">
|
||||||
|
|
||||||
|
<TextBlock Name="HintTextBlock"
|
||||||
|
Margin="5,2"
|
||||||
|
Text="Find a setting"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground2}"
|
||||||
|
Background="{x:Static UI:Theme.Background}" />
|
||||||
|
|
||||||
|
<TextBox Name="SearchTextBox"
|
||||||
|
Height="25"
|
||||||
|
Padding="1,2,0,0"
|
||||||
|
BorderThickness="2"
|
||||||
|
Background="Transparent"
|
||||||
|
TextChanged="SearchTextBox_TextChanged"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
CaretBrush="{x:Static UI:Theme.Foreground}" />
|
||||||
|
|
||||||
|
<Button Name="SearchClearButton"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
FontFamily="Marlett"
|
||||||
|
FontSize="10"
|
||||||
|
Width="17"
|
||||||
|
Height="17"
|
||||||
|
Margin="2,0,4,0"
|
||||||
|
Visibility="Hidden"
|
||||||
|
Click="SearchClearButton_Click" >r
|
||||||
|
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{x:Static UI:Theme.Background}"/>
|
||||||
|
<Setter Property="Foreground" Value="{x:Static UI:Theme.Foreground2}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border BorderThickness="1"
|
||||||
|
BorderBrush="{TemplateBinding Foreground}"
|
||||||
|
SnapsToDevicePixels="True">
|
||||||
|
|
||||||
|
<ContentPresenter HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Foreground" Value="{x:Static UI:Theme.Heading}"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Windows;
|
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ namespace Controls
|
|||||||
|
|
||||||
public string Text { get => SearchTextBox.Text; set => SearchTextBox.Text = value; }
|
public string Text { get => SearchTextBox.Text; set => SearchTextBox.Text = value; }
|
||||||
|
|
||||||
private string _HintText;
|
string _HintText;
|
||||||
|
|
||||||
public string HintText {
|
public string HintText {
|
||||||
get => _HintText;
|
get => _HintText;
|
||||||
@@ -23,13 +24,13 @@ namespace Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchClearButton_Click(object sender, RoutedEventArgs e)
|
void SearchClearButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
SearchTextBox.Text = "";
|
SearchTextBox.Text = "";
|
||||||
Keyboard.Focus(SearchTextBox);
|
Keyboard.Focus(SearchTextBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateControls();
|
UpdateControls();
|
||||||
}
|
}
|
||||||
33
mpv.net/WPF/SetupWindow.xaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<Window x:Class="mpvnet.SetupWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:UI="clr-namespace:UI"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
|
||||||
|
Title="mpv.net Setup"
|
||||||
|
FontSize="13"
|
||||||
|
Foreground="{x:Static UI:Theme.Foreground}"
|
||||||
|
Background="{x:Static UI:Theme.Background}"
|
||||||
|
SizeToContent="WidthAndHeight"
|
||||||
|
WindowStartupLocation="CenterOwner" >
|
||||||
|
|
||||||
|
<Window.Resources>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Padding" Value="10"></Setter>
|
||||||
|
<Setter Property="Margin" Value="5"></Setter>
|
||||||
|
</Style>
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<StackPanel Margin="10">
|
||||||
|
<Button Name="RegisterVideo" Click="RegisterVideo_Click">Register video file extensions (requires admin rights)</Button>
|
||||||
|
<Button Name="RegisterAudio" Click="RegisterAudio_Click">Register audio file extensions (requires admin rights)</Button>
|
||||||
|
<Button Name="RegisterImage" Click="RegisterImage_Click">Register image file extensions (requires admin rights)</Button>
|
||||||
|
<Button Name="UnregisterFileAssociations" Click="UnregisterFileAssociations_Click">Unregister file extensions (requires admin rights)</Button>
|
||||||
|
<Button Name="AddToPathEnvVar" Click="AddToPathEnvVar_Click">Add mpv.net to Path environment variable</Button>
|
||||||
|
<Button Name="RemoveFromPathEnvVar" Click="RemoveFromPathEnvVar_Click">Remove mpv.net from Path environment variable</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
64
mpv.net/WPF/SetupWindow.xaml.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
using WinForms = System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace mpvnet
|
||||||
|
{
|
||||||
|
public partial class SetupWindow : Window
|
||||||
|
{
|
||||||
|
public SetupWindow() => InitializeComponent();
|
||||||
|
|
||||||
|
void RegisterFileAssociations(string value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Process proc = new Process())
|
||||||
|
{
|
||||||
|
proc.StartInfo.FileName = WinForms.Application.ExecutablePath;
|
||||||
|
proc.StartInfo.Arguments = "--reg-file-assoc " + value;
|
||||||
|
proc.StartInfo.Verb = "runas";
|
||||||
|
proc.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.Start("ms-settings:defaultapps");
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterVideo_Click(object sender, RoutedEventArgs e) => RegisterFileAssociations("video");
|
||||||
|
void RegisterAudio_Click(object sender, RoutedEventArgs e) => RegisterFileAssociations("audio");
|
||||||
|
void RegisterImage_Click(object sender, RoutedEventArgs e) => RegisterFileAssociations("image");
|
||||||
|
|
||||||
|
void UnregisterFileAssociations_Click(object sender, RoutedEventArgs e) => RegisterFileAssociations("unreg");
|
||||||
|
|
||||||
|
void AddToPathEnvVar_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
string var = WinForms.Application.StartupPath + ";";
|
||||||
|
string path = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.User);
|
||||||
|
|
||||||
|
if (path.Contains(var))
|
||||||
|
Msg.ShowWarning("Path was already containing mpv.net.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("Path", var + path, EnvironmentVariableTarget.User);
|
||||||
|
Msg.Show("mpv.net was successfully added to Path.", (var + path).Replace(";","\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveFromPathEnvVar_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
string var = WinForms.Application.StartupPath + ";";
|
||||||
|
string path = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.User);
|
||||||
|
|
||||||
|
if (path.Contains(var))
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("Path", path.Replace(var, ""), EnvironmentVariableTarget.User);
|
||||||
|
Msg.Show("mpv.net was successfully removed from Path.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Msg.ShowWarning("Path was not containing mpv.net.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,69 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
|
||||||
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using mpvnet;
|
|
||||||
|
|
||||||
namespace WPF
|
namespace WPF
|
||||||
{
|
{
|
||||||
public class WPF
|
public class WPF
|
||||||
{
|
{
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
|
||||||
EnsureApplicationResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EnsureApplicationResources()
|
|
||||||
{
|
{
|
||||||
if (Application.Current == null)
|
if (Application.Current == null)
|
||||||
{
|
{
|
||||||
new Application();
|
new Application();
|
||||||
|
|
||||||
Application.Current.Resources.MergedDictionaries.Add(
|
Application.Current.Resources.MergedDictionaries.Add(
|
||||||
Application.LoadComponent(new Uri("mpvnet;component/WPF/Resources.xaml",
|
Application.LoadComponent(new Uri("mpvnet;component/WPF/Resources.xaml",
|
||||||
UriKind.Relative)) as ResourceDictionary);
|
UriKind.Relative)) as ResourceDictionary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Brush ThemeBrush { get; } = new SolidColorBrush(ThemeColor);
|
|
||||||
|
|
||||||
static bool WasThemeColorSet;
|
|
||||||
|
|
||||||
static Color _ThemeColor;
|
|
||||||
|
|
||||||
public static Color ThemeColor {
|
|
||||||
get {
|
|
||||||
if (!WasThemeColorSet)
|
|
||||||
{
|
|
||||||
Color? color = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (App.IsDarkMode && !string.IsNullOrEmpty(App.DarkColor))
|
|
||||||
color = (Color)ColorConverter.ConvertFromString(App.DarkColor);
|
|
||||||
else if (!App.IsDarkMode && !string.IsNullOrEmpty(App.LightColor))
|
|
||||||
color = (Color)ColorConverter.ConvertFromString(App.LightColor);
|
|
||||||
} catch { }
|
|
||||||
|
|
||||||
if (!color.HasValue)
|
|
||||||
{
|
|
||||||
if (Environment.OSVersion.Version.Major < 10)
|
|
||||||
{
|
|
||||||
int argb = Convert.ToInt32(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0));
|
|
||||||
var wfc = System.Drawing.Color.FromArgb(argb);
|
|
||||||
color = Color.FromArgb(wfc.A, wfc.R, wfc.G, wfc.B);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
color = SystemParameters.WindowGlassColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (App.IsDarkMode && color == Colors.Black) color = Colors.Orange;
|
|
||||||
if (!App.IsDarkMode && color == Colors.White) color = Colors.Orange;
|
|
||||||
_ThemeColor = color.Value;
|
|
||||||
WasThemeColorSet = true;
|
|
||||||
}
|
|
||||||
return _ThemeColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
20
mpv.net/WinForms/MainForm.Designer.cs
generated
@@ -30,14 +30,19 @@
|
|||||||
{
|
{
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||||
this.Timer = new System.Windows.Forms.Timer(this.components);
|
this.CursorTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.ProgressTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// Timer
|
// CursorTimer
|
||||||
//
|
//
|
||||||
this.Timer.Enabled = true;
|
this.CursorTimer.Enabled = true;
|
||||||
this.Timer.Interval = 1000;
|
this.CursorTimer.Interval = 1000;
|
||||||
this.Timer.Tick += new System.EventHandler(this.Timer_Tick);
|
this.CursorTimer.Tick += new System.EventHandler(this.CursorTimer_Tick);
|
||||||
|
//
|
||||||
|
// ProgressTimer
|
||||||
|
//
|
||||||
|
this.ProgressTimer.Tick += new System.EventHandler(this.ProgressTimer_Tick);
|
||||||
//
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
@@ -45,7 +50,7 @@
|
|||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||||
this.BackColor = System.Drawing.Color.Black;
|
this.BackColor = System.Drawing.Color.Black;
|
||||||
this.ClientSize = new System.Drawing.Size(542, 0);
|
this.ClientSize = new System.Drawing.Size(348, 0);
|
||||||
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
@@ -57,6 +62,7 @@
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.Timer Timer;
|
private System.Windows.Forms.Timer CursorTimer;
|
||||||
|
private System.Windows.Forms.Timer ProgressTimer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,9 +117,12 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<metadata name="Timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="CursorTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>30, 12</value>
|
<value>30, 12</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="ProgressTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>321, 12</value>
|
||||||
|
</metadata>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.Linq;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Text;
|
using System.Drawing.Text;
|
||||||
using Microsoft.Win32;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
@@ -131,52 +130,29 @@ public class MenuItem : ToolStripMenuItem
|
|||||||
|
|
||||||
public class ToolStripRendererEx : ToolStripSystemRenderer
|
public class ToolStripRendererEx : ToolStripSystemRenderer
|
||||||
{
|
{
|
||||||
public static bool IsDarkMode { get; set; }
|
public static Color ForegroundColor { get; set; }
|
||||||
|
public static Color BackgroundColor { get; set; }
|
||||||
public static Color ColorForeground { get; set; } = Color.Black;
|
public static Color SelectionColor { get; set; }
|
||||||
public static Color ColorTheme { get; set; }
|
public static Color CheckedColor { get; set; }
|
||||||
public static Color ColorChecked { get; set; }
|
public static Color BorderColor { get; set; }
|
||||||
public static Color ColorBorder { get; set; }
|
|
||||||
public static Color ColorTop { get; set; }
|
|
||||||
public static Color ColorSelection { get; set; }
|
|
||||||
public static Color ColorBackground { get; set; }
|
|
||||||
|
|
||||||
public static Color ColorToolStrip1 { get; set; }
|
|
||||||
public static Color ColorToolStrip2 { get; set; }
|
|
||||||
public static Color ColorToolStrip3 { get; set; }
|
|
||||||
public static Color ColorToolStrip4 { get; set; }
|
|
||||||
|
|
||||||
int TextOffset;
|
int TextOffset;
|
||||||
|
|
||||||
public static void InitColors(Color c, bool darkMode)
|
public static void SetDefaultColors()
|
||||||
{
|
{
|
||||||
ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100);
|
ForegroundColor = Color.FromArgb(unchecked((int)0xFF000000));
|
||||||
ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(160);
|
BackgroundColor = Color.FromArgb(unchecked((int)0xFFDFDFDF));
|
||||||
ColorSelection = HSLColor.Convert(c).ToColorSetLuminosity(180);
|
SelectionColor = Color.FromArgb(unchecked((int)0xFFBFBFBF));
|
||||||
ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(210);
|
CheckedColor = Color.FromArgb(unchecked((int)0xFFAAAAAA));
|
||||||
ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240);
|
BorderColor = Color.FromArgb(unchecked((int)0xFF6A6A6A));
|
||||||
|
|
||||||
if (darkMode)
|
|
||||||
{
|
|
||||||
ColorBorder = Color.White;
|
|
||||||
ColorBackground = Color.FromArgb(50, 50, 50);
|
|
||||||
ColorSelection = Color.FromArgb(80, 80, 80);
|
|
||||||
ColorForeground = Color.White;
|
|
||||||
ColorChecked = Color.FromArgb(90, 90, 90);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorToolStrip1 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 1)));
|
|
||||||
ColorToolStrip2 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.7f)));
|
|
||||||
ColorToolStrip3 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.1f)));
|
|
||||||
ColorToolStrip4 = ControlPaint.LightLight(ControlPaint.LightLight(ControlPaint.Light(ColorBorder, 0.4f)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
|
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
|
||||||
{
|
{
|
||||||
Rectangle r = e.AffectedBounds;
|
Rectangle r = e.AffectedBounds;
|
||||||
r.Inflate(-1, -1);
|
r.Inflate(-1, -1);
|
||||||
ControlPaint.DrawBorder(e.Graphics, r, ColorBackground, ButtonBorderStyle.Solid);
|
ControlPaint.DrawBorder(e.Graphics, r, BackgroundColor, ButtonBorderStyle.Solid);
|
||||||
ControlPaint.DrawBorder(e.Graphics, e.AffectedBounds, ColorBorder, ButtonBorderStyle.Solid);
|
ControlPaint.DrawBorder(e.Graphics, e.AffectedBounds, BorderColor, ButtonBorderStyle.Solid);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
|
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
|
||||||
@@ -193,37 +169,26 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
|||||||
else
|
else
|
||||||
TextOffset = Convert.ToInt32(e.Item.Height * 0.2);
|
TextOffset = Convert.ToInt32(e.Item.Height * 0.2);
|
||||||
|
|
||||||
e.TextColor = ColorForeground;
|
e.TextColor = ForegroundColor;
|
||||||
e.TextRectangle = new Rectangle(TextOffset, Convert.ToInt32((e.Item.Height - rect.Height) / 2.0), rect.Width, rect.Height);
|
e.TextRectangle = new Rectangle(TextOffset, Convert.ToInt32((e.Item.Height - rect.Height) / 2.0), rect.Width, rect.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnRenderItemText(e);
|
base.OnRenderItemText(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
|
|
||||||
{
|
|
||||||
if (!(e.ToolStrip is ToolStripDropDownMenu) && !(e.ToolStrip.LayoutStyle == ToolStripLayoutStyle.VerticalStackWithOverflow))
|
|
||||||
{
|
|
||||||
Rectangle r = new Rectangle(-1, -1, e.AffectedBounds.Width, e.AffectedBounds.Height);
|
|
||||||
|
|
||||||
using (SolidBrush b = new SolidBrush(ColorToolStrip2))
|
|
||||||
e.Graphics.FillRectangle(b, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
|
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
|
||||||
{
|
{
|
||||||
Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
|
Rectangle rect = new Rectangle(Point.Empty, e.Item.Size);
|
||||||
|
|
||||||
if (!(e.Item.Owner is MenuStrip))
|
if (!(e.Item.Owner is MenuStrip))
|
||||||
e.Graphics.Clear(ColorBackground);
|
e.Graphics.Clear(BackgroundColor);
|
||||||
|
|
||||||
if (e.Item.Selected && e.Item.Enabled)
|
if (e.Item.Selected && e.Item.Enabled)
|
||||||
{
|
{
|
||||||
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
rect = new Rectangle(rect.X + 2, rect.Y, rect.Width - 4, rect.Height - 1);
|
rect = new Rectangle(rect.X + 2, rect.Y, rect.Width - 4, rect.Height - 1);
|
||||||
rect.Inflate(-1, -1);
|
rect.Inflate(-1, -1);
|
||||||
using (SolidBrush b = new SolidBrush(ColorSelection))
|
using (SolidBrush b = new SolidBrush(SelectionColor))
|
||||||
e.Graphics.FillRectangle(b, rect);
|
e.Graphics.FillRectangle(b, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,7 +204,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
|||||||
float y3 = e.Item.Height * 0.75f;
|
float y3 = e.Item.Height * 0.75f;
|
||||||
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
|
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
|
||||||
using (Brush b = new SolidBrush(ColorForeground))
|
using (Brush b = new SolidBrush(ForegroundColor))
|
||||||
{
|
{
|
||||||
using (Pen p = new Pen(b, Control.DefaultFont.Height / 20f))
|
using (Pen p = new Pen(b, Control.DefaultFont.Height / 20f))
|
||||||
{
|
{
|
||||||
@@ -265,7 +230,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
|||||||
rect = new Rectangle(rect.X + 2, rect.Y, rect.Height - 1, rect.Height - 1);
|
rect = new Rectangle(rect.X + 2, rect.Y, rect.Height - 1, rect.Height - 1);
|
||||||
rect.Inflate(-1, -1);
|
rect.Inflate(-1, -1);
|
||||||
|
|
||||||
using (Brush brush = new SolidBrush(ColorChecked))
|
using (Brush brush = new SolidBrush(CheckedColor))
|
||||||
e.Graphics.FillRectangle(brush, rect);
|
e.Graphics.FillRectangle(brush, rect);
|
||||||
|
|
||||||
float ellipseWidth = rect.Height / 3f;
|
float ellipseWidth = rect.Height / 3f;
|
||||||
@@ -275,17 +240,17 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
|
|||||||
ellipseWidth,
|
ellipseWidth,
|
||||||
ellipseWidth);
|
ellipseWidth);
|
||||||
|
|
||||||
using (Brush brush = new SolidBrush(ColorForeground))
|
using (Brush brush = new SolidBrush(ForegroundColor))
|
||||||
e.Graphics.FillEllipse(brush, rectF);
|
e.Graphics.FillEllipse(brush, rectF);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
|
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
|
||||||
{
|
{
|
||||||
e.Graphics.Clear(ColorBackground);
|
e.Graphics.Clear(BackgroundColor);
|
||||||
int top = e.Item.Height / 2;
|
int top = e.Item.Height / 2;
|
||||||
top -= 1;
|
top -= 1;
|
||||||
int offset = Convert.ToInt32(e.Item.Font.Height * 0.7);
|
int offset = Convert.ToInt32(e.Item.Font.Height * 0.7);
|
||||||
using (Pen p = new Pen(ColorBorder))
|
using (Pen p = new Pen(BorderColor))
|
||||||
e.Graphics.DrawLine(p,
|
e.Graphics.DrawLine(p,
|
||||||
new Point(offset, top),
|
new Point(offset, top),
|
||||||
new Point(e.Item.Width - offset, top));
|
new Point(e.Item.Width - offset, top));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>mpvnet</RootNamespace>
|
<RootNamespace>mpvnet</RootNamespace>
|
||||||
<AssemblyName>mpvnet</AssemblyName>
|
<AssemblyName>mpvnet</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile />
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
|
||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
|
||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
@@ -72,31 +73,9 @@
|
|||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="IKVM.Reflection, Version=7.2.4630.5, Culture=neutral, PublicKeyToken=13235d27fcbfff58, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>IronPython\IKVM.Reflection.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="IronPython, Version=2.7.9.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>IronPython\IronPython.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="IronPython.Modules, Version=2.7.9.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>IronPython\IronPython.Modules.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="IronPythonAddon">
|
|
||||||
<HintPath>IronPython\IronPythonAddon.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Dynamic, Version=1.2.2.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>IronPython\Microsoft.Dynamic.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Scripting, Version=1.2.2.0, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>IronPython\Microsoft.Scripting.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.VisualBasic" />
|
<Reference Include="Microsoft.VisualBasic" />
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
<Reference Include="PresentationFramework" />
|
<Reference Include="PresentationFramework" />
|
||||||
@@ -108,14 +87,29 @@
|
|||||||
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll</HintPath>
|
<HintPath>..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xaml" />
|
<Reference Include="System.Xaml" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Misc\App.cs" />
|
||||||
|
<Compile Include="Misc\NewLine.cs" />
|
||||||
<Compile Include="Misc\Extension.cs" />
|
<Compile Include="Misc\Extension.cs" />
|
||||||
<Page Include="Controls\SearchTextBoxUserControl.xaml">
|
<Content Include="..\License.txt">
|
||||||
|
<Link>License.txt</Link>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Resources\theme.txt" />
|
||||||
|
<None Include="Update.ps1">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<Page Include="WPF\SearchTextBoxUserControl.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
<Page Include="WPF\SetupWindow.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -135,7 +129,12 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Compile Include="Controls\SearchTextBoxUserControl.xaml.cs">
|
<Compile Include="Misc\Help.cs" />
|
||||||
|
<Compile Include="Misc\UpdateCheck.cs" />
|
||||||
|
<Compile Include="Misc\RegistryHelp.cs" />
|
||||||
|
<Compile Include="Misc\Theme.cs" />
|
||||||
|
<Compile Include="Misc\PowerShell.cs" />
|
||||||
|
<Compile Include="WPF\SearchTextBoxUserControl.xaml.cs">
|
||||||
<DependentUpon>SearchTextBoxUserControl.xaml</DependentUpon>
|
<DependentUpon>SearchTextBoxUserControl.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="DynamicGUI\DynamicGUI.cs" />
|
<Compile Include="DynamicGUI\DynamicGUI.cs" />
|
||||||
@@ -146,17 +145,17 @@
|
|||||||
<DependentUpon>StringSettingControl.xaml</DependentUpon>
|
<DependentUpon>StringSettingControl.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="DynamicGUI\Tommy.cs" />
|
<Compile Include="DynamicGUI\Tommy.cs" />
|
||||||
|
<Compile Include="Misc\ExtensionMethods.cs" />
|
||||||
<Compile Include="Native\MediaInfo.cs" />
|
<Compile Include="Native\MediaInfo.cs" />
|
||||||
|
<Compile Include="Native\Taskbar.cs" />
|
||||||
<Compile Include="WinForms\Menu.cs">
|
<Compile Include="WinForms\Menu.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Scripting\PowerShellScript.cs" />
|
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Scripting\PythonScript.cs" />
|
|
||||||
<Compile Include="mpv\libmpv.cs" />
|
<Compile Include="mpv\libmpv.cs" />
|
||||||
<Compile Include="WinForms\MainForm.cs">
|
<Compile Include="WinForms\MainForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
@@ -165,13 +164,16 @@
|
|||||||
<DependentUpon>MainForm.cs</DependentUpon>
|
<DependentUpon>MainForm.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Misc\Misc.cs" />
|
<Compile Include="Misc\Misc.cs" />
|
||||||
<Compile Include="mpv\mp.cs" />
|
<Compile Include="mpv\Core.cs" />
|
||||||
<Compile Include="Misc\Command.cs" />
|
<Compile Include="Misc\Commands.cs" />
|
||||||
<Compile Include="Native\Native.cs" />
|
<Compile Include="Native\Native.cs" />
|
||||||
<Compile Include="Native\NativeHelp.cs" />
|
<Compile Include="Native\NativeHelp.cs" />
|
||||||
<Compile Include="Misc\Program.cs" />
|
<Compile Include="Misc\Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Native\TaskDialog.cs" />
|
<Compile Include="Native\TaskDialog.cs" />
|
||||||
|
<Compile Include="WPF\SetupWindow.xaml.cs">
|
||||||
|
<DependentUpon>SetupWindow.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="WPF\EverythingWindow.xaml.cs">
|
<Compile Include="WPF\EverythingWindow.xaml.cs">
|
||||||
<DependentUpon>EverythingWindow.xaml</DependentUpon>
|
<DependentUpon>EverythingWindow.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -202,15 +204,12 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<None Include="..\Changelog.md">
|
<None Include="..\Changelog.md">
|
||||||
<Link>Changelog.md</Link>
|
<Link>Changelog.md</Link>
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\Manual.md">
|
<None Include="..\Manual.md">
|
||||||
<Link>Manual.md</Link>
|
<Link>Manual.md</Link>
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\README.md">
|
<None Include="..\README.md">
|
||||||
<Link>README.md</Link>
|
<Link>README.md</Link>
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
</None>
|
||||||
<None Include="app.manifest" />
|
<None Include="app.manifest" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
@@ -223,23 +222,17 @@
|
|||||||
<DependentUpon>Settings.settings</DependentUpon>
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Content Include="..\LICENSE.txt">
|
|
||||||
<Link>LICENSE.txt</Link>
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="mpvnet.ico" />
|
<Content Include="mpvnet.ico" />
|
||||||
<Content Include="Resources\mpvConf.txt" />
|
<Content Include="Resources\mpv.conf.txt" />
|
||||||
<Content Include="Resources\mpvConfToml.txt" />
|
<Content Include="Resources\editor.toml.txt" />
|
||||||
<None Include="Resources\mpvnet.ico" />
|
<None Include="Resources\mpvnet.ico" />
|
||||||
<None Include="Resources\mpvnet.png" />
|
<None Include="Resources\mpvnet.png" />
|
||||||
<None Include="Resources\mpvNetConf.txt" />
|
|
||||||
<Content Include="Resources\mpvNetConfToml.txt" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Resources\inputConf.txt" />
|
<Content Include="Resources\input.conf.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Include="DynamicGUI\OptionSettingControl.xaml">
|
<Page Include="DynamicGUI\OptionSettingControl.xaml">
|
||||||
|
|||||||
1163
mpv.net/mpv/Core.cs
Normal file
@@ -1,25 +1,31 @@
|
|||||||
using System;
|
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace mpvnet
|
public class libmpv
|
||||||
{
|
{
|
||||||
public class libmpv
|
|
||||||
{
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern IntPtr mpv_create();
|
public static extern IntPtr mpv_create();
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_initialize(IntPtr mpvHandle);
|
public static extern mpv_error mpv_initialize(IntPtr mpvHandle);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_command(IntPtr mpvHandle, IntPtr strings);
|
public static extern mpv_error mpv_command(IntPtr mpvHandle, IntPtr strings);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_command_string(IntPtr mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string command);
|
public static extern mpv_error mpv_command_string(IntPtr mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string command);
|
||||||
|
|
||||||
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern IntPtr mpv_error_string(mpv_error error);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_terminate_destroy(IntPtr mpvHandle);
|
public static extern int mpv_terminate_destroy(IntPtr mpvHandle);
|
||||||
|
|
||||||
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern mpv_error mpv_request_log_messages(IntPtr mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string min_level);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_set_option(IntPtr mpvHandle, byte[] name, mpv_format format, ref long data);
|
public static extern int mpv_set_option(IntPtr mpvHandle, byte[] name, mpv_format format, ref long data);
|
||||||
|
|
||||||
@@ -27,23 +33,22 @@ namespace mpvnet
|
|||||||
public static extern int mpv_set_option_string(IntPtr mpvHandle, byte[] name, byte[] value);
|
public static extern int mpv_set_option_string(IntPtr mpvHandle, byte[] name, byte[] value);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, out IntPtr data);
|
public static extern mpv_error mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, out IntPtr data);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data);
|
public static extern mpv_error mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, out double data);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref byte[] data);
|
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref byte[] data);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref Int64 data);
|
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref Int64 data);
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_observe_property(
|
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data);
|
||||||
IntPtr mpvHandle,
|
|
||||||
UInt64 reply_userdata,
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
[MarshalAs(UnmanagedType.LPUTF8Str)] string name,
|
public static extern mpv_error mpv_observe_property(IntPtr mpvHandle, UInt64 reply_userdata, [MarshalAs(UnmanagedType.LPUTF8Str)] string name, mpv_format format);
|
||||||
mpv_format format);
|
|
||||||
|
|
||||||
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern int mpv_unobserve_property(IntPtr mpvHandle, UInt64 registered_reply_userdata);
|
public static extern int mpv_unobserve_property(IntPtr mpvHandle, UInt64 registered_reply_userdata);
|
||||||
@@ -147,9 +152,9 @@ namespace mpvnet
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct mpv_event_log_message
|
public struct mpv_event_log_message
|
||||||
{
|
{
|
||||||
public string prefix;
|
public IntPtr prefix;
|
||||||
public string level;
|
public IntPtr level;
|
||||||
public string text;
|
public IntPtr text;
|
||||||
public mpv_log_level log_level;
|
public mpv_log_level log_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,5 +188,50 @@ namespace mpvnet
|
|||||||
public int reason;
|
public int reason;
|
||||||
public int error;
|
public int error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IntPtr AllocateUtf8ArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
|
||||||
|
{
|
||||||
|
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
|
||||||
|
byteArrayPointers = new IntPtr[numberOfStrings];
|
||||||
|
IntPtr rootPointer = Marshal.AllocCoTaskMem(IntPtr.Size * numberOfStrings);
|
||||||
|
|
||||||
|
for (int index = 0; index < arr.Length; index++)
|
||||||
|
{
|
||||||
|
var bytes = GetUtf8Bytes(arr[index]);
|
||||||
|
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
|
||||||
|
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
|
||||||
|
byteArrayPointers[index] = unmanagedPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Marshal.Copy(byteArrayPointers, 0, rootPointer, numberOfStrings);
|
||||||
|
return rootPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] ConvertFromUtf8Strings(IntPtr utf8StringArray, int stringCount)
|
||||||
|
{
|
||||||
|
IntPtr[] intPtrArray = new IntPtr[stringCount];
|
||||||
|
string[] stringArray = new string[stringCount];
|
||||||
|
Marshal.Copy(utf8StringArray, intPtrArray, 0, stringCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < stringCount; i++)
|
||||||
|
stringArray[i] = ConvertFromUtf8(intPtrArray[i]);
|
||||||
|
|
||||||
|
return stringArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ConvertFromUtf8(IntPtr nativeUtf8)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
while (Marshal.ReadByte(nativeUtf8, len) != 0)
|
||||||
|
++len;
|
||||||
|
|
||||||
|
byte[] buffer = new byte[len];
|
||||||
|
Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
|
||||||
|
return Encoding.UTF8.GetString(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetError(mpv_error err) => ConvertFromUtf8(mpv_error_string(err));
|
||||||
|
|
||||||
|
public static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
|
||||||
}
|
}
|
||||||
@@ -1,829 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Drawing2D;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
using WinForms = System.Windows.Forms;
|
|
||||||
|
|
||||||
using static mpvnet.libmpv;
|
|
||||||
using static mpvnet.Native;
|
|
||||||
|
|
||||||
namespace mpvnet
|
|
||||||
{
|
|
||||||
public delegate void MpvBoolPropChangeHandler(string propName, bool value);
|
|
||||||
|
|
||||||
public class mp
|
|
||||||
{
|
|
||||||
public static event Action VideoSizeChanged;
|
|
||||||
// Lua/JS event libmpv event
|
|
||||||
|
|
||||||
// MPV_EVENT_NONE
|
|
||||||
public static event Action Shutdown; // shutdown MPV_EVENT_SHUTDOWN
|
|
||||||
public static event Action LogMessage; // log-message MPV_EVENT_LOG_MESSAGE
|
|
||||||
public static event Action GetPropertyReply; // get-property-reply MPV_EVENT_GET_PROPERTY_REPLY
|
|
||||||
public static event Action SetPropertyReply; // set-property-reply MPV_EVENT_SET_PROPERTY_REPLY
|
|
||||||
public static event Action CommandReply; // command-reply MPV_EVENT_COMMAND_REPLY
|
|
||||||
public static event Action StartFile; // start-file MPV_EVENT_START_FILE
|
|
||||||
public static event Action<EndFileEventMode> EndFile; // end-file MPV_EVENT_END_FILE
|
|
||||||
public static event Action FileLoaded; // file-loaded MPV_EVENT_FILE_LOADED
|
|
||||||
public static event Action TracksChanged; // MPV_EVENT_TRACKS_CHANGED
|
|
||||||
public static event Action TrackSwitched; // MPV_EVENT_TRACK_SWITCHED
|
|
||||||
public static event Action Idle; // idle MPV_EVENT_IDLE
|
|
||||||
public static event Action Pause; // MPV_EVENT_PAUSE
|
|
||||||
public static event Action Unpause; // MPV_EVENT_UNPAUSE
|
|
||||||
public static event Action Tick; // tick MPV_EVENT_TICK
|
|
||||||
public static event Action ScriptInputDispatch; // MPV_EVENT_SCRIPT_INPUT_DISPATCH
|
|
||||||
public static event Action<string[]> ClientMessage; // client-message MPV_EVENT_CLIENT_MESSAGE
|
|
||||||
public static event Action VideoReconfig; // video-reconfig MPV_EVENT_VIDEO_RECONFIG
|
|
||||||
public static event Action AudioReconfig; // audio-reconfig MPV_EVENT_AUDIO_RECONFIG
|
|
||||||
public static event Action MetadataUpdate; // MPV_EVENT_METADATA_UPDATE
|
|
||||||
public static event Action Seek; // seek MPV_EVENT_SEEK
|
|
||||||
public static event Action PlaybackRestart; // playback-restart MPV_EVENT_PLAYBACK_RESTART
|
|
||||||
// MPV_EVENT_PROPERTY_CHANGE
|
|
||||||
public static event Action ChapterChange; // MPV_EVENT_CHAPTER_CHANGE
|
|
||||||
public static event Action QueueOverflow; // MPV_EVENT_QUEUE_OVERFLOW
|
|
||||||
public static event Action Hook; // MPV_EVENT_HOOK
|
|
||||||
|
|
||||||
public static IntPtr Handle { get; set; }
|
|
||||||
public static IntPtr WindowHandle { get; set; }
|
|
||||||
public static Extension Extension { get; set; }
|
|
||||||
public static bool IsLogoVisible { set; get; }
|
|
||||||
public static bool IsQuitNeeded { set; get; } = true;
|
|
||||||
public static List<KeyValuePair<string, Action<bool>>> BoolPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<bool>>>();
|
|
||||||
public static List<KeyValuePair<string, Action<int>>> IntPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<int>>>();
|
|
||||||
public static List<KeyValuePair<string, Action<string>>> StringPropChangeActions { get; set; } = new List<KeyValuePair<string, Action<string>>>();
|
|
||||||
public static Size VideoSize { get; set; }
|
|
||||||
public static List<PythonScript> PythonScripts { get; set; } = new List<PythonScript>();
|
|
||||||
public static AutoResetEvent ShutdownAutoResetEvent { get; set; } = new AutoResetEvent(false);
|
|
||||||
public static AutoResetEvent VideoSizeAutoResetEvent { get; set; } = new AutoResetEvent(false);
|
|
||||||
public static List<MediaTrack> MediaTracks { get; set; } = new List<MediaTrack>();
|
|
||||||
public static List<KeyValuePair<string, double>> Chapters { get; set; } = new List<KeyValuePair<string, double>>();
|
|
||||||
|
|
||||||
public static string InputConfPath { get; } = ConfigFolder + "\\input.conf";
|
|
||||||
public static string ConfPath { get; } = ConfigFolder + "\\mpv.conf";
|
|
||||||
public static string Sid { get; set; } = "";
|
|
||||||
public static string Aid { get; set; } = "";
|
|
||||||
public static string Vid { get; set; } = "";
|
|
||||||
|
|
||||||
public static bool Fullscreen { get; set; }
|
|
||||||
public static bool Border { get; set; } = true;
|
|
||||||
|
|
||||||
public static int Screen { get; set; } = -1;
|
|
||||||
public static int Edition { get; set; }
|
|
||||||
|
|
||||||
public static float Autofit { get; set; } = 0.5f;
|
|
||||||
public static float AutofitSmaller { get; set; } = 0.4f;
|
|
||||||
public static float AutofitLarger { get; set; } = 0.75f;
|
|
||||||
|
|
||||||
public static void Init()
|
|
||||||
{
|
|
||||||
LoadLibrary("mpv-1.dll");
|
|
||||||
Handle = mpv_create();
|
|
||||||
|
|
||||||
if (App.IsStartedFromTerminal)
|
|
||||||
{
|
|
||||||
set_property_string("terminal", "yes");
|
|
||||||
set_property_string("msg-level", "osd/libass=fatal");
|
|
||||||
}
|
|
||||||
|
|
||||||
set_property_string("config-dir", ConfigFolder);
|
|
||||||
set_property_string("osc", "yes");
|
|
||||||
set_property_string("config", "yes");
|
|
||||||
set_property_string("wid", MainForm.Hwnd.ToString());
|
|
||||||
set_property_string("force-window", "yes");
|
|
||||||
set_property_string("input-media-keys", "yes");
|
|
||||||
mpv_initialize(Handle);
|
|
||||||
ShowLogo();
|
|
||||||
ProcessCommandLine();
|
|
||||||
Task.Run(() => { EventLoop(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ProcessProperty(string name, string value)
|
|
||||||
{
|
|
||||||
switch (name)
|
|
||||||
{
|
|
||||||
case "autofit":
|
|
||||||
if (int.TryParse(value.Trim('%'), out int result))
|
|
||||||
Autofit = result / 100f;
|
|
||||||
break;
|
|
||||||
case "autofit-smaller":
|
|
||||||
if (int.TryParse(value.Trim('%'), out int result2))
|
|
||||||
AutofitSmaller = result2 / 100f;
|
|
||||||
break;
|
|
||||||
case "autofit-larger":
|
|
||||||
if (int.TryParse(value.Trim('%'), out int result3))
|
|
||||||
AutofitLarger = result3 / 100f;
|
|
||||||
break;
|
|
||||||
case "fs":
|
|
||||||
case "fullscreen": Fullscreen = value == "yes"; break;
|
|
||||||
case "border": Border = value == "yes"; break;
|
|
||||||
case "screen": Screen = Convert.ToInt32(value); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static string _ConfigFolder;
|
|
||||||
|
|
||||||
public static string ConfigFolder {
|
|
||||||
get {
|
|
||||||
if (_ConfigFolder == null)
|
|
||||||
{
|
|
||||||
_ConfigFolder = Application.StartupPath + "\\portable_config\\";
|
|
||||||
|
|
||||||
if (!Directory.Exists(_ConfigFolder))
|
|
||||||
_ConfigFolder = RegHelp.GetString(App.RegPath, "ConfigFolder");
|
|
||||||
|
|
||||||
if (!Directory.Exists(_ConfigFolder))
|
|
||||||
{
|
|
||||||
string portableFolder = Application.StartupPath + "\\portable_config\\";
|
|
||||||
string appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv.net\\";
|
|
||||||
string appdataFolderMpv = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
|
|
||||||
string startupFolder = Application.StartupPath + "\\";
|
|
||||||
|
|
||||||
using (TaskDialog<string> td = new TaskDialog<string>())
|
|
||||||
{
|
|
||||||
td.MainInstruction = "Choose a settings folder.";
|
|
||||||
td.AddCommandLink(@"AppData\Roaming\mpv.net", appdataFolder, appdataFolder);
|
|
||||||
td.AddCommandLink(@"AppData\Roaming\mpv", appdataFolderMpv, appdataFolderMpv);
|
|
||||||
td.AddCommandLink("<startup>\\portable_config", portableFolder, portableFolder);
|
|
||||||
td.AddCommandLink("<startup>", startupFolder, startupFolder);
|
|
||||||
td.AddCommandLink("Choose custom folder", "custom");
|
|
||||||
td.AllowCancel = false;
|
|
||||||
_ConfigFolder = td.Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_ConfigFolder == "custom")
|
|
||||||
{
|
|
||||||
using (var d = new WinForms.FolderBrowserDialog())
|
|
||||||
{
|
|
||||||
d.Description = "Choose a folder.";
|
|
||||||
if (d.ShowDialog() == WinForms.DialogResult.OK)
|
|
||||||
_ConfigFolder = d.SelectedPath + "\\";
|
|
||||||
else
|
|
||||||
_ConfigFolder = appdataFolder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Directory.Exists(_ConfigFolder))
|
|
||||||
Directory.CreateDirectory(_ConfigFolder);
|
|
||||||
|
|
||||||
if (!_ConfigFolder.Contains("portable_config"))
|
|
||||||
RegHelp.SetObject(App.RegPath, "ConfigFolder", _ConfigFolder);
|
|
||||||
|
|
||||||
if (!File.Exists(_ConfigFolder + "\\input.conf"))
|
|
||||||
File.WriteAllText(_ConfigFolder + "\\input.conf", Properties.Resources.inputConf);
|
|
||||||
|
|
||||||
if (!File.Exists(_ConfigFolder + "\\mpv.conf"))
|
|
||||||
File.WriteAllText(_ConfigFolder + "\\mpv.conf", Properties.Resources.mpvConf);
|
|
||||||
|
|
||||||
if (!File.Exists(_ConfigFolder + "\\mpvnet.conf"))
|
|
||||||
File.WriteAllText(_ConfigFolder + "\\mpvnet.conf", Properties.Resources.mpvNetConf);
|
|
||||||
}
|
|
||||||
return _ConfigFolder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (var i in File.ReadAllLines(ConfPath))
|
|
||||||
if (i.Contains("=") && ! i.StartsWith("#"))
|
|
||||||
_Conf[i.Substring(0, i.IndexOf("=")).Trim()] = i.Substring(i.IndexOf("=") + 1).Trim();
|
|
||||||
|
|
||||||
foreach (var i in Conf)
|
|
||||||
ProcessProperty(i.Key, i.Value);
|
|
||||||
}
|
|
||||||
return _Conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadScripts()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (Directory.Exists(Application.StartupPath + "\\Scripts"))
|
|
||||||
{
|
|
||||||
string[] startupScripts = Directory.GetFiles(Application.StartupPath + "\\Scripts");
|
|
||||||
|
|
||||||
foreach (string scriptPath in startupScripts)
|
|
||||||
if (scriptPath.EndsWith(".lua") || scriptPath.EndsWith(".js"))
|
|
||||||
commandv("load-script", $"{scriptPath}");
|
|
||||||
|
|
||||||
foreach (string scriptPath in startupScripts)
|
|
||||||
if (Path.GetExtension(scriptPath) == ".py")
|
|
||||||
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
|
|
||||||
|
|
||||||
foreach (string scriptPath in startupScripts)
|
|
||||||
if (Path.GetExtension(scriptPath) == ".ps1")
|
|
||||||
PowerShellScript.Init(scriptPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Directory.Exists(ConfigFolder + "Scripts"))
|
|
||||||
foreach (string scriptPath in Directory.GetFiles(ConfigFolder + "Scripts"))
|
|
||||||
if (Path.GetExtension(scriptPath) == ".py")
|
|
||||||
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
|
|
||||||
else if (Path.GetExtension(scriptPath) == ".ps1")
|
|
||||||
PowerShellScript.Init(scriptPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EventLoop()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
IntPtr ptr = mpv_wait_event(Handle, -1);
|
|
||||||
mpv_event evt = (mpv_event)Marshal.PtrToStructure(ptr, typeof(mpv_event));
|
|
||||||
|
|
||||||
if (WindowHandle == IntPtr.Zero)
|
|
||||||
WindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
|
|
||||||
|
|
||||||
// Debug.WriteLine(evt.event_id.ToString());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (evt.event_id)
|
|
||||||
{
|
|
||||||
case mpv_event_id.MPV_EVENT_SHUTDOWN:
|
|
||||||
IsQuitNeeded = false;
|
|
||||||
Shutdown?.Invoke();
|
|
||||||
WriteHistory(null);
|
|
||||||
ShutdownAutoResetEvent.Set();
|
|
||||||
return;
|
|
||||||
case mpv_event_id.MPV_EVENT_LOG_MESSAGE:
|
|
||||||
LogMessage?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_GET_PROPERTY_REPLY:
|
|
||||||
GetPropertyReply?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_SET_PROPERTY_REPLY:
|
|
||||||
SetPropertyReply?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_COMMAND_REPLY:
|
|
||||||
CommandReply?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_START_FILE:
|
|
||||||
StartFile?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_END_FILE:
|
|
||||||
var end_fileData = (mpv_event_end_file)Marshal.PtrToStructure(evt.data, typeof(mpv_event_end_file));
|
|
||||||
EndFileEventMode reason = (EndFileEventMode)end_fileData.reason;
|
|
||||||
EndFile?.Invoke(reason);
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_FILE_LOADED:
|
|
||||||
HideLogo();
|
|
||||||
FileLoaded?.Invoke();
|
|
||||||
Size vidSize = new Size(get_property_int("width"), get_property_int("height"));
|
|
||||||
if (vidSize.Width == 0 || vidSize.Height == 0)
|
|
||||||
vidSize = new Size(1, 1);
|
|
||||||
if (VideoSize != vidSize)
|
|
||||||
{
|
|
||||||
VideoSize = vidSize;
|
|
||||||
VideoSizeChanged?.Invoke();
|
|
||||||
}
|
|
||||||
VideoSizeAutoResetEvent.Set();
|
|
||||||
Task.Run(new Action(() => ReadMetaData()));
|
|
||||||
WriteHistory(get_property_string("path"));
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_TRACKS_CHANGED:
|
|
||||||
TracksChanged?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_TRACK_SWITCHED:
|
|
||||||
TrackSwitched?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_IDLE:
|
|
||||||
Idle?.Invoke();
|
|
||||||
if (get_property_int("playlist-count") == 0) ShowLogo();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_PAUSE:
|
|
||||||
Pause?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_UNPAUSE:
|
|
||||||
Unpause?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_TICK:
|
|
||||||
Tick?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_SCRIPT_INPUT_DISPATCH:
|
|
||||||
ScriptInputDispatch?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_CLIENT_MESSAGE:
|
|
||||||
var client_messageData = (mpv_event_client_message)Marshal.PtrToStructure(evt.data, typeof(mpv_event_client_message));
|
|
||||||
string[] args = NativeUtf8StrArray2ManagedStrArray(client_messageData.args, client_messageData.num_args);
|
|
||||||
if (args.Length > 1 && args[0] == "mpv.net")
|
|
||||||
Command.Execute(args[1], args.Skip(2).ToArray());
|
|
||||||
else if (args.Length > 0)
|
|
||||||
ClientMessage?.Invoke(args);
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_VIDEO_RECONFIG:
|
|
||||||
VideoReconfig?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_AUDIO_RECONFIG:
|
|
||||||
AudioReconfig?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_METADATA_UPDATE:
|
|
||||||
MetadataUpdate?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_SEEK:
|
|
||||||
Seek?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_PROPERTY_CHANGE:
|
|
||||||
var propData = (mpv_event_property)Marshal.PtrToStructure(evt.data, typeof(mpv_event_property));
|
|
||||||
|
|
||||||
if (propData.format == mpv_format.MPV_FORMAT_FLAG)
|
|
||||||
foreach (var i in BoolPropChangeActions)
|
|
||||||
if (i.Key== propData.name)
|
|
||||||
i.Value.Invoke(Marshal.PtrToStructure<int>(propData.data) == 1);
|
|
||||||
|
|
||||||
if (propData.format == mpv_format.MPV_FORMAT_STRING)
|
|
||||||
foreach (var i in StringPropChangeActions)
|
|
||||||
if (i.Key == propData.name)
|
|
||||||
i.Value.Invoke(StringFromNativeUtf8(Marshal.PtrToStructure<IntPtr>(propData.data)));
|
|
||||||
|
|
||||||
if (propData.format == mpv_format.MPV_FORMAT_INT64)
|
|
||||||
foreach (var i in IntPropChangeActions)
|
|
||||||
if (i.Key == propData.name)
|
|
||||||
i.Value.Invoke(Marshal.PtrToStructure<int>(propData.data));
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
|
|
||||||
PlaybackRestart?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE:
|
|
||||||
ChapterChange?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_QUEUE_OVERFLOW:
|
|
||||||
QueueOverflow?.Invoke();
|
|
||||||
break;
|
|
||||||
case mpv_event_id.MPV_EVENT_HOOK:
|
|
||||||
Hook?.Invoke();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Msg.ShowException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void HideLogo()
|
|
||||||
{
|
|
||||||
if (IsLogoVisible)
|
|
||||||
{
|
|
||||||
commandv("overlay-remove", "0");
|
|
||||||
IsLogoVisible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<PythonEventObject> PythonEventObjects = new List<PythonEventObject>();
|
|
||||||
|
|
||||||
public static void register_event(string name, IronPython.Runtime.PythonFunction pyFunc)
|
|
||||||
{
|
|
||||||
foreach (var eventInfo in typeof(mp).GetEvents())
|
|
||||||
{
|
|
||||||
if (eventInfo.Name.ToLower() == name.Replace("-", ""))
|
|
||||||
{
|
|
||||||
PythonEventObject eventObject = new PythonEventObject();
|
|
||||||
PythonEventObjects.Add(eventObject);
|
|
||||||
eventObject.PythonFunction = pyFunc;
|
|
||||||
MethodInfo mi;
|
|
||||||
|
|
||||||
if (eventInfo.EventHandlerType == typeof(Action))
|
|
||||||
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.Invoke));
|
|
||||||
else if (eventInfo.EventHandlerType == typeof(Action<EndFileEventMode>))
|
|
||||||
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.InvokeEndFileEventMode));
|
|
||||||
else if (eventInfo.EventHandlerType == typeof(Action<string[]>))
|
|
||||||
mi = eventObject.GetType().GetMethod(nameof(PythonEventObject.InvokeStrings));
|
|
||||||
else
|
|
||||||
throw new Exception();
|
|
||||||
|
|
||||||
eventObject.EventInfo = eventInfo;
|
|
||||||
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventObject, mi);
|
|
||||||
eventObject.Delegate = handler;
|
|
||||||
eventInfo.AddEventHandler(eventObject, handler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void unregister_event(IronPython.Runtime.PythonFunction pyFunc)
|
|
||||||
{
|
|
||||||
foreach (var eventObjects in PythonEventObjects)
|
|
||||||
if (eventObjects.PythonFunction == pyFunc)
|
|
||||||
eventObjects.EventInfo.RemoveEventHandler(eventObjects, eventObjects.Delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void commandv(params string[] args)
|
|
||||||
{
|
|
||||||
if (Handle == IntPtr.Zero) return;
|
|
||||||
IntPtr mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out IntPtr[] byteArrayPointers);
|
|
||||||
int err = mpv_command(Handle, mainPtr);
|
|
||||||
if (err < 0) throw new Exception($"{(mpv_error)err}");
|
|
||||||
foreach (var ptr in byteArrayPointers)
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
Marshal.FreeHGlobal(mainPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void command(string command, bool throwException = false)
|
|
||||||
{
|
|
||||||
if (Handle == IntPtr.Zero) return;
|
|
||||||
int err = mpv_command_string(Handle, command);
|
|
||||||
if (err < 0 && throwException) throw new Exception($"{(mpv_error)err}\n\n" + command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void set_property_string(string name, string value, bool throwOnException = false)
|
|
||||||
{
|
|
||||||
byte[] bytes = GetUtf8Bytes(value);
|
|
||||||
int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
|
|
||||||
if (err < 0 && throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string get_property_string(string name, bool throwOnException = false)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
{
|
|
||||||
if (throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
string ret = StringFromNativeUtf8(lpBuffer);
|
|
||||||
mpv_free(lpBuffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (throwOnException) throw e;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int get_property_int(string name, bool throwOnException = false)
|
|
||||||
{
|
|
||||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
{
|
|
||||||
if (throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lpBuffer.ToInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double get_property_number(string name, bool throwOnException = false)
|
|
||||||
{
|
|
||||||
double val = 0;
|
|
||||||
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
{
|
|
||||||
if (throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void set_property_int(string name, int value, bool throwOnException = false)
|
|
||||||
{
|
|
||||||
Int64 val = value;
|
|
||||||
int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
|
|
||||||
if (err < 0 && throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void observe_property_int(string name, Action<int> action)
|
|
||||||
{
|
|
||||||
int err = mpv_observe_property(Handle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_INT64);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
else
|
|
||||||
IntPropChangeActions.Add(new KeyValuePair<string, Action<int>>(name, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void observe_property_bool(string name, Action<bool> action)
|
|
||||||
{
|
|
||||||
int err = mpv_observe_property(Handle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_FLAG);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
else
|
|
||||||
BoolPropChangeActions.Add(new KeyValuePair<string, Action<bool>>(name, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void observe_property_string(string name, Action<string> action)
|
|
||||||
{
|
|
||||||
int err = mpv_observe_property(Handle, (ulong)action.GetHashCode(), name, mpv_format.MPV_FORMAT_STRING);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
throw new Exception($"{name}: {(mpv_error)err}");
|
|
||||||
else
|
|
||||||
StringPropChangeActions.Add(new KeyValuePair<string, Action<string>>(name, action));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void ProcessCommandLine()
|
|
||||||
{
|
|
||||||
var args = Environment.GetCommandLineArgs().Skip(1);
|
|
||||||
List<string> files = new List<string>();
|
|
||||||
|
|
||||||
foreach (string i in args)
|
|
||||||
{
|
|
||||||
if (!i.StartsWith("--") && (i == "-" || i.Contains("://") || File.Exists(i)))
|
|
||||||
{
|
|
||||||
files.Add(i);
|
|
||||||
if (i.Contains("://")) RegHelp.SetObject(App.RegPath, "LastURL", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string i in args)
|
|
||||||
{
|
|
||||||
if (i.StartsWith("--"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (i.Contains("="))
|
|
||||||
{
|
|
||||||
string left = i.Substring(2, i.IndexOf("=") - 2);
|
|
||||||
string right = i.Substring(left.Length + 3);
|
|
||||||
set_property_string(left, right, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
set_property_string(i.Substring(2), "yes", true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Msg.ShowException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Load(files.ToArray(), App.ProcessInstance != "queue", Control.ModifierKeys.HasFlag(Keys.Control));
|
|
||||||
|
|
||||||
if (files.Count == 0 || files[0].Contains("://"))
|
|
||||||
{
|
|
||||||
VideoSizeAutoResetEvent.Set();
|
|
||||||
VideoSizeChanged?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DateTime LastLoad;
|
|
||||||
|
|
||||||
public static void Load(string[] files, bool loadFolder, bool append)
|
|
||||||
{
|
|
||||||
if (files is null || files.Length == 0) return;
|
|
||||||
HideLogo();
|
|
||||||
|
|
||||||
if ((DateTime.Now - LastLoad).TotalMilliseconds < 500)
|
|
||||||
append = true;
|
|
||||||
|
|
||||||
LastLoad = DateTime.Now;
|
|
||||||
|
|
||||||
for (int i = 0; i < files.Length; i++)
|
|
||||||
if (App.SubtitleTypes.Contains(Path.GetExtension(files[i]).TrimStart('.').ToLower()))
|
|
||||||
commandv("sub-add", files[i]);
|
|
||||||
else
|
|
||||||
if (i == 0 && !append)
|
|
||||||
commandv("loadfile", files[i]);
|
|
||||||
else
|
|
||||||
commandv("loadfile", files[i], "append");
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(get_property_string("path")))
|
|
||||||
set_property_int("playlist-pos", 0);
|
|
||||||
|
|
||||||
if (loadFolder && !append) Task.Run(() => LoadFolder()); // user reported race condition
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadFolder()
|
|
||||||
{
|
|
||||||
Thread.Sleep(200); // user reported race condition
|
|
||||||
string path = get_property_string("path");
|
|
||||||
if (!File.Exists(path) || get_property_int("playlist-count") != 1) return;
|
|
||||||
List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
|
|
||||||
files = files.Where((file) =>
|
|
||||||
App.VideoTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower()) ||
|
|
||||||
App.AudioTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower()) ||
|
|
||||||
App.ImageTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower())).ToList();
|
|
||||||
files.Sort(new StringLogicalComparer());
|
|
||||||
int index = files.IndexOf(path);
|
|
||||||
files.Remove(path);
|
|
||||||
foreach (string i in files)
|
|
||||||
commandv("loadfile", i, "append");
|
|
||||||
if (index > 0) commandv("playlist-move", "0", (index + 1).ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
|
|
||||||
{
|
|
||||||
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
|
|
||||||
byteArrayPointers = new IntPtr[numberOfStrings];
|
|
||||||
IntPtr rootPointer = Marshal.AllocCoTaskMem(IntPtr.Size * numberOfStrings);
|
|
||||||
|
|
||||||
for (int index = 0; index < arr.Length; index++)
|
|
||||||
{
|
|
||||||
var bytes = GetUtf8Bytes(arr[index]);
|
|
||||||
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
|
|
||||||
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
|
|
||||||
byteArrayPointers[index] = unmanagedPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
Marshal.Copy(byteArrayPointers, 0, rootPointer, numberOfStrings);
|
|
||||||
return rootPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string[] NativeUtf8StrArray2ManagedStrArray(IntPtr unmanagedStringArray, int StringCount)
|
|
||||||
{
|
|
||||||
IntPtr[] intPtrArray = new IntPtr[StringCount];
|
|
||||||
string[] stringArray = new string[StringCount];
|
|
||||||
Marshal.Copy(unmanagedStringArray, intPtrArray, 0, StringCount);
|
|
||||||
|
|
||||||
for (int i = 0; i < StringCount; i++)
|
|
||||||
stringArray[i] = StringFromNativeUtf8(intPtrArray[i]);
|
|
||||||
|
|
||||||
return stringArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string StringFromNativeUtf8(IntPtr nativeUtf8)
|
|
||||||
{
|
|
||||||
int len = 0;
|
|
||||||
while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len;
|
|
||||||
byte[] buffer = new byte[len];
|
|
||||||
Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length);
|
|
||||||
return Encoding.UTF8.GetString(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte[] GetUtf8Bytes(string s) => Encoding.UTF8.GetBytes(s + "\0");
|
|
||||||
|
|
||||||
static string LastHistoryPath;
|
|
||||||
static DateTime LastHistoryStartDateTime;
|
|
||||||
|
|
||||||
static void WriteHistory(string path)
|
|
||||||
{
|
|
||||||
if (!File.Exists(path)) return;
|
|
||||||
int totalMinutes = Convert.ToInt32((DateTime.Now - LastHistoryStartDateTime).TotalMinutes);
|
|
||||||
|
|
||||||
if (File.Exists(LastHistoryPath) && totalMinutes > 1)
|
|
||||||
{
|
|
||||||
string historyFilepath = ConfigFolder + "history.txt";
|
|
||||||
|
|
||||||
File.AppendAllText(historyFilepath, DateTime.Now.ToString().Substring(0, 16) +
|
|
||||||
" " + totalMinutes.ToString().PadLeft(3) + " " +
|
|
||||||
Path.GetFileNameWithoutExtension(LastHistoryPath) + "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
LastHistoryPath = path;
|
|
||||||
LastHistoryStartDateTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ShowLogo()
|
|
||||||
{
|
|
||||||
if (MainForm.Instance is null) return;
|
|
||||||
Rectangle cr = MainForm.Instance.ClientRectangle;
|
|
||||||
int len = cr.Height / 5;
|
|
||||||
if (len == 0) return;
|
|
||||||
|
|
||||||
using (Bitmap b = new Bitmap(len, len))
|
|
||||||
{
|
|
||||||
using (Graphics g = Graphics.FromImage(b))
|
|
||||||
{
|
|
||||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
||||||
g.Clear(Color.Black);
|
|
||||||
Rectangle rect = new Rectangle(0, 0, len, len);
|
|
||||||
g.DrawImage(Properties.Resources.mpvnet, rect);
|
|
||||||
BitmapData bd = b.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
|
|
||||||
int x = Convert.ToInt32((cr.Width - len) / 2.0);
|
|
||||||
int y = Convert.ToInt32(((cr.Height - len) / 2.0) * 0.9);
|
|
||||||
commandv("overlay-add", "0", $"{x}", $"{y}", "&" + bd.Scan0.ToInt64().ToString(), "0", "bgra", bd.Width.ToString(), bd.Height.ToString(), bd.Stride.ToString());
|
|
||||||
b.UnlockBits(bd);
|
|
||||||
IsLogoVisible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ReadMetaData()
|
|
||||||
{
|
|
||||||
lock (MediaTracks)
|
|
||||||
{
|
|
||||||
MediaTracks.Clear();
|
|
||||||
string path = get_property_string("path");
|
|
||||||
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
using (MediaInfo mi = new MediaInfo(path))
|
|
||||||
{
|
|
||||||
int count = mi.GetCount(MediaInfoStreamKind.Video);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
MediaTrack track = new MediaTrack();
|
|
||||||
Add(track, mi.GetVideo(i, "Format"));
|
|
||||||
Add(track, mi.GetVideo(i, "Format_Profile"));
|
|
||||||
Add(track, mi.GetVideo(i, "Width") + "x" + mi.GetVideo(i, "Height"));
|
|
||||||
Add(track, mi.GetVideo(i, "FrameRate") + " FPS");
|
|
||||||
Add(track, mi.GetVideo(i, "Language/String"));
|
|
||||||
Add(track, mi.GetVideo(i, "Forced") == "Yes" ? "Forced" : "");
|
|
||||||
Add(track, mi.GetVideo(i, "Default") == "Yes" ? "Default" : "");
|
|
||||||
Add(track, mi.GetVideo(i, "Title"));
|
|
||||||
track.Text = "V: " + track.Text.Trim(' ', ',');
|
|
||||||
track.Type = "v";
|
|
||||||
track.ID = i + 1;
|
|
||||||
MediaTracks.Add(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = mi.GetCount(MediaInfoStreamKind.Audio);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
MediaTrack track = new MediaTrack();
|
|
||||||
Add(track, mi.GetAudio(i, "Language/String"));
|
|
||||||
Add(track, mi.GetAudio(i, "Format"));
|
|
||||||
Add(track, mi.GetAudio(i, "Format_Profile"));
|
|
||||||
Add(track, mi.GetAudio(i, "BitRate/String"));
|
|
||||||
Add(track, mi.GetAudio(i, "Channel(s)/String"));
|
|
||||||
Add(track, mi.GetAudio(i, "SamplingRate/String"));
|
|
||||||
Add(track, mi.GetAudio(i, "Forced") == "Yes" ? "Forced" : "");
|
|
||||||
Add(track, mi.GetAudio(i, "Default") == "Yes" ? "Default" : "");
|
|
||||||
Add(track, mi.GetAudio(i, "Title"));
|
|
||||||
track.Text = "A: " + track.Text.Trim(' ', ',');
|
|
||||||
track.Type = "a";
|
|
||||||
track.ID = i + 1;
|
|
||||||
MediaTracks.Add(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = mi.GetCount(MediaInfoStreamKind.Text);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
MediaTrack track = new MediaTrack();
|
|
||||||
Add(track, mi.GetText(i, "Language/String"));
|
|
||||||
Add(track, mi.GetText(i, "Format"));
|
|
||||||
Add(track, mi.GetText(i, "Format_Profile"));
|
|
||||||
Add(track, mi.GetText(i, "Forced") == "Yes" ? "Forced" : "");
|
|
||||||
Add(track, mi.GetText(i, "Default") == "Yes" ? "Default" : "");
|
|
||||||
Add(track, mi.GetText(i, "Title"));
|
|
||||||
track.Text = "S: " + track.Text.Trim(' ', ',');
|
|
||||||
track.Type = "s";
|
|
||||||
track.ID = i + 1;
|
|
||||||
MediaTracks.Add(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = get_property_int("edition-list/count");
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
MediaTrack track = new MediaTrack();
|
|
||||||
track.Text = "E: " + get_property_string($"edition-list/{i}/title");
|
|
||||||
track.Type = "e";
|
|
||||||
track.ID = i;
|
|
||||||
MediaTracks.Add(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Add(MediaTrack track, string val)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(val) && !(track.Text != null && track.Text.Contains(val)))
|
|
||||||
track.Text += " " + val + ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (Chapters)
|
|
||||||
{
|
|
||||||
Chapters.Clear();
|
|
||||||
int count = get_property_int("chapter-list/count");
|
|
||||||
|
|
||||||
for (int x = 0; x < count; x++)
|
|
||||||
{
|
|
||||||
string text = get_property_string($"chapter-list/{x}/title");
|
|
||||||
double time = get_property_number($"chapter-list/{x}/time");
|
|
||||||
Chapters.Add(new KeyValuePair<string, double>(text, time));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum EndFileEventMode
|
|
||||||
{
|
|
||||||
Eof,
|
|
||||||
Stop,
|
|
||||||
Quit,
|
|
||||||
Error,
|
|
||||||
Redirect,
|
|
||||||
Unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
39
scripts/c-sharp/dynamic-context-menu-items.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
// This script creates context menu items dynamically.
|
||||||
|
|
||||||
|
using mpvnet;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
class Script
|
||||||
|
{
|
||||||
|
MainForm MainForm;
|
||||||
|
Core core;
|
||||||
|
|
||||||
|
public Script()
|
||||||
|
{
|
||||||
|
core = Core.core;
|
||||||
|
MainForm = mpvnet.MainForm.Instance;
|
||||||
|
MainForm.ContextMenu.Opening += ContextMenu_Opening;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextMenu_Opening(object sender, CancelEventArgs e)
|
||||||
|
{
|
||||||
|
// edit input.conf and add 'Edition' menu item there
|
||||||
|
MenuItem menuItem = MainForm.FindMenuItem("Edition");
|
||||||
|
|
||||||
|
if (menuItem == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
menuItem.DropDownItems.Clear();
|
||||||
|
var editionTracks = core.MediaTracks.Where(track => track.Type == "e");
|
||||||
|
|
||||||
|
foreach (MediaTrack track in editionTracks)
|
||||||
|
{
|
||||||
|
MenuItem mi = new MenuItem(track.Text);
|
||||||
|
mi.Action = () => { core.commandv("set", "edition", track.ID.ToString()); };
|
||||||
|
mi.Checked = core.Edition == track.ID;
|
||||||
|
menuItem.DropDownItems.Add(mi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
scripts/c-sharp/key-binding.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
// This script adds a key binding.
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using mpvnet;
|
||||||
|
|
||||||
|
class Script
|
||||||
|
{
|
||||||
|
public Script()
|
||||||
|
{
|
||||||
|
string content = "ctrl+w script-message my-message-1 my-argument-1";
|
||||||
|
string sectionName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||||
|
Core core = Core.core;
|
||||||
|
core.commandv("define-section", sectionName, content, "force");
|
||||||
|
core.commandv("enable-section", sectionName);
|
||||||
|
core.ClientMessage += ClientMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientMessage(string[] args)
|
||||||
|
{
|
||||||
|
switch (args[0])
|
||||||
|
{
|
||||||
|
case "my-message-1":
|
||||||
|
Msg.Show(args[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
scripts/c-sharp/observe-property-and-draw-text.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
// This script observes the fullscreen property and
|
||||||
|
// draws text on screen when the property changes.
|
||||||
|
|
||||||
|
using mpvnet;
|
||||||
|
|
||||||
|
class Script
|
||||||
|
{
|
||||||
|
Core core;
|
||||||
|
|
||||||
|
public Script()
|
||||||
|
{
|
||||||
|
core = Core.core;
|
||||||
|
core.observe_property_bool("fullscreen", FullscreenChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullscreenChange(bool value)
|
||||||
|
{
|
||||||
|
core.commandv("show-text", "fullscreen: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
scripts/c-sharp/pause-when-minimize.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
// Pauses playback when window is minimized and resumes afterwards.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
using mpvnet;
|
||||||
|
|
||||||
|
class Script
|
||||||
|
{
|
||||||
|
MainForm Form;
|
||||||
|
Core core;
|
||||||
|
|
||||||
|
bool WasPlaying;
|
||||||
|
bool WasPaused;
|
||||||
|
|
||||||
|
public Script()
|
||||||
|
{
|
||||||
|
core = Core.core;
|
||||||
|
Form = MainForm.Instance;
|
||||||
|
Form.Resize += Form_Resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Form_Resize(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (Form.WindowState == FormWindowState.Minimized)
|
||||||
|
{
|
||||||
|
WasPlaying = !core.get_property_bool("pause");
|
||||||
|
|
||||||
|
if (WasPlaying)
|
||||||
|
{
|
||||||
|
core.set_property_bool("pause", true, true);
|
||||||
|
WasPaused = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (WasPaused)
|
||||||
|
{
|
||||||
|
core.set_property_bool("pause", false, true);
|
||||||
|
WasPaused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
scripts/javascript/seek-show-position.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
// When seeking displays position and duration like so: 70:00 / 80:00
|
||||||
|
// Which is different from most players which use: 01:10:00 / 01:20:00
|
||||||
|
// In input.conf set the input command prefix no-osd infront of the seek command.
|
||||||
|
|
||||||
|
function add_zero(val)
|
||||||
|
{
|
||||||
|
val = Math.round(val);
|
||||||
|
return val > 9 ? "" + val : "0" + val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(val)
|
||||||
|
{
|
||||||
|
var sec = Math.round(val);
|
||||||
|
|
||||||
|
if (sec < 0)
|
||||||
|
sec = 0;
|
||||||
|
|
||||||
|
pos_min_floor = Math.floor(sec / 60);
|
||||||
|
sec_rest = sec - pos_min_floor * 60;
|
||||||
|
return add_zero(pos_min_floor) + ":" + add_zero(sec_rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
function on_seek(_)
|
||||||
|
{
|
||||||
|
pos = mp.get_property_number("time-pos");
|
||||||
|
dur = mp.get_property_number("duration");
|
||||||
|
|
||||||
|
if (pos > dur)
|
||||||
|
pos = dur;
|
||||||
|
|
||||||
|
mp.commandv("show-text", format(pos) + " / " + format(dur));
|
||||||
|
}
|
||||||
|
|
||||||
|
mp.register_event("seek", on_seek);
|
||||||
26
scripts/javascript/show-playlist.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
// This script shows the playlist.
|
||||||
|
|
||||||
|
function showPlaylist()
|
||||||
|
{
|
||||||
|
// set font size
|
||||||
|
mp.set_property_number("osd-font-size", 40);
|
||||||
|
|
||||||
|
// show playlist for 5 seconds
|
||||||
|
mp.command("show-text ${playlist} 5000");
|
||||||
|
|
||||||
|
// restore original font size in 6 seconds
|
||||||
|
setTimeout(resetFontSize, 6000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore original font size
|
||||||
|
function resetFontSize()
|
||||||
|
{
|
||||||
|
mp.set_property_number("osd-font-size", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save original font size
|
||||||
|
var size = mp.get_property_number("osd-font-size");
|
||||||
|
|
||||||
|
// input.conf: key script-binding show-playlist
|
||||||
|
mp.add_key_binding(null, "show-playlist", showPlaylist);
|
||||||
23
scripts/lua/pause-when-minimize.lua
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
-- https://github.com/mpv-player/mpv/blob/master/TOOLS/lua/pause-when-minimize.lua
|
||||||
|
|
||||||
|
-- This script pauses playback when minimizing the window, and resumes playback
|
||||||
|
-- if it's brought back again. If the player was already paused when minimizing,
|
||||||
|
-- then try not to mess with the pause state.
|
||||||
|
|
||||||
|
local did_minimize = false
|
||||||
|
|
||||||
|
mp.observe_property("window-minimized", "bool", function(name, value)
|
||||||
|
local pause = mp.get_property_native("pause")
|
||||||
|
if value == true then
|
||||||
|
if pause == false then
|
||||||
|
mp.set_property_native("pause", true)
|
||||||
|
did_minimize = true
|
||||||
|
end
|
||||||
|
elseif value == false then
|
||||||
|
if did_minimize and (pause == true) then
|
||||||
|
mp.set_property_native("pause", false)
|
||||||
|
end
|
||||||
|
did_minimize = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
20
scripts/powershell/open-file-dialog.ps1
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
# Shows the Open File dialog to open a file without loading its folder into the playlist.
|
||||||
|
|
||||||
|
# In input.conf add: <key> script-message load-without-folder
|
||||||
|
|
||||||
|
$code = {
|
||||||
|
if ($args[0] -eq 'load-without-folder')
|
||||||
|
{
|
||||||
|
$dialog = New-Object Windows.Forms.OpenFileDialog
|
||||||
|
|
||||||
|
if ($dialog.ShowDialog() -eq 'OK')
|
||||||
|
{
|
||||||
|
$core.LoadFiles($dialog.FileNames, $false, $false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialog.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$mp.register_event("client-message", $code)
|
||||||