Compare commits

...

25 Commits
4.7 ... 4.7.7

Author SHA1 Message Date
Frank Skare
d321ab477f key binding MBTN_Mid 2019-07-21 20:31:47 +02:00
Frank Skare
1cd0f87278 readme, manual and AssemblyInfo.cs updated 2019-07-21 20:10:35 +02:00
Frank Skare
936274fc3b new main screenshot, about dialog for rating addon 2019-07-21 19:56:19 +02:00
Frank Skare
2bbaa30322 options autofit-smaller, autofit-larger added 2019-07-21 19:22:17 +02:00
Frank Skare
cedd54d64d start-threshold setting added 2019-07-21 17:06:55 +02:00
Frank Skare
38604459a6 update changelog 2019-07-20 17:54:52 +02:00
Frank Skare
0a48a0dc6f new logic to find the settings folder 2019-07-20 17:53:34 +02:00
Frank Skare
85a23fbae1 tweaks and refactoring 2019-07-18 05:47:16 +02:00
Frank Skare
01da76bdc4 fix changelog 2019-07-17 19:22:47 +02:00
Frank Skare
1f1553e159 - 2019-07-17 19:04:24 +02:00
Frank Skare
2af84941ca color theme related improvements 2019-07-17 18:18:33 +02:00
Frank Skare
a82f558acf - 2019-07-14 12:22:50 +02:00
Frank Skare
d13f7201ba - 2019-07-14 06:16:52 +02:00
Frank Skare
89aa0c6133 added image format support to the info command, to file association management, to folder loading, to Everything 2019-07-14 06:07:25 +02:00
Frank Skare
1699467e0d added image format support for the info command 2019-07-14 05:52:23 +02:00
Frank Skare
7a27ab0513 added file size to info command using audio files 2019-07-14 05:38:53 +02:00
Frank Skare
2a0c68e4ec - 2019-07-14 05:15:59 +02:00
Frank Skare
91c42d4d3f - 2019-07-14 05:04:22 +02:00
Frank Skare
49d56166d7 - 2019-07-14 04:34:45 +02:00
Frank Skare
1ac603b904 - 2019-07-14 04:03:58 +02:00
Frank Skare
d5b2923c68 reorganize code for easier scripting 2019-07-14 02:06:23 +02:00
Frank Skare
b80b375df1 move code before base.OnShown so scripts can use the ContextMenu 2019-07-14 01:40:13 +02:00
Frank Skare
2b2b60b90f fix rotating cursor 2019-07-13 19:22:51 +02:00
Frank Skare
3977283ecb minor tweak 2019-07-13 17:49:39 +02:00
Frank Skare
d27778775d few layout problems were fixed, autosize for instance did not work 2019-07-13 16:35:42 +02:00
26 changed files with 675 additions and 446 deletions

View File

@@ -1,3 +1,37 @@
### 4.7.7
- on Win 7 the theme color was hardcoded to DarkSlateGrey because
WPF was returning a bad color on Win 7, this was fixed by reading
the theme color from the Registry on Win 7. If the theme color
is identical to the background color it's corrected
- dark-color setting was added to overwrite the OS theme color used in dark mode,
find the setting on the General tab
- light-color setting was added to overwrite the OS theme color used in non dark mode,
find the setting on the General tab
- various changes regarding input handling, multi media keys and
mouse forward/backward were successfully tested
- it's now possible to use a custom folder as config folder,
A TaskDialog shows five options: 1. appdata mpv.net, 2. appdata mpv (shared with mpv),
3. portable_config, 4. startup, 5. custom
- slightly increased startup performance, start-threshold setting added.
Threshold in milliseconds to wait for libmpv returning the video resolution
before the window is shown, otherwise default dimensions are used as defined
by autofit and start-size. Default: 1500
- autofit-smaller setting added. Minimum window height in percent. Default: 40%
- autofit-larger setting added. Maximum window height in percent. Default: 75%
### 4.7.3
- fix cursor showing load activity on startup
- added file size and type to info command using audio files
- added image format support to the info command, to file
association management, to folder loading, to Everything
- readme/github have a updated features and architecture section
### 4.7.1
- few layout problems were fixed, autosize for instance did not work
### 4.7 ### 4.7
- remember-height was replaced with start-size, when start-size is set - remember-height was replaced with start-size, when start-size is set
@@ -7,10 +41,10 @@
- on exit the window location can be saved with remember-position - on exit the window location can be saved with remember-position
- in the learn window of the input editor underscores were stripped - in the learn window of the input editor underscores were stripped
because they have a special meaning in WPF labels because they have a special meaning in WPF labels
- keys/input not working for MBTN_LEFT_DBL, MBTN_BACK, MBTN_FORWARD - fix for keys/input not working for MBTN_LEFT_DBL, MBTN_BACK, MBTN_FORWARD
- in the learn window of the input editor support was added for - in the learn window of the input editor support was added for
mouse left, mouse left double, mouse mid, mouse forward, mouse back mouse left, mouse left double, mouse mid, mouse forward, mouse back
- libmpv updated to shinchiro 2019-07-07 - libmpv was updated to shinchiro 2019-07-07
- when border is none it wasn't possible to minimize the window from - when border is none it wasn't possible to minimize the window from
the task bar because this is the WinForms default behavier. This the task bar because this is the WinForms default behavier. This
was fixed by calling Spy++ to the rescue and adding WS_MINIMIZEBOX was fixed by calling Spy++ to the rescue and adding WS_MINIMIZEBOX

View File

@@ -90,7 +90,6 @@
+ [Exit](#exit) + [Exit](#exit)
+ [Exit Watch Later](#exit-watch-later) + [Exit Watch Later](#exit-watch-later)
* [Command Line Interface](#command-line-interface) * [Command Line Interface](#command-line-interface)
* [Settings](#settings)
## About mpv.net ## About mpv.net
@@ -734,7 +733,7 @@ Shows the command palette window which allows to find mpv.net commands, it shows
### Tools > Show History ### Tools > Show History
When enabled shows a file that contains the playback history containing the time and filename. Shows a text file that contains the file history. If the file don't exist it asks if the file should be created in the settings folder. Once the file exist then the history is logged. It logges the playback history containing the time and filename.
### Tools > Set/clear A-B loop points ### Tools > Set/clear A-B loop points
@@ -819,28 +818,3 @@ mpvnet implements a basic CLI to set mpv commands.
Example: Example:
mpvnet --mute=yes <file|URL> mpvnet --mute=yes <file|URL>
## Settings
mpv.net is able to share the settings with mpv and mpv.net uses the same logic to decide from where the settings are loaded. The default location is:
```Text
C:\Users\%username%\AppData\Roaming\mpv\mpv.conf
```
If a directory named portable_config next to the mpvnet.exe exists, all config will be loaded from this directory only.
```Text
<startup>\portable_config\mpv.conf
```
In case there isn't any config folder mpv.net asks where to create it. If no mpv.conf file exists mpv.net generates it with the following defaults:
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt>
Config files located in the same directory as mpvnet.exe are loaded with lower priority. Some config files are loaded only once, which means that e.g. of 2 input.conf files located in two config directories, only the one from the directory with higher priority will be loaded.
The key bindings and the context menu definitions are stored in the input.conf file,
if it's missing mpv.net generates it with the following defaults:
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt>

View File

@@ -46,19 +46,38 @@ Table of contents
### Features ### Features
- Very high degree of mpv compatibility, almost all mpv features are available
- Great usability due to everything in the application being searchable
- Open source built with modern tools
- Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt)) - Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt))
- Searchable config dialog ([Screenshot](#config-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt)) - Searchable config dialog ([Screenshot](#config-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt))
- Searchable input (key/mouse) binding editor ([Screenshot](#input-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt)) - Searchable input (key/mouse) binding editor ([Screenshot](#input-editor-screenshot), [Defaults](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt))
- Configuration files that are easy to read and edit
- Searchable command palette to quickly launch commands and look for keys ([Screenshot](#command-palette-screenshot)) - Searchable command palette to quickly launch commands and look for keys ([Screenshot](#command-palette-screenshot))
- Modern UI with dark mode ([Screenshot](#config-editor-screenshot)) - Modern WPF based graphical user interface with dark mode ([Screenshot](#config-editor-screenshot))
- Addon/extension API for .NET languages - Addon/extension API for .NET languages
- Scripting API for Python, C#, Lua, JavaScript and PowerShell ([Wiki](https://github.com/stax76/mpv.net/wiki/Scripting)) - Scripting API for Python, C#, Lua, JavaScript and PowerShell ([Wiki](https://github.com/stax76/mpv.net/wiki/Scripting))
- mpv's OSC, IPC and conf files - Language agnostic JSON IPC to control the player with a external programs
- On Screen Controler (OSC, play control buttons)
- [Command Line Interface](https://mpv.io/manual/master/#options) - [Command Line Interface](https://mpv.io/manual/master/#options)
- DXVA2 video decoding acceleration - DXVA2 video decoding acceleration
- OpenGL based video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more - OpenGL based video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more
- Search feature powered by [Everything](https://www.voidtools.com) to find and play media ([Screenshot](#media-search-screenshot)) - Search feature powered by [Everything](https://www.voidtools.com) to find and play media ([Screenshot](#media-search-screenshot))
- Extension to start mpv.net from Google Chrome ([Manual](Manual.md#chrome-extension)) - Extension to start mpv.net from Google Chrome ([Manual](Manual.md#chrome-extension))
- Extremely fast seek performance
- Very fast startup performance, video is usally ready to play in less then a second
- Usable as video player, audio player and image viewer with a wide range of supported formats
- All decoders are built-in, no external codecs have to be installed
- Setup and portable download options, setup is recommended but not required
- Build-in media streaming via youtube-dl
- x64 and x86 Support (64-bit and 32-bit)
- File associations can be created by the setup and from the player
- External audio and subtitle files can either be loaded manually or automatically
- Screenshot feature with many options
- File history feature to log time and filename
- A-B loop feature
- watch later feature to save the position
- [Manual](#manual)
### Screenshots ### Screenshots
@@ -117,30 +136,32 @@ input.conf defines mpv's key and mouse bindings and mpv.net uses comments to def
### Settings ### Settings
mpv.net is able to share the settings with mpv and mpv.net uses the same logic to decide from where the settings are loaded. The default location is: mpv.net is able to share the settings with mpv.
If a directory named portable_config next to the mpvnet.exe exists,
all config will be loaded from this directory only.
```Text ```Text
C:\Users\%username%\AppData\Roaming\mpv\mpv.conf <startup>\portable_config\
``` ```
If a directory named portable_config next to the mpvnet.exe exists, all config will be loaded from this directory only. On first start if no portable config folder exists mpv.net asks
which folder should be used as config folder.
```Text mpv specific settings are stored in the file mpv.conf, if no mpv.conf file exists
<startup>\portable_config\mpv.conf mpv.net generates it with the following defaults:
```
In case there isn't any config folder mpv.net asks where to create it. If no mpv.conf file exists mpv.net generates it with the following defaults:
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt> <https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/mpvConf.txt>
Config files located in the same directory as mpvnet.exe are loaded with lower priority. Some config files are loaded only once, which means that e.g. of 2 input.conf files located in two config directories, only the one from the directory with higher priority will be loaded. mpv.net specific settings are stored in the file mpvnet.conf
The key bindings and the context menu definitions are stored in the input.conf file, The input (key/mouse) bindings and the context menu definitions are stored in the
if it's missing mpv.net generates it with the following defaults: input.conf file, if it's missing mpv.net generates it with the following defaults:
<https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt> <https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt>
mpv.net supports almost all mpv settings and features, [limitations are listed in the wiki](https://github.com/stax76/mpv.net/wiki/Limitations). mpv.net supports almost all mpv settings and features,
[limitations are listed in the wiki](https://github.com/stax76/mpv.net/wiki/Limitations).
### Scripting ### Scripting
@@ -152,7 +173,15 @@ mpv.net supports almost all mpv settings and features, [limitations are listed i
### Architecture ### Architecture
mpv.net is written in C# 7.0 and runs on the .NET framework 4.7 or higher. Coding mpv.net was great fun because libmpv is such a awesome
library with a very clever design, I'm having a great experience
with libmpv.
The player does not contain any feature that was more work than 1-2 days or
was difficult to build, the hard parts are totally covered by libmpv.
mpv.net is written in C# 7 and runs on .NET 4.7, I've not yet decided
if I will port it to C# 8 and .NET 5 once available.
The Add-on implementation is based on the [Managed Extensibility Framework](https://docs.microsoft.com/en-us/dotnet/framework/mef/). The Add-on implementation is based on the [Managed Extensibility Framework](https://docs.microsoft.com/en-us/dotnet/framework/mef/).
@@ -162,9 +191,10 @@ this decision was made to keep the code simple and lightweight.
Python scripting is implemented with IronPython which uses Python 2.7. Python scripting is implemented with IronPython which uses Python 2.7.
The main/video window is WinForms based, all other windows are WPF based. The main window is WinForms based and uses less than 600 lines of code,
all other windows are WPF based and use even less code.
The config editor adds it's controls dynamically and uses TOML to define it's The config editor adds it's controls dynamically and uses [TOML](https://en.wikipedia.org/wiki/TOML) to define it's
content, there are only two simple types, StringSetting and OptionSetting. content, there are only two simple types, StringSetting and OptionSetting.
mpv.net was started 2017 and consists of about 6000 lines of code and markup. mpv.net was started 2017 and consists of about 6000 lines of code and markup.

View File

@@ -16,8 +16,8 @@ Public Class CSScriptAddon
Sub New() Sub New()
Dim scriptFiles As New List(Of String) Dim scriptFiles As New List(Of String)
If Directory.Exists(mp.ConfFolder + "scripts") Then If Directory.Exists(mp.ConfigFolder + "scripts") Then
scriptFiles.AddRange(Directory.GetFiles(mp.ConfFolder + "scripts", "*.cs")) scriptFiles.AddRange(Directory.GetFiles(mp.ConfigFolder + "scripts", "*.cs"))
End If End If
If Directory.Exists(Application.StartupPath + "\scripts") Then If Directory.Exists(Application.StartupPath + "\scripts") Then

View File

@@ -1,5 +1,4 @@
// this addon writes a rating to the filename of the current video, // sometimes the add-on don't work, it's containing a lot of trace code at the moment
// the input.conf defaults contain key bindings for this addon
using System; using System;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
@@ -7,30 +6,36 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using mpvnet; using mpvnet;
using System.Diagnostics;
// the assembly name must end with 'Addon'
namespace RatingAddon namespace RatingAddon
{ {
[Export(typeof(IAddon))] [Export(typeof(IAddon))]
public class RatingAddon : IAddon public class RatingAddon : IAddon
{ {
// dictionory to store the filename and the rating
Dictionary<string, int> Dic = new Dictionary<string, int>(); Dictionary<string, int> Dic = new Dictionary<string, int>();
public RatingAddon() public RatingAddon() // plugin initialization
{ {
mp.ClientMessage += ClientMessage; //handles keys defined in input.conf mp.ClientMessage += ClientMessage; //handles keys defined in input.conf
mp.Shutdown += Shutdown; mp.Shutdown += Shutdown; // handles MPV_EVENT_SHUTDOWN
} }
// handles MPV_EVENT_SHUTDOWN
void Shutdown() void Shutdown()
{ {
if (App.DebugMode) Trace.WriteLine("aaa");
foreach (var i in Dic) foreach (var i in Dic)
{ {
string filepath = i.Key; string filepath = i.Key;
int rating = i.Value; int rating = i.Value;
if (App.DebugMode) Trace.WriteLine("bbb");
if (String.IsNullOrEmpty(filepath) || ! File.Exists(filepath)) if (String.IsNullOrEmpty(filepath) || ! File.Exists(filepath))
return; return;
if (App.DebugMode) Trace.WriteLine("ccc");
string basename = Path.GetFileNameWithoutExtension(filepath); string basename = Path.GetFileNameWithoutExtension(filepath);
for (int x = 0; x < 6; x++) for (int x = 0; x < 6; x++)
@@ -39,21 +44,29 @@ namespace RatingAddon
basename += $" ({rating}stars)"; basename += $" ({rating}stars)";
string newPath = Path.Combine(Path.GetDirectoryName(filepath), basename + Path.GetExtension(filepath)); string newPath = Path.Combine(Path.GetDirectoryName(filepath), basename + Path.GetExtension(filepath));
if (App.DebugMode) Trace.WriteLine("ddd");
if (filepath.ToLower() != newPath.ToLower()) if (filepath.ToLower() != newPath.ToLower())
File.Move(filepath, newPath); File.Move(filepath, newPath);
if (App.DebugMode) Trace.WriteLine("eee");
File.SetLastWriteTime(newPath, DateTime.Now); File.SetLastWriteTime(newPath, DateTime.Now);
if (App.DebugMode) Trace.WriteLine("fff");
} }
} }
//handles keys defined in input.conf //handles keys defined in input.conf
void ClientMessage(string[] args) void ClientMessage(string[] args)
{ {
if (args[0] != "rate-file" || ! int.TryParse(args[1], out int rating)) if (args[0] != "rate-file") return;
return;
Dic[mp.get_property_string("path")] = rating; if (int.TryParse(args[1], out int rating))
mp.commandv("show-text", $"Rating: {rating}"); {
string path = mp.get_property_string("path");
if (!File.Exists(path)) return;
Dic[path] = rating;
mp.commandv("show-text", $"Rating: {rating}");
}
else if (args[1] == "about")
Msg.Show("Rating Extension", "This extension writes a rating to the filename of rated videos when mpv.net shuts down.\n\nThe input.conf defaults contain key bindings for this addon to set ratings.");
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@@ -15,7 +15,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBox x:Name="ValueTextBox" Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="150" HorizontalAlignment="Left" Height="20" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" TextChanged="ValueTextBox_TextChanged"/> <TextBox x:Name="ValueTextBox" Text="{Binding Path=Text, ElementName=StringSettingControl1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="150" HorizontalAlignment="Left" Height="20" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CaretBrush="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" TextChanged="ValueTextBox_TextChanged"/>
<Button x:Name="Button" Height="20" Grid.Column="1" Visibility="{Binding Path=Text, ElementName=StringSettingControl1}" Margin="5,0,0,0" Width="20" Click="Button_Click">...</Button> <Button x:Name="Button" Height="20" Grid.Column="1" Visibility="{Binding Path=Text, ElementName=StringSettingControl1}" Margin="5,0,0,0" Width="20" Click="Button_Click">...</Button>
</Grid> </Grid>
<TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox> <TextBox x:Name="HelpTextBox" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Background="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></TextBox>

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@@ -55,7 +56,7 @@ namespace DynamicGUI
{ {
d.Description = "Choose a folder."; d.Description = "Choose a folder.";
d.SelectedPath = ValueTextBox.Text; d.SelectedPath = ValueTextBox.Text;
if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) if (d.ShowDialog() == WinForms.DialogResult.OK)
ValueTextBox.Text = d.SelectedPath; ValueTextBox.Text = d.SelectedPath;
} }
break; break;
@@ -64,11 +65,14 @@ namespace DynamicGUI
{ {
d.FullOpen = true; d.FullOpen = true;
try { try {
Color col = GetColor(ValueTextBox.Text); if (!string.IsNullOrEmpty(ValueTextBox.Text))
d.Color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B); {
} catch { } Color col = GetColor(ValueTextBox.Text);
d.Color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B);
}
} catch {}
if (d.ShowDialog() == WinForms.DialogResult.OK) if (d.ShowDialog() == WinForms.DialogResult.OK)
ValueTextBox.Text = System.Drawing.ColorTranslator.ToHtml(d.Color); ValueTextBox.Text = "#" + d.Color.ToArgb().ToString("X8");
} }
break; break;
} }

View File

@@ -26,7 +26,7 @@ namespace mpvnet
foreach (string i in Directory.GetDirectories(dir)) foreach (string i in Directory.GetDirectories(dir))
catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll")); catalog.Catalogs.Add(new DirectoryCatalog(i, "*Addon.dll"));
dir = mp.ConfFolder + "\\Addons"; dir = mp.ConfigFolder + "\\Addons";
if (Directory.Exists(dir)) if (Directory.Exists(dir))
foreach (string i in Directory.GetDirectories(dir)) foreach (string i in Directory.GetDirectories(dir))

View File

@@ -28,7 +28,7 @@ namespace mpvnet
case "show-about": ShowDialog(typeof(AboutWindow)); break; case "show-about": ShowDialog(typeof(AboutWindow)); break;
case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break; case "show-conf-editor": ShowDialog(typeof(ConfWindow)); break;
case "show-input-editor": ShowDialog(typeof(InputWindow)); break; case "show-input-editor": ShowDialog(typeof(InputWindow)); break;
case "open-conf-folder": Process.Start(mp.ConfFolder); break; case "open-conf-folder": Process.Start(mp.ConfigFolder); break;
case "open-files": OpenFiles(args); break; case "open-files": OpenFiles(args); break;
case "shell-execute": Process.Start(args[0]); break; case "shell-execute": Process.Start(args[0]); break;
case "show-info": ShowInfo(); break; case "show-info": ShowInfo(); break;
@@ -68,7 +68,7 @@ namespace mpvnet
public static void ShowHistory() public static void ShowHistory()
{ {
var fp = mp.ConfFolder + "history.txt"; var fp = mp.ConfigFolder + "history.txt";
if (File.Exists(fp)) if (File.Exists(fp))
Process.Start(fp); Process.Start(fp);
@@ -109,6 +109,22 @@ namespace mpvnet
if (genre != "") text += "Genre: " + genre + "\n"; if (genre != "") text += "Genre: " + genre + "\n";
if (date != "") text += "Year: " + date + "\n"; if (date != "") text += "Year: " + date + "\n";
if (duration != "") text += "Length: " + duration + "\n"; if (duration != "") text += "Length: " + duration + "\n";
text += "Size: " + mediaInfo.GetInfo(MediaInfoStreamKind.General, "FileSize/String") + "\n";
text += "Type: " + Path.GetExtension(path).ToUpper().TrimStart('.');
mp.commandv("show-text", text, "5000");
return;
}
}
else if (App.ImageTypes.Contains(Path.GetExtension(path).ToLower().TrimStart('.')))
{
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.GetExtension(path).ToUpper().TrimStart('.');
mp.commandv("show-text", text, "5000"); mp.commandv("show-text", text, "5000");
return; return;
@@ -170,7 +186,8 @@ namespace mpvnet
InvokeOnMainThread(new Action(() => { InvokeOnMainThread(new Action(() => {
using (var d = new OpenFileDialog()) using (var d = new OpenFileDialog())
{ {
d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false)); string path = mp.get_property_string("path");
if (File.Exists(path)) d.InitialDirectory = Path.GetDirectoryName(path);
d.Multiselect = true; d.Multiselect = true;
if (d.ShowDialog() == DialogResult.OK) if (d.ShowDialog() == DialogResult.OK)
foreach (string i in d.FileNames) foreach (string i in d.FileNames)
@@ -184,7 +201,9 @@ namespace mpvnet
InvokeOnMainThread(new Action(() => { InvokeOnMainThread(new Action(() => {
using (var d = new OpenFileDialog()) using (var d = new OpenFileDialog())
{ {
d.InitialDirectory = Path.GetDirectoryName(mp.get_property_string("path", false)); string path = mp.get_property_string("path");
if (File.Exists(path))
d.InitialDirectory = Path.GetDirectoryName(path);
d.Multiselect = true; d.Multiselect = true;
if (d.ShowDialog() == DialogResult.OK) if (d.ShowDialog() == DialogResult.OK)
@@ -196,10 +215,10 @@ namespace mpvnet
public static void CycleAudio() public static void CycleAudio()
{ {
string filePath = mp.get_property_string("path", false); string path = mp.get_property_string("path");
if (!File.Exists(filePath)) return; if (!File.Exists(path)) return;
using (MediaInfo mi = new MediaInfo(filePath)) using (MediaInfo mi = new MediaInfo(path))
{ {
MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray(); MediaTrack[] audTracks = mp.MediaTracks.Where(track => track.Type == "a").ToArray();
if (audTracks.Length < 2) return; if (audTracks.Length < 2) return;
@@ -220,6 +239,7 @@ namespace mpvnet
td.AddCommandLink("Register video file extensions", "video"); td.AddCommandLink("Register video file extensions", "video");
td.AddCommandLink("Register audio file extensions", "audio"); td.AddCommandLink("Register audio file extensions", "audio");
td.AddCommandLink("Register audio file extensions", "image");
td.AddCommandLink("Unregister file extensions", "unreg"); td.AddCommandLink("Unregister file extensions", "unreg");
string result = td.Show(); string result = td.Show();

View File

@@ -18,19 +18,24 @@ namespace mpvnet
{ {
public class App public class App
{ {
public static string ConfFilePath { get; } = mp.ConfFolder + "\\mpvnet.conf";
public static string RegPath { get; } = @"HKCU\Software\" + Application.ProductName; public static string RegPath { get; } = @"HKCU\Software\" + Application.ProductName;
public static string ConfFilePath { get; } = mp.ConfigFolder + "\\mpvnet.conf";
public static string DarkMode { get; set; } = "always"; public static string DarkMode { get; set; } = "always";
public static string ProcessInstance { get; set; } = "single"; public static string ProcessInstance { get; set; } = "single";
public static string DarkColor { get; set; }
public static string LightColor { get; set; }
public static string[] VideoTypes { get; } = "mkv mp4 mpg avi mov webm vob wmv flv avs 264 h264 asf webm mpeg mpv y4m avc hevc 265 h265 m2v m2ts vpy mts m4v".Split(' '); public static string[] VideoTypes { get; } = "mkv mp4 mpg avi mov webm vob wmv flv avs 264 h264 asf webm mpeg mpv y4m avc hevc 265 h265 m2v m2ts vpy mts m4v".Split(' ');
public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(' '); public static string[] AudioTypes { get; } = "mp3 mp2 ac3 ogg opus flac wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 mka aac mpa".Split(' ');
public static string[] ImageTypes { get; } = "jpg bmp gif".Split(' ');
public static string[] SubtitleTypes { get; } = "srt ass idx sup ttxt ssa smi".Split(' '); public static string[] SubtitleTypes { get; } = "srt ass idx sup ttxt ssa smi".Split(' ');
public static string[] UrlWhitelist { get; set; } = { "tube", "vimeo", "ard", "zdf" }; public static string[] UrlWhitelist { get; set; } = { "tube", "vimeo", "ard", "zdf" };
public static bool RememberHeight { get; set; } = true; public static bool RememberHeight { get; set; } = true;
public static bool RememberPosition { get; set; } public static bool RememberPosition { get; set; }
public static bool DebugMode { get; set; } = false; public static bool DebugMode { get; set; }
public static int StartThreshold { get; set; } = 1500;
public static bool IsDarkMode { public static bool IsDarkMode {
get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always"; get => (DarkMode == "system" && Sys.IsDarkTheme) || DarkMode == "always";
@@ -38,7 +43,7 @@ namespace mpvnet
public static void Init() public static void Init()
{ {
string dummy = mp.ConfFolder; string dummy = mp.ConfigFolder;
var dummy2 = mp.Conf; var dummy2 = mp.Conf;
foreach (var i in Conf) foreach (var i in Conf)
@@ -48,12 +53,10 @@ namespace mpvnet
{ {
try try
{ {
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\mpvnet-debug.log"; string filePath = mp.ConfigFolder + "\\mpvnet-debug.log";
if (File.Exists(filePath)) File.Delete(filePath); if (File.Exists(filePath)) File.Delete(filePath);
Trace.Listeners.Clear();
Trace.Listeners.Add(new TextWriterTraceListener(filePath)); Trace.Listeners.Add(new TextWriterTraceListener(filePath));
foreach (Screen screen in Screen.AllScreens) Trace.AutoFlush = true;
Trace.WriteLine(screen);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -62,11 +65,6 @@ namespace mpvnet
} }
} }
public static void Exit()
{
if (Trace.Listeners.Count > 0) Trace.Listeners[0].Close();
}
static Dictionary<string, string> _Conf; static Dictionary<string, string> _Conf;
public static Dictionary<string, string> Conf { public static Dictionary<string, string> Conf {
@@ -93,9 +91,15 @@ namespace mpvnet
case "process-instance": ProcessInstance = value; break; case "process-instance": ProcessInstance = value; break;
case "dark-mode": DarkMode = value; break; case "dark-mode": DarkMode = value; break;
case "debug-mode": DebugMode = value == "yes"; break; case "debug-mode": DebugMode = value == "yes"; break;
case "dark-color": DarkColor = value.Trim('\'', '"'); break;
case "light-color": LightColor = value.Trim('\'', '"'); break;
case "url-whitelist": case "url-whitelist":
UrlWhitelist = value.Split(' ', ',', ';'); UrlWhitelist = value.Split(' ', ',', ';');
break; break;
case "start-threshold":
int.TryParse(value, out int result);
StartThreshold = result;
break;
} }
} }
@@ -189,6 +193,8 @@ namespace mpvnet
RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "video"); RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "video");
if (App.AudioTypes.Contains(ext)) if (App.AudioTypes.Contains(ext))
RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "audio"); RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "audio");
if (App.ImageTypes.Contains(ext))
RegHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "image");
RegHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open", null, "Play with " + Application.ProductName); RegHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open", null, "Play with " + Application.ProductName);
RegHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\""); RegHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\"");
RegHelp.SetObject(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext); RegHelp.SetObject(@"HKLM\SOFTWARE\Clients\Media\mpv.net\Capabilities\FileAssociations", "." + ext, ExeFilenameNoExt + "." + ext);

View File

@@ -15,12 +15,16 @@ namespace mpvnet
{ {
try try
{ {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray(); string[] args = Environment.GetCommandLineArgs().Skip(1).ToArray();
if (args.Length == 2 && args[0] == "--reg-file-assoc") if (args.Length == 2 && args[0] == "--reg-file-assoc")
{ {
if (args[1] == "audio") FileAssociation.Register(App.AudioTypes); if (args[1] == "audio") FileAssociation.Register(App.AudioTypes);
if (args[1] == "video") FileAssociation.Register(App.VideoTypes); if (args[1] == "video") FileAssociation.Register(App.VideoTypes);
if (args[1] == "image") FileAssociation.Register(App.ImageTypes);
if (args[1] == "unreg") FileAssociation.Unregister(); if (args[1] == "unreg") FileAssociation.Unregister();
return; return;
} }
@@ -60,8 +64,6 @@ namespace mpvnet
return; return;
} }
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm()); Application.Run(new MainForm());
mutex.Dispose(); mutex.Dispose();
} }

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 // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.7.0.0")] [assembly: AssemblyVersion("4.7.7.0")]
[assembly: AssemblyFileVersion("4.7.0.0")] [assembly: AssemblyFileVersion("4.7.7.0")]

View File

@@ -131,6 +131,8 @@
KP3 script-message rate-file 3 #menu: Extensions > Rating > 3stars KP3 script-message rate-file 3 #menu: Extensions > Rating > 3stars
KP4 script-message rate-file 4 #menu: Extensions > Rating > 4stars KP4 script-message rate-file 4 #menu: Extensions > Rating > 4stars
KP5 script-message rate-file 5 #menu: Extensions > Rating > 5stars KP5 script-message rate-file 5 #menu: Extensions > Rating > 5stars
_ ignore #menu: Extensions > Rating > -
_ script-message rate-file about #menu: Extensions > Rating > About
Ctrl+t set ontop yes #menu: View > On Top > Enable Ctrl+t set ontop yes #menu: View > On Top > Enable
Ctrl+T set ontop no #menu: View > On Top > Disable Ctrl+T set ontop no #menu: View > On Top > Disable
@@ -166,23 +168,26 @@
Esc quit #menu: Exit Esc quit #menu: Exit
Q quit-watch-later #menu: Exit Watch Later Q quit-watch-later #menu: Exit Watch Later
> playlist-next Power quit
< playlist-prev Play cycle pause
Power quit Pause cycle pause
Play cycle pause PlayPause cycle pause
Pause cycle pause MBTN_Mid cycle pause
PlayPause cycle pause Stop stop
Stop stop Forward seek 60
Forward seek 60 Rewind seek -60
Rewind seek -60 Mute cycle mute
Mute cycle mute Volume_Up add volume 10
Volume_Up add volume 10 Volume_Down add volume -10
Volume_Down add volume -10 Wheel_Up add volume 10
Wheel_Up add volume 10 Wheel_Down add volume -10
Wheel_Down add volume -10 Prev playlist-prev
Prev playlist-prev Next playlist-next
Next playlist-next MBTN_Forward playlist-next
MBTN_Back playlist-prev
> playlist-next
< playlist-prev
Ctrl+Wheel_Up no-osd seek 7 Ctrl+Wheel_Up no-osd seek 7
Ctrl+Wheel_Down no-osd seek -7 Ctrl+Wheel_Down no-osd seek -7
MBTN_LEFT_DBL cycle fullscreen MBTN_Left_DBL cycle fullscreen
KP_ENTER cycle fullscreen KP_Enter cycle fullscreen

View File

@@ -250,9 +250,18 @@ help = "Store screenshots in this directory. This path is joined with the filena
[[settings]] [[settings]]
name = "autofit" name = "autofit"
default = "50%"
filter = "Screen" filter = "Screen"
help = "Set the initial window size in percent. Please note that this setting is only partly implemented in mpv.net, accepted are only integer values with percent sign added. Default: 50%" help = "<int> Initial window height in percent. Default: 50%"
[[settings]]
name = "autofit-smaller"
filter = "Screen"
help = "<int> Minimum window height in percent. Default: 40%"
[[settings]]
name = "autofit-larger"
filter = "Screen"
help = "<int> Maximum window height in percent. Default: 75%"
[[settings]] [[settings]]
name = "keep-open-pause" name = "keep-open-pause"
@@ -274,7 +283,7 @@ options = [{ name = "yes", help = "Don't terminate if the current file is the
[[settings]] [[settings]]
name = "loop-file" name = "loop-file"
filter = "Playback" filter = "Playback"
help = "Loop a single file N times. inf means forever, no means normal playback.\n\nThe difference to loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file. loop is an alias for this option." help = "<N|inf|no> Loop a single file N times. inf means forever, no means normal playback.\n\nThe difference to loop-playlist is that this doesn't loop the playlist, just the file itself. If the playlist contains only a single file, the difference between the two option is that this option performs a seek on loop, instead of reloading the file. loop is an alias for this option."
[[settings]] [[settings]]
name = "save-position-on-quit" name = "save-position-on-quit"

View File

@@ -2,22 +2,34 @@
name = "dark-mode" name = "dark-mode"
default = "always" default = "always"
filter = "General" filter = "General"
help = "Enables a dark theme." help = "Enables a dark theme. (mpv.net specific setting)"
options = [{ name = "always" }, options = [{ name = "always" },
{ name = "system" , help = "Available on Windows 10 or higher" }, { name = "system" , help = "Available on Windows 10 or higher" },
{ name = "never" }] { name = "never" }]
[[settings]]
name = "dark-color"
type = "color"
filter = "General"
help = "Theme color used in dark-mode. Leave empty to use OS theme. (mpv.net specific setting)"
[[settings]]
name = "light-color"
type = "color"
filter = "General"
help = "Theme color used when dark-mode is disabled. Leave empty to use OS theme. (mpv.net specific setting)"
[[settings]] [[settings]]
name = "url-whitelist" name = "url-whitelist"
filter = "General" filter = "General"
type = "string" type = "string"
help = "mpv.net specific whitelist setting to monitor the clipboard for URLs to play.\n\nDefault: tube vimeo ard zdf" help = "Whitelist setting to monitor the clipboard for URLs to play. (mpv.net specific setting)\n\nDefault: tube vimeo ard zdf"
[[settings]] [[settings]]
name = "process-instance" name = "process-instance"
default = "single" default = "single"
filter = "General" filter = "General"
help = "mpv.net specific setting that defines if more then one mpv.net process is allowed.\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." help = "Defines if more then one mpv.net process is allowed. (mpv.net specific setting)\n\nTip: Whenever the control key is pressed when files or URLs are opened, the playlist is not cleared but the files or URLs are appended to the playlist. This not only works on process startup but in all mpv.net features that open files."
options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" }, options = [{ name = "multi", help = "Create a new process everytime the shell starts mpv.net" },
{ name = "single", help = "Force a single process everytime the shell starts mpv.net" }, { name = "single", help = "Force a single process everytime the shell starts mpv.net" },
{ name = "queue", help = "Force a single process and add files to playlist" }] { name = "queue", help = "Force a single process and add files to playlist" }]
@@ -26,7 +38,7 @@ options = [{ name = "multi", help = "Create a new process everytime the shell s
name = "debug-mode" name = "debug-mode"
default = "no" default = "no"
filter = "General" filter = "General"
help = "mpv.net specific setting that writes debug info to a file located on the desktop." help = "Enable this only when a developer asks for it. (mpv.net specific setting)"
options = [{ name = "yes" }, options = [{ name = "yes" },
{ name = "no" }] { name = "no" }]
@@ -34,14 +46,19 @@ options = [{ name = "yes" },
name = "start-size" name = "start-size"
default = "previous" default = "previous"
filter = "Screen" filter = "Screen"
help = "mpv.net specific setting to remember the window height in the current session, otherwise the video's native resolution is used." help = "Setting to remember the window height in the current session, otherwise the video's native resolution is used. (mpv.net specific setting)"
options = [{ name = "video", help = "Window size is set to native video resolution" }, options = [{ name = "video", help = "Window size is set to native video resolution" },
{ name = "previous", help = "Window size is remembered but only from the current session" }] { name = "previous", help = "Window size is remembered but only from the current session" }]
[[settings]]
name = "start-threshold"
filter = "Screen"
help = "Threshold in milliseconds to wait for libmpv returning the video resolution before the window is shown, otherwise default dimensions are used as defined by autofit and start-size. (mpv.net specific setting) Default: 1500"
[[settings]] [[settings]]
name = "remember-position" name = "remember-position"
default = "no" default = "no"
filter = "Screen" filter = "Screen"
help = "mpv.net specific setting to save the window position on exit." help = "Setting to save the window position on exit. (mpv.net specific setting)"
options = [{ name = "yes" }, options = [{ name = "yes" },
{ name = "no" }] { name = "no" }]

View File

@@ -1,5 +1,6 @@
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
namespace mpvnet namespace mpvnet
{ {
@@ -9,7 +10,6 @@ namespace mpvnet
{ {
InitializeComponent(); InitializeComponent();
Version.Text = $"Version {System.Windows.Forms.Application.ProductVersion}"; Version.Text = $"Version {System.Windows.Forms.Application.ProductVersion}";
Foreground = WPF.WPF.ThemeBrush;
} }
protected override void OnPreviewKeyDown(KeyEventArgs e) => Close(); protected override void OnPreviewKeyDown(KeyEventArgs e) => Close();

View File

@@ -141,8 +141,12 @@ namespace mpvnet
{ {
Everything_GetResultFullPathName(i, buf, bufsize); Everything_GetResultFullPathName(i, buf, bufsize);
string ext = Path.GetExtension(buf.ToString()).TrimStart('.').ToLower(); string ext = Path.GetExtension(buf.ToString()).TrimStart('.').ToLower();
if (App.AudioTypes.Contains(ext) || App.VideoTypes.Contains(ext))
if (App.AudioTypes.Contains(ext) || App.VideoTypes.Contains(ext) ||
App.ImageTypes.Contains(ext))
items.Add(buf.ToString()); items.Add(buf.ToString());
if (items.Count > 100) break; if (items.Count > 100) break;
} }
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop; using System.Windows.Interop;
@@ -61,59 +60,59 @@ namespace mpvnet
case WF.Keys.NumPad9: case WF.Keys.NumPad9:
text = "KP" + e.KeyCode.ToString()[6].ToString(); break; text = "KP" + e.KeyCode.ToString()[6].ToString(); break;
case WF.Keys.Space: case WF.Keys.Space:
text = "Space"; break; text = "SPACE"; break;
case WF.Keys.Enter: case WF.Keys.Enter:
text = "Enter"; break; text = "ENTER"; break;
case WF.Keys.Tab: case WF.Keys.Tab:
text = "Tab"; break; text = "TAB"; break;
case WF.Keys.Back: case WF.Keys.Back:
text = "BS"; break; text = "BS"; break;
case WF.Keys.Delete: case WF.Keys.Delete:
text = "Del"; break; text = "DEL"; break;
case WF.Keys.Insert: case WF.Keys.Insert:
text = "Ins"; break; text = "INS"; break;
case WF.Keys.Home: case WF.Keys.Home:
text = "Home"; break; text = "HOME"; break;
case WF.Keys.End: case WF.Keys.End:
text = "End"; break; text = "END"; break;
case WF.Keys.PageUp: case WF.Keys.PageUp:
text = "PGUP"; break; text = "PGUP"; break;
case WF.Keys.PageDown: case WF.Keys.PageDown:
text = "PGDWN"; break; text = "PGDWN"; break;
case WF.Keys.Escape: case WF.Keys.Escape:
text = "Esc"; break; text = "ESC"; break;
case WF.Keys.PrintScreen: case WF.Keys.PrintScreen:
text = "Print"; break; text = "PRINT"; break;
case WF.Keys.Play: case WF.Keys.Play:
text = "Play"; break; text = "PLAY"; break;
case WF.Keys.Pause: case WF.Keys.Pause:
text = "Pause"; break; text = "PAUSE"; break;
case WF.Keys.MediaPlayPause: case WF.Keys.MediaPlayPause:
text = "PlayPause"; break; text = "PLAYPAUSE"; break;
case WF.Keys.MediaStop: case WF.Keys.MediaStop:
text = "Stop"; break; text = "STOP"; break;
case WF.Keys.MediaNextTrack: case WF.Keys.MediaNextTrack:
text = "Next"; break; text = "NEXT"; break;
case WF.Keys.MediaPreviousTrack: case WF.Keys.MediaPreviousTrack:
text = "Prev"; break; text = "PREV"; break;
case WF.Keys.VolumeUp: case WF.Keys.VolumeUp:
text = "Volume_Up"; break; text = "VOLUME_UP"; break;
case WF.Keys.VolumeDown: case WF.Keys.VolumeDown:
text = "Volume_Down"; break; text = "VOLUME_DOWN"; break;
case WF.Keys.VolumeMute: case WF.Keys.VolumeMute:
text = "Mute"; break; text = "MUTE"; break;
case WF.Keys.BrowserHome: case WF.Keys.BrowserHome:
text = "Homepage"; break; text = "HOMEPAGE"; break;
case WF.Keys.LaunchMail: case WF.Keys.LaunchMail:
text = "Mail"; break; text = "MAIL"; break;
case WF.Keys.BrowserFavorites: case WF.Keys.BrowserFavorites:
text = "Favorites"; break; text = "FAVORITES"; break;
case WF.Keys.BrowserSearch: case WF.Keys.BrowserSearch:
text = "Search"; break; text = "SEARCH"; break;
case WF.Keys.Sleep: case WF.Keys.Sleep:
text = "Sleep"; break; text = "SLEEP"; break;
case WF.Keys.Cancel: case WF.Keys.Cancel:
text = "Cancel"; break; text = "CANCEL"; break;
} }
bool shiftWasHandled = false; bool shiftWasHandled = false;
@@ -138,11 +137,14 @@ namespace mpvnet
SetKey(text); SetKey(text);
} }
DateTime LastKeyUp;
void SetKey(string key) void SetKey(string key)
{ {
NewKey = key; NewKey = key;
MenuTextBlock.Text = InputItem.Path; MenuTextBlock.Text = InputItem.Path;
KeyTextBlock.Text = key; KeyTextBlock.Text = key;
LastKeyUp = DateTime.Now;
} }
[DllImport("user32.dll")] [DllImport("user32.dll")]
@@ -187,49 +189,66 @@ namespace mpvnet
OnKeyUp(new WF.KeyEventArgs((WF.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys)); OnKeyUp(new WF.KeyEventArgs((WF.Keys)(unchecked((int)(long)m.WParam)) | ModifierKeys));
else if (m.Msg == WM_APPCOMMAND) else if (m.Msg == WM_APPCOMMAND)
{ {
switch ((AppCommand)(m.LParam.ToInt32() >> 16)) var value = (AppCommand)(m.LParam.ToInt64() >> 16 & ~0xf000);
switch (value)
{ {
case AppCommand.MEDIA_CHANNEL_DOWN: case AppCommand.APPCOMMAND_MEDIA_CHANNEL_DOWN:
SetKey("Channel_Down"); SetKey("CHANNEL_DOWN");
break; break;
case AppCommand.MEDIA_CHANNEL_UP: case AppCommand.APPCOMMAND_MEDIA_CHANNEL_UP:
SetKey("Channel_Up"); SetKey("CHANNEL_UP");
break; break;
case AppCommand.MEDIA_FAST_FORWARD: case AppCommand.APPCOMMAND_MEDIA_FAST_FORWARD:
SetKey("Forward"); SetKey("FORWARD");
break; break;
case AppCommand.MEDIA_REWIND: case AppCommand.APPCOMMAND_MEDIA_REWIND:
SetKey("Rewind"); SetKey("REWIND");
break; break;
case AppCommand.MEDIA_PAUSE: case AppCommand.APPCOMMAND_MEDIA_PAUSE:
SetKey("Pause"); SetKey("PAUSE");
break; break;
case AppCommand.MEDIA_PLAY: case AppCommand.APPCOMMAND_MEDIA_PLAY:
SetKey("Play"); SetKey("PLAY");
break; break;
case AppCommand.MEDIA_PLAY_PAUSE: case AppCommand.APPCOMMAND_MEDIA_PLAY_PAUSE:
SetKey("PlayPause"); SetKey("PLAYPAUSE");
break; break;
case AppCommand.MEDIA_NEXTTRACK: case AppCommand.APPCOMMAND_MEDIA_NEXTTRACK:
SetKey("Next"); SetKey("NEXT");
break; break;
case AppCommand.MEDIA_PREVIOUSTRACK: case AppCommand.APPCOMMAND_MEDIA_PREVIOUSTRACK:
SetKey("Prev"); SetKey("PREV");
break; break;
case AppCommand.MEDIA_RECORD: case AppCommand.APPCOMMAND_MEDIA_RECORD:
SetKey("Record"); SetKey("RECORD");
break; break;
case AppCommand.MEDIA_STOP: case AppCommand.APPCOMMAND_MEDIA_STOP:
SetKey("Stop"); SetKey("STOP");
break; break;
case AppCommand.VolumeUp: case AppCommand.APPCOMMAND_VOLUME_UP:
SetKey("Volume_Up"); SetKey("VOLUME_UP");
break; break;
case AppCommand.VolumeDown: case AppCommand.APPCOMMAND_VOLUME_DOWN:
SetKey("Volume_Down"); SetKey("VOLUME_DOWN");
break; break;
case AppCommand.VolumeMute: case AppCommand.APPCOMMAND_VOLUME_MUTE:
SetKey("Mute"); SetKey("MUTE");
break;
case AppCommand.APPCOMMAND_BROWSER_HOME:
SetKey("HOMEPAGE");
break;
case AppCommand.APPCOMMAND_LAUNCH_MAIL:
SetKey("MAIL");
break;
case AppCommand.APPCOMMAND_BROWSER_FAVORITES:
SetKey("FAVORITES");
break;
case AppCommand.APPCOMMAND_BROWSER_SEARCH:
SetKey("SEARCH");
break;
case AppCommand.APPCOMMAND_PRINT:
SetKey("PRINT");
break; break;
} }
} }
@@ -237,20 +256,58 @@ namespace mpvnet
internal enum AppCommand internal enum AppCommand
{ {
MEDIA_CHANNEL_DOWN = 52, APPCOMMAND_BASS_BOOST = 20,
MEDIA_CHANNEL_UP = 51, APPCOMMAND_BASS_DOWN = 19,
MEDIA_FAST_FORWARD = 49, APPCOMMAND_BASS_UP = 21,
MEDIA_NEXTTRACK = 11, APPCOMMAND_BROWSER_BACKWARD = 1,
MEDIA_PAUSE = 47, APPCOMMAND_BROWSER_FAVORITES = 6,
MEDIA_PLAY = 46, APPCOMMAND_BROWSER_FORWARD = 2,
MEDIA_PLAY_PAUSE = 14, APPCOMMAND_BROWSER_HOME = 7,
MEDIA_PREVIOUSTRACK = 12, APPCOMMAND_BROWSER_REFRESH = 3,
MEDIA_RECORD = 48, APPCOMMAND_BROWSER_SEARCH = 5,
MEDIA_REWIND = 50, APPCOMMAND_BROWSER_STOP = 4,
MEDIA_STOP = 13, APPCOMMAND_CLOSE = 31,
VolumeMute = 8, APPCOMMAND_COPY = 36,
VolumeDown = 9, APPCOMMAND_CORRECTION_LIST = 45,
VolumeUp = 10 APPCOMMAND_CUT = 37,
APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43,
APPCOMMAND_FIND = 28,
APPCOMMAND_FORWARD_MAIL = 40,
APPCOMMAND_HELP = 27,
APPCOMMAND_LAUNCH_APP1 = 17,
APPCOMMAND_LAUNCH_APP2 = 18,
APPCOMMAND_LAUNCH_MAIL = 15,
APPCOMMAND_LAUNCH_MEDIA_SELECT = 16,
APPCOMMAND_MEDIA_CHANNEL_DOWN = 52,
APPCOMMAND_MEDIA_CHANNEL_UP = 51,
APPCOMMAND_MEDIA_FAST_FORWARD = 49,
APPCOMMAND_MEDIA_NEXTTRACK = 11,
APPCOMMAND_MEDIA_PAUSE = 47,
APPCOMMAND_MEDIA_PLAY = 46,
APPCOMMAND_MEDIA_PLAY_PAUSE = 14,
APPCOMMAND_MEDIA_PREVIOUSTRACK = 12,
APPCOMMAND_MEDIA_RECORD = 48,
APPCOMMAND_MEDIA_REWIND = 50,
APPCOMMAND_MEDIA_STOP = 13,
APPCOMMAND_MIC_ON_OFF_TOGGLE = 44,
APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25,
APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24,
APPCOMMAND_MICROPHONE_VOLUME_UP = 26,
APPCOMMAND_NEW = 29,
APPCOMMAND_OPEN = 30,
APPCOMMAND_PASTE = 38,
APPCOMMAND_PRINT = 33,
APPCOMMAND_REDO = 35,
APPCOMMAND_REPLY_TO_MAIL = 39,
APPCOMMAND_SAVE = 32,
APPCOMMAND_SEND_MAIL = 41,
APPCOMMAND_SPELL_CHECK = 42,
APPCOMMAND_TREBLE_DOWN = 22,
APPCOMMAND_TREBLE_UP = 23,
APPCOMMAND_UNDO = 34,
APPCOMMAND_VOLUME_DOWN = 9,
APPCOMMAND_VOLUME_MUTE = 8,
APPCOMMAND_VOLUME_UP = 10
} }
[DllImport("user32.dll", CharSet = CharSet.Auto)] [DllImport("user32.dll", CharSet = CharSet.Auto)]

View File

@@ -1,7 +1,11 @@
using System; using System;
using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Microsoft.Win32;
using mpvnet;
namespace WPF namespace WPF
{ {
public class WPF public class WPF
@@ -22,12 +26,43 @@ namespace WPF
} }
} }
public static Brush ThemeBrush { public static Brush ThemeBrush { get; } = new SolidColorBrush(ThemeColor);
static bool WasThemeColorSet;
static Color _ThemeColor;
public static Color ThemeColor {
get { get {
if (Environment.OSVersion.Version.Major < 10) if (!WasThemeColorSet)
return new SolidColorBrush(Colors.DarkSlateGray); {
else Color? color = null;
return SystemParameters.WindowGlassBrush;
try {
if (App.IsDarkMode && !string.IsNullOrEmpty(App.DarkColor))
color = (Color)ColorConverter.ConvertFromString(App.DarkColor);
else if (!App.IsDarkMode && !string.IsNullOrEmpty(App.LightColor))
color = (Color)ColorConverter.ConvertFromString(App.LightColor);
} catch { }
if (!color.HasValue)
{
if (Environment.OSVersion.Version.Major < 10)
{
int argb = Convert.ToInt32(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0));
var wfc = System.Drawing.Color.FromArgb(argb);
color = Color.FromArgb(wfc.A, wfc.R, wfc.G, wfc.B);
}
else
color = SystemParameters.WindowGlassColor;
}
if (App.IsDarkMode && color == Colors.Black) color = Colors.Orange;
if (!App.IsDarkMode && color == Colors.White) color = Colors.Orange;
_ThemeColor = color.Value;
WasThemeColorSet = true;
}
return _ThemeColor;
} }
} }
} }

View File

@@ -45,13 +45,12 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F); this.AutoScaleDimensions = new System.Drawing.SizeF(288F, 288F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.Black; this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(1777, 1109); this.ClientSize = new System.Drawing.Size(542, 0);
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.Name = "MainForm"; this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "mpv.net";
this.ResumeLayout(false); this.ResumeLayout(false);
} }

View File

@@ -8,6 +8,7 @@ using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace mpvnet namespace mpvnet
@@ -30,14 +31,13 @@ namespace mpvnet
try try
{ {
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
Msg.SupportURL = "https://github.com/stax76/mpv.net#support";
Instance = this; Instance = this;
WPF.WPF.Init();
System.Windows.Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
Hwnd = Handle; Hwnd = Handle;
Text += " " + Application.ProductVersion; mp.Init();
AppDomain.CurrentDomain.UnhandledException += (sender, e) => Msg.ShowError(e.ExceptionObject.ToString());
Application.ThreadException += (sender, e) => Msg.ShowException(e.Exception);
Msg.SupportURL = "https://github.com/stax76/mpv.net#support";
Text = "mpv.net " + Application.ProductVersion;
object recent = RegHelp.GetObject(App.RegPath, "Recent"); object recent = RegHelp.GetObject(App.RegPath, "Recent");
@@ -46,6 +46,10 @@ namespace mpvnet
else else
RecentFiles = new List<string>(); RecentFiles = new List<string>();
ContextMenu = new ContextMenuStripEx(components);
ContextMenu.Opened += ContextMenu_Opened;
ContextMenu.Opening += ContextMenu_Opening;
App.ProcessCommandLineEarly(); App.ProcessCommandLineEarly();
if (mp.Screen == -1) mp.Screen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen); if (mp.Screen == -1) mp.Screen = Array.IndexOf(Screen.AllScreens, Screen.PrimaryScreen);
@@ -71,8 +75,8 @@ namespace mpvnet
mp.VideoSizeChanged += VideoSizeChanged; mp.VideoSizeChanged += VideoSizeChanged;
mp.FileLoaded += FileLoaded; mp.FileLoaded += FileLoaded;
mp.Idle += Idle; mp.Idle += Idle;
Task.Run(() => mp.Init()); mp.VideoSizeAutoResetEvent.WaitOne(App.StartThreshold);
mp.VideoSizeAutoResetEvent.WaitOne(1000); if (Height < FontHeight * 4) SetFormPosAndSize();
mp.observe_property_bool("fullscreen", PropChangeFullscreen); mp.observe_property_bool("fullscreen", PropChangeFullscreen);
mp.observe_property_bool("ontop", PropChangeOnTop); mp.observe_property_bool("ontop", PropChangeOnTop);
mp.observe_property_bool("border", PropChangeBorder); mp.observe_property_bool("border", PropChangeBorder);
@@ -221,6 +225,8 @@ namespace mpvnet
return null; return null;
} }
bool WasInitialSizeSet;
void SetFormPosAndSize() void SetFormPosAndSize()
{ {
if (mp.Fullscreen) if (mp.Fullscreen)
@@ -229,25 +235,55 @@ namespace mpvnet
return; return;
} }
Size size = mp.VideoSize;
Screen screen = Screen.FromControl(this); Screen screen = Screen.FromControl(this);
int fixedHeight = Convert.ToInt32(screen.Bounds.Height * mp.Autofit); int autoFitHeight = Convert.ToInt32(screen.WorkingArea.Height * mp.Autofit);
if (size.Height == 0 || size.Width == 0 || size.Width / (float)size.Height < 1.3) if (mp.VideoSize.Height == 0 || mp.VideoSize.Width == 0 ||
{ mp.VideoSize.Width / (float)mp.VideoSize.Height < 1.3)
size.Height = fixedHeight;
size.Width = (int)(fixedHeight * 1.7); mp.VideoSize = new Size((int)(autoFitHeight * (16 / 9.0)), autoFitHeight);
}
Size size = mp.VideoSize;
int height = size.Height; int height = size.Height;
if (App.RememberHeight) if (App.RememberHeight)
height = ClientSize.Height; {
if (WasInitialSizeSet)
if (height > screen.Bounds.Height * 0.9) height = ClientSize.Height;
height = fixedHeight; else
{
height = autoFitHeight;
WasInitialSizeSet = true;
}
}
int width = Convert.ToInt32(height * size.Width / (double)size.Height); int width = Convert.ToInt32(height * size.Width / (double)size.Height);
if (height > screen.WorkingArea.Height * 0.9)
{
height = Convert.ToInt32(screen.WorkingArea.Height * 0.9);
width = Convert.ToInt32(height * size.Width / (double)size.Height);
}
if (width > screen.WorkingArea.Width * 0.9)
{
width = Convert.ToInt32(screen.WorkingArea.Width * 0.9);
height = Convert.ToInt32(width * size.Height / (double)size.Width);
}
if (height < screen.WorkingArea.Height * mp.AutofitSmaller)
{
height = Convert.ToInt32(screen.WorkingArea.Height * mp.AutofitSmaller);
width = Convert.ToInt32(height * size.Width / (double)size.Height);
}
if (height > screen.WorkingArea.Height * mp.AutofitLarger)
{
height = Convert.ToInt32(screen.WorkingArea.Height * mp.AutofitLarger);
width = Convert.ToInt32(height * size.Width / (double)size.Height);
}
Point middlePos = new Point(Left + Width / 2, Top + Height / 2); Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height)); var rect = new Native.RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
NativeHelp.AddWindowBorders(Handle, ref rect); NativeHelp.AddWindowBorders(Handle, ref rect);
@@ -340,16 +376,6 @@ namespace mpvnet
if (RecentFiles.Count > 15) RecentFiles.RemoveAt(15); if (RecentFiles.Count > 15) RecentFiles.RemoveAt(15);
} }
void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
Msg.ShowException(e.Exception);
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Msg.ShowError(e.ExceptionObject.ToString());
}
protected override CreateParams CreateParams { protected override CreateParams CreateParams {
get { get {
CreateParams cp = base.CreateParams; CreateParams cp = base.CreateParams;
@@ -360,7 +386,7 @@ namespace mpvnet
protected override void WndProc(ref Message m) protected override void WndProc(ref Message m)
{ {
//System.Diagnostics.Debug.WriteLine(m); //Debug.WriteLine(m);
switch (m.Msg) switch (m.Msg)
{ {
@@ -368,13 +394,14 @@ namespace mpvnet
case 0x0202: // WM_LBUTTONUP case 0x0202: // WM_LBUTTONUP
case 0x0207: // WM_MBUTTONDOWN case 0x0207: // WM_MBUTTONDOWN
case 0x0208: // WM_MBUTTONUP case 0x0208: // WM_MBUTTONUP
case 0x020b: // WM_XBUTTONDOWN
case 0x020c: // WM_XBUTTONUP
case 0x020A: // WM_MOUSEWHEEL case 0x020A: // WM_MOUSEWHEEL
case 0x020C: // WM_XBUTTONUP
case 0x020B: // WM_XBUTTONDOWN
case 0x0100: // WM_KEYDOWN case 0x0100: // WM_KEYDOWN
case 0x0101: // WM_KEYUP case 0x0101: // WM_KEYUP
case 0x0104: // WM_SYSKEYDOWN case 0x0104: // WM_SYSKEYDOWN
case 0x0105: // WM_SYSKEYUP case 0x0105: // WM_SYSKEYUP
case 0x319: // WM_APPCOMMAND
if (mp.WindowHandle != IntPtr.Zero) if (mp.WindowHandle != IntPtr.Zero)
Native.SendMessage(mp.WindowHandle, m.Msg, m.WParam, m.LParam); Native.SendMessage(mp.WindowHandle, m.Msg, m.WParam, m.LParam);
break; break;
@@ -388,10 +415,6 @@ namespace mpvnet
case 0x2a3: // WM_MOUSELEAVE case 0x2a3: // WM_MOUSELEAVE
mp.command_string("mouse 1 1"); // osc won't always auto hide mp.command_string("mouse 1 1"); // osc won't always auto hide
break; break;
case 0x319: // WM_APPCOMMAND
if (mp.WindowHandle != IntPtr.Zero)
Native.PostMessage(mp.WindowHandle, m.Msg, m.WParam, m.LParam);
break;
case 0x203: // Native.WM.LBUTTONDBLCLK case 0x203: // Native.WM.LBUTTONDBLCLK
{ {
Point pos = PointToClient(Cursor.Position); Point pos = PointToClient(Cursor.Position);
@@ -408,7 +431,9 @@ namespace mpvnet
var r = rc; var r = rc;
NativeHelp.SubtractWindowBorders(Handle, ref r); NativeHelp.SubtractWindowBorders(Handle, ref r);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top; int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
float aspect = mp.VideoSize.Width / (float)mp.VideoSize.Height; Size s = mp.VideoSize;
if (s == Size.Empty) s = new Size(16, 9);
float aspect = s.Width / (float)s.Height;
int d_w = Convert.ToInt32(c_h * aspect - c_w); int d_w = Convert.ToInt32(c_h * aspect - c_w);
int d_h = Convert.ToInt32(c_w / aspect - c_h); int d_h = Convert.ToInt32(c_w / aspect - c_h);
int[] d_corners = { d_w, d_h, -d_w, -d_h }; int[] d_corners = { d_w, d_h, -d_w, -d_h };
@@ -499,14 +524,16 @@ namespace mpvnet
protected override void OnShown(EventArgs e) protected override void OnShown(EventArgs e)
{ {
base.OnShown(e); base.OnShown(e);
if (App.IsDarkMode) ToolStripRendererEx.ColorTheme = Color.Black; var wpfColor = WPF.WPF.ThemeColor;
ContextMenu = new ContextMenuStripEx(components); Color color = Color.FromArgb(wpfColor.A, wpfColor.R, wpfColor.G, wpfColor.B);
ContextMenu.Opened += ContextMenu_Opened; ToolStripRendererEx.InitColors(color, App.IsDarkMode);
ContextMenu.Opening += ContextMenu_Opening;
BuildMenu(); BuildMenu();
ContextMenuStrip = ContextMenu; ContextMenuStrip = ContextMenu;
WPF.WPF.Init();
System.Windows.Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
IgnoreDpiChanged = false; IgnoreDpiChanged = false;
CheckClipboardForURL(); CheckClipboardForURL();
Cursor.Position = new Point(Cursor.Position.X + 1, Cursor.Position.Y);
} }
protected override void OnActivated(EventArgs e) protected override void OnActivated(EventArgs e)
@@ -534,7 +561,6 @@ namespace mpvnet
} }
RegHelp.SetObject(App.RegPath, "Recent", RecentFiles.ToArray()); RegHelp.SetObject(App.RegPath, "Recent", RecentFiles.ToArray());
App.Exit();
mp.commandv("quit"); mp.commandv("quit");
mp.ShutdownAutoResetEvent.WaitOne(3000); mp.ShutdownAutoResetEvent.WaitOne(3000);
} }

View File

@@ -131,8 +131,10 @@ public class MenuItem : ToolStripMenuItem
public class ToolStripRendererEx : ToolStripSystemRenderer public class ToolStripRendererEx : ToolStripSystemRenderer
{ {
public static bool IsDarkMode { get; set; }
public static Color ColorForeground { get; set; } = Color.Black; public static Color ColorForeground { get; set; } = Color.Black;
public static Color ColorTheme { get; set; } = Color.Empty; public static Color ColorTheme { get; set; }
public static Color ColorChecked { get; set; } public static Color ColorChecked { get; set; }
public static Color ColorBorder { get; set; } public static Color ColorBorder { get; set; }
public static Color ColorTop { get; set; } public static Color ColorTop { get; set; }
@@ -146,19 +148,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
int TextOffset; int TextOffset;
public ToolStripRendererEx() public static void InitColors(Color c, bool darkMode)
{
var argb = Convert.ToInt32(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", 0));
if (argb == 0)
argb = Color.LightBlue.ToArgb();
if (ColorTheme == Color.Empty)
InitColors(Color.FromArgb(argb));
else
InitColors(ColorTheme);
}
public static void InitColors(Color c)
{ {
ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100); ColorBorder = HSLColor.Convert(c).ToColorSetLuminosity(100);
ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(160); ColorChecked = HSLColor.Convert(c).ToColorSetLuminosity(160);
@@ -166,7 +156,7 @@ public class ToolStripRendererEx : ToolStripSystemRenderer
ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(210); ColorBackground = HSLColor.Convert(c).ToColorSetLuminosity(210);
ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240); ColorTop = HSLColor.Convert(c).ToColorSetLuminosity(240);
if (ColorTheme == Color.Black) if (darkMode)
{ {
ColorBorder = Color.White; ColorBorder = Color.White;
ColorBackground = Color.FromArgb(50, 50, 50); ColorBackground = Color.FromArgb(50, 50, 50);

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using System.Drawing.Imaging;
@@ -12,6 +13,8 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using WinForms = System.Windows.Forms;
using static mpvnet.libmpv; using static mpvnet.libmpv;
using static mpvnet.Native; using static mpvnet.Native;
@@ -65,8 +68,8 @@ namespace mpvnet
public static List<MediaTrack> MediaTracks { get; set; } = new List<MediaTrack>(); public static List<MediaTrack> MediaTracks { get; set; } = new List<MediaTrack>();
public static List<KeyValuePair<string, double>> Chapters { get; set; } = new List<KeyValuePair<string, double>>(); public static List<KeyValuePair<string, double>> Chapters { get; set; } = new List<KeyValuePair<string, double>>();
public static string InputConfPath { get; } = ConfFolder + "\\input.conf"; public static string InputConfPath { get; } = ConfigFolder + "\\input.conf";
public static string ConfPath { get; } = ConfFolder + "\\mpv.conf"; public static string ConfPath { get; } = ConfigFolder + "\\mpv.conf";
public static string Sid { get; set; } = ""; public static string Sid { get; set; } = "";
public static string Aid { get; set; } = ""; public static string Aid { get; set; } = "";
public static string Vid { get; set; } = ""; public static string Vid { get; set; } = "";
@@ -78,11 +81,14 @@ namespace mpvnet
public static int Edition { get; set; } public static int Edition { get; set; }
public static float Autofit { get; set; } = 0.5f; public static float Autofit { get; set; } = 0.5f;
public static float AutofitSmaller { get; set; } = 0.4f;
public static float AutofitLarger { get; set; } = 0.75f;
public static void Init() public static void Init()
{ {
LoadLibrary("mpv-1.dll"); LoadLibrary("mpv-1.dll");
Handle = mpv_create(); Handle = mpv_create();
set_property_string("config-dir", ConfigFolder);
set_property_string("osc", "yes"); set_property_string("osc", "yes");
set_property_string("config", "yes"); set_property_string("config", "yes");
set_property_string("wid", MainForm.Hwnd.ToString()); set_property_string("wid", MainForm.Hwnd.ToString());
@@ -101,9 +107,16 @@ namespace mpvnet
switch (name) switch (name)
{ {
case "autofit": case "autofit":
if (value.Length == 3 && value.EndsWith("%")) if (int.TryParse(value.Trim('%'), out int result))
if (int.TryParse(value.Substring(0, 2), out int result)) Autofit = result / 100f;
Autofit = result / 100f; break;
case "autofit-smaller":
if (int.TryParse(value.Trim('%'), out int result2))
AutofitSmaller = result2 / 100f;
break;
case "autofit-larger":
if (int.TryParse(value.Trim('%'), out int result3))
AutofitLarger = result3 / 100f;
break; break;
case "fs": case "fs":
case "fullscreen": Fullscreen = value == "yes"; break; case "fullscreen": Fullscreen = value == "yes"; break;
@@ -112,48 +125,62 @@ namespace mpvnet
} }
} }
static string _ConfFolder; static string _ConfigFolder;
public static string ConfFolder { public static string ConfigFolder {
get { get {
if (_ConfFolder == null) if (_ConfigFolder == null)
{ {
string portableFolder = Application.StartupPath + "\\portable_config\\"; _ConfigFolder = Application.StartupPath + "\\portable_config\\";
string appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
string startupFolder = Application.StartupPath + "\\";
if (!Directory.Exists(appdataFolder) && !Directory.Exists(portableFolder) && if (!Directory.Exists(_ConfigFolder))
Sys.IsDirectoryWritable(Application.StartupPath) && _ConfigFolder = RegHelp.GetString(App.RegPath, "ConfigFolder");
!File.Exists(startupFolder + "mpv.conf"))
if (!Directory.Exists(_ConfigFolder))
{ {
string portableFolder = Application.StartupPath + "\\portable_config\\";
string appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv.net\\";
string appdataFolderMpv = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
string startupFolder = Application.StartupPath + "\\";
using (TaskDialog<string> td = new TaskDialog<string>()) using (TaskDialog<string> td = new TaskDialog<string>())
{ {
td.MainInstruction = "Choose a settings folder."; td.MainInstruction = "Choose a settings folder.";
td.Content = "[MPV documentation about files on Windows.](https://mpv.io/manual/master/#files-on-windows)"; td.AddCommandLink(@"AppData\Roaming\mpv.net", appdataFolder, appdataFolder);
td.AddCommandLink("appdata", appdataFolder, appdataFolder); td.AddCommandLink(@"AppData\Roaming\mpv", appdataFolderMpv, appdataFolderMpv);
td.AddCommandLink("portable", portableFolder, portableFolder); td.AddCommandLink("<startup>\\portable_config", portableFolder, portableFolder);
td.AddCommandLink("startup", startupFolder, startupFolder); td.AddCommandLink("<startup>", startupFolder, startupFolder);
td.AddCommandLink("Choose custom folder", "custom");
td.AllowCancel = false; td.AllowCancel = false;
_ConfFolder = td.Show(); _ConfigFolder = td.Show();
}
if (_ConfigFolder == "custom")
{
using (var d = new WinForms.FolderBrowserDialog())
{
d.Description = "Choose a folder.";
if (d.ShowDialog() == WinForms.DialogResult.OK)
_ConfigFolder = d.SelectedPath + "\\";
else
_ConfigFolder = appdataFolder;
}
} }
} }
else if (Directory.Exists(portableFolder))
_ConfFolder = portableFolder;
else if (Directory.Exists(appdataFolder))
_ConfFolder = appdataFolder;
else if (File.Exists(Application.StartupPath + "\\mpv.conf"))
_ConfFolder = Application.StartupPath + "\\";
if (string.IsNullOrEmpty(_ConfFolder)) _ConfFolder = appdataFolder; if (!Directory.Exists(_ConfigFolder))
if (!Directory.Exists(_ConfFolder)) Directory.CreateDirectory(_ConfFolder); Directory.CreateDirectory(_ConfigFolder);
if (!File.Exists(_ConfFolder + "\\input.conf")) if (!_ConfigFolder.Contains("portable_config"))
File.WriteAllText(_ConfFolder + "\\input.conf", Properties.Resources.inputConf); RegHelp.SetObject(App.RegPath, "ConfigFolder", _ConfigFolder);
if (!File.Exists(_ConfFolder + "\\mpv.conf")) if (!File.Exists(_ConfigFolder + "\\input.conf"))
File.WriteAllText(_ConfFolder + "\\mpv.conf", Properties.Resources.mpvConf); File.WriteAllText(_ConfigFolder + "\\input.conf", Properties.Resources.inputConf);
if (!File.Exists(_ConfigFolder + "\\mpv.conf"))
File.WriteAllText(_ConfigFolder + "\\mpv.conf", Properties.Resources.mpvConf);
} }
return _ConfFolder; return _ConfigFolder;
} }
} }
@@ -179,22 +206,26 @@ namespace mpvnet
public static void LoadScripts() public static void LoadScripts()
{ {
string[] startupScripts = Directory.GetFiles(Application.StartupPath + "\\Scripts");
foreach (string scriptPath in startupScripts) if (Directory.Exists(Application.StartupPath + "\\Scripts"))
if (scriptPath.EndsWith(".lua") || scriptPath.EndsWith(".js")) {
commandv("load-script", $"{scriptPath}"); string[] startupScripts = Directory.GetFiles(Application.StartupPath + "\\Scripts");
foreach (string scriptPath in startupScripts) foreach (string scriptPath in startupScripts)
if (Path.GetExtension(scriptPath) == ".py") if (scriptPath.EndsWith(".lua") || scriptPath.EndsWith(".js"))
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath))); commandv("load-script", $"{scriptPath}");
foreach (string scriptPath in startupScripts) foreach (string scriptPath in startupScripts)
if (Path.GetExtension(scriptPath) == ".ps1") if (Path.GetExtension(scriptPath) == ".py")
PowerShellScript.Init(scriptPath); PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
if (Directory.Exists(ConfFolder + "Scripts")) foreach (string scriptPath in startupScripts)
foreach (string scriptPath in Directory.GetFiles(ConfFolder + "Scripts")) if (Path.GetExtension(scriptPath) == ".ps1")
PowerShellScript.Init(scriptPath);
}
if (Directory.Exists(ConfigFolder + "Scripts"))
foreach (string scriptPath in Directory.GetFiles(ConfigFolder + "Scripts"))
if (Path.GetExtension(scriptPath) == ".py") if (Path.GetExtension(scriptPath) == ".py")
PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath))); PythonScripts.Add(new PythonScript(File.ReadAllText(scriptPath)));
else if (Path.GetExtension(scriptPath) == ".ps1") else if (Path.GetExtension(scriptPath) == ".ps1")
@@ -211,14 +242,16 @@ namespace mpvnet
if (WindowHandle == IntPtr.Zero) if (WindowHandle == IntPtr.Zero)
WindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null); WindowHandle = FindWindowEx(MainForm.Hwnd, IntPtr.Zero, "mpv", null);
//System.Diagnostics.Debug.WriteLine(evt.event_id.ToString()); // Debug.WriteLine(evt.event_id.ToString());
try try
{ {
switch (evt.event_id) switch (evt.event_id)
{ {
case mpv_event_id.MPV_EVENT_SHUTDOWN: case mpv_event_id.MPV_EVENT_SHUTDOWN:
if (App.DebugMode) Trace.WriteLine("before Shutdown.Invoke");
Shutdown?.Invoke(); Shutdown?.Invoke();
if (App.DebugMode) Trace.WriteLine("after Shutdown.Invoke");
WriteHistory(null); WriteHistory(null);
ShutdownAutoResetEvent.Set(); ShutdownAutoResetEvent.Set();
return; return;
@@ -245,6 +278,16 @@ namespace mpvnet
case mpv_event_id.MPV_EVENT_FILE_LOADED: case mpv_event_id.MPV_EVENT_FILE_LOADED:
HideLogo(); HideLogo();
FileLoaded?.Invoke(); FileLoaded?.Invoke();
Size vidSize = new Size(get_property_int("width"), get_property_int("height"));
if (vidSize.Width == 0 || vidSize.Height == 0)
vidSize = new Size(1, 1);
if (VideoSize != vidSize)
{
VideoSize = vidSize;
VideoSizeChanged?.Invoke();
}
VideoSizeAutoResetEvent.Set();
Task.Run(new Action(() => ReadMetaData()));
WriteHistory(get_property_string("path")); WriteHistory(get_property_string("path"));
break; break;
case mpv_event_id.MPV_EVENT_TRACKS_CHANGED: case mpv_event_id.MPV_EVENT_TRACKS_CHANGED:
@@ -309,17 +352,6 @@ namespace mpvnet
break; break;
case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART: case mpv_event_id.MPV_EVENT_PLAYBACK_RESTART:
PlaybackRestart?.Invoke(); PlaybackRestart?.Invoke();
Size vidSize = new Size(get_property_int("dwidth"), get_property_int("dheight"));
if (VideoSize != vidSize && vidSize != Size.Empty)
{
VideoSize = vidSize;
VideoSizeChanged?.Invoke();
}
VideoSizeAutoResetEvent.Set();
Task.Run(new Action(() => ReadMetaData()));
break; break;
case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE: case mpv_event_id.MPV_EVENT_CHAPTER_CHANGE:
ChapterChange?.Invoke(); ChapterChange?.Invoke();
@@ -401,16 +433,14 @@ namespace mpvnet
{ {
if (Handle == IntPtr.Zero) return; if (Handle == IntPtr.Zero) return;
int err = mpv_command_string(Handle, command); int err = mpv_command_string(Handle, command);
if (err < 0 && throwException) if (err < 0 && throwException) throw new Exception($"{(mpv_error)err}\n\n" + command);
throw new Exception($"{(mpv_error)err}\r\n\r\n" + command);
} }
public static void set_property_string(string name, string value, bool throwOnException = false) public static void set_property_string(string name, string value, bool throwOnException = false)
{ {
byte[] bytes = GetUtf8Bytes(value); byte[] bytes = GetUtf8Bytes(value);
int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes); int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, ref bytes);
if (err < 0 && throwOnException) if (err < 0 && throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
throw new Exception($"{name}: {(mpv_error)err}");
} }
public static string get_property_string(string name, bool throwOnException = false) public static string get_property_string(string name, bool throwOnException = false)
@@ -418,7 +448,13 @@ namespace mpvnet
try try
{ {
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer); int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_STRING, out IntPtr lpBuffer);
if (err < 0 && throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
if (err < 0)
{
if (throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
return "";
}
string ret = StringFromNativeUtf8(lpBuffer); string ret = StringFromNativeUtf8(lpBuffer);
mpv_free(lpBuffer); mpv_free(lpBuffer);
return ret; return ret;
@@ -434,10 +470,13 @@ namespace mpvnet
{ {
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer); int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, out IntPtr lpBuffer);
if (err < 0 && throwOnException) if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}"); {
else if (throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
return lpBuffer.ToInt32(); return 0;
}
return lpBuffer.ToInt32();
} }
public static double get_property_number(string name, bool throwOnException = false) public static double get_property_number(string name, bool throwOnException = false)
@@ -445,10 +484,13 @@ namespace mpvnet
double val = 0; double val = 0;
int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val); int err = mpv_get_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_DOUBLE, ref val);
if (err < 0 && throwOnException) if (err < 0)
throw new Exception($"{name}: {(mpv_error)err}"); {
else if (throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
return val; return 0;
}
return val;
} }
public static bool get_property_bool(string name, bool throwOnException = false) public static bool get_property_bool(string name, bool throwOnException = false)
@@ -465,9 +507,7 @@ namespace mpvnet
{ {
Int64 val = value; Int64 val = value;
int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val); int err = mpv_set_property(Handle, GetUtf8Bytes(name), mpv_format.MPV_FORMAT_INT64, ref val);
if (err < 0 && throwOnException) throw new Exception($"{name}: {(mpv_error)err}");
if (err < 0 && throwOnException)
throw new Exception($"{name}: {(mpv_error)err}");
} }
public static void observe_property_int(string name, Action<int> action) public static void observe_property_int(string name, Action<int> action)
@@ -516,7 +556,11 @@ namespace mpvnet
Load(files.ToArray(), App.ProcessInstance != "queue", Control.ModifierKeys.HasFlag(Keys.Control)); Load(files.ToArray(), App.ProcessInstance != "queue", Control.ModifierKeys.HasFlag(Keys.Control));
if (files.Count == 0) VideoSizeAutoResetEvent.Set(); if (files.Count == 0 || files[0].Contains("://"))
{
VideoSizeAutoResetEvent.Set();
VideoSizeChanged?.Invoke();
}
foreach (string i in args) foreach (string i in args)
{ {
@@ -564,6 +608,7 @@ namespace mpvnet
if (string.IsNullOrEmpty(get_property_string("path"))) if (string.IsNullOrEmpty(get_property_string("path")))
set_property_int("playlist-pos", 0); set_property_int("playlist-pos", 0);
if (loadFolder && !append) Task.Run(() => LoadFolder()); // user reported race condition if (loadFolder && !append) Task.Run(() => LoadFolder()); // user reported race condition
} }
@@ -575,7 +620,8 @@ namespace mpvnet
List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList(); List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
files = files.Where((file) => files = files.Where((file) =>
App.VideoTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower()) || App.VideoTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower()) ||
App.AudioTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower())).ToList(); App.AudioTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower()) ||
App.ImageTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower())).ToList();
files.Sort(new StringLogicalComparer()); files.Sort(new StringLogicalComparer());
int index = files.IndexOf(path); int index = files.IndexOf(path);
files.Remove(path); files.Remove(path);
@@ -628,20 +674,21 @@ namespace mpvnet
static string LastHistoryPath; static string LastHistoryPath;
static DateTime LastHistoryStartDateTime; static DateTime LastHistoryStartDateTime;
static void WriteHistory(string filePath) static void WriteHistory(string path)
{ {
if (!File.Exists(path)) return;
int totalMinutes = Convert.ToInt32((DateTime.Now - LastHistoryStartDateTime).TotalMinutes); int totalMinutes = Convert.ToInt32((DateTime.Now - LastHistoryStartDateTime).TotalMinutes);
if (File.Exists(LastHistoryPath) && totalMinutes > 1) if (File.Exists(LastHistoryPath) && totalMinutes > 1)
{ {
string historyFilepath = ConfFolder + "history.txt"; string historyFilepath = ConfigFolder + "history.txt";
File.AppendAllText(historyFilepath, DateTime.Now.ToString().Substring(0, 16) + File.AppendAllText(historyFilepath, DateTime.Now.ToString().Substring(0, 16) +
" " + totalMinutes.ToString().PadLeft(3) + " " + " " + totalMinutes.ToString().PadLeft(3) + " " +
Path.GetFileNameWithoutExtension(LastHistoryPath) + "\r\n"); Path.GetFileNameWithoutExtension(LastHistoryPath) + "\r\n");
} }
LastHistoryPath = filePath; LastHistoryPath = path;
LastHistoryStartDateTime = DateTime.Now; LastHistoryStartDateTime = DateTime.Now;
} }
@@ -649,8 +696,8 @@ namespace mpvnet
{ {
if (MainForm.Instance is null) return; if (MainForm.Instance is null) return;
Rectangle cr = MainForm.Instance.ClientRectangle; Rectangle cr = MainForm.Instance.ClientRectangle;
if (cr.Width == 0 || cr.Height == 0) return;
int len = cr.Height / 5; int len = cr.Height / 5;
if (len == 0) return;
using (Bitmap b = new Bitmap(len, len)) using (Bitmap b = new Bitmap(len, len))
{ {
@@ -675,80 +722,84 @@ namespace mpvnet
lock (MediaTracks) lock (MediaTracks)
{ {
MediaTracks.Clear(); MediaTracks.Clear();
string path = get_property_string("path");
using (MediaInfo mi = new MediaInfo(get_property_string("path"))) if (File.Exists(path))
{ {
int count = mi.GetCount(MediaInfoStreamKind.Video); using (MediaInfo mi = new MediaInfo(path))
for (int i = 0; i < count; i++)
{ {
MediaTrack track = new MediaTrack(); int count = mi.GetCount(MediaInfoStreamKind.Video);
Add(track, mi.GetVideo(i, "Format"));
Add(track, mi.GetVideo(i, "Format_Profile"));
Add(track, mi.GetVideo(i, "Width") + "x" + mi.GetVideo(i, "Height"));
Add(track, mi.GetVideo(i, "FrameRate") + " FPS");
Add(track, mi.GetVideo(i, "Language/String"));
Add(track, mi.GetVideo(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetVideo(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetVideo(i, "Title"));
track.Text = "V: " + track.Text.Trim(' ', ',');
track.Type = "v";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = mi.GetCount(MediaInfoStreamKind.Audio); for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetVideo(i, "Format"));
Add(track, mi.GetVideo(i, "Format_Profile"));
Add(track, mi.GetVideo(i, "Width") + "x" + mi.GetVideo(i, "Height"));
Add(track, mi.GetVideo(i, "FrameRate") + " FPS");
Add(track, mi.GetVideo(i, "Language/String"));
Add(track, mi.GetVideo(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetVideo(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetVideo(i, "Title"));
track.Text = "V: " + track.Text.Trim(' ', ',');
track.Type = "v";
track.ID = i + 1;
MediaTracks.Add(track);
}
for (int i = 0; i < count; i++) count = mi.GetCount(MediaInfoStreamKind.Audio);
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetAudio(i, "Language/String"));
Add(track, mi.GetAudio(i, "Format"));
Add(track, mi.GetAudio(i, "Format_Profile"));
Add(track, mi.GetAudio(i, "BitRate/String"));
Add(track, mi.GetAudio(i, "Channel(s)/String"));
Add(track, mi.GetAudio(i, "SamplingRate/String"));
Add(track, mi.GetAudio(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetAudio(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetAudio(i, "Title"));
track.Text = "A: " + track.Text.Trim(' ', ',');
track.Type = "a";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = mi.GetCount(MediaInfoStreamKind.Text); for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetAudio(i, "Language/String"));
Add(track, mi.GetAudio(i, "Format"));
Add(track, mi.GetAudio(i, "Format_Profile"));
Add(track, mi.GetAudio(i, "BitRate/String"));
Add(track, mi.GetAudio(i, "Channel(s)/String"));
Add(track, mi.GetAudio(i, "SamplingRate/String"));
Add(track, mi.GetAudio(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetAudio(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetAudio(i, "Title"));
track.Text = "A: " + track.Text.Trim(' ', ',');
track.Type = "a";
track.ID = i + 1;
MediaTracks.Add(track);
}
for (int i = 0; i < count; i++) count = mi.GetCount(MediaInfoStreamKind.Text);
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetText(i, "Language/String"));
Add(track, mi.GetText(i, "Format"));
Add(track, mi.GetText(i, "Format_Profile"));
Add(track, mi.GetText(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetText(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetText(i, "Title"));
track.Text = "S: " + track.Text.Trim(' ', ',');
track.Type = "s";
track.ID = i + 1;
MediaTracks.Add(track);
}
count = get_property_int("edition-list/count"); for (int i = 0; i < count; i++)
{
MediaTrack track = new MediaTrack();
Add(track, mi.GetText(i, "Language/String"));
Add(track, mi.GetText(i, "Format"));
Add(track, mi.GetText(i, "Format_Profile"));
Add(track, mi.GetText(i, "Forced") == "Yes" ? "Forced" : "");
Add(track, mi.GetText(i, "Default") == "Yes" ? "Default" : "");
Add(track, mi.GetText(i, "Title"));
track.Text = "S: " + track.Text.Trim(' ', ',');
track.Type = "s";
track.ID = i + 1;
MediaTracks.Add(track);
}
for (int i = 0; i < count; i++) count = get_property_int("edition-list/count");
{
MediaTrack track = new MediaTrack();
track.Text = "E: " + get_property_string($"edition-list/{i}/title");
track.Type = "e";
track.ID = i;
MediaTracks.Add(track);
}
void Add(MediaTrack track, string val) for (int i = 0; i < count; i++)
{ {
if (!string.IsNullOrEmpty(val) && !(track.Text != null && track.Text.Contains(val))) MediaTrack track = new MediaTrack();
track.Text += " " + val + ","; track.Text = "E: " + get_property_string($"edition-list/{i}/title");
track.Type = "e";
track.ID = i;
MediaTracks.Add(track);
}
void Add(MediaTrack track, string val)
{
if (!string.IsNullOrEmpty(val) && !(track.Text != null && track.Text.Contains(val)))
track.Text += " " + val + ",";
}
} }
} }
} }

View File

@@ -39,6 +39,7 @@ Source: "{#MyAppSourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesub
[Run] [Run]
Filename: "{app}\{#MyAppExeName}"; Description: "Associate video file extensions?"; Flags: postinstall unchecked runascurrentuser runhidden nowait; Parameters: "--reg-file-assoc video" Filename: "{app}\{#MyAppExeName}"; Description: "Associate video file extensions?"; Flags: postinstall unchecked runascurrentuser runhidden nowait; Parameters: "--reg-file-assoc video"
Filename: "{app}\{#MyAppExeName}"; Description: "Associate audio file extensions?"; Flags: postinstall unchecked runascurrentuser runhidden nowait; Parameters: "--reg-file-assoc audio" Filename: "{app}\{#MyAppExeName}"; Description: "Associate audio file extensions?"; Flags: postinstall unchecked runascurrentuser runhidden nowait; Parameters: "--reg-file-assoc audio"
Filename: "{app}\{#MyAppExeName}"; Description: "Associate image file extensions?"; Flags: postinstall unchecked runascurrentuser runhidden nowait; Parameters: "--reg-file-assoc image"
[UninstallRun] [UninstallRun]
Filename: "{app}\{#MyAppExeName}"; Flags: runascurrentuser runhidden; Parameters: "--reg-file-assoc unreg" Filename: "{app}\{#MyAppExeName}"; Flags: runascurrentuser runhidden; Parameters: "--reg-file-assoc unreg"

View File

@@ -1,48 +0,0 @@
# exit the script if the exit code is greater than 0
function CheckExitCode {
if ($LastExitCode -gt 0) {
Write-Host "`nExit code $LastExitCode was returned.`n" -ForegroundColor Red
exit
}
}
# exit the script if the file don't exist
function CheckFileExist($path) {
if (![IO.File]::Exists($path)) {
Write-Host "`nFile is missing:`n`n$path`n" -ForegroundColor Red
exit
}
}
$msbuild = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
$innoSetup = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
$sevenZip = "C:\Program Files\7-Zip\7z.exe"
# exit the script if one of the executables don't exist
CheckFileExist($msbuild); CheckFileExist($innoSetup); CheckFileExist($sevenZip);
# build the projects using msbuild
& $msbuild mpv.net.sln /p:Configuration=Debug /p:Platform=x64; CheckExitCode
& $msbuild mpv.net.sln /p:Configuration=Debug /p:Platform=x86; CheckExitCode
# build the setups using inno setup
& $innoSetup /Darch="x64" setup.iss; CheckExitCode
& $innoSetup /Darch="x86" setup.iss; CheckExitCode
# create the x64 portable archives using 7zip
$scriptDir = Split-Path -Path $PSCommandPath -Parent
$desktopDir = [Environment]::GetFolderPath("Desktop")
$exePath = $scriptDir + "\mpv.net\bin\x64\mpvnet.exe"
$version = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath).FileVersion
$targetDir = $desktopDir + "\mpv.net-portable-x64-" + $version
Copy-Item $scriptDir\mpv.net\bin\x64 $targetDir -Recurse -Exclude System.Management.Automation.xml -Force
& $sevenZip a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"; CheckExitCode
& $sevenZip a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"; CheckExitCode
# create the x86 portable archives using 7zip
$exePath = $scriptDir + "\mpv.net\bin\x86\mpvnet.exe"
$version = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath).FileVersion
$targetDir = $desktopDir + "\mpv.net-portable-x86-" + $version
Copy-Item $scriptDir\mpv.net\bin\x86 $targetDir -Recurse -Exclude System.Management.Automation.xml -Force
& $sevenZip a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"; CheckExitCode
& $sevenZip a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"; CheckExitCode