Compare commits

..

347 Commits

Author SHA1 Message Date
stax76
80c827974a v6.0.4.0 Stable 2023-08-17 02:50:45 +02:00
stax76
d2e7d4551f v6.0.4.0 Stable 2023-08-17 02:38:41 +02:00
stax76
308e3ed044 Merge pull request #541 from soredake/sub-override-keybind
input.conf.txt: add binding for overriding sub styles
2023-08-17 02:31:42 +02:00
soredake
f563342eb5 input.conf.txt: add binding for overriding sub styles 2023-05-07 19:56:30 +03:00
stax76
16d6e4d471 Merge pull request #517 from Torben2000/feature/playlist-titles
Use item title in playlist command palette if set
2023-01-21 08:12:56 +01:00
stax76
030aa930a1 Merge pull request #529 from hooke007/dll
relink to libmpv-2
2023-01-21 08:12:01 +01:00
hooke007
3a6df857da relink to libmpv-2 2023-01-20 15:35:59 +00:00
Torben2000
7d9340d9d5 Use item title in playlist command palette if set
Fixes https://github.com/mpvnet-player/mpv.net/issues/509
2022-12-03 19:30:37 +01:00
stax76
9dca27c941 Merge pull request #510 from soredake/screenshot-without-subtitles
input.conf.txt: add binding for screenshot without subtitles
2022-11-27 07:41:31 +01:00
soredake
6f2b30f762 input.conf.txt: add binding for screenshot without subtitles 2022-11-15 11:57:49 +02:00
stax76
89be723132 Merge pull request #505 from nkh0472/patch-2
fix typo
2022-10-20 17:29:37 +02:00
nkh0472
ec1dde650f fix typo 2022-10-20 23:12:35 +08:00
stax76
dbf1a32580 v6.0.3.2 2022-10-14 12:18:12 +02:00
stax76
a81ed58983 finish repo transfer 2022-10-12 12:40:40 +02:00
stax76
33df960d04 Merge branch 'master' of https://github.com/stax76/mpv.net 2022-10-02 15:40:55 +02:00
stax76
337bee9f28 fix severe termination bug 2022-10-02 15:40:53 +02:00
stax76
e57c41a254 Merge pull request #495 from nkh0472/patch-1
Update Manual_chs.md
2022-10-01 10:19:41 +02:00
nkh0472
62d06c65ab Update Manual_chs.md
Co-authored-by: hooke007 <hooke007@qq.com>
2022-09-25 19:21:22 +08:00
nkh0472
e70a935d7a Update Manual_chs.md
Add more info about translations update this time
2022-09-19 21:14:48 +08:00
nkh0472
c8e6ce678a Update Manual_chs.md
Translations for b73d2e7107 and 1f6025a10f
2022-09-18 23:03:37 +08:00
stax76
22960af78b mouse cursor auto-hide behavior 2022-08-19 07:13:07 +02:00
stax76
95e31a1d3f Improved mouse cursor hide behavior 2022-08-19 06:53:49 +02:00
stax76
06ff83b75c shorter OSD media info 2022-08-18 09:44:52 +02:00
stax76
1f6025a10f New command to move the Window to the screen edge 2022-08-18 09:31:23 +02:00
stax76
00bfa20fac improved OSD media info 2022-08-08 03:19:11 +02:00
stax76
1475d5ee66 conf editor option definition simplyfication 2022-08-07 14:21:11 +02:00
stax76
b73d2e7107 new history-filter option added 2022-08-07 13:50:29 +02:00
stax76
a7fa76d63a relative path fix 2022-08-05 07:11:50 +02:00
stax76
e2c720346a fix #480 2022-08-05 06:29:49 +02:00
stax76
01a853e865 Merge pull request #475 from hooke007/doc
bump Manual_chs v6.0.3.1
2022-07-31 06:47:19 +02:00
hooke007
6510de2bd8 bump Manual_chs v6.0.3.1 2022-07-31 01:01:58 +01:00
stax76
7fc1de2ce3 update process-instance description 2022-07-30 13:35:17 +02:00
stax76
b0d399e9ee update changelog 2022-07-30 13:20:39 +02:00
stax76
7f680829ef update changelog 2022-07-30 13:05:30 +02:00
stax76
603f956261 update changelog 2022-07-30 12:55:32 +02:00
stax76
6d06df9004 6.0.3.1 2022-07-30 12:52:19 +02:00
stax76
5ea086d05b Support --audio-file and --sub-file aliases 2022-07-30 11:45:07 +02:00
stax76
1ad819fa9d Fix external audio tracks not shown correctly in tracks context menu 2022-07-30 11:26:45 +02:00
stax76
f2dd6205b5 Merge branch 'master' of https://github.com/stax76/mpv.net 2022-07-27 09:42:02 +02:00
stax76
b2a3c231ff command line syntax is supported in mpv.conf 2022-07-27 09:42:00 +02:00
stax76
f6c223a411 Update issue templates 2022-07-25 09:51:28 +02:00
stax76
e7a2ba6805 Update issue templates 2022-07-25 09:43:58 +02:00
stax76
5a08d9ccd6 Shift key enables process-instance=multi 2022-07-23 08:50:07 +02:00
stax76
5714a5e62a Merge branch 'master' of https://github.com/stax76/mpv.net 2022-07-17 08:04:43 +02:00
stax76
def7e5ac5a misc 2022-07-17 08:04:32 +02:00
stax76
601bb20492 Update FUNDING.yml 2022-07-14 04:31:20 +02:00
stax76
59600df977 update manual 2022-07-13 09:02:51 +02:00
stax76
e1b9730e9b use mpv.net to cycle subtitles 2022-07-12 05:49:05 +02:00
stax76
e378551938 misc 2022-07-11 13:14:26 +02:00
stax76
a82b2ef571 disable unused mpv events 2022-07-11 07:05:50 +02:00
stax76
6157a01701 disable unused mpv events 2022-07-11 06:57:10 +02:00
stax76
ec17ae8ce9 support shortcuts with media file target 2022-07-11 06:14:01 +02:00
stax76
f719528017 fix #293 2022-07-10 10:30:01 +02:00
stax76
966b45eb65 shorten annoying media info titles 2022-07-10 00:49:56 +02:00
stax76
eeae6994a2 remove basic view and enhance advanced view of show-info command 2022-07-09 17:26:49 +02:00
stax76
07809d882f use mpvnet instead of mpv to create playlist from folder 2022-07-08 12:20:36 +02:00
stax76
e970f0b4e4 libmpv shinchiro 2022-07-02 2022-07-08 05:51:06 +02:00
stax76
a36b6a3fdf misc 2022-07-04 08:45:37 +02:00
stax76
4febca257f properly fix OSC hide behavior 2022-07-04 08:32:53 +02:00
stax76
9d493b4d08 store package update 2022-07-03 10:49:13 +02:00
stax76
9a6bf5a481 v6.0.3.0 update changelog 2022-07-03 10:35:39 +02:00
stax76
40565e8b3d fix possible race condition 2022-07-02 15:10:22 +02:00
stax76
fb294c441d 6.0.2.0 2022-07-02 10:19:19 +02:00
stax76
03b775370b window title fix 2022-07-02 09:35:15 +02:00
stax76
1015f87533 changelog fix 2022-06-30 15:19:42 +02:00
stax76
cadc5d65cf 6.0.1.0 2022-06-30 15:00:07 +02:00
stax76
3e2f104aa7 fix #449 2022-06-28 15:17:35 +02:00
stax76
c87ce3b66f fix #449 2022-06-28 07:53:48 +02:00
stax76
3093dd43a4 add smart-volume script to changelog 2022-06-27 15:03:26 +02:00
stax76
061bb39b60 improve changlog 2022-06-25 16:22:05 +02:00
stax76
d994c79d5d fix #372 2022-06-25 16:18:16 +02:00
stax76
9ca66db07b Merge pull request #448 from soredake/patch-1
Add two new keybinds for controlling volume
2022-06-25 16:02:22 +02:00
stax76
4a382d4e29 border issue 2022-06-25 13:56:45 +02:00
stax76
69a5ba4470 Fix #445 chapters that are script created after the media file is loaded 2022-06-25 13:07:17 +02:00
soredake
4a890a4da7 Add two new keybinds for controlling volume
This keybinds is used in mpv, - + are intuitive for controlling volume, but i have compact keyboard without numpad, and pressing + in number row requires me to press it with shift, which i want to avoid.
2022-06-23 21:23:29 +03:00
stax76
023c1db417 recent list path normalization 2022-06-20 19:29:39 +02:00
stax76
7ef1f9315e Width of command palette slightly increased 2022-06-20 19:24:24 +02:00
stax76
a148c88435 new option minimum-aspect-ratio-audio 2022-06-19 18:06:08 +02:00
stax76
f6ad169f9d show Default only when track count is > 1 2022-06-19 08:21:31 +02:00
stax76
e69a5559e8 Fix start-size=session not working 2022-06-19 07:51:30 +02:00
stax76
500fe9abc4 #442 show chapters in the command palette 2022-06-19 05:23:10 +02:00
stax76
55f4a340af setting env var MPVNET_VERSION 2022-06-14 15:09:56 +02:00
stax76
b17ed3675e #334 New support of the mpv option snap-window 2022-06-11 09:32:02 +02:00
stax76
34031fa15d Fix borderless window not resizable with mouse 2022-06-09 21:48:35 +02:00
stax76
d6d31d8ae9 Fix compatibility with mpv-osc-tethys 2022-06-09 19:37:42 +02:00
stax76
0bfee26418 logo change 2022-06-09 10:25:06 +02:00
stax76
71d6b96c10 Fix logo overlap using mordenx.lua 2022-06-09 08:27:45 +02:00
stax76
d1b7250a7a changelog update 2022-06-08 21:39:36 +02:00
stax76
39b81d0664 manual update 2022-06-08 21:05:42 +02:00
stax76
6337818dbc New options autofit-image and autofit-audio 2022-06-08 10:16:40 +02:00
stax76
2257af6294 change minimum-aspect-ratio default value to 0 2022-06-07 23:00:10 +02:00
stax76
572257b645 change minimum-aspect-ratio default value to 1 2022-06-07 22:51:52 +02:00
stax76
6eb82b6b7e Merge pull request #437 from hooke007/doc
bump Manual_chs v6.0.0.0
2022-06-06 19:30:56 +02:00
hooke007
7ef703da42 bump Manual_chs v6.0.0.0 2022-06-06 17:12:09 +01:00
stax76
f7f8aa550a use filtered-metadata option for music osd 2022-06-05 18:55:08 +02:00
stax76
8d693b5e01 fix minor conf editor issue 2022-06-05 17:26:44 +02:00
stax76
e8bc8311e6 add header format to changelog 2022-06-05 16:45:11 +02:00
stax76
19c4a1d6c1 6.0.0.0 Beta 2022-06-05 16:42:47 +02:00
stax76
a53fa7178f libmpv update changelog 2022-06-05 13:09:43 +02:00
stax76
09aee26cd4 Fix logo not hiding sometimes using gpu-api=vulkan 2022-06-05 12:55:53 +02:00
stax76
0c6e486eb0 #435 Fix mpv options not working in case of existing same line comments 2022-06-05 06:40:42 +02:00
stax76
1561ed90f6 remove 'mpv.net' from conf editor definitions that are not specific to mpv.net 2022-06-04 10:31:52 +02:00
stax76
c2f965ced9 improved changelog 2022-06-04 10:06:48 +02:00
stax76
aed524bbc5 Merge pull request #434 from dyphire/track_menu
optimize subtitle format information
2022-06-04 08:42:53 +02:00
dyphire
8cf7e4fd71 optimize subtitle format information 2022-06-04 11:21:06 +08:00
stax76
0ebcf12502 update changelog 2022-06-04 00:32:45 +02:00
stax76
2af13e995f using media info by default 2022-06-04 00:27:17 +02:00
stax76
2e2562fefc shorter media info to better fit on screen 2022-06-04 00:17:56 +02:00
stax76
1860c42114 Merge pull request #433 from dyphire/track_menu
Minor changes to track menu
2022-06-03 23:10:22 +02:00
dyphire
8782ae8ad2 Minor changes 2022-06-04 04:21:07 +08:00
stax76
5d9cde10ce fix issue using external tracks 2022-06-03 21:08:30 +02:00
stax76
2ee2b31bc0 menu fix 2022-06-03 21:02:29 +02:00
stax76
4cd92db141 use new msg model everywhere 2022-06-03 20:23:05 +02:00
stax76
8ee389e8cb misc 2022-06-03 18:38:53 +02:00
stax76
971fe1fe7c - 2022-06-03 15:47:21 +02:00
stax76
e9df0f9f99 - 2022-06-02 20:16:13 +02:00
stax76
d465b13a03 Merge branch 'master' into no-mediainfo 2022-06-02 14:18:07 +02:00
stax76
412d4d7238 Merge pull request #432 from dyphire/track_menu
Optimize track menu.
2022-06-02 14:17:04 +02:00
stax76
1dd93bfcff - 2022-06-02 14:15:02 +02:00
stax76
4ebf241306 shorten mpv.conf preview 2022-06-02 12:37:56 +02:00
dyphire
1a714a39df Optimize track menu
Add encoding information to subtitles

Add title for external tracks, match and replace the filename to avoid too long characters
2022-06-02 11:33:18 +08:00
stax76
b2b387c017 #344 cache and demuxer-max-bytes option added to conf editor 2022-06-01 14:55:04 +02:00
stax76
bf43328e7a require at least 2 characters in conf editor search 2022-06-01 10:16:36 +02:00
stax76
4cba6bb03c fix changelog 2022-05-28 00:54:33 +02:00
stax76
72f9f156b8 fix external tracks 2022-05-27 16:21:42 +02:00
stax76
c78719c3bf Fix #426 external audio and subtitle tracks 2022-05-27 14:07:04 +02:00
stax76
7e4ea640cf Command messages are dispatched with script-message-to mpvnet 2022-05-27 12:20:37 +02:00
stax76
6ddca6d608 minor rewrite 2022-05-26 19:06:32 +02:00
stax76
0fae17b42a support idlelogo 2022-05-26 18:39:44 +02:00
stax76
7e834cea6d Fix #424 media title issues 2022-05-26 11:36:24 +02:00
stax76
6fc546c69c auto-load-folder threading stability 2022-05-22 15:49:25 +02:00
stax76
e8baa21d42 Fix auto-load-folder not working with user scripts 2022-05-22 14:35:43 +02:00
stax76
4c3c65dded #423 Fix chapter time display in menu 2022-05-22 11:48:35 +02:00
stax76
843f7d1a41 manual fix 2022-05-22 09:10:10 +02:00
stax76
673d5a8c0e manual improvement 2022-05-22 09:07:36 +02:00
stax76
6bd4540106 Fix #422 slow startup using osd-scale-by-window=no 2022-05-22 08:22:49 +02:00
stax76
5b57e6214e change profile using command palette 2022-05-22 08:07:48 +02:00
stax76
27f7935127 misc 2022-05-21 10:58:39 +02:00
stax76
cd84819a03 New show-santa-logo (green and grumpy) option 2022-05-21 08:52:44 +02:00
stax76
0efc335232 new quick bookmark feature 2022-05-21 08:31:06 +02:00
stax76
b04fb9b789 input conf use 'V' for 'Open URL or file from clipboard' 2022-05-20 18:18:56 +02:00
stax76
354d5493c4 improved error handling 2022-05-20 14:50:56 +02:00
stax76
3e499befbc Fix #421 crash choosing Matroska edition in the menu. 2022-05-20 14:29:21 +02:00
stax76
bc0fc2a29d Fix auto-play not working with user scripts 2022-05-19 23:17:23 +02:00
stax76
229ace708d minor input.conf change 2022-05-18 11:54:34 +02:00
stax76
2708937554 input.conf duplicate fix 2022-05-17 18:37:31 +02:00
stax76
66654537fe idle fix 2022-05-17 17:10:45 +02:00
stax76
5d16d7b2d1 support mpv idle property partly 2022-05-17 15:05:00 +02:00
stax76
b3ebf85772 Merge pull request #419 from hooke007/doc
bump Manual_chs v5.9.0.0
2022-05-14 14:24:11 +02:00
hooke007
733f0999e1 bump Manual_chs v5.9.0.0 2022-05-13 21:28:25 +01:00
stax76
2aec8856c7 script-opts defaults 2022-05-13 13:39:40 +02:00
stax76
a0d5a6f234 libmpv update 2022-05-08 15:08:32 +02:00
stax76
d9afd172f9 5.9.0.0 Beta 2022-05-08 15:01:45 +02:00
stax76
3b9368230c fix #414 2022-05-05 12:31:13 +02:00
stax76
7d510a8ba7 update about 2022-05-04 15:25:51 +02:00
stax76
e7f08bf0a7 about update 2022-05-04 13:12:33 +02:00
stax76
ad3235bb96 update project description 2022-05-04 12:33:47 +02:00
stax76
b5b18f2a1a try to fix #413 2022-05-04 12:06:20 +02:00
stax76
28f9df1cee New mpv.net specific option keep-open-exit added 2022-05-03 15:18:42 +02:00
stax76
cd2f2aeec8 Fix config editor handling keep-open incorrectly 2022-05-03 14:25:15 +02:00
stax76
a15d2cdbbe playlist-add command added 2022-05-01 01:01:51 +02:00
stax76
f489d59168 Fix multi monitor setup with different DPI values 2022-04-28 21:53:50 +02:00
stax76
309ddbf08e Fix #398 keyboard layout change not working 2022-04-08 19:16:18 +02:00
stax76
1bc6fb9509 Merge pull request #400 from hooke007/dev
update manual_chs for v5.8.0.0
2022-04-05 19:55:19 +02:00
hooke007
88e5628d7b update manual_chs for v5.8.0.0 2022-04-03 21:29:07 +01:00
stax76
27dc98af21 v5.8.0.0 2022-04-02 15:14:36 +02:00
stax76
ce12eb61fd Info command shows the length 2022-04-02 11:40:40 +02:00
stax76
8ed62df8e2 workaround not reproducible logo drawing crash 2022-04-02 11:15:04 +02:00
stax76
f4b4be5466 add show-menu to changelog and manual 2022-03-31 16:41:23 +02:00
stax76
9a33bea7e7 context menu issue fix #396 2022-03-31 16:22:54 +02:00
stax76
3f469897b0 Fix crash on Windows 7 systems without PowerShell. 2022-03-24 18:32:32 +01:00
stax76
1aa380f768 manual 2022-03-13 14:15:24 +01:00
stax76
b0c3988a9d improved manual 2022-03-13 14:00:26 +01:00
stax76
8c02bb59ee Media Info is shown using command palette 2022-03-12 21:27:07 +01:00
stax76
d60bf050cf show commands with text editor 2022-03-12 14:26:00 +01:00
stax76
a0f2e8bd92 Merge pull request #386 from hooke007/doc
update Manual_chs for v5.7.0.0
2022-03-11 22:05:51 +01:00
stax76
63db623d07 2 fixes 2022-03-11 22:02:54 +01:00
hooke007
ab0b2c4da2 update Manual_chs for v5.7.0.0 2022-03-12 03:35:18 +08:00
stax76
091e159d10 fix MS Store page displaying non existing ARM and x86 support 2022-03-11 15:31:11 +01:00
stax76
91fa89b058 Fix showing incorrect timestamps in About dialog of Store version 2022-03-10 18:27:33 +01:00
stax76
36d3543852 5.7.0.0 Stable 2022-03-09 12:48:52 +01:00
stax76
72ed687390 minor things 2022-03-05 22:06:20 +01:00
stax76
c56855bbc7 5.6.2.0 Beta 2022-03-05 21:05:50 +01:00
stax76
9377804b06 fixing reintroduced osc issue, sorry 2022-03-05 15:39:56 +01:00
stax76
c50ac7a53b manual update again 2022-03-05 15:23:23 +01:00
stax76
677e7b5a59 manual update 2022-03-05 15:21:33 +01:00
stax76
8066d07a76 5.6.1.0 Beta 2022-03-05 14:59:05 +01:00
stax76
e8d6081f9f ms store issue fix 2022-03-05 09:51:39 +01:00
stax76
5fb888262e Merge pull request #370 from KaranKad/conf
Added config location for Microsoft Store version
2022-03-05 08:32:13 +01:00
stax76
a4ffab7b50 misc 2022-03-05 07:55:34 +01:00
stax76
8d25803b71 #369 #367 protocol registration 2022-03-05 04:36:09 +01:00
stax76
df4baca6bc protocol fix 2022-03-05 04:05:04 +01:00
stax76
dc43ab4c8f rtsp protocol support 2022-03-05 03:48:47 +01:00
stax76
2249174f96 misc... 2022-03-04 21:49:05 +01:00
stax76
6916a63de6 several improvements 2022-03-02 21:19:55 +01:00
stax76
1064a80dad gpu-next fix 2022-03-02 14:33:47 +01:00
Karan09
4844215462 Add config location for msstore 2022-02-15 21:08:02 +05:30
stax76
b84889b03d manual download instruction updated 2022-01-03 20:57:54 +01:00
stax76
b38bfd9c65 Fix libmpv API changes 2021-12-19 18:40:34 +01:00
stax76
b807ad8002 Merge pull request #357 from hooke007/libmpv
support mpv-2
2021-12-19 16:01:57 +01:00
hooke007
f5854cde1b support mpv-2
drop the support of mpv-1
2021-12-17 07:43:31 +08:00
stax76
bde4849465 menu issue fix 2021-12-01 14:09:31 +01:00
stax76
8677efdb06 Update Main.webp 2021-11-20 21:29:22 +01:00
stax76
2bbd5705c2 readme update 2021-11-20 21:02:04 +01:00
stax76
0bf9b73ba8 manual update 2021-11-19 16:12:10 +01:00
stax76
42fd54269e improved manual 2021-11-19 14:04:46 +01:00
stax76
28f1c5c132 register ytdl protocol with file associations 2021-11-19 12:48:12 +01:00
stax76
30b60a5b4e Merge pull request #343 from hooke007/dev
Update doc
2021-11-18 10:44:50 +01:00
stax76
f0c9dd7956 docs improvement 2021-11-18 10:36:32 +01:00
hooke007
78ee4fbba2 Update Manual_chs.md
follow orginal commit 243b45326e
2021-11-17 02:54:24 +08:00
stax76
243b45326e Auto update feature removed 2021-11-14 00:05:31 +01:00
stax76
4efe85aad7 misc... 2021-11-13 23:43:47 +01:00
stax76
975f918703 changelog update 2021-11-06 16:15:05 +01:00
stax76
d9f4218bb4 Merge pull request #336 from hooke007/dev
update editor
2021-11-06 16:03:36 +01:00
stax76
671c15385a manual fix 2021-11-05 15:58:25 +01:00
stax76
091b9aad5b manual fix 2021-11-05 15:56:14 +01:00
stax76
e51b745a13 5.5.0.4 Beta 2021-11-05 15:53:57 +01:00
stax76
ad1ea92cbd window-scale property support 2021-11-05 15:23:47 +01:00
hooke007
66bfb80f3c update editor
mainly support `gpu-next`
2021-11-04 08:13:28 +08:00
stax76
ef6b453673 readme update 2021-11-02 11:47:32 +01:00
stax76
5496d22c48 readme update 2021-11-02 11:45:20 +01:00
stax76
7cd3a8276d WPF blur issue fix? 2021-10-26 12:24:23 +02:00
stax76
99ea7285ba manual fix 2021-10-24 17:19:47 +02:00
stax76
9722d46d00 support input-default-bindings 2021-10-24 17:08:07 +02:00
stax76
b115cf82d9 manual fix 2021-10-21 00:24:45 +02:00
stax76
f4e72b5a99 typo 2021-10-11 12:50:27 +02:00
stax76
24596626bd misc 2021-10-11 12:29:30 +02:00
stax76
6e761c0a4e minor change 2021-10-10 15:55:51 +02:00
stax76
2a3738f79e Improved handling of default options. 2021-10-10 15:20:12 +02:00
stax76
1a475f9fe8 Support input-builtin-bindings 2021-10-09 14:31:34 +02:00
Frank Skare
819b026ec7 Window size flicker issue fix when changing files 2021-09-23 19:46:38 +02:00
Frank Skare
38a816a255 5.5.0.3 Beta 2021-09-23 12:45:09 +02:00
Frank Skare
e8af1d2ccf cosmetic 2021-09-16 16:13:06 +02:00
Frank Skare
33cd881ae6 #321 new auto-play option 2021-09-16 16:02:59 +02:00
Frank Skare
a3b6af9f22 5.5.0.2 Beta 2021-09-15 13:25:58 +02:00
Frank Skare
458007862e 5.5.0.1 Beta 2021-09-15 11:57:01 +02:00
Frank Skare
2fac5d76e9 5.4.9.9 Beta 2021-09-14 17:26:05 +02:00
Frank Skare
1e886fc124 remove console-scale fix 2021-09-05 22:51:09 +02:00
Frank Skare
c075278180 5.4.9.8 Beta 2021-09-05 22:27:01 +02:00
Frank Skare
333d0ee62f better folder browser code 2021-09-05 21:59:05 +02:00
Frank Skare
7a6b2011e4 improved menu performance and folder browser fix 2021-09-05 08:23:42 +02:00
Frank Skare
e4c65cd84e Use Vista folder browser 2021-09-05 06:06:15 +02:00
Frank Skare
10e2a2cf3b #318 Fix message box not working when ontop is enabled 2021-09-04 12:39:28 +02:00
Frank Skare
0d72731ce7 PS ConvertFrom-Json replaced with JSONParser 2021-09-03 13:04:06 +02:00
Frank Skare
33fb645694 fix watch-later-options default 2021-09-02 15:01:11 +02:00
Frank Skare
d369c9db8e Merge branch 'master' of https://github.com/stax76/mpv.net 2021-09-02 14:42:56 +02:00
Frank Skare
a935cac791 misc 2021-09-02 14:42:53 +02:00
stax76
a08a4b4f92 Merge pull request #317 from hooke007/dev
update misc
2021-09-02 14:42:18 +02:00
hooke007
bd2ba612de a tiny optimize for console output 2021-09-02 19:45:04 +08:00
hooke007
306d186bef revert keep-open 2021-09-02 19:24:17 +08:00
hooke007
da67d62946 fix mpvconf
disable `start`
2021-09-02 00:35:49 +08:00
hooke007
50cc295e9e fix editor 2021-09-01 01:06:38 +08:00
hooke007
bec97545d1 Update CorePlayer.cs 2021-08-30 21:01:00 +08:00
hooke007
db5f0334c4 update&fix manuals 2021-08-30 02:41:06 +08:00
Frank Skare
42c623c8ca 5.4.9.7 Beta 2021-08-28 12:47:24 +02:00
Frank Skare
d3c1e2ab56 5.4.9.6 Beta 2021-08-26 13:11:07 +02:00
Frank Skare
57e60287ff msgbox fix 2021-08-26 12:51:20 +02:00
Frank Skare
007fbf8be5 5.4.9.5 Beta 2021-08-25 14:12:45 +02:00
Frank Skare
d3baa47f93 Message boxes are themed 2021-08-25 11:31:20 +02:00
Frank Skare
225905ebff menu fix 2021-08-24 16:00:16 +02:00
Frank Skare
c08ddd5057 menu performance 2021-08-24 15:20:54 +02:00
Frank Skare
970dfc069d 5.4.9.4 Beta 2021-08-24 08:22:59 +02:00
Frank Skare
9b5f9a64fd readme fix 2021-08-23 01:19:02 +02:00
Frank Skare
6720e2429e Button style in input editor. 2021-08-23 01:14:25 +02:00
Frank Skare
5070b166d9 new images 2021-08-23 00:15:17 +02:00
Frank Skare
8b6d12d57b new image 2021-08-23 00:10:45 +02:00
Frank Skare
8888747137 new images 2021-08-23 00:02:58 +02:00
Frank Skare
d83b5b14a8 5.4.9.3 Beta 2021-08-22 23:50:42 +02:00
Frank Skare
17ecd9cb82 Major UI rework! 2021-08-22 18:50:11 +02:00
Frank Skare
0829b4bd9e lua string escape fix 2021-08-16 22:28:02 +02:00
Frank Skare
fbc9652f20 update changelog 2021-08-16 11:18:42 +02:00
Frank Skare
c7d9d658f2 libmpv shinchiro 2021-08-15 2021-08-16 11:18:00 +02:00
Frank Skare
1c525618e2 #291 Leaving fullscreen using keepaspect-window=no restores the correct size 2021-08-16 11:12:53 +02:00
Frank Skare
9ead5dbd19 #309 support hwdec=auto-safe 2021-08-16 09:07:33 +02:00
Frank Skare
625e887dc1 string escape issue fix 2021-08-15 20:21:43 +02:00
Frank Skare
60cbf894e5 5.4.9.2 Beta 2021-08-08 15:26:54 +02:00
Frank Skare
95a3403898 5.4.9.2 Beta 2021-08-08 14:31:43 +02:00
Frank Skare
fbf50e7466 themed scroll bars, rounded courners, libmpv update 2021-08-08 11:55:43 +02:00
Frank Skare
e9b6988a69 window fix 2021-07-30 08:57:52 +02:00
Frank Skare
8d49c96c57 Drawing flicker in the command palette (playlist) was fixed 2021-07-29 14:25:37 +02:00
Frank Skare
ea56dcdda8 conf editor support for keepaspect-window 2021-07-28 12:28:43 +02:00
stax76
5ef8340ba3 Merge pull request #290 from hooke007/dev
fix a potential bug when switching back to `auto`
2021-07-28 11:37:07 +02:00
hooke007
51e1e85867 fix a potential bug when switching back to auto 2021-07-27 19:08:47 +08:00
Frank Skare
b24f740129 Merge branch 'master' of https://github.com/stax76/mpv.net 2021-07-27 08:50:21 +02:00
Frank Skare
653d66c343 #289 fix line break issue in conf editor 2021-07-27 08:50:19 +02:00
stax76
3dd4ae1bfc Create FUNDING.yml 2021-07-24 10:16:31 +02:00
Frank Skare
27c8ae79e0 update readme 2021-07-24 08:32:43 +02:00
Frank Skare
53e3231452 update readme 2021-07-24 08:31:30 +02:00
Frank Skare
bcf98d847a update readme 2021-07-24 08:28:51 +02:00
Frank Skare
b6ee67d506 Delete License.txt 2021-07-22 19:05:29 +02:00
Frank Skare
3f13747413 Change license from MIT to GPL v2 2021-07-22 17:50:40 +02:00
Frank Skare
54046d5c9d Merge branch 'master' of https://github.com/stax76/mpv.net 2021-07-22 08:43:12 +02:00
Frank Skare
8966f25e06 watch-later-options support added to conf editor 2021-07-22 08:43:09 +02:00
stax76
27fca2cb82 Merge pull request #286 from hooke007/dev
add watch-later-options
2021-07-22 08:41:44 +02:00
hooke007
0d1a17a41a add watch-later-options 2021-07-21 23:06:48 +08:00
Frank Skare
517e4a1142 update changelog 2021-07-19 16:15:16 +02:00
Frank Skare
a380f87b5f Profile selection in the context menu 2021-07-19 15:22:36 +02:00
Frank Skare
35d9d29d40 Support for --keep-open=no 2021-07-19 10:29:13 +02:00
Frank Skare
e1c9d81496 misc 2021-07-19 02:33:32 +02:00
Frank Skare
fbeeb3f015 manual update 2021-07-18 14:54:07 +02:00
Frank Skare
48735a602a #281 handling settings.xml crash 2021-07-17 16:45:34 +02:00
Frank Skare
886f3349ae use pascal casing everywhere 2021-07-15 14:40:59 +02:00
Frank Skare
43c150a18b set pause no before loading file 2021-07-12 00:58:16 +02:00
Frank Skare
33bbc4a2c4 Update delete-current-file.lua 2021-07-11 22:37:37 +02:00
Frank Skare
6c4a014e57 Update delete-current-file.lua 2021-07-02 16:27:25 +02:00
Frank Skare
ce0dd9ceec globalization bug fix 2021-07-01 16:30:55 +02:00
Frank Skare
3520ce6a3f script update 2021-07-01 14:16:05 +02:00
Frank Skare
376f8226ab playlist shows current file 2021-06-28 23:09:09 +02:00
Frank Skare
6b6ae6bfef Changelog update 2021-06-28 10:42:25 +02:00
stax76
b13dbf0b59 Merge pull request #278 from hooke007/dev
doc-manual:chs
2021-06-28 10:37:54 +02:00
stax76
0f7ac5c0ba Merge pull request #277 from soredake/master
Swap screenshot and stop bindings
2021-06-28 10:28:05 +02:00
Frank Skare
25b94bc2c1 new script delete-current-file.lua 2021-06-28 10:27:24 +02:00
hooke007
445730a833 follow upstream's commit 2021-06-27 20:44:01 +08:00
Frank Skare
fd1590142e toml parser replaced with own conf parser 2021-06-27 13:11:34 +02:00
hooke007
c41adc54c5 tiny fix on orig manual & fully translation 2021-06-27 16:21:52 +08:00
hooke007
a3f6b105de doc-manual:chs 2021-06-27 01:26:39 +08:00
soredake
6e402d4931 Swap screenshot and stop bindings 2021-06-26 13:10:37 +03:00
Frank Skare
c40a0d8835 Merge branch 'master' of https://github.com/stax76/mpv.net 2021-06-24 17:22:33 +02:00
Frank Skare
28416dc3d2 Merge branch 'pr/272-improvements-to-input-conf' 2021-06-24 17:20:03 +02:00
Frank Skare
1bde5b6836 misc 2021-06-24 17:19:20 +02:00
stax76
d1619bca22 Merge pull request #276 from hooke007/patch-2
update editor
2021-06-24 16:37:14 +02:00
hooke007
a123c38dfd update editor 2021-06-24 14:05:05 +08:00
stax76
e02d1850a2 Merge pull request #273 from hooke007/patch-1
fix editor's error
2021-06-23 11:54:10 +02:00
Frank Skare
bd37761fc5 readme update 2021-06-23 11:52:59 +02:00
hooke007
897b901c7c fix editor's error
"If this option is unset, the filter implied by scale will be applied."
2021-06-23 15:32:38 +08:00
Frank Skare
da882c3c11 updating screenshots 2021-06-23 09:01:00 +02:00
Frank Skare
bd1a46d18d 5.4.9.1 2021-06-23 07:28:29 +02:00
Frank Skare
1c23c10c81 #268 Fix exception using named pipes 2021-06-23 06:02:02 +02:00
Frank Skare
55f16d2c53 fancy new command palette 2021-06-22 20:54:14 +02:00
Frank Skare
bac8b2b96c misc 2021-06-22 19:10:27 +02:00
soredake
08328c91c4 Improvements to input.conf 2021-06-22 15:11:10 +03:00
Frank Skare
6634ef094c misc 2021-06-20 16:01:04 +02:00
Frank Skare
3b6e6167b0 misc 2021-06-20 11:34:57 +02:00
Frank Skare
f55dfa7a73 misc 2021-06-20 11:29:58 +02:00
Frank Skare
93f0c970da misc 2021-06-20 11:11:51 +02:00
Frank Skare
aa94da9767 #263 enhancing mpv.net option process-instance 2021-06-18 19:43:30 +02:00
Frank Skare
8340c18257 docs 2021-06-17 23:52:25 +02:00
Frank Skare
075e238c46 docs 2021-06-17 23:51:37 +02:00
Frank Skare
6e6b5ae98c docs 2021-06-17 23:49:00 +02:00
Frank Skare
2078ff867b docs 2021-06-17 23:45:58 +02:00
Frank Skare
446d88e16a trying to fix window issues 2021-06-17 17:46:17 +02:00
Frank Skare
ebacaa0341 #140 Fix window size not being saved 2021-06-17 16:32:35 +02:00
Frank Skare
8420abd915 external audio and subtitle tracks 2021-05-31 10:17:55 +02:00
Frank Skare
650c41eb8a Context menu font render quality fix 2021-05-30 19:42:41 +02:00
Frank Skare
db3018bbf5 Show error message box on main window thread. 2021-05-30 15:08:44 +02:00
Frank Skare
539f94d1c9 New media info command 2021-05-30 14:39:15 +02:00
Frank Skare
f56502d8f3 do not load extensions from startup directory 2021-05-30 12:25:57 +02:00
136 changed files with 14063 additions and 6693 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
github: stax76
ko_fi: stax76

View File

@@ -8,3 +8,33 @@ assignees: stax76
--- ---
This template is meant for usage questions of mpv.net. This template is meant for usage questions of mpv.net.
Some type of questions like questions about a problem require filling out an issue template:
**Describe the problem**
A clear and concise description of what the problem is.
**To Reproduce**
To reproduce, try the last beta version using the CLI option `--config=no`.
In case of an audio or video problem, try to reproduce the problem using mpv instead of mpv.net.
If it can be reproduced with mpv, use the [mpv issue tracker](https://github.com/mpv-player/mpv/issues).
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.
1. mpv.net version
2. Windows version
3. GPU name
4. Media info

View File

@@ -11,6 +11,11 @@ assignees: stax76
A clear and concise description of what the bug is. A clear and concise description of what the bug is.
**To Reproduce** **To Reproduce**
To reproduce, try the last beta version using the CLI option `--config=no`.
In case of an audio or video issue, try to reproduce the issue using mpv instead of mpv.net.
If it can be reproduced with mpv, use the [mpv issue tracker](https://github.com/mpv-player/mpv/issues).
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
@@ -25,3 +30,7 @@ If applicable, add screenshots to help explain your problem.
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.
1. mpv.net version
2. Windows version
3. GPU name
4. Media info

340
License.txt Normal file
View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -6,8 +6,15 @@
🎞 mpv.net 🎞 mpv.net
========== ==========
mpv.net is a modern media player for Windows based on the popular [mpv](https://mpv.io) player. mpv.net is a modern desktop media player for Windows based on the popular [mpv](https://mpv.io) player.
mpv.net is designed to be mpv compatible, almost all mpv features are available
because they are all contained in libmpv, this means the official
[mpv manual](https://mpv.io/manual/master/) applies to mpv.net.
mpv focuses on the usage of the command line and the terminal,
mpv.net retains the ability to be used from the command line and
the terminal and adds a modern Windows GUI on top of it.
#### Graphical User Interface #### Graphical User Interface
@@ -16,12 +23,14 @@ Modern GUI with customizable color themes.
#### Command Line Interface #### Command Line Interface
mpv.net supports mpvs property based command line switches. mpv.net supports mpvs command line interface.
#### High quality video output #### High quality video output
Video output that is capable of many features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more. 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
@@ -41,54 +50,60 @@ mpv.net is under active development.
#### Based on libmpv #### Based on libmpv
mpv.net is based on libmpv which offers a straightforward C API that was designed from the ground up to make mpv usable as a library and facilitate easy integration into other applications. mpv is like VLC not based on DirectShow or Media Foundation. mpv.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-that-mpv-and-mpvnet-have-in-common)
- [Support](#support) - [Support](#support)
- [Download](#download) - [Download](#download)
- [Manual](#manual) - [Manual](#manual)
- [Screenshots](#screenshots) - [Screenshots](#screenshots)
Features Features that mpv and mpv.net have in common
-------- --------------------------------------------
- High degree of mpv compatibility, almost all mpv features are available - Lua and JavaScript Scripting
- Customizable context menu defined in the same file as the key bindings - Hundreds available user scripts make mpv the most feature rich desktop video player
- Config dialog - Simple config files that are easy to read and edit
- Shorcut key editor
- Global hotkeys
- 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 - JSON IPC to control the player with a external programs
- On Screen Controler (OSC, play control buttons) with modern flat design - On Screen Controler (OSC, play control buttons) with modern flat design
- Command Line Interface - Command Line Interface
- Started from a terminal status and debug output is printed on the terminal - Started from a terminal status, error and debug output is printed on the terminal
- DXVA2 video decoding acceleration - DXVA2 video decoding acceleration
- 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 - 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 - Browser extensions to start mpv.net from the browser
- Fast seek performance - Fast seek performance
- Fast startup performance - Fast startup performance
- Usable as video player, audio player and image viewer with a wide range of supported formats - 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 - Built-in decoders, no external codecs have to be installed
- Setup as x64 installer, portable and Chocolatey - Build-in media streaming (requires yt-dlp being installed)
- Build-in media streaming (requires youtube-dl being installed)
- File associations can be created by the setup and from the player
- External audio and subtitle files can be loaded manually or automatically - External audio and subtitle files can be loaded manually or automatically
- Screenshot feature - Screenshot feature
- Watch later feature to save the video position
Features exclusiv to mpv.net
----------------------------
- Very high degree of mpv compatibility, almost all mpv features are available
- Modern graphical user interface with customizable color themes
- Customizable context menu defined in the same file as the key bindings
- Searchable config editor
- Searchable input (shorcut keys) editor
- C# and PowerShell Scripting
- Global keyboard shortcuts
- Command palette to quickly and easily find commands and keys
- Extension API for .NET languages (C#, VB.NET and F#)
- Portable, MS Store or WinGet download and installation
- File history feature to log time and filename - File history feature to log time and filename
- Watch later feature to save the position
- Files can be enqueued from File Explorer - Files can be enqueued from File Explorer
- Update check and update routine
## [Support](docs/Manual.md#support) ## [Support](docs/Manual.md#support)
@@ -111,7 +126,7 @@ Screenshots
#### Main Window #### Main Window
![Main Window](docs/img/Main.png) ![Main Window](docs/img/Main.webp)
#### Context Menu #### Context Menu
@@ -139,11 +154,24 @@ OSD console and status printed on the terminal.
Searchable key and mouse binding editor. Searchable key and mouse binding editor.
![Input Editor](docs/img/InputEditor.png) ![Input Editor](docs/img/InputEditor.webp)
#### Command Palette #### Command Palette
Command Palette to find commands and shortcut keys easily. Command Palette to easily find commands and shortcut keys.
![Command Palette](docs/img/CommandPalette.png) ![Command Palette](docs/img/CommandPalette.webp)
#### Playlist
The command palette based playlist showing my favorite artist of the stax record label.
![Playlist](docs/img/Playlist.png)
List of my apps
---------------
https://stax76.github.io/frankskare

View File

@@ -1,4 +1,326 @@
# v6.0.4.0 Stable (2023-08-17)
- libmpv-2.dll support
- MediaInfo v23.07
- libmpv shinchiro 2023-08-16
# v6.0.3.2 Beta (2022-10-14)
- Support multiple folders input (regression fix).
- Relative file input paths are converted to absolute paths.
- New history-filter option added to define paths to be excluded from the history log feature.
- New command to move the Window to the screen edge (Alt+Arrow) or center (Alt+BS).
- Smaller OSD media info font size and more duplicated and obvious info removed from titles.
- Improved mouse cursor auto hide behavior.
- Fix severe bug causing termination before scripts having a chance reacting to shutdown event.
- mediainfo v22.09.
- libmpv shinchiro 2022-10-14, fixes a severe bug causing hangs:
https://github.com/mpv-player/mpv/pull/10569
input.conf changes:
New:
```
Alt+Left script-message-to mpvnet move-window left #menu: View > Move > Left
Alt+Right script-message-to mpvnet move-window right #menu: View > Move > Right
Alt+Up script-message-to mpvnet move-window top #menu: View > Move > Top
Alt+Down script-message-to mpvnet move-window bottom #menu: View > Move > Bottom
Alt+BS script-message-to mpvnet move-window center #menu: View > Move > Center
```
# 6.0.3.1 (2022-07-30)
- Creating a playlist from a folder uses absolute normalized paths, non-media files are ignored.
- The show-info command shows directly an advanced view, which was enhanced with a General section and the filename.
- Media info titles are shortened if they contain duplicated or obvious information.
- Support of shortcuts (.lnk files) with media file target.
- Support --audio-file and --sub-file aliases.
- playlist-random (F9 key) command jumps to a random playlist entry.
- Fix OSC hide behavior on mouse move.
- New binding (e key) to show the current file in File Explorer.
- Shift key enables process-instance=multi.
- Command line syntax (preceding double hyphen) is supported in mpv.conf for options implemented by mpv.net.
- MediaInfo v22.06
- libmpv shinchiro 2022-07-30
input.conf changes:
New:
```
e run powershell -command "explorer.exe '/select,' ( \"${path}\" -replace '/', '\\' )" #menu: Tools > Show current file in File Explorer
F9 script-message-to mpvnet playlist-random #menu: Navigate > Random File
```
# 6.0.3.0 (2022-07-03)
- Fix the rare occasion of duplicated playlist entries produced by the auto-load-folder feature.
# 6.0.2.0 (2022-07-02)
- Fix main window shown collapsed when the player was started with full screen.
# 6.0.1.0 (2022-06-30)
- New tutorial: [Extending mpv and mpv.net via Lua scripting](https://github.com/mpvnet-player/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting)
- New options `autofit-image` and `autofit-audio`, like autofit, but used for image and audio files.
- New [auto-mode](https://github.com/stax76/mpv-scripts) script to use mpv and mpv.net as image viewer and audio player.
- New [smart-volume](https://github.com/stax76/mpv-scripts) script. Records the volume per file in order to restore it
in future sessions. What is recorded and restored is the volume offset relative to the session average volume.
- New support of the mpv option `snap-window`.
- New feature to show chapters in the command palette, see binding and menu definition below.
- New option minimum-aspect-ratio-audio, same as minimum-aspect-ratio but used for audio files.
- Fix long commands causing key bindings not visible in the command palette.
- Fix script compatibility with mordenx and mpv-osc-tethys.
- Fix borderless window not resizable with mouse.
- Fix start-size=session not working.
- Fix chapters that are script created after the media file is loaded.
- Width of command palette slightly increased.
- The default key bindings for 0 and 9 change the volume, like mpv.
- When a menu item is defined multiple times with different key bindings,
only one menu item is created, it shows all bindings.
- libmpv zhongfly 2022-06-19
input.conf changes:
New:
```
Ctrl+c script-message-to mpvnet show-chapters #menu: View > Show Chapters
```
# 6.0.0.0 Beta (2022-06-05)
- The options `cache` and `demuxer-max-bytes`have been added
to the conf editor.
- Command messages are dispatched with `script-message-to mpvnet`.
- New feature to change profile using the command palette.
- New feature to show media info on screen, the command palette shows
an osd option and the show-info command shows more detailed info
after a second key press. Media info display in the track menu
was also improved. Thanks to dyphire helping with code.
- New `media-info` option allowing to use mpv `track-list`
instead of the media info library.
- New show-santa-logo (green and grumpy) option.
- New quick bookmark feature, see manual.
- Progress command shows time and date.
- When input.conf is created on the very first start and a
script-opts folder does not exist, a script-opts folder
is created with osc and console defaults:
`console-scale=1.5`
`osc-idlescreen=no` (hides the original mpv logo)
`osc-hidetimeout=2000`
`osc-scalewindowed=1.5`
- Support mpv idle property, see manual for remarks.
- Fix external audio and subtitle files not shown in all use cases.
- Fix various mpv options not working in case of existing same line comments.
- Fix crash choosing Matroska edition in the menu.
- Fix auto-play and auto-load-folder not working with user scripts.
- Fix slow startup using `osd-scale-by-window=no`.
- Fix URL shown instead of media title on file change OSD,
in recent menu and in recent command palette.
- Fix chapter time display in menu.
- Fix incorrect startup window size using gpu-api=vulkan.
- Fix logo not hiding sometimes using gpu-api=vulkan.
- libmpv shinchiro 2022-06-05
input.conf changes:
Old:
```
F9 show-text ${track-list} 5000 #menu: View > Show Tracks
```
New:
```
F9 script-message-to mpvnet show-media-info osd #menu: View > Show Tracks
Ctrl+p script-message-to mpvnet select-profile #menu: View > Show Profile Selection
Alt+q script-message-to mpvnet quick-bookmark
```
All occurrences of `script-message mpv.net` were changed to `script-message-to mpvnet`.
# 5.9.0.0 Beta (2022-05-08)
- Fix startup without media file not working with gpu-api=vulkan.
- Fix keyboard layout change not working.
- Fix multi monitor setup with different DPI values not working.
- Fix config editor handling `keep-open` and `keep-open-pause` incorrectly.
- New mpv.net specific option `keep-open-exit` added. If set to yes and
keep-open is set to no, mpv.net exits after the last file ends.
- New `playlist-add` command added to change the playlist position,
jumps to the other end when the beginning or end is reached.
Ctrl+F11 goes 10 positions backward.
Ctrl+F12 goes 10 positions forward.
- libmpv zhongfly 2022-05-07
5.8.0.0 Beta (2022-04-02)
- Fix crash on Windows 7 systems without PowerShell.
- Fix showing incorrect timestamps in About dialog of Store version.
- Fix Store page showing non-existent ARM and x86 support.
- Fix opening zip files.
- The list of available input commands is like before shown
by the text editor, so it's like everything else searchable.
- Media Info isn't shown directly, instead the command palette
shows several choices. The command palette can be bypassed
using the arguments: msgbox, editor, full, raw.
https://github.com/mpvnet-player/mpv.net/blob/master/docs/Manual.md#show-media-info-flags
- mpv.net specific commands, the command palette, auto-play property
and various other things are documented in the manual.
- The action used for the right mouse button can be configured.
https://github.com/mpvnet-player/mpv.net/blob/master/docs/Manual.md#show-menu
- Workaround not reproducible logo drawing crash.
- Info command shows the length.
- New mpv.net specific option `show-logo` that allows to disable
the drawing of the blue mpv.net logo on top of the native OSC logo.
- MediaInfo 22.03
5.7.0.0 Stable (2022-03-09)
- Improved title and chapter menu for Blu-Rays.
- Fix of conf folder virtualization issue of MS Store version.
5.6.2.0 Beta (2022-03-05)
- Fix script-opts files being ignored, removed options are:
script-opts = osc-scalewindowed=1.5,osc-hidetimeout=2000,console-scale=1.5
- Update MediaInfo to version 21.9.0.0 and
write version and date in About dialog.
- Provide setup options in command palette to ensure backward
compatibility with previous input.conf definitions.
5.6.1.0 Beta (2022-03-05)
- Various conf editor improvements. (hooke007)
- Custom conf folder location feature removed.
- Inno Setup replaced with Microsoft Store setup.
- Fix script-opts files being ignored.
- Showing the recent list in the command palette,
the top item gets auto selected.
https://github.com/mpvnet-player/mpv.net/issues/328#issuecomment-1057296054
- If the play list is empty, the most recent file
gets loaded when pressing space.
https://github.com/mpvnet-player/mpv.net/issues/328#issuecomment-1057296054
- Ctrl+v (previously u) opens files (or URLs) from the clipboard,
previously it had to be a file path (format string) and now
it can also be the clipboard format of type file.
- The usability of the menu structure was improved.
- Audio and subtitle tracks and various other features
are now available in the command palette.
- Single character input in the command palette searches exclusively
key bindings, much like the search field of the input editor.
- Various default key bindings improved.
- New protocol registrations, so far supported are: ytdl, rtsp, srt, srtp
- libmpv zhongfly 2022-02-27
5.5.0.4 Beta (2021-11-05)
- Window size flicker issue fix when changing files.
- Support input-builtin-bindings to make mp.add_key_binding behave same as in mpv.
- window-scale property support.
- libmpv shinchiro 2021-10-31
5.5.0.3 Beta (2021-09-23)
- New mpv.net option auto-play which sets pause=no on file load and
selecting from the playlist. Disabled by default.
- New option start-size=session to freeze the window size per session.
- Changed keepaspect-window behavior.
5.5.0.2 Beta (2021-09-15)
- Fix of keepaspect-window=no.
5.4.9.8 Beta (2021-09-05)
- All PowerShell dependencies except the scipt host were
removed in order to improve Windows 7 compatibility.
- Fix message box not working when ontop is enabled.
- Use Vista folder browser.
- Improved context menu performance.
- libmpv shinchiro 2021-09-05
5.4.9.7 Beta (2021-08-28)
- Fix exception closing command palette on Windows 7.
5.4.9.6 Beta (2021-08-26)
- Message box fix.
5.4.9.5 Beta (2021-08-25)
- Message boxes are themed.
5.4.9.4 Beta (2021-08-24)
- Fix of command palette crash on Windows 7.
5.4.9.3 Beta (2021-08-22)
- Leaving fullscreen using keepaspect-window=no restores the correct size.
- Major UI rework!
- libmpv shinchiro 2021-08-15
5.4.9.2 Beta (2021-08-08)
- Manual translated to simplified Chinese. (hooke007)
- watch-later-options support added to conf editor. (hooke007)
- Showing the playlist selects the currently played file/stream in the playlist.
- Properties are shown in the command palette instead of the text editor
making it very easy to find a property and show/print its value.
- Support for --keep-open=no.
- Profile selection in the context menu.
- Use defaults in case settings.xml fails loading (not reproducible).
- conf editor support for keepaspect-window.
- Drawing flicker in the command palette (playlist) was fixed.
- Saving window size and position was fixed.
- Some scroll bars where replaced with Windows 10 styled scroll bars,
complex code used from HandyControl project.
- Some UI elements use rounded corners.
- The recent list can also be shown in the command palette:
Alt+r script-message mpv.net show-recent #menu: View > Show Recent
- The recent context menu removes the folder info in case of very long paths.
- libmpv shinchiro 2021-08-01
5.4.9.1 Beta (2021-06-23)
=========================
- Fix exception using named pipes.
- The mpv window property keepaspect-window was implemented.
- Everything search removed to keep the core player lightweight,
it might come back as user script or extension.
- The command palette is integrated into the main window.
- Playlist is shown with the command palette and not using the OSD.
- New media info command: `Ctrl+m script-message mpv.net show-media-info #menu: View > Show Media Info`
- Context menu font render quality fix.
- Context menu and `cycle-audio` command supports external audio and subtitle tracks.
- Fix window size not being saved.
- libmpv shinchiro 2021-06-20
5.4.9.0 (2021-05-29) 5.4.9.0 (2021-05-29)
==================== ====================
@@ -258,27 +580,27 @@ stable release, no changes since the last beta
https://mpv.io/manual/master/#legacy-option-syntax https://mpv.io/manual/master/#legacy-option-syntax
- new: PowerShell script host was completely rewritten, events can be assigned - new: PowerShell script host was completely rewritten, events can be assigned
by using `Register-ObjectEvent`, the scripting wiki page was updated by using `Register-ObjectEvent`, the scripting wiki page was updated
https://github.com/stax76/mpv.net/wiki/Scripting#powershell https://github.com/mpvnet-player/mpv.net/wiki/Scripting#powershell
- new: Context Menu > View > Show Profiles - new: Context Menu > View > Show Profiles
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L147 https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L147
- new: Context Menu > View > Show Properties - new: Context Menu > View > Show Properties
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L148 https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L148
- new: Context Menu > View > Show Commands - new: Context Menu > View > Show Commands
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149 https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149
- new: config editor tab is now remembered - new: config editor tab is now remembered
- new: osd-duration setting added to config editor and default mpv.conf - new: osd-duration setting added to config editor and default mpv.conf
- new: external console replaced with internal console, in case mpv.conf is missing it's - new: external console replaced with internal console, in case mpv.conf is missing it's
generated with correct Hight DPI font size scale settings. generated with correct Hight DPI font size scale settings.
`script-opts=console-scale=<dpiscale>` `script-opts=console-scale=<dpiscale>`
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L150 https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L150
https://mpv.io/manual/master/#console https://mpv.io/manual/master/#console
- new: blue color in dark theme is now less intense - new: blue color in dark theme is now less intense
https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#color-theme
- new: menu item 'View > Show Progress' (p key) to show progress bar - new: menu item 'View > Show Progress' (p key) to show progress bar
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L146 https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L146
- new: `script-message mpv.net playlist-first`, unlike mpv does not - new: `script-message mpv.net playlist-first`, unlike mpv does not
restart if the first file is already active restart if the first file is already active
https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L44 https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L44
- new: if mpv.net is started from the terminal and an error happens then the error - new: if mpv.net is started from the terminal and an error happens then the error
is printed to the terminal instead of shown with a message box is printed to the terminal instead of shown with a message box
- fix: update routine did only work when mpv.net was located in 'Program Files' - fix: update routine did only work when mpv.net was located in 'Program Files'
@@ -295,7 +617,7 @@ stable release, no changes since the last beta
- new: update check, it must be enabled first in the conf editor under General - new: update check, it must be enabled first in the conf editor under General
- new: update feature, requires PowerShell 5 and curl, - new: update feature, requires PowerShell 5 and curl,
an up to date Windows 10 system has both included. an up to date Windows 10 system has both included.
Main menu (input.conf) must be reset or updated manually ([defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt)) Main menu (input.conf) must be reset or updated manually ([defaults](https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt))
- update: libmpv shinchiro 2019-11-10 - update: libmpv shinchiro 2019-11-10
@@ -304,17 +626,17 @@ stable release, no changes since the last beta
- fix: the file association routine uses no longer 'Play with mpv.net' for the - fix: the file association routine uses no longer 'Play with mpv.net' for the
default open verb caption because it doesn't support multi selection, default open verb caption because it doesn't support multi selection,
it shows now only Open, the manual explains how to get multi selection it shows now only Open, the manual explains how to get multi selection
in File Explorer, read about it [here](https://github.com/stax76/mpv.net/blob/master/Manual.md#open-with) in File Explorer, read about it [here](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#open-with)
- fix: x86 builds had an older version included because - fix: x86 builds had an older version included because
of a misconfiguration in the solution file of a misconfiguration in the solution file
### 5.4.3.0 ### 5.4.3.0
- new: the color themes can now be customized ([manual](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme)) - new: the color themes can now be customized ([manual](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#color-theme))
- new: three new sections were added to the [manual](https://github.com/stax76/mpv.net/blob/master/Manual.md): - new: three new sections were added to the [manual](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md):
1. [Color Theme](https://github.com/stax76/mpv.net/blob/master/Manual.md#color-theme) 1. [Color Theme](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#color-theme)
2. [Hidden and secret features](https://github.com/stax76/mpv.net/blob/master/Manual.md#hidden-and-secret-features) 2. [Hidden and secret features](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#hidden-and-secret-features)
3. [External Tools](https://github.com/stax76/mpv.net/blob/master/Manual.md#external-tools) 3. [External Tools](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#external-tools)
- fix: window restore from maximized and from minimized was broken - fix: window restore from maximized and from minimized was broken
- fix: it's possible to multi select files in File Explorer and press - fix: it's possible to multi select files in File Explorer and press
@@ -334,13 +656,13 @@ stable release, no changes since the last beta
context menu item in explorer with multi selection support use my context menu item in explorer with multi selection support use my
[Open with++](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist) shell extension, as far as I know multi selection [Open with++](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist) shell extension, as far as I know multi selection
can not be done using the Registry but only via shell extension can not be done using the Registry but only via shell extension
- window-size mpv property support added ([default bindings](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L137)) - window-size mpv property support added ([default bindings](https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L137))
- the config editor keeps profiles and comments in mpv.conf intact! - the config editor keeps profiles and comments in mpv.conf intact!
- the options in the config editor are better organized - the options in the config editor are better organized
### 5.4.2 ### 5.4.2
- new: the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting#powershell) was improved - new: the [scripting wiki page](https://github.com/mpvnet-player/mpv.net/wiki/Scripting#powershell) was improved
- new: Toggle Shuffle has been added to the menu defaults - new: Toggle Shuffle has been added to the menu defaults
- new: for URLs the media title is shown in the title bar and in the info command - new: for URLs the media title is shown in the title bar and in the info command
instead of displaying the URL, mpv.conf defaults were changed to use instead of displaying the URL, mpv.conf defaults were changed to use
@@ -408,7 +730,7 @@ stable release, no changes since the last beta
### 5.1 ### 5.1
- many [wiki pages](https://github.com/stax76/mpv.net/wiki) were improved - many [wiki pages](https://github.com/mpvnet-player/mpv.net/wiki) were improved
- the logo/icon had a very small cosmetic change - the logo/icon had a very small cosmetic change
- the help in the context menu was improved, - the help in the context menu was improved,
for quick access consider the command palette (F1 key) for quick access consider the command palette (F1 key)
@@ -442,7 +764,7 @@ stable release, no changes since the last beta
### 5.0 ### 5.0
- [changed icon design](https://github.com/stax76/mpv.net/blob/master/img/mpvnet.png) - [changed icon design](https://github.com/mpvnet-player/mpv.net/blob/master/img/mpvnet.png)
- libmpv was updated to shinchiro 2019-07-14 - libmpv was updated to shinchiro 2019-07-14
- new or improved config editor settings: screenshot-directory, - new or improved config editor settings: screenshot-directory,
screenshot-format, screenshot-tag-colorspace, screenshot-high-bit-depth, screenshot-format, screenshot-tag-colorspace, screenshot-high-bit-depth,
@@ -461,7 +783,7 @@ stable release, no changes since the last beta
the script is located at startup/scripts the script is located at startup/scripts
- terminal support added using mpvnet.com ! - terminal support added using mpvnet.com !
- script engine performance and error handling was improved - script engine performance and error handling was improved
- the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting) was improved - the [scripting wiki page](https://github.com/mpvnet-player/mpv.net/wiki/Scripting) was improved
- the C# scripting host extension was converted from VB to C# because it's not - the C# scripting host extension was converted from VB to C# because it's not
only used for hosting but I also use it now to code and debug script code only used for hosting but I also use it now to code and debug script code
- there was a copy paste bug in the file association feature resulting in keys - there was a copy paste bug in the file association feature resulting in keys
@@ -531,7 +853,7 @@ stable release, no changes since the last beta
pressed, the files are opened as selected, the order is random though pressed, the files are opened as selected, the order is random though
because Explorer starts multiple mpv.net processes concurrently because Explorer starts multiple mpv.net processes concurrently
- libmpv was updated to shinchiro 2019-06-30 - libmpv was updated to shinchiro 2019-06-30
- the [mpv.conf defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpv.conf.txt) were changed to show a larger OSC - the [mpv.conf defaults](https://github.com/mpvnet-player/mpv.net/blob/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
@@ -549,7 +871,7 @@ stable release, no changes since the last beta
- invalid command-line arguments were ignored, now an error message is shown - invalid command-line arguments were ignored, now an error message is shown
- a description on how to start mpv.net from Google Chrome was added to the - a description on how to start mpv.net from Google Chrome was added to the
manual, it's useful to play videos from sites like YouTube, find the manual, it's useful to play videos from sites like YouTube, find the
description [here](https://github.com/stax76/mpv.net/blob/master/Manual.md#chrome-extension) description [here](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md#chrome-extension)
- new config setting remember-height added to remember the window height, - new config setting remember-height added to remember the window height,
otherwise the video's native resolution is used otherwise the video's native resolution is used
- support for protocols other then http added - support for protocols other then http added
@@ -564,13 +886,13 @@ stable release, no changes since the last beta
- the playlist is never cleared whenever the control key is down but - the playlist is never cleared whenever the control key is down but
files and URLs are appended instead files and URLs are appended instead
- powershell script hosting bugs were fixed and a new powershell example script - powershell script hosting bugs were fixed and a new powershell example script
was added to the [scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting#powershell) was added to the [scripting wiki page](https://github.com/mpvnet-player/mpv.net/wiki/Scripting#powershell)
- the menu entry for the command palette was renamed to 'Show All Commands' and - the menu entry for the command palette was renamed to 'Show All Commands' and
the default key binding was changed to F1 which is also the default in VS Code the default key binding was changed to F1 which is also the default in VS Code
- the default key binding of the Everything media search was changed to F3 - the default key binding of the Everything media search was changed to F3
- support for the mpv property 'border' was added to the config editor - support for the mpv property 'border' was added to the config editor
to show/hide the window decoration (titlebar, border). A toggle menu item and to show/hide the window decoration (titlebar, border). A toggle menu item and
key binding (b) was added as well ([Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L135)) key binding (b) was added as well ([Default Binding](https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L135))
### 4.3.1 ### 4.3.1
@@ -585,7 +907,7 @@ stable release, no changes since the last beta
- the help and layout in the config editor was improved - the help and layout in the config editor was improved
- clipboard monitoring for URLs can be disabled in the settings - clipboard monitoring for URLs can be disabled in the settings
- the context menu has a new feature: Open > Add files to playlist, - the context menu has a new feature: Open > Add files to playlist,
it appends files to the playlist [(Default binding)](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L33) it appends files to the playlist [(Default binding)](https://github.com/mpvnet-player/mpv.net/blob/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
@@ -600,7 +922,7 @@ stable release, no changes since the last beta
- on the start screen the mpv.NET icon is shown instead of the mpv icon, - on the start screen the mpv.NET icon is shown instead of the mpv icon,
feedback and contributions regarding the icon are welcome! The paint.net feedback and contributions regarding the icon are welcome! The paint.net
pdn and png source is located [here](https://github.com/stax76/mpv.net/tree/master/img) pdn and png source is located [here](https://github.com/mpvnet-player/mpv.net/tree/master/img)
- everytime only one file is opened the complete folder is loaded in the playlist - everytime only one file is opened the complete folder is loaded in the playlist
- the info command (i key) shows the audio format - the info command (i key) shows the audio format
- new options osd-font-size, sub-font, sub-font-size - new options osd-font-size, sub-font, sub-font-size
@@ -627,7 +949,7 @@ stable release, no changes since the last beta
- there was a bug that caused underscores beeing removed from input like MBTN_LEFT_DBL - there was a bug that caused underscores beeing removed from input like MBTN_LEFT_DBL
- the search clear button in the input editor had a render issue in dark mode - the search clear button in the input editor had a render issue in dark mode
- new search feature added to search and play media files, requires - new search feature added to search and play media files, requires
[Everything](https://www.voidtools.com) to be installed. [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L29) [Everything](https://www.voidtools.com) to be installed. [Default Binding](https://github.com/mpvnet-player/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L29)
### 3.5 ### 3.5
@@ -640,6 +962,6 @@ stable release, no changes since the last beta
### 3.4 ### 3.4
- new feature added to manage file associations from within the app. It can be found in the menu at: Tools > Manage... [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/input.conf.txt#L149) - new feature added to manage file associations from within the app. It can be found in the menu at: Tools > Manage... [Default Binding](https://github.com/mpvnet-player/mpv.net/blob/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

View File

@@ -1,24 +0,0 @@
MIT License
Copyright (C) 2017-2021 mpv.net/mpv/mplayer
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and ssociated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -2,6 +2,8 @@
mpv.net manual mpv.net manual
============== ==============
**ENGLISH** | **[简体中文](Manual_chs.md)**
Table of contents Table of contents
----------------- -----------------
@@ -11,8 +13,10 @@ Table of contents
* [Support](#support) * [Support](#support)
* [Settings](#settings) * [Settings](#settings)
* [Input and context menu](#input-and-context-menu) * [Input and context menu](#input-and-context-menu)
* [Command Palette](#command-palette)
* [Command Line Interface](#command-line-interface) * [Command Line Interface](#command-line-interface)
* [Terminal](#terminal) * [Terminal](#terminal)
* [mpv.net specific commands](#mpvnet-specific-commands)
* [mpv.net specific options](#mpvnet-specific-options) * [mpv.net specific options](#mpvnet-specific-options)
* [External Tools](#external-tools) * [External Tools](#external-tools)
* [Scripting](#scripting) * [Scripting](#scripting)
@@ -38,53 +42,40 @@ mpv focuses on the usage of the command line and the terminal,
mpv.net retains the ability to be used from the command line and mpv.net retains the ability to be used from the command line and
the terminal and adds a modern Windows GUI on top of it. the terminal and adds a modern Windows GUI on top of it.
Like mpv, mpv.net is designed for power users.
Download Download
-------- --------
1. [Stable via Microsoft Store](https://www.microsoft.com/store/productId/9N64SQZTB3LM)
2. [Stable and beta via GitHub download](../../../releases)
3. `winget install mpv.net`
[Changelog](Changelog.md) [Changelog](Changelog.md)
### Stable
[Release page](../../../releases)
### Beta
[OneDrive](https://1drv.ms/u/s!ArwKS_ZUR01g1ldoLA90tX9DzKTj?e=xITXbC)
[DropBox](https://www.dropbox.com/sh/t54p9igdwvllbpl/AADKyWpaFnIhdyosxyP5d3_xa?dl=0)
Installation Installation
------------ ------------
mpv.net requires the .NET Framework 4.8 and Windows 7 or 10 and a modern graphics card. mpv.net requires the .NET Framework 4.8 and Windows 7 or higher and a modern graphics card.
There is a setup exe and a portable zip file download. Internet streaming requires:
For internet streaming youtube-dl must be downloaded and installed manually,
meaning it must be located in the PATH environment variable or in the startup directory.
mpvnet.exe is platform agnostic, users that need x86 have to replace 4 native tools:
- Everything.dll
- mpv-1.dll
- MediaInfo.dll
- mpvnet.com
- Downloading [yt-dlp](https://github.com/yt-dlp/yt-dlp) and adding its folder
to the [user environment variable PATH](https://www.google.com/search?q=user+environment+variable+PATH).
- In case of proxy server usage, [manual configuration](https://github.com/mpvnet-player/mpv.net/issues/401).
#### File Associations #### File Associations
File Associations can be created using the context menu under 'Tools > Setup'. File Associations can be registered using the context menu under 'Settings > Setup'.
After the file associations were registered, go to the Windows settings under After the file associations were registered, it might be necessary to change the
'Settings > Apps > Default apps' or shell execute `ms-settings:defaultapps` and choose default app in the Windows settings (Win+I, ms-settings:defaultapps).
mpv.net as default app for Video and optionally for Audio and Images.
It's possible to change the default application using the 'Open with' feature Another way to register file associations is using Windows File Explorer,
of the context menu in File Explorer. select a media file and select 'Open with > Choose another app' in the context menu.
[Open with++](#open-with) can be used to extend the File Explorer context menu [Open with++](#open-with) can be used to extend the File Explorer context menu
to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) and to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) and
@@ -97,12 +88,21 @@ the files are opened in mpv.net in random order, this works with maximum 15 file
Support Support
------- -------
Before making a support request, please try a newer [beta version](#beta) first. Before making a support request, please try the newest [beta version](../../../releases) first.
Bugs and feature requests can be made on the github [issue tracker](../../../issues), Support can be requested here:
feel free to use for anything mpv.net related, usage questions are welcome.
Or use the [support thread](https://forum.videohelp.com/threads/392514-mpv-net-a-extendable-media-player-for-windows) in the VideoHelp forum. Beginner questions:
https://www.reddit.com/r/mpv
mpv.net bug reports, feature requests and advanced questions:
https://github.com/mpvnet-player/mpv.net/issues
Advanced mpv questions:
https://github.com/mpv-player/mpv/issues
Settings Settings
@@ -111,39 +111,77 @@ Settings
mpv.net searches the config folder at: mpv.net searches the config folder at:
1. startup\portable_config 1. startup\portable_config
2. %APPDATA%\mpv.net 2. %APPDATA%\mpv.net (`C:\Users\%USERNAME%\AppData\Roaming\mpv.net`)
In order to use a custom directory create following file: mpv options are stored in the file mpv.conf,
mpv.net options are stored in the file mpvnet.conf,
startup\settings-directory.txt mpv.net options are documented [here](#mpvnet-specific-options).
Put your custom directory in that file.
The custom directory path can be relative to the startup directory path.
This custom directory is only used if the portable_config and %APPDATA% directory does not exist.
mpv specific settings are stored in the file mpv.conf, if no mpv.conf file exists
mpv.net generates it with the following defaults:
[mpv.conf defaults](../../../tree/master/src/Resources/mpv.conf.txt)
mpv.net specific settings are stored in the file mpvnet.conf,
these options are documented [here](#mpvnet-specific-options).
Input and context menu Input and context menu
---------------------- ----------------------
The input (key/mouse) bindings and the context menu definitions are stored in the 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: input.conf file, if it's missing mpv.net generates it with default values.
[input.conf defaults](../../../tree/master/src/Resources/input.conf.txt) Please be aware that once input.conf exists, mpv.net cannot update it, this means
the menu becomes outdated when mpv.net is updated with new or changed default menu
items. The only way to get an up-to-date menu is either resetting the menu by
deleting input.conf or updating it by manually editing input.conf.
Global hotkeys are supported via global-input.conf file. Global keyboard shortcuts are supported via global-input.conf file.
The config folder can be opened from the context menu: `Settings > Open Config Folder` The config folder can be opened from the context menu: `Settings > Open Config Folder`
A input and config editor can be found in the context menu under 'Settings'.
The input test mode can be started via command line: --input-test
The input key list can be printed with --input-keylist or
shown from the context menu under: View > Advanced > Show Keys
mpv.net input.conf defaults:
https://github.com/mpvnet-player/mpv.net/blob/master/src/Resources/input.conf.txt
mpv input.conf defaults:
https://github.com/mpv-player/mpv/blob/master/etc/input.conf
mpv input commands:
https://mpv.io/manual/master/#list-of-input-commands
mpv input options:
https://mpv.io/manual/master/#input
Command Palette
---------------
The command palette is designed to quickly find,
select and execute commands.
It can also be used to easily find shortcut keys.
The following functionality is presented with the Command Palette:
- Show media info in different ways.
- Show and select audio tracks.
- Show and select subtitle tracks.
- Show and select playlist files.
- Show and select recent files.
- Show available mpv properties.
- Show available decoders.
- Show available demuxers.
- Show available keys.
- Show available protocols.
| Key | Action |
| ------ | --------------------------- |
| F1 | Shows the command palette. |
| Escape | Hides the command palette. |
| Enter | Executes the selected item. |
| Up | Moves the selection up. |
| Down | Moves the selection down. |
Command Line Interface Command Line Interface
---------------------- ----------------------
@@ -170,12 +208,12 @@ Supported are all mpv properties, they are documented here:
https://mpv.io/manual/master/#properties https://mpv.io/manual/master/#properties
mpv.net has a feature to list all properties: mpv.net has a feature to list all available properties:
_Context Menu > View > Show Properties_ _Context Menu > View > Advanced > Show Properties_
Non property switches are generally not supported in mpv.net! mpv has a few non property based switches which are generally not supported in mpv.net.
Terminal Terminal
@@ -184,12 +222,174 @@ Terminal
When mpv.net is started from a terminal it will output status, When mpv.net is started from a terminal it will output status,
error and debug messages to the terminal and accept input keys from the terminal. error and debug messages to the terminal and accept input keys from the terminal.
In the context menu under _Tools > Setup_ a button can be found to add
mpv.net to the path environment variable.
A common task for the terminal is debugging scripts. A common task for the terminal is debugging scripts.
mpv.net specific commands
-------------------------
`script-message-to mpvnet <command> <arguments>`
mpv.net commands are used when mpv commands don't exist or lack a feature.
### cycle-audio
Switches to the next audio track and shows info about that track.
### load-audio
Shows a file browser dialog to open external audio files.
### load-sub
Shows a file browser dialog to open external subtitle files.
### move-window [left|top|right|bottom|center]
Moves the Window to the screen edge (Alt+Arrow) or center (Alt+BS).
### open-conf-folder
Opens the config folder with Windows File Explorer.
### open-files [\<flags\>]
**append**
Appends files to the playlist.
Opens a file browser dialog in order to select files to be opened.
The file browser dialog supports multiselect to load multiple files
at once. Pressing CTRL appends the files to the playlist.
### open-optical-media
Shows a folder browser dialog to open a DVD or BD folder.
ISO images don't have to be mounted, but instead can be
opened directly with the open-files command.
### open-clipboard
Opens a single URL or filepath from the clipboard,
or multiple files in the file clipboard format.
### play-pause
Cycles the pause property. In case the playlist is empty,
the most recent file from the recent files list is loaded.
### playlist-add \<integer\>
Changes the playlist position by adding the supplied integer value.
If the position goes out of range, it jumpes to the opposite end.
### playlist-first
Jumps to the first playlist entry, if the loaded file is
already the first entry, nothing happens.
### playlist-last
Jumps to the last playlist entry, if the loaded file is
already the last entry, nothing happens.
### playlist-random
Jumps to a random playlist entry.
### quick-bookmark
On the first press a bookmark is saved, on the second
press it is restored and removed. When a new file is
loaded the bookmark is removed.
### reg-file-assoc \<audio|video|image\>
Registers the file associations.
### scale-window \<factor\>
Decreases or increases the Window size.
### select-profile
Shows the command palette to select a profile.
### shell-execute \<file|URL\>
Shell executes a single file or URL.
### show-about
Shows the about dialog.
### show-audio-devices
Shows available audio devices in a message box.
### show-audio-tracks
Shows available audio tracks in the command palette
and allows to load the selected audio track.
### show-chapters
Shows chapters in the command palette.
### show-command-palette
Shows the command palette.
### show-commands
Shows available mpv input commands.
### show-conf-editor
Shows the conf editor.
### show-decoders
Shows available decoders.
### show-demuxers
Shows available demuxers.
### show-history
Shows the history file when existing.
### show-input-editor
Shows the input editor.
### show-keys
Shows available keys (as shown with `--input-keylist`) in the command palette.
### show-media-info [\<flags\>]
**msgbox**
Shows media info in a messsage box.
**editor**
Shows media info in the text editor.
**osd**
Displays media info on screen.
**full**
Shows fully detailed media info.
**raw**
Shows media info with raw property names.
### show-menu
Shows the context menu.
### show-playlist
Shows the playlist in the command palette
and allows to play the selected entry.
### show-profiles
Shows available profiles with a message box.
### show-progress
Shows a simple OSD progress message with time and date.
### show-properties
Shows available properties in the command palette and
allows to display the property value of the selected property.
### show-protocols
Shows available protocols in the command palette.
### show-recent
Shows recently played files and URLs in the
command palette and allows to select and play entries.
### show-subtitle-tracks
Shows available subtitles in the command palette
and allows to activate the selected subtitle.
### show-text \<text\> \<duration\> \<font-size\>
Shows a OSD message with given text, duration and font size.
### window-scale \<factor\>
Works similar as the [window-scale](https://mpv.io/manual/master/#command-interface-window-scale) mpv property.
mpv.net specific options mpv.net specific options
------------------------ ------------------------
@@ -197,6 +397,12 @@ mpv.net specific options can be found in the conf editor searching for 'mpv.net'
The options are saved in the mpvnet.conf file. The options are saved in the mpvnet.conf file.
#### --autofit-audio \<integer\>
Initial window height in percent for audio files. Default: 70
#### --autofit-image \<integer\>
Initial window height in percent for image files. Default: 80
#### --queue \<files\> #### --queue \<files\>
Adds files to the playlist, requires [--process-instance=single](#--process-instancevalue). Adds files to the playlist, requires [--process-instance=single](#--process-instancevalue).
@@ -204,9 +410,8 @@ Adds files to the playlist, requires [--process-instance=single](#--process-inst
#### --command=\<input command\> #### --command=\<input command\>
Sends a input command. Useful to control mpv.net from the command line, for instance Sends a input command to a running mpv.net instance via command line, for instance
to create global hotkeys with AutoHotkey, for that [process-instance=single](#--process-instancevalue) to create global keyboard shortcuts with AutoHotkey. Requires [process-instance=single](#--process-instancevalue).
must be used. Spaces have to be escaped with quotes and quotes have to be escaped with double quotes.
### Audio ### Audio
@@ -221,9 +426,6 @@ Save volume and mute on exit and restore it on start. Default: yes
Setting to remember the window size. Setting to remember the window size.
**video**
Window size is set to video resolution.
**width-session** **width-session**
Width is remembered in the current session. Width is remembered in the current session.
@@ -236,9 +438,27 @@ Height is remembered in the current session. Default
**height-always** **height-always**
Height is always remembered. Height is always remembered.
**always** **video**
Size is always remembered. Window size is set to video resolution.
**session**
Window size is remembered in the current session.
**always**
Window size is always remembered.
#### --minimum-aspect-ratio=\<float\>
Minimum aspect ratio of the window. Useful to force
a wider window and therefore a larger OSC.
#### --minimum-aspect-ratio-audio=\<float\>
Same as minimum-aspect-ratio but used for audio files.
#### --remember-window-position=\<yes|no\>
Save the window position on exit. Default: no
#### --start-threshold=\<milliseconds\> #### --start-threshold=\<milliseconds\>
@@ -246,19 +466,6 @@ Threshold in milliseconds to wait for libmpv returning the video
resolution before the window is shown, otherwise default dimensions resolution before the window is shown, otherwise default dimensions
are used as defined by autofit and start-size. Default: 1500 are used as defined by autofit and start-size. Default: 1500
#### --minimum-aspect-ratio=\<float\>
Minimum aspect ratio, if the AR is smaller than the defined value then
the window AR is set to 16/9. This avoids a square window for Music
with cover art. Default: 1.2
#### --remember-window-position=\<yes|no\>
Save the window position on exit. Default: no
### Playback ### Playback
#### --auto-load-folder=\<yes|no\> #### --auto-load-folder=\<yes|no\>
@@ -266,22 +473,24 @@ Save the window position on exit. Default: no
For single files automatically load the entire directory into the playlist. For single files automatically load the entire directory into the playlist.
Can be suppressed via shift key. Default: yes Can be suppressed via shift key. Default: yes
#### --auto-play=\<yes|no\>
If the player is paused and another file is loaded,
playback automatically resumes.
### General ### General
#### --update-check=\<yes|no\>
Daily check for new version. (requires PowerShell 5 and curl.) Default: no
#### --process-instance=\<value\> #### --process-instance=\<value\>
Defines if more then one mpv.net process is allowed. Defines if more then one mpv.net process is allowed.
Tip: Whenever the control key is pressed when files or URLs are opened, Whenever the CTRL key is pressed when files or URLs are opened,
the playlist is not cleared but the files or URLs are appended to the playlist. the playlist is not cleared but the files or URLs are appended to the playlist.
This not only works on process startup but in all mpv.net features that open files and URLs. This not only works on process startup but in all mpv.net features that open files and URLs.
Multi can alternatively be enabled by pressing the SHIFT key.
**multi** **multi**
Create a new process everytime the shell starts mpv.net. Create a new process everytime the shell starts mpv.net.
@@ -291,27 +500,30 @@ Force a single process everytime the shell starts mpv.net. Default
**queue** **queue**
Force a single process and add files to playlist. Force a single process and add files to playlist.
#### --recent-count=\<int\> #### --recent-count=\<int\>
Amount of recent files to be remembered. Default: 15 Amount of recent files to be remembered. Default: 15
#### --media-info=\<yes|no\>
Usage of the media info library instead of mpv to access media information. Default: yes (mpv.net specific option)
#### --history-filter
Semicolon separated list of paths to be excluded from the history log feature.
#### --video-file-extensions=\<string\> #### --video-file-extensions=\<string\>
Video file extensions used to create file associations and used by the auto-load-folder feature. Video file extensions used to create file associations and used by the auto-load-folder feature.
#### --audio-file-extensions=\<string\> #### --audio-file-extensions=\<string\>
Audio file extensions used to create file associations and used by the auto-load-folder feature. Audio file extensions used to create file associations and used by the auto-load-folder feature.
#### --image-file-extensions=\<string\> #### --image-file-extensions=\<string\>
Image file extensions used to create file associations and used by the auto-load-folder feature. Image file extensions used to create file associations and used by the auto-load-folder feature.
#### --debug-mode=\<yes|no\> #### --debug-mode=\<yes|no\>
Enable this only when a developer asks for it. Default: no Enable this only when a developer asks for it. Default: no
@@ -331,20 +543,26 @@ Available on Windows 10 or higher.
**never** **never**
#### --dark-theme=\<string\>
#### ---dark-theme=\<string\>
Color theme used in dark mode. Default: dark Color theme used in dark mode. Default: dark
[Color Themes](#color-theme) [Color Themes](#color-theme)
#### --light-theme=\<string\> #### --light-theme=\<string\>
Color theme used in light mode. Default: light Color theme used in light mode. Default: light
[Color Themes](#color-theme) [Color Themes](#color-theme)
#### --show-logo=\<yes|no\>
Draws the blue mpv.net logo ontop of the native OSC logo. Default: yes
#### --show-santa-logo=\<yes|no\>
Draws the blue mpv.net logo with a santa hat in december,
the option is called greenandgrumpy in mpv. Default: yes
External Tools External Tools
-------------- --------------
@@ -370,71 +588,54 @@ Alternatively the Chrome/Firefox extension [Open With](../../../issues/119) can
[Open with++](https://github.com/stax76/OpenWithPlusPlus) can be used to extend the File Explorer context menu to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) and [Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist). [Open with++](https://github.com/stax76/OpenWithPlusPlus) can be used to extend the File Explorer context menu to get menu items for [Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) and [Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist).
### External Application Button
Videos can be streamed or downloaded easily with the Chrome extension
External Application Button, for download (recommended):
path: `wt`
args: `-- pwsh -NoLogo -Command "yt-dlp --ignore-errors --download-archive 'C:\External Application Button.txt' --output 'C:\YouTube\%(channel)s - %(title)s.%(ext)s' ('[HREF]' -replace '&list=.+','')"`
Scripting Scripting
--------- ---------
#### Lua #### Lua
File Type: `lua` A very large collection of Lua user scripts can be found in the mpv wiki [here](https://github.com/mpv-player/mpv/wiki/User-Scripts).
Location: `<config folder>\scripts`
The Lua script host is built into libmpv.
There is no debugging support, only error and debug messages printed on the terminal.
Lua scripts are loaded before the first media file loads.
[mpv Lua documentation](https://mpv.io/manual/master/#lua-scripting)
[mpv user scripts](https://github.com/mpv-player/mpv/wiki/User-Scripts)
Lua scripting is documented in the mpv.net wiki [here](https://github.com/mpvnet-player/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting).
#### JavaScript #### JavaScript
File Type: `js`
Location: `<config folder>\scripts`
The JavaScript script host is built into libmpv.
There is no debugging support, only error and debug messages printed on the terminal.
JavaScript scripts are loaded before the first media file loads.
[mpv JavaScript documentation](https://mpv.io/manual/master/#javascript) [mpv JavaScript documentation](https://mpv.io/manual/master/#javascript)
[mpv user scripts](https://github.com/mpv-player/mpv/wiki/User-Scripts)
#### PowerShell #### PowerShell
File Type: `ps1`
Location: `<config folder>\scripts-ps` Location: `<config folder>\scripts-ps`
The PowerShell scripting host is like extensions not The PowerShell scripting host is not initialized before media files are loaded.
initialized before media files are loaded.
mpv.net does not define scripting interfaces but instead exposed
its complete internals, there are no compatibility guaranties.
[Example Scripts](../../../tree/master/src/Scripts) [Example Scripts](../../../tree/master/src/Scripts)
#### C# #### C#
File Type: `cs`
Location: `<config folder>\scripts-cs` Location: `<config folder>\scripts-cs`
mpv.net does not define scripting interfaces but instead exposed There are no compatibility guaranties.
its complete internals, there are no compatibility guaranties.
Script code can be written within a C# [extension](../../../tree/master/src/Extensions), Script code can be written within a C# [extension](../../../tree/master/src/Extensions),
that way full code completion and debugger support is available. that way full code completion and debugger support is available.
Once the code was developed and debugged, it can be moved Once the code was developed and debugged, it can be moved
from the extension to a lightweight standalone script. from the extension to a lightweight standalone script.
The script host uses an old C# version, modern features
like string interpolation are not available.
There are synchronous and asynchronous events, prefer asynchronous events
and don't block synchronous events and observed properties, as it would
block the main event loop.
The C# scripting host is like [extensions](../../../tree/master/src/Extensions) The C# scripting host is like [extensions](../../../tree/master/src/Extensions)
not initialized before media files are loaded. not initialized before media files are loaded.
@@ -452,9 +653,9 @@ and the filename must have the same name as the directory:
<config folder>\extensions\ExampleExtension\ExampleExtension.dll <config folder>\extensions\ExampleExtension\ExampleExtension.dll
``` ```
mpv.net does not define extension interfaces but instead exposed There are synchronous and asynchronous events, prefer asynchronous events
its complete internals, there are no compatibility guaranties. and don't block synchronous events and observed properties, as it would
block the main event loop.
### Walkthrough creating an extension ### Walkthrough creating an extension
@@ -549,29 +750,35 @@ features are supported that have an own implementation in mpv.net.
A window free mode is currently not supported, the main window is always A window free mode is currently not supported, the main window is always
visible, even when mpv.net is started from the terminal and music is played. visible, even when mpv.net is started from the terminal and music is played.
The documentation of mpvs window features can be found here: The documentation of mpv's window features can be found here:
https://mpv.io/manual/master/#window https://mpv.io/manual/master/#window
mpv.net has currently implemented the following window features: **mpv.net has currently implemented the following window properties:**
- [border](https://mpv.io/manual/master/#options-border) - [border](https://mpv.io/manual/master/#options-border)
- [fullscreen](https://mpv.io/manual/master/#options-fullscreen) - [fullscreen](https://mpv.io/manual/master/#options-fullscreen)
- [keepaspect-window](https://mpv.io/manual/master/#options-keepaspect-window)
- [ontop](https://mpv.io/manual/master/#options-ontop) - [ontop](https://mpv.io/manual/master/#options-ontop)
- [screen](https://mpv.io/manual/master/#options-screen) - [screen](https://mpv.io/manual/master/#options-screen)
- [snap-window](https://mpv.io/manual/master/#options-snap-window)
- [title](https://mpv.io/manual/master/#options-title) - [title](https://mpv.io/manual/master/#options-title)
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized) - [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized) - [window-minimized](https://mpv.io/manual/master/#options-window-minimized)
- [window-scale](https://mpv.io/manual/master/#options-window-scale)
**Partly implemented are:** **Partly implemented are:**
[autofit](https://mpv.io/manual/master/#options-autofit) - [autofit-larger](https://mpv.io/manual/master/#options-autofit-larger)
Supported is a single integer value in the range 0-100.
- [autofit-smaller](https://mpv.io/manual/master/#options-autofit-smaller)
Supported is a single integer value in the range 0-100.
- [autofit](https://mpv.io/manual/master/#options-autofit)
Supported is a single integer value in the range 0-100.
[autofit-smaller](https://mpv.io/manual/master/#options-autofit-smaller) mpv.net specific window features are documented in the [screen section](#screen).
[autofit-larger](https://mpv.io/manual/master/#options-autofit-larger)
### Command Line Limitations ### Command Line Limitations
@@ -589,12 +796,19 @@ need an own implementation in mpv.net, so far implemented are:
--vd=help --vd=help
--version --version
### Other Limitations
The mpv property [idle](https://mpv.io/manual/master/#options-idle) can be
used and mpv.net functions accordingly, but Lua scripts always see `idle=yes`
because mpv.net has to set it to function correctly, this is a difficult
to overcome libmpv limitation.
### mpv.net specific options ### mpv.net specific options
Options that are specific to mpv.net can be found by entering _mpv.net_ Options that are specific to mpv.net can be found by entering _mpv.net_
in the search field of the config editor, in the manual they are documented in the search field of the config editor, in the mpv.net manual they are
[here](#mpvnet-specific-options). documented [here](#mpvnet-specific-options).
mpv.net specific options are saved in the file mpvnet.conf and are just mpv.net specific options are saved in the file mpvnet.conf and are just
as mpv properties available on the command line. as mpv properties available on the command line.
@@ -611,16 +825,10 @@ The Extension implementation is based on the
The main window is WinForms based because WinForms allows better libmpv integration The main window is WinForms based because WinForms allows better libmpv integration
compared to WPF, all other windows are WPF based. compared to WPF, all other windows are WPF based.
The config editor adds it's controls dynamically and uses
[TOML](https://en.wikipedia.org/wiki/TOML) to define it's content.
Third party components are: Third party components are:
- [libmpv provides the core functionality](https://mpv.io/) - [libmpv provides the core functionality](https://mpv.io/)
- [MediaInfo](https://mediaarea.net/en/MediaInfo) - [MediaInfo](https://mediaarea.net/en/MediaInfo)
- [Tommy, a single file TOML parser](https://github.com/dezhidki/Tommy)
- [Everything, a fast file search service](https://www.voidtools.com)
Context Menu Context Menu
@@ -631,9 +839,9 @@ located in the config directory.
If the input.conf file does not exists mpv.net generates it with the following defaults: If the input.conf file does not exists mpv.net generates it with the following defaults:
<https://github.com/stax76/mpv.net/tree/master/src/Resources/input.conf.txt> <https://github.com/mpvnet-player/mpv.net/tree/master/src/Resources/input.conf.txt>
input.conf defines mpvs key and mouse bindings and mpv.net uses input.conf defines mpv's key and mouse bindings and mpv.net uses
comments to define the context menu. comments to define the context menu.
@@ -661,20 +869,12 @@ Opens files and URLs from the clipboard. How to open URLs directly
from the browser from sites like YouTube is described in the from the browser from sites like YouTube is described in the
[External Tools section](#external-tools). [External Tools section](#external-tools).
For internet streaming youtube-dl must be downloaded and installed manually,
meaning it must be located in the PATH environment variable or in the startup directory.
### Open > Open DVD/Blu-ray Drive/Folder ### Open > Open DVD/Blu-ray Drive/Folder
Opens a DVD/Blu-ray Drive/Folder. Opens a DVD/Blu-ray Drive/Folder.
### Open > Show media search
mpv.net supports system wide media searches using the Everything indexing
service installed by the popular file search tool [Everything](www.voidtools.com).
### Open > Load external audio files ### Open > Load external audio files
Allows to load an external audio file. It's also possible to auto detect Allows to load an external audio file. It's also possible to auto detect
@@ -1032,7 +1232,7 @@ Adds a negative audio delay using the following command:
Shows the next subtitle track using the following command: Shows the next subtitle track using the following command:
`cycle sub` `script-message-to mpvnet cycle-subtitles`
[cycle command](https://mpv.io/manual/master/#command-interface-cycle-%3Cname%3E-[%3Cvalue%3E]) [cycle command](https://mpv.io/manual/master/#command-interface-cycle-%3Cname%3E-[%3Cvalue%3E])
@@ -1333,7 +1533,7 @@ Enables to set loop start and end points using the following command:
Loops the current file infinitely using the following command: Loops the current file infinitely using the following command:
cycle-values loop-file "inf" "no" `cycle-values loop-file "inf" "no"`
[cycle-values command](https://mpv.io/manual/master/#command-interface-cycle-values) [cycle-values command](https://mpv.io/manual/master/#command-interface-cycle-values)
@@ -1368,19 +1568,12 @@ Shows the [mpv.net web site](https://mpv-net.github.io/mpv.net-web-site/).
### Help > Show mpv.net manual ### Help > Show mpv.net manual
Shows the [mpv.net manual](https://github.com/stax76/mpv.net/blob/master/Manual.md). Shows the [mpv.net manual](https://github.com/mpvnet-player/mpv.net/blob/master/Manual.md).
### Help > Check for Updates
Checks for updates and allows to execute the update routine.
The update routine requires PowerShell 5 and curl, an up to date Windows 10 system has both included.
### Help > About mpv.net ### Help > About mpv.net
Shows the mpv.net about dialog which shows a copyright notice, the versions of mpv.net and libmpv and a license notice (MIT). Shows the mpv.net about dialog which shows a copyright notice, the versions of mpv.net and libmpv and a license notice (GPL v2).
### Exit ### Exit

1516
docs/Manual_chs.md Normal file

File diff suppressed because it is too large Load Diff

2
docs/Privacy.md Normal file
View File

@@ -0,0 +1,2 @@
mpv.net does not collect any personal information.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

BIN
docs/img/InputEditor.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

BIN
docs/img/Main.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 KiB

After

Width:  |  Height:  |  Size: 536 KiB

BIN
docs/img/Playlist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 355 KiB

22
src/.editorconfig Normal file
View File

@@ -0,0 +1,22 @@
[*.cs]
# IDE0058: Expression value is never used
dotnet_diagnostic.IDE0058.severity = none
# IDE0055: Fix formatting
dotnet_diagnostic.IDE0055.severity = none
# IDE0022: Use block body for methods
dotnet_diagnostic.IDE0022.severity = none
# IDE0040: Add accessibility modifiers
dotnet_diagnostic.IDE0040.severity = none
# IDE0011: Add braces
dotnet_diagnostic.IDE0011.severity = none
# IDE0010: Add missing cases
dotnet_diagnostic.IDE0010.severity = none
# IDE0044: Add readonly modifier
dotnet_diagnostic.IDE0044.severity = silent

File diff suppressed because it is too large Load Diff

View File

@@ -80,7 +80,7 @@ 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 = Core.get_property_string("path"); string path = Core.GetPropertyString("path");
if (!File.Exists(path)) if (!File.Exists(path))
return; return;
@@ -90,7 +90,7 @@ namespace RatingExtension // the assembly name must end with 'Extension'!
else else
{ {
Dic[path] = rating; Dic[path] = rating;
Core.commandv("show-text", $"Rating: {rating}"); Core.CommandV("show-text", $"Rating: {rating}");
} }
} }
else if (args[1] == "about") else if (args[1] == "about")
@@ -104,26 +104,26 @@ namespace RatingExtension // the assembly name must end with 'Extension'!
{ {
if (rating == 0) if (rating == 0)
{ {
FileToDelete = Core.get_property_string("path"); FileToDelete = Core.GetPropertyString("path");
DeleteTime = DateTime.Now; DeleteTime = DateTime.Now;
Core.commandv("show-text", "Press 1 to delete file", "5000"); Core.CommandV("show-text", "Press 1 to delete file", "5000");
} }
else else
{ {
TimeSpan ts = DateTime.Now - DeleteTime; TimeSpan ts = DateTime.Now - DeleteTime;
string path = Core.get_property_string("path"); string path = Core.GetPropertyString("path");
if (FileToDelete == path && ts.TotalSeconds < 5 && File.Exists(FileToDelete)) if (FileToDelete == path && ts.TotalSeconds < 5 && File.Exists(FileToDelete))
{ {
Core.command("playlist-remove current"); Core.Command("playlist-remove current");
int pos = Core.get_property_int("playlist-pos"); int pos = Core.GetPropertyInt("playlist-pos");
if (pos == -1) if (pos == -1)
{ {
int count = Core.get_property_int("playlist-count"); int count = Core.GetPropertyInt("playlist-count");
if (count > 0) if (count > 0)
Core.set_property_int("playlist-pos", count - 1); Core.SetPropertyInt("playlist-pos", count - 1);
} }
Thread.Sleep(2000); Thread.Sleep(2000);

View File

@@ -13,22 +13,22 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin\</OutputPath> <OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\</OutputPath> <OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>

View File

@@ -12,6 +12,10 @@ namespace mpvnet
{ {
public static class App public static class App
{ {
public static List<string> TempFiles { get; } = new List<string>();
public static string[] HistoryFilter { get; set; }
public static string ConfPath { get => Core.ConfigFolder + "mpvnet.conf"; } public static string ConfPath { get => Core.ConfigFolder + "mpvnet.conf"; }
public static string ProcessInstance { get; set; } = "single"; public static string ProcessInstance { get; set; } = "single";
public static string DarkMode { get; set; } = "always"; public static string DarkMode { get; set; } = "always";
@@ -19,24 +23,30 @@ namespace mpvnet
public static string LightTheme { get; set; } = "light"; public static string LightTheme { get; set; } = "light";
public static string StartSize { get; set; } = "height-session"; public static string StartSize { get; set; } = "height-session";
public static bool RememberWindowPosition { 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 AutoLoadFolder { get; set; } = true;
public static bool AutoPlay { get; set; }
public static bool DebugMode { get; set; }
public static bool Exit { get; set; }
public static bool IsTerminalAttached { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
public static bool MediaInfo { get; set; } = true;
public static bool Queue { get; set; } public static bool Queue { get; set; }
public static bool UpdateCheck { get; set; } public static bool RememberVolume { get; set; } = true;
public static bool RememberWindowPosition { get; set; }
public static bool ShowLogo { get; set; } = true;
public static bool ShowSantaLogo { get; set; } = true;
public static int StartThreshold { get; set; } = 1500; public static int StartThreshold { get; set; } = 1500;
public static int RecentCount { get; set; } = 15; public static int RecentCount { get; set; } = 15;
public static float MinimumAspectRatio { get; set; } = 1.2f; public static float AutofitAudio { get; set; } = 0.7f;
public static float AutofitImage { get; set; } = 0.8f;
public static float MinimumAspectRatio { get; set; }
public static float MinimumAspectRatioAudio { get; set; }
public static float QuickBookmark { get; set; }
public static Extension Extension { get; set; } public static Extension Extension { get; set; }
public static bool IsDarkMode { public static bool IsDarkMode => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
}
static AppSettings _Settings; static AppSettings _Settings;
@@ -80,8 +90,8 @@ namespace mpvnet
InitTheme(); InitTheme();
Core.Shutdown += Shutdown; Core.Shutdown += Core_Shutdown;
Core.Initialized += Initialized; Core.Initialized += Core_Initialized;
} }
public static void InitTheme() public static void InitTheme()
@@ -95,12 +105,26 @@ namespace mpvnet
themeContent, themeContent,
Properties.Resources.theme, Properties.Resources.theme,
IsDarkMode ? DarkTheme : LightTheme); IsDarkMode ? DarkTheme : LightTheme);
}
ToolStripRendererEx.ForegroundColor = Theme.Current.GetWinFormsColor("menu-foreground"); public static void UpdateWpfColors()
ToolStripRendererEx.BackgroundColor = Theme.Current.GetWinFormsColor("menu-background"); {
ToolStripRendererEx.SelectionColor = Theme.Current.GetWinFormsColor("menu-highlight"); var dic = System.Windows.Application.Current.Resources;
ToolStripRendererEx.BorderColor = Theme.Current.GetWinFormsColor("menu-border");
ToolStripRendererEx.CheckedColor = Theme.Current.GetWinFormsColor("menu-checked"); dic.Remove("BorderColor");
dic.Add("BorderColor", Theme.Current.GetColor("menu-highlight"));
dic.Remove("RegionColor");
dic.Add("RegionColor", Theme.Current.GetColor("menu-background"));
dic.Remove("SecondaryRegionColor");
dic.Add("SecondaryRegionColor", Theme.Current.GetColor("menu-highlight"));
dic.Remove("PrimaryTextColor");
dic.Add("PrimaryTextColor", Theme.Current.GetColor("menu-foreground"));
dic.Remove("HighlightColor");
dic.Add("HighlightColor", Theme.Current.GetColor("highlight"));
} }
public static void RunTask(Action action) public static void RunTask(Action action)
@@ -108,62 +132,94 @@ namespace mpvnet
Task.Run(() => { Task.Run(() => {
try { try {
action.Invoke(); action.Invoke();
} catch (Exception e) { }
catch (Exception e) {
ShowException(e); ShowException(e);
} }
}); });
} }
public static string Version { public static string Version => "Copyright (C) 2000-2022 mpv.net/mpv/mplayer\n" +
get { $"mpv.net {Application.ProductVersion}" + GetLastWriteTime(Application.ExecutablePath) + "\n" +
return "Copyright (C) 2000-2021 mpv.net/mpv/mplayer\n" + $"{Core.GetPropertyString("mpv-version")}" + GetLastWriteTime(Folder.Startup + "libmpv-2.dll") + "\n" +
$"mpv.net {Application.ProductVersion} ({File.GetLastWriteTime(Application.ExecutablePath).ToShortDateString()})\n" + $"ffmpeg {Core.GetPropertyString("ffmpeg-version")}\n" +
$"{Core.get_property_string("mpv-version")} ({File.GetLastWriteTime(Folder.Startup + "mpv-1.dll").ToShortDateString()})\nffmpeg {Core.get_property_string("ffmpeg-version")}\nMIT License"; $"MediaInfo {FileVersionInfo.GetVersionInfo(Path.Combine(Application.StartupPath, "MediaInfo.dll")).FileVersion}" +
} GetLastWriteTime(Path.Combine(Application.StartupPath , "MediaInfo.dll")) + "\nGPL v2 License";
static string GetLastWriteTime(string path)
{
if (IsStoreVrsion)
return "";
return $" ({File.GetLastWriteTime(path).ToShortDateString()})";
} }
static bool IsStoreVrsion => Application.StartupPath.Contains("FrankSkare.mpv.net");
public static void ShowException(object obj) public static void ShowException(object obj)
{ {
if (IsStartedFromTerminal) if (IsTerminalAttached)
Terminal.WriteError(obj.ToString()); Terminal.WriteError(obj.ToString());
else else
{ {
if (obj is Exception e) if (obj is Exception e)
Msg.ShowException(e); InvokeOnMainThread(() => Msg.ShowException(e));
else else
Msg.ShowError(obj.ToString()); InvokeOnMainThread(() => Msg.ShowError(obj.ToString()));
} }
} }
public static void ShowError(string title, string msg = null) public static void InvokeOnMainThread(Action action)
{ {
if (IsStartedFromTerminal) if (action == null)
{ return;
if (title != null)
Terminal.WriteError(title);
if (MainForm.Instance == null)
action.Invoke();
else
MainForm.Instance.BeginInvoke(action);
}
public static void ShowInfo(string msg)
{
if (IsTerminalAttached)
{
if (msg != null)
Terminal.Write(msg);
}
else
InvokeOnMainThread(() => Msg.ShowInfo(msg));
}
public static void ShowError(string msg)
{
if (IsTerminalAttached)
{
if (msg != null) if (msg != null)
Terminal.WriteError(msg); Terminal.WriteError(msg);
} }
else else
Msg.ShowError(title, msg); InvokeOnMainThread(() => Msg.ShowError(msg));
} }
static void Initialized() static void Core_Initialized()
{ {
if (RememberVolume) if (RememberVolume)
{ {
Core.set_property_int("volume", Settings.Volume); Core.SetPropertyInt("volume", Settings.Volume);
Core.set_property_string("mute", Settings.Mute); Core.SetPropertyString("mute", Settings.Mute);
} }
} }
static void Shutdown() static void Core_Shutdown()
{ {
Settings.Volume = Core.get_property_int("volume"); Settings.Volume = Core.GetPropertyInt("volume");
Settings.Mute = Core.get_property_string("mute"); Settings.Mute = Core.GetPropertyString("mute");
SettingsManager.Save(Settings); SettingsManager.Save(Settings);
foreach (string file in TempFiles)
FileHelp.Delete(file);
} }
static Dictionary<string, string> _Conf; static Dictionary<string, string> _Conf;
@@ -187,28 +243,56 @@ namespace mpvnet
{ {
switch (name) switch (name)
{ {
case "remember-window-position": RememberWindowPosition = 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.ToInt(); return true;
case "recent-count": RecentCount = value.ToInt(); return true;
case "minimum-aspect-ratio": MinimumAspectRatio = value.ToFloat(); return true;
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
case "video-file-extensions": CorePlayer.VideoTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
case "audio-file-extensions": CorePlayer.AudioTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true; case "audio-file-extensions": CorePlayer.AudioTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
case "auto-load-folder": AutoLoadFolder = value == "yes"; return true;
case "auto-play": AutoPlay = value == "yes"; return true;
case "autofit-audio": AutofitAudio = value.Trim('%').ToInt() / 100f; return true;
case "autofit-image": AutofitImage = value.Trim('%').ToInt() / 100f; return true;
case "dark-mode": DarkMode = value; return true;
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
case "debug-mode": DebugMode = value == "yes"; return true;
case "history-filter": HistoryFilter = value.Split(';'); return true;
case "image-file-extensions": CorePlayer.ImageTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true; case "image-file-extensions": CorePlayer.ImageTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
case "media-info": MediaInfo = value == "yes"; return true;
case "minimum-aspect-ratio-audio": MinimumAspectRatioAudio = value.ToFloat(); return true;
case "minimum-aspect-ratio": MinimumAspectRatio = value.ToFloat(); return true;
case "process-instance": ProcessInstance = value; return true;
case "queue": Queue = value == "yes"; return true;
case "recent-count": RecentCount = value.ToInt(); return true;
case "remember-volume": RememberVolume = value == "yes"; return true;
case "remember-window-position": RememberWindowPosition = value == "yes"; return true;
case "show-logo": ShowLogo = value == "yes"; return true;
case "show-santa-logo": ShowSantaLogo = value == "yes"; return true;
case "start-size": StartSize = value; return true;
case "start-threshold": StartThreshold = value.ToInt(); return true;
case "video-file-extensions": CorePlayer.VideoTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
default: default:
if (writeError) if (writeError)
Terminal.WriteError($"unknown mpvnet.conf property: {name}"); Terminal.WriteError($"unknown mpvnet.conf property: {name}");
return false; return false;
} }
} }
public static void CopyMpvnetCom()
{
string dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData).AddSep() +
"Microsoft\\WindowsApps\\";
if (File.Exists(dir + "mpvnet.exe") && !File.Exists(dir + "mpvnet.com"))
File.Copy(Folder.Startup + "mpvnet.com", dir + "mpvnet.com");
}
public static (string Title, string Path) GetTitleAndPath(string input)
{
if (input.Contains("|"))
{
var a = input.Split('|');
return (a[1], a[0]);
}
return (input, input);
}
} }
} }

View File

@@ -1,12 +1,9 @@
 
using System;
using System.CodeDom.Compiler; using System.CodeDom.Compiler;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Microsoft.CSharp; using Microsoft.CSharp;
@@ -28,7 +25,7 @@ namespace mpvnet
static void Execute(string file) static void Execute(string file)
{ {
string code = File.ReadAllText(file); string code = File.ReadAllText(file);
string filename = Path.GetFileNameWithoutExtension(file) + " " + GetMD5(code) + ".dll"; string filename = Path.GetFileNameWithoutExtension(file) + " " + StringHelp.GetMD5Hash(code) + "-v6.dll";
string outputFile = Path.Combine(Path.GetTempPath(), filename); string outputFile = Path.Combine(Path.GetTempPath(), filename);
if (!File.Exists(outputFile)) if (!File.Exists(outputFile))
@@ -70,15 +67,5 @@ namespace mpvnet
if (errors.Count() > 0) if (errors.Count() > 0)
Terminal.WriteError(string.Join(BR2, errors), Path.GetFileName(file)); Terminal.WriteError(string.Join(BR2, errors), Path.GetFileName(file));
} }
static string GetMD5(string code)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBuffer = Encoding.UTF8.GetBytes(code);
byte[] hashBuffer = md5.ComputeHash(inputBuffer);
return BitConverter.ToString(md5.ComputeHash(inputBuffer)).Replace("-", "");
}
}
} }
} }

File diff suppressed because it is too large Load Diff

65
src/Misc/Common.cs Normal file
View File

@@ -0,0 +1,65 @@

using System.Collections.Generic;
using System.Linq;
namespace mpvnet
{
public class StringPair
{
public string Name { get; set; }
public string Value { get; set; }
}
public class ConfParser
{
public static List<ConfSection> Parse(string content)
{
string[] lines = content.Split(new[] { "\r\n" }, System.StringSplitOptions.None);
var sections = new List<ConfSection>();
ConfSection currentGroup = null;
foreach (string i in lines)
{
string line = i.Trim();
if (line == "")
{
currentGroup = new ConfSection();
sections.Add(currentGroup);
}
else if (line.Contains("="))
{
string name = line.Substring(0, line.IndexOf("=")).Trim();
string value = line.Substring(line.IndexOf("=") + 1).Trim();
currentGroup.Items.Add(new StringPair() { Name = name, Value = value });
}
}
return sections;
}
}
public class ConfSection
{
public List<StringPair> Items { get; set; } = new List<StringPair>();
public bool HasName(string name)
{
foreach (var i in Items)
if (i.Name == name)
return true;
return false;
}
public string GetValue(string name)
{
foreach (var i in Items)
if (i.Name == name)
return i.Value;
return null;
}
public List<StringPair> GetValues(string name) => Items.Where(i => i.Name == name).ToList();
}
}

View File

@@ -1,49 +1,42 @@
 
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows.Navigation; using System.Windows.Navigation;
using Tommy; namespace mpvnet
using mpvnet;
namespace DynamicGUI
{ {
public class Settings public class Conf
{ {
public static List<SettingBase> LoadSettings(string content) public static List<SettingBase> LoadConf(string content)
{ {
TomlTable table; List<SettingBase> settingsList = new List<SettingBase>();
using (StringReader reader = new StringReader(content)) foreach (ConfSection section in ConfParser.Parse(content))
table = TOML.Parse(reader);
List<SettingBase> settingsList = new List<SettingBase>();
foreach (TomlTable setting in table["settings"])
{ {
SettingBase baseSetting = null; SettingBase baseSetting = null;
if (setting.HasKey("options")) if (section.HasName("option"))
{ {
OptionSetting optionSetting = new OptionSetting(); OptionSetting optionSetting = new OptionSetting();
baseSetting = optionSetting; baseSetting = optionSetting;
optionSetting.Default = setting["default"]; optionSetting.Default = section.GetValue("default");
optionSetting.Value = optionSetting.Default; optionSetting.Value = optionSetting.Default;
foreach (TomlTable option in setting["options"]) foreach (var i in section.GetValues("option"))
{ {
var opt = new OptionSettingOption(); var opt = new OptionSettingOption();
opt.Name = option["name"];
if (option.HasKey("help")) if (i.Value.Contains(" "))
opt.Help = option["help"]; {
opt.Name = i.Value.Substring(0, i.Value.IndexOf(" "));
opt.Help = i.Value.Substring(i.Value.IndexOf(" ")).Trim();
}
else
opt.Name = i.Value;
if (option.HasKey("text")) if (opt.Name == optionSetting.Default)
opt.Text = option["text"];
else if (opt.Name == optionSetting.Default)
opt.Text = opt.Name + " (Default)"; opt.Text = opt.Name + " (Default)";
opt.OptionSetting = optionSetting; opt.OptionSetting = optionSetting;
@@ -54,20 +47,24 @@ namespace DynamicGUI
{ {
StringSetting stringSetting = new StringSetting(); StringSetting stringSetting = new StringSetting();
baseSetting = stringSetting; baseSetting = stringSetting;
stringSetting.Default = setting.HasKey("default") ? setting["default"].ToString() : ""; stringSetting.Default = section.HasName("default") ? section.GetValue("default") : "";
} }
baseSetting.Name = setting["name"]; baseSetting.Name = section.GetValue("name");
baseSetting.File = setting["file"]; baseSetting.File = section.GetValue("file");
baseSetting.Filter = setting["filter"]; baseSetting.Filter = section.GetValue("filter");
if (setting.HasKey("help")) baseSetting.Help = setting["help"]; if (section.HasName("help")) baseSetting.Help = section.GetValue("help");
if (setting.HasKey("url")) baseSetting.URL = setting["url"]; if (section.HasName("url")) baseSetting.URL = section.GetValue("url");
if (setting.HasKey("width")) baseSetting.Width = setting["width"]; if (section.HasName("width")) baseSetting.Width = Convert.ToInt32(section.GetValue("width"));
if (setting.HasKey("type")) baseSetting.Type = setting["type"]; if (section.HasName("type")) baseSetting.Type = section.GetValue("type");
if (baseSetting.Help.ContainsEx("\\n"))
baseSetting.Help = baseSetting.Help.Replace("\\n", "\n");
settingsList.Add(baseSetting); settingsList.Add(baseSetting);
} }
return settingsList; return settingsList;
} }
} }
@@ -155,11 +152,13 @@ namespace DynamicGUI
public void SetURL(string url) public void SetURL(string url)
{ {
if (string.IsNullOrEmpty(url)) return; if (string.IsNullOrEmpty(url))
return;
NavigateUri = new Uri(url); NavigateUri = new Uri(url);
RequestNavigate += HyperLinkEx_RequestNavigate; RequestNavigate += HyperLinkEx_RequestNavigate;
Inlines.Clear(); Inlines.Clear();
Inlines.Add(url); Inlines.Add(url);
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@ 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.Linq;
using static mpvnet.Global; using static mpvnet.Global;
@@ -22,25 +21,7 @@ namespace mpvnet
try try
{ {
AggregateCatalog catalog = new AggregateCatalog(); AggregateCatalog catalog = new AggregateCatalog();
string dir = Folder.Startup + "Extensions"; string dir = Core.ConfigFolder + "extensions";
if (Directory.Exists(dir))
{
string[] knownExtensions = { "RatingExtension", "ScriptingExtension" };
foreach (string extDir in Directory.GetDirectories(dir))
{
if (knownExtensions.Contains(Path.GetFileName(extDir)))
catalog.Catalogs.Add(new DirectoryCatalog(extDir, Path.GetFileName(extDir) + ".dll"));
else
Terminal.WriteError("Failed to load extension:" + BR2 + extDir +
BR2 + "Only extensions that ship with mpv.net are allowed in <startup>\\extensions" +
BR2 + "User extensions have to use <config folder>\\extensions" +
BR2 + "Never 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 extDir in Directory.GetDirectories(dir)) foreach (string extDir in Directory.GetDirectories(dir))

View File

@@ -1,12 +1,13 @@
 
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text.RegularExpressions;
public static class TestStringExtension public static class TestStringExtension
{ {
public static bool ContainsEx(this string instance, string value) public static bool ContainsEx(this string instance, string value)
{ {
if (instance != null && value != null) if (!string.IsNullOrEmpty(instance) && !string.IsNullOrEmpty(value))
return instance.Contains(value); return instance.Contains(value);
return false; return false;
@@ -46,6 +47,8 @@ public static class ConvertToStringExtension
return instance.Trim(); return instance.Trim();
} }
public static string ToStringEx(this object instance) => instance?.ToString() ?? "";
} }
public static class ConvertStringExtension public static class ConvertStringExtension
@@ -67,13 +70,25 @@ public static class ConvertStringExtension
public static class PathStringExtension public static class PathStringExtension
{ {
// return extension with lower case and without dot. public static string Ext(this string filepath) => Ext(filepath, false);
public static string Ext(this string instance)
public static string Ext(this string filepath, bool includeDot)
{ {
if (instance == null) if (string.IsNullOrEmpty(filepath))
return ""; return "";
return Path.GetExtension(instance).TrimStart('.').ToLower(); char[] chars = filepath.ToCharArray();
for (int x = filepath.Length - 1; x >= 0; x--)
{
if (chars[x] == Path.DirectorySeparatorChar)
return "";
if (chars[x] == '.')
return filepath.Substring(x + (includeDot ? 0 : 1)).ToLowerInvariant();
}
return "";
} }
public static string FileName(this string instance) public static string FileName(this string instance)
@@ -94,23 +109,25 @@ public static class PathStringExtension
return instance; return instance;
} }
// Ensure trailing directory separator char public static string ShortPath(this string instance, int maxLength)
{
if (string.IsNullOrEmpty(instance))
return "";
if (instance.Length > maxLength && instance.Substring(1, 2) == ":\\")
instance = instance.Substring(0, 3) + "...\\" + instance.FileName();
return instance;
}
public static string AddSep(this string instance) public static string AddSep(this string instance)
{ {
if (string.IsNullOrEmpty(instance)) if (string.IsNullOrEmpty(instance))
return ""; return "";
if (!instance.EndsWith(Path.DirectorySeparatorChar.ToString())) if (!instance.EndsWith(Path.DirectorySeparatorChar.ToString()))
instance = instance + Path.DirectorySeparatorChar; instance += Path.DirectorySeparatorChar;
return instance; return instance;
} }
public static bool IsIdenticalFolder(this string instance, string testFolder)
{
if (string.IsNullOrEmpty(instance) || string.IsNullOrEmpty(testFolder))
return false;
return instance.ToLowerInvariant().AddSep() == testFolder.ToLowerInvariant().AddSep();
}
} }

124
src/Misc/FolderBrowser.cs Normal file
View File

@@ -0,0 +1,124 @@

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace mpvnet
{
public class FolderBrowser
{
public string SelectedPath { get; set; }
string _initialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
public string InitialDirectory {
get => _initialDirectory;
set {
if (Directory.Exists(value))
_initialDirectory = value;
}
}
public bool Show() => Show(GetOwnerHandle());
public bool Show(IntPtr hWndOwner)
{
ShowDialogResult result = VistaDialog.Show(hWndOwner, InitialDirectory);
if (result.Result)
SelectedPath = result.FileName;
return result.Result;
}
struct ShowDialogResult
{
public bool Result { get; set; }
public string FileName { get; set; }
}
public static IntPtr GetOwnerHandle()
{
IntPtr foregroundWindow = GetForegroundWindow();
GetWindowThreadProcessId(foregroundWindow, out var procID);
using (var proc = Process.GetCurrentProcess())
if (proc.Id == procID)
return foregroundWindow;
return IntPtr.Zero;
}
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
static class VistaDialog
{
const string foldersFilter = "Folders|\n";
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
static Assembly windowsFormsAssembly = typeof(FileDialog).Assembly;
static Type iFileDialogType = windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
static MethodInfo createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", flags);
static MethodInfo onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", flags);
static MethodInfo getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", flags);
static MethodInfo setOptionsMethodInfo = iFileDialogType.GetMethod("SetOptions", flags);
static uint fosPickFoldersBitFlag = (uint)windowsFormsAssembly
.GetType("System.Windows.Forms.FileDialogNative+FOS")
.GetField("FOS_PICKFOLDERS")
.GetValue(null);
static ConstructorInfo vistaDialogEventsConstructorInfo = windowsFormsAssembly
.GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
.GetConstructor(flags, null, new[] { typeof(FileDialog) }, null);
static MethodInfo adviseMethodInfo = iFileDialogType.GetMethod("Advise");
static MethodInfo unAdviseMethodInfo = iFileDialogType.GetMethod("Unadvise");
static MethodInfo showMethodInfo = iFileDialogType.GetMethod("Show");
public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory)
{
var openFileDialog = new OpenFileDialog
{
AddExtension = false,
CheckFileExists = false,
DereferenceLinks = true,
Filter = foldersFilter,
InitialDirectory = initialDirectory,
Multiselect = false,
};
var iFileDialog = createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint)getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | fosPickFoldersBitFlag });
var adviseParametersWithOutputConnectionToken = new[] { vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);
try
{
int retVal = (int)showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
return new ShowDialogResult
{
Result = retVal == 0,
FileName = openFileDialog.FileName
};
}
finally
{
unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
}
}
}
class WindowWrapper : IWin32Window
{
IntPtr _handle;
public WindowWrapper(IntPtr handle) { _handle = handle; }
public IntPtr Handle => _handle;
}
}
}

View File

@@ -46,10 +46,10 @@ namespace mpvnet
{ {
string umod = parts[i].ToUpper(); string umod = parts[i].ToUpper();
if (umod == "ALT") mod |= KeyModifiers.Alt; if (umod == "ALT") mod |= KeyModifiers.Alt;
if (umod == "CTRL") mod |= KeyModifiers.Ctrl; if (umod == "CTRL") mod |= KeyModifiers.Ctrl;
if (umod == "SHIFT") mod |= KeyModifiers.Shift; if (umod == "SHIFT") mod |= KeyModifiers.Shift;
if (umod == "WIN") mod |= KeyModifiers.Win; if (umod == "WIN") mod |= KeyModifiers.Win;
} }
key = parts[parts.Length - 1]; key = parts[parts.Length - 1];
@@ -61,9 +61,6 @@ namespace mpvnet
int hi = result >> 8; int hi = result >> 8;
int lo = result & 0xFF; int lo = result & 0xFF;
if (lo == -1)
return;
vk = lo; vk = lo;
if ((hi & 1) == 1) mod |= KeyModifiers.Shift; if ((hi & 1) == 1) mod |= KeyModifiers.Shift;
@@ -89,7 +86,7 @@ namespace mpvnet
public static void Execute(int id) public static void Execute(int id)
{ {
if (Commands.ContainsKey(id)) if (Commands.ContainsKey(id))
Core.command(Commands[id]); Core.Command(Commands[id]);
} }
static int mpv_to_VK(string value) static int mpv_to_VK(string value)

View File

@@ -1,8 +1,12 @@
 
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.Win32; using Microsoft.Win32;
@@ -11,6 +15,32 @@ using static mpvnet.Global;
namespace mpvnet namespace mpvnet
{ {
public static class StringHelp
{
public static string GetMD5Hash(string txt)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBuffer = Encoding.UTF8.GetBytes(txt);
byte[] hashBuffer = md5.ComputeHash(inputBuffer);
return BitConverter.ToString(md5.ComputeHash(inputBuffer)).Replace("-", "");
}
}
}
public static class FileHelp
{
public static void Delete(string path)
{
try {
if (File.Exists(path))
File.Delete(path);
} catch (Exception ex) {
Terminal.WriteError("Failed to delete file:" + BR + path + BR + ex.Message);
}
}
}
public static class ProcessHelp public static class ProcessHelp
{ {
public static void Execute(string file, string arguments = null) public static void Execute(string file, string arguments = null)
@@ -60,9 +90,8 @@ namespace mpvnet
public static bool IsPosDifferent(Point screenPos) public static bool IsPosDifferent(Point screenPos)
{ {
return return Math.Abs(screenPos.X - Control.MousePosition.X) > 10 ||
Math.Abs(screenPos.X - Control.MousePosition.X) > 10 || Math.Abs(screenPos.Y - Control.MousePosition.Y) > 10;
Math.Abs(screenPos.Y - Control.MousePosition.Y) > 10;
} }
} }
@@ -70,45 +99,44 @@ namespace mpvnet
{ {
public static string GetProfiles() public static string GetProfiles()
{ {
string code = @" string json = Core.GetPropertyString("profile-list");
foreach ($item in ($json | ConvertFrom-Json | foreach { $_ } | sort name)) var o = json.FromJson<List<Dictionary<string, object>>>().OrderBy(i => i["name"]);
{ StringBuilder sb = new StringBuilder();
$item.name
''
foreach ($option in $item.options) foreach (Dictionary<string, object> i in o)
{ {
' ' + $option.key + ' = ' + $option.value sb.Append(i["name"].ToString() + BR2);
}
'' foreach (Dictionary<string, object> i2 in i["options"] as List<object>)
}"; sb.AppendLine(" " + i2["key"] + " = " + i2["value"]);
string json = Core.get_property_string("profile-list"); sb.Append(BR);
return PowerShell.InvokeAndReturnString(code, "json", json).Trim(); }
return sb.ToString();
} }
public static string GetDecoders() public static string GetDecoders()
{ {
string code = @" string json = Core.GetPropertyString("decoder-list");
foreach ($item in ($json | ConvertFrom-Json | foreach { $_ } | sort codec)) var o = json.FromJson<List<Dictionary<string, object>>>().OrderBy(i => i["codec"]);
{ StringBuilder sb = new StringBuilder();
$item.codec + ' - ' + $item.description
}";
string json = Core.get_property_string("decoder-list"); foreach (Dictionary<string, object> i in o)
return PowerShell.InvokeAndReturnString(code, "json", json).Trim(); sb.AppendLine(i["codec"] + " - " + i["description"]);
return sb.ToString();
} }
public static string GetProtocols() public static string GetProtocols()
{ {
string list = Core.get_property_string("protocol-list"); string list = Core.GetPropertyString("protocol-list");
return string.Join(BR, list.Split(',').OrderBy(a => a)); return string.Join(BR, list.Split(',').OrderBy(a => a));
} }
public static string GetDemuxers() public static string GetDemuxers()
{ {
string list = Core.get_property_string("demuxer-lavf-list"); string list = Core.GetPropertyString("demuxer-lavf-list");
return string.Join(BR, list.Split(',').OrderBy(a => a)); return string.Join(BR, list.Split(',').OrderBy(a => a));
} }
} }

415
src/Misc/JSONParser.cs Normal file
View File

@@ -0,0 +1,415 @@

// https://github.com/zanders3/json
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
namespace mpvnet
{
public static class JSONParser
{
[ThreadStatic] static Stack<List<string>> splitArrayPool;
[ThreadStatic] static StringBuilder stringBuilder;
[ThreadStatic] static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfoCache;
[ThreadStatic] static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyInfoCache;
public static T FromJson<T>(this string json)
{
// Initialize, if needed, the ThreadStatic variables
if (propertyInfoCache == null)
propertyInfoCache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
if (fieldInfoCache == null)
fieldInfoCache = new Dictionary<Type, Dictionary<string, FieldInfo>>();
if (stringBuilder == null)
stringBuilder = new StringBuilder();
if (splitArrayPool == null)
splitArrayPool = new Stack<List<string>>();
//Remove all whitespace not within strings to make parsing simpler
stringBuilder.Length = 0;
for (int i = 0; i < json.Length; i++)
{
char c = json[i];
if (c == '"')
{
i = AppendUntilStringEnd(true, i, json);
continue;
}
if (char.IsWhiteSpace(c))
continue;
stringBuilder.Append(c);
}
//Parse the thing!
return (T)ParseValue(typeof(T), stringBuilder.ToString());
}
static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
{
stringBuilder.Append(json[startIdx]);
for (int i = startIdx + 1; i < json.Length; i++)
{
if (json[i] == '\\')
{
if (appendEscapeCharacter)
stringBuilder.Append(json[i]);
stringBuilder.Append(json[i + 1]);
i++;//Skip next character as it is escaped
}
else if (json[i] == '"')
{
stringBuilder.Append(json[i]);
return i;
}
else
stringBuilder.Append(json[i]);
}
return json.Length - 1;
}
//Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings
static List<string> Split(string json)
{
List<string> splitArray = splitArrayPool.Count > 0 ? splitArrayPool.Pop() : new List<string>();
splitArray.Clear();
if (json.Length == 2)
return splitArray;
int parseDepth = 0;
stringBuilder.Length = 0;
for (int i = 1; i < json.Length - 1; i++)
{
switch (json[i])
{
case '[':
case '{':
parseDepth++;
break;
case ']':
case '}':
parseDepth--;
break;
case '"':
i = AppendUntilStringEnd(true, i, json);
continue;
case ',':
case ':':
if (parseDepth == 0)
{
splitArray.Add(stringBuilder.ToString());
stringBuilder.Length = 0;
continue;
}
break;
}
stringBuilder.Append(json[i]);
}
splitArray.Add(stringBuilder.ToString());
return splitArray;
}
internal static object ParseValue(Type type, string json)
{
if (type == typeof(string))
{
if (json.Length <= 2)
return string.Empty;
StringBuilder parseStringBuilder = new StringBuilder(json.Length);
for (int i = 1; i < json.Length - 1; ++i)
{
if (json[i] == '\\' && i + 1 < json.Length - 1)
{
int j = "\"\\nrtbf/".IndexOf(json[i + 1]);
if (j >= 0)
{
parseStringBuilder.Append("\"\\\n\r\t\b\f/"[j]);
++i;
continue;
}
if (json[i + 1] == 'u' && i + 5 < json.Length - 1)
{
uint c = 0;
if (uint.TryParse(json.Substring(i + 2, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out c))
{
parseStringBuilder.Append((char)c);
i += 5;
continue;
}
}
}
parseStringBuilder.Append(json[i]);
}
return parseStringBuilder.ToString();
}
if (type.IsPrimitive)
{
var result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture);
return result;
}
if (type == typeof(decimal))
{
decimal result;
decimal.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
return result;
}
if (json == "null")
return null;
if (type.IsEnum)
{
if (json[0] == '"')
json = json.Substring(1, json.Length - 2);
try
{
return Enum.Parse(type, json, false);
}
catch
{
return 0;
}
}
if (type.IsArray)
{
Type arrayType = type.GetElementType();
if (json[0] != '[' || json[json.Length - 1] != ']')
return null;
List<string> elems = Split(json);
Array newArray = Array.CreateInstance(arrayType, elems.Count);
for (int i = 0; i < elems.Count; i++)
newArray.SetValue(ParseValue(arrayType, elems[i]), i);
splitArrayPool.Push(elems);
return newArray;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
Type listType = type.GetGenericArguments()[0];
if (json[0] != '[' || json[json.Length - 1] != ']')
return null;
List<string> elems = Split(json);
var list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count });
for (int i = 0; i < elems.Count; i++)
list.Add(ParseValue(listType, elems[i]));
splitArrayPool.Push(elems);
return list;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
Type keyType, valueType;
{
Type[] args = type.GetGenericArguments();
keyType = args[0];
valueType = args[1];
}
//Refuse to parse dictionary keys that aren't of type string
if (keyType != typeof(string))
return null;
//Must be a valid dictionary element
if (json[0] != '{' || json[json.Length - 1] != '}')
return null;
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
return null;
var dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 });
for (int i = 0; i < elems.Count; i += 2)
{
if (elems[i].Length <= 2)
continue;
string keyValue = elems[i].Substring(1, elems[i].Length - 2);
object val = ParseValue(valueType, elems[i + 1]);
dictionary[keyValue] = val;
}
return dictionary;
}
if (type == typeof(object))
return ParseAnonymousValue(json);
if (json[0] == '{' && json[json.Length - 1] == '}')
return ParseObject(type, json);
return null;
}
static object ParseAnonymousValue(string json)
{
if (json.Length == 0)
return null;
if (json[0] == '{' && json[json.Length - 1] == '}')
{
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
return null;
var dict = new Dictionary<string, object>(elems.Count / 2);
for (int i = 0; i < elems.Count; i += 2)
dict[elems[i].Substring(1, elems[i].Length - 2)] = ParseAnonymousValue(elems[i + 1]);
return dict;
}
if (json[0] == '[' && json[json.Length - 1] == ']')
{
List<string> items = Split(json);
var finalList = new List<object>(items.Count);
for (int i = 0; i < items.Count; i++)
finalList.Add(ParseAnonymousValue(items[i]));
return finalList;
}
if (json[0] == '"' && json[json.Length - 1] == '"')
{
string str = json.Substring(1, json.Length - 2);
return str.Replace("\\", string.Empty);
}
if (char.IsDigit(json[0]) || json[0] == '-')
{
if (json.Contains("."))
{
double result;
double.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
return result;
}
else
{
int result;
int.TryParse(json, out result);
return result;
}
}
if (json == "true")
return true;
if (json == "false")
return false;
// handles json == "null" as well as invalid JSON
return null;
}
static Dictionary<string, T> CreateMemberNameDictionary<T>(T[] members) where T : MemberInfo
{
Dictionary<string, T> nameToMember = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < members.Length; i++)
{
T member = members[i];
if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true))
continue;
string name = member.Name;
if (member.IsDefined(typeof(DataMemberAttribute), true))
{
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true);
if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
name = dataMemberAttribute.Name;
}
nameToMember.Add(name, member);
}
return nameToMember;
}
static object ParseObject(Type type, string json)
{
object instance = FormatterServices.GetUninitializedObject(type);
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);
if (elems.Count % 2 != 0)
return instance;
Dictionary<string, FieldInfo> nameToField;
Dictionary<string, PropertyInfo> nameToProperty;
if (!fieldInfoCache.TryGetValue(type, out nameToField))
{
nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
fieldInfoCache.Add(type, nameToField);
}
if (!propertyInfoCache.TryGetValue(type, out nameToProperty))
{
nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
propertyInfoCache.Add(type, nameToProperty);
}
for (int i = 0; i < elems.Count; i += 2)
{
if (elems[i].Length <= 2)
continue;
string key = elems[i].Substring(1, elems[i].Length - 2);
string value = elems[i + 1];
FieldInfo fieldInfo;
PropertyInfo propertyInfo;
if (nameToField.TryGetValue(key, out fieldInfo))
fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value));
else if (nameToProperty.TryGetValue(key, out propertyInfo))
propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null);
}
return instance;
}
}
}

View File

@@ -48,9 +48,9 @@ namespace mpvnet
{ {
switch (value) switch (value)
{ {
case 5: return "SEARCH"; // BROWSER_SEARCH case 5: return "SEARCH"; // BROWSER_SEARCH
case 6: return "FAVORITES"; // BROWSER_FAVORITES case 6: return "FAVORITES"; // BROWSER_FAVORITES
case 7: return "HOMEPAGE"; // BROWSER_HOME case 7: return "HOMEPAGE"; // BROWSER_HOME
case 15: return "MAIL"; // LAUNCH_MAIL case 15: return "MAIL"; // LAUNCH_MAIL
case 33: return "PRINT"; // PRINT case 33: return "PRINT"; // PRINT
case 11: return "NEXT"; // MEDIA_NEXTTRACK case 11: return "NEXT"; // MEDIA_NEXTTRACK
@@ -75,47 +75,69 @@ namespace mpvnet
static string ExePath = Application.ExecutablePath; static string ExePath = Application.ExecutablePath;
static string ExeFilename = Path.GetFileName(Application.ExecutablePath); static string ExeFilename = Path.GetFileName(Application.ExecutablePath);
static string ExeFilenameNoExt = Path.GetFileNameWithoutExtension(Application.ExecutablePath); static string ExeFilenameNoExt = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
static string[] Types;
public static void Register(string[] types) public static void Register(string perceivedType, string[] extensions)
{ {
Types = types; string[] protocols = { "ytdl", "rtsp", "srt", "srtp" };
RegistryHelp.SetValue(@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename, null, ExePath); if (perceivedType != "unreg")
RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename, "FriendlyAppName", "mpv.net media player");
RegistryHelp.SetValue($@"HKCR\Applications\{ExeFilename}\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationDescription", "mpv.net media player");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationName", "mpv.net");
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename, null, "");
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename, null, "");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net", @"SOFTWARE\Clients\Media\mpv.net\Capabilities");
foreach (string ext in Types)
{ {
RegistryHelp.SetValue($@"HKCR\Applications\{ExeFilename}\SupportedTypes", "." + ext, ""); foreach (string i in protocols)
RegistryHelp.SetValue($@"HKCR\" + "." + ext, null, ExeFilenameNoExt + "." + ext); {
RegistryHelp.SetValue($@"HKCR\" + "." + ext + @"\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, ""); RegistryHelp.SetValue($@"HKCR\{i}", $"{i.ToUpper()} Protocol", "");
RegistryHelp.SetValue($@"HKCR\{i}\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
}
if (CorePlayer.VideoTypes.Contains(ext)) RegistryHelp.SetValue(@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename, null, ExePath);
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "video"); RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename, "FriendlyAppName", "mpv.net media player");
RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename + @"\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename, null, "");
RegistryHelp.SetValue(@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename, null, "");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net", @"SOFTWARE\Clients\Media\mpv.net\Capabilities");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationDescription", "mpv.net media player");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities", "ApplicationName", "mpv.net");
if (CorePlayer.AudioTypes.Contains(ext)) foreach (string ext in extensions)
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "audio"); {
RegistryHelp.SetValue(@"HKCR\Applications\" + ExeFilename + @"\SupportedTypes", "." + ext, "");
RegistryHelp.SetValue(@"HKCR\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
RegistryHelp.SetValue(@"HKCR\" + "." + ext + @"\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", perceivedType);
RegistryHelp.SetValue(@"HKCR\" + ExeFilenameNoExt + "." + ext + @"\shell\open\command", null, $"\"{ExePath}\" \"%1\"");
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);
}
}
else
{
foreach (string i in protocols)
RegistryHelp.RemoveKey($@"HKCR\{i}");
if (CorePlayer.ImageTypes.Contains(ext)) RegistryHelp.RemoveKey(@"HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\" + ExeFilename);
RegistryHelp.SetValue(@"HKCR\" + "." + ext, "PerceivedType", "image"); RegistryHelp.RemoveKey(@"HKCR\Applications\" + ExeFilename);
RegistryHelp.RemoveKey(@"HKLM\SOFTWARE\Clients\Media\mpv.net");
RegistryHelp.RemoveKey(@"HKCR\SystemFileAssociations\video\OpenWithList\" + ExeFilename);
RegistryHelp.RemoveKey(@"HKCR\SystemFileAssociations\audio\OpenWithList\" + ExeFilename);
RegistryHelp.RemoveValue(@"HKLM\SOFTWARE\RegisteredApplications", "mpv.net");
RegistryHelp.SetValue($@"HKCR\" + ExeFilenameNoExt + "." + ext + @"\shell\open\command", null, $"\"{ExePath}\" \"%1\""); foreach (string id in Registry.ClassesRoot.GetSubKeyNames())
RegistryHelp.SetValue(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext); {
if (id.StartsWith(ExeFilenameNoExt + "."))
Registry.ClassesRoot.DeleteSubKeyTree(id);
RegistryHelp.RemoveValue($@"HKCR\Software\Classes\{id}\OpenWithProgIDs", ExeFilenameNoExt + id);
RegistryHelp.RemoveValue($@"HKLM\Software\Classes\{id}\OpenWithProgIDs", ExeFilenameNoExt + id);
}
} }
} }
} }
public class MediaTrack public class MediaTrack
{ {
public string Text { get; set; } public int ID { get; set; }
public bool External { get; set; }
public string Text { get; set; } = "";
public string Type { get; set; } public string Type { get; set; }
public int ID { get; set; }
} }
public class CommandItem : INotifyPropertyChanged public class CommandItem : INotifyPropertyChanged
@@ -124,7 +146,19 @@ namespace mpvnet
public string Path { get; set; } = ""; public string Path { get; set; } = "";
public string Command { get; set; } = ""; public string Command { get; set; } = "";
public string Display { get { return string.IsNullOrEmpty(Path) ? Command : Path; } }
public string Display {
get {
if (string.IsNullOrEmpty(Path))
{
if (Command.Length > 47)
return Command.Substring(0, 47) + "...";
return Command;
}
else
return Path;
}
}
public CommandItem() { } public CommandItem() { }
@@ -145,6 +179,14 @@ namespace mpvnet
} }
} }
public string Alias {
get {
if (Input.Contains("SHARP") || Input.Contains("sharp") || Input.Contains("Sharp"))
return "#";
return null;
}
}
public static ObservableCollection<CommandItem> GetItems(string content) public static ObservableCollection<CommandItem> GetItems(string content)
{ {
var items = new ObservableCollection<CommandItem>(); var items = new ObservableCollection<CommandItem>();
@@ -198,7 +240,6 @@ namespace mpvnet
get { get {
if (_Items is null) if (_Items is null)
_Items = GetItems(File.ReadAllText(Core.InputConfPath)); _Items = GetItems(File.ReadAllText(Core.InputConfPath));
return _Items; return _Items;
} }
} }
@@ -208,23 +249,66 @@ namespace mpvnet
{ {
public static string Startup { get; } = Application.StartupPath.AddSep(); public static string Startup { get; } = Application.StartupPath.AddSep();
public static string AppData { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).AddSep(); public static string AppData { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).AddSep();
}
public static string CustomSettings { public class CommandPaletteItem
{
public CommandPaletteItem() {}
public CommandPaletteItem(string text, Action action)
{
Text = text;
Action = action;
}
public CommandPaletteItem(string text, string secondaryText, Action action)
{
Text = text;
Action = action;
SecondaryText = secondaryText;
}
public string Text { get; set; } = "";
public string SecondaryText { get; set; } = "";
public Action Action { get; set; }
public CommandItem CommandItem { get; set; }
}
public class CommandPalette
{
public static CommandPaletteControl Instance { get; } = new CommandPaletteControl();
public static IEnumerable<CommandPaletteItem> GetItems()
{
return CommandItem.Items
.Where(i => i.Command != "")
.Select(i => new CommandPaletteItem() {
Text = i.Display,
SecondaryText = i.Input,
Action = () => Core.Command(i.Command),
CommandItem = i
});
}
}
public class Chapter
{
public string Title { get; set; }
public double Time { get; set; }
string _TimeDisplay;
public string TimeDisplay {
get { get {
string linkFile = Startup + "settings-directory.txt"; if (_TimeDisplay == null)
if (File.Exists(linkFile))
{ {
string linkTarget = File.ReadAllText(linkFile).Trim(); _TimeDisplay = TimeSpan.FromSeconds(Time).ToString();
if (linkTarget.StartsWithEx(".")) if (_TimeDisplay.ContainsEx("."))
linkTarget = Startup + linkTarget; _TimeDisplay = _TimeDisplay.Substring(0, _TimeDisplay.LastIndexOf("."));
if (Directory.Exists(linkTarget))
return linkTarget.AddSep();
} }
return ""; return _TimeDisplay;
} }
} }
} }

View File

@@ -1,41 +1,49 @@
 
using System; using System;
using System.Windows.Forms; using System.Threading;
using System.Windows;
using static mpvnet.Global; using WinForms = System.Windows.Forms;
using MsgBoxEx;
public class Msg public class Msg
{ {
public static void ShowInfo(object title, object content = null) public static void ShowInfo(object msg) => Show(msg, MessageBoxImage.Information);
{
Show(title, content, MessageBoxIcon.Information);
}
public static void ShowError(object title, object content = null) public static void ShowError(object msg) => Show(msg, MessageBoxImage.Error);
{
Show(title, content, MessageBoxIcon.Error);
}
public static void ShowWarning(object title, object content = null) public static void ShowWarning(object msg) => Show(msg, MessageBoxImage.Warning);
{
Show(title, content, MessageBoxIcon.Warning);
}
public static DialogResult ShowQuestion(object title, object content = null, public static MessageBoxResult ShowQuestion(object msg,
MessageBoxButtons buttons = MessageBoxButtons.OKCancel) MessageBoxButton buttons = MessageBoxButton.OKCancel)
{ {
return Show(title, content, MessageBoxIcon.Question, buttons); return Show(msg, MessageBoxImage.Question, buttons);
} }
public static void ShowException(Exception exception) public static void ShowException(Exception exception)
{ {
Show(exception, null, MessageBoxIcon.Error); Show(exception.Message, MessageBoxImage.Error, MessageBoxButton.OK, exception.ToString());
} }
public static DialogResult Show(object title, object content, MessageBoxIcon icon, public static MessageBoxResult Show(
MessageBoxButtons buttons = MessageBoxButtons.OK) object msg,
MessageBoxImage img,
MessageBoxButton buttons = MessageBoxButton.OK,
string details = null)
{ {
string msg = (title?.ToString().TrimEx() + BR2 + content?.ToString().TrimEx()).Trim(); MessageBoxResult fn()
return MessageBox.Show(msg, Application.ProductName, buttons, icon); {
MessageBoxEx.DetailsText = details;
return MessageBoxEx.OpenMessageBox((msg ?? "").ToString().Trim(),
WinForms.Application.ProductName, buttons, img);
}
ApartmentState state = Thread.CurrentThread.GetApartmentState();
if (state == ApartmentState.STA)
return fn();
else
return Application.Current.Dispatcher.Invoke(fn);
} }
} }

1890
src/Misc/Player.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -58,7 +58,7 @@ namespace mpvnet
Pipeline.Output.DataReady += Output_DataReady; Pipeline.Output.DataReady += Output_DataReady;
Pipeline.Error.DataReady += Error_DataReady; Pipeline.Error.DataReady += Error_DataReady;
} }
return Pipeline.Invoke(); return Pipeline.Invoke();
} }
catch (RuntimeException e) catch (RuntimeException e)
@@ -94,7 +94,7 @@ namespace mpvnet
public void Error_DataReady(object sender, EventArgs e) public void Error_DataReady(object sender, EventArgs e)
{ {
var output = sender as PipelineReader<Object>; var output = sender as PipelineReader<object>;
while (output.Count > 0) while (output.Count > 0)
Terminal.WriteError(output.Read(), Module); Terminal.WriteError(output.Read(), Module);
@@ -109,54 +109,59 @@ namespace mpvnet
} }
} }
public void commandv(params string[] args) => Core.commandv(args); public void CommandV(params string[] args) => Core.CommandV(args);
public void command(string command) => Core.command(command); public void Command(string command) => Core.Command(command);
public bool get_property_bool(string name) => Core.get_property_bool(name); public bool GetPropertyBool(string name) => Core.GetPropertyBool(name);
public void set_property_bool(string name, bool value) => Core.set_property_bool(name, value); public void SetPropertyBool(string name, bool value) => Core.SetPropertyBool(name, value);
public int get_property_int(string name) => Core.get_property_int(name); public int GetPropertyInt(string name) => Core.GetPropertyInt(name);
public void set_property_int(string name, int value) => Core.set_property_int(name, value); public void SetPropertyInt(string name, int value) => Core.SetPropertyInt(name, value);
public double get_property_number(string name) => Core.get_property_number(name); public double GetPropertyDouble(string name) => Core.GetPropertyDouble(name);
public void set_property_number(string name, double value) => Core.set_property_number(name, value); public void SetPropertyDouble(string name, double value) => Core.SetPropertyDouble(name, value);
public string get_property_string(string name) => Core.get_property_string(name); public string GetPropertyString(string name) => Core.GetPropertyString(name);
public void set_property_string(string name, string value) => Core.set_property_string(name, value); public void SetPropertyString(string name, string value) => Core.SetPropertyString(name, value);
public void observe_property(string name, string type, ScriptBlock sb) public void ObserveProperty(string name, string type, ScriptBlock sb)
{ {
PropChangedHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb)); PropChangedHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
switch (type) switch (type)
{ {
case "bool": case "boolean": case "bool": case "boolean":
Core.observe_property_bool(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value))); Core.ObservePropertyBool(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
break; break;
case "string": case "string":
Core.observe_property_string(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value))); Core.ObservePropertyString(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
break; break;
case "int": case "integer": case "int": case "integer":
Core.observe_property_int(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value))); Core.ObservePropertyInt(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
break; break;
case "float": case "double": case "float": case "double":
Core.observe_property_double(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value))); Core.ObservePropertyDouble(name, value => App.RunTask(() => PropertyChanged.Invoke(name, value)));
break; break;
case "nil": case "none": case "native": case "nil": case "none": case "native":
Core.observe_property(name, () => App.RunTask(() => PropertyChanged.Invoke(name, null))); Core.ObserveProperty(name, () => App.RunTask(() => PropertyChanged.Invoke(name, null)));
break; break;
default: default:
App.ShowError("Invalid Type", "Valid types are: bool or boolean, string, int or integer, float or double, nil or none or native"); App.ShowError("Invalid Type, valid types are: bool or boolean, string, int or integer, float or double, nil or none or native");
break; break;
} }
} }
public void register_event(string name, ScriptBlock sb) public void RegisterEvent(string name, ScriptBlock sb)
{ {
EventHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb)); EventHandlers.Add(new KeyValuePair<string, ScriptBlock>(name, sb));
@@ -198,10 +203,6 @@ namespace mpvnet
Core.FileLoadedAsync += () => Event.Invoke("file-loaded", null); Core.FileLoadedAsync += () => Event.Invoke("file-loaded", null);
break; break;
case "idle":
Core.IdleAsync += () => Event.Invoke("idle", null);
break;
case "video-reconfig": case "video-reconfig":
Core.VideoReconfigAsync += () => Event.Invoke("video-reconfig", null); Core.VideoReconfigAsync += () => Event.Invoke("video-reconfig", null);
break; break;

View File

@@ -18,27 +18,22 @@ namespace mpvnet
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
if (App.IsStartedFromTerminal) if (App.IsTerminalAttached)
Native.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/); Native.AttachConsole(-1 /*ATTACH_PARENT_PROCESS*/);
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 > 0 && args[0] == "--register-file-associations")
{ {
if (args[1] == "audio") FileAssociation.Register(args[1], args.Skip(1).ToArray());
FileAssociation.Register(CorePlayer.AudioTypes);
else if (args[1] == "video")
FileAssociation.Register(CorePlayer.VideoTypes);
else if (args[1] == "image")
FileAssociation.Register(CorePlayer.ImageTypes);
else
FileAssociation.Register(args.Skip(1).ToArray());
return; return;
} }
App.Init(); App.Init();
Mutex mutex = new Mutex(true, "mpvnetProcessInstance", out bool isFirst); Mutex mutex = new Mutex(true, StringHelp.GetMD5Hash(App.ConfPath), out bool isFirst);
if (Control.ModifierKeys.HasFlag(Keys.Shift))
App.ProcessInstance = "multi";
if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst) if ((App.ProcessInstance == "single" || App.ProcessInstance == "queue") && !isFirst)
{ {
@@ -75,7 +70,7 @@ namespace mpvnet
Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data); Native.SendMessage(proc.MainWindowHandle, 0x004A /*WM_COPYDATA*/, IntPtr.Zero, ref data);
mutex.Dispose(); mutex.Dispose();
if (App.IsStartedFromTerminal) if (App.IsTerminalAttached)
Native.FreeConsole(); Native.FreeConsole();
return; return;
@@ -91,7 +86,7 @@ namespace mpvnet
Application.Run(new MainForm()); Application.Run(new MainForm());
if (App.IsStartedFromTerminal) if (App.IsTerminalAttached)
Native.FreeConsole(); Native.FreeConsole();
mutex.Dispose(); mutex.Dispose();

View File

@@ -14,42 +14,55 @@ namespace mpvnet
[Serializable()] [Serializable()]
public class AppSettings public class AppSettings
{ {
public int LastUpdateCheck; public bool InputDefaultBindingsFixApplied;
public bool ShowMenuFixApplied;
public int Volume = 70; public int Volume = 70;
public List<string> RecentFiles = new List<string>(); public List<string> RecentFiles = new List<string>();
public Point WindowLocation; public Point WindowLocation;
public Point WindowPosition; public Point WindowPosition;
public Size WindowSize; public Size WindowSize;
public string ConfigEditorSearch = ""; public string ConfigEditorSearch = "Video:";
public string Mute = "no"; public string Mute = "no";
public string UpdateCheckVersion = "";
} }
class SettingsManager class SettingsManager
{ {
public static string SettingsFile { public static string SettingsFile => Core.ConfigFolder + "settings.xml";
get => Core.ConfigFolder + "settings.xml";
}
public static AppSettings Load() public static AppSettings Load()
{ {
if (!File.Exists(SettingsFile)) if (!File.Exists(SettingsFile))
return new AppSettings(); return new AppSettings();
XmlSerializer serializer = new XmlSerializer(typeof(AppSettings)); try
{
XmlSerializer serializer = new XmlSerializer(typeof(AppSettings));
using (FileStream fs = new FileStream(SettingsFile, FileMode.Open)) using (FileStream fs = new FileStream(SettingsFile, FileMode.Open))
return (AppSettings)serializer.Deserialize(fs); return (AppSettings)serializer.Deserialize(fs);
}
catch (Exception ex)
{
Terminal.WriteError(ex.ToString());
return new AppSettings();
}
} }
public static void Save(object obj) public static void Save(object obj)
{ {
using (XmlTextWriter writer = new XmlTextWriter(SettingsFile, Encoding.UTF8)) try
{ {
writer.Formatting = Formatting.Indented; using (XmlTextWriter writer = new XmlTextWriter(SettingsFile, Encoding.UTF8))
writer.Indentation = 4; {
XmlSerializer serializer = new XmlSerializer(obj.GetType()); writer.Formatting = Formatting.Indented;
serializer.Serialize(writer, obj); writer.Indentation = 4;
XmlSerializer serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(writer, obj);
}
}
catch (Exception ex)
{
Terminal.WriteError(ex.ToString());
} }
} }
} }

View File

@@ -14,21 +14,20 @@ namespace mpvnet
public static Theme Current { get; set; } public static Theme Current { get; set; }
public Brush Background { get; set; }
public Brush Foreground { get; set; } public Brush Foreground { get; set; }
public Brush Foreground2 { get; set; } public Brush Foreground2 { get; set; }
public Brush Background { get; set; }
public Brush Heading { get; set; } public Brush Heading { get; set; }
public Brush MenuBackground { get; set; }
public System.Drawing.Color GetWinFormsColor(string key) public Brush MenuHighlight { get; set; }
{
return System.Drawing.ColorTranslator.FromHtml(Dictionary[key]);
}
public Brush GetBrush(string key) public Brush GetBrush(string key)
{ {
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key])); return new SolidColorBrush((Color)ColorConverter.ConvertFromString(Dictionary[key]));
} }
public Color GetColor(string key) => (Color)ColorConverter.ConvertFromString(Dictionary[key]);
public static void Init(string customContent, string defaultContent, string activeTheme) public static void Init(string customContent, string defaultContent, string activeTheme)
{ {
Current = null; Current = null;
@@ -67,10 +66,12 @@ namespace mpvnet
if (Current == null) if (Current == null)
Current = DefaultThemes[0]; Current = DefaultThemes[0];
Current.Background = Current.GetBrush("background");
Current.Foreground = Current.GetBrush("foreground"); Current.Foreground = Current.GetBrush("foreground");
Current.Foreground2 = Current.GetBrush("foreground2"); Current.Foreground2 = Current.GetBrush("foreground2");
Current.Background = Current.GetBrush("background");
Current.Heading = Current.GetBrush("heading"); Current.Heading = Current.GetBrush("heading");
Current.MenuBackground = Current.GetBrush("menu-background");
Current.MenuHighlight = Current.GetBrush("menu-highlight");
} }
static List<Theme> Load(string content) static List<Theme> Load(string content)

View File

@@ -1,84 +0,0 @@

using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using static mpvnet.Global;
namespace mpvnet
{
class UpdateCheck
{
public static void DailyCheck()
{
if (App.UpdateCheck && App.Settings.LastUpdateCheck != DateTime.Now.DayOfYear)
CheckOnline();
}
public static async void CheckOnline(bool showUpToDateMessage = false)
{
try
{
using (HttpClient client = new HttpClient())
{
App.Settings.LastUpdateCheck = 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-([\d\.]+)-portable\.zip""");
if (!match.Success)
{
App.ShowError("Update check is currently not available.");
return;
}
Version onlineVersion = Version.Parse(match.Groups[1].Value);
Version currentVersion = Assembly.GetEntryAssembly().GetName().Version;
if (onlineVersion <= currentVersion)
{
if (showUpToDateMessage)
Msg.ShowInfo($"{Application.ProductName} is up to date.");
return;
}
if ((App.Settings.UpdateCheckVersion != onlineVersion.ToString() ||
showUpToDateMessage) && Msg.ShowQuestion(
$"New version {onlineVersion} is available, update now?") == DialogResult.OK)
{
string url = $"https://github.com/stax76/mpv.net/releases/download/{onlineVersion}/mpv.net-{onlineVersion}-portable.zip";
using (Process proc = new Process())
{
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
proc.StartInfo.FileName = "powershell.exe";
proc.StartInfo.Arguments = $"-NoExit -ExecutionPolicy Bypass -File \"{Folder.Startup + "Setup\\update.ps1"}\" \"{url}\" \"{Folder.Startup.TrimEnd(Path.DirectorySeparatorChar)}\"";
if (Folder.Startup.Contains("Program Files"))
proc.StartInfo.Verb = "runas";
proc.Start();
}
Core.command("quit");
}
App.Settings.UpdateCheckVersion = onlineVersion.ToString();
}
}
catch (Exception ex)
{
if (showUpToDateMessage)
App.ShowException(ex);
}
}
}
}

View File

@@ -23,6 +23,12 @@ public class MediaInfo : IDisposable
public int GetCount(MediaInfoStreamKind kind) => MediaInfo_Count_Get(Handle, kind, -1); public int GetCount(MediaInfoStreamKind kind) => MediaInfo_Count_Get(Handle, kind, -1);
public string GetGeneral(string parameter)
{
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.General,
0, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
}
public string GetVideo(int stream, string parameter) public string GetVideo(int stream, string parameter)
{ {
return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video, return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Video,
@@ -41,6 +47,13 @@ public class MediaInfo : IDisposable
stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name)); stream, parameter, MediaInfoKind.Text, MediaInfoKind.Name));
} }
public string GetSummary(bool complete, bool rawView)
{
MediaInfo_Option(Handle, "Language", rawView ? "raw" : "");
MediaInfo_Option(Handle, "Complete", complete ? "1" : "0");
return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, 0)) ?? "";
}
bool Disposed; bool Disposed;
public void Dispose() public void Dispose()

View File

@@ -18,6 +18,12 @@ namespace mpvnet
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string path); public static extern IntPtr LoadLibrary(string path);
[DllImport("user32.dll")]
public static extern uint ActivateKeyboardLayout(IntPtr hkl, uint flags);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[DllImport("user32.dll", CharSet = CharSet.Unicode)] [DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx( public static extern IntPtr FindWindowEx(
IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle); IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
@@ -57,20 +63,65 @@ namespace mpvnet
[DllImport("user32.dll", EntryPoint = "GetWindowLong")] [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex); static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")] [DllImport("user32.dll")]
static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex); static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex) public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
{ {
if (IntPtr.Size == 8) if (IntPtr.Size == 8)
return GetWindowLong64(hWnd, nIndex); return GetWindowLongPtr(hWnd, nIndex);
else else
return GetWindowLong32(hWnd, nIndex); return GetWindowLong32(hWnd, nIndex);
} }
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
public static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, uint dwNewLong);
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong)
{
if (IntPtr.Size == 8)
return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
else
return SetWindowLong32(hWnd, nIndex, dwNewLong);
}
[DllImport("gdi32.dll")] [DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex); public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(
IntPtr hwnd, uint dwAttribute, out RECT pvAttribute, uint cbAttribute);
public static bool GetDwmWindowRect(IntPtr handle, out RECT rect)
{
const uint DWMWA_EXTENDED_FRAME_BOUNDS = 9;
return 0 == DwmGetWindowAttribute(handle, DWMWA_EXTENDED_FRAME_BOUNDS, out rect, (uint)Marshal.SizeOf<RECT>());
}
public static Rectangle GetWorkingArea(IntPtr handle, Rectangle workingArea)
{
if (handle != IntPtr.Zero && GetDwmWindowRect(handle, out RECT dwmRect) &&
GetWindowRect(handle, out RECT rect))
{
int left = workingArea.Left;
int top = workingArea.Top;
int right = workingArea.Right;
int bottom = workingArea.Bottom;
left += rect.Left - dwmRect.Left;
top -= rect.Top - dwmRect.Top;
right -= dwmRect.Right - rect.Right;
bottom -= dwmRect.Bottom - rect.Bottom;
return new Rectangle(left, top, right - left, bottom - top);
}
return workingArea;
}
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct RECT public struct RECT
{ {
@@ -99,6 +150,16 @@ namespace mpvnet
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;
public static RECT FromRectangle(Rectangle rect)
{
return new RECT(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
}
public override string ToString()
{
return "{Left=" + Left + ",Top=" + Top + ",Right=" + Right + ",Bottom=" + Bottom + "}";
}
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]

View File

@@ -5,66 +5,72 @@ using System.Text;
public class libmpv public class libmpv
{ {
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_create(); public static extern IntPtr mpv_create();
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_create_client(IntPtr mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string command);
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_initialize(IntPtr mpvHandle); public static extern mpv_error mpv_initialize(IntPtr mpvHandle);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mpv_destroy(IntPtr mpvHandle);
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error 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("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error 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)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_command_ret(IntPtr mpvHandle, IntPtr strings, IntPtr node); public static extern mpv_error mpv_command_ret(IntPtr mpvHandle, IntPtr strings, IntPtr node);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mpv_free_node_contents(IntPtr node); public static extern void mpv_free_node_contents(IntPtr node);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_error_string(mpv_error error); public static extern IntPtr mpv_error_string(mpv_error error);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
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); 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("libmpv-2.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);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
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("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error 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("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_get_property(IntPtr mpvHandle, byte[] name, mpv_format format, out 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("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error 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("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref long data); public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref long data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data); public static extern mpv_error mpv_set_property(IntPtr mpvHandle, byte[] name, mpv_format format, ref double data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_observe_property(IntPtr mpvHandle, ulong reply_userdata, [MarshalAs(UnmanagedType.LPUTF8Str)] string name, mpv_format format); public static extern mpv_error mpv_observe_property(IntPtr mpvHandle, ulong reply_userdata, [MarshalAs(UnmanagedType.LPUTF8Str)] string name, mpv_format format);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mpv_unobserve_property(IntPtr mpvHandle, ulong registered_reply_userdata); public static extern int mpv_unobserve_property(IntPtr mpvHandle, ulong registered_reply_userdata);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mpv_free(IntPtr data); public static extern void mpv_free(IntPtr data);
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_wait_event(IntPtr mpvHandle, double timeout); public static extern IntPtr mpv_wait_event(IntPtr mpvHandle, double timeout);
[DllImport("libmpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_request_event(IntPtr mpvHandle, mpv_event_id id, int enable);
public enum mpv_error public enum mpv_error
{ {
MPV_ERROR_SUCCESS = 0, MPV_ERROR_SUCCESS = 0,
@@ -101,21 +107,15 @@ public class libmpv
MPV_EVENT_START_FILE = 6, MPV_EVENT_START_FILE = 6,
MPV_EVENT_END_FILE = 7, MPV_EVENT_END_FILE = 7,
MPV_EVENT_FILE_LOADED = 8, MPV_EVENT_FILE_LOADED = 8,
MPV_EVENT_TRACKS_CHANGED = 9, MPV_EVENT_IDLE = 11, //deprecated
MPV_EVENT_TRACK_SWITCHED = 10, MPV_EVENT_TICK = 14, //deprecated
MPV_EVENT_IDLE = 11,
MPV_EVENT_PAUSE = 12,
MPV_EVENT_UNPAUSE = 13,
MPV_EVENT_TICK = 14,
MPV_EVENT_SCRIPT_INPUT_DISPATCH = 15, MPV_EVENT_SCRIPT_INPUT_DISPATCH = 15,
MPV_EVENT_CLIENT_MESSAGE = 16, MPV_EVENT_CLIENT_MESSAGE = 16,
MPV_EVENT_VIDEO_RECONFIG = 17, MPV_EVENT_VIDEO_RECONFIG = 17,
MPV_EVENT_AUDIO_RECONFIG = 18, MPV_EVENT_AUDIO_RECONFIG = 18,
MPV_EVENT_METADATA_UPDATE = 19,
MPV_EVENT_SEEK = 20, MPV_EVENT_SEEK = 20,
MPV_EVENT_PLAYBACK_RESTART = 21, MPV_EVENT_PLAYBACK_RESTART = 21,
MPV_EVENT_PROPERTY_CHANGE = 22, MPV_EVENT_PROPERTY_CHANGE = 22,
MPV_EVENT_CHAPTER_CHANGE = 23,
MPV_EVENT_QUEUE_OVERFLOW = 24, MPV_EVENT_QUEUE_OVERFLOW = 24,
MPV_EVENT_HOOK = 25 MPV_EVENT_HOOK = 25
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="5664FrankSkare.mpv.net"
Publisher="CN=6A1A1E69-736C-4C77-B310-7B6D38E32617"
Version="6.0.4.0" />
<Properties>
<DisplayName>mpv.net</DisplayName>
<PublisherDisplayName>Frank Skare</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="mpv.net"
Description="mpv.net is a modern media player based on the popular mpv player."
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" />
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<uap3:Extension Category="windows.appExecutionAlias">
<uap3:AppExecutionAlias>
<desktop:ExecutionAlias Alias="mpvnet.exe" />
</uap3:AppExecutionAlias>
</uap3:Extension>
<uap:Extension Category="windows.fileTypeAssociation">
<uap:FileTypeAssociation Name="videotypes">
<uap:SupportedFileTypes>
<uap:FileType>.264</uap:FileType>
<uap:FileType>.265</uap:FileType>
<uap:FileType>.asf</uap:FileType>
<uap:FileType>.avc</uap:FileType>
<uap:FileType>.avi</uap:FileType>
<uap:FileType>.avs</uap:FileType>
<uap:FileType>.dav</uap:FileType>
<uap:FileType>.flv</uap:FileType>
<uap:FileType>.h264</uap:FileType>
<uap:FileType>.h265</uap:FileType>
<uap:FileType>.hevc</uap:FileType>
<uap:FileType>.m2t</uap:FileType>
<uap:FileType>.m2ts</uap:FileType>
<uap:FileType>.m2v</uap:FileType>
<uap:FileType>.m4v</uap:FileType>
<uap:FileType>.mkv</uap:FileType>
<uap:FileType>.mov</uap:FileType>
<uap:FileType>.mp4</uap:FileType>
<uap:FileType>.mpeg</uap:FileType>
<uap:FileType>.mpg</uap:FileType>
<uap:FileType>.mpv</uap:FileType>
<uap:FileType>.mts</uap:FileType>
<uap:FileType>.ts</uap:FileType>
<uap:FileType>.vob</uap:FileType>
<uap:FileType>.vpy</uap:FileType>
<uap:FileType>.webm</uap:FileType>
<uap:FileType>.wmv</uap:FileType>
<uap:FileType>.y4m</uap:FileType>
</uap:SupportedFileTypes>
</uap:FileTypeAssociation>
</uap:Extension>
<uap:Extension Category="windows.fileTypeAssociation">
<uap:FileTypeAssociation Name="audiotypes">
<uap:SupportedFileTypes>
<uap:FileType>.aac</uap:FileType>
<uap:FileType>.ac3</uap:FileType>
<uap:FileType>.dts</uap:FileType>
<uap:FileType>.dtshd</uap:FileType>
<uap:FileType>.dtshr</uap:FileType>
<uap:FileType>.dtsma</uap:FileType>
<uap:FileType>.eac3</uap:FileType>
<uap:FileType>.flac</uap:FileType>
<uap:FileType>.m4a</uap:FileType>
<uap:FileType>.mka</uap:FileType>
<uap:FileType>.mp2</uap:FileType>
<uap:FileType>.mp3</uap:FileType>
<uap:FileType>.mpa</uap:FileType>
<uap:FileType>.mpc</uap:FileType>
<uap:FileType>.ogg</uap:FileType>
<uap:FileType>.opus</uap:FileType>
<uap:FileType>.thd</uap:FileType>
<uap:FileType>.w64</uap:FileType>
<uap:FileType>.wav</uap:FileType>
</uap:SupportedFileTypes>
</uap:FileTypeAssociation>
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="ytdl" />
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="rtsp" />
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="srt" />
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="srtp" />
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '15.0'">
<VisualStudioVersion>15.0</VisualStudioVersion>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup>
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
</PropertyGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
<PropertyGroup>
<ProjectGuid>81daee3a-76ff-4494-9384-d28a651d70bb</ProjectGuid>
<TargetPlatformVersion>10.0.22000.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.14393.0</TargetPlatformMinVersion>
<DefaultLanguage>en-US</DefaultLanguage>
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
<EntryPointProjectUniqueName>..\mpv.net.csproj</EntryPointProjectUniqueName>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
<GenerateTemporaryStoreCertificate>True</GenerateTemporaryStoreCertificate>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="..\bin\MediaInfo.dll">
<Link>mpv.net\MediaInfo.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\bin\Microsoft.Management.Infrastructure.dll">
<Link>mpv.net\Microsoft.Management.Infrastructure.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\bin\libmpv-2.dll">
<Link>mpv.net\libmpv-2.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\bin\mpvnet.com">
<Link>mpv.net\mpvnet.com</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Images\SplashScreen.scale-200.png" />
<Content Include="Images\LockScreenLogo.scale-200.png" />
<Content Include="Images\Square150x150Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Images\StoreLogo.png" />
<Content Include="Images\Wide310x150Logo.scale-200.png" />
<None Include="Package.StoreAssociation.xml" />
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.19041.8" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net.csproj" />
</ItemGroup>
</Project>

View File

@@ -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("mpv based media player")] [assembly: AssemblyDescription("mpv based media player for Windows")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("mpv.net/mpv/mplayer")] [assembly: AssemblyCompany("mpv.net/mpv/mplayer")]
[assembly: AssemblyProduct("mpv.net")] [assembly: AssemblyProduct("mpv.net")]
[assembly: AssemblyCopyright("Copyright (C) 2000-2021 mpv.net/mpv/mplayer")] [assembly: AssemblyCopyright("Copyright (C) 2000-2022 mpv.net/mpv/mplayer")]
[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.4.9.0")] [assembly: AssemblyVersion("6.0.4.0")]
[assembly: AssemblyFileVersion("5.4.9.0")] [assembly: AssemblyFileVersion("6.0.4.0")]

View File

@@ -19,7 +19,7 @@ namespace mpvnet.Properties {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
@@ -62,38 +62,39 @@ namespace mpvnet.Properties {
/// <summary> /// <summary>
/// Looks up a localized string similar to /// Looks up a localized string similar to
///[[settings]] ///[setting]
///name = &quot;hwdec&quot; ///name = hwdec
///file = &quot;mpv&quot; ///file = mpv
///default = &quot;no&quot; ///default = no
///filter = &quot;Video&quot; ///filter = Video
///url = &quot;https://mpv.io/manual/master/#options-hwdec&quot; ///url = https://mpv.io/manual/master/#options-hwdec
///help = &quot;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:&quot; ///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 = &quot;no&quot;, help = &quot;always use software decoding&quot; }, ///
/// { name = &quot;auto&quot;, h [rest of string was truncated]&quot;;. ///option = no always use software decoding
///option = auto enable best hw decoder
///option = yes exact [rest of string was truncated]&quot;;.
/// </summary> /// </summary>
internal static string editor_toml { internal static string editor_conf {
get { get {
return ResourceManager.GetString("editor_toml", resourceCulture); return ResourceManager.GetString("editor_conf", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to /// Looks up a localized string similar to
/// # This file defines the key and mouse bindings and the context menu of mpv.net. ///# This file defines the key and mouse bindings and also the context menu of mpv.net.
///
/// # A input and config editor can be found in the context menu under &apos;Settings&apos;.
///
/// # The mpv.conf defaults of mpv.net contain: &apos;input-default-bindings = no&apos;
/// # which disables the input defaults of mpv.
///
/// # Every line in this file begins with a space character to make search easier,
/// # if you want to know if &apos;o&apos; has already a binding you can search for &apos; o &apos;.
/// ///
/// # input test mode: ///# A input and config editor can be found in the context menu under &apos;Settings&apos;.
/// # mpvnet --input-test
/// ///
/// # The [rest of string was truncated]&quot;;. ///# The mpv.conf defaults of mpv.net contain input-default-bindings=yes and
///# input-builtin-bindings=no which disables the input defaults of mpv.
///
///# The input test mode can be started via command line: --input-test
///
///# The input key list can be printed with --input-keylist or
///# shown from the context menu under: View &gt; Show Keys
///
///# m [rest of string was truncated]&quot;;.
/// </summary> /// </summary>
internal static string input_conf { internal static string input_conf {
get { get {
@@ -101,28 +102,6 @@ namespace mpvnet.Properties {
} }
} }
/// <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 = &apos;${filename}&apos;
///script-opts = osc-scalewindowed=1.5,osc-hidetimeout=2000,osc-greenandgrumpy=yes,console-scale=1
///screenshot-directory = &apos;~~desktop/&apos;
///
///[protocol.https]
///osd-playing-msg = &apos;${media-title}&apos;
///.
/// </summary>
internal static string mpv_conf {
get {
return ResourceManager.GetString("mpv_conf", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@@ -151,12 +130,11 @@ namespace mpvnet.Properties {
///foreground = #DDDDDD ///foreground = #DDDDDD
///foreground2 = #AAAAAA ///foreground2 = #AAAAAA
///background = #323232 ///background = #323232
///highlight = #404040
/// ///
///menu-foreground = #DDDDDD ///menu-foreground = #DDDDDD
///menu-background = #323232 ///menu-background = #323232
///menu-highlight = #505050 ///menu-highlight = #505050
///menu-border = #FFFFFF
///menu-checked = #5A5A5A
/// ///
/// ///
///[light] ///[light]
@@ -165,12 +143,11 @@ namespace mpvnet.Properties {
///foreground = #000000 ///foreground = #000000
///foreground2 = #4C4C4C ///foreground2 = #4C4C4C
///background = #F7F7F7 ///background = #F7F7F7
///highlight = #DFDFDF
/// ///
///menu-foreground = #000000 ///menu-foreground = #000000
///menu-background = #DFDFDF ///menu-background = #DFDFDF
///menu-highlight = #BFBFBF ///menu-highlight = #BFBFBF
///menu-border = #6A6A6A
///menu-checked = #AAAAAA
///. ///.
/// </summary> /// </summary>
internal static string theme { internal static string theme {

View File

@@ -118,8 +118,8 @@
<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="editor_toml" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="editor_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\editor.toml.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> <value>..\Resources\editor_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data> </data>
<data name="input_conf" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="input_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\input.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value> <value>..\Resources\input.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
@@ -130,9 +130,6 @@
<data name="mpvnet_santa" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="mpvnet_santa" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\mpvnet-santa.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\mpvnet-santa.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="mpv_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\mpv.conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="theme" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="theme" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\theme.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> <value>..\Resources\theme.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data> </data>

View File

@@ -2,54 +2,18 @@
$tmpDir = 'D:\Work' $tmpDir = 'D:\Work'
$exePath = $PSScriptRoot + '\bin\mpvnet.exe' $exePath = $PSScriptRoot + '\bin\mpvnet.exe'
$versionInfo = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath) $versionInfo = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath)
$inno = 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe'
$7z = 'C:\Program Files\7-Zip\7z.exe' $7z = 'C:\Program Files\7-Zip\7z.exe'
$cloudDirectories = 'C:\Users\frank\OneDrive\Public\mpv.net\', $targetDir = $tmpDir + "\mpv.net-$($versionInfo.FileVersion)-beta"
'C:\Users\frank\Dropbox\Public\mpv.net\' Copy-Item $PSScriptRoot\bin $targetDir -Recurse -Exclude System.Management.Automation.xml
function UploadBeta($sourceFile) $folders = 'Debug', 'Release', 'x64', 'x86', 'Arm'
{
foreach ($cloudDirectory in $cloudDirectories)
{
if (-not (Test-Path $cloudDirectory))
{
throw $cloudDirectory
}
$targetFile = $cloudDirectory + (Split-Path $sourceFile -Leaf) foreach ($folder in $folders) {
Remove-Item (Join-Path $targetDir $folder) -Recurse -ErrorAction SilentlyContinue
if (Test-Path $targetFile)
{
throw $targetFile
}
Copy-Item $sourceFile $targetFile
}
} }
if ($versionInfo.FilePrivatePart -eq 0) & $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
{ if ($LastExitCode) { throw $LastExitCode }
& $inno $PSScriptRoot\setup.iss
if ($LastExitCode) { throw $LastExitCode }
$targetDir = $tmpDir + "\mpv.net-$($versionInfo.FileVersion)-portable"
Copy-Item $PSScriptRoot\bin $targetDir -Recurse -Exclude 'System.Management.Automation.xml', 'settings-directory.txt'
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
if ($LastExitCode) { throw $LastExitCode }
}
else
{
$targetDir = "$tmpDir\mpv.net-$($versionInfo.FileVersion)-portable-beta"
Copy-Item $PSScriptRoot\bin $targetDir -Recurse -Exclude 'System.Management.Automation.xml', 'settings-directory.txt'
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
if ($LastExitCode) { throw $LastExitCode }
UploadBeta "$targetDir.zip"
foreach ($cloudDirectory in $cloudDirectories)
{
Invoke-Item $cloudDirectory
}
}
Write-Host 'successfully finished' -ForegroundColor Green Write-Host 'successfully finished' -ForegroundColor Green

View File

@@ -1,619 +0,0 @@
[[settings]]
name = "hwdec"
file = "mpv"
default = "no"
filter = "Video"
url = "https://mpv.io/manual/master/#options-hwdec"
help = "Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:"
options = [{ name = "no", help = "always use software decoding" },
{ name = "auto", help = "enable best hw decoder (see below)" },
{ name = "yes", help = "exactly the same as auto" },
{ name = "auto-copy", help = "enable best hw decoder with copy-back (see below)" },
{ name = "dxva2", help = "requires vo=gpu with gpu-context=d3d11, gpu-context=angle or gpu-context=dxinterop (Windows only)" },
{ name = "dxva2-copy", help = "copies video back to system RAM (Windows only)" },
{ name = "d3d11va", help = "requires vo=gpu with gpu-context=d3d11 or gpu-context=angle (Windows 8+ only)" },
{ name = "d3d11va-copy", help = "copies video back to system RAM (Windows 8+ only)" },
{ name = "cuda", help = "requires vo=gpu (Any platform CUDA is available)" },
{ name = "cuda-copy", help = "copies video back to system RAM (Any platform CUDA is available)" },
{ name = "nvdec", help = "requires vo=gpu (Any platform CUDA is available)" },
{ name = "nvdec-copy", help = "copies video back to system RAM (Any platform CUDA is available)" },
{ name = "crystalhd", help = "copies video back to system RAM (Any platform supported by hardware)" },
{ name = "rkmpp", help = "requires vo=gpu (some RockChip devices only)" }]
[[settings]]
name = "gpu-api"
file = "mpv"
default = "auto"
filter = "Video"
help = "Controls which type of graphics APIs will be accepted. Auto uses d3d11, it should only be changed in case of problems, Vulkan is not recommended."
options = [{ name = "auto", help = "Use any available API" },
{ name = "opengl", help = "Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)" },
{ name = "vulkan", help = "Allow only Vulkan (not recommended). " },
{ name = "d3d11", help = "Allow only gpu-context=d3d11" }]
[[settings]]
name = "gpu-context"
file = "mpv"
default = "auto"
filter = "Video"
options = [{ name = "auto", help = "auto-select" },
{ name = "win", help = "Win32/WGL" },
{ name = "winvk", help = "VK_KHR_win32_surface" },
{ name = "angle", help = "Direct3D11 through the OpenGL ES translation layer ANGLE. This supports almost everything the win backend does (if the ANGLE build is new enough)." },
{ name = "dxinterop", help = "(experimental) Win32, using WGL for rendering and Direct3D 9Ex for presentation. Works on Nvidia and AMD. Newer Intel chips with the latest drivers may also work." },
{ name = "d3d11", help = "Win32, with native Direct3D 11 rendering." }]
[[settings]]
name = "vo"
file = "mpv"
default = "gpu"
filter = "Video"
help = "Video output drivers to be used.\n\nFor more information visit:"
url = "https://mpv.io/manual/master/#video-output-drivers-vo"
options = [{ name = "gpu", help = "General purpose, customizable, GPU-accelerated video output driver. It supports extended scaling methods, dithering, color management, custom shaders, HDR, and more." },
{ name = "direct3d", help = "Video output driver that uses the Direct3D interface" }]
[[settings]]
name = "video-sync"
file = "mpv"
default = "audio"
filter = "Video"
help = "How the player synchronizes audio and video.\n\nFor more information visit:"
url = "https://mpv.io/manual/master/#options-video-sync"
options = [{ name = "audio" },
{ name = "display-resample" },
{ name = "display-resample-vdrop" },
{ name = "display-resample-desync" },
{ name = "display-vdrop" },
{ name = "display-adrop" },
{ name = "display-desync" },
{ name = "desync" }]
[[settings]]
name = "scale"
file = "mpv"
default = "bilinear"
filter = "Video"
help = "The GPU renderer filter function to use when upscaling video. There are some more filters, but most are not as useful. For a complete list, pass help as value, e.g.: mpv --scale=help"
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
{ name = "ewa_lanczossharp", help = "A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default." },
{ name = "mitchell", help = "Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale)." },
{ name = "oversample", help = "A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as \"smoothmotion\" (see tscale)." },
{ name = "linear", help = "A tscale filter." }]
[[settings]]
name = "cscale"
file = "mpv"
default = "bilinear"
filter = "Video"
help = "As scale, but for interpolating chroma information. If the image is not subsampled, this option is ignored entirely."
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
{ name = "ewa_lanczossharp", help = "A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default." },
{ name = "mitchell", help = "Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale)." },
{ name = "oversample", help = "A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as \"smoothmotion\" (see tscale)." },
{ name = "linear", help = "A tscale filter." }]
[[settings]]
name = "dscale"
file = "mpv"
default = "bilinear"
filter = "Video"
help = "Like scale, but apply these filters on downscaling instead. If this option is unset, the filter implied by scale will be applied."
options = [{ name = "bilinear", help = "Bilinear hardware texture filtering (fastest, very low quality)." },
{ name = "spline36", help = "Mid quality and speed. This is the default when using gpu-hq." },
{ name = "lanczos", help = "Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)" },
{ name = "ewa_lanczos", help = "Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)" },
{ name = "ewa_lanczossharp", help = "A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default." },
{ name = "mitchell", help = "Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale)." },
{ name = "oversample", help = "A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as \"smoothmotion\" (see tscale)." },
{ name = "linear", help = "A tscale filter." }]
[[settings]]
name = "dither-depth"
file = "mpv"
default = "no"
filter = "Video"
help = "Set dither target depth to N. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output."
options = [{ name = "no", help = "Disable any dithering done by mpv." },
{ name = "auto", help = "Automatic selection. If output bit depth cannot be detected, 8 bits per component are assumed." },
{ name = "8", help = "Dither to 8 bit output." }]
[[settings]]
name = "correct-downscaling"
file = "mpv"
default = "no"
filter = "Video"
help = "When using convolution based filters, extend the filter size when downscaling. Increases quality, but reduces performance while downscaling.\n\nThis will perform slightly sub-optimally for anamorphic video (but still better than without it) since it will extend the size to match only the milder of the scale factors between the axes."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "sigmoid-upscaling"
file = "mpv"
default = "no"
filter = "Video"
help = "When upscaling, use a sigmoidal color transform to avoid emphasizing ringing artifacts. This also implies linear-scaling."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "deband"
file = "mpv"
default = "no"
filter = "Video"
help = "Enable the debanding algorithm. This greatly reduces the amount of visible banding, blocking and other quantization artifacts, at the expense of very slightly blurring some of the finest details. In practice, it's virtually always an improvement - the only reason to disable it would be for performance."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "d3d11va-zero-copy"
file = "mpv"
default = "no"
filter = "Video"
help = "By default, when using hardware decoding with --gpu-api=d3d11, the video image will be copied (GPU-to-GPU) from the decoder surface to a shader resource. Set this option to avoid that copy by sampling directly from the decoder image. This may increase performance and reduce power usage, but can cause the image to be sampled incorrectly on the bottom and right edges due to padding, and may invoke driver bugs, since Direct3D 11 technically does not allow sampling from a decoder surface (though most drivers support it.)"
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "hdr-compute-peak"
file = "mpv"
default = "auto"
filter = "Video"
help = "Compute the HDR peak and frame average brightness per-frame instead of relying on tagged metadata. These values are averaged over local regions as well as over several frames to prevent the value from jittering around too much. This option basically gives you dynamic, per-scene tone mapping. Requires compute shaders, which is a fairly recent OpenGL feature, and will probably also perform horribly on some drivers, so enable at your own risk. The special value auto (default) will enable HDR peak computation automatically if compute shaders and SSBOs are supported."
options = [{ name = "auto" },
{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "volume"
file = "mpv"
filter = "Audio"
help = "Set the startup volume. 0 means silence, 100 means no volume reduction or amplification. Negative values can be passed for compatibility, but are treated as 0. Since mpv 0.18.1, this always controls the internal mixer (aka \"softvol\"). Default: 100"
[[settings]]
name = "remember-volume"
file = "mpvnet"
default = "yes"
filter = "Audio"
help = "Save volume and mute on exit and restore it on start. (mpv.net specific setting)"
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "alang"
file = "mpv"
filter = "Audio"
type = "string"
help = "Specify a priority list of audio languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two-letter language codes, Matroska, MPEG-TS and NUT use ISO 639-2 three-letter language codes, while OGM uses a free-form identifier. See also aid.\n\nExamples\n\nmpv dvd://1 alang=hu,en chooses the Hungarian language track on a DVD and falls back on English if Hungarian is not available.\n\nmpv alang=jpn example.mkv plays a Matroska file with Japanese audio."
[[settings]]
name = "audio-file-auto"
file = "mpv"
default = "no"
filter = "Audio"
help = "Load additional audio files matching the video filename. The parameter specifies how external audio files are matched."
options = [{ name = "no", help = "Don't automatically load external audio files." },
{ name = "exact", help = "Load the media filename with audio file extension." },
{ name = "fuzzy", help = "Load all audio files containing media filename." },
{ name = "all", help = "Load all audio files in the current and audio-file-paths directories." }]
[[settings]]
name = "audio-device"
file = "mpv"
filter = "Audio"
type = "string"
url = "https://mpv.io/manual/master/#options-audio-device"
help = "<name> Use the given audio device. This consists of the audio output name, e.g. alsa, followed by /, followed by the audio output specific device name. The default value for this option is auto, which tries every audio output in preference order with the default device.\nAvailable devices can be found in the mpv.net context menu under:\nView > Show Audio Devices"
[[settings]]
name = "slang"
file = "mpv"
filter = "Subtitle"
type = "string"
help = "Specify a priority list of subtitle languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two letter language codes, Matroska uses ISO 639-2 three letter language codes while OGM uses a free-form identifier. See also sid."
[[settings]]
name = "sub-auto"
file = "mpv"
default = "exact"
filter = "Subtitle"
help = "Load additional subtitle files matching the video filename. The parameter specifies how external subtitle files are matched. exact is enabled by default."
options = [{ name = "no", help = "Don't automatically load external subtitle files." },
{ name = "exact", help = "Load the media filename with subtitle file extension." },
{ name = "fuzzy", help = "Load all subs containing media filename." },
{ name = "all", help = "Load all subs in the current and sub-file-paths directories." }]
[[settings]]
name = "sub-font"
file = "mpv"
filter = "Subtitle"
type = "string"
help = "Specify font to use for subtitles that do not themselves specify a particular font. The default is sans-serif."
[[settings]]
name = "sub-font-size"
file = "mpv"
filter = "Subtitle"
help = "Specify the sub font size. The unit is the size in scaled pixels at a window height of 720. The actual pixel size is scaled with the window height: if the window height is larger or smaller than 720, the actual size of the text increases or decreases as well. Default: 55"
[[settings]]
name = "sub-color"
file = "mpv"
type = "color"
filter = "Subtitle"
help = "Specify the color used for unstyled text subtitles.\n\nThe color is specified in the form r/g/b, where each color component is specified as number in the range 0.0 to 1.0. It's also possible to specify the transparency by using r/g/b/a, where the alpha value 0 means fully transparent, and 1.0 means opaque. If the alpha component is not given, the color is 100% opaque.\n\nPassing a single number to the option sets the sub to gray, and the form gray/a lets you specify alpha additionally.\n\nExamples\n\n1.0/0.0/0.0 set sub to opaque red\n1.0/0.0/0.0/0.75 set sub to opaque red with 75% alpha\n0.5/0.75 set sub to 50% gray with 75% alpha\n\nAlternatively, the color can be specified as a RGB hex triplet in the form #RRGGBB, where each 2-digit group expresses a color value in the range 0 (00) to 255 (FF). For example, #FF0000 is red. This is similar to web colors. Alpha is given with #AARRGGBB.\n\nExamples\n\n#FF0000 set sub to opaque red\n#C0808080 set sub to 50% gray with 75% alpha"
[[settings]]
name = "sub-border-color"
file = "mpv"
type = "color"
filter = "Subtitle"
help = "See sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent)."
[[settings]]
name = "sub-back-color"
file = "mpv"
type = "color"
filter = "Subtitle"
help = "See sub-color. Color used for sub text background. You can use sub-shadow-offset to change its size relative to the text."
[[settings]]
name = "fullscreen"
file = "mpv"
default = "no"
filter = "Screen"
help = "Start the player in fullscreen mode."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "border"
file = "mpv"
default = "yes"
filter = "Screen"
help = "Show window with decoration (titlebar, border)."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "screen"
file = "mpv"
filter = "Screen"
help = "<0-32> In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on."
[[settings]]
name = "osd-playing-msg"
file = "mpv"
width = 300
filter = "Screen"
type = "string"
help = "Show a message on OSD when playback starts. The string is expanded for properties, e.g. osd-playing-msg='file: ${filename}' will show the message file: followed by a space and the currently played filename. For more information visit:"
url = "https://mpv.io/manual/master/#property-expansion"
[[settings]]
name = "osd-font-size"
file = "mpv"
filter = "Screen"
help = "Specify the OSD font size. See sub-font-size for details. Default: 55"
[[settings]]
name = "osd-duration"
file = "mpv"
filter = "Screen"
help = "Set the duration of the OSD messages in ms. Default: 1000"
[[settings]]
name = "osd-scale-by-window"
file = "mpv"
default = "yes"
filter = "Screen"
help = "Whether to scale the OSD with the window size. If this is disabled, osd-font-size and other OSD options that use scaled pixels are always in actual pixels. The effect is that changing the window size won't change the OSD font size."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "autofit"
file = "mpv"
filter = "Screen"
help = "<int> Initial window height in percent. Default: 60"
[[settings]]
name = "autofit-smaller"
file = "mpv"
filter = "Screen"
help = "<int> Minimum window height in percent. Default: 10"
[[settings]]
name = "autofit-larger"
file = "mpv"
filter = "Screen"
help = "<int> Maximum window height in percent. Default: 80"
[[settings]]
name = "start-size"
file = "mpvnet"
default = "height-session"
filter = "Screen"
help = "Setting to remember the window size. (mpv.net specific setting)"
options = [{ name = "video", help = "Window size is set to video resolution" },
{ name = "width-session", help = "Width is remembered in the current session" },
{ name = "width-always", help = "Width is always remembered" },
{ name = "height-session", help = "Height is remembered in the current session" },
{ name = "height-always", help = "Height is always remembered" },
{ name = "always", help = "Size is always remembered" }]
[[settings]]
name = "start-threshold"
file = "mpvnet"
filter = "Screen"
help = "Threshold in milliseconds to wait for libmpv returning the video resolution before the window is shown, otherwise default dimensions are used as defined by autofit and start-size. Default: 1500 (mpv.net specific setting)"
[[settings]]
name = "minimum-aspect-ratio"
file = "mpvnet"
filter = "Screen"
help = "<float> Minimum aspect ratio, if the AR is smaller than the defined value then the window AR is set to 16/9. This avoids a square window for Music with cover art. Default: 1.2 (mpv.net specific setting)"
[[settings]]
name = "remember-window-position"
file = "mpvnet"
default = "no"
filter = "Screen"
help = "Save the window position on exit. (mpv.net specific setting)"
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "window-maximized"
file = "mpv"
default = "no"
filter = "Screen"
help = "Start with a maximized window."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "screenshot-directory"
file = "mpv"
width = 500
type = "folder"
filter = "Screen"
help = "Store screenshots in this directory. This path is joined with the filename generated by screenshot-template. If the template filename is already absolute, the directory is ignored.\n\nIf the directory does not exist, it is created on the first screenshot. If it is not a directory, an error is generated when trying to write a screenshot."
[[settings]]
name = "screenshot-format"
file = "mpv"
default = "jpg"
filter = "Screen"
help = "Set the image file type used for saving screenshots."
options = [{ name = "jpg" },
{ name = "png" }]
[[settings]]
name = "screenshot-tag-colorspace"
file = "mpv"
default = "no"
filter = "Screen"
help = "Tag screenshots with the appropriate colorspace. Note that not all formats are supported."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "screenshot-high-bit-depth"
file = "mpv"
default = "yes"
filter = "Screen"
help = "If possible, write screenshots with a bit depth similar to the source video. This is interesting in particular for PNG, as this sometimes triggers writing 16 bit PNGs with huge file sizes. This will also include an unused alpha channel in the resulting files if 16 bit is used."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "screenshot-jpeg-source-chroma"
file = "mpv"
default = "yes"
filter = "Screen"
help = "Write JPEG files with the same chroma subsampling as the video. If disabled, the libjpeg default is used."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "screenshot-template"
file = "mpv"
filter = "Screen"
type = "string"
help = "Specify the filename template used to save screenshots. The template specifies the filename without file extension, and can contain format specifiers, which will be substituted when taking a screenshot. By default, the template is mpv-shot%n, which results in filenames like mpv-shot0012.png for example.\n\nFind the full documentation here:"
url = "https://mpv.io/manual/master/#options-screenshot-template"
[[settings]]
name = "screenshot-jpeg-quality"
file = "mpv"
filter = "Screen"
help = "<0-100> Set the JPEG quality level. Higher means better quality. The default is 90."
[[settings]]
name = "screenshot-png-compression"
file = "mpv"
filter = "Screen"
help = "<0-9> Set the PNG compression level. Higher means better compression. This will affect the file size of the written screenshot file and the time it takes to write a screenshot. Too high compression might occupy enough CPU time to interrupt playback. The default is 7."
[[settings]]
name = "screenshot-png-filter"
file = "mpv"
filter = "Screen"
help = "<0-5> Set the filter applied prior to PNG compression. 0 is none, 1 is 'sub', 2 is 'up', 3 is 'average', 4 is 'Paeth', and 5 is 'mixed'. This affects the level of compression that can be achieved. For most images, 'mixed' achieves the best compression ratio, hence it is the default."
[[settings]]
name = "taskbar-progress"
file = "mpv"
default = "yes"
filter = "Playback"
help = "Show progress in taskbar."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "keep-open-pause"
file = "mpv"
default = "yes"
filter = "Playback"
help = "If set to no, instead of pausing when keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "keep-open"
file = "mpv"
default = "no"
filter = "Playback"
help = "Using no, mpv would terminate after the last file but mpv.net never terminates automatically."
options = [{ name = "yes", help = "If the current file ends, go to the next file, keep the last file open."},
{ name = "no", help = "If the current file ends, go to the next file." },
{ name = "always", help = "Playback will never automatically advance to the next file."}]
[[settings]]
name = "loop-file"
file = "mpv"
filter = "Playback"
help = "<N|inf|no> Loop a single file N times. inf means forever, no means normal playback.\n\nThe difference to loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file. loop is an alias for this option."
[[settings]]
name = "save-position-on-quit"
file = "mpv"
default = "no"
filter = "Playback"
help = "Always save the current playback position on quit. When this file is played again later, the player will seek to the old playback position on start. This does not happen if playback of a file is stopped in any other way than quitting. For example, going to the next file in the playlist will not save the position, and start playback at beginning the next time the file is played.\n\nThis behavior is disabled by default, but is always available when quitting the player with Shift+Q."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "hr-seek"
file = "mpv"
default = "absolute"
filter = "Playback"
help = "Select when to use precise seeks that are not limited to keyframes. Such seeks require decoding video from the previous keyframe up to the target position and so can take some time depending on decoding performance. For some video formats, precise seeks are disabled. This option selects the default choice to use for seeks; it is possible to explicitly override that default in the definition of key bindings and in input commands."
options = [{ name = "yes", help = "Use precise seeks whenever possible." },
{ name = "no", help = "Never use precise seeks." },
{ name = "absolute", help = "Use precise seeks if the seek is to an absolute position in the file, such as a chapter seek, but not for relative seeks like the default behavior of arrow keys." },
{ name = "always", help = "Same as yes (for compatibility)." }]
[[settings]]
name = "track-auto-selection"
file = "mpv"
default = "yes"
filter = "Playback"
help = "Enable the default track auto-selection. Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected."
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "loop-playlist"
file = "mpv"
filter = "Playback"
help = "<N|inf|force|no> Loops playback N times. A value of 1 plays it one time (default), 2 two times, etc. inf means forever. no is the same as 1 and disables looping. If several files are specified on command line, the entire playlist is looped. The force mode is like inf, but does not skip playlist entries which have been marked as failing. This means the player might waste CPU time trying to loop a file that doesn't exist. But it might be useful for playing webradios under very bad network conditions."
[[settings]]
name = "auto-load-folder"
file = "mpvnet"
default = "yes"
filter = "Playback"
help = "For single files automatically load the entire directory into the playlist. Can be suppressed via shift key. (mpv.net specific setting)"
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "input-ar-delay"
file = "mpv"
filter = "Input"
help = "Delay in milliseconds before we start to autorepeat a key (0 to disable)."
[[settings]]
name = "input-ar-rate"
file = "mpv"
filter = "Input"
help = "Number of key presses to generate per second on autorepeat."
[[settings]]
name = "update-check"
file = "mpvnet"
default = "no"
filter = "General"
help = "Daily check for new version. (requires PowerShell 5 and curl. mpv.net specific setting)"
options = [{ name = "yes" },
{ name = "no" }]
[[settings]]
name = "process-instance"
file = "mpvnet"
default = "single"
filter = "General"
help = "Defines if more then one mpv.net process is allowed. (mpv.net specific setting)\n\nTip: Whenever the control key is pressed when files or URLs are opened, the playlist is not cleared but the files or URLs are appended to the playlist. This not only works on process startup but in all mpv.net features that open files and URLs."
options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" },
{ name = "single", help = "Force a single process everytime the shell starts mpv.net" },
{ name = "queue", help = "Force a single process and add files to playlist" }]
[[settings]]
name = "recent-count"
file = "mpvnet"
filter = "General"
help = "<int> Amount of recent files to be remembered. Default: 15 (mpv.net specific setting)"
[[settings]]
name = "video-file-extensions"
file = "mpvnet"
filter = "General"
width = 500
help = "Video file extensions used to create file associations and used by the auto-load-folder feature. (mpv.net specific setting)"
[[settings]]
name = "audio-file-extensions"
file = "mpvnet"
filter = "General"
width = 500
help = "Audio file extensions used to create file associations and used by the auto-load-folder feature. (mpv.net specific setting)"
[[settings]]
name = "image-file-extensions"
file = "mpvnet"
filter = "General"
width = 500
help = "Image file extensions used to create file associations and used by the auto-load-folder feature. (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/docs/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/docs/Manual.md#color-theme"
help = "Color theme used in light mode. Default: light"

View File

@@ -0,0 +1,646 @@
name = process-instance
file = mpvnet
default = single
filter = General
help = Defines if more then one mpv.net process is allowed. (mpv.net specific option)\n\nMulti can alternatively be enabled by pressing the SHIFT key.\n\nWhenever 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.
option = multi Create a new process everytime the shell starts mpv.net
option = single Force a single process everytime the shell starts mpv.net
option = queue Force a single process and add files to playlist
name = recent-count
file = mpvnet
filter = General
help = <int> Amount of recent files to be remembered. Default: 15 (mpv.net specific option)
name = media-info
file = mpvnet
default = yes
filter = General
help = Usage of the media info library instead of mpv to access media information. (mpv.net specific option)
option = yes
option = no
name = history-filter
file = mpvnet
filter = General
width = 500
help = Semicolon separated list of paths to be excluded from the history log feature.
name = video-file-extensions
file = mpvnet
filter = General
width = 500
help = Video file extensions used to create file associations and used by the auto-load-folder feature. (mpv.net specific option)
name = audio-file-extensions
file = mpvnet
filter = General
width = 500
help = Audio file extensions used to create file associations and used by the auto-load-folder feature. (mpv.net specific option)
name = image-file-extensions
file = mpvnet
filter = General
width = 500
help = Image file extensions used to create file associations and used by the auto-load-folder feature. (mpv.net specific option)
name = debug-mode
file = mpvnet
default = no
filter = General
help = Enable this only when a developer asks for it. (mpv.net specific option)
option = yes
option = no
name = vo
file = mpv
default = gpu
filter = Video
help = Video output drivers to be used.\n\nFor more information visit:
url = https://mpv.io/manual/master/#video-output-drivers-vo
option = gpu General purpose, customizable, GPU-accelerated video output driver. It supports extended scaling methods, dithering, color management, custom shaders, HDR, and more.
option = gpu-next Experimental video renderer based on libplacebo. This supports almost the same set of features as --vo=gpu.
option = direct3d Video output driver that uses the Direct3D interface.
name = hwdec
file = mpv
default = no
filter = Video
url = https://mpv.io/manual/master/#options-hwdec
help = Specify the hardware video decoding API that should be used if possible. Whether hardware decoding is actually done depends on the video codec. If hardware decoding is not possible, mpv will fall back on software decoding.\n\nFor more information visit:
option = no always use software decoding
option = auto enable best hw decoder
option = yes exactly the same as auto
option = auto-copy enable best hw decoder with copy-back
option = auto-safe enable any whitelisted hw decoder
option = dxva2 requires vo=gpu with gpu-context=d3d11, gpu-context=angle or gpu-context=dxinterop (Windows only)
option = dxva2-copy copies video back to system RAM (Windows only)
option = d3d11va requires vo=gpu with gpu-context=d3d11 or gpu-context=angle (Windows 8+ only)
option = d3d11va-copy copies video back to system RAM (Windows 8+ only)
option = cuda requires vo=gpu (Any platform CUDA is available)
option = cuda-copy copies video back to system RAM (Any platform CUDA is available)
option = nvdec requires vo=gpu (Any platform CUDA is available)
option = nvdec-copy copies video back to system RAM (Any platform CUDA is available)
name = gpu-api
file = mpv
default = auto
filter = Video
help = Controls which type of graphics APIs will be accepted. Auto uses d3d11, it should only be changed in case of problems, Vulkan is not recommended.
option = auto Use any available API
option = d3d11 Allow only gpu-context=d3d11
option = opengl Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)
option = vulkan Allow only Vulkan
name = gpu-context
file = mpv
default = auto
filter = Video
option = auto auto-select
option = d3d11 Win32, with native Direct3D 11 rendering.
option = angle Direct3D11 through the OpenGL ES translation layer ANGLE. This supports almost everything the win backend does (if the ANGLE build is new enough).
option = win Win32/WGL
option = dxinterop (experimental) Win32, using WGL for rendering and Direct3D 9Ex for presentation. Works on Nvidia and AMD. Newer Intel chips with the latest drivers may also work.
option = winvk VK_KHR_win32_surface
name = video-sync
file = mpv
default = audio
filter = Video
help = How the player synchronizes audio and video.\n\nFor more information visit:
url = https://mpv.io/manual/master/#options-video-sync
option = audio
option = display-resample
option = display-resample-vdrop
option = display-resample-desync
option = display-vdrop
option = display-adrop
option = display-desync
option = desync
name = scale
file = mpv
default = bilinear
filter = Video
help = The GPU renderer filter function to use when upscaling video. There are some more filters, but most are not as useful. For a complete list, pass help as value, e.g.: mpv --scale=help
option = bilinear Bilinear hardware texture filtering (fastest, very low quality).
option = spline36 Mid quality and speed. This is the default when using gpu-hq.
option = lanczos Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)
option = ewa_lanczos Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)
option = ewa_lanczossharp A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default.
option = mitchell Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale).
option = oversample A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as "smoothmotion" (see tscale).
name = cscale
file = mpv
default = bilinear
filter = Video
help = As scale, but for interpolating chroma information. If the image is not subsampled, this option is ignored entirely.
option = bilinear Bilinear hardware texture filtering (fastest, very low quality).
option = spline36 Mid quality and speed. This is the default when using gpu-hq.
option = lanczos Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)
option = ewa_lanczos Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)
option = ewa_lanczossharp A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default.
option = mitchell Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale).
option = oversample A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as "smoothmotion" (see tscale).
name = dscale
file = mpv
default =
filter = Video
help = Like scale, but apply these filters on downscaling instead. \nIf no option is selected, it will keep the same with the upscaler.
option = bilinear Bilinear hardware texture filtering (fastest, very low quality).
option = spline36 Mid quality and speed. This is the default when using gpu-hq.
option = lanczos Lanczos scaling. Provides mid quality and speed. Generally worse than spline36, but it results in a slightly sharper image which is good for some content types. The number of taps can be controlled with scale-radius, but is best left unchanged. (This filter is an alias for sinc-windowed sinc)
option = ewa_lanczos Elliptic weighted average Lanczos scaling. Also known as Jinc. Relatively slow, but very good quality. The radius can be controlled with scale-radius. Increasing the radius makes the filter sharper but adds more ringing. (This filter is an alias for jinc-windowed jinc)
option = ewa_lanczossharp A slightly sharpened version of ewa_lanczos, preconfigured to use an ideal radius and parameter. If your hardware can run it, this is probably what you should use by default.
option = mitchell Mitchell-Netravali. The B and C parameters can be set with scale-param1 and scale-param2. This filter is very good at downscaling (see dscale).
option = oversample A version of nearest neighbour that (naively) oversamples pixels, so that pixels overlapping edges get linearly interpolated instead of rounded. This essentially removes the small imperfections and judder artifacts caused by nearest-neighbour interpolation, in exchange for adding some blur. This filter is good at temporal interpolation, and also known as "smoothmotion" (see tscale).
name = dither-depth
file = mpv
default = no
filter = Video
help = Set dither target depth to N. Note that the depth of the connected video display device cannot be detected. Often, LCD panels will do dithering on their own, which conflicts with this option and leads to ugly output.
option = no Disable any dithering done by mpv.
option = auto Automatic selection. If output bit depth cannot be detected, 8 bits per component are assumed.
option = 8 Dither to 8 bit output.
option = 10 Dither to 10 bit output.
name = correct-downscaling
file = mpv
default = no
filter = Video
help = When using convolution based filters, extend the filter size when downscaling. Increases quality, but reduces performance while downscaling.\n\nThis will perform slightly sub-optimally for anamorphic video (but still better than without it) since it will extend the size to match only the milder of the scale factors between the axes.
option = yes
option = no
name = sigmoid-upscaling
file = mpv
default = no
filter = Video
help = When upscaling, use a sigmoidal color transform to avoid emphasizing ringing artifacts. This also implies linear-scaling.
option = yes
option = no
name = deband
file = mpv
default = no
filter = Video
help = Enable the debanding algorithm. This greatly reduces the amount of visible banding, blocking and other quantization artifacts, at the expense of very slightly blurring some of the finest details. In practice, it's virtually always an improvement - the only reason to disable it would be for performance.
option = yes
option = no
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.)
option = yes
option = no
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.
option = auto
option = yes
option = no
name = allow-delayed-peak-detect
file = mpv
default = yes
filter = Video
help = When using --hdr-compute-peak, allow delaying the detected peak by a frame when beneficial for performance. In particular, this is required to avoid an unnecessary FBO indirection when no advanced rendering is required otherwise. Has no effect if there already is an indirect pass, such as when advanced scaling is enabled. (Only affects --vo=gpu-next, note that --vo=gpu always delays the peak.)
option = yes
option = no
name = volume
file = mpv
filter = Audio
help = Set the startup volume. 0 means silence, 100 means no volume reduction or amplification. Negative values can be passed for compatibility, but are treated as 0. Since mpv 0.18.1, this always controls the internal mixer (aka "softvol"). Default: 100
name = remember-volume
file = mpvnet
default = yes
filter = Audio
help = Save volume and mute on exit and restore it on start. (mpv.net specific option)
option = yes
option = no
name = alang
file = mpv
filter = Audio
type = string
help = Specify a priority list of audio languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two-letter language codes, Matroska, MPEG-TS and NUT use ISO 639-2 three-letter language codes, while OGM uses a free-form identifier. See also aid.\n\nExamples\n\nmpv dvd://1 alang=hu,en chooses the Hungarian language track on a DVD and falls back on English if Hungarian is not available.\n\nmpv alang=jpn example.mkv plays a Matroska file with Japanese audio.
name = audio-file-auto
file = mpv
default = no
filter = Audio
help = Load additional audio files matching the video filename. The parameter specifies how external audio files are matched.
option = no Don't automatically load external audio files.
option = exact Load the media filename with audio file extension.
option = fuzzy Load all audio files containing media filename.
option = all Load all audio files in the current and audio-file-paths directories.
name = audio-device
file = mpv
filter = Audio
type = string
url = https://mpv.io/manual/master/#options-audio-device
help = <name> Use the given audio device. This consists of the audio output name, e.g. alsa, followed by /, followed by the audio output specific device name. The default value for this option is auto, which tries every audio output in preference order with the default device.\nAvailable devices can be found in the context menu under:\nView > Advanced > Show Audio Devices
name = slang
file = mpv
filter = Subtitle
type = string
help = Specify a priority list of subtitle languages to use. Different container formats employ different language codes. DVDs use ISO 639-1 two letter language codes, Matroska uses ISO 639-2 three letter language codes while OGM uses a free-form identifier. See also sid.
name = sub-auto
file = mpv
default = exact
filter = Subtitle
help = Load additional subtitle files matching the video filename. The parameter specifies how external subtitle files are matched. exact is enabled by default.
option = no Don't automatically load external subtitle files.
option = exact Load the media filename with subtitle file extension.
option = fuzzy Load all subs containing media filename.
option = all Load all subs in the current and sub-file-paths directories.
name = sub-font
file = mpv
filter = Subtitle
type = string
help = Specify font to use for subtitles that do not themselves specify a particular font. The default is sans-serif.
name = sub-font-size
file = mpv
filter = Subtitle
help = Specify the sub font size. The unit is the size in scaled pixels at a window height of 720. The actual pixel size is scaled with the window height: if the window height is larger or smaller than 720, the actual size of the text increases or decreases as well. Default: 55
name = sub-color
file = mpv
type = color
filter = Subtitle
help = Specify the color used for unstyled text subtitles.\n\nThe color is specified in the form r/g/b, where each color component is specified as number in the range 0.0 to 1.0. It's also possible to specify the transparency by using r/g/b/a, where the alpha value 0 means fully transparent, and 1.0 means opaque. If the alpha component is not given, the color is 100% opaque.\n\nPassing a single number to the option sets the sub to gray, and the form gray/a lets you specify alpha additionally.\n\nExamples\n\n1.0/0.0/0.0 set sub to opaque red\n1.0/0.0/0.0/0.75 set sub to opaque red with 75% alpha\n0.5/0.75 set sub to 50% gray with 75% alpha\n\nAlternatively, the color can be specified as a RGB hex triplet in the form #RRGGBB, where each 2-digit group expresses a color value in the range 0 (00) to 255 (FF). For example, #FF0000 is red. This is similar to web colors. Alpha is given with #AARRGGBB.\n\nExamples\n\n#FF0000 set sub to opaque red\n#C0808080 set sub to 50% gray with 75% alpha
name = sub-border-color
file = mpv
type = color
filter = Subtitle
help = See sub-color. Color used for the sub font border. Ignored when sub-back-color is specified (or more exactly: when that option is not set to completely transparent).
name = sub-back-color
file = mpv
type = color
filter = Subtitle
help = See sub-color. Color used for sub text background. You can use sub-shadow-offset to change its size relative to the text.
name = fullscreen
file = mpv
default = no
filter = Screen
help = Start the player in fullscreen mode.
option = yes
option = no
name = border
file = mpv
default = yes
filter = Screen
help = Show window with decoration (titlebar, border).
option = yes
option = no
name = screen
file = mpv
filter = Screen
help = <0-32> In multi-monitor configurations (i.e. a single desktop that spans across multiple displays), this option tells mpv which screen to display the video on.
name = osd-playing-msg
file = mpv
width = 300
filter = Screen
type = string
help = Show a message on OSD when playback starts. The string is expanded for properties, e.g. osd-playing-msg='file: ${filename}' will show the message file: followed by a space and the currently played filename. For more information visit:
url = https://mpv.io/manual/master/#property-expansion
name = osd-font-size
file = mpv
filter = Screen
help = Specify the OSD font size. See sub-font-size for details. Default: 55
name = osd-duration
file = mpv
filter = Screen
help = Set the duration of the OSD messages in ms. Default: 1000
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.
option = yes
option = no
name = autofit
file = mpv
filter = Screen
help = <int> Initial window height in percent. Default: 60
name = autofit-image
file = mpvnet
filter = Screen
help = <int> Initial window height in percent for image files. Default: 80
name = autofit-audio
file = mpvnet
filter = Screen
help = <int> Initial window height in percent for audio files. Default: 70
name = autofit-smaller
file = mpv
filter = Screen
help = <int> Minimum window height in percent. Default: 10
name = autofit-larger
file = mpv
filter = Screen
help = <int> Maximum window height in percent. Default: 80
name = start-size
file = mpvnet
default = height-session
filter = Screen
help = Setting to remember the window size. (mpv.net specific option)
option = width-session Window width is remembered in the current session
option = width-always Window width is always remembered
option = height-session Window height is remembered in the current session
option = height-always Window height is always remembered
option = video Window size is set to video resolution
option = session Window size is remembered in the current session
option = always Window size is always remembered
name = keepaspect-window
file = mpv
default = yes
filter = Screen
help = keepaspect-window will lock the window size to the video aspect. Default: yes
option = yes
option = no
name = minimum-aspect-ratio
file = mpvnet
filter = Screen
help = <float> Minimum aspect ratio of the window. Useful to force a wider window and therefore a larger OSC. (mpv.net specific option)
name = minimum-aspect-ratio-audio
file = mpvnet
filter = Screen
help = Same as minimum-aspect-ratio but used for audio files.
name = remember-window-position
file = mpvnet
default = no
filter = Screen
help = Save the window position on exit. (mpv.net specific option)
option = yes
option = no
name = snap-window
file = mpv
default = no
filter = Screen
help = Snap the player window to screen edges.
option = yes
option = no
name = window-maximized
file = mpv
default = no
filter = Screen
help = Start with a maximized window.
option = yes
option = no
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 option)
name = taskbar-progress
file = mpv
default = yes
filter = Playback
help = Show progress in taskbar.
option = yes
option = no
name = keep-open
file = mpv
default = no
filter = Playback
option = yes If the current file ends, go to the next file, keep the last file open.
option = no If the current file ends, go to the next file. If idle is set to no, the player exits after the last file.
option = always Playback will never automatically advance to the next file.
name = keep-open-pause
file = mpv
default = yes
filter = Playback
help = If set to no, instead of pausing when keep-open is active, just stop at end of file and continue playing forward when you seek backwards until end where it stops again.
option = yes
option = no
name = idle
file = mpv
default = yes
filter = Playback
help = If set to no and keep-open is also set to no, the player exits after the last file ends.
option = yes
option = no
option = once
name = auto-play
file = mpvnet
default = no
filter = Playback
help = Sets pause=no on file load. (mpv.net specific option)
option = yes
option = no
name = loop-file
file = mpv
filter = Playback
help = <N|inf|no> Loop a single file N times. inf means forever, no means normal playback.\n\nThe difference to loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file. loop is an alias for this option.
name = save-position-on-quit
file = mpv
default = no
filter = Playback
help = Always save the current playback position on quit. When this file is played again later, the player will seek to the old playback position on start. This does not happen if playback of a file is stopped in any other way than quitting. For example, going to the next file in the playlist will not save the position, and start playback at beginning the next time the file is played.\n\nThis behavior is disabled by default, but is always available when quitting the player with Shift+Q.
option = yes
option = no
name = watch-later-options
file = mpv
filter = Playback
help = The options that are saved in "watch later" files if they have been changed since when mpv started. These values will be restored the next time the files are played. This is a string list option. For more information visit:
url = https://mpv.io/manual/master/#options-watch-later-options
name = hr-seek
file = mpv
default = absolute
filter = Playback
help = Select when to use precise seeks that are not limited to keyframes. Such seeks require decoding video from the previous keyframe up to the target position and so can take some time depending on decoding performance. For some video formats, precise seeks are disabled. This option selects the default choice to use for seeks; it is possible to explicitly override that default in the definition of key bindings and in input commands.
option = yes Use precise seeks whenever possible.
option = no Never use precise seeks.
option = absolute Use precise seeks if the seek is to an absolute position in the file, such as a chapter seek, but not for relative seeks like the default behavior of arrow keys.
option = always Same as yes (for compatibility).
name = track-auto-selection
file = mpv
default = yes
filter = Playback
help = Enable the default track auto-selection. Enabling this will make the player select streams according to aid, alang, and others. If it is disabled, no tracks are selected. In addition, the player will not exit if no tracks are selected, and wait instead (this wait mode is similar to pausing, but the pause option is not set).\n\nThis is useful with lavfi-complex: you can start playback in this mode, and then set select tracks at runtime by setting the filter graph. Note that if lavfi-complex is set before playback is started, the referenced tracks are always selected.
option = yes
option = no
name = loop-playlist
file = mpv
filter = Playback
help = <N|inf|force|no> Loops playback N times. A value of 1 plays it one time (default), 2 two times, etc. inf means forever. no is the same as 1 and disables looping. If several files are specified on command line, the entire playlist is looped. The force mode is like inf, but does not skip playlist entries which have been marked as failing. This means the player might waste CPU time trying to loop a file that doesn't exist. But it might be useful for playing webradios under very bad network conditions.
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 option)
option = yes
option = no
name = input-ar-delay
file = mpv
filter = Input
help = Delay in milliseconds before we start to autorepeat a key (0 to disable).
name = input-ar-rate
file = mpv
filter = Input
help = Number of key presses to generate per second on autorepeat.
name = dark-mode
file = mpvnet
default = always
filter = UI
help = Changes between a light and dark theme.\nmpv.net must be restarted after a change.\nmpv.net specific option.
option = always
option = system Available on Windows 10 or higher
option = never
name = dark-theme
file = mpvnet
filter = UI
url = https://github.com/mpvnet-player/mpv.net/blob/master/docs/Manual.md#color-theme
help = Color theme used in dark mode.\nmpv.net must be restarted after a change.\nmpv.net specific option. Default: dark
name = light-theme
file = mpvnet
filter = UI
url = https://github.com/mpvnet-player/mpv.net/blob/master/docs/Manual.md#color-theme
help = Color theme used in light mode.\nmpv.net must be restarted after a change.\nmpv.net specific option. Default: light
name = show-logo
file = mpvnet
default = yes
filter = UI
help = Draws the blue mpv.net logo ontop of the native OSC logo.
option = yes
option = no
name = show-santa-logo
file = mpvnet
default = yes
filter = UI
help = Draws the blue mpv.net logo with a santa hat in december, the option is called greenandgrumpy in mpv.
option = yes
option = no
name = screenshot-directory
file = mpv
width = 500
type = folder
filter = Screenshot
help = Store screenshots in this directory. This path is joined with the filename generated by screenshot-template. If the template filename is already absolute, the directory is ignored.\n\nIf the directory does not exist, it is created on the first screenshot. If it is not a directory, an error is generated when trying to write a screenshot.
name = screenshot-format
file = mpv
default = jpg
filter = Screenshot
help = Set the image file type used for saving screenshots.
option = jpg
option = png
name = screenshot-tag-colorspace
file = mpv
default = no
filter = Screenshot
help = Tag screenshots with the appropriate colorspace. Note that not all formats are supported.
option = yes
option = no
name = screenshot-high-bit-depth
file = mpv
default = yes
filter = Screenshot
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.
option = yes
option = no
name = screenshot-jpeg-source-chroma
file = mpv
default = yes
filter = Screenshot
help = Write JPEG files with the same chroma subsampling as the video. If disabled, the libjpeg default is used.
option = yes
option = no
name = screenshot-template
file = mpv
filter = Screenshot
type = string
help = Specify the filename template used to save screenshots. The template specifies the filename without file extension, and can contain format specifiers, which will be substituted when taking a screenshot. By default, the template is mpv-shot%n, which results in filenames like mpv-shot0012.png for example.\n\nFind the full documentation here:
url = https://mpv.io/manual/master/#options-screenshot-template
name = screenshot-jpeg-quality
file = mpv
filter = Screenshot
help = <0-100> Set the JPEG quality level. Higher means better quality. The default is 90.
name = screenshot-png-compression
file = mpv
filter = Screenshot
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.
name = screenshot-png-filter
file = mpv
filter = Screenshot
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.
name = cache
file = mpv
default = auto
filter = Cache
help = Decide whether to use network cache settings.
url = https://mpv.io/manual/master/#options-cache
option = yes
option = no
option = auto
name = demuxer-max-bytes
file = mpv
filter = Demuxer
help = <bytesize> Controls how much the demuxer is allowed to buffer ahead.\nSuffixes such as KiB and MiB are supported.
url = https://mpv.io/manual/master/#options-demuxer-max-bytes

View File

@@ -1,208 +1,227 @@
# This file defines the key and mouse bindings and the context menu of mpv.net. # https://github.com/mpvnet-player/mpv.net/blob/master/docs/Manual.md#input-and-context-menu
# A input and config editor can be found in the context menu under 'Settings'.
# The mpv.conf defaults of mpv.net contain: 'input-default-bindings = no'
# which disables the input defaults of mpv.
# Every line in this file begins with a space character to make search easier,
# if you want to know if 'o' has already a binding you can search for ' o '.
# input test mode: o script-message-to mpvnet open-files #menu: Open > Open Files...
# mpvnet --input-test V script-message-to mpvnet open-clipboard #menu: Open > Open URL or file from clipboard
_ script-message-to mpvnet open-optical-media #menu: Open > Open DVD/Blu-ray Drive/Folder...
_ ignore #menu: Open > -
Alt+a script-message-to mpvnet load-audio #menu: Open > Load external audio files...
Alt+s script-message-to mpvnet load-sub #menu: Open > Load external subtitle files...
_ ignore #menu: Open > -
_ script-message-to mpvnet open-files append #menu: Open > Add files to playlist...
_ ignore #menu: Open > -
_ ignore #menu: Open > Recent
# The input key list can be found in the context menu under: View > Show Keys _ ignore #menu: -
Space script-message-to mpvnet play-pause #menu: Play/Pause
Ctrl+s stop #menu: Stop
_ ignore #menu: -
Enter cycle fullscreen #menu: Toggle Fullscreen
# mpv.net input.conf defaults: F11 script-message-to mpvnet playlist-add -1 #menu: Navigate > Previous File
# https://github.com/stax76/mpv.net/blob/master/src/Resources/input.conf.txt F12 script-message-to mpvnet playlist-add 1 #menu: Navigate > Next File
_ ignore #menu: Navigate > -
Home script-message-to mpvnet playlist-first #menu: Navigate > First File
End script-message-to mpvnet playlist-last #menu: Navigate > Last File
_ ignore #menu: Navigate > -
F9 script-message-to mpvnet playlist-random #menu: Navigate > Random File
_ ignore #menu: Navigate > -
PGUP add chapter 1 #menu: Navigate > Next Chapter
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
_ ignore #menu: Navigate > -
. frame-step #menu: Navigate > Jump Next Frame
, frame-back-step #menu: Navigate > Jump Previous Frame
_ ignore #menu: Navigate > -
Right seek 5 #menu: Navigate > Jump 5 sec forward
Left seek -5 #menu: Navigate > Jump 5 sec backward
_ ignore #menu: Navigate > -
Up seek 30 #menu: Navigate > Jump 30 sec forward
Down seek -30 #menu: Navigate > Jump 30 sec backward
_ ignore #menu: Navigate > -
Ctrl+Right seek 300 #menu: Navigate > Jump 5 min forward
Ctrl+Left seek -300 #menu: Navigate > Jump 5 min backward
_ ignore #menu: Navigate > -
_ ignore #menu: Navigate > Titles
_ ignore #menu: Navigate > Chapters
# mpv input.conf defaults: Ctrl++ add video-zoom 0.1 #menu: Pan & Scan > Increase Size
# https://github.com/mpv-player/mpv/blob/master/etc/input.conf Ctrl+- add video-zoom -0.1 #menu: Pan & Scan > Decrease Size
_ ignore #menu: Pan & Scan > -
Ctrl+KP4 add video-pan-x -0.01 #menu: Pan & Scan > Move Left
Ctrl+KP6 add video-pan-x 0.01 #menu: Pan & Scan > Move Right
_ ignore #menu: Pan & Scan > -
Ctrl+KP8 add video-pan-y -0.01 #menu: Pan & Scan > Move Up
Ctrl+KP2 add video-pan-y 0.01 #menu: Pan & Scan > Move Down
_ ignore #menu: Pan & Scan > -
w add panscan -0.1 #menu: Pan & Scan > Decrease Height
W add panscan 0.1 #menu: Pan & Scan > Increase Height
_ ignore #menu: Pan & Scan > -
Ctrl+BS set video-zoom 0; set video-pan-x 0; set video-pan-y 0 #menu: Pan & Scan > Reset
# mpv input commands: Ctrl+1 add contrast -1 #menu: Video > Decrease Contrast
# https://mpv.io/manual/master/#list-of-input-commands Ctrl+2 add contrast 1 #menu: Video > Increase Contrast
_ ignore #menu: Video > -
Ctrl+3 add brightness -1 #menu: Video > Decrease Brightness
Ctrl+4 add brightness 1 #menu: Video > Increase Brightness
_ ignore #menu: Video > -
Ctrl+5 add gamma -1 #menu: Video > Decrease Gamma
Ctrl+6 add gamma 1 #menu: Video > Increase Gamma
_ ignore #menu: Video > -
Ctrl+7 add saturation -1 #menu: Video > Decrease Saturation
Ctrl+8 add saturation 1 #menu: Video > Increase Saturation
_ ignore #menu: Video > -
s async screenshot #menu: Video > Take Screenshot
S async screenshot video #menu: Video > Take Screenshot without subtitles
d cycle deinterlace #menu: Video > Toggle Deinterlace
a cycle-values video-aspect 16:9 4:3 2.35:1 -1 #menu: Video > Cycle Aspect Ratio
Ctrl+r cycle-values video-rotate 90 180 270 0 #menu: Video > Rotate Video
# mpv input options: KP7 script-message-to mpvnet cycle-audio #menu: Audio > Cycle/Next
# https://mpv.io/manual/master/#input _ ignore #menu: Audio > -
Ctrl+d add audio-delay 0.1 #menu: Audio > Delay +0.1
Ctrl+D add audio-delay -0.1 #menu: Audio > Delay -0.1
o script-message mpv.net open-files #menu: Open > Open Files... KP8 script-message-to mpvnet cycle-subtitles #menu: Subtitle > Cycle/Next
u script-message mpv.net open-url #menu: Open > Open URL or file path from clipboard v cycle sub-visibility #menu: Subtitle > Toggle Visibility
_ script-message mpv.net open-optical-media #menu: Open > Open DVD/Blu-ray Drive/Folder... _ ignore #menu: Subtitle > -
_ ignore #menu: Open > - z add sub-delay -0.1 #menu: Subtitle > Delay -0.1
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files... Z add sub-delay 0.1 #menu: Subtitle > Delay +0.1
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files... _ ignore #menu: Subtitle > -
_ ignore #menu: Open > - r add sub-pos -1 #menu: Subtitle > Move Up
_ script-message mpv.net open-files append #menu: Open > Add files to playlist... R add sub-pos +1 #menu: Subtitle > Move Down
F3 script-message mpv.net show-media-search #menu: Open > Show media search... _ ignore #menu: Subtitle > -
_ ignore #menu: Open > - F add sub-scale -0.1 #menu: Subtitle > Decrease Subtitle Font Size
_ ignore #menu: Open > Recent G add sub-scale 0.1 #menu: Subtitle > Increase Subtitle Font Size
_ ignore #menu: Subtitle > -
u cycle-values sub-ass-override force no #menu: Subtitle > Advanced > Toggle overriding SSA/ASS subtitle styles with the normal styles
_ ignore #menu: - _ ignore #menu: Track
Space cycle pause #menu: Play/Pause
s stop #menu: Stop
_ ignore #menu: -
Enter cycle fullscreen #menu: Toggle Fullscreen
F11 playlist-prev; set pause no #menu: Navigate > Previous File
F12 playlist-next; set pause no #menu: Navigate > Next File
_ ignore #menu: Navigate > -
Home script-message mpv.net playlist-first #menu: Navigate > First File
End script-message mpv.net playlist-last #menu: Navigate > Last File
_ ignore #menu: Navigate > -
PGUP add chapter 1 #menu: Navigate > Next Chapter
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
_ ignore #menu: Navigate > -
. frame-step #menu: Navigate > Jump Next Frame
, frame-back-step #menu: Navigate > Jump Previous Frame
_ ignore #menu: Navigate > -
Right seek 5 #menu: Navigate > Jump 5 sec forward
Left seek -5 #menu: Navigate > Jump 5 sec backward
_ ignore #menu: Navigate > -
Up seek 30 #menu: Navigate > Jump 30 sec forward
Down seek -30 #menu: Navigate > Jump 30 sec backward
_ ignore #menu: Navigate > -
Ctrl+Right seek 300 #menu: Navigate > Jump 5 min forward
Ctrl+Left seek -300 #menu: Navigate > Jump 5 min backward
_ ignore #menu: Navigate > -
_ ignore #menu: Navigate > Titles
_ ignore #menu: Navigate > Chapters
Ctrl++ add video-zoom 0.1 #menu: Pan & Scan > Increase Size + add volume 2 #menu: Volume > Up
Ctrl+- add video-zoom -0.1 #menu: Pan & Scan > Decrease Size - add volume -2 #menu: Volume > Down
_ ignore #menu: Pan & Scan > - 0 add volume 2 #menu: Volume > Up
Ctrl+KP4 add video-pan-x -0.01 #menu: Pan & Scan > Move Left 9 add volume -2 #menu: Volume > Down
Ctrl+KP6 add video-pan-x 0.01 #menu: Pan & Scan > Move Right _ ignore #menu: Volume > -
_ ignore #menu: Pan & Scan > - m cycle mute #menu: Volume > Mute
Ctrl+KP8 add video-pan-y -0.01 #menu: Pan & Scan > Move Up
Ctrl+KP2 add video-pan-y 0.01 #menu: Pan & Scan > Move Down
_ ignore #menu: Pan & Scan > -
w add panscan -0.1 #menu: Pan & Scan > Decrease Height
W add panscan 0.1 #menu: Pan & Scan > Increase Height
_ ignore #menu: Pan & Scan > -
Ctrl+BS set video-zoom 0; set video-pan-x 0; set video-pan-y 0 #menu: Pan & Scan > Reset
Ctrl+1 add contrast -1 #menu: Video > Decrease Contrast [ multiply speed 1/1.1 #menu: Speed > -10%
Ctrl+2 add contrast 1 #menu: Video > Increase Contrast ] multiply speed 1.1 #menu: Speed > +10%
_ ignore #menu: Video > - _ ignore #menu: Speed > -
Ctrl+3 add brightness -1 #menu: Video > Decrease Brightness { multiply speed 0.5 #menu: Speed > Half
Ctrl+4 add brightness 1 #menu: Video > Increase Brightness } multiply speed 2.0 #menu: Speed > Double
_ ignore #menu: Video > - _ ignore #menu: Speed > -
Ctrl+5 add gamma -1 #menu: Video > Decrease Gamma BS set speed 1 #menu: Speed > Reset
Ctrl+6 add gamma 1 #menu: Video > Increase Gamma
_ ignore #menu: Video > -
Ctrl+7 add saturation -1 #menu: Video > Decrease Saturation
Ctrl+8 add saturation 1 #menu: Video > Increase Saturation
_ ignore #menu: Video > -
Ctrl+s async screenshot #menu: Video > Take Screenshot
d cycle deinterlace #menu: Video > Toggle Deinterlace
a cycle-values video-aspect 16:9 4:3 2.35:1 -1 #menu: Video > Cycle Aspect Ratio
KP7 script-message mpv.net cycle-audio #menu: Audio > Cycle/Next Alt++ script-message-to mpvnet scale-window 1.2 #menu: View > Zoom > Enlarge
_ ignore #menu: Audio > - Alt+- script-message-to mpvnet scale-window 0.8 #menu: View > Zoom > Shrink
KP6 add audio-delay 0.1 #menu: Audio > Delay +0.1 _ ignore #menu: View > Zoom > -
KP9 add audio-delay -0.1 #menu: Audio > Delay -0.1 Alt+0 script-message-to mpvnet window-scale 0.5 #menu: View > Zoom > 50 %
Alt+1 script-message-to mpvnet window-scale 1.0 #menu: View > Zoom > 100 %
Alt+2 script-message-to mpvnet window-scale 2.0 #menu: View > Zoom > 200 %
Alt+3 script-message-to mpvnet window-scale 3.0 #menu: View > Zoom > 300 %
KP8 cycle sub #menu: Subtitle > Cycle/Next Alt+Left script-message-to mpvnet move-window left #menu: View > Move > Left
v cycle sub-visibility #menu: Subtitle > Toggle Visibility Alt+Right script-message-to mpvnet move-window right #menu: View > Move > Right
_ ignore #menu: Subtitle > - Alt+Up script-message-to mpvnet move-window top #menu: View > Move > Top
z add sub-delay -0.1 #menu: Subtitle > Delay -0.1 Alt+Down script-message-to mpvnet move-window bottom #menu: View > Move > Bottom
Z add sub-delay 0.1 #menu: Subtitle > Delay +0.1 Alt+BS script-message-to mpvnet move-window center #menu: View > Move > Center
_ ignore #menu: Subtitle > -
r add sub-pos -1 #menu: Subtitle > Move Up
R add sub-pos +1 #menu: Subtitle > Move Down
_ ignore #menu: Subtitle > -
_ add sub-scale -0.1 #menu: Subtitle > Decrease Subtitle Font Size
_ add sub-scale 0.1 #menu: Subtitle > Increase Subtitle Font Size
_ ignore #menu: Track F8 script-message-to mpvnet show-playlist #menu: View > Show Playlist
Ctrl+p script-message-to mpvnet select-profile #menu: View > Show Profile Selection
Ctrl+P script-message-to mpvnet show-profiles #menu: View > Show Profiles
Ctrl+7 script-message-to mpvnet show-audio-tracks #menu: View > Show Audio Tracks
Ctrl+8 script-message-to mpvnet show-subtitle-tracks #menu: View > Show Subtitle Tracks
Ctrl+c script-message-to mpvnet show-chapters #menu: View > Show Chapters
b cycle border #menu: View > Toggle Border
Ctrl+t cycle ontop #menu: View > Toggle On Top
t script-binding stats/display-stats-toggle #menu: View > Toggle Statistics
Del script-binding osc/visibility #menu: View > Toggle OSC Visibility
i script-message-to mpvnet show-info #menu: View > Show Media Info
Ctrl+m script-message-to mpvnet show-media-info #menu: View > Show Media Info Advanced
p show-progress #menu: View > Show Progress
Alt+r script-message-to mpvnet show-recent #menu: View > Show Recent
+ add volume 10 #menu: Volume > Up ` script-binding console/enable #menu: View > Advanced > Show Console
- add volume -10 #menu: Volume > Down _ script-message-to mpvnet show-audio-devices #menu: View > Advanced > Show Audio Devices
_ ignore #menu: Volume > - P script-message-to mpvnet show-properties #menu: View > Advanced > Show Properties
m cycle mute #menu: Volume > Mute C script-message-to mpvnet show-commands #menu: View > Advanced > Show Commands
_ script-message-to mpvnet show-demuxers #menu: View > Advanced > Show Demuxers
_ script-message-to mpvnet show-decoders #menu: View > Advanced > Show Decoders
_ script-message-to mpvnet show-protocols #menu: View > Advanced > Show Protocols
_ script-message-to mpvnet show-keys #menu: View > Advanced > Show Keys
[ multiply speed 1/1.1 #menu: Speed > -10% _ ignore #menu: Profile
] multiply speed 1.1 #menu: Speed > +10%
_ ignore #menu: Speed > -
{ multiply speed 0.5 #menu: Speed > Half
} multiply speed 2.0 #menu: Speed > Double
_ ignore #menu: Speed > -
BS set speed 1 #menu: Speed > Reset
Ctrl+t set ontop yes #menu: View > On Top > Enable c script-message-to mpvnet show-conf-editor #menu: Settings > Show Config Editor
Ctrl+T set ontop no #menu: View > On Top > Disable Ctrl+i script-message-to mpvnet show-input-editor #menu: Settings > Show Input Editor
Alt++ script-message mpv.net scale-window 1.2 #menu: View > Zoom > Enlarge Ctrl+f script-message-to mpvnet open-conf-folder #menu: Settings > Open Config Folder
Alt+- script-message mpv.net scale-window 0.8 #menu: View > Zoom > Shrink
_ ignore #menu: View > Zoom > -
Alt+0 script-message mpv.net window-scale 0.5 #menu: View > Zoom > 50 %
Alt+1 script-message mpv.net window-scale 1.0 #menu: View > Zoom > 100 %
Alt+2 script-message mpv.net window-scale 2.0 #menu: View > Zoom > 200 %
Alt+3 script-message mpv.net window-scale 3.0 #menu: View > Zoom > 300 %
b cycle border #menu: View > Toggle Border
i script-message mpv.net show-info #menu: View > File/Stream Info
t script-binding stats/display-stats #menu: View > Show Statistics
T script-binding stats/display-stats-toggle #menu: View > Toggle Statistics
Del script-binding osc/visibility #menu: View > Toggle OSC Visibility
Ctrl+r cycle-values video-rotate 90 180 270 0 #menu: View > Rotate Video
_ script-message mpv.net show-audio-devices #menu: View > Show Audio Devices
Shift+c script-message mpv.net show-commands #menu: View > Show Commands
` script-binding console/enable #menu: View > Show Console
_ script-message mpv.net show-decoders #menu: View > Show Decoders
_ script-message mpv.net show-demuxers #menu: View > Show Demuxers
_ script-message mpv.net show-keys #menu: View > Show Keys
F8 script-message mpv.net show-playlist #menu: View > Show Playlist
Ctrl+p script-message mpv.net show-profiles #menu: View > Show Profiles
p show-progress #menu: View > Show Progress
Shift+p script-message mpv.net show-properties #menu: View > Show Properties
_ script-message mpv.net show-protocols #menu: View > Show Protocols
F9 show-text ${track-list} 5000 #menu: View > Show Tracks
c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor _ script-message-to mpvnet reg-file-assoc video #menu: Settings > Setup > Register video file associations
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor _ script-message-to mpvnet reg-file-assoc audio #menu: Settings > Setup > Register audio file associations
Ctrl+f script-message mpv.net open-conf-folder #menu: Settings > Open Config Folder _ script-message-to mpvnet reg-file-assoc image #menu: Settings > Setup > Register image file associations
_ script-message-to mpvnet reg-file-assoc unreg #menu: Settings > Setup > Unregister file associations
F1 script-message mpv.net show-command-palette #menu: Tools > Show All Commands h script-message-to mpvnet 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 _ playlist-shuffle #menu: Tools > Shuffle Playlist
_ playlist-shuffle #menu: Tools > Shuffle Playlist Ctrl+h cycle-values hwdec auto no #menu: Tools > Toggle Hardware Decoding
Ctrl+h cycle-values hwdec auto no #menu: Tools > Toggle Hardware Decoding Q quit-watch-later #menu: Tools > Exit Watch Later
_ script-message mpv.net show-setup-dialog #menu: Tools > Setup... e run powershell -command "explorer.exe '/select,' ( \"${path}\" -replace '/', '\\' )" #menu: Tools > Show current file in File Explorer
_ script-message mpv.net shell-execute https://mpv.io #menu: Help > Website mpv _ script-message-to mpvnet shell-execute https://mpv.io #menu: Help > Website mpv
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net #menu: Help > Website mpv.net _ script-message-to mpvnet shell-execute https://github.com/mpvnet-player/mpv.net #menu: Help > Website mpv.net
_ ignore #menu: Help > - _ ignore #menu: Help > -
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Manual mpv _ script-message-to mpvnet 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/docs/Manual.md #menu: Help > Manual mpv.net _ script-message-to mpvnet shell-execute https://github.com/mpvnet-player/mpv.net/blob/master/docs/Manual.md #menu: Help > Manual mpv.net
_ ignore #menu: Help > - _ ignore #menu: Help > -
_ script-message mpv.net update-check #menu: Help > Check for Updates _ script-message-to mpvnet show-about #menu: Help > About mpv.net
_ script-message mpv.net show-about #menu: Help > About mpv.net
_ ignore #menu: - F1 script-message-to mpvnet show-command-palette #menu: Command Palette
Esc quit #menu: Exit _ ignore #menu: -
Q quit-watch-later #menu: Exit Watch Later Esc quit #menu: Exit
Power quit MBTN_Right script-message-to mpvnet show-menu
Play cycle pause 6 script-message-to mpvnet show-progress
Pause cycle pause KP6 script-message-to mpvnet show-progress
PlayPause cycle pause KP9 ab-loop
MBTN_Mid cycle pause 7 script-message-to mpvnet cycle-audio
Stop stop Sharp script-message-to mpvnet cycle-audio
Forward seek 60 Ctrl+F11 script-message-to mpvnet playlist-add -10
Rewind seek -60 Ctrl+F12 script-message-to mpvnet playlist-add 10
Wheel_Up add volume 10 Alt+q script-message-to mpvnet quick-bookmark
Wheel_Down add volume -10 8 script-message-to mpvnet cycle-subtitles
Wheel_Left add volume -10 j script-message-to mpvnet cycle-subtitles
Wheel_Right add volume 10 q quit
Prev playlist-prev Power quit
Next playlist-next Play cycle pause
MBTN_Forward playlist-next Pause cycle pause
MBTN_Back playlist-prev PlayPause cycle pause
> playlist-next MBTN_Mid cycle pause
< playlist-prev Stop stop
Ctrl+Wheel_Up no-osd seek 7 Forward seek 60
Ctrl+Wheel_Down no-osd seek -7 Rewind seek -60
MBTN_Left_DBL cycle fullscreen Wheel_Up add volume 2
KP_Enter cycle fullscreen Wheel_Down add volume -2
Wheel_Left add volume -2
Wheel_Right add volume 2
Prev playlist-prev
Next playlist-next
MBTN_Forward playlist-next
MBTN_Back playlist-prev
> playlist-next
< playlist-prev
MBTN_Left ignore
f cycle fullscreen
MBTN_Left_DBL cycle fullscreen
KP_Enter cycle fullscreen
Shift+Right no-osd seek 1 exact
Shift+Left no-osd seek -1 exact
Shift+Up no-osd seek 5 exact
Shift+Down no-osd seek -5 exact
Shift+BS revert-seek # undo the previous (or marked) seek
Shift+Ctrl+BS revert-seek mark # mark the position for revert-seek
Ctrl+Shift+Left no-osd sub-seek -1 # seek to the previous subtitle
Ctrl+Shift+Right no-osd sub-seek 1 # seek to the next subtitle
Ctrl+Wheel_Up no-osd seek 7
Ctrl+Wheel_Down no-osd seek -7

View File

@@ -1,13 +0,0 @@
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/'
[protocol.https]
osd-playing-msg = '${media-title}'

View File

@@ -5,12 +5,11 @@ heading = #3C8CC8
foreground = #DDDDDD foreground = #DDDDDD
foreground2 = #AAAAAA foreground2 = #AAAAAA
background = #323232 background = #323232
highlight = #404040
menu-foreground = #DDDDDD menu-foreground = #DDDDDD
menu-background = #323232 menu-background = #323232
menu-highlight = #505050 menu-highlight = #505050
menu-border = #FFFFFF
menu-checked = #5A5A5A
[light] [light]
@@ -19,9 +18,8 @@ heading = #0068B2
foreground = #000000 foreground = #000000
foreground2 = #4C4C4C foreground2 = #4C4C4C
background = #F7F7F7 background = #F7F7F7
highlight = #DFDFDF
menu-foreground = #000000 menu-foreground = #000000
menu-background = #DFDFDF menu-background = #DFDFDF
menu-highlight = #BFBFBF menu-highlight = #BFBFBF
menu-border = #6A6A6A
menu-checked = #AAAAAA

View File

@@ -3,8 +3,11 @@
// In input.conf add: // In input.conf add:
// KP0 script-message delete-current-file ask #menu: Script > Delete current file > Ask // KP0 script-message delete-current-file delete #menu: Script > Delete current file > Delete
// 0 script-message delete-current-file delete #menu: Script > Delete current file > Delete
// KP1 script-message delete-current-file confirm #menu: Script > Delete current file > Confirm // KP1 script-message delete-current-file confirm #menu: Script > Delete current file > Confirm
// 1 script-message delete-current-file confirm #menu: Script > Delete current file > Confirm
using System; using System;
using System.IO; using System.IO;
@@ -31,32 +34,34 @@ class Script
if (args == null || args.Length != 2 || args[0] != "delete-current-file") if (args == null || args.Length != 2 || args[0] != "delete-current-file")
return; return;
if (args[1] == "ask") if (args[1] == "delete")
{ {
FileToDelete = Core.get_property_string("path"); FileToDelete = Core.GetPropertyString("path");
DeleteTime = DateTime.Now; DeleteTime = DateTime.Now;
Core.commandv("show-text", "Press 1 to delete file", "5000"); Core.CommandV("show-text", "Press 1 to delete file", "10000");
} }
else if (args[1] == "confirm") else if (args[1] == "confirm")
{ {
TimeSpan ts = DateTime.Now - DeleteTime; TimeSpan ts = DateTime.Now - DeleteTime;
string path = Core.get_property_string("path"); string path = Core.GetPropertyString("path");
if (FileToDelete == path && ts.TotalSeconds < 5 && File.Exists(FileToDelete)) if (FileToDelete == path && ts.TotalSeconds < 10 && File.Exists(FileToDelete))
{ {
Core.command("playlist-remove current"); Core.CommandV("show-text", "");
int pos = Core.get_property_int("playlist-pos");
if (pos == -1) int count = Core.GetPropertyInt("playlist-count");
{ int pos = Core.GetPropertyInt("playlist-pos");
int count = Core.get_property_int("playlist-count"); int newPos = pos == count - 1 ? pos - 1 : pos + 1;
if (count > 0) if (newPos > -1)
Core.set_property_int("playlist-pos", count - 1); Core.SetPropertyNumber("playlist-pos", newPos);
}
Thread.Sleep(2000); Core.Command("playlist-remove " + pos);
FileSystem.DeleteFile(FileToDelete, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
App.RunTask(() => {
Thread.Sleep(2000);
FileSystem.DeleteFile(FileToDelete, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
});
} }
} }
} }

View File

@@ -12,8 +12,8 @@ class Script
string content = "ctrl+w script-message my-message-1 my-argument-1"; string content = "ctrl+w script-message my-message-1 my-argument-1";
string sectionName = Assembly.GetExecutingAssembly().GetName().Name; string sectionName = Assembly.GetExecutingAssembly().GetName().Name;
CorePlayer core = Global.Core; CorePlayer core = Global.Core;
core.commandv("define-section", sectionName, content, "force"); core.CommandV("define-section", sectionName, content, "force");
core.commandv("enable-section", sectionName); core.CommandV("enable-section", sectionName);
core.ClientMessage += ClientMessage; core.ClientMessage += ClientMessage;
} }

View File

@@ -11,11 +11,11 @@ class Script
public Script() public Script()
{ {
Core = Global.Core; Core = Global.Core;
Core.observe_property_bool("fullscreen", FullscreenChange); Core.ObservePropertyBool("fullscreen", FullscreenChange);
} }
void FullscreenChange(bool value) void FullscreenChange(bool value)
{ {
Core.commandv("show-text", "fullscreen: " + value); Core.CommandV("show-text", "fullscreen: " + value);
} }
} }

View File

@@ -25,11 +25,11 @@ class Script
{ {
if (MainForm.WindowState == FormWindowState.Minimized) if (MainForm.WindowState == FormWindowState.Minimized)
{ {
WasPlaying = !Core.get_property_bool("pause"); WasPlaying = !Core.GetPropertyBool("pause");
if (WasPlaying) if (WasPlaying)
{ {
Core.set_property_bool("pause", true, true); Core.SetPropertyBool("pause", true, true);
WasPaused = true; WasPaused = true;
} }
} }
@@ -37,7 +37,7 @@ class Script
{ {
if (WasPaused) if (WasPaused)
{ {
Core.set_property_bool("pause", false, true); Core.SetPropertyBool("pause", false, true);
WasPaused = false; WasPaused = false;
} }
} }

View File

@@ -62,20 +62,20 @@ class Script
//handles keys defined in input.conf //handles keys defined in input.conf
void ClientMessage(string[] args) void ClientMessage(string[] args)
{ {
if (args[0] != "rate-file") if (args == null || args.Length != 2 || args[0] != "rate-file")
return; return;
int rating; int rating;
if (int.TryParse(args[1], out rating)) if (int.TryParse(args[1], out rating))
{ {
string path = Core.get_property_string("path"); string path = Core.GetPropertyString("path");
if (!File.Exists(path)) if (!File.Exists(path))
return; return;
Dic[path] = rating; Dic[path] = rating;
Core.commandv("show-text", "Rating: " + rating); Core.CommandV("show-text", "Rating: " + rating);
} }
else if (args[1] == "about") else if (args[1] == "about")
MessageBox.Show("This extension writes a rating to the filename of rated videos when mpv.net shuts down.", MessageBox.Show("This extension writes a rating to the filename of rated videos when mpv.net shuts down.",

View File

@@ -31,7 +31,7 @@ class Script
foreach (MediaTrack track in editionTracks) foreach (MediaTrack track in editionTracks)
{ {
MenuItem mi = new MenuItem(track.Text); MenuItem mi = new MenuItem(track.Text);
mi.Action = () => { Core.commandv("set", "edition", track.ID.ToString()); }; mi.Action = () => { Core.CommandV("set", "edition", track.ID.ToString()); };
mi.Checked = Core.Edition == track.ID; mi.Checked = Core.Edition == track.ID;
menuItem.DropDownItems.Add(mi); menuItem.DropDownItems.Add(mi);
} }

View File

@@ -1,35 +0,0 @@
// 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);

View File

@@ -1,26 +0,0 @@
// 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);

View File

@@ -1,23 +0,0 @@
-- 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)

View File

@@ -17,4 +17,4 @@ $code = {
} }
} }
$mp.register_event("client-message", $code) $mp.RegisterEvent("client-message", $code)

View File

@@ -1,13 +1,13 @@
$code = { $code = {
$isMinimized = $args[0] $isMinimized = $args[0]
$isPaused = $mp.get_property_bool('pause') $isPaused = $mp.GetPropertyBool('pause')
if ($isMinimized) if ($isMinimized)
{ {
if (-not $isPaused) if (-not $isPaused)
{ {
$mp.set_property_bool('pause', $true) $mp.SetPropertyBool('pause', $true)
$script:wasPaused = $true $script:wasPaused = $true
} }
} }
@@ -15,11 +15,11 @@ $code = {
{ {
if ($script:wasPaused -and $isPaused) if ($script:wasPaused -and $isPaused)
{ {
$mp.set_property_bool('pause', $false) $mp.SetPropertyBool('pause', $false)
} }
$script:wasPaused = $false $script:wasPaused = $false
} }
} }
$mp.observe_property('window-minimized', 'bool', $code) $mp.ObserveProperty('window-minimized', 'bool', $code)

View File

@@ -6,9 +6,8 @@
$code = { $code = {
if ($args[0] -eq 'show-in-file-explorer') if ($args[0] -eq 'show-in-file-explorer')
{ {
# probably works only with shell execute for which powershell has no built-in support Start-Process explorer.exe '/n,','/select,',"$($mp.GetPropertyString('path'))"
[Diagnostics.Process]::Start('explorer.exe', '/n, /select, "' + $mp.get_property_string('path') + '"')
} }
} }
$mp.register_event("client-message", $code) $mp.RegisterEvent("client-message", $code)

View File

@@ -1,31 +0,0 @@
#define MyAppName "mpv.net"
#define MyAppExeName "mpvnet.exe"
#define MyAppSourceDir "bin"
#define MyAppVersion GetFileVersion("bin\mpvnet.exe")
[Setup]
AppId={{9AA2B100-BEF3-44D0-B819-D8FC3C4D557D}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher=Frank Skare (stax76)
ArchitecturesInstallIn64BitMode=x64
Compression=lzma2
DefaultDirName={commonpf}\{#MyAppName}
OutputBaseFilename=mpv.net-{#MyAppVersion}-setup
OutputDir=D:\Work
DefaultGroupName={#MyAppName}
SetupIconFile=mpvnet.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
[Files]
Source: "{#MyAppSourceDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#MyAppSourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; Excludes: "System.Management.Automation.xml,settings-directory.txt"
[UninstallRun]
Filename: "powershell.exe"; Flags: runhidden; Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\Setup\remove file associations.ps1"""
Filename: "powershell.exe"; Flags: runhidden; Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\Setup\remove start menu shortcut.ps1"""
Filename: "powershell.exe"; Flags: runhidden; Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{app}\Setup\remove environment variable.ps1"""

View File

@@ -16,8 +16,6 @@ namespace mpvnet
protected override void OnPreviewKeyDown(KeyEventArgs e) => Close(); protected override void OnPreviewKeyDown(KeyEventArgs e) => Close();
protected override void OnMouseDown(MouseButtonEventArgs e) => Close(); protected override void OnMouseDown(MouseButtonEventArgs e) => Close();
public Theme Theme { public Theme Theme => Theme.Current;
get => Theme.Current;
}
} }
} }

View File

@@ -0,0 +1,126 @@
<UserControl
x:Class="mpvnet.CommandPaletteControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:mpvnet"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
mc:Ignorable="d"
FontSize="13"
Loaded="OnLoaded"
Background="#111111"
>
<UserControl.InputBindings>
<KeyBinding Gesture="Esc" Command="{Binding EscapeCommand}"/>
<KeyBinding Gesture="Enter" Command="{Binding ExecuteCommand}"/>
</UserControl.InputBindings>
<Border Name="MainBorder"
BorderThickness="1,0,1,1"
CornerRadius="0,0,5,5"
Padding="0,0,0,5"
BorderBrush="{Binding Theme.MenuHighlight}"
Background="{Binding Theme.Background}"
SnapsToDevicePixels="True"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderBrush="{Binding Theme.Heading}"
BorderThickness="1"
CornerRadius="3"
Margin="7"
>
<local:SearchTextBoxUserControl
HintText="Search"
x:Name="SearchControl"
Grid.ColumnSpan="2"
Padding="1,1,1,0"
/>
</Border>
<ListView Name="MainListView"
Grid.Row="1"
Foreground="{Binding Theme.Foreground}"
Background="{Binding Theme.Background}"
BorderThickness="0"
MaxHeight="202"
SizeChanged="MainListView_SizeChanged"
MouseUp="MainListView_MouseUp"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Height" Value="25"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="BD"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="BD" Value="{DynamicResource HighlightBrush}" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="BD" Value="{DynamicResource BorderBrush}" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="3"/>
</Style>
</Style.Resources>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Text}"></TextBlock>
<TextBlock
Grid.Column="1"
Text="{Binding SecondaryText}"
HorizontalAlignment="Right"
/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,150 @@

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
namespace mpvnet
{
public partial class CommandPaletteControl : UserControl
{
public ICollectionView CollectionView { get; set; }
public ICommand EscapeCommand { get; }
public ICommand ExecuteCommand { get; }
public CollectionViewSource CollectionViewSource { get; }
public ObservableCollection<CommandPaletteItem> Items { get; } = new ObservableCollection<CommandPaletteItem>();
public CommandPaletteControl()
{
InitializeComponent();
DataContext = this;
CollectionViewSource = new CollectionViewSource() { Source = Items };
CollectionView = CollectionViewSource.View;
CollectionView.Filter = new Predicate<object>(item => Filter((CommandPaletteItem)item));
MainListView.ItemsSource = CollectionView;
EscapeCommand = new RelayCommand(OnEscapeCommand);
ExecuteCommand = new RelayCommand(OnExecuteCommand);
SearchControl.SearchTextBox.PreviewKeyDown += SearchTextBox_PreviewKeyDown;
SearchControl.SearchTextBox.TextChanged += SearchTextBox_TextChanged;
SearchControl.HideClearButton = true;
if (Environment.OSVersion.Version < new Version(10, 0))
MainBorder.CornerRadius = new CornerRadius(0);
}
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionView.Refresh();
SelectFirst();
}
void SearchTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Up:
{
int index = MainListView.SelectedIndex;
index -= 1;
if (index < 0)
index = 0;
MainListView.SelectedIndex = index;
MainListView.ScrollIntoView(MainListView.SelectedItem);
}
break;
case Key.Down:
{
int index = MainListView.SelectedIndex;
if (++index > MainListView.Items.Count - 1)
index = MainListView.Items.Count - 1;
MainListView.SelectedIndex = index;
MainListView.ScrollIntoView(MainListView.SelectedItem);
}
break;
}
}
void MainListView_SizeChanged(object sender, SizeChangedEventArgs e) => AdjustHeight();
void MainListView_MouseUp(object sender, MouseButtonEventArgs e) => Execute();
void OnEscapeCommand(object param) => MainForm.Instance.HideCommandPalette();
void OnExecuteCommand(object param) => Execute();
void OnLoaded(object sender, RoutedEventArgs e) => Keyboard.Focus(SearchControl.SearchTextBox);
public Theme Theme => Theme.Current;
bool Filter(CommandPaletteItem item)
{
string filter = SearchControl.SearchTextBox.Text.ToLower();
if (item.CommandItem != null)
{
if (item.CommandItem.Alias.ContainsEx(filter))
return true;
if (filter.Length == 1)
return item.CommandItem.Input.ToLower().Replace("ctrl+", "")
.Replace("shift+", "")
.Replace("alt+", "") == filter.ToLower();
if (item.CommandItem.Command.ToLower().Contains(filter))
return true;
}
if (filter == "" || item.Text.ToLower().Contains(filter) ||
item.SecondaryText.ToLower().Contains(filter))
return true;
return false;
}
public void SelectFirst()
{
if (MainListView.Items.Count > 0)
{
MainListView.SelectedIndex = 0;
MainListView.ScrollIntoView(MainListView.SelectedItem);
}
}
void Execute()
{
if (MainListView.SelectedItem != null)
{
CommandPaletteItem item = MainListView.SelectedItem as CommandPaletteItem;
MainForm.Instance.HideCommandPalette();
item.Action.Invoke();
MainForm.Instance.Voodoo();
}
}
public void SetItems(IEnumerable<CommandPaletteItem> items)
{
Items.Clear();
foreach (var i in items)
Items.Add(i);
}
public void AdjustHeight()
{
double actualHeight = SearchControl.ActualHeight + MainListView.ActualHeight + 5 + 16;
int dpi = Native.GetDPI(MainForm.Instance.Handle);
MainForm.Instance.CommandPaletteHost.Height = (int)(actualHeight / 96.0 * dpi);
}
}
}

View File

@@ -1,66 +0,0 @@
<Window
x:Class="mpvnet.CommandPaletteWindow"
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"
mc:Ignorable="d"
Title="Command Palette"
Height="295"
Width="400"
FontSize="13"
ResizeMode="NoResize"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox
Name="FilterTextBox"
Foreground="{Binding Theme.Foreground}"
Background="{Binding Theme.Background}"
PreviewKeyDown="FilterTextBox_PreviewKeyDown"
TextChanged="FilterTextBox_TextChanged"
/>
<ListView
Name="ListView"
Grid.Row="1"
Foreground="{Binding Theme.Foreground}"
Background="{Binding Theme.Background}"
MouseUp="ListView_MouseUp"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Display}"></TextBlock>
<TextBlock
Grid.Column="1"
Text="{Binding Input}"
HorizontalAlignment="Right"
/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>

View File

@@ -1,130 +0,0 @@

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interop;
using static mpvnet.Global;
namespace mpvnet
{
public partial class CommandPaletteWindow : Window
{
ICollectionView CollectionView;
public CommandPaletteWindow()
{
InitializeComponent();
DataContext = this;
CollectionViewSource collectionViewSource = new CollectionViewSource() { Source = CommandItem.Items };
CollectionView = collectionViewSource.View;
var yourCostumFilter = new Predicate<object>(item => Filter((CommandItem)item));
CollectionView.Filter = yourCostumFilter;
ListView.ItemsSource = CollectionView;
}
public Theme Theme {
get => Theme.Current;
}
bool Filter(CommandItem item)
{
if (item.Command == "")
return false;
string filter = FilterTextBox.Text.ToLower();
if (filter == "")
return true;
if (item.Command.ToLower().Contains(filter) ||
item.Input.ToLower().Contains(filter) ||
item.Path.ToLower().Contains(filter))
return true;
return false;
}
void Window_Loaded(object sender, RoutedEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
Keyboard.Focus(FilterTextBox);
SelectFirst();
}
void SelectFirst()
{
if (ListView.Items.Count > 0)
ListView.SelectedIndex = 0;
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed)
handled = true;
return IntPtr.Zero;
}
void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Up:
{
int index = ListView.SelectedIndex;
index -= 1;
if (index < 0)
index = 0;
ListView.SelectedIndex = index;
ListView.ScrollIntoView(ListView.SelectedItem);
}
break;
case Key.Down:
{
int index = ListView.SelectedIndex;
if (++index > ListView.Items.Count - 1)
index = ListView.Items.Count - 1;
ListView.SelectedIndex = index;
ListView.ScrollIntoView(ListView.SelectedItem);
}
break;
case Key.Escape:
Close();
break;
case Key.Enter:
Execute();
break;
}
}
void Execute()
{
if (ListView.SelectedItem != null)
{
CommandItem item = ListView.SelectedItem as CommandItem;
Close();
Core.command(item.Command);
}
}
void ListView_MouseUp(object sender, MouseButtonEventArgs e)
{
Execute();
}
void FilterTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
CollectionView.Refresh();
SelectFirst();
}
}
}

View File

@@ -1,13 +1,15 @@
<Window <Window
xmlns:Controls="clr-namespace:Controls" x:Name="ConfWindow1" x:Class="mpvnet.ConfWindow" x:Name="ConfWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="mpvnet.ConfWindow"
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:local="clr-namespace:mpvnet"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
mc:Ignorable="d" mc:Ignorable="d"
Title="Config Editor" Title="Config Editor"
Height="530" Height="540"
Width="700" Width="700"
Foreground="{Binding Theme.Foreground}" Foreground="{Binding Theme.Foreground}"
Background="{Binding Theme.Background}" Background="{Binding Theme.Background}"
@@ -23,11 +25,11 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="100" /> <ColumnDefinition Width="110" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Controls:SearchTextBoxUserControl <local:SearchTextBoxUserControl
x:Name="SearchControl" x:Name="SearchControl"
HintText="Find a setting" HintText="Find a setting"
Width="250" Width="250"
@@ -55,7 +57,17 @@
Foreground="{Binding Theme.Heading}" Foreground="{Binding Theme.Heading}"
Background="{Binding Theme.Background}" Background="{Binding Theme.Background}"
> >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="3"/>
</Style>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<TextBlock Text="{Binding}" FontSize="16" /> <TextBlock Text="{Binding}" FontSize="16" />
@@ -63,10 +75,9 @@
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>
<TextBlock Name="OpenSettingsTextBlock" Margin="0,30,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="OpenSettingsTextBlock_MouseUp">Open config folder</TextBlock> <TextBlock Name="ShowMpvNetSpecific" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="ShowMpvNetSpecific_MouseUp">Show mpv.net specific options</TextBlock>
<TextBlock Name="PreviewTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="PreviewTextBlock_MouseUp">Preview mpv.conf</TextBlock> <TextBlock Name="PreviewTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="PreviewTextBlock_MouseUp">Preview mpv.conf</TextBlock>
<TextBlock Name="ShowManualTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="ShowManualTextBlock_MouseUp">Show mpv manual</TextBlock> <TextBlock Name="ShowManualTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="ShowManualTextBlock_MouseUp">Show mpv manual</TextBlock>
<TextBlock Name="SupportTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="SupportTextBlock_MouseUp">Show support forum</TextBlock>
</StackPanel> </StackPanel>
</Grid> </Grid>
</Window> </Window>

View File

@@ -17,10 +17,11 @@ namespace mpvnet
{ {
public partial class ConfWindow : Window public partial class ConfWindow : Window
{ {
List<SettingBase> SettingsDefinitions = Settings.LoadSettings(Properties.Resources.editor_toml); List<SettingBase> SettingsDefinitions = Conf.LoadConf(Properties.Resources.editor_conf.TrimEnd());
List<ConfItem> ConfItems = new List<ConfItem>(); 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;
string ThemeConf = GetThemeConf();
public ConfWindow() public ConfWindow()
{ {
@@ -35,9 +36,9 @@ namespace mpvnet
FilterListBox.SelectedItem = SearchControl.Text.TrimEnd(':'); FilterListBox.SelectedItem = SearchControl.Text.TrimEnd(':');
} }
public Theme Theme { static string GetThemeConf() => App.IsDarkMode + App.DarkTheme + App.LightTheme;
get => Theme.Current;
} public Theme Theme => Theme.Current;
void LoadSettings() void LoadSettings()
{ {
@@ -62,10 +63,10 @@ namespace mpvnet
switch (setting) switch (setting)
{ {
case StringSetting s: case StringSetting s:
MainStackPanel.Children.Add(new StringSettingControl(s)); MainStackPanel.Children.Add(new StringSettingControl(s) { Visibility = Visibility.Collapsed });
break; break;
case OptionSetting s: case OptionSetting s:
MainStackPanel.Children.Add(new OptionSettingControl(s)); MainStackPanel.Children.Add(new OptionSettingControl(s) { Visibility = Visibility.Collapsed });
break; break;
} }
} }
@@ -75,10 +76,10 @@ namespace mpvnet
{ {
base.OnClosed(e); base.OnClosed(e);
App.Settings.ConfigEditorSearch = SearchControl.Text; App.Settings.ConfigEditorSearch = SearchControl.Text;
if (InitialContent == GetCompareString()) if (InitialContent == GetCompareString())
return; return;
File.WriteAllText(Core.ConfPath, GetContent("mpv")); File.WriteAllText(Core.ConfPath, GetContent("mpv"));
File.WriteAllText(App.ConfPath, GetContent("mpvnet")); File.WriteAllText(App.ConfPath, GetContent("mpvnet"));
@@ -89,15 +90,7 @@ namespace mpvnet
if (item.File == "mpv") if (item.File == "mpv")
{ {
Core.ProcessProperty(item.Name, item.Value); Core.ProcessProperty(item.Name, item.Value);
Core.SetPropertyString(item.Name, item.Value);
try
{
Core.set_property_string(item.Name, item.Value, true);
}
catch (Exception ex)
{
App.ShowError(ex.Message);
}
} }
else if (item.File == "mpvnet") else if (item.File == "mpvnet")
App.ProcessProperty(item.Name, item.Value, true); App.ProcessProperty(item.Name, item.Value, true);
@@ -105,6 +98,10 @@ namespace mpvnet
} }
App.InitTheme(); App.InitTheme();
App.UpdateWpfColors();
if (ThemeConf != GetThemeConf())
MessageBox.Show("Changed theme settings require mpv.net being restarted.", "Info");
} }
string GetCompareString() string GetCompareString()
@@ -280,15 +277,16 @@ namespace mpvnet
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e) void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{ {
string activeFilter = ""; string activeFilter = "";
string searchText = SearchControl.Text;
foreach (var i in FilterStrings) foreach (string i in FilterStrings)
if (SearchControl.Text == i + ":") if (searchText == i + ":")
activeFilter = i; activeFilter = i;
if (activeFilter == "") if (activeFilter == "")
{ {
foreach (UIElement i in MainStackPanel.Children) foreach (UIElement i in MainStackPanel.Children)
if ((i as ISettingControl).Contains(SearchControl.Text)) if ((i as ISettingControl).Contains(searchText) && searchText.Length > 1)
i.Visibility = Visibility.Visible; i.Visibility = Visibility.Visible;
else else
i.Visibility = Visibility.Collapsed; i.Visibility = Visibility.Collapsed;
@@ -320,18 +318,11 @@ namespace mpvnet
SearchControl.Text = e.AddedItems[0] + ":"; SearchControl.Text = e.AddedItems[0] + ":";
} }
void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e) => void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e) => Msg.ShowInfo(GetContent("mpv"));
ProcessHelp.ShellExecute(Path.GetDirectoryName(Core.ConfPath));
void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e) =>
Msg.ShowInfo("mpv.conf Preview", GetContent("mpv"));
void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e) => void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e) =>
ProcessHelp.ShellExecute("https://mpv.io/manual/master/"); ProcessHelp.ShellExecute("https://mpv.io/manual/master/");
void SupportTextBlock_MouseUp(object sender, MouseButtonEventArgs e) =>
ProcessHelp.ShellExecute("https://github.com/stax76/mpv.net/blob/master/docs/Manual.md#support");
protected override void OnKeyDown(KeyEventArgs e) protected override void OnKeyDown(KeyEventArgs e)
{ {
base.OnKeyDown(e); base.OnKeyDown(e);
@@ -339,5 +330,7 @@ namespace mpvnet
if (e.Key == Key.Escape) if (e.Key == Key.Escape)
Close(); Close();
} }
void ShowMpvNetSpecific_MouseUp(object sender, MouseButtonEventArgs e) => SearchControl.Text = "mpv.net";
} }
} }

View File

@@ -1,49 +0,0 @@
<Window
x:Class="mpvnet.EverythingWindow"
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"
mc:Ignorable="d"
Title="Media File Search"
FontSize="13"
Height="300"
Width="600"
ResizeMode="NoResize"
WindowStartupLocation="CenterOwner"
Loaded="Window_Loaded"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox
Name="FilterTextBox"
Foreground="{Binding Theme.Foreground}"
Background="{Binding Theme.Background}"
PreviewKeyDown="FilterTextBox_PreviewKeyDown"
TextChanged="FilterTextBox_TextChanged"
/>
<ListView
Name="ListView"
Foreground="{Binding Theme.Foreground}"
Background="{Binding Theme.Background}"
Grid.Row="1"
MouseUp="ListView_MouseUp"
PreviewKeyDown="ListView_PreviewKeyDown"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Window>

View File

@@ -1,169 +0,0 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using static mpvnet.Global;
namespace mpvnet
{
public partial class EverythingWindow : Window
{
public EverythingWindow()
{
InitializeComponent();
DataContext = this;
}
public Theme Theme {
get => Theme.Current;
}
const int EVERYTHING_REQUEST_FILE_NAME = 0x00000001;
const int EVERYTHING_REQUEST_PATH = 0x00000002;
[DllImport("Everything.dll", CharSet = CharSet.Unicode)]
public static extern int Everything_SetSearch(string lpSearchString);
[DllImport("Everything.dll")]
public static extern void Everything_SetRequestFlags(UInt32 dwRequestFlags);
[DllImport("Everything.dll")]
public static extern void Everything_SetSort(UInt32 dwSortType);
[DllImport("Everything.dll", CharSet = CharSet.Unicode)]
public static extern bool Everything_Query(bool bWait);
[DllImport("Everything.dll", CharSet = CharSet.Unicode)]
public static extern void Everything_GetResultFullPathName(UInt32 nIndex, StringBuilder lpString, UInt32 nMaxCount);
[DllImport("Everything.dll")]
public static extern bool Everything_GetResultSize(UInt32 nIndex, out long lpFileSize);
[DllImport("Everything.dll")]
public static extern UInt32 Everything_GetNumResults();
void Window_Loaded(object sender, RoutedEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
Keyboard.Focus(FilterTextBox);
}
void SelectFirst()
{
if (ListView.Items.Count > 0)
ListView.SelectedIndex = 0;
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == 0x200 /*WM_MOUSEMOVE*/ && Mouse.LeftButton != MouseButtonState.Pressed)
handled = true;
return IntPtr.Zero;
}
void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Up:
{
int index = ListView.SelectedIndex;
if (--index < 0)
index = 0;
ListView.SelectedIndex = index;
ListView.ScrollIntoView(ListView.SelectedItem);
}
break;
case Key.Down:
{
int index = ListView.SelectedIndex;
if (++index > ListView.Items.Count - 1)
index = ListView.Items.Count - 1;
ListView.SelectedIndex = index;
ListView.ScrollIntoView(ListView.SelectedItem);
}
break;
case Key.Escape: Close(); break;
case Key.Enter: Execute(); break;
}
}
void ListView_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
Close();
if (e.Key == Key.Enter)
Execute();
}
void Execute()
{
if (ListView.SelectedItem != null)
Core.LoadFiles(new[] { ListView.SelectedItem as string }, true, Keyboard.Modifiers == ModifierKeys.Control);
Keyboard.Focus(FilterTextBox);
}
void ListView_MouseUp(object sender, MouseButtonEventArgs e) => Execute();
void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string searchtext = FilterTextBox.Text;
App.RunTask(() => Search(searchtext));
}
object LockObject = new object();
void Search(string searchText)
{
lock (LockObject)
{
try
{
List<string> items = new List<string>();
StringBuilder sb = new StringBuilder(500);
Everything_SetSearch(searchText);
Everything_SetRequestFlags(EVERYTHING_REQUEST_FILE_NAME | EVERYTHING_REQUEST_PATH);
Everything_Query(true);
uint count = Everything_GetNumResults();
for (uint i = 0; i < count; i++)
{
Everything_GetResultFullPathName(i, sb, (uint)sb.Capacity);
string ext = sb.ToString().Ext();
if (CorePlayer.AudioTypes.Contains(ext) || CorePlayer.VideoTypes.Contains(ext) || CorePlayer.ImageTypes.Contains(ext))
items.Add(sb.ToString());
if (items.Count > 100)
break;
}
Application.Current.Dispatcher.Invoke(() => {
ListView.ItemsSource = items;
SelectFirst();
});
}
catch (Exception)
{
Msg.ShowError("Search query failed.",
"The search feature depends on [Everything](https://www.voidtools.com) being installed.");
}
}
}
}
}

View File

@@ -0,0 +1,52 @@

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using HandyControl.Data;
using HandyControl.Tools.Converter;
namespace HandyControl.Controls
{
public class BorderElement
{
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached(
"CornerRadius", typeof(CornerRadius), typeof(BorderElement), new FrameworkPropertyMetadata(default(CornerRadius), FrameworkPropertyMetadataOptions.Inherits));
public static void SetCornerRadius(DependencyObject element, CornerRadius value) => element.SetValue(CornerRadiusProperty, value);
public static CornerRadius GetCornerRadius(DependencyObject element) => (CornerRadius) element.GetValue(CornerRadiusProperty);
public static readonly DependencyProperty CircularProperty = DependencyProperty.RegisterAttached(
"Circular", typeof(bool), typeof(BorderElement), new PropertyMetadata(ValueBoxes.FalseBox, OnCircularChanged));
private static void OnCircularChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Border border)
{
if ((bool) e.NewValue)
{
var binding = new MultiBinding
{
Converter = new BorderCircularConverter()
};
binding.Bindings.Add(new Binding(FrameworkElement.ActualWidthProperty.Name) { Source = border });
binding.Bindings.Add(new Binding(FrameworkElement.ActualHeightProperty.Name) { Source = border });
border.SetBinding(Border.CornerRadiusProperty, binding);
}
else
{
BindingOperations.ClearBinding(border, FrameworkElement.ActualWidthProperty);
BindingOperations.ClearBinding(border, FrameworkElement.ActualHeightProperty);
BindingOperations.ClearBinding(border, Border.CornerRadiusProperty);
}
}
}
public static void SetCircular(DependencyObject element, bool value)
=> element.SetValue(CircularProperty, ValueBoxes.BooleanBox(value));
public static bool GetCircular(DependencyObject element)
=> (bool) element.GetValue(CircularProperty);
}
}

View File

@@ -0,0 +1,36 @@

using System.Windows;
using System.Windows.Media;
namespace HandyControl.Controls
{
public class IconElement
{
public static readonly DependencyProperty GeometryProperty = DependencyProperty.RegisterAttached(
"Geometry", typeof(Geometry), typeof(IconElement), new PropertyMetadata(default(Geometry)));
public static void SetGeometry(DependencyObject element, Geometry value)
=> element.SetValue(GeometryProperty, value);
public static Geometry GetGeometry(DependencyObject element)
=> (Geometry) element.GetValue(GeometryProperty);
public static readonly DependencyProperty WidthProperty = DependencyProperty.RegisterAttached(
"Width", typeof(double), typeof(IconElement), new PropertyMetadata(double.NaN));
public static void SetWidth(DependencyObject element, double value)
=> element.SetValue(WidthProperty, value);
public static double GetWidth(DependencyObject element)
=> (double) element.GetValue(WidthProperty);
public static readonly DependencyProperty HeightProperty = DependencyProperty.RegisterAttached(
"Height", typeof(double), typeof(IconElement), new PropertyMetadata(double.NaN));
public static void SetHeight(DependencyObject element, double value)
=> element.SetValue(HeightProperty, value);
public static double GetHeight(DependencyObject element)
=> (double) element.GetValue(HeightProperty);
}
}

View File

@@ -0,0 +1,111 @@

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
namespace HandyControl.Controls
{
public class MenuTopLineAttach
{
public static readonly DependencyProperty PopupProperty = DependencyProperty.RegisterAttached(
"Popup", typeof(Popup), typeof(MenuTopLineAttach), new PropertyMetadata(default(Popup), OnPopupChanged));
private static void OnPopupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var topLine = (FrameworkElement)d;
if (e.NewValue is Popup)
{
Popup popup = e.NewValue as Popup;
MenuItem menuItem = popup.TemplatedParent as MenuItem;
SetTopLine(menuItem, topLine);
menuItem.Loaded += MenuItem_Loaded;
}
}
private static void MenuItem_Loaded(object sender, RoutedEventArgs e)
{
var menuItem = (FrameworkElement)sender;
menuItem.Unloaded += MenuItem_Unloaded;
var topLine = GetTopLine(menuItem);
var popup = GetPopup(topLine);
if (popup != null)
{
popup.Opened += Popup_Opened;
}
}
private static void MenuItem_Unloaded(object sender, RoutedEventArgs e)
{
var menuItem = (FrameworkElement)sender;
menuItem.Unloaded -= MenuItem_Unloaded;
var topLine = GetTopLine(menuItem);
var popup = GetPopup(topLine);
if (popup != null)
{
popup.Opened -= Popup_Opened;
}
}
private static void Popup_Opened(object sender, EventArgs e)
{
var popup = (Popup)sender;
if (popup.TemplatedParent is MenuItem menuItem)
{
var topLine = GetTopLine(menuItem);
if (topLine == null) return;
topLine.HorizontalAlignment = HorizontalAlignment.Left;
topLine.Width = menuItem.ActualWidth;
topLine.Margin = new Thickness();
var positionLeftTop = menuItem.PointToScreen(new Point());
var positionRightBottom = menuItem.PointToScreen(new Point(menuItem.ActualWidth, menuItem.ActualHeight));
ScreenHelper.FindMonitorRectsFromPoint(InteropMethods.GetCursorPos(), out _, out var workAreaRect);
var panel = VisualHelper.GetParent<Panel>(topLine);
if (positionLeftTop.X < 0)
{
topLine.Margin = new Thickness(positionLeftTop.X - panel.Margin.Left, 0, 0, 0);
}
else if (positionLeftTop.X + panel.ActualWidth > workAreaRect.Right)
{
var overflowWidth = positionRightBottom.X - workAreaRect.Right;
if (overflowWidth > 0)
{
topLine.Width -= overflowWidth + panel.Margin.Right;
}
topLine.HorizontalAlignment = HorizontalAlignment.Left;
topLine.Margin = new Thickness(positionLeftTop.X + panel.ActualWidth - workAreaRect.Right + panel.Margin.Right, 0, 0, 0);
}
if (positionRightBottom.Y > workAreaRect.Bottom)
{
topLine.Width = 0;
topLine.HorizontalAlignment = HorizontalAlignment.Stretch;
topLine.Margin = new Thickness();
}
}
}
public static void SetPopup(DependencyObject element, Popup value)
=> element.SetValue(PopupProperty, value);
public static Popup GetPopup(DependencyObject element)
=> (Popup)element.GetValue(PopupProperty);
internal static readonly DependencyProperty TopLineProperty = DependencyProperty.RegisterAttached(
"TopLine", typeof(FrameworkElement), typeof(MenuTopLineAttach), new PropertyMetadata(default(FrameworkElement)));
internal static void SetTopLine(DependencyObject element, FrameworkElement value)
=> element.SetValue(TopLineProperty, value);
internal static FrameworkElement GetTopLine(DependencyObject element)
=> (FrameworkElement)element.GetValue(TopLineProperty);
}
}

View File

@@ -0,0 +1,19 @@

using System.Windows;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class ScrollViewerAttach
{
public static readonly DependencyProperty AutoHideProperty = DependencyProperty.RegisterAttached(
"AutoHide", typeof(bool), typeof(ScrollViewerAttach), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetAutoHide(DependencyObject element, bool value)
=> element.SetValue(AutoHideProperty, value);
public static bool GetAutoHide(DependencyObject element)
=> (bool) element.GetValue(AutoHideProperty);
}
}

View File

@@ -0,0 +1,192 @@

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class ScrollViewer : System.Windows.Controls.ScrollViewer
{
private double _totalVerticalOffset;
private double _totalHorizontalOffset;
private bool _isRunning;
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation", typeof(Orientation), typeof(ScrollViewer), new PropertyMetadata(Orientation.Vertical));
public Orientation Orientation
{
get => (Orientation) GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
public static readonly DependencyProperty CanMouseWheelProperty = DependencyProperty.Register(
"CanMouseWheel", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.TrueBox));
public bool CanMouseWheel
{
get => (bool) GetValue(CanMouseWheelProperty);
set => SetValue(CanMouseWheelProperty, ValueBoxes.BooleanBox(value));
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
if (!CanMouseWheel) return;
if (!IsInertiaEnabled)
{
if (Orientation == Orientation.Vertical)
{
base.OnMouseWheel(e);
}
else
{
_totalHorizontalOffset = HorizontalOffset;
CurrentHorizontalOffset = HorizontalOffset;
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
CurrentHorizontalOffset = _totalHorizontalOffset;
}
return;
}
e.Handled = true;
if (Orientation == Orientation.Vertical)
{
if (!_isRunning)
{
_totalVerticalOffset = VerticalOffset;
CurrentVerticalOffset = VerticalOffset;
}
_totalVerticalOffset = Math.Min(Math.Max(0, _totalVerticalOffset - e.Delta), ScrollableHeight);
ScrollToVerticalOffsetWithAnimation(_totalVerticalOffset);
}
else
{
if (!_isRunning)
{
_totalHorizontalOffset = HorizontalOffset;
CurrentHorizontalOffset = HorizontalOffset;
}
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
ScrollToHorizontalOffsetWithAnimation(_totalHorizontalOffset);
}
}
internal void ScrollToTopInternal(double milliseconds = 500)
{
if (!_isRunning)
{
_totalVerticalOffset = VerticalOffset;
CurrentVerticalOffset = VerticalOffset;
}
ScrollToVerticalOffsetWithAnimation(0, milliseconds);
}
public void ScrollToVerticalOffsetWithAnimation(double offset, double milliseconds = 500)
{
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
animation.EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseOut
};
animation.FillBehavior = FillBehavior.Stop;
animation.Completed += (s, e1) =>
{
CurrentVerticalOffset = offset;
_isRunning = false;
};
_isRunning = true;
BeginAnimation(CurrentVerticalOffsetProperty, animation, HandoffBehavior.Compose);
}
public void ScrollToHorizontalOffsetWithAnimation(double offset, double milliseconds = 500)
{
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
animation.EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseOut
};
animation.FillBehavior = FillBehavior.Stop;
animation.Completed += (s, e1) =>
{
CurrentHorizontalOffset = offset;
_isRunning = false;
};
_isRunning = true;
BeginAnimation(CurrentHorizontalOffsetProperty, animation, HandoffBehavior.Compose);
}
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) =>
IsPenetrating ? null : base.HitTestCore(hitTestParameters);
public static readonly DependencyProperty IsInertiaEnabledProperty = DependencyProperty.RegisterAttached(
"IsInertiaEnabled", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox));
public static void SetIsInertiaEnabled(DependencyObject element, bool value) => element.SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsInertiaEnabled(DependencyObject element) => (bool) element.GetValue(IsInertiaEnabledProperty);
public bool IsInertiaEnabled
{
get => (bool) GetValue(IsInertiaEnabledProperty);
set => SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty IsPenetratingProperty = DependencyProperty.RegisterAttached(
"IsPenetrating", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsPenetrating
{
get => (bool) GetValue(IsPenetratingProperty);
set => SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
}
public static void SetIsPenetrating(DependencyObject element, bool value) => element.SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsPenetrating(DependencyObject element) => (bool) element.GetValue(IsPenetratingProperty);
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentVerticalOffsetChanged));
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ScrollViewer ctl && e.NewValue is double v)
{
ctl.ScrollToVerticalOffset(v);
}
}
internal double CurrentVerticalOffset
{
get => (double) GetValue(CurrentVerticalOffsetProperty);
set => SetValue(CurrentVerticalOffsetProperty, value);
}
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentHorizontalOffsetChanged));
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ScrollViewer ctl && e.NewValue is double v)
{
ctl.ScrollToHorizontalOffset(v);
}
}
internal double CurrentHorizontalOffset
{
get => (double) GetValue(CurrentHorizontalOffsetProperty);
set => SetValue(CurrentHorizontalOffsetProperty, value);
}
}
}

View File

@@ -0,0 +1,37 @@

using System;
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
public class SimplePanel : Panel
{
protected override Size MeasureOverride(Size constraint)
{
var maxSize = new Size();
foreach (UIElement child in InternalChildren)
{
if (child != null)
{
child.Measure(constraint);
maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
}
}
return maxSize;
}
protected override Size ArrangeOverride(Size arrangeSize)
{
foreach (UIElement child in InternalChildren)
{
child?.Arrange(new Rect(arrangeSize));
}
return arrangeSize;
}
}
}

View File

@@ -0,0 +1,24 @@

namespace HandyControl.Data
{
internal static class ValueBoxes
{
internal static object TrueBox = true;
internal static object FalseBox = false;
internal static object Double0Box = .0;
internal static object Double01Box = .1;
internal static object Double1Box = 1.0;
internal static object Double10Box = 10.0;
internal static object Double20Box = 20.0;
internal static object Double100Box = 100.0;
internal static object Double200Box = 200.0;
internal static object Double300Box = 300.0;
internal static object DoubleNeg1Box = -1.0;
internal static object Int0Box = 0;
internal static object Int1Box = 1;
internal static object Int2Box = 2;
internal static object Int5Box = 5;
internal static object Int99Box = 99;
internal static object BooleanBox(bool value) => value ? TrueBox : FalseBox;
}
}

View File

@@ -0,0 +1,81 @@

using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Tools.Extension;
namespace HandyControl.Tools
{
public class AnimationHelper
{
public static ThicknessAnimation CreateAnimation(Thickness thickness = default, double milliseconds = 200)
{
return new ThicknessAnimation(thickness, new Duration(TimeSpan.FromMilliseconds(milliseconds)))
{
EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut }
};
}
public static DoubleAnimation CreateAnimation(double toValue, double milliseconds = 200)
{
return new DoubleAnimation(toValue, new Duration(TimeSpan.FromMilliseconds(milliseconds)))
{
EasingFunction = new PowerEase { EasingMode = EasingMode.EaseInOut }
};
}
internal static void DecomposeGeometryStr(string geometryStr, out double[] arr)
{
var collection = Regex.Matches(geometryStr, RegexPatterns.DigitsPattern);
arr = new double[collection.Count];
for (var i = 0; i < collection.Count; i++)
{
arr[i] = collection[i].Value.Value<double>();
}
}
internal static Geometry ComposeGeometry(string[] strings, double[] arr)
{
var builder = new StringBuilder(strings[0]);
for (var i = 0; i < arr.Length; i++)
{
var s = strings[i + 1];
var n = arr[i];
if (!double.IsNaN(n))
{
builder.Append(n).Append(s);
}
}
return Geometry.Parse(builder.ToString());
}
internal static Geometry InterpolateGeometry(double[] from, double[] to, double progress, string[] strings)
{
var accumulated = new double[to.Length];
for (var i = 0; i < to.Length; i++)
{
var fromValue = from[i];
accumulated[i] = fromValue + (to[i] - fromValue) * progress;
}
return ComposeGeometry(strings, accumulated);
}
internal static double[] InterpolateGeometryValue(double[] from, double[] to, double progress)
{
var accumulated = new double[to.Length];
for (var i = 0; i < to.Length; i++)
{
var fromValue = from[i];
accumulated[i] = fromValue + (to[i] - fromValue) * progress;
}
return accumulated;
}
}
}

View File

@@ -0,0 +1,32 @@

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace HandyControl.Tools.Converter
{
public class BorderCircularConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 2 && values[0] is double width && values[1] is double height)
{
if (width < double.Epsilon || height < double.Epsilon)
{
return new CornerRadius();
}
var min = Math.Min(width, height);
return new CornerRadius(min / 2);
}
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@@ -0,0 +1,33 @@

using System;
using System.ComponentModel;
namespace HandyControl.Tools.Extension
{
public static class StringExtension
{
public static T Value<T>(this string input)
{
try
{
return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return default;
}
}
public static object Value(this string input, Type type)
{
try
{
return TypeDescriptor.GetConverter(type).ConvertFromString(input);
}
catch
{
return null;
}
}
}
}

View File

@@ -0,0 +1,87 @@

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
{
internal class ScreenHelper
{
internal static void FindMaximumSingleMonitorRectangle(Rect windowRect, out Rect screenSubRect, out Rect monitorRect)
{
var windowRect2 = new InteropValues.RECT(windowRect);
FindMaximumSingleMonitorRectangle(windowRect2, out var rect, out var rect2);
screenSubRect = new Rect(rect.Position, rect.Size);
monitorRect = new Rect(rect2.Position, rect2.Size);
}
private static void FindMaximumSingleMonitorRectangle(InteropValues.RECT windowRect, out InteropValues.RECT screenSubRect, out InteropValues.RECT monitorRect)
{
var rects = new List<InteropValues.RECT>();
InteropMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero,
delegate (IntPtr hMonitor, IntPtr hdcMonitor, ref InteropValues.RECT rect, IntPtr lpData)
{
var monitorInfo = default(InteropValues.MONITORINFO);
monitorInfo.cbSize = (uint) Marshal.SizeOf(typeof(InteropValues.MONITORINFO));
InteropMethods.GetMonitorInfo(hMonitor, ref monitorInfo);
rects.Add(monitorInfo.rcWork);
return true;
}, IntPtr.Zero);
var num = 0L;
screenSubRect = new InteropValues.RECT
{
Left = 0,
Right = 0,
Top = 0,
Bottom = 0
};
monitorRect = new InteropValues.RECT
{
Left = 0,
Right = 0,
Top = 0,
Bottom = 0
};
foreach (var current in rects)
{
var rect = current;
InteropMethods.IntersectRect(out var rECT2, ref rect, ref windowRect);
var num2 = (long) (rECT2.Width * rECT2.Height);
if (num2 > num)
{
screenSubRect = rECT2;
monitorRect = current;
num = num2;
}
}
}
internal static void FindMonitorRectsFromPoint(Point point, out Rect monitorRect, out Rect workAreaRect)
{
var intPtr = InteropMethods.MonitorFromPoint(new InteropValues.POINT
{
X = (int) point.X,
Y = (int) point.Y
}, 2);
monitorRect = new Rect(0.0, 0.0, 0.0, 0.0);
workAreaRect = new Rect(0.0, 0.0, 0.0, 0.0);
if (intPtr != IntPtr.Zero)
{
InteropValues.MONITORINFO monitorInfo = default;
monitorInfo.cbSize = (uint) Marshal.SizeOf(typeof(InteropValues.MONITORINFO));
InteropMethods.GetMonitorInfo(intPtr, ref monitorInfo);
monitorRect = new Rect(monitorInfo.rcMonitor.Position, monitorInfo.rcMonitor.Size);
workAreaRect = new Rect(monitorInfo.rcWork.Position, monitorInfo.rcWork.Size);
}
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Linq;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
{
public static class VisualHelper
{
internal static VisualStateGroup TryGetVisualStateGroup(DependencyObject d, string groupName)
{
var root = GetImplementationRoot(d);
if (root == null) return null;
return VisualStateManager
.GetVisualStateGroups(root)?
.OfType<VisualStateGroup>()
.FirstOrDefault(group => string.CompareOrdinal(groupName, group.Name) == 0);
}
internal static FrameworkElement GetImplementationRoot(DependencyObject d) =>
1 == VisualTreeHelper.GetChildrenCount(d)
? VisualTreeHelper.GetChild(d, 0) as FrameworkElement
: null;
public static T GetChild<T>(DependencyObject d) where T : DependencyObject
{
if (d == null) return default;
if (d is T t) return t;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++)
{
var child = VisualTreeHelper.GetChild(d, i);
var result = GetChild<T>(child);
if (result != null) return result;
}
return default;
}
public static T GetParent<T>(DependencyObject d) where T : DependencyObject
{
if (d == null)
return default;
if (d is T)
return d as T;
if (d is Window)
return null;
return GetParent<T>(VisualTreeHelper.GetParent(d));
}
public static IntPtr GetHandle(this Visual visual) => (PresentationSource.FromVisual(visual) as HwndSource)?.Handle ?? IntPtr.Zero;
internal static void HitTestVisibleElements(Visual visual, HitTestResultCallback resultCallback, HitTestParameters parameters) =>
VisualTreeHelper.HitTest(visual, ExcludeNonVisualElements, resultCallback, parameters);
private static HitTestFilterBehavior ExcludeNonVisualElements(DependencyObject potentialHitTestTarget)
{
if (!(potentialHitTestTarget is Visual)) return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
if (!(potentialHitTestTarget is UIElement uIElement) || uIElement.IsVisible && uIElement.IsEnabled)
return HitTestFilterBehavior.Continue;
return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
}
internal static bool ModifyStyle(IntPtr hWnd, int styleToRemove, int styleToAdd)
{
var windowLong = InteropMethods.GetWindowLong(hWnd, InteropValues.GWL.STYLE);
var num = (windowLong & ~styleToRemove) | styleToAdd;
if (num == windowLong) return false;
InteropMethods.SetWindowLong(hWnd, InteropValues.GWL.STYLE, num);
return true;
}
}
}

Some files were not shown because too many files have changed in this diff Show More