Compare commits

...

103 Commits

Author SHA1 Message Date
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
23 changed files with 2050 additions and 1120 deletions

View File

@@ -6,8 +6,19 @@
🎞 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.
Like mpv, mpv.net is designed for power users, for regular users there is a
[mpv.net-next](https://github.com/mpv-net-player/mpv.net-next)
project under construction.
#### Graphical User Interface
@@ -63,6 +74,7 @@ Features that mpv and mpv.net have in common
--------------------------------------------
- Lua and JavaScript Scripting
- Hundreds available user scripts make mpv the most feature rich desktop video player
- Simple config files that are easy to read and edit
- JSON IPC to control the player with a external programs
- On Screen Controler (OSC, play control buttons) with modern flat design

View File

@@ -1,9 +1,112 @@
# 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/stax76/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 existant ARM and x86 support.
- 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.
@@ -18,7 +121,7 @@
- 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 ontop of the native OSC logo.
the drawing of the blue mpv.net logo on top of the native OSC logo.
- MediaInfo 22.03

View File

@@ -42,6 +42,10 @@ mpv focuses on the usage of the command line and the terminal,
mpv.net retains the ability to be used from the command line and
the terminal and adds a modern Windows GUI on top of it.
Like mpv, mpv.net is designed for power users, for regular users there is a
[mpv.net-next](https://github.com/mpv-net-player/mpv.net-next)
project under construction.
Download
--------
@@ -59,9 +63,11 @@ Installation
mpv.net requires the .NET Framework 4.8 and Windows 7 or higher and a modern graphics card.
For internet streaming from YouTube and similar sites, yt-dlp must be
copied into the mpv.net folder or the user environment variable PATH
must be edited to include the yt-dlp folder.
Internet streaming requires:
- 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/stax76/mpv.net/issues/401).
#### File Associations
@@ -215,7 +221,7 @@ A common task for the terminal is debugging scripts.
mpv.net specific commands
-------------------------
`script-message mpv.net <command> <arguments>`
`script-message-to mpvnet <command> <arguments>`
mpv.net commands are used when mpv commands don't exist or lack a feature.
@@ -232,9 +238,6 @@ Shows a file browser dialog to open external subtitle files.
Opens the config folder with Windows File Explorer.
### open-files [\<flags\>]
**no-folder**
For single files prevents loading the complete folder into the playlist.
**append**
Appends files to the playlist.
@@ -255,6 +258,10 @@ or multiple files in the file clipboard format.
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.
@@ -263,12 +270,21 @@ already the first entry, nothing happens.
Jumps to the last playlist entry, if the loaded file is
already the last entry, nothing happens.
### quick-bookmark
On the first press a bookmark is saved, on the second
press it is restored and removed. When a new file is
loaded the bookmark is removed.
### reg-file-assoc \<audio|video|image\>
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.
@@ -282,6 +298,9 @@ Shows available audio devices in a message box.
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.
@@ -302,7 +321,7 @@ Shows available demuxers.
Shows the history file when existing.
### show-info
Shows a simple file info.
Shows media info on screen, a second key press shows more detailed media info.
### show-input-editor
Shows the input editor.
@@ -317,6 +336,9 @@ Shows media info in a messsge box.
**editor**
Shows media info in the text editor.
**osd**
Displays media info on screen.
**full**
Shows fully detailed media info.
@@ -334,7 +356,7 @@ and allows to play the selected entry.
Shows available profiles with a message box.
### show-progress
Shows a simple OSD progress message.
Shows a simple OSD progress message with time and date.
### show-properties
Shows available properties in the command palette and
@@ -365,6 +387,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.
#### --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\>
Adds files to the playlist, requires [--process-instance=single](#--process-instancevalue).
@@ -409,22 +437,24 @@ Window size is remembered in the current session.
**always**
Window size is always remembered.
#### --start-threshold=\<milliseconds\>
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
#### --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
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\>
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
### Playback
@@ -462,6 +492,10 @@ Force a single process and add files to playlist.
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)
#### --video-file-extensions=\<string\>
Video file extensions used to create file associations and used by the auto-load-folder feature.
@@ -507,9 +541,12 @@ Color theme used in light mode. Default: light
#### --show-logo=\<yes|no\>
Draws the blue mpv.net logo ontop of the native OSC logo.
Changes take effect after application restart. Default: yes
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
--------------
@@ -575,64 +612,28 @@ Scripting
#### 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.
Error and debug messages are 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 in the wiki](https://github.com/mpv-player/mpv/wiki/User-Scripts)
[mpv user scripts on GitHub](https://github.com/topics/mpv-script)
[mpv user scripts found by Google](https://www.google.com/search?q=mpv+script)
Lua scripting is documented in the mpv.net wiki [here](https://github.com/stax76/mpv.net/wiki/Extending-mpv-and-mpv.net-via-Lua-scripting).
#### JavaScript
File Type: `js`
Location: `<config folder>\scripts`
The JavaScript script host is built into libmpv.
Error and debug messages are printed on the terminal.
JavaScript scripts are loaded before the first media file loads.
[mpv JavaScript documentation](https://mpv.io/manual/master/#javascript)
[mpv user scripts](https://github.com/mpv-player/mpv/wiki/User-Scripts)
#### PowerShell
File Type: `ps1`
Location: `<config folder>\scripts-ps`
The PowerShell scripting host is like extensions not
initialized before media files are loaded.
mpv.net does not define scripting interfaces but instead exposed
its complete internals, there are no compatibility guaranties.
The PowerShell scripting host is not initialized before media files are loaded.
[Example Scripts](../../../tree/master/src/Scripts)
#### C#
File Type: `cs`
Location: `<config folder>\scripts-cs`
mpv.net does not define scripting interfaces but instead exposed
its complete internals, there are no compatibility guaranties.
There are no compatibility guaranties.
Script code can be written within a C# [extension](../../../tree/master/src/Extensions),
that way full code completion and debugger support is available.
@@ -641,6 +642,10 @@ from the extension to a lightweight standalone script.
The script host uses an old C# version, modern features
like string interpolation are not available.
There are synchronous and asynchronous events, prefer asynchronous events
and don't block synchronous events and observed properties, as it would
block the main event loop.
The C# scripting host is like [extensions](../../../tree/master/src/Extensions)
not initialized before media files are loaded.
@@ -657,9 +662,9 @@ and the filename must have the same name as the directory:
<config folder>\extensions\ExampleExtension\ExampleExtension.dll
```
mpv.net does not define extension interfaces but instead exposed
its complete internals, there are no compatibility guaranties.
There are synchronous and asynchronous events, prefer asynchronous events
and don't block synchronous events and observed properties, as it would
block the main event loop.
### Walkthrough creating an extension
@@ -766,6 +771,7 @@ https://mpv.io/manual/master/#window
- [keepaspect-window](https://mpv.io/manual/master/#options-keepaspect-window)
- [ontop](https://mpv.io/manual/master/#options-ontop)
- [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)
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized)
@@ -774,10 +780,12 @@ https://mpv.io/manual/master/#window
**Partly implemented are:**
- [autofit-larger](https://mpv.io/manual/master/#options-autofit-larger)
- [autofit-smaller](https://mpv.io/manual/master/#options-autofit-smaller)
- [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.
mpv.net specific window features are documented in the [screen section](#screen).
@@ -797,6 +805,13 @@ need an own implementation in mpv.net, so far implemented are:
--vd=help
--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

View File

@@ -2,7 +2,7 @@
mpv.net手册
==============
同步源提交_[20211114](https://github.com/stax76/mpv.net/commit/243b45326ef8defa038edacd01fafee13f6a009a#diff-bf7b5e59783955f479505de4969f792255eca0a69945ccfe3ec5dda409495bbe)
适配版本 [v6.0.0.0-beta](https://github.com/stax76/mpv.net/releases/tag/v6.0.0.0-beta)
**[ENGLISH](Manual.md)** | **简体中文**
@@ -15,8 +15,10 @@ mpv.net手册
* [支持](#支持)
* [设置](#设置)
* [快捷键和上下文菜单](#快捷键和上下文菜单)
* [命令面板](#命令面板)
* [命令行界面](#命令行界面)
* [终端](#终端)
* [mpv.net的专属命令](#mpvnet的专属命令)
* [mpv.net的专属选项](#mpvnet的专属选项)
* [外部工具](#外部工具)
* [脚本](#脚本)
@@ -39,6 +41,9 @@ mpv.net出于兼容mpv而设计几乎所有mpv的功能都可用因为它
mpv专注命令行与终端的使用而mpv.net保留了这些并加入了现代化的图形界面。
与mpv一样mpv.net也是为高级用户设计的对于普通用户
有一个正在建设中的 [mpv.net-next](https://github.com/mpv-net-player/mpv.net-next) 项目。
下载
--------
@@ -57,7 +62,10 @@ mpv专注命令行与终端的使用而mpv.net保留了这些并加入了现
mpv.net需要.NET Framework 4.8运行库和高于win7版本的系统以及一张不太旧的显卡。
对于网络串流必须手动下载安装yt-dlp它必须位于环境变量 PATH 或启动目录中。
互联网流媒体需要:
- 下载[yt-dlp](https://github.com/yt-dlp/yt-dlp)并将其添加到[用户环境变量PATH](https://www.google.com/search?q=user+environment+variable+PATH)
- 在使用代理服务器的情况下,需要[手动配置](https://github.com/stax76/mpv.net/issues/401)。
#### 文件关联
@@ -66,14 +74,16 @@ mpv.net需要.NET Framework 4.8运行库和高于win7版本的系统以及一张
注册完文件关联后,进入 "Windows设置 > 应用 > 默认应用" (Win+I, ms-settings:defaultapps)
然后选择mpv. net作为视频/音频/图像的默认程序。
另一种注册文件关联的方式是使用文件资源管理器,选中媒体文件后,选择上下文菜单的 '打开方式 > 选择其它应用' 。
另一种注册文件关联的方式是使用文件资源管理器,选中媒体文件后,
选择上下文菜单的 '打开方式 > 选择其它应用' 。
[Open with++](#open-with) 可用来扩展资源管理器的上下文菜单
[Play with mpv.net](https://github.com/stax76/OpenWithPlusPlus#play-with-mpvnet) 和
[Add to mpv.net playlist](https://github.com/stax76/OpenWithPlusPlus#add-to-mpvnet-playlist).
可用来获取 'Play with mpv.net' 和 'Add to mpv.net playlist' 的菜单子项
当在资源管理器中选择多个文件并按 enter 键时文件会在mpv.net随机排序打开最多限制15个文件。
当在资源管理器中选择多个文件并按 enter 键时文件会在mpv.net随机排序打开
最多限制15个文件。
支持
@@ -104,9 +114,7 @@ mpv.net的专属选项保存在 mpvnet.conf 文件中,
----------------------
键鼠的快捷键和上下文菜单的操作保存在 input.conf 文件中,
如果设置目录中不存在,将使用以下文件生成默认的初始设置:
[input.conf defaults](../../../tree/master/src/Resources/input.conf.txt)
如果设置目录中不存在,mpv.net会用默认值生成它。
请注意,一旦 input.conf 存在, mpv.net 就不能更新它,这意味着当 mpv.net 升级了
新的版本或改变了的默认菜单项时,菜单条目就会过时。获得最新菜单的唯一方法是
@@ -136,6 +144,35 @@ mpv的input选项
https://mpv.io/manual/master/#input
命令面板
---------------
命令面板能用来快速查找、选择和执行命令。
它也可以用来方便的找到快捷键。
命令面板提供了以下功能:
- 以不同方式显示 mediainfo
- 显示和选择音轨
- 显示和选择字幕轨
- 显示和选择播放列表的文件
- 显示和选择最近的文件
- 显示可用的mpv属性
- 显示可用的解码器
- 显示可用的解复用器
- 显示可用的按键
- 显示可用的协议
| 按键 | 动作 |
| ----- | -------------- |
| F1 | 显示命令面板 |
| Esc | 隐藏命令面板 |
| Enter | 执行所选的条目 |
| Up | 光标向上移动 |
| Down | 光标向下移动 |
命令行界面
----------------------
@@ -161,12 +198,12 @@ mpv的参数与mpv.net共通例如
https://mpv.io/manual/master/#properties
mpv.net可以使用以下功能列出所有属性
mpv.net可以使用以下功能列出所有可用的属性:
'Context Menu > View > Show Properties'
_Context Menu > View > Advanced > Show Properties_
mpv.net通常不支持非属性的运行时状态切换
mpv有一些基于非属性的开关在mpv.net中一般不受支持。
终端
@@ -174,11 +211,150 @@ mpv.net通常不支持非属性的运行时状态切换
当mpv. net从终端启动时它将输出状态、错误和调试消息并接受终端的输入。
在菜单中的 'Tools > Setup' 可以将mpv.net添加到环境变量PATH。
终端的常见用处是脚本调试。
mpv.net的专属命令
-------------------------
`script-message-to mpvnet <command> <arguments>`
mpv.net命令可在mpv命令不存在或缺乏某种功能时使用。
### cycle-audio
切换到下一个音轨并显示该音轨的信息。
### load-audio
显示一个资源管理器的对话框来加载外部音频文件。
### load-sub
显示一个资源管理器的对话框来加载外部字幕文件。
### open-conf-folder
用Windows资源管理器打开配置文件夹。
### open-files [\<flags\>]
**append**
追加文件到播放列表中。
打开一个资源管理器的对话框,以便选择要打开的文件。资源管理器的对话框
支持多选以一次性加载多个文件。按住CTRL键可以将这些文件追加到播放列表中。
### open-optical-media
显示一个资源管理器的对话框来打开一个DVD或BD文件夹。ISO镜像不需要被挂载
但可以直接用 open-files 命令打开。
### open-clipboard
从剪贴板打开单个的URL或文件路径或以文件剪贴板中的格式打开多个文件。
### play-pause
循环切换 pause 的属性。如果播放列表为空,将加载最近文件列表中的最新文件。
### playlist-add \<integer\>
通过指定的整数值来跳转播放的条目。如果已到达末尾则它会跳到开头,反之亦然。
### playlist-first
跳转到播放列表的第一个条目,如果加载的文件已经是第一个条目,则无动作。
### playlist-last
跳转到播放列表的最后一个条目,如果加载的文件已经是最后一个条目,则无动作。
### quick-bookmark
第一次触发时,书签被保存,第二次触发时,它被恢复并移除。当加载新文件时,
书签也会被移除。
### reg-file-assoc \<audio|video|image\>
注册文件关联。
### scale-window \<factor\>
减小或增大窗口的尺寸。
### shell-execute \<file|URL\>
Shell执行单个文件或URL。
### show-about
显示 "关于" 的对话框。
### show-audio-devices
在一个信息框中显示可用的音频设备。
### show-audio-tracks
在命令面板中显示可用的音轨,并允许加载选中的音轨。
### show-command-palette
显示命令面板。
### show-commands
显示可用的mpv输入命令。
### show-conf-editor
显示配置编辑器。
### show-decoders
显示可用的解码器。
### show-demuxers
显示可用的解复用器。
### show-history
显示已有的历史文件。
### show-info
在屏幕上显示mediainfo第二次触发可显示更详细的媒体信息。
### show-input-editor
显示器快捷键编辑器。
### show-keys
在命令面板中显示可用的按键。(与 `--input-keylist` 显示的内容一致)
### show-media-info [\<flags\>]
**msgbox**
在一个信息框中显示mediainfo
**editor**
在一个文本编辑器中显示mediainfo
**osd**
OSD上显示mediainfo
**full**
显示mediainfo的完整细节
**raw**
显示带有原始属性名的mediainfo
### show-menu
显示上下文菜单。
### show-playlist
在命令面板中显示播放列表,并允许播放选中的条目。
### show-profiles
用一个信息框显示可用的profile
### show-progress
显示一个简易的OSD进度条信息附带时间和日期。
### show-properties
在命令面板中显示可用的属性,并允许显示所选属性的值。
### show-protocols
在命令面板中显示可用的协议。
### show-recent
在命令面板中显示最近播放的文件和URL并允许选择和播放条目。
### show-subtitle-tracks
在命令面板中显示可用的字幕轨,并允许激活选中的字幕。
### show-text \<text\> \<duration\> \<font-size\>
显示一个具有指定文本、持续时间和字体大小的OSD信息。
### window-scale \<factor\>
职能类似于mpv的属性 [window-scale](https://mpv.io/manual/master/#command-interface-window-scale)
mpv.net的专属选项
------------------------
@@ -193,8 +369,8 @@ mpv.net的专属选项
#### --command=\<input command\>
通过命令行向正在运行的mpv.net实例发送输入命令例如使用 AutoHotkey 创建全局热键,
必须设置 [process-instance=single](#--process-instancevalue) 。
通过命令行向正在运行的mpv.net实例发送输入命令例如使用 AutoHotkey 创建
全局热键,必须设置 [process-instance=single](#--process-instancevalue) 。
### Audio
@@ -255,6 +431,11 @@ mpv.net的专属选项
打开单个文件时,自动将整个目录加载到播放列表中。可以通过 shift 键临时禁用。默认yes
#### --auto-play=\<yes|no\>
如果在播放器暂停时,加载另一个文件,会自动恢复播放。
### General
#### --process-instance=\<value\>
@@ -279,6 +460,11 @@ mpv.net的专属选项
最近文件的记录数量。默认15
#### --media-info=\<yes|no\>
使用MediaInfo而不是mpv来访问媒体信息。默认yes
#### --video-file-extensions=\<string\>
用于创建文件关联的视频文件扩展名,由自动加载文件夹的功能使用。
@@ -315,7 +501,7 @@ mpv.net的专属选项
从不
#### ---dark-theme=\<string\>
#### --dark-theme=\<string\>
深色模式中使用的配色主题。默认dark
@@ -329,6 +515,16 @@ mpv.net的专属选项
[配色主题](#配色主题)
#### --show-logo=\<yes|no\>
在原始OSC标志的基础上绘制蓝色的mpvnet图标。默认yes
#### --show-santa-logo=\<yes|no\>
在12月绘制蓝色的mpvnet图标时使用圣诞彩蛋。默认yes
外部工具
--------------
@@ -385,6 +581,15 @@ Universal Remote 的 File Browser 功能十分有用。
Philips code 0556 和 FLIRC USB (gen2) 一同被使用。
### External Application Button
视频可以通过Chrome扩展程序的外部应用按钮进行流式传输或轻松下载对于下载推荐
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=.+','')"`
脚本
---------
@@ -396,13 +601,17 @@ Philips code 0556 和 FLIRC USB (gen2) 一同被使用。
Lua脚本的host由libmpv内建。
没有调试支持,只有错误和调试消息输出在终端上。
错误和调试消息输出在终端上。
Lua脚本在第一个媒体文件打开之前加载。
[mpv Lua 文档](https://mpv.io/manual/master/#lua-scripting)
[mpv用户脚本](https://github.com/mpv-player/mpv/wiki/User-Scripts)
[mpv 用户脚本 wiki](https://github.com/mpv-player/mpv/wiki/User-Scripts)
[mpv 用户脚本 GitHub](https://github.com/topics/mpv-script)
[mpv 用户脚本 Google](https://www.google.com/search?q=mpv+script)
#### JavaScript
@@ -413,7 +622,7 @@ Lua脚本在第一个媒体文件打开之前加载。
JavaScriptLua脚本的host由libmpv内建。
没有调试支持,只有错误和调试消息输出在终端上。
错误和调试消息输出在终端上。
JavaScript脚本在第一个媒体文件打开之前加载。
@@ -443,8 +652,10 @@ mpv.net没有定义脚本接口而是公开了它的完整内部没有兼
mpv.net没有定义脚本接口而是公开了它的完整内部没有兼容性保证。
脚本代码可以在C#[扩展](../../../tree/master/src/Extensions)中编写,这样就可以获得
完整的代码和调试器支持。一旦代码被调试和开发完成,就可以将其从扩展转移到轻量级的独立脚本。
脚本代码可以在C#[扩展](../../../tree/master/src/Extensions)中编写,这样
就可以获得完整的代码和调试器支持。一旦代码被调试和开发完成,就可以将其
从扩展转移到轻量级的独立脚本。脚本host使用的是旧的C#版本,像字符串插值
这样的现代功能是不存在的。
C#脚本的host类似于[扩展](../../../tree/master/src/Extensions),在打开媒体文件前尚未初始化。
@@ -589,6 +800,13 @@ mpv.net支持基于属性的mpv命令行选项这意味着它支持mpv几乎
--version
### 其它限制
mpv的属性 [idle](https://mpv.io/manual/master/#options-idle) 在mpv.net中
也会相应的发挥作用但是LUA脚本获取到的值始终是 `yes` 因为mpv.net必须
设置它才能正常工作这是一个难以攻克的来自libmpv的限制。
### mpv.net的专属选项
在config editor中输入 `mpv.net` 检索这些选项,在[此处](#mpvnet的专属选项)的手册中有对应说明。
@@ -1281,8 +1499,8 @@ input.conf 文件内涵mpv的键鼠绑定
### Tools > Show History
显示包含历史记录的文本文件。如果文件不存在,则会询问是否在设置文件夹中创建该文件。
一旦文件存在,则写入历史记录(包括时间和文件名)
显示包含历史记录的文本文件。如果文件不存在,则会询问是否在设置文件夹中
创建该文件。一旦文件存在,则写入历史记录(包括时间和文件名)
屏蔽部分路径的参数:

View File

@@ -24,16 +24,23 @@ namespace mpvnet
public static bool AutoLoadFolder { get; set; } = true;
public static bool AutoPlay { get; set; }
public static bool DebugMode { get; set; }
public static bool Exit { get; set; }
public static bool IsTerminalAttached { get; } = Environment.GetEnvironmentVariable("_started_from_console") == "yes";
public static bool MediaInfo { get; set; } = true;
public static bool Queue { get; set; }
public static bool RememberVolume { get; set; } = true;
public static bool RememberWindowPosition { get; set; }
public static bool ShowLogo { get; set; } = true;
public static bool ShowSantaLogo { get; set; } = true;
public static int StartThreshold { get; set; } = 1500;
public static int RecentCount { get; set; } = 15;
public static float 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; }
@@ -237,18 +244,23 @@ namespace mpvnet
case "audio-file-extensions": CorePlayer.AudioTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
case "auto-load-folder": AutoLoadFolder = value == "yes"; return true;
case "auto-play": AutoPlay = value == "yes"; return true;
case "autofit-image": AutofitImage = value.Trim('%').ToInt() / 100f; return true;
case "autofit-audio": AutofitAudio = value.Trim('%').ToInt() / 100f; return true;
case "dark-mode": DarkMode = value; return true;
case "dark-theme": DarkTheme = value.Trim('\'', '"'); return true;
case "debug-mode": DebugMode = value == "yes"; return true;
case "image-file-extensions": CorePlayer.ImageTypes = value.Split(" ,;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); return true;
case "light-theme": LightTheme = value.Trim('\'', '"'); return true;
case "media-info": MediaInfo = value == "yes"; return true;
case "minimum-aspect-ratio": MinimumAspectRatio = value.ToFloat(); return true;
case "minimum-aspect-ratio-audio": MinimumAspectRatioAudio = value.ToFloat(); return true;
case "process-instance": ProcessInstance = value; return true;
case "queue": Queue = value == "yes"; return true;
case "recent-count": RecentCount = value.ToInt(); return true;
case "remember-volume": RememberVolume = value == "yes"; return true;
case "show-logo": ShowLogo = 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;
@@ -267,5 +279,16 @@ namespace mpvnet
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

@@ -25,7 +25,7 @@ namespace mpvnet
static void Execute(string file)
{
string code = File.ReadAllText(file);
string filename = Path.GetFileNameWithoutExtension(file) + " " + StringHelp.GetMD5Hash(code) + ".dll";
string filename = Path.GetFileNameWithoutExtension(file) + " " + StringHelp.GetMD5Hash(code) + "-v6.dll";
string outputFile = Path.Combine(Path.GetTempPath(), filename);
if (!File.Exists(outputFile))

View File

@@ -6,15 +6,15 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media;
using WinForms = System.Windows.Forms;
using static mpvnet.Global;
using System.Windows.Media;
using System.Text.RegularExpressions;
namespace mpvnet
{
@@ -35,14 +35,18 @@ namespace mpvnet
case "open-optical-media": Open_DVD_Or_BD_Folder(); break;
case "open-url": OpenFromClipboard(); break; // deprecated 2022
case "play-pause": PlayPause(); break;
case "playlist-add": PlaylistAdd(Convert.ToInt32(args[0])); break;
case "playlist-first": PlaylistFirst(); break;
case "playlist-last": PlaylistLast(); break;
case "quick-bookmark": QuickBookmark(); break;
case "reg-file-assoc": RegisterFileAssociations(args[0]); break;
case "scale-window": ScaleWindow(float.Parse(args[0], CultureInfo.InvariantCulture)); break;
case "select-profile": SelectProfile(); break;
case "shell-execute": ProcessHelp.ShellExecute(args[0]); break;
case "show-about": ShowDialog(typeof(AboutWindow)); break;
case "show-audio-devices": Msg.ShowInfo(Core.GetPropertyOsdString("audio-device-list")); break;
case "show-audio-tracks": ShowAudioTracks(); break;
case "show-chapters": ShowChapters(); break;
case "show-command-palette": ShowCommandPalette(); break;
case "show-commands": ShowCommands(); break;
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
@@ -64,8 +68,6 @@ namespace mpvnet
case "show-subtitle-tracks": ShowSubtitleTracks(); break;
case "show-text": ShowText(args[0], Convert.ToInt32(args[1]), Convert.ToInt32(args[2])); break;
case "window-scale": WindowScale(float.Parse(args[0], CultureInfo.InvariantCulture)); break;
default: Terminal.WriteError($"No command '{id}' found, reset input.conf by deleting it."); break;
}
}
@@ -87,21 +89,15 @@ namespace mpvnet
public static void OpenFiles(params string[] args)
{
bool append = Control.ModifierKeys.HasFlag(Keys.Control);
bool loadFolder = true;
foreach (string arg in args)
{
if (arg == "append")
append = true;
if (arg == "no-folder")
loadFolder = false;
}
App.InvokeOnMainThread(new Action(() => {
using (var d = new OpenFileDialog() { Multiselect = true })
if (d.ShowDialog() == DialogResult.OK)
Core.LoadFiles(d.FileNames, loadFolder, append);
Core.LoadFiles(d.FileNames, true, append);
}));
}
@@ -115,18 +111,15 @@ namespace mpvnet
public static void PlaylistFirst()
{
int pos = Core.GetPropertyInt("playlist-pos");
if (pos != 0)
if (Core.PlaylistPos != 0)
Core.SetPropertyInt("playlist-pos", 0);
}
public static void PlaylistLast()
{
int pos = Core.GetPropertyInt("playlist-pos");
int count = Core.GetPropertyInt("playlist-count");
if (pos < count - 1)
if (Core.PlaylistPos < count - 1)
Core.SetPropertyInt("playlist-pos", count - 1);
}
@@ -162,79 +155,60 @@ namespace mpvnet
}
}
static int LastShowInfo;
public static void ShowInfo()
{
try
if (Core.PlaylistPos == -1)
return;
if (Environment.TickCount - LastShowInfo < 5000)
{
string performer, title, album, genre, date, duration, text = "";
long fileSize = 0;
string path = Core.GetPropertyString("path");
Core.Command("script-message-to mpvnet show-media-info osd");
LastShowInfo = 0;
return;
}
if (path.Contains("://"))
path = Core.GetPropertyString("media-title");
LastShowInfo = Environment.TickCount;
if (File.Exists(path))
string text;
long fileSize = 0;
string path = Core.GetPropertyString("path");
if (File.Exists(path))
{
fileSize = new FileInfo(path).Length;
if (CorePlayer.AudioTypes.Contains(path.Ext()))
{
fileSize = new FileInfo(path).Length;
if (CorePlayer.AudioTypes.Contains(path.Ext()))
{
using (MediaInfo mediaInfo = new MediaInfo(path))
{
performer = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Performer");
title = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Title");
album = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Album");
genre = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Genre");
date = mediaInfo.GetInfo(MediaInfoStreamKind.General, "Recorded_Date");
duration = mediaInfo.GetInfo(MediaInfoStreamKind.Audio, "Duration/String");
if (performer != "") text += "Artist: " + performer + "\n";
if (title != "") text += "Title: " + title + "\n";
if (album != "") text += "Album: " + album + "\n";
if (genre != "") text += "Genre: " + genre + "\n";
if (date != "") text += "Year: " + date + "\n";
if (duration != "") text += "Length: " + duration + "\n";
text += "Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n";
text += "Type: " + path.Ext().ToUpper();
Core.CommandV("show-text", text, "5000");
return;
}
}
else if (CorePlayer.ImageTypes.Contains(path.Ext()))
{
using (MediaInfo mediaInfo = new MediaInfo(path))
{
text =
"Width: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Width") + "\n" +
"Height: " + mediaInfo.GetInfo(MediaInfoStreamKind.Image, "Height") + "\n" +
"Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n" +
"Type: " + path.Ext().ToUpper();
Core.CommandV("show-text", text, "5000");
return;
}
}
text = Core.GetPropertyOsdString("filtered-metadata");
Core.CommandV("show-text", text, "5000");
return;
}
else if (CorePlayer.ImageTypes.Contains(path.Ext()))
{
text = "Width: " + Core.GetPropertyInt("width") + "\n" +
"Height: " + Core.GetPropertyInt("height") + "\n" +
"Size: " + Convert.ToInt32(fileSize / 1024.0) + " KB\n" +
"Type: " + path.Ext().ToUpper();
string videoFormat = Core.GetPropertyString("video-format").ToUpper();
string audioCodec = Core.GetPropertyString("audio-codec-name").ToUpper();
int width = Core.GetPropertyInt("video-params/w");
int height = Core.GetPropertyInt("video-params/h");
TimeSpan len = TimeSpan.FromSeconds(Core.GetPropertyDouble("duration"));
text = path.FileName() + "\n";
text += FormatTime(len.TotalMinutes) + ":" + FormatTime(len.Seconds) + "\n";
if (fileSize > 0) text += Convert.ToInt32(fileSize / 1024.0 / 1024.0) + " MB\n";
text += $"{width} x {height}\n";
text += $"{videoFormat}\n{audioCodec}";
Core.CommandV("show-text", text, "5000");
return;
}
}
Core.CommandV("show-text", text, "5000");
}
catch (Exception e)
{
App.ShowException(e);
}
if (path.Contains("://")) path = Core.GetPropertyString("media-title");
string videoFormat = Core.GetPropertyString("video-format").ToUpper();
string audioCodec = Core.GetPropertyString("audio-codec-name").ToUpper();
int width = Core.GetPropertyInt("video-params/w");
int height = Core.GetPropertyInt("video-params/h");
TimeSpan len = TimeSpan.FromSeconds(Core.GetPropertyDouble("duration"));
text = path.FileName() + "\n";
text += FormatTime(len.TotalMinutes) + ":" + FormatTime(len.Seconds) + "\n";
if (fileSize > 0) text += Convert.ToInt32(fileSize / 1024.0 / 1024.0) + " MB\n";
text += $"{width} x {height}\n";
text += $"{videoFormat}\n{audioCodec}";
Core.CommandV("show-text", text, "5000");
}
static string FormatTime(double value) => ((int)value).ToString("00");
@@ -247,7 +221,8 @@ namespace mpvnet
string text = FormatTime(position.TotalMinutes) + ":" +
FormatTime(position.Seconds) + " / " +
FormatTime(duration.TotalMinutes) + ":" +
FormatTime(duration.Seconds);
FormatTime(duration.Seconds) + " " +
DateTime.Now.ToString("H:mm dddd d MMMM", CultureInfo.InvariantCulture);
Core.CommandV("show-text", text, "5000");
}
@@ -262,15 +237,19 @@ namespace mpvnet
else
{
string clipboard = WinForms.Clipboard.GetText();
List<string> files = new List<string>();
if (string.IsNullOrEmpty(clipboard) || (!clipboard.Contains("://") && !File.Exists(clipboard)) ||
clipboard.Contains("\n"))
foreach (string i in clipboard.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
if (i.Contains("://") || File.Exists(i))
files.Add(i);
if (files.Count == 0)
{
App.ShowError("The clipboard does not contain a valid URL or file.");
return;
}
Core.LoadFiles(new [] { clipboard }, false, Control.ModifierKeys.HasFlag(Keys.Control));
Core.LoadFiles(files.ToArray(), false, Control.ModifierKeys.HasFlag(Keys.Control));
}
});
@@ -310,26 +289,30 @@ namespace mpvnet
public static void CycleAudio()
{
MediaTrack[] audioTracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
int len = audioTracks.Length;
Core.UpdateExternalTracks();
if (len < 1)
lock (Core.MediaTracksLock)
{
Core.CommandV("show-text", "No audio tracks");
return;
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
if (tracks.Length < 1)
{
Core.CommandV("show-text", "No audio tracks");
return;
}
int aid = Core.GetPropertyInt("aid");
if (tracks.Length > 1)
{
if (++aid > tracks.Length)
aid = 1;
Core.CommandV("set", "aid", aid.ToString());
}
Core.CommandV("show-text", aid + "/" + tracks.Length + ": " + tracks[aid - 1].Text.Substring(3), "5000");
}
int aid = Core.GetPropertyInt("aid");
if (len > 1)
{
if (++aid > len)
aid = 1;
Core.CommandV("set", "aid", aid.ToString());
}
Core.CommandV("show-text", aid + "/" + len + ": " + audioTracks[aid - 1].Text.Substring(3), "5000");
}
public static void ShowCommands()
@@ -359,7 +342,7 @@ namespace mpvnet
public static void ScaleWindow(float factor) => Core.RaiseScaleWindow(factor);
public static void WindowScale(float value) => Core.RaiseWindowScale(value);
public static void WindowScale(float value) => Core.RaiseWindowScaleNET(value);
public static void ShowText(string text, int duration = 0, int fontSize = 0)
{
@@ -381,10 +364,11 @@ namespace mpvnet
if (args == null || args.Length == 0)
{
(string Name, string Value)[] pairs = {
("Show text box", "script-message mpv.net show-media-info default"),
("Show text editor", "script-message mpv.net show-media-info editor"),
("Show full", "script-message mpv.net show-media-info editor full"),
("Show raw", "script-message mpv.net show-media-info editor full raw") };
("Show text box", "script-message-to mpvnet show-media-info default"),
("Show text editor", "script-message-to mpvnet show-media-info editor"),
("Show on screen", "script-message-to mpvnet show-media-info osd"),
("Show full", "script-message-to mpvnet show-media-info editor full"),
("Show raw", "script-message-to mpvnet show-media-info editor full raw") };
var list = pairs.Select(i => new CommandPaletteItem(i.Name, () => Core.Command(i.Value)));
CommandPalette.Instance.SetItems(list);
@@ -394,27 +378,35 @@ namespace mpvnet
}
string path = Core.GetPropertyString("path");
string text = "";
if (File.Exists(path) && !path.Contains(@"\\.\pipe\"))
{
bool full = args.Contains("full");
bool raw = args.Contains("raw");
bool editor = args.Contains("editor");
bool osd = args.Contains("osd");
if (App.MediaInfo && !osd && File.Exists(path) && !path.Contains(@"\\.\pipe\"))
using (MediaInfo mediaInfo = new MediaInfo(path))
{
bool full = args.Contains("full");
bool raw = args.Contains("raw");
bool editor = args.Contains("editor");
text = Regex.Replace(mediaInfo.GetSummary(full, raw), "Unique ID.+", "");
else
{
Core.UpdateExternalTracks();
lock (Core.MediaTracksLock)
foreach (MediaTrack track in Core.MediaTracks)
text += track.Text + BR;
}
string text = mediaInfo.GetSummary(full, raw);
text = Regex.Replace(text, "Unique ID.+", "");
text = text.TrimEx();
if (editor)
ShowTextWithEditor("media-info", text);
else
{
MsgBoxEx.MessageBoxEx.MsgFontFamily = new FontFamily("Consolas");
Msg.ShowInfo(text);
MsgBoxEx.MessageBoxEx.MsgFontFamily = new FontFamily("Segoe UI");
}
}
if (editor)
ShowTextWithEditor("media-info", text);
else if (osd)
ShowText(text.Replace("\r", ""), 5000, 17);
else
{
MsgBoxEx.MessageBoxEx.MsgFontFamily = new FontFamily("Consolas");
Msg.ShowInfo(text);
MsgBoxEx.MessageBoxEx.MsgFontFamily = new FontFamily("Segoe UI");
}
});
@@ -427,72 +419,81 @@ namespace mpvnet
public static void ShowAudioTracks() => App.InvokeOnMainThread(() =>
{
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
int len = tracks.Length;
Core.UpdateExternalTracks();
if (len < 1)
lock (Core.MediaTracksLock)
{
Core.CommandV("show-text", "No audio tracks");
return;
}
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
foreach (MediaTrack i in tracks)
{
MediaTrack track = i;
CommandPaletteItem item = new CommandPaletteItem()
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
if (tracks.Length < 1)
{
Text = track.Text,
Action = () => {
Core.CommandV("set", "aid", track.ID.ToString());
Core.CommandV("show-text", track.ID + "/" + len + ": " +
tracks[track.ID - 1].Text.Substring(3), "5000");
}
};
Core.CommandV("show-text", "No audio tracks");
return;
}
items.Add(item);
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
foreach (MediaTrack i in tracks)
{
MediaTrack track = i;
CommandPaletteItem item = new CommandPaletteItem()
{
Text = track.Text,
Action = () => {
Core.CommandV("set", "aid", track.ID.ToString());
Core.CommandV("show-text", track.ID + "/" + tracks.Length + ": " +
tracks[track.ID - 1].Text.Substring(3), "5000");
}
};
items.Add(item);
}
CommandPalette.Instance.SetItems(items);
MainForm.Instance.ShowCommandPalette();
CommandPalette.Instance.SelectFirst();
}
CommandPalette.Instance.SetItems(items);
MainForm.Instance.ShowCommandPalette();
CommandPalette.Instance.SelectFirst();
});
public static void ShowSubtitleTracks() => App.InvokeOnMainThread(() =>
{
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "s").ToArray();
int len = tracks.Length;
Core.UpdateExternalTracks();
if (len < 1)
lock (Core.MediaTracksLock)
{
Core.CommandV("show-text", "No subtitle tracks");
return;
}
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
foreach (MediaTrack i in tracks)
{
MediaTrack track = i;
CommandPaletteItem item = new CommandPaletteItem()
MediaTrack[] tracks = Core.MediaTracks.Where(track => track.Type == "s").ToArray();
if (tracks.Length < 1)
{
Text = track.Text,
Action = () => {
Core.CommandV("set", "sid", track.ID.ToString());
Core.CommandV("show-text", track.ID + "/" + len + ": " +
tracks[track.ID - 1].Text.Substring(3), "5000");
}
};
Core.CommandV("show-text", "No subtitle tracks");
return;
}
items.Add(item);
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
foreach (MediaTrack i in tracks)
{
MediaTrack track = i;
CommandPaletteItem item = new CommandPaletteItem()
{
Text = track.Text,
Action = () => {
Core.CommandV("set", "sid", track.ID.ToString());
Core.CommandV("show-text", track.ID + "/" + tracks.Length + ": " +
tracks[track.ID - 1].Text.Substring(3), "5000");
}
};
items.Add(item);
}
CommandPalette.Instance.SetItems(items);
MainForm.Instance.ShowCommandPalette();
CommandPalette.Instance.SelectFirst();
}
CommandPalette.Instance.SetItems(items);
MainForm.Instance.ShowCommandPalette();
CommandPalette.Instance.SelectFirst();
});
public static void ShowPlaylist() => App.InvokeOnMainThread(() =>
@@ -514,12 +515,7 @@ namespace mpvnet
CommandPaletteItem item = new CommandPaletteItem()
{
Text = file.FileName(),
Action = () => {
Core.SetPropertyInt("playlist-pos", index);
if (App.AutoPlay && Core.Paused)
Core.SetPropertyBool("pause", false);
}
Action = () => Core.SetPropertyInt("playlist-pos", index)
};
items.Add(item);
@@ -574,14 +570,14 @@ namespace mpvnet
{
List<CommandPaletteItem> items = new List<CommandPaletteItem>();
foreach (string i in App.Settings.RecentFiles)
foreach (string path in App.Settings.RecentFiles)
{
string file = i;
var file = App.GetTitleAndPath(path);
CommandPaletteItem item = new CommandPaletteItem()
{
Text = file.ShortPath(60),
Action = () => Core.LoadFiles(new[] { file }, true, Control.ModifierKeys.HasFlag(Keys.Control))
Text = file.Title.ShortPath(60),
Action = () => Core.LoadFiles(new[] { file.Path }, true, Control.ModifierKeys.HasFlag(Keys.Control))
};
items.Add(item);
@@ -650,10 +646,10 @@ namespace mpvnet
public static void ShowSetupDialog() => App.InvokeOnMainThread(() =>
{
(string Name, string Value)[] pairs = {
("Register video file associations", "script-message mpv.net reg-file-assoc video"),
("Register audio file associations", "script-message mpv.net reg-file-assoc audio"),
("Register image file associations", "script-message mpv.net reg-file-assoc image"),
("Unregister file associations", "script-message mpv.net reg-file-assoc unreg") };
("Register video file associations", "script-message-to mpvnet reg-file-assoc video"),
("Register audio file associations", "script-message-to mpvnet reg-file-assoc audio"),
("Register image file associations", "script-message-to mpvnet reg-file-assoc image"),
("Unregister file associations", "script-message-to mpvnet reg-file-assoc unreg") };
var list = pairs.Select(i => new CommandPaletteItem(i.Name, () => Core.Command(i.Value)));
CommandPalette.Instance.SetItems(list);
@@ -661,6 +657,64 @@ namespace mpvnet
CommandPalette.Instance.SelectFirst();
});
public static void SelectProfile() => App.InvokeOnMainThread(() =>
{
var items = Core.ProfileNames.Where(i => !i.StartsWith("extension."))
.Select(i => new CommandPaletteItem(i, () => {
Core.CommandV("show-text", i);
Core.CommandV("apply-profile", i);
}));
CommandPalette.Instance.SetItems(items);
MainForm.Instance.ShowCommandPalette();
CommandPalette.Instance.SelectFirst();
});
public static void ShowChapters() => App.InvokeOnMainThread(() =>
{
var items = Core.GetChapters().Select(i => new CommandPaletteItem(i.Title, i.TimeDisplay, () =>
Core.CommandV("seek", i.Time.ToString(CultureInfo.InvariantCulture), "absolute")));
CommandPalette.Instance.SetItems(items);
MainForm.Instance.ShowCommandPalette();
CommandPalette.Instance.SelectFirst();
});
public static void ShowMenu() => Core.RaiseShowMenu();
public static void PlaylistAdd(int value)
{
int pos = Core.PlaylistPos;
int count = Core.GetPropertyInt("playlist-count");
if (count < 2)
return;
pos = pos + value;
if (pos < 0)
pos = count - 1;
if (pos > count - 1)
pos = 0;
Core.SetPropertyInt("playlist-pos", pos);
}
public static void QuickBookmark()
{
if (App.QuickBookmark == 0)
{
App.QuickBookmark = (float)Core.GetPropertyDouble("time-pos");
if (App.QuickBookmark != 0)
Core.Command("show-text 'Bookmark Saved'");
}
else
{
Core.SetPropertyDouble("time-pos", App.QuickBookmark);
App.QuickBookmark = 0;
}
}
}
}

View File

@@ -134,9 +134,10 @@ namespace mpvnet
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 int ID { get; set; }
}
public class CommandItem : INotifyPropertyChanged
@@ -145,7 +146,19 @@ namespace mpvnet
public string Path { 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() { }
@@ -227,7 +240,6 @@ namespace mpvnet
get {
if (_Items is null)
_Items = GetItems(File.ReadAllText(Core.InputConfPath));
return _Items;
}
}
@@ -249,6 +261,13 @@ namespace mpvnet
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; }
@@ -271,4 +290,26 @@ namespace mpvnet
});
}
}
public class Chapter
{
public string Title { get; set; }
public double Time { get; set; }
string _TimeDisplay;
public string TimeDisplay {
get {
if (_TimeDisplay == null)
{
_TimeDisplay = TimeSpan.FromSeconds(Time).ToString();
if (_TimeDisplay.ContainsEx("."))
_TimeDisplay = _TimeDisplay.Substring(0, _TimeDisplay.LastIndexOf("."));
}
return _TimeDisplay;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,14 +15,13 @@ namespace mpvnet
public class AppSettings
{
public bool InputDefaultBindingsFixApplied;
public bool LogoCrash;
public bool ShowMenuFixApplied;
public int Volume = 70;
public List<string> RecentFiles = new List<string>();
public Point WindowLocation;
public Point WindowPosition;
public Size WindowSize;
public string ConfigEditorSearch = "";
public string ConfigEditorSearch = "Video:";
public string Mute = "no";
public string UpdateCheckVersion = "";
}

View File

@@ -18,6 +18,12 @@ namespace mpvnet
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string path);
[DllImport("user32.dll")]
public static extern uint ActivateKeyboardLayout(IntPtr hkl, uint flags);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx(
IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
@@ -85,6 +91,37 @@ namespace mpvnet
[DllImport("gdi32.dll")]
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)]
public struct RECT
{
@@ -113,6 +150,16 @@ namespace mpvnet
public Size Size => new Size(Right - Left, Bottom - Top);
public int Width => Right - Left;
public int Height => Bottom - Top;
public static RECT FromRectangle(Rectangle rect)
{
return new RECT(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
}
public override string ToString()
{
return "{Left=" + Left + ",Top=" + Top + ",Right=" + Right + ",Bottom=" + Bottom + "}";
}
}
[StructLayout(LayoutKind.Sequential)]

View File

@@ -8,6 +8,9 @@ public class libmpv
[DllImport("mpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_create();
[DllImport("mpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_create_client(IntPtr mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string command);
[DllImport("mpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_initialize(IntPtr mpvHandle);
@@ -26,9 +29,6 @@ public class libmpv
[DllImport("mpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr mpv_error_string(mpv_error error);
[DllImport("mpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mpv_terminate_destroy(IntPtr mpvHandle);
[DllImport("mpv-2.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern mpv_error mpv_request_log_messages(IntPtr mpvHandle, [MarshalAs(UnmanagedType.LPUTF8Str)] string min_level);

View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.8.0.0")]
[assembly: AssemblyFileVersion("5.8.0.0")]
[assembly: AssemblyVersion("6.0.2.0")]
[assembly: AssemblyFileVersion("6.0.2.0")]

View File

@@ -5,7 +5,14 @@ $versionInfo = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath)
$7z = 'C:\Program Files\7-Zip\7z.exe'
$targetDir = $tmpDir + "\mpv.net-$($versionInfo.FileVersion)-beta"
Copy-Item $PSScriptRoot\bin $targetDir -Recurse -Exclude 'System.Management.Automation.xml'
Copy-Item $PSScriptRoot\bin $targetDir -Recurse -Exclude System.Management.Automation.xml
$folders = 'Debug', 'Release', 'x64', 'x86', 'Arm'
foreach ($folder in $folders) {
Remove-Item (Join-Path $targetDir $folder) -Recurse -ErrorAction SilentlyContinue
}
& $7z a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
if ($LastExitCode) { throw $LastExitCode }

View File

@@ -1,4 +1,62 @@
[setting]
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\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.
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
[setting]
name = recent-count
file = mpvnet
filter = General
help = <int> Amount of recent files to be remembered. Default: 15 (mpv.net specific option)
[setting]
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
[setting]
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)
[setting]
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)
[setting]
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)
[setting]
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
[setting]
name = vo
file = mpv
@@ -234,7 +292,7 @@ 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
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
[setting]
name = slang
@@ -352,6 +410,18 @@ file = mpv
filter = Screen
help = <int> Initial window height in percent. Default: 60
[setting]
name = autofit-image
file = mpvnet
filter = Screen
help = <int> Initial window height in percent for image files. Default: 80
[setting]
name = autofit-audio
file = mpvnet
filter = Screen
help = <int> Initial window height in percent for audio files. Default: 70
[setting]
name = autofit-smaller
file = mpv
@@ -389,17 +459,17 @@ help = keepaspect-window will lock the window size to the video aspect. Default:
option = yes
option = no
[setting]
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)
[setting]
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 option)
help = <float> Minimum aspect ratio of the window. Useful to force a wider window and therefore a larger OSC. (mpv.net specific option)
[setting]
name = minimum-aspect-ratio-audio
file = mpvnet
filter = Screen
help = Same as minimum-aspect-ratio but used for audio files.
[setting]
name = remember-window-position
@@ -411,6 +481,16 @@ help = Save the window position on exit. (mpv.net specific option)
option = yes
option = no
[setting]
name = snap-window
file = mpv
default = no
filter = Screen
help = Snap the player window to screen edges.
option = yes
option = no
[setting]
name = window-maximized
file = mpv
@@ -422,78 +502,10 @@ option = yes
option = no
[setting]
name = screenshot-directory
file = mpv
width = 500
type = folder
name = start-threshold
file = mpvnet
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.
[setting]
name = screenshot-format
file = mpv
default = jpg
filter = Screen
help = Set the image file type used for saving screenshots.
option = jpg
option = png
[setting]
name = screenshot-tag-colorspace
file = mpv
default = no
filter = Screen
help = Tag screenshots with the appropriate colorspace. Note that not all formats are supported.
option = yes
option = no
[setting]
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.
option = yes
option = no
[setting]
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.
option = yes
option = no
[setting]
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
[setting]
name = screenshot-jpeg-quality
file = mpv
filter = Screen
help = <0-100> Set the JPEG quality level. Higher means better quality. The default is 90.
[setting]
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.
[setting]
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.
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)
[setting]
name = taskbar-progress
@@ -505,6 +517,16 @@ help = Show progress in taskbar.
option = yes
option = no
[setting]
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.
[setting]
name = keep-open-pause
file = mpv
@@ -516,22 +538,22 @@ option = yes
option = no
[setting]
name = keep-open
name = idle
file = mpv
default = no
default = yes
filter = Playback
help = Using no, mpv would terminate after the last file but mpv.net never terminates automatically.
help = If set to no and keep-open is also set to no, the player exits after the last file ends.
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.
option = always Playback will never automatically advance to the next file.
option = yes
option = no
option = once
[setting]
name = auto-play
file = mpvnet
default = no
filter = Playback
help = Sets pause=no on file load and selecting from the playlist. (mpv.net specific option)
help = Sets pause=no on file load. (mpv.net specific option)
option = yes
option = no
@@ -609,54 +631,6 @@ file = mpv
filter = Input
help = Number of key presses to generate per second on autorepeat.
[setting]
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\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.
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
[setting]
name = recent-count
file = mpvnet
filter = General
help = <int> Amount of recent files to be remembered. Default: 15 (mpv.net specific option)
[setting]
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)
[setting]
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)
[setting]
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)
[setting]
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
[setting]
name = dark-mode
file = mpvnet
@@ -691,3 +665,106 @@ help = Draws the blue mpv.net logo ontop of the native OSC logo.
option = yes
option = no
[setting]
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
[setting]
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.
[setting]
name = screenshot-format
file = mpv
default = jpg
filter = Screenshot
help = Set the image file type used for saving screenshots.
option = jpg
option = png
[setting]
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
[setting]
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
[setting]
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
[setting]
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
[setting]
name = screenshot-jpeg-quality
file = mpv
filter = Screenshot
help = <0-100> Set the JPEG quality level. Higher means better quality. The default is 90.
[setting]
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.
[setting]
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.
[setting]
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
[setting]
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,28 +1,28 @@
# https://github.com/stax76/mpv.net/blob/master/docs/Manual.md#input-and-context-menu
o script-message mpv.net open-files #menu: Open > Open Files...
Ctrl+v script-message mpv.net open-clipboard #menu: Open > Open URL or file from clipboard
_ script-message mpv.net open-optical-media #menu: Open > Open DVD/Blu-ray Drive/Folder...
_ ignore #menu: Open > -
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
_ ignore #menu: Open > -
_ script-message mpv.net open-files append #menu: Open > Add files to playlist...
_ ignore #menu: Open > -
_ ignore #menu: Open > Recent
o script-message-to mpvnet open-files #menu: Open > Open Files...
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
_ ignore #menu: -
Space script-message mpv.net play-pause #menu: Play/Pause
Ctrl+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: -
Space script-message-to mpvnet play-pause #menu: Play/Pause
Ctrl+s stop #menu: Stop
_ ignore #menu: -
Enter cycle fullscreen #menu: Toggle Fullscreen
F11 script-message-to mpvnet playlist-add -1 #menu: Navigate > Previous File
F12 script-message-to mpvnet playlist-add 1 #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
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 > -
PGUP add chapter 1 #menu: Navigate > Next Chapter
PGDWN add chapter -1 #menu: Navigate > Previous Chapter
@@ -73,7 +73,7 @@ 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
KP7 script-message mpv.net cycle-audio #menu: Audio > Cycle/Next
KP7 script-message-to mpvnet cycle-audio #menu: Audio > Cycle/Next
_ 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
@@ -94,6 +94,8 @@ _ ignore #menu: Track
+ add volume 2 #menu: Volume > Up
- add volume -2 #menu: Volume > Down
0 add volume 2 #menu: Volume > Up
9 add volume -2 #menu: Volume > Down
_ ignore #menu: Volume > -
m cycle mute #menu: Volume > Mute
@@ -105,72 +107,78 @@ _ ignore #menu: Speed > -
_ ignore #menu: Speed > -
BS set speed 1 #menu: Speed > Reset
Alt++ script-message mpv.net scale-window 1.2 #menu: View > Zoom > Enlarge
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 %
Alt++ script-message-to mpvnet scale-window 1.2 #menu: View > Zoom > Enlarge
Alt+- script-message-to mpvnet scale-window 0.8 #menu: View > Zoom > Shrink
_ ignore #menu: View > Zoom > -
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 %
F8 script-message mpv.net show-playlist #menu: View > Show Playlist
Ctrl+7 script-message mpv.net show-audio-tracks #menu: View > Show Audio Tracks
Ctrl+8 script-message mpv.net show-subtitle-tracks #menu: View > Show Subtitle Tracks
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 mpv.net show-info #menu: View > Show File/Stream Info
p show-progress #menu: View > Show Progress
Ctrl+p script-message mpv.net show-profiles #menu: View > Show Profiles
F9 show-text ${track-list} 5000 #menu: View > Show Tracks
Ctrl+m script-message mpv.net show-media-info #menu: View > Show Media Info
Alt+r script-message mpv.net show-recent #menu: View > Show Recent
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 File/Stream Info
p show-progress #menu: View > Show Progress
F9 script-message-to mpvnet show-media-info osd #menu: View > Show Tracks
Ctrl+m script-message-to mpvnet show-media-info #menu: View > Show Media Info
Alt+r script-message-to mpvnet show-recent #menu: View > Show Recent
` script-binding console/enable #menu: View > Advanced > Show Console
_ script-message mpv.net show-audio-devices #menu: View > Advanced > Show Audio Devices
P script-message mpv.net show-properties #menu: View > Advanced > Show Properties
C script-message mpv.net show-commands #menu: View > Advanced > Show Commands
_ script-message mpv.net show-demuxers #menu: View > Advanced > Show Demuxers
_ script-message mpv.net show-decoders #menu: View > Advanced > Show Decoders
_ script-message mpv.net show-protocols #menu: View > Advanced > Show Protocols
_ script-message mpv.net show-keys #menu: View > Advanced > Show Keys
` script-binding console/enable #menu: View > Advanced > Show Console
_ script-message-to mpvnet show-audio-devices #menu: View > Advanced > Show Audio Devices
P script-message-to mpvnet show-properties #menu: View > Advanced > Show Properties
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
_ ignore #menu: Profile
_ ignore #menu: Profile
c script-message mpv.net show-conf-editor #menu: Settings > Show Config Editor
Ctrl+i script-message mpv.net show-input-editor #menu: Settings > Show Input Editor
Ctrl+f script-message mpv.net open-conf-folder #menu: Settings > Open Config Folder
c script-message-to mpvnet show-conf-editor #menu: Settings > Show Config Editor
Ctrl+i script-message-to mpvnet show-input-editor #menu: Settings > Show Input Editor
Ctrl+f script-message-to mpvnet open-conf-folder #menu: Settings > Open Config Folder
_ script-message mpv.net reg-file-assoc video #menu: Settings > Setup > Register video file associations
_ script-message mpv.net reg-file-assoc audio #menu: Settings > Setup > Register audio file associations
_ script-message mpv.net reg-file-assoc image #menu: Settings > Setup > Register image file associations
_ script-message mpv.net reg-file-assoc unreg #menu: Settings > Setup > Unregister file associations
_ script-message-to mpvnet reg-file-assoc video #menu: Settings > Setup > Register video file associations
_ script-message-to mpvnet reg-file-assoc audio #menu: Settings > Setup > Register audio file associations
_ 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
h script-message mpv.net show-history #menu: Tools > Show History
l ab-loop #menu: Tools > Set/clear A-B loop points
L cycle-values loop-file inf no #menu: Tools > Toggle infinite file looping
_ playlist-shuffle #menu: Tools > Shuffle Playlist
Ctrl+h cycle-values hwdec auto no #menu: Tools > Toggle Hardware Decoding
Q quit-watch-later #menu: Tools > Exit Watch Later
h script-message-to mpvnet show-history #menu: Tools > Show History
l ab-loop #menu: Tools > Set/clear A-B loop points
L cycle-values loop-file inf no #menu: Tools > Toggle infinite file looping
_ playlist-shuffle #menu: Tools > Shuffle Playlist
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 shell-execute https://mpv.io #menu: Help > Website mpv
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net #menu: Help > Website mpv.net
_ ignore #menu: Help > -
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Manual mpv
_ script-message mpv.net shell-execute https://github.com/stax76/mpv.net/blob/master/docs/Manual.md #menu: Help > Manual mpv.net
_ ignore #menu: Help > -
_ script-message mpv.net show-about #menu: Help > About mpv.net
_ script-message-to mpvnet shell-execute https://mpv.io #menu: Help > Website mpv
_ script-message-to mpvnet shell-execute https://github.com/stax76/mpv.net #menu: Help > Website mpv.net
_ ignore #menu: Help > -
_ script-message-to mpvnet shell-execute https://mpv.io/manual/stable/ #menu: Help > Manual mpv
_ script-message-to mpvnet shell-execute https://github.com/stax76/mpv.net/blob/master/docs/Manual.md #menu: Help > Manual mpv.net
_ ignore #menu: Help > -
_ script-message-to mpvnet show-about #menu: Help > About mpv.net
F1 script-message mpv.net show-command-palette #menu: Command Palette
_ ignore #menu: -
Esc quit #menu: Exit
F1 script-message-to mpvnet show-command-palette #menu: Command Palette
_ ignore #menu: -
Esc quit #menu: Exit
MBTN_Right script-message mpv.net show-menu
6 script-message mpv.net show-progress
KP6 script-message mpv.net show-progress
7 script-message mpv.net cycle-audio
Sharp script-message mpv.net cycle-audio
MBTN_Right script-message-to mpvnet show-menu
6 script-message-to mpvnet show-progress
KP6 script-message-to mpvnet show-progress
KP9 ab-loop
7 script-message-to mpvnet cycle-audio
Sharp script-message-to mpvnet cycle-audio
Ctrl+F11 script-message-to mpvnet playlist-add -10
Ctrl+F12 script-message-to mpvnet playlist-add 10
Alt+q script-message-to mpvnet quick-bookmark
8 cycle sub
j cycle sub
q quit
@@ -202,8 +210,6 @@ 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
Shift+g add sub-scale +0.1 # increase the subtitle font size
Shift+f add sub-scale -0.1 # decrease the subtitle font size
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

View File

@@ -25,7 +25,7 @@
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="105" />
<ColumnDefinition Width="110" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
@@ -76,10 +76,8 @@
</ListBox>
<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="OpenSettingsTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="OpenSettingsTextBlock_MouseUp">Open config folder</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="SupportTextBlock" Margin="0,15,0,0" Cursor="Hand" TextWrapping="WrapWithOverflow" Foreground="{Binding Theme.Heading}" MouseUp="SupportTextBlock_MouseUp">Show support forum</TextBlock>
</StackPanel>
</Grid>
</Window>

View File

@@ -63,10 +63,10 @@ namespace mpvnet
switch (setting)
{
case StringSetting s:
MainStackPanel.Children.Add(new StringSettingControl(s));
MainStackPanel.Children.Add(new StringSettingControl(s) { Visibility = Visibility.Collapsed });
break;
case OptionSetting s:
MainStackPanel.Children.Add(new OptionSettingControl(s));
MainStackPanel.Children.Add(new OptionSettingControl(s) { Visibility = Visibility.Collapsed });
break;
}
}
@@ -90,15 +90,7 @@ namespace mpvnet
if (item.File == "mpv")
{
Core.ProcessProperty(item.Name, item.Value);
try
{
Core.SetPropertyString(item.Name, item.Value, true);
}
catch (Exception ex)
{
App.ShowError(ex.Message);
}
Core.SetPropertyString(item.Name, item.Value);
}
else if (item.File == "mpvnet")
App.ProcessProperty(item.Name, item.Value, true);
@@ -285,15 +277,16 @@ namespace mpvnet
void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string activeFilter = "";
string searchText = SearchControl.Text;
foreach (var i in FilterStrings)
if (SearchControl.Text == i + ":")
foreach (string i in FilterStrings)
if (searchText == i + ":")
activeFilter = i;
if (activeFilter == "")
{
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;
else
i.Visibility = Visibility.Collapsed;
@@ -325,18 +318,11 @@ namespace mpvnet
SearchControl.Text = e.AddedItems[0] + ":";
}
void OpenSettingsTextBlock_MouseUp(object sender, MouseButtonEventArgs e) =>
ProcessHelp.ShellExecute(Path.GetDirectoryName(Core.ConfPath));
void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e) =>
Msg.ShowInfo("mpv.conf Preview" + BR2 + GetContent("mpv"));
void PreviewTextBlock_MouseUp(object sender, MouseButtonEventArgs e) => Msg.ShowInfo(GetContent("mpv"));
void ShowManualTextBlock_MouseUp(object sender, MouseButtonEventArgs e) =>
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)
{
base.OnKeyDown(e);

View File

@@ -50,7 +50,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(348, 0);
this.ClientSize = new System.Drawing.Size(857, 444);
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);

View File

@@ -1,9 +1,9 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
@@ -21,10 +21,12 @@ namespace mpvnet
{
public partial class MainForm : Form
{
public SnapManager SnapManager = new SnapManager();
public ElementHost CommandPaletteHost { get; set; }
public IntPtr mpvWindowHandle { get; set; }
public static MainForm Instance { get; set; }
public static IntPtr Hwnd { get; set; }
public Dictionary<string, WpfControls.MenuItem> MenuItemDuplicate = new Dictionary<string, WpfControls.MenuItem>();
new WpfControls.ContextMenu ContextMenu { get; set; }
AutoResetEvent MenuAutoResetEvent { get; } = new AutoResetEvent(false);
Point LastCursorPosition;
@@ -35,7 +37,6 @@ namespace mpvnet
int TaskbarButtonCreatedMessage;
bool WasMaximized;
bool WasShown;
public MainForm()
{
@@ -44,39 +45,20 @@ namespace mpvnet
try
{
Instance = this;
Hwnd = Handle;
Core.Init();
Core.Shutdown += Core_Shutdown;
Core.ShowMenu += Core_ShowMenu;
Core.VideoSizeChanged += Core_VideoSizeChanged;
Core.ScaleWindow += Core_ScaleWindow;
Core.WindowScale += Core_WindowScale;
Core.FileLoaded += Core_FileLoaded;
Core.Pause += Core_Pause;
Core.PlaylistPosChanged += Core_PlaylistPosChanged;
Core.ScaleWindow += Core_ScaleWindow;
Core.Seek += () => UpdateProgressBar();
Core.PlaylistPosChanged += (value) => SetTitle();
Core.ObserveProperty("window-maximized", PropChangeWindowMaximized);
Core.ObserveProperty("window-minimized", PropChangeWindowMinimized);
Core.ObservePropertyBool("border", PropChangeBorder);
Core.ObservePropertyBool("fullscreen", PropChangeFullscreen);
Core.ObservePropertyBool("keepaspect-window", value => Core.KeepaspectWindow = value);
Core.ObservePropertyBool("ontop", PropChangeOnTop);
Core.ObservePropertyBool("pause", PropChangePause);
Core.ObservePropertyString("sid", PropChangeSid);
Core.ObservePropertyString("aid", PropChangeAid);
Core.ObservePropertyString("vid", PropChangeVid);
Core.ObservePropertyString("title", PropChangeTitle);
Core.ObservePropertyInt("edition", PropChangeEdition);
Core.ObservePropertyDouble("window-scale", WindowScale);
Core.ShowMenu += Core_ShowMenu;
Core.Shutdown += Core_Shutdown;
Core.VideoSizeChanged += Core_VideoSizeChanged;
Core.WindowScaleMpv += Core_WindowScaleMpv;
Core.WindowScaleNET += Core_WindowScaleNET;
if (Core.GPUAPI != "vulkan")
Core.ProcessCommandLine(false);
Init();
AppDomain.CurrentDomain.UnhandledException += (sender, e) => App.ShowException(e.ExceptionObject);
Application.ThreadException += (sender, e) => App.ShowException(e.Exception);
@@ -136,7 +118,37 @@ namespace mpvnet
}
}
private void Core_ShowMenu()
private void Core_PlaylistPosChanged(int pos)
{
if (pos == -1)
SetTitle();
}
void Init()
{
Core.Init(Handle);
// bool methods not working correctly
Core.ObserveProperty("window-maximized", PropChangeWindowMaximized);
Core.ObserveProperty("window-minimized", PropChangeWindowMinimized);
Core.ObservePropertyBool("border", PropChangeBorder);
Core.ObservePropertyBool("fullscreen", PropChangeFullscreen);
Core.ObservePropertyBool("keepaspect-window", value => Core.KeepaspectWindow = value);
Core.ObservePropertyBool("ontop", PropChangeOnTop);
Core.ObservePropertyString("sid", PropChangeSid);
Core.ObservePropertyString("aid", PropChangeAid);
Core.ObservePropertyString("vid", PropChangeVid);
Core.ObservePropertyString("title", PropChangeTitle);
Core.ObservePropertyInt("edition", PropChangeEdition);
Core.ProcessCommandLine(false);
}
void Core_ShowMenu()
{
BeginInvoke(new Action(() => {
if (IsMouseInOSC())
@@ -167,7 +179,7 @@ namespace mpvnet
}));
}
void Core_WindowScale(float scale)
void Core_WindowScaleNET(float scale)
{
BeginInvoke(new Action(() => {
SetSize(
@@ -178,9 +190,9 @@ namespace mpvnet
}));
}
void WindowScale(double scale)
void Core_WindowScaleMpv(double scale)
{
if (!WasShown)
if (!Core.Shown)
return;
BeginInvoke(new Action(() => {
@@ -217,12 +229,14 @@ namespace mpvnet
if (FormBorderStyle == FormBorderStyle.None)
top = ClientSize.Height * 0.1f;
return pos.Y > ClientSize.Height * 0.85 || pos.Y < top;
return pos.Y > ClientSize.Height * 0.78 || pos.Y < top;
}
void UpdateMenu()
{
lock (Core.MediaTracks)
Core.UpdateExternalTracks();
lock (Core.MediaTracksLock)
{
var trackMenuItem = FindMenuItem("Track");
@@ -230,42 +244,42 @@ namespace mpvnet
{
trackMenuItem.Items.Clear();
MediaTrack[] audTracks = Core.MediaTracks.Where(track => track.Type == "a").ToArray();
MediaTrack[] subTracks = Core.MediaTracks.Where(track => track.Type == "s").ToArray();
MediaTrack[] vidTracks = Core.MediaTracks.Where(track => track.Type == "v").ToArray();
MediaTrack[] ediTracks = Core.MediaTracks.Where(track => track.Type == "e").ToArray();
var audTracks = Core.MediaTracks.Where(track => track.Type == "a");
var subTracks = Core.MediaTracks.Where(track => track.Type == "s");
var vidTracks = Core.MediaTracks.Where(track => track.Type == "v");
var ediTracks = Core.MediaTracks.Where(track => track.Type == "e");
foreach (MediaTrack track in vidTracks)
{
var mi = new WpfControls.MenuItem() { Header = track.Text };
var mi = new WpfControls.MenuItem() { Header = track.Text.Replace("_", "__") };
mi.Click += (sender, args) => Core.CommandV("set", "vid", track.ID.ToString());
mi.IsChecked = Core.VID == track.ID.ToString();
trackMenuItem.Items.Add(mi);
}
if (vidTracks.Length > 0)
if (vidTracks.Count() > 0)
trackMenuItem.Items.Add(new WpfControls.Separator());
foreach (MediaTrack track in audTracks)
{
var mi = new WpfControls.MenuItem() { Header = track.Text };
var mi = new WpfControls.MenuItem() { Header = track.Text.Replace("_", "__") };
mi.Click += (sender, args) => Core.CommandV("set", "aid", track.ID.ToString());
mi.IsChecked = Core.AID == track.ID.ToString();
trackMenuItem.Items.Add(mi);
}
if (subTracks.Length > 0)
if (subTracks.Count() > 0)
trackMenuItem.Items.Add(new WpfControls.Separator());
foreach (MediaTrack track in subTracks)
{
var mi = new WpfControls.MenuItem() { Header = track.Text };
var mi = new WpfControls.MenuItem() { Header = track.Text.Replace("_", "__") };
mi.Click += (sender, args) => Core.CommandV("set", "sid", track.ID.ToString());
mi.IsChecked = Core.SID == track.ID.ToString();
trackMenuItem.Items.Add(mi);
}
if (subTracks.Length > 0)
if (subTracks.Count() > 0)
{
var mi = new WpfControls.MenuItem() { Header = "S: No subtitles" };
mi.Click += (sender, args) => Core.CommandV("set", "sid", "no");
@@ -273,12 +287,12 @@ namespace mpvnet
trackMenuItem.Items.Add(mi);
}
if (ediTracks.Length > 0)
if (ediTracks.Count() > 0)
trackMenuItem.Items.Add(new WpfControls.Separator());
foreach (MediaTrack track in ediTracks)
{
var mi = new WpfControls.MenuItem() { Header = track.Text };
var mi = new WpfControls.MenuItem() { Header = track.Text.Replace("_", "__") };
mi.Click += (sender, args) => Core.CommandV("set", "edition", track.ID.ToString());
mi.IsChecked = Core.Edition == track.ID;
trackMenuItem.Items.Add(mi);
@@ -286,21 +300,18 @@ namespace mpvnet
}
}
lock (Core.Chapters)
var chaptersMenuItem = FindMenuItem("Chapters");
if (chaptersMenuItem != null)
{
var chaptersMenuItem = FindMenuItem("Chapters");
chaptersMenuItem.Items.Clear();
if (chaptersMenuItem != null)
foreach (Chapter chapter in Core.GetChapters())
{
chaptersMenuItem.Items.Clear();
foreach (var pair in Core.Chapters)
{
var chapterMenuItem = new WpfControls.MenuItem() { Header = pair.Key };
chapterMenuItem.InputGestureText = TimeSpan.FromSeconds(pair.Value).ToString().Substring(0, 8);
chapterMenuItem.Click += (sender, args) => Core.CommandV("seek", pair.Value.ToString(CultureInfo.InvariantCulture), "absolute");
chaptersMenuItem.Items.Add(chapterMenuItem);
}
var chapterMenuItem = new WpfControls.MenuItem() { Header = chapter.Title };
chapterMenuItem.InputGestureText = chapter.TimeDisplay;
chapterMenuItem.Click += (sender, args) => Core.CommandV("seek", chapter.Time.ToString(CultureInfo.InvariantCulture), "absolute");
chaptersMenuItem.Items.Add(chapterMenuItem);
}
}
@@ -312,11 +323,12 @@ namespace mpvnet
foreach (string path in App.Settings.RecentFiles)
{
var mi = MenuHelp.Add(recentMenuItem.Items, path.ShortPath(100));
var file = App.GetTitleAndPath(path);
var mi = MenuHelp.Add(recentMenuItem.Items, file.Title.ShortPath(100));
if (mi != null)
mi.Click += (sender, args) =>
Core.LoadFiles(new[] { path }, true, ModifierKeys.HasFlag(Keys.Control));
Core.LoadFiles(new[] { file.Path }, true, ModifierKeys.HasFlag(Keys.Control));
}
recentMenuItem.Items.Add(new WpfControls.Separator());
@@ -364,7 +376,7 @@ namespace mpvnet
{
profilesMenuItem.Items.Clear();
foreach (string profile in ProfileNames)
foreach (string profile in Core.ProfileNames)
{
if (!profile.StartsWith("extension."))
{
@@ -382,23 +394,6 @@ namespace mpvnet
}
}
private string[] _ProfileNames;
public string[] ProfileNames {
get {
if (_ProfileNames == null)
{
string[] ignore = { "builtin-pseudo-gui", "encoding", "libmpv", "pseudo-gui", "default" };
string profileList = Core.GetPropertyString("profile-list");
var json = profileList.FromJson<List<Dictionary<string, object>>>();
_ProfileNames = json.Select(i => i["name"].ToString())
.Where(i => !ignore.Contains(i)).ToArray();
}
return _ProfileNames;
}
}
public WpfControls.MenuItem FindMenuItem(string text) => FindMenuItem(text, ContextMenu.Items);
WpfControls.MenuItem FindMenuItem(string text, WpfControls.ItemCollection items)
@@ -437,13 +432,23 @@ namespace mpvnet
}
Screen screen = Screen.FromControl(this);
int autoFitHeight = Convert.ToInt32(screen.WorkingArea.Height * Core.Autofit);
Rectangle workingArea = GetWorkingArea(Handle, screen.WorkingArea);
int autoFitHeight = Convert.ToInt32(workingArea.Height * Core.Autofit);
if (Core.VideoSize.Height == 0 || Core.VideoSize.Width == 0 ||
Core.VideoSize.Width / (float)Core.VideoSize.Height < App.MinimumAspectRatio)
if (App.AutofitAudio > 1) App.AutofitAudio = 1;
if (App.AutofitImage > 1) App.AutofitImage = 1;
if (Core.IsAudio) autoFitHeight = Convert.ToInt32(workingArea.Height * App.AutofitAudio);
if (Core.IsImage) autoFitHeight = Convert.ToInt32(workingArea.Height * App.AutofitImage);
if (Core.VideoSize.Height == 0 || Core.VideoSize.Width == 0)
Core.VideoSize = new Size((int)(autoFitHeight * (16 / 9f)), autoFitHeight);
float minAspectRatio = Core.IsAudio ? App.MinimumAspectRatioAudio : App.MinimumAspectRatio;
if (minAspectRatio != 0 && Core.VideoSize.Width / (float)Core.VideoSize.Height < minAspectRatio)
Core.VideoSize = new Size((int)(autoFitHeight * minAspectRatio), autoFitHeight);
Size videoSize = Core.VideoSize;
int height = videoSize.Height;
@@ -479,7 +484,7 @@ namespace mpvnet
height = windowSize.Height;
width = height * videoSize.Width / videoSize.Height;
}
else if (App.StartSize == "height-session")
else if (App.StartSize == "height-session" || App.StartSize == "session")
{
height = autoFitHeight;
width = height * videoSize.Width / videoSize.Height;
@@ -494,7 +499,7 @@ namespace mpvnet
width = autoFitHeight / 9 * 16;
height = (int)Math.Ceiling(width * videoSize.Height / (double)videoSize.Width);
}
else if (KeepSize() && windowSize.Height != 0)
else if (App.StartSize == "always" && windowSize.Height != 0)
{
height = windowSize.Height;
width = windowSize.Width;
@@ -508,8 +513,10 @@ namespace mpvnet
void SetSize(int width, int height, Screen screen, bool checkAutofit = true)
{
int maxHeight = screen.WorkingArea.Height - (Height - ClientSize.Height) - 2;
int maxWidth = screen.WorkingArea.Width - (Width - ClientSize.Width);
Rectangle workingArea = GetWorkingArea(Handle, screen.WorkingArea);
int maxHeight = workingArea.Height - (Height - ClientSize.Height) - 2;
int maxWidth = workingArea.Width - (Width - ClientSize.Width);
int startWidth = width;
int startHeight = height;
@@ -564,10 +571,10 @@ namespace mpvnet
Screen[] screens = Screen.AllScreens;
int minLeft = screens.Select(val => val.WorkingArea.X).Min();
int maxRight = screens.Select(val => val.WorkingArea.Right).Max();
int minTop = screens.Select(val => val.WorkingArea.Y).Min();
int maxBottom = screens.Select(val => val.WorkingArea.Bottom).Max();
int minLeft = screens.Select(val => GetWorkingArea(Handle, val.WorkingArea).X).Min();
int maxRight = screens.Select(val => GetWorkingArea(Handle, val.WorkingArea).Right).Max();
int minTop = screens.Select(val => GetWorkingArea(Handle, val.WorkingArea).Y).Min();
int maxBottom = screens.Select(val => GetWorkingArea(Handle, val.WorkingArea).Bottom).Max();
if (left < minLeft)
left = minLeft;
@@ -613,7 +620,12 @@ namespace mpvnet
if (WasMaximized)
WindowState = FormWindowState.Maximized;
else
{
WindowState = FormWindowState.Normal;
if (!Core.WasInitialSizeSet)
SetFormPosAndSize();
}
if (Core.Border)
FormBorderStyle = FormBorderStyle.Sizable;
@@ -628,7 +640,7 @@ namespace mpvnet
public int GetHorizontalLocation(Screen screen)
{
Rectangle workingArea = screen.WorkingArea;
Rectangle workingArea = GetWorkingArea(Handle, screen.WorkingArea);
Rectangle rect = new Rectangle(Left - workingArea.X, Top - workingArea.Y, Width, Height);
if (workingArea.Width / (float)Width < 1.1)
@@ -645,7 +657,7 @@ namespace mpvnet
public int GetVerticalLocation(Screen screen)
{
Rectangle workingArea = screen.WorkingArea;
Rectangle workingArea = GetWorkingArea(Handle, screen.WorkingArea);
Rectangle rect = new Rectangle(Left - workingArea.X, Top - workingArea.Y, Width, Height);
if (workingArea.Height / (float)Height < 1.1)
@@ -662,10 +674,9 @@ namespace mpvnet
public void BuildMenu()
{
string content = File.ReadAllText(Core.InputConfPath);
var items = CommandItem.GetItems(content);
var items = CommandItem.GetItems(Core.InputConfContent);
if (!content.Contains("#menu:"))
if (!Core.InputConfContent.Contains("#menu:"))
{
var defaultItems = CommandItem.GetItems(Properties.Resources.input_conf);
@@ -679,41 +690,48 @@ namespace mpvnet
foreach (CommandItem item in items)
{
var tempItem = item;
CommandItem tempItem = item;
if (string.IsNullOrEmpty(tempItem.Path))
continue;
var menuItem = MenuHelp.Add(ContextMenu.Items, tempItem.Path);
if (menuItem != null)
if (MenuItemDuplicate.ContainsKey(tempItem.Path))
{
menuItem.Click += (sender, args) => {
try {
App.RunTask(() => {
MenuAutoResetEvent.WaitOne();
System.Windows.Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background, new Action(delegate { }));
if (!string.IsNullOrEmpty(tempItem.Command))
Core.Command(tempItem.Command);
});
}
catch (Exception ex) {
Msg.ShowException(ex);
}
};
var mi = MenuItemDuplicate[tempItem.Path];
mi.InputGestureText = mi.InputGestureText + ", " + tempItem.Input;
}
else
{
var menuItem = MenuHelp.Add(ContextMenu.Items, tempItem.Path);
menuItem.InputGestureText = tempItem.Input;
if (menuItem != null)
{
MenuItemDuplicate[tempItem.Path] = menuItem;
menuItem.Click += (sender, args) => {
try {
App.RunTask(() => {
MenuAutoResetEvent.WaitOne();
System.Windows.Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background, new Action(delegate { }));
if (!string.IsNullOrEmpty(tempItem.Command))
Core.Command(tempItem.Command);
});
}
catch (Exception ex) {
Msg.ShowException(ex);
}
};
menuItem.InputGestureText = tempItem.Input;
}
}
}
}
void Core_FileLoaded()
{
string path = Core.GetPropertyString("path");
BeginInvoke(new Action(() => {
Text = Core.Expand(Title);
SetTitleInternal();
int interval = (int)(Core.Duration.TotalMilliseconds / 100);
@@ -727,17 +745,47 @@ namespace mpvnet
UpdateProgressBar();
}));
if (App.Settings.RecentFiles.Contains(path))
App.Settings.RecentFiles.Remove(path);
string path = Core.GetPropertyString("path");
if ((path.Contains(":/") && !path.Contains("://")) || (path.Contains(":\\") && path.Contains("/")))
path = path.Replace("/", "\\");
if (path.Contains("://"))
{
string title = Core.GetPropertyString("media-title");
if (!string.IsNullOrEmpty(title) && path != title)
path = path + "|" + title;
}
if (!string.IsNullOrEmpty(path) && path != @"bd://" && path != @"dvd://")
{
if (App.Settings.RecentFiles.Contains(path))
App.Settings.RecentFiles.Remove(path);
if (path != @"bd://" && path != @"dvd://")
App.Settings.RecentFiles.Insert(0, path);
while (App.Settings.RecentFiles.Count > App.RecentCount)
App.Settings.RecentFiles.RemoveAt(App.RecentCount);
while (App.Settings.RecentFiles.Count > App.RecentCount)
App.Settings.RecentFiles.RemoveAt(App.RecentCount);
}
}
void SetTitle() => BeginInvoke(new Action(() => Text = Core.Expand(Title)));
void SetTitle() => BeginInvoke(new Action(() => SetTitleInternal()));
void SetTitleInternal()
{
string title = Title;
if (title == "${filename}" && Core.Path.ContainsEx("://"))
title = "${media-title}";
string text = Core.Expand(title);
if (text == "(unavailable)")
text = "mpv.net";
Text = text;
}
public void Voodoo()
{
@@ -747,7 +795,7 @@ namespace mpvnet
void SaveWindowProperties()
{
if (WindowState == FormWindowState.Normal && WasShown)
if (WindowState == FormWindowState.Normal && Core.Shown)
{
SavePosition();
App.Settings.WindowSize = ClientSize;
@@ -812,8 +860,14 @@ namespace mpvnet
case 0x20b: // WM_XBUTTONDOWN
case 0x20c: // WM_XBUTTONUP
case 0x20e: // WM_MOUSEHWHEEL
if (Core.WindowHandle != IntPtr.Zero)
m.Result = SendMessage(Core.WindowHandle, m.Msg, m.WParam, m.LParam);
if (mpvWindowHandle == IntPtr.Zero)
mpvWindowHandle = FindWindowEx(Handle, IntPtr.Zero, "mpv", null);
if (mpvWindowHandle != IntPtr.Zero)
m.Result = SendMessage(mpvWindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x51: // WM_INPUTLANGCHANGE
ActivateKeyboardLayout(m.LParam, 0x00000100u /*KLF_SETFORPROCESS*/);
break;
case 0x319: // WM_APPCOMMAND
{
@@ -827,10 +881,10 @@ namespace mpvnet
}
}
break;
case 0x0312: // WM_HOTKEY
case 0x312: // WM_HOTKEY
GlobalHotkey.Execute(m.WParam.ToInt32());
break;
case 0x0200: // WM_MOUSEMOVE
case 0x200: // WM_MOUSEMOVE
if (Environment.TickCount - LastCycleFullscreen > 500)
{
Point pos = PointToClient(Cursor.Position);
@@ -850,16 +904,16 @@ namespace mpvnet
Core.Command($"mouse {pos.X} {pos.Y} 0 double");
}
break;
case 0x02E0: // WM_DPICHANGED
case 0x2E0: // WM_DPICHANGED
{
if (!WasShown)
if (!Core.Shown)
break;
RECT rect = Marshal.PtrToStructure<RECT>(m.LParam);
SetWindowPos(Handle, IntPtr.Zero, rect.Left, rect.Top, rect.Width, rect.Height, 0);
}
break;
case 0x0214: // WM_SIZING
case 0x214: // WM_SIZING
if (Core.KeepaspectWindow)
{
RECT rc = Marshal.PtrToStructure<RECT>(m.LParam);
@@ -887,7 +941,7 @@ namespace mpvnet
m.Result = new IntPtr(1);
}
return;
case 0x004A: // WM_COPYDATA
case 0x4A: // WM_COPYDATA
{
var copyData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
string[] args = copyData.lpData.Split('\n');
@@ -911,6 +965,56 @@ namespace mpvnet
Activate();
}
return;
case 0x84: // WM_NCHITTEST
// resize borderless window
if (!Core.Border && !Core.Fullscreen) {
const int HTCLIENT = 1;
const int HTLEFT = 10;
const int HTRIGHT = 11;
const int HTTOP = 12;
const int HTTOPLEFT = 13;
const int HTTOPRIGHT = 14;
const int HTBOTTOM = 15;
const int HTBOTTOMLEFT = 16;
const int HTBOTTOMRIGHT = 17;
int x = (short)(m.LParam.ToInt32() & 0xFFFF); // LoWord
int y = (short)(m.LParam.ToInt32() >> 16); // HiWord
Point pt = PointToClient(new Point(x, y));
Size cs = ClientSize;
m.Result = new IntPtr(HTCLIENT);
int distance = FontHeight / 3;
if (pt.X >= cs.Width - distance && pt.Y >= cs.Height - distance && cs.Height >= distance)
m.Result = (IntPtr)HTBOTTOMRIGHT;
else if (pt.X <= distance && pt.Y >= cs.Height - distance && cs.Height >= distance)
m.Result = (IntPtr)HTBOTTOMLEFT;
else if (pt.X <= distance && pt.Y <= distance && cs.Height >= distance)
m.Result = (IntPtr)HTTOPLEFT;
else if (pt.X >= cs.Width - distance && pt.Y <= distance && cs.Height >= distance)
m.Result = (IntPtr)HTTOPRIGHT;
else if (pt.Y <= distance && cs.Height >= distance)
m.Result = (IntPtr)HTTOP;
else if (pt.Y >= cs.Height - distance && cs.Height >= distance)
m.Result = (IntPtr)HTBOTTOM;
else if (pt.X <= distance && cs.Height >= distance)
m.Result = (IntPtr)HTLEFT;
else if (pt.X >= cs.Width - distance && cs.Height >= distance)
m.Result = (IntPtr)HTRIGHT;
return;
}
break;
case 0x231: // WM_ENTERSIZEMOVE
case 0x005: // WM_SIZE
if (Core.SnapWindow)
SnapManager.OnSizeAndEnterSizeMove(this);
break;
case 0x216: // WM_MOVING
if (Core.SnapWindow)
SnapManager.OnMoving(ref m);
break;
}
if (m.Msg == TaskbarButtonCreatedMessage && Core.TaskbarProgress)
@@ -943,7 +1047,7 @@ namespace mpvnet
void UpdateProgressBar()
{
if (Core.TaskbarProgress && Taskbar != null)
Taskbar.SetValue(Core.GetPropertyDouble("time-pos"), Core.Duration.TotalSeconds);
Taskbar.SetValue(Core.GetPropertyDouble("time-pos", false), Core.Duration.TotalSeconds);
}
void PropChangeOnTop(bool value) => BeginInvoke(new Action(() => TopMost = value));
@@ -960,7 +1064,7 @@ namespace mpvnet
void PropChangeWindowMaximized()
{
if (!WasShown)
if (!Core.Shown)
return;
BeginInvoke(new Action(() =>
@@ -976,7 +1080,7 @@ namespace mpvnet
void PropChangeWindowMinimized()
{
if (!WasShown)
if (!Core.Shown)
return;
BeginInvoke(new Action(() =>
@@ -1005,13 +1109,11 @@ namespace mpvnet
}));
}
void PropChangePause(bool paused)
void Core_Pause()
{
Core.Paused = paused;
if (Taskbar != null && Core.TaskbarProgress)
{
if (paused)
if (Core.Paused)
Taskbar.SetState(TaskbarStates.Paused);
else
Taskbar.SetState(TaskbarStates.Normal);
@@ -1021,9 +1123,12 @@ namespace mpvnet
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Core.VideoSizeAutoResetEvent.WaitOne(App.StartThreshold);
if (Core.GPUAPI != "vulkan")
Core.VideoSizeAutoResetEvent.WaitOne(App.StartThreshold);
LastCycleFullscreen = Environment.TickCount;
SetFormPosAndSize();
if (Core.PlaylistPos == -1)
Core.ShowLogo();
}
protected override void OnActivated(EventArgs e)
@@ -1036,12 +1141,12 @@ namespace mpvnet
{
base.OnShown(e);
if (Core.GPUAPI == "vulkan")
Init();
if (WindowState == FormWindowState.Maximized)
Core.SetPropertyBool("window-maximized", true);
if (Core.GPUAPI == "vulkan")
Core.ProcessCommandLine(false);
WPF.Init();
App.UpdateWpfColors();
MessageBoxEx.MessageForeground = Theme.Current.GetBrush("heading");
@@ -1058,7 +1163,7 @@ namespace mpvnet
App.RunTask(() => App.Extension = new Extension());
App.RunTask(() => App.CopyMpvnetCom());
CSharpScriptHost.ExecuteScriptsInFolder(Core.ConfigFolder + "scripts-cs");
WasShown = true;
Core.Shown = true;
}
void ContextMenu_Closed(object sender, System.Windows.RoutedEventArgs e)
@@ -1071,7 +1176,7 @@ namespace mpvnet
base.OnResize(e);
SaveWindowProperties();
if (Core.IsLogoVisible)
if (Core.PlaylistPos == -1 && Core.Shown)
Core.ShowLogo();
if (FormBorderStyle != FormBorderStyle.None)
@@ -1082,7 +1187,7 @@ namespace mpvnet
WasMaximized = false;
}
if (WasShown)
if (Core.Shown)
{
if (WindowState == FormWindowState.Minimized)
Core.SetPropertyBool("window-minimized", true);
@@ -1242,7 +1347,7 @@ namespace mpvnet
if (CommandPaletteHost == null)
return;
CommandPaletteHost.Width = FontHeight * 25;
CommandPaletteHost.Width = FontHeight * 26;
if (CommandPaletteHost.Width > ClientSize.Width)
CommandPaletteHost.Width = ClientSize.Width;

View File

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

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using static mpvnet.Native;
namespace mpvnet
{
public class SnapManager
{
int DragOffsetX { get; set; }
int DragOffsetY { get; set; }
IntPtr Handle;
[Flags]
public enum SnapLocation
{
None = 0,
Left = 1 << 0,
Top = 1 << 1,
Right = 1 << 2,
Bottom = 1 << 3,
All = Left | Top | Right | Bottom
}
public int AnchorDistance { get; set; }
public int SnapDistance { get; set; }
bool InSnapRange(int a, int b) => Math.Abs(a - b) < SnapDistance;
void FindSnap(ref Rectangle effectiveBounds)
{
Screen currentScreen = Screen.FromPoint(effectiveBounds.Location);
Rectangle workingArea = GetWorkingArea(Handle, currentScreen.WorkingArea);
if (InSnapRange(effectiveBounds.Left, workingArea.Left + AnchorDistance))
effectiveBounds.X = workingArea.Left + AnchorDistance;
else if (InSnapRange(effectiveBounds.Right, workingArea.Right - AnchorDistance))
effectiveBounds.X = workingArea.Right - AnchorDistance - effectiveBounds.Width;
if (InSnapRange(effectiveBounds.Top, workingArea.Top + AnchorDistance))
effectiveBounds.Y = workingArea.Top + AnchorDistance;
else if (InSnapRange(effectiveBounds.Bottom, workingArea.Bottom - AnchorDistance))
effectiveBounds.Y = workingArea.Bottom - AnchorDistance - effectiveBounds.Height;
}
public void OnMoving(ref Message m)
{
if (Handle == IntPtr.Zero)
return;
RECT boundsLtrb = Marshal.PtrToStructure<RECT>(m.LParam);
Rectangle bounds = boundsLtrb.ToRectangle();
// This is where the window _would_ be located if snapping
// had not occurred. This prevents the cursor from sliding
// off the title bar if the snap distance is too large.
Rectangle effectiveBounds = new Rectangle(
Cursor.Position.X - DragOffsetX,
Cursor.Position.Y - DragOffsetY,
bounds.Width,
bounds.Height);
FindSnap(ref effectiveBounds);
RECT newLtrb = RECT.FromRectangle(effectiveBounds);
Marshal.StructureToPtr(newLtrb, m.LParam, false);
m.Result = new IntPtr(1);
}
public void OnSizeAndEnterSizeMove(Form form)
{
Handle = form.Handle;
SnapDistance = form.Font.Height;
// Need to handle window size changed as well when
// un-maximizing the form by dragging the title bar.
DragOffsetX = Cursor.Position.X - form.Left;
DragOffsetY = Cursor.Position.Y - form.Top;
}
}
}

View File

@@ -93,6 +93,7 @@
<Compile Include="Misc\Common.cs" />
<Compile Include="Misc\FolderBrowser.cs" />
<Compile Include="Misc\JSONParser.cs" />
<Compile Include="WinForms\SnapManager.cs" />
<Compile Include="WPF\HandyControl\Controls\Attach\BorderElement.cs" />
<Compile Include="WPF\HandyControl\Controls\Attach\MenuTopLineAttach.cs" />
<Compile Include="WPF\HandyControl\Tools\Converter\BorderCircularConverter.cs" />
@@ -186,14 +187,14 @@
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Native\libmpv.cs" />
<Compile Include="Misc\MainForm.cs">
<Compile Include="WinForms\MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Misc\MainForm.Designer.cs">
<Compile Include="WinForms\MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Misc\Misc.cs" />
<Compile Include="Misc\CorePlayer.cs" />
<Compile Include="Misc\Player.cs" />
<Compile Include="Misc\Commands.cs" />
<Compile Include="Native\Native.cs" />
<Compile Include="Misc\Program.cs" />
@@ -211,7 +212,7 @@
<DependentUpon>InputWindow.xaml</DependentUpon>
</Compile>
<Compile Include="WPF\WPF.cs" />
<EmbeddedResource Include="Misc\MainForm.resx">
<EmbeddedResource Include="WinForms\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>