Compare commits

..

26 Commits
3.3 ... 3.7

Author SHA1 Message Date
Frank Skare
19c09da4e1 - 2019-05-25 02:01:17 +02:00
Frank Skare
95c9c115b2 - 2019-05-23 03:35:10 +02:00
Frank Skare
2512c02bff 3.6.1 2019-05-23 00:51:15 +02:00
Frank Skare
351fae8344 - 2019-05-13 03:29:12 +02:00
Frank Skare
30b562a1e1 - 2019-05-13 03:23:33 +02:00
Frank Skare
8a9a017875 - 2019-05-13 03:22:31 +02:00
Frank Skare
fa0b0f496f - 2019-05-13 03:20:44 +02:00
Frank Skare
83b5d9b65c - 2019-05-13 03:19:17 +02:00
Frank Skare
b199d33f7a - 2019-05-13 03:00:41 +02:00
Frank Skare
a7b6f79ee1 - 2019-05-13 02:48:46 +02:00
Frank Skare
fc3c5ee3a7 - 2019-05-13 02:35:31 +02:00
Frank Skare
ed71cb704f - 2019-05-11 02:09:41 +02:00
Frank Skare
a9474b1c22 - 2019-05-11 00:49:38 +02:00
Frank Skare
be3b31f7e6 - 2019-05-09 19:16:48 +02:00
Frank Skare
b2884e2037 - 2019-05-09 12:41:58 +02:00
Frank Skare
3910776b54 - 2019-05-09 12:36:05 +02:00
Frank Skare
b37272db8b - 2019-05-09 12:28:17 +02:00
Frank Skare
08a23430c7 - 2019-05-05 04:02:10 +02:00
Frank Skare
ba41b8026f - 2019-05-04 19:15:18 +02:00
Frank Skare
4aeb00afb5 - 2019-05-04 19:04:18 +02:00
Frank Skare
6e6015b185 - 2019-05-04 15:10:00 +02:00
Frank Skare
68240ac49d - 2019-05-04 15:02:26 +02:00
Frank Skare
bafc481117 - 2019-05-04 14:53:42 +02:00
Frank Skare
9198d610ad - 2019-05-04 14:03:59 +02:00
Frank Skare
ad4199aff0 - 2019-05-04 00:17:31 +02:00
Frank Skare
3164e2322c - 2019-05-03 18:27:05 +02:00
48 changed files with 1979 additions and 1327 deletions

131
README.md
View File

@@ -43,17 +43,18 @@ Table of contents
### Features
- Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu))
- Searchable config dialog ([Screenshot](#config-editor))
- Searchable input (key/mouse) binding editor ([Screenshot](#input-editor))
- Searchable command palette to quickly launch commands and look for keys ([Screenshot](#command-palette))
- Modern UI with dark mode ([Screenshot](#config-editor))
- Customizable context menu defined in the same file as the key bindings ([Screenshot](#context-menu-screenshot))
- Searchable config dialog ([Screenshot](#config-editor-screenshot))
- Searchable input (key/mouse) binding editor ([Screenshot](#input-editor-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))
- Addon/extension API for .NET languages
- 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
- Support of the same [CLI options](https://mpv.io/manual/master/#options) as mpv
- DXVA2 video decoding acceleration
- OpenGL based video output capable of features loved by videophiles, such as video scaling with popular high quality algorithms, color management, frame timing, interpolation, HDR, and more
- Search feature powered by [Everything](https://www.voidtools.com) to find and play media ([Screenshot](#media-search-screenshot))
### Screenshots
@@ -86,6 +87,12 @@ Just press Ctrl+Shift+P and find it easily in the searchable command palette.
![Command Palette](https://raw.githubusercontent.com/stax76/mpv.net/master/img/CommandPalette.png)
#### Media Search Screenshot
Media search feature powered by [Everything](https://www.voidtools.com) to find and play media.
![Media Search](https://raw.githubusercontent.com/stax76/mpv.net/master/img/MediaSearch.png)
### Context Menu
The context menu can be customized via input.conf file located in the config directory:
@@ -102,43 +109,31 @@ input.conf defines mpv's key and mouse bindings and mpv.net uses comments to def
### Settings
mpv.net shares the settings with mpv, settings can be edited in a settings dialog or in a config file called mpv.conf located in the config directory:
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
```
or in a portable setup at:
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
```
if it's missing 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>
### Scripting
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.
Scripting is supported via Python, C#, Lua, JavaScript and PowerShell
### Scripting
[Scripting wiki page](https://github.com/stax76/mpv.net/wiki/Scripting)
### Add-ons
Add-ons are located in the config directory:
```Text
C:\Users\%username%\AppData\Roaming\mpv\Addons\ExampleAddon\ExampleAddon.dll
```
The add-on filename must end with 'Addon.dll'.
Examples:
[RatingAddon.cs](https://github.com/stax76/mpv.net/blob/master/RatingAddon/RatingAddon.cs)
[CSScriptAddon.vb](https://github.com/stax76/mpv.net/blob/master/CSScriptAddon/CSScriptAddon.vb)
[Add-on wiki page](https://github.com/stax76/mpv.net/wiki/Addons)
### Architecture
@@ -162,6 +157,8 @@ Third party components are:
- [MediaInfo](https://mediaarea.net/en/MediaInfo)
- [Tommy (TOML parser)](https://github.com/dezhidki/Tommy)
- [IronPython](https://ironpython.net/)
- [CS-Script](http://www.csscript.net/)
- [Everything](https://www.voidtools.com)
### Support
@@ -201,76 +198,36 @@ mpv.net bugs and requests: <https://github.com/stax76/mpv.net/issues>
### Changelog
### 3.3 (2019-05-01)
### 3.7
- dark mode support was added to the command palette and partly to the input editor
- a new icon was designed. [Website](https://mpv-net.github.io/mpv.net-web-site/)
- all windows (main, conf, input, about, command palette) can now be closed
by just pressing the Escape key
- new feature added to open recent files and URLs with the context menu. [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L33)
- the info command (i key) now works also for URLs
- CSScriptAddon add-on didn't load cs scripts from \<startup\>\\scripts
- error handling was improved by showing an improved message box that supports a text copy feature, a support link and text heading and text folding
- libmpv was updated
- new icon design
- the radio buttons in the config editor have now a Windows 10 like design,
they are larger and use the Windows theme color
### 3.2 (2019-04-27)
### 3.6.1
- mpvInputEdit and mpvConfEdit were discontinued and merged into
mpvnet because separate apps were to difficult to work with
- portable mode: in case no config folder exists and the
startup folder has write access mpvnet will ask where
the config folder should be created (portable or appdata)
- there was an issue causing keys not working after a modal window was shown
- there was a crash when no script folder existed in the conf folder
- MediaInfo and youtube-dl were updated
- a new JavaScript example script was added to the wiki and the
script descriptions were improved. [Scripting Page](https://github.com/stax76/mpv.net/wiki/Scripting).
- greatly improved README.md file and [github startpage](https://github.com/stax76/mpv.net)
- About dialog added
- the input editor shows only a closing message if actually a change was made
- the input editor don't show confusing menu separators any longer. [Screenshot](https://github.com/stax76/mpv.net#input-editor)
- new Command Palette feature added. [Screenshot](https://github.com/stax76/mpv.net#command-palette), [Default input binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L141)
- the history feature had a bug causing files to be logged more than once
- there was a bug causing an exception if both the input editor and config editor
is opened, as soon as one is opened, the other can't be opened
### 3.1 (2019-04-23)
### 3.6
- the Tracks and Chapters menu are now only added if default bindings exist and
it's now possible to move the chapters menu to the top level by editing input.conf
- mpvnet supports now like mpv a portable settings directory. If a directory named portable_config
next to the mpvnet.exe exists, all config will be loaded and written in this directory.
- there is now a portable download in 7zip format.
- playing files from rar archives caused an exception
- there was a bug that caused underscores beeing removed from input like MBTN_LEFT_DBL
- the search clear button in the input editor had a render issue in dark mode
- new search feature added to search and play media files, requires
[Everything](https://www.voidtools.com) to be installed. [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L29)
### 3.0 (2019-04-20)
### 3.5
- the history feature logs now only files that were opened longer than 90 seconds
- the default input command for cycling the audio tracks was replaced with an
mpv.net command that shows detailed track info and has no 'no audio' track. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L89).
- new website at <https://mpv-net.github.io/mpv.net-web-site/>
- the Tracks menu supports now MKV edition selection. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L106).
- the Navigate menu supports now chapter selection. [Default binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L57).
- opening the context menu was crashing if the default binding for Tracks was missing
- when the main windows gets activated and the clipboard content starts with http
mpv.net will ask to play the URL, previously this was restricted to YouTube URLs
- Python script errors show line and column whenever it is supported by IronPython
- if conf files exist in the startup directory mpv.net will use the startup
directory as config directory instead of creating default conf files in appdata
- renamed commands are handled now by migration code instead of being broken
### 2.9 (2019-04-16)
### 3.4
- clicking the right top corner in full screen mode
closes the player but it did not work on all displays
- the info display was changed to display the filename on top
so it's not displayed in the middle of the screen
- on start up of the config editor all text is now selected in the
search text box so it's ready for a new search to be typed
- the config editor was changed to write the settings to disk
only if the settings were actually modified, also the message
that says that the settings will be available on next start
is now only shown if the settings were actually modified.
- there was an instance in the context menu where the sub menu
arrow was overlapping with the text
- in the input editor when only one character is entered in the
search text box the search is performed only in the input and
not in the command or menu
- in the input editor the routine that generates the input string
was completely rewritten because it was adding Shift where it
wasn't necessary (it took a huge amount of time to implement)
- the context menu has a new track menu where the active track
can be seen and selected, it shows video, audio and subtitle
tracks with various metadata. [Menu default definition](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L104).
The screenshots were updated showing the [new track menu](https://github.com/stax76/mpv.net#screenshots).
- new feature added to manage file associations from within the app. It can be found in the menu at: Tools > Manage... [Default Binding](https://github.com/stax76/mpv.net/blob/master/mpv.net/Resources/inputConf.txt#L149)
- new zip download option added
- new x86 download option added

View File

@@ -28,7 +28,7 @@ Public Class CSScriptAddon
Try
CSScriptLibrary.CSScript.Evaluator.LoadCode(File.ReadAllText(i))
Catch ex As Exception
Sys.Msg.ShowException(ex)
Msg.ShowException(ex)
End Try
Next
End Sub

View File

@@ -47,6 +47,48 @@
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>..\..\mpv.net\bin\x86\Addons\CSScriptAddon\</OutputPath>
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<DefineTrace>true</DefineTrace>
<OutputPath>..\mpv.net\bin\x86\Addons\CSScriptAddon\</OutputPath>
<Optimize>true</Optimize>
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>..\..\mpv.net\bin\x64\Addons\CSScriptAddon\</OutputPath>
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<DefineTrace>true</DefineTrace>
<OutputPath>..\mpv.net\bin\x64\Addons\CSScriptAddon\</OutputPath>
<Optimize>true</Optimize>
<NoWarn>42105,42106,42107,42353,42354,42355</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="CSScriptLibrary, Version=3.27.5.0, Culture=neutral, PublicKeyToken=70fcc3d18c749033, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -114,7 +156,7 @@
<Content Include="CSScriptLibrary.dll" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
<ProjectReference Include="..\..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55C88710-539D-4402-84C8-31694841C731}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RatingAddon</RootNamespace>
<AssemblyName>RatingAddon</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\mpv.net\bin\x86\Addons\RatingAddon\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\mpv.net\bin\x86\Addons\RatingAddon\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\mpv.net\bin\x64\Addons\RatingAddon\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>..\mpv.net\bin\x64\Addons\RatingAddon\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="RatingAddon.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TestAddon")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestAddon")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("06f854b0-00f9-4b53-94d9-0be65a7c55d8")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,27 @@
using System.ComponentModel.Composition;
using mpvnet;
namespace TestAddon
{
[Export(typeof(IAddon))]
public class TestAddon : IAddon
{
// do some init work in constructor
public TestAddon()
{
// Observe changes of the fullscreen property.
// You can find a list of available mpv properties
// in mpv.net's wiki on github or use mpv --list-properties.
// You can test properties in mpv.net in the menu at:
// Tools > Execute mpv command
// where you can enter: show-text ${fullscreen}
mp.observe_property_bool("fullscreen", OnFullscreenChange);
}
void OnFullscreenChange(bool val)
{
mp.commandv("show-text", "fullscreen: " + val.ToString());
}
}
}

View File

@@ -4,20 +4,20 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55C88710-539D-4402-84C8-31694841C731}</ProjectGuid>
<ProjectGuid>{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RatingAddon</RootNamespace>
<AssemblyName>RatingAddon</AssemblyName>
<RootNamespace>TestAddon</RootNamespace>
<AssemblyName>TestAddon</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -25,7 +25,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\mpv.net\bin\Addons\RatingAddon\</OutputPath>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -42,11 +42,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="RatingAddon.cs" />
<Compile Include="TestAddon.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mpv.net\mpv.net.csproj">
<ProjectReference Include="..\..\mpv.net\mpv.net.csproj">
<Project>{1751f378-8edf-4b62-be6d-304c7c287089}</Project>
<Name>mpv.net</Name>
<Private>False</Private>

BIN
img/MediaSearch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -5,28 +5,70 @@ VisualStudioVersion = 16.0.28729.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mpv.net", "mpv.net\mpv.net.csproj", "{1751F378-8EDF-4B62-BE6D-304C7C287089}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingAddon", "RatingAddon\RatingAddon.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CSScriptAddon", "addons\CSScriptAddon\CSScriptAddon.vbproj", "{71808A87-8B1C-4DF8-957C-D79C3B164CCA}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CSScriptAddon", "CSScriptAddon\CSScriptAddon.vbproj", "{71808A87-8B1C-4DF8-957C-D79C3B164CCA}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingAddon", "addons\RatingAddon\RatingAddon.csproj", "{55C88710-539D-4402-84C8-31694841C731}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAddon", "addons\TestAddon\TestAddon.csproj", "{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.ActiveCfg = Debug|x64
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x64.Build.0 = Debug|x64
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.ActiveCfg = Debug|x86
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Debug|x86.Build.0 = Debug|x86
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|Any CPU.Build.0 = Release|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.Build.0 = Release|Any CPU
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.ActiveCfg = Release|x64
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x64.Build.0 = Release|x64
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.ActiveCfg = Release|x86
{1751F378-8EDF-4B62-BE6D-304C7C287089}.Release|x86.Build.0 = Release|x86
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x64.ActiveCfg = Debug|x64
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x64.Build.0 = Debug|x64
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x86.ActiveCfg = Debug|x86
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Debug|x86.Build.0 = Debug|x86
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|Any CPU.Build.0 = Release|Any CPU
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x64.ActiveCfg = Release|x64
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x64.Build.0 = Release|x64
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x86.ActiveCfg = Release|x86
{71808A87-8B1C-4DF8-957C-D79C3B164CCA}.Release|x86.Build.0 = Release|x86
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.ActiveCfg = Debug|x64
{55C88710-539D-4402-84C8-31694841C731}.Debug|x64.Build.0 = Debug|x64
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.ActiveCfg = Debug|x86
{55C88710-539D-4402-84C8-31694841C731}.Debug|x86.Build.0 = Debug|x86
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Release|Any CPU.Build.0 = Release|Any CPU
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.ActiveCfg = Release|x64
{55C88710-539D-4402-84C8-31694841C731}.Release|x64.Build.0 = Release|x64
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.ActiveCfg = Release|x86
{55C88710-539D-4402-84C8-31694841C731}.Release|x86.Build.0 = Release|x86
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Debug|x64.ActiveCfg = Debug|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Debug|x64.Build.0 = Debug|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Debug|x86.ActiveCfg = Debug|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Debug|x86.Build.0 = Debug|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Release|Any CPU.Build.0 = Release|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Release|x64.ActiveCfg = Release|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Release|x64.Build.0 = Release|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Release|x86.ActiveCfg = Release|Any CPU
{06F854B0-00F9-4B53-94D9-0BE65A7C55D8}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -5,8 +5,6 @@ using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Windows.Forms;
using Sys;
namespace mpvnet
{
public class Addon

View File

@@ -7,8 +7,6 @@ using System.Reflection;
using System.Windows.Forms;
using System.Windows.Interop;
using Sys;
namespace mpvnet
{
public class Command
@@ -28,7 +26,7 @@ namespace mpvnet
Type type = typeof(Command);
MethodInfo[] methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
foreach (var i in methods)
foreach (MethodInfo i in methods)
{
ParameterInfo[] parameters = i.GetParameters();
@@ -46,14 +44,9 @@ namespace mpvnet
public static void open_files(string[] args)
{
MainForm.Instance.Invoke(new Action(() => {
using (var d = new OpenFileDialog())
{
d.Multiselect = true;
d.Filter = Sys.GetFilter();
using (var d = new OpenFileDialog() { Multiselect = true })
if (d.ShowDialog() == DialogResult.OK)
mp.LoadFiles(d.FileNames);
}
}));
}
@@ -98,6 +91,15 @@ namespace mpvnet
}));
}
public static void show_media_search(string[] args)
{
MainForm.Instance.Invoke(new Action(() => {
var w = new EverythingWindow();
new WindowInteropHelper(w).Owner = MainForm.Instance.Handle;
w.ShowDialog();
}));
}
public static void show_history(string[] args)
{
var fp = mp.MpvConfFolder + "history.txt";
@@ -126,7 +128,7 @@ namespace mpvnet
{
fileSize = new FileInfo(path).Length;
if (FileAssociation.AudioTypes.Contains(Path.GetExtension(path).ToLower().TrimStart('.')))
if (App.AudioTypes.Contains(Path.GetExtension(path).ToLower().TrimStart('.')))
{
using (MediaInfo mediaInfo = new MediaInfo(path))
{
@@ -239,5 +241,35 @@ namespace mpvnet
mp.commandv("show-text", audTracks[aid - 1].Text.Substring(3), "5000");
}
}
public static void manage_file_associations(string[] args)
{
using (var td = new TaskDialog<string>())
{
td.MainInstruction = "Choose an option.";
td.MainIcon = MsgIcon.Shield;
td.AddCommandLink("Register video file extensions", "video");
td.AddCommandLink("Register audio file extensions", "audio");
td.AddCommandLink("Unregister file extensions", "unreg");
string result = td.Show();
if (!string.IsNullOrEmpty(result))
{
using (var proc = new Process())
{
proc.StartInfo.FileName = Application.ExecutablePath;
proc.StartInfo.Arguments = "--reg-file-assoc " + result;
proc.StartInfo.Verb = "runas";
try {
proc.Start();
}
catch (Exception)
{ }
}
}
}
}
}
}

View File

@@ -10,8 +10,6 @@ using System.ComponentModel;
using System.Globalization;
using System.Diagnostics;
using Sys;
namespace mpvnet
{
public partial class MainForm : Form
@@ -309,55 +307,32 @@ namespace mpvnet
public void BuildMenu()
{
string content = File.ReadAllText(mp.InputConfPath);
List<string> lines = null;
Dictionary<string, string> commandInputDic = new Dictionary<string, string>();
var items = CommandItem.GetItems(content);
if (content.Contains("#menu:"))
lines = content.Split("\r\n".ToCharArray()).ToList();
else
if (!content.Contains("#menu:"))
{
lines = Properties.Resources.inputConf.Split("\r\n".ToCharArray()).ToList();
foreach (string i in content.Split("\r\n".ToCharArray()))
{
string line = i.Trim();
if (line.StartsWith("#") || !line.Contains(" ")) continue;
string input = line.Substring(0, line.IndexOf(" ")).Trim();
string command = line.Substring(line.IndexOf(" ") + 1).Trim();
commandInputDic[command] = input;
}
var defaultItems = CommandItem.GetItems(Properties.Resources.inputConf);
foreach (CommandItem item in items)
foreach (CommandItem defaultItem in defaultItems)
if (item.Command == defaultItem.Command)
defaultItem.Input = item.Input;
items = defaultItems;
}
foreach (string line in lines)
foreach (CommandItem item in items)
{
if (!line.Contains("#menu:")) continue;
string left = line.Substring(0, line.IndexOf("#menu:")).Trim();
if (left.StartsWith("#")) continue;
string command = left.Substring(left.IndexOf(" ") + 1).Trim();
string menu = line.Substring(line.IndexOf("#menu:") + "#menu:".Length).Trim();
string input = left.Substring(0, left.IndexOf(" "));
if (input == "_") input = "";
if (menu.Contains(";")) input = menu.Substring(0, menu.IndexOf(";")).Trim();
string path = menu.Substring(menu.IndexOf(";") + 1).Trim().Replace("&", "&&");
if (path == "" || command == "") continue;
if (commandInputDic.Count > 0)
if (commandInputDic.ContainsKey(command))
input = commandInputDic[command];
else
input = "";
if (string.IsNullOrEmpty(item.Path))
continue;
string path = item.Path.Replace("&", "&&");
MenuItem menuItem = ContextMenu.Add(path, () => {
try {
mp.command_string(command);
}
catch (Exception ex) {
mp.command_string(item.Command);
} catch (Exception ex) {
Msg.ShowException(ex);
}
});
if (menuItem != null)
menuItem.ShortcutKeyDisplayString = input + " ";
menuItem.ShortcutKeyDisplayString = item.Input + " ";
}
}
@@ -366,7 +341,12 @@ namespace mpvnet
private void Mp_FileLoaded()
{
string path = mp.get_property_string("path");
BeginInvoke(new Action(() => { Text = Path.GetFileName(path) + " - mpv.net " + Application.ProductVersion; }));
BeginInvoke(new Action(() => {
if (File.Exists(path) || path.StartsWith("http"))
Text = Path.GetFileName(path) + " - mpv.net " + Application.ProductVersion;
else
Text = "mpv.net " + Application.ProductVersion;
}));
if (RecentFiles.Contains(path)) RecentFiles.Remove(path);
RecentFiles.Insert(0, path);
if (RecentFiles.Count > 15) RecentFiles.RemoveAt(15);
@@ -568,7 +548,7 @@ namespace mpvnet
BuildMenu();
ContextMenuStrip = ContextMenu;
IgnoreDpiChanged = false;
CheckYouTube();
CheckURL();
}
protected override void OnFormClosed(FormClosedEventArgs e)
@@ -588,18 +568,18 @@ namespace mpvnet
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
CheckYouTube();
CheckURL();
}
void CheckYouTube()
void CheckURL()
{
string clipboard = Clipboard.GetText();
if (clipboard.StartsWith("https://www.youtube.com/watch?") && RegistryHelp.GetString("HKCU\\Software\\" + Application.ProductName, "LastYouTubeURL") != clipboard && Visible)
if (clipboard.StartsWith("http") && RegistryHelp.GetString("HKCU\\Software\\" + Application.ProductName, "LastURL") != clipboard && Visible)
{
RegistryHelp.SetObject("HKCU\\Software\\" + Application.ProductName, "LastYouTubeURL", clipboard);
RegistryHelp.SetObject("HKCU\\Software\\" + Application.ProductName, "LastURL", clipboard);
if (Msg.ShowQuestion("Play YouTube URL?", clipboard) == MsgResult.OK)
if (Msg.ShowQuestion("Play URL?", clipboard) == MsgResult.OK)
mp.LoadFiles(clipboard);
}
}

View File

@@ -123,383 +123,422 @@
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAQAEBAAAAEAIABoBAAARgAAACAgAAABACAAqBAAAK4EAAAwMAAAAQAgAKglAABWFQAAAAAAAAEA
IABKHQAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMMOAADDDgAAAAAAAAAAAAAAAAAAAAAAAP/c
uQD/3LgH/968SP/ct6j/16rk/9Kf+//Sn/v/16rj/9y3qP/evEj/3LgH/9y5AAAAAAAAAAAA/9u1AP/c
uQD/3bkY/9y3kv/Ole7/t1j//6Us//+eGv//nhr//6Us//+3WP//zpXu/9y3kv/duRj/3LkA/9u1AP/b
tgD/3bkY/9qysP/AcP//nRf//5MA//+TAP//kgD//5IA//+SAP//kwD//50X///AcP//2rKw/925GP/b
tgD/3LgG/9y3kv/AcP//lwr//5MA//+UAf//mxL//6Us//+mLv//nBb//5QB//+TAP//lwr//8Bw///c
t5L/3LgG/968Sf/OlO3/nRj//5MA//+VBP//sEf//8+X///ZsP//2a///9Gc//+1U///lwj//5MA//+d
GP//zpTt/968Sf/ct6f/tlj//5MA//+TAP//r0X//9mv///Xq///0Zz//9y3///cuP//2rP//7ZW//+U
Af//kwD//7ZY///ct6f/16ri/6Us//+TAP//mg///82S///duv//zZH//6Ij//+9aP//16v//9y4///S
n///nhn//5IA//+lLP//16rj/9Kf+/+eGv//kgD//6Ml///Xq///3Lj//82R//+YC///lAL//6gy///P
lv//2rP//6k2//+SAP//nhr//9Kf+//Sn/v/nhr//5IA//+jJf//16v//9y4///Nkv//mAv//5YH//+v
RP//0p7//9qz//+pNv//kgD//54a///Sn/v/16ri/6Us//+TAP//mg///82S///duv//zpP//6Yu///D
d///2bH//9y4///Sn///nhn//5IA//+lLP//16ri/9y3p/+2WP//kwD//5MA//+vRf//2a///9iu///V
pP//3Lf//9y3///as///tlb//5QB//+TAP//tlj//9y3p//evEn/zpTt/50Y//+TAP//lQT//7BH///P
lv//2a///9mv///RnP//tVP//5cI//+TAP//nRj//86U7f/evEn/3LgG/9y3kf/AcP//lwr//5MA//+U
Af//mxL//6Us//+mLv//nBX//5QB//+TAP//lwr//8Bw///ct5L/3LgG/9u2AP/duRj/2rKw/8Bw//+d
F///kwD//5MA//+SAP//kgD//5IA//+TAP//nRf//8Bw///asrD/3bkY/9u2AP/btQD/3LkA/925GP/c
t5L/zpXu/7dY//+lLP//nhr//54a//+lLP//t1j//86V7v/ct5L/3bkY/9y5AP/btQAAAAAAAAAAAP/c
uQD/3LcH/968SP/ct6j/16rk/9Kf+//Sn/v/16rk/9y3qP/evEj/3LcH/9y5AAAAAAAAAAAA4AcAAMAD
AACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAADAAwAA4AcAACgA
AAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP/btQD/27UE/9u1Kf/btWz/27Ws/9u12f/btvH/3Lf9/9y3/f/btvH/27XY/9u1q//b
tWz/27Up/9u1BP/btQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP/btQD/27UD/9u1N//btZf/27bf/9y4+//ctv//2bD//9Wn///ToP//06D//9Wn///Z
sP//3Lb//9y4+//btt//27WX/9u1N//btQP/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP/btQD/27UA/9u1Gf/btYn/27bq/9y3///WqP//xoD//7RT//+nMv//oCD//50X//+d
F///oCD//6cy//+0U///xoD//9ao///ct///27bq/9u1if/btRn/27UA/9u1AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/27UA/9u1AP/btTX/27XC/9y3/v/Wqf//vmv//6Mn//+WBv//kwD//5MA//+T
AP//kwD//5MA//+TAP//kwD//5MA//+WBv//oyf//75r///Wqf//3Lf+/9u1wv/btTX/27UA/9u1AAAA
AAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQD/27VB/9u12P/btv//y4z//6cw//+VA///kwD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//lQP//6cw///LjP//27b//9u12P/b
tUH/27UA/9u1AAAAAAAAAAAAAAAAAP/btQD/27UA/9u1Nv/btdj/27X//8N4//+cFf//kwD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//5wV///D
eP//27X//9u12P/btTb/27UA/9u1AAAAAAAAAAAA/9u1AP/btRr/27XB/9u2///DeP//mQ7//5MA//+U
AP//lAD//5QA//+UAP//lAD//5MA//+TAP//kwD//5MA//+TAP//kwD//5QA//+UAP//lAD//5QA//+U
AP//kwD//5kO///DeP//27b//9u1wf/btRr/27UAAAAAAP/btQD/27UC/9u1if/ct///y4z//5wV//+T
AP//lAD//5QA//+UAP//lAD//5MA//+VBP//oB7//60///+1VP//tlf//7BG//+jJ///lwn//5MA//+U
AP//lAD//5QA//+UAP//kwD//5wV///LjP//3Lf//9u1if/btQL/27UA/9u1AP/btTf/27bo/9ap//+n
Mf//kwD//5QA//+UAP//lAD//5QA//+UAf//oyf//8F0///UpP//2rT//9y3///ct///27X//9eq///I
hP//qzr//5UF//+UAP//lAD//5QA//+UAP//kwD//6cx///Wqf//27bp/9u1N//btQD/27UC/9u1l//c
t///vmv//5UC//+UAP//lAD//5QA//+UAP//lQP//7BH///Uo///3Lj//9u2///btf//27X//9u1///b
tf//27b//9y4///Yrv//u2L//5gL//+UAP//lAD//5QA//+UAP//lQL//75r///ct///27WX/9u1A//b
tSr/27be/9ao//+jJ///kwD//5QA//+UAP//lAD//5QA//+vRf//2Kz//9y3///btf//27T//9y2///b
tv//27X//9u1///btf//27X//9u2///btf//vGX//5YF//+UAP//lAD//5QA//+TAP//oyf//9ao///b
tt7/27Uq/9u1bP/cuPv/xoD//5YG//+UAP//lAD//5QA//+TAP//oSL//9Og///ct///27X//9y3///M
kP//wHD//9it///ct///27X//9u1///btf//27X//9u2///ZsP//rUH//5MA//+UAP//lAD//5QA//+W
Bv//xoD//9y4+//btWz/27Wr/9y2//+0U///kwD//5QA//+UAP//lAD//5QB//++av//3Lj//9u1///b
tf//3Lj//8V+//+XCP//qjj//8uN///btf//27b//9u1///btf//27X//9y4///Ljf//mQ3//5QA//+U
AP//lAD//5MA//+0U///3Lb//9u1rP/btdj/2bD//6cy//+TAP//lAD//5QA//+TAP//nBb//9Gc///c
t///27X//9u1///cuP//xn///5UD//+TAP//mxH//7hb///Vpf//3Lf//9u1///btf//27X//9mv//+o
Mv//kwD//5QA//+UAP//kwD//6cy///ZsP//27XY/9u28f/Vp///oCD//5MA//+UAP//lAD//5MA//+n
Mf//2a///9u1///btf//27X//9y4///Hgf//lgT//5QA//+UAP//lAH//6Qo///Ffv//2rH//9u2///b
tf//3Lf//7ZW//+TAP//lAD//5QA//+TAP//oCD//9Wn///btvH/3Lf9/9Og//+dF///kwD//5QA//+U
AP//kwD//65C///btf//27X//9u1///btf//3Lj//8eB//+WBP//lAD//5QA//+UAP//kwD//5cI//+z
T///16v//9u2///cuP//vmr//5QA//+UAP//lAD//5MA//+dF///06D//9y3/f/ct/3/06D//50X//+T
AP//lAD//5QA//+TAP//rkL//9u1///btf//27X//9u1///cuP//x4L//5YE//+UAP//lAD//5QA//+T
AP//oB7//8Fy///ZsP//27X//9y4//++av//lAD//5QA//+UAP//kwD//50X///ToP//3Lf9/9u28f/V
p///oCD//5MA//+UAP//lAD//5MA//+nMf//2a///9u1///btf//27X//9y4///Hg///lgX//5QA//+T
AP//lwn//7FK///RnP//3Lf//9u1///btf//3Lf//7ZW//+TAP//lAD//5QA//+TAP//oCD//9Wn///b
tvH/27XY/9mw//+nMv//kwD//5QA//+UAP//kwD//5wV///RnP//3Lf//9u1///btf//3Lj//8eD//+V
Bf//lAH//6Mm///FfP//2rL//9y3///btf//27X//9u1///Zr///qDL//5MA//+UAP//lAD//5MA//+n
Mv//2bD//9u12P/btav/3Lb//7RT//+TAP//lAD//5QA//+UAP//lAH//75q///cuP//27X//9u1///c
uP//yIT//5sS//+1VP//1KL//9y3///btf//27X//9u1///btf//3Lj//8uN//+ZDf//lAD//5QA//+U
AP//kwD//7RT///ctv//27Wr/9u1bP/cuPv/xoD//5YG//+UAP//lAD//5QA//+TAP//oSL//9Of///c
t///27X//9y2///RnP//yYj//9u0///ctv//27X//9u1///btf//27X//9u2///ZsP//rUH//5MA//+U
AP//lAD//5QA//+WBv//xoD//9y4+//btWz/27Uq/9u23v/WqP//oyf//5MA//+UAP//lAD//5QA//+U
AP//r0T//9es///ct///27X//9u2///ct///27X//9u1///btf//27X//9u1///btv//27T//7xl//+W
Bf//lAD//5QA//+UAP//kwD//6Mn///WqP//27be/9u1Kv/btQL/27WW/9y3//++a///lQL//5QA//+U
AP//lAD//5QA//+VA///sEf//9Sj///cuP//27b//9u1///btf//27X//9u1///btv//3Lj//9iu//+7
Yv//mAr//5QA//+UAP//lAD//5QA//+VAv//vmv//9y3///btZb/27UC/9u1AP/btTf/27bo/9ap//+n
Mf//kwD//5QA//+UAP//lAD//5QA//+UAf//oyf//8F0///UpP//2rT//9y3///ct///27X//9eq///I
hP//qzr//5UF//+UAP//lAD//5QA//+UAP//kwD//6cx///Wqf//27bp/9u1N//btQD/27UA/9u1Av/b
tYj/3Lf//8uM//+cFf//kwD//5QA//+UAP//lAD//5QA//+TAP//lQT//6Ae//+tP///tVT//7ZX//+w
Rv//oyf//5cJ//+TAP//lAD//5QA//+UAP//lAD//5MA//+cFf//y4z//9y3///btYn/27UC/9u1AAAA
AAD/27UA/9u1Gv/btcH/27b//8N4//+ZDv//kwD//5QA//+UAP//lAD//5QA//+UAP//kwD//5MA//+T
AP//kwD//5MA//+TAP//lAD//5QA//+UAP//lAD//5QA//+TAP//mQ7//8N4///btv//27XB/9u1Gv/b
tQAAAAAAAAAAAP/btQD/27UA/9u1Nf/btdj/27X//8N4//+cFf//kwD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//5wV///DeP//27X//9u12P/b
tTX/27UA/9u1AAAAAAAAAAAAAAAAAP/btQD/27UA/9u1P//btdj/27b//8uM//+nMf//lQP//5MA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//5UD//+nMf//y4z//9u2///b
tdj/27U//9u1AP/btQAAAAAAAAAAAAAAAAAAAAAAAAAAAP/btQD/27UA/9u1Nf/btcL/3Lf+/9ap//++
a///oyf//5YG//+TAP//kwD//5MA//+TAP//kwD//5MA//+TAP//kwD//5YG//+jJ///vmv//9ap///c
t/7/27XC/9u1Nf/btQD/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/btQD/27UA/9u1Gf/b
tYn/27bq/9y3///WqP//xoD//7RT//+nMv//oCD//50X//+dF///oCD//6cy//+0U///xoD//9ao///c
t///27bq/9u1if/btRn/27UA/9u1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD/27UA/9u1A//btTf/27WX/9u23//cuPv/3Lb//9mw///Vp///06D//9Og///Vp///2bD//9y2///c
uPv/27bf/9u1l//btTf/27UD/9u1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQT/27Up/9u1bP/btaz/27XZ/9u28f/ct/3/3Lf9/9u28f/b
tdn/27Ws/9u1bP/btSn/27UE/9u1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AB//4A
AH/8AAA/+AAAH/AAAA/gAAAHwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAcAAAAPgAAAH8AAAD/gAAB/8AAA//gAAf/+A
Af8oAAAAMAAAAGAAAAABACAAAAAAAAAkAADDDgAAww4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/27UA/9u1AP/btQ3/27U2/9u1bf/b
taP/27XL/9u15f/btfX/27X+/9u1/v/btfT/27Xk/9u1y//btaH/27Vs/9u1Nv/btQ3/27UA/9u1AAAA
AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAgAKgQAABGDgAAMDAAAAEA
IACoJQAA7h4AAAAAAAABACAAzhwAAJZEAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAADDDgAAww4AAAAA
AAAAAAAAAAAAAAAAAAD/lAAA/5QABf+UAEH/lACe/5QA3P+UAPX/lAD1/5QA3P+UAJ7/lABB/5QABf+U
AAAAAAAAAAAAAP+UAAD/lAAA/5QAFP+UAIn/lADr/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA6/+U
AIr/lAAU/5QAAP+UAAD/lAAA/5QAFP+UAKj/lAD+/5QA//+TAP//lgb//5oR//+aEf//lgf//5MA//+U
AP//lAD+/5QAqf+UABT/lAAA/5QABP+UAIn/lAD+/5QA//+WBv//qDb//7po///Be///wXz//7tq//+p
Ov//lwj//5QA//+UAP7/lACK/5QABP+UAEH/lADp/5QA//+WBv//sVD//8aK///KlP//x4z//8eN///I
jv//x4v//7NW//+XCP//lAD//5QA6f+UAEH/lACe/5QA//+TAP//qDf//8aK///Ijv//5Mj//926///J
kP//xov//8eM///Hi///qj7//5QA//+UAP//lACe/5QA2/+UAP//lgb//7pp///Ijv//yI3//+zZ///+
/v//7Nn//9Ki///HjP//yI7//71v//+XCf//lAD//5QA2/+UAPT/lAD//5oR///BfP//x43//8eN///s
2P/////////////58///373//8iP///CgP//nBb//5MA//+UAPT/lAD0/5QA//+aEf//wXv//8eN///H
jf//7Nj/////////////9u3//9u1///Ijv//wn///5wW//+TAP//lAD0/5QA2/+UAP//lgb//7ln///I
jv//x43//+zY///9/P//6dL//8+c///Gi///yI7//7xt//+XCP//lAD//5QA2/+UAJ3/lAD//5MA//+m
M///xoj//8iO///iw///27T//8iO///Gi///x43//8aK//+pOf//lAD//5QA//+UAJ3/lABB/5QA6f+U
AP//lQT//69J///GiP//ypL//8eN///Hjf//yI7//8aJ//+xT///lgb//5QA//+UAOn/lABB/5QABP+U
AIn/lAD+/5QA//+VBP//pS///7dh//+/dv//v3f//7hj//+mMv//lgX//5QA//+UAP7/lACJ/5QABP+U
AAD/lAAU/5QAqP+UAP7/lAD//5MA//+VBP//mQ3//5kN//+VBP//kwD//5QA//+UAP7/lACo/5QAFP+U
AAD/lAAA/5QAAP+UABT/lACJ/5QA6/+UAP//lAD//5QA//+UAP//lAD//5QA//+UAOv/lACJ/5QAFP+U
AAD/lAAAAAAAAAAAAAD/lAAA/5QABf+UAEH/lACe/5QA3P+UAPX/lAD1/5QA3P+UAJ7/lABB/5QABf+U
AAAAAAAAAAAAAOAHAADAAwAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACAAQAAwAMAAOAHAAAoAAAAGAAAADAAAAABACAAAAAAAAAJAADDDgAAww4AAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/lAAA/5QABP+UADD/lAB8/5QAvf+UAOP/lADz/5QA8/+UAOP/lAC9/5QAfP+U
ADD/lAAE/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAo/5QAk/+U
AOP/lAD9/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA/f+UAOP/lACT/5QAKf+UAAD/lAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/lAAA/5QAA/+UAFf/lADa/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA2v+UAFj/lAAD/5QAAAAAAAAAAAAAAAAAAP+UAAD/lAAD/5QAa/+U
AO//lAD//5QA//+UAP//lAD//5MA//+TAP//kwD//5MA//+TAP//kwD//5QA//+UAP//lAD//5QA//+U
APD/lABr/5QAA/+UAAAAAAAA/5QAAP+UAAD/lABY/5QA7/+UAP//lAD//5QA//+TAP//lQT//54c//+p
Of//r0r//69L//+qPP//nx///5YG//+TAP//lAD//5QA//+UAP//lADv/5QAWP+UAAD/lAAA/5QAAP+U
ACn/lADZ/5QA//+UAP//lAD//5QA//+eG///tVz//8OC///HjP//yI7//8iO///Hjf//xIT//7dh//+g
IP//lAH//5QA//+UAP//lAD//5QA2f+UACn/lAAA/5QAA/+UAJP/lAD//5QA//+UAP//lAD//6Mq///A
ef//yI7//8eM///Hi///x4z//8eM///HjP//x43//8iO///Cfv//pjL//5QA//+UAP//lAD//5QA//+U
AJP/lAAD/5QAMf+UAOL/lAD//5QA//+TAP//nhz//8B6///Ijv//x4z//9Wp///Qn///xov//8eM///H
jP//x4z//8eM///Ijv//wn///6Ek//+TAP//lAD//5QA//+UAOL/lAAx/5QAfP+UAP3/lAD//5QA//+V
BP//tlz//8iO///HjP//xov//+XK///48P//3br//8mR///Gi///x4z//8eM///HjP//yI7//7lm//+X
CP//lAD//5QA//+UAP3/lAB8/5QAvf+UAP//lAD//5MA//+fHv//xIP//8eN///HjP//xov//+XK////
/////vz//+3a///So///x4v//8eL///HjP//x4z//8WH//+iJ///kwD//5QA//+UAP//lAC8/5QA4v+U
AP//lAD//5MA//+qO///x43//8eM///HjP//xov//+XJ///////////////////58///4cL//8uU///H
i///x4z//8iO//+uR///kwD//5QA//+UAP//lADi/5QA8v+UAP//lAD//5MA//+vS///yI7//8eM///H
jP//xov//+XJ/////////////////////////v7///Hi///Rof//x4v//8iO//+zVv//lAD//5QA//+U
AP//lADy/5QA8v+UAP//lAD//5MA//+vSf//yI7//8eM///HjP//xov//+TI////////////////////
/////fv//+rU///Om///x4v//8iO//+zVf//lAD//5QA//+UAP//lADy/5QA4v+UAP//lAD//5MA//+p
OP//x4z//8eM///HjP//xov//+TH///////////////////16///27T//8iP///Hi///x4z//8iO//+t
RP//kwD//5QA//+UAP//lADi/5QAvP+UAP//lAD//5MA//+eG///w4H//8eN///HjP//xov//+TH////
/////Pn//+jQ///Om///xov//8eM///HjP//x4z//8WG//+hJP//kwD//5QA//+UAP//lAC8/5QAe/+U
AP3/lAD//5QA//+VA///s1f//8iO///HjP//xov//+PG///16v//2bH//8iO///Gi///x4z//8eM///H
jP//yI7//7dh//+WBv//lAD//5QA//+UAP3/lAB7/5QAMf+UAOL/lAD//5QA//+UAP//nBf//750///I
jv//x4z//9Ki///Omv//xor//8eM///HjP//x4z//8eM///Ijv//wXr//58e//+TAP//lAD//5QA//+U
AOL/lAAx/5QAA/+UAJL/lAD//5QA//+UAP//lAD//6Ah//++cv//yI7//8eM///Hi///x4z//8eM///H
jP//x43//8iO///AeP//oyn//5QA//+UAP//lAD//5QA//+UAJL/lAAD/5QAAP+UACj/lADY/5QA//+U
AP//lAD//5QA//+bFP//sVD//8F8///Giv//x43//8eN///Hi///wn7//7NW//+dGP//lAD//5QA//+U
AP//lAD//5QA2f+UACn/lAAA/5QAAP+UAAD/lABX/5QA7/+UAP//lAD//5QA//+UAP//lAL//5sU//+l
Lv//qz7//6s///+mMf//nBb//5UD//+TAP//lAD//5QA//+UAP//lADv/5QAWP+UAAD/lAAAAAAAAP+U
AAD/lAAD/5QAav+UAO//lAD//5QA//+UAP//lAD//5QA//+TAP//kwD//5MA//+TAP//lAD//5QA//+U
AP//lAD//5QA//+UAPD/lABr/5QAA/+UAAAAAAAAAAAAAAAAAAD/lAAA/5QAA/+UAFf/lADZ/5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA2v+UAFj/lAAD/5QAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAo/5QAk/+UAOP/lAD9/5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA/f+UAOP/lACT/5QAKP+UAAD/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD/lAAA/5QABP+UADD/lAB8/5QAvf+UAOP/lADz/5QA8/+UAOP/lAC9/5QAfP+UADD/lAAE/5QAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/AA/APgAHwDgAAcAwAADAMAAAwCAAAEAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAABAMAAAwDAAAMA4AAHAPgAHwD8AD8AKAAAACAA
AABAAAAAAQAgAAAAAAAAEAAAww4AAMMOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/5QAAP+UAAL/lAAd/5QAWv+UAJr/lADI/5QA5P+UAO//lADv/5QA5P+UAMj/lACa/5QAWv+U
AB7/lAAC/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/5QAAP+UAAH/lAAq/5QAh/+UANT/lAD3/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD4/5QA1P+UAIf/lAAr/5QAAv+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/5QAAP+UAAD/lAAS/5QAeP+UAOH/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAOH/lAB5/5QAEv+UAAD/lAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP+UAAD/lAAA/5QAKf+UALL/lAD8/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAPz/lACz/5QAKv+UAAD/lAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/lAAA/5QAAP+UADT/lADM/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5MA//+TAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lADN/5QANP+U
AAD/lAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAq/5QAzP+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//kwD//5UE//+ZDv//nBb//5wW//+aEP//lgX//5MA//+TAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lADN/5QAKv+UAAD/lAAAAAAAAAAAAAD/lAAA/5QAEv+UALL/lAD//5QA//+UAP//lAD//5QA//+U
AP//lAH//5wV//+rP///uGP//793///Cf///wn///8B5//+5Z///rUT//50a//+UAv//lAD//5QA//+U
AP//lAD//5QA//+UAP//lACz/5QAEv+UAAAAAAAA/5QAAP+UAAD/lAB4/5QA/f+UAP//lAD//5QA//+U
AP//lAD//5cI//+rPv//wHr//8eN///Ijv//x43//8eN///Hjf//x43//8iO///Hjf//wn7//65H//+Y
DP//kwD//5QA//+UAP//lAD//5QA//+UAP3/lAB5/5QAAP+UAAD/lAAA/5QALP+UAOD/lAD//5QA//+U
AP//lAD//5QA//+ZDv//tVr//8eL///Hjf//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jf//x4z//7hk//+bFf//kwD//5QA//+UAP//lAD//5QA//+UAOD/lAAs/5QAAP+UAAD/lACH/5QA//+U
AP//lAD//5QA//+UAP//lwj//7Va///Hjf//x4z//8eM///Lk///yZD//8aL///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//yI7//7lm//+ZDv//lAD//5QA//+UAP//lAD//5QA//+UAIf/lAAA/5QAHv+U
ANP/lAD//5QA//+UAP//lAD//5QA//+rQP//x4v//8eM///HjP//xor//9y2///r1f//0J///8aL///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//x43//7BO//+VAv//lAD//5QA//+UAP//lAD//5QA0/+U
AB7/lABa/5QA9/+UAP//lAD//5QA//+UAP//nBb//8B6///Hjf//x4z//8eM///Giv//3rr////////3
7///3rv//8qS///Gi///x4z//8eM///HjP//x4z//8eM///Hjf//w4L//6Ah//+TAP//lAD//5QA//+U
AP//lAD3/5QAWv+UAJr/lAD//5QA//+UAP//lAD//5MA//+sQf//x43//8eM///HjP//x4z//8aK///e
uv/////////////+/P//7tz//9Ol///HjP//x4v//8eM///HjP//x4z//8eM///Ijv//slH//5QA//+U
AP//lAD//5QA//+UAP//lACa/5QAyP+UAP//lAD//5QA//+UAP//lgX//7lm///Ijv//x4z//8eM///H
jP//xor//926////////////////////////+fT//+LD///Llf//xor//8eM///HjP//x4z//8iO//+9
cv//mAv//5QA//+UAP//lAD//5QA//+UAMj/lADj/5QA//+UAP//lAD//5QA//+aEP//wHn//8eN///H
jP//x4z//8eM///Giv//3bn//////////////////////////////v7///Hj///Wq///yI3//8eM///H
jP//x43//8OB//+dGv//kwD//5QA//+UAP//lAD//5QA4/+UAO//lAD//5QA//+UAP//kwD//5wW///C
f///x43//8eM///HjP//x4z//8aK///duf////////////////////////////////////////z4///k
x///yZD//8eM///HjP//xYb//6Ah//+TAP//lAD//5QA//+UAP//lADv/5QA7/+UAP//lAD//5QA//+U
AP//nBX//8J////Hjf//x4z//8eM///HjP//xor//924////////////////////////////////////
////9u3//9u2///Ijv//x4z//8eM///Fhv//oCH//5MA//+UAP//lAD//5QA//+UAO//lADj/5QA//+U
AP//lAD//5QA//+ZDv//v3f//8eN///HjP//x4z//8eM///Giv//3Lf/////////////////////////
/////Pr//+nR///PnP//xov//8eM///HjP//x43//8OA//+dGP//kwD//5QA//+UAP//lAD//5QA4/+U
AMj/lAD//5QA//+UAP//lAD//5UE//+4Yv//yI7//8eM///HjP//x4z//8aK///ct///////////////
//////////Xq///asv//yI7//8aL///HjP//x4z//8eM///Ijv//vG///5cJ//+UAP//lAD//5QA//+U
AP//lADI/5QAmv+UAP//lAD//5QA//+UAP//kwD//6o8///HjP//x4z//8eM///HjP//xor//9y3////
//////////z5///nzv//zpr//8aL///HjP//x4z//8eM///HjP//x4z//8iO//+vS///lAD//5QA//+U
AP//lAD//5QA//+UAJr/lABa/5QA9/+UAP//lAD//5QA//+UAP//mhH//791///Ijv//x4z//8eM///G
iv//27b////+///z5///2K///8iO///Hi///x4z//8eM///HjP//x4z//8eM///Hjf//wn7//54b//+T
AP//lAD//5QA//+UAP//lAD3/5QAWv+UAB7/lADT/5QA//+UAP//lAD//5QA//+UAP//qDf//8aI///H
jf//x4z//8aK///Yr///5cr//82Y///Giv//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eL//+t
Rf//lAH//5QA//+UAP//lAD//5QA//+UANP/lAAe/5QAAP+UAIb/lAD//5QA//+UAP//lAD//5QA//+V
Bf//sU///8eM///Hjf//x4z//8mQ///Ijf//x4v//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jf//tVv//5cJ//+UAP//lAD//5QA//+UAP//lAD//5QAhv+UAAD/lAAA/5QAK/+UAOD/lAD//5QA//+U
AP//lAD//5QA//+XCf//sEz//8WH///Ijv//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///I
jv//xor//7RX//+ZDf//lAD//5QA//+UAP//lAD//5QA//+UAOD/lAAr/5QAAP+UAAD/lAAA/5QAd/+U
APz/lAD//5QA//+UAP//lAD//5QA//+VBP//pjD//7xv///Giv//yI7//8iO///Ijf//yI3//8iO///I
jv//x4v//750//+pOf//lgf//5QA//+UAP//lAD//5QA//+UAP//lAD9/5QAeP+UAAD/lAAAAAAAAP+U
AAD/lAAS/5QAsf+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//mAz//6Uv//+zVf//u2z//791//+/
dv//vG7//7RZ//+nNf//mg///5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UALL/lAAS/5QAAAAA
AAAAAAAA/5QAAP+UAAD/lAAp/5QAy/+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//5QB//+X
B///mAz//5kN//+XCP//lAH//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lADM/5QAKf+U
AAD/lAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAz/5QAy/+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QAzP+U
ADT/lAAA/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAo/5QAsv+UAPz/lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA/P+U
ALP/lAAp/5QAAP+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAR/5QAd/+U
AOH/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AOH/lAB4/5QAEv+UAAD/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+U
AAD/lAAB/5QAKv+UAIf/lADU/5QA9/+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA+P+U
ANT/lACH/5QAK/+UAAH/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/lAAA/5QAAv+UAB3/lABa/5QAmv+UAMj/lADk/5QA7/+UAO//lADk/5QAyP+U
AJr/lABa/5QAHv+UAAL/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAH//gAAf/wA
AD/4AAAf8AAAD+AAAAfAAAADwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAHAAAADwAAAA+AAAAfwAAAP+AAAH/wAAD/+AAB//4AB/ygA
AAAwAAAAYAAAAAEAIAAAAAAAACQAAMMOAADDDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+UAAD/lAAA/5QABf+UACL/lABU/5QAif+U
AK//lADP/5QA3/+UAOn/lADp/5QA3/+UAND/lACw/5QAif+UAFT/lAAj/5QABv+UAAD/lAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQP/27Un/9u1c//b
tbz/27Xp/9u1/P/btf//27X//9u2///btv//3Lb//9y2///btv//27b//9u1///btf//27X8/9u16f/b
tbz/27Vz/9u1J//btQP/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/btQD/27UC/9u1Lf/b
tZD/27Xh/9u1/v/btf//3Lb//9y4///ct///2rP//9es///UpP//06D//9Og///UpP//16z//9qz///c
t///3Lj//9y2///btf//27X+/9u14f/btZD/27Ut/9u1Av/btQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/27UA/9u1AP/b
tRX/27V8/9u14v/btf//27X//9y3///btP//06H//8Z+//+3Wf//qzz//6Qo//+fHf//nRb//50W//+f
Hf//pCj//6s8//+3Wf//xn7//9Oh///btP//3Lf//9u1///btf//27Xi/9u1fP/btRX/27UA/9u1AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/b
tQD/27UA/9u1Ov/btb7/27X9/9u1///ct///2a///8mG//+xSv//nhv//5YF//+TAP//kwD//5MA//+T
AP//kwD//5MA//+TAP//kwD//5MA//+TAP//lgX//54b//+xSv//yYb//9mv///ct///27X//9u1/f/b
tb7/27U6/9u1AP/btQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/9u1AP/btQT/27Vc/9u14v/btf//3Lb//9q0///JiP//qzv//5gK//+TAP//kwD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+TAP//mAr//6s7///J
iP//2rT//9y2///btf//27Xi/9u1XP/btQT/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/27UA/9u1Bf/btXD/27Xw/9u1///ct///1KP//7RT//+ZDv//kwD//5QA//+U
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/lAAA/5QAAP+UABr/lABZ/5QApf+U
ANv/lAD2/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAPb/lADb/5QApv+U
AFn/lAAa/5QAAP+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAe/5QAdv+U
ANL/lAD7/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAPv/lADS/5QAdv+UAB7/lAAA/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+UAAD/lAAA/5QADP+U
AGH/lADS/5QA/f+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA/f+UANP/lABi/5QADf+UAAD/lAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+U
AAD/lAAn/5QAqP+UAPj/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD5/5QAqf+U
ACf/lAAA/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD/lAAA/5QAAP+UAEb/lADR/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5MA//+ZDv//tFP//9Sj///ct///27X//9u18P/btXD/27UF/9u1AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/btQD/27UE/9u1cP/btfT/27X//9y3///Mjv//pSv//5QB//+U
AP//lAD//5QA//+UANL/lABH/5QAAf+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP+UAAD/lAAC/5QAV/+UAOT/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAH//6Ur///Mjv//3Lf//9u1///btfT/27Vw/9u1BP/b
tQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQD/27Ve/9u18f/btf//27b//8eC//+e
Gv//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+eGv//x4L//9u2///b
tf//27Xx/9u1Xv/btQD/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAD/27UA/9u1AP/btTv/27Xi/9u1///c
t///x4L//5wV//+TAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+T
AP//nBX//8eC///ct///27X//9u14v/btTv/27UA/9u1AAAAAAAAAAAAAAAAAAAAAAD/27UA/9u1Fv/b
tb7/27X//9y3///Mj///nhr//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//kwD//5MA//+UAf//lQP//5UD//+UAf//kwD//5MA//+TAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//kwD//54a///Mjv//3Lf//9u1///btb7/27UW/9u1AAAAAAAAAAAAAAAAAP/b
tQD/27UA/9u1e//btf7/3Lb//9Sj//+lLP//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5MA//+YC///pSz//7RS//+/bf//xHz//8Z////BdP//uV7//6s8//+dF///lAL//5MA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+lLP//1KP//9y2///btf7/27V8/9u1AP/b
tQAAAAAAAAAAAP/btQD/27Ut/9u14P/btf//2rP//7RS//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+TAP//mQ7//7FL///Li///2K3//9y2///cuP//3Lj//9y4///cuP//3Lj//9qy///R
nP//vGf//6Eh//+UAf//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//tFL//9qz///b
tf//27Xh/9u1Lv/btQAAAAAA/9u1AP/btQL/27WR/9u1///ct///yYf//5kN//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QB//+mLf//yYj//9u0///ct///27b//9u1///btf//27X//9u1///b
tf//27X//9u1///ct///3Lf//9Og//+zUP//lwj//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//mQ3//8mH///ct///27X//9u1kf/btQL/27UA/9u1AP/btSj/27Xh/9u1///Zr///qzv//5MA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAL//65C///Uo///3Lj//9u1///btf//27X//9u1///b
tf//27X//9u1///btf//27X//9u1///btf//27X//9y3///asv//v23//5kO//+TAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//kwD//6s7///Zr///27X//9u14f/btSj/27UA/9u1AP/btXL/27X//9y3///J
h///mAr//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//rUD//9eq///ct///27X//9u1///b
tf//27b//9u2///btf//27X//9u1///btf//27X//9u1///btf//27X//9u1///btv//27b//8Bw//+Y
Cv//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5gK///Jhv//3Lf//9u1///btXL/27UA/9u1Df/b
tbv/27X//9u0//+xSv//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+jKP//06D//9y3///b
tf//27X//9u1///btf//1qf//9it///ct///27X//9u1///btf//27X//9u1///btf//27X//9u1///b
tf//27X//9q0//+2WP//lAH//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+xSv//27T//9u1///b
tbv/27UN/9u1Nv/bten/3Lb//9Oh//+eG///kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5gK///G
f///3Lj//9u1///btf//27X//9u1///cuP//wHD//6s8///Nkf//27b//9u2///btf//27X//9u1///b
tf//27X//9u1///btf//27X//9y2///Vpv//pCr//5MA//+UAP//lAD//5QA//+UAP//lAD//5MA//+e
G///06H//9y2///bten/27U2/9u1bP/btfz/3Lj//8Z///+WBf//lAD//5QA//+UAP//lAD//5QA//+U
AP//kwD//6w9///Zsf//27X//9u1///btf//27X//9u1///cuP//vmv//5MA//+cFP//umD//9Wn///c
t///27X//9u1///btf//27X//9u1///btf//27X//9u1///cuP//wnT//5UE//+UAP//lAD//5QA//+U
AP//lAD//5QA//+WBf//xn///9y4///btfz/27Vt/9u1of/btf//3Lf//7dZ//+TAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lgX//8V8///cuP//27X//9u1///btf//27X//9u1///cuP//vmv//5QA//+T
AP//lAL//6Ut///Hgv//2rP//9y3///btf//27X//9u1///btf//27X//9u1///btv//1ab//6Ej//+T
AP//lAD//5QA//+UAP//lAD//5QA//+TAP//t1n//9y3///btf//27Wi/9u1yv/btf//2rP//6s8//+T
AP//lAD//5QA//+UAP//lAD//5QA//+TAP//nx3//9Sj///btv//27X//9u1///btf//27X//9u1///c
uP//vmz//5QA//+UAP//lAD//5MA//+YC///sk7//9Kd///ct///27b//9u1///btf//27X//9u1///b
tf//27b//7NP//+TAP//lAD//5QA//+UAP//lAD//5QA//+TAP//qzz//9qz///btf//27XK/9u15P/b
tv//16z//6Qo//+TAP//lAD//5QA//+UAP//lAD//5QA//+TAP//qzv//9qy///btf//27X//9u1///b
tf//27X//9u1///cuP//v27//5QA//+UAP//lAD//5QA//+UAP//kwD//6Af///Acf//2K7//9y3///b
tf//27X//9u1///btf//3Lj//8J1//+VAf//lAD//5QA//+UAP//lAD//5QA//+TAP//pCj//9es///b
tv//27Xk/9u19f/btv//1KT//58c//+TAP//lAD//5QA//+UAP//lAD//5QA//+TAP//tVP//9y3///b
tf//27X//9u1///btf//27X//9u1///cuP//v2///5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+W
Bv//qzz//82Q///btP//27X//9u1///btf//3Lf//8uL//+XCf//lAD//5QA//+UAP//lAD//5QA//+T
AP//nx3//9Sk///btv//27X1/9u1/v/ctv//06D//50W//+TAP//lAD//5QA//+UAP//lAD//5QA//+T
AP//umH//9y4///btf//27X//9u1///btf//27X//9u1///cuP//v2///5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//kwD//5sS///BdP//27X//9u1///btf//3Lf//8+W//+aDv//lAD//5QA//+U
AP//lAD//5QA//+TAP//nRb//9Og///ctv//27X+/9u1/v/ctv//06D//50W//+TAP//lAD//5QA//+U
AP//lAD//5QA//+TAP//umH//9y4///btf//27X//9u1///btf//27X//9u1///cuP//wG///5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+TAP//lwj//69E///QmP//27X//9u1///btf//3Lf//8+W//+a
Dv//lAD//5QA//+UAP//lAD//5QA//+TAP//nRb//9Og///ctv//27X+/9u19f/btv//1KT//58d//+T
AP//lAD//5QA//+UAP//lAD//5QA//+TAP//tVP//9y3///btf//27X//9u1///btf//27X//9u1///c
uP//wHL//5QA//+UAP//lAD//5QA//+UAP//lAD//5QB//+hIv//w3f//9mx///ct///27X//9u1///b
tf//3Lf//8uL//+XCf//lAD//5QA//+UAP//lAD//5QA//+TAP//nx3//9Sk///btv//27X1/9u15P/b
tv//16z//6Qo//+TAP//lAD//5QA//+UAP//lAD//5QA//+TAP//qzv//9qy///btf//27X//9u1///b
tf//27X//9u1///cuP//wXL//5QA//+UAP//lAD//5QA//+TAP//mAv//7NP///Sn///3Lf//9u1///b
tf//27X//9u1///btf//3Lj//8J1//+VAf//lAD//5QA//+UAP//lAD//5QA//+TAP//pCj//9es///b
tv//27Xk/9u1yv/btf//2rP//6s8//+TAP//lAD//5QA//+UAP//lAD//5QA//+TAP//nxz//9Sj///b
tv//27X//9u1///btf//27X//9u1///cuP//wXL//5QA//+UAP//lAD//5QB//+kKf//xoH//9qz///c
t///27X//9u1///btf//27X//9u1///btf//27b//7NP//+TAP//lAD//5QA//+UAP//lAD//5QA//+T
AP//qzz//9qz///btf//27XK/9u1of/btf//3Lf//7dZ//+TAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lgX//8V8///cuP//27X//9u1///btf//27X//9u1///cuP//wXL//5QA//+TAP//mg///7dZ///V
pf//3Lf//9u1///btf//27X//9u1///btf//27X//9u1///btv//1ab//6Ej//+TAP//lAD//5QA//+U
AP//lAD//5QA//+TAP//t1n//9y3///btf//27Wh/9u1bP/btfz/3Lj//8Z///+WBf//lAD//5QA//+U
AP//lAD//5QA//+UAP//kwD//6w9///Zsf//27X//9u1///btf//27X//9u1///cuP//wXX//5UE//+n
Mv//yon//9u1///btv//27X//9u1///btf//27X//9u1///btf//27X//9u1///cuP//wnT//5UE//+U
AP//lAD//5QA//+UAP//lAD//5QA//+WBf//xn///9y4///btfz/27Vs/9u1Nv/bten/3Lb//9Oh//+e
G///kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5gK///Gf///3Lj//9u1///btf//27X//9u1///c
t///yIX//7tk///Wqf//3Lf//9u1///btf//27X//9u1///btf//27X//9u1///btf//27X//9y2///V
pv//pCr//5MA//+UAP//lAD//5QA//+UAP//lAD//5MA//+eG///06H//9y2///bten/27U2/9u1Df/b
tbv/27X//9u0//+xSv//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+jJ///06D//9y3///b
tf//27X//9u1///btf//2rL//9u1///btv//27X//9u1///btf//27X//9u1///btf//27X//9u1///b
tf//27X//9q0//+2V///lAH//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+xSv//27T//9u1///b
tbv/27UN/9u1AP/btXL/27X//9y3///Jh///mAr//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//rUD//9ap///ct///27X//9u1///btf//27X//9u1///btf//27X//9u1///btf//27X//9u1///b
tf//27X//9u1///btv//27X//8Bv//+YCv//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5gK///J
h///3Lf//9u1///btXL/27UA/9u1AP/btSf/27Xg/9u1///Zr///qzv//5MA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAL//65C///Uo///3Lj//9u1///btf//27X//9u1///btf//27X//9u1///b
tf//27X//9u1///btf//27X//9y3///asv//vmz//5kO//+TAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//kwD//6s7///Zr///27X//9u14P/btSf/27UA/9u1AP/btQH/27WQ/9u1///ct///yYf//5kN//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QB//+mLf//yYj//9u0///ct///27b//9u1///b
tf//27X//9u1///btf//27X//9u1///ct///3Lf//9Og//+zUP//lwj//5MA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//mQ3//8mH///ct///27X//9u1kP/btQH/27UAAAAAAP/btQD/27Ut/9u14P/b
tf//2rP//7RS//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//mQ7//7FL///K
i///2Kz//9y2///cuP//3Lj//9y4///cuP//3Lj//9qy///RnP//vGf//6Eh//+UAf//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//tFL//9qz///btf//27Xh/9u1Lv/btQAAAAAAAAAAAP/b
tQD/27UA/9u1e//btf3/3Lb//9Sj//+lLP//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5MA//+YC///pSz//7RS//+/bf//xHz//8Z////BdP//uV7//6s7//+dFv//lAL//5MA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+lLP//1KP//9y2///btf3/27V8/9u1AP/b
tQAAAAAAAAAAAAAAAAD/27UA/9u1Fv/btb3/27X//9y3///Mj///nhr//5MA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//5MA//+UAf//lQP//5UD//+UAf//kwD//5MA//+T
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//54a///Mjv//3Lf//9u1///b
tb3/27UW/9u1AAAAAAAAAAAAAAAAAAAAAAD/27UA/9u1AP/btTv/27Xh/9u1///ct///x4L//5wV//+T
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lADl/5QAWf+UAAL/lAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lABX/5QA6v+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//kwD//5MA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA6/+UAFn/lAAA/5QAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/lAAA/5QAAP+UAEf/lADk/5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//5MA//+VAv//mAr//5wW//+dGf//nRn//5wX//+Z
DP//lQT//5MA//+TAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AOX/lABH/5QAAP+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+UAAD/lAAA/5QAJ/+UANH/lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+VA///nRn//6o8//+2Xv//vXL//8J+///D
gf//w4H//8J///++dP//uGL//6xD//+fHv//lgb//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lADS/5QAKP+UAAD/lAAAAAAAAAAAAAAAAAAAAAAAAP+UAAD/lAAM/5QAp/+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAH//58f//+0WP//wn///8eM///I
jv//yI7//8eN///Hjf//x43//8eN///Ijf//yI7//8eN///Eg///uGL//6Mp//+VBP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QAqf+UAA3/lAAAAAAAAAAAAAAAAAAA/5QAAP+U
AAD/lABi/5QA+P+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+XCv//rUT//8J////I
jv//x43//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///Hjf//yI7//8SF//+y
Uv//mhH//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA+f+UAGP/lAAA/5QAAAAA
AAAAAAAA/5QAAP+UAB//lADS/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5sU//+3
YP//x4z//8eN///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eN///Hjf//vG3//58g//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
ANL/lAAf/5QAAAAAAAD/lAAA/5QAAP+UAHb/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+T
AP//mxX//7tr///Ijv//x4z//8eM///HjP//x4z//8eL///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//yI7//8B4//+gIv//kwD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAB2/5QAAP+UAAD/lAAA/5QAGv+UANH/lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+YCv//t2D//8iO///HjP//x4z//8eM///HjP//ypL//82Z///Gi///x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8iO//+9cP//mxX//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lADR/5QAGv+UAAD/lAAA/5QAWf+UAPv/lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QB//+uSP//x4z//8eM///HjP//x4z//8eM///Gi///0aD///Hj///c
uP//yZD//8aL///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///I
jv//tVz//5YG//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD7/5QAWf+UAAD/lAAF/5QApf+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//kwD//6Ag///DgP//x43//8eM///HjP//x4z//8eM///G
i///0aD///v2///9/P//7Nf//9Gh///Hi///x4v//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//xoj//6cz//+TAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QApf+U
AAX/lAAj/5QA2/+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lQP//7RZ///Ijv//x4z//8eM///H
jP//x4z//8eM///Gi///0aD///v2//////////////jx///gv///ypP//8aL///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//yI7//7xt//+YC///lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA2/+UACP/lABU/5QA9v+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//nhv//8OA///H
jf//x4z//8eM///HjP//x4z//8eM///Gi///0aD///v2///////////////////+/f//797//9Sn///H
jP//x4v//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8aJ//+lMP//kwD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA9v+UAFT/lACI/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+T
AP//rEH//8eN///HjP//x4z//8eM///HjP//x4z//8eM///Gi///0aD///v2////////////////////
//////////r1///jxv//zJf//8aK///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8iO//+0
V///lAH//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAIj/lACv/5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+VA///t2D//8iO///HjP//x4z//8eM///HjP//x4z//8eM///Gi///0J////r1////
/////////////////////////////////v//8uX//9iu///Ijv//xov//8eM///HjP//x4z//8eM///H
jP//x4z//8iO//++c///mAz//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAK//lADP/5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+YDP//vnT//8iN///HjP//x4z//8eM///HjP//x4z//8eM///G
i///0J7///r1//////////////////////////////////////////////z4///nzv//zpv//8aL///H
jP//x4z//8eM///HjP//x4z//8eN///Dgv//nhv//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AM//lADf/5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+cF///wn///8eN///HjP//x4z//8eM///H
jP//x4z//8eM///Gi///0J7///r1////////////////////////////////////////////////////
////9ev//9u1///JkP//x4z//8eM///HjP//x4z//8eM///Gif//oyn//5MA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAN//lADp/5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+dGf//w4H//8eN///H
jP//x4z//8eM///HjP//x4z//8eM///Gi///0J7///r1////////////////////////////////////
//////////////////////////38///p0f//y5T//8eM///HjP//x4z//8eM///Gif//pCv//5MA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAOn/lADp/5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+d
Gf//w4H//8eN///HjP//x4z//8eM///HjP//x4z//8eM///Gi///0J7///r1////////////////////
//////////////////////////////////////////bs///ct///yY///8eM///HjP//x4z//8eM///G
if//pCz//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAOn/lADf/5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+bFP//wX3//8eN///HjP//x4z//8eM///HjP//x4z//8eM///Gi///z53///n0////
///////////////////////////////////////////////8+v//6dH//8+c///Gi///x4z//8eM///H
jP//x4z//8eM///FiP//oif//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAN//lADP/5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+YCv//vXH//8iO///HjP//x4z//8eM///HjP//x4z//8eM///G
i///z5z///nz//////////////////////////////////////////////Tp///asv//yI7//8aL///H
jP//x4z//8eM///HjP//x4z//8eN///DgP//nRj//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AM//lACv/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+VAv//tVv//8iO///HjP//x4z//8eM///H
jP//x4z//8eM///Gi///z5z///nz///////////////////////////////////8+f//587//86a///G
i///x4z//8eM///HjP//x4z//8eM///HjP//x4z//8iO//+8bv//lwn//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAK//lACI/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//qTr//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///Gi///z5z///nz//////////////////////////7///Pn///Y
r///yI7//8eL///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8iO//+xUP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAIj/lABU/5QA9v+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//mxX//8F7///Hjf//x4z//8eM///HjP//x4z//8eM///Hi///z5z///nz///////////////////7
9///5cr//82Y///Gi///x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8WG//+i
Jv//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA9v+UAFT/lAAj/5QA2v+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAH//7BO///Ijf//x4z//8eM///HjP//x4z//8eM///Hi///zpv///jy////
//////7///Lk///WrP//x43//8eL///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//yI7//7hj//+WB///lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA2v+UACP/lAAF/5QApf+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5wX///Aef//yI3//8eM///HjP//x4z//8eM///H
i///zpv///ny///79v//48f//8yW///Giv//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eM///Hjf//xIT//6Io//+TAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QApP+U
AAX/lAAA/5QAWf+UAPv/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+pOv//xon//8eN///H
jP//x4z//8eM///Hi///zpr//+rU///Vqf//x4z//8eL///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//sE7//5UD//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD7/5QAWf+UAAD/lAAA/5QAGv+UANH/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+W
Bf//sU///8eM///HjP//x4z//8eM///HjP//yI7//8mR///Gi///x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8iO//+3Yf//mAz//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lADR/5QAGv+UAAD/lAAA/5QAAP+UAHb/lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//mAv//7Va///Hi///x43//8eM///HjP//x4z//8eM///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x43//7pp//+bFf//kwD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP7/lAB2/5QAAP+UAAAAAAAA/5QAAP+UAB//lADR/5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5cJ//+wTP//xYb//8iO///HjP//x4z//8eM///H
jP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eN///Giv//tVv//5oR//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UANH/lAAf/5QAAAAAAAAAAAAA/5QAAP+U
AAD/lABg/5QA+P+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+VBP//pTD//71x///H
jP//yI7//8eM///HjP//x4z//8eM///HjP//x4z//8eM///HjP//x4z//8eM///Ijf//yI3//8B5//+q
Pf//lwj//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA+P+UAGL/lAAA/5QAAAAA
AAAAAAAAAAAAAP+UAAD/lAAL/5QApv+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//kwD//5oQ//+sQf//vG7//8WH///Ijv//yI7//8iO///Ijv//yI7//8iO///Ijv//yI7//8aJ//+/
df//r0v//5wX//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QAqP+U
AAz/lAAAAAAAAAAAAAAAAAAAAAAAAP+UAAD/lAAA/5QAJv+UAND/lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//mAv//6In//+uR///tl7//7xv//++c///vnP//71x//+4
Yv//sEz//6Qt//+ZD///lAH//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lADR/5QAJ/+UAAD/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/lAAA/5QAAP+UAEX/lADj/5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+TAP//lQL//5cJ//+Y
C///mAv//5gK//+VA///lAD//5MA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAOP/lABG/5QAAP+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+U
AAD/lABV/5QA6f+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+TAP//nBX//8eC///c
t///27X//9u14f/btTv/27UA/9u1AAAAAAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQD/27Vc/9u18P/b
tf//27b//8eC//+eGv//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5MA//+e
Gv//x4L//9u2///btf//27Xw/9u1XP/btQD/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/b
tQD/27UD/9u1b//btfL/27X//9y3///Mjv//pSv//5QB//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA6v+UAFf/lAAA/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP+UAAD/lAAB/5QAVf+UAOP/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAH//6Ur///Mjv//3Lf//9u1///btfL/27Vv/9u1A//btQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD/27UA/9u1Bf/btW7/27Xw/9u1///ct///1KP//7VT//+ZDv//kwD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lADk/5QAV/+UAAL/lAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/lAAA/5QAAP+UAEX/lADR/5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5MA//+ZDv//tVP//9Sj///ct///27X//9u18P/btW7/27UF/9u1AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQT/27Vc/9u14v/btf//3Lb//9u0///J
iP//qzv//5gK//+TAP//kwD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5MA//+TAP//mAr//6s7///JiP//27T//9y2///btf//27Xi/9u1XP/btQT/27UAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/btQD/27UA/9u1Ov/b
tb7/27X9/9u1///ct///2a///8mG//+xSv//nhv//5YF//+TAP//kwD//5MA//+TAP//kwD//5MA//+T
AP//kwD//5MA//+TAP//lgX//54b//+xSv//yYb//9mv///ct///27X//9u1/f/btb7/27U6/9u1AP/b
tQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD/27UA/9u1AP/btRX/27V8/9u14v/btf//27X//9y3///btP//06H//8Z+//+3Wf//qzz//6Qo//+f
HP//nRb//50W//+fHf//pCj//6s8//+3Wf//xn7//9Oh///btP//3Lf//9u1///btf//27Xi/9u1fP/b
tRX/27UA/9u1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/btQD/27UC/9u1Lf/btZD/27Xh/9u1/v/btf//3Lb//9y4///c
t///2rP//9es///UpP//06D//9Og///UpP//16z//9qz///ct///3Lj//9y2///btf//27X+/9u14f/b
tZD/27Ut/9u1Av/btQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9u1AP/btQP/27Un/9u1c//b
tbz/27Xp/9u1/P/btf//27X//9u2///btv//3Lb//9y2///btv//27b//9u1///btf//27X8/9u16f/b
tbz/27Vz/9u1J//btQP/27UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UANL/lABH/5QAAf+UAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAm/5QApv+U
APj/lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD4/5QAqP+UACf/lAAA/5QAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+U
AAD/lAAA/5QAC/+UAGD/lADS/5QA/f+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA/f+UANP/lABh/5QADP+U
AAD/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/5QAAP+UAAD/lAAe/5QAdv+UANL/lAD7/5QA//+UAP//lAD//5QA//+U
AP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAPv/lADS/5QAdv+U
AB7/lAAA/5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/lAAA/5QAAP+UABr/lABZ/5QApf+U
ANv/lAD2/5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAPb/lADb/5QApv+U
AFn/lAAa/5QAAP+UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+U
AAD/lAAA/5QABf+UACL/lABU/5QAif+UAK//lADP/5QA3/+UAOn/lADp/5QA3/+UAND/lACw/5QAif+U
AFT/lAAj/5QABv+UAAD/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD//wAA//8AAP/8AAA//wAA//AAAA//AAD/wAAAA/8AAP+AAAAB/wAA/wAAAAB/
AAD8AAAAAD8AAPwAAAAAPwAA+AAAAAAfAADwAAAAAA8AAOAAAAAABwAA4AAAAAAHAADAAAAAAAMAAMAA
AAAAAwAAgAAAAAABAACAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
</value>
</data>
</root>

View File

@@ -17,13 +17,13 @@ namespace mpvnet
{
public class App
{
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(" ".ToCharArray());
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(" ".ToCharArray());
public static bool IsDarkMode {
get {
string darkMode = MainForm.Instance.MpvNetDarkMode;
object value = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1);
if (value is null) value = 1;
bool isDarkTheme = (int)value == 0;
return (darkMode == "system" && isDarkTheme) || darkMode == "always";
return (darkMode == "system" && Sys.IsDarkTheme) || darkMode == "always";
}
}
}
@@ -51,12 +51,6 @@ namespace mpvnet
{ }
return false;
}
public static string GetFilter()
{
string[] fileTypes = "264 265 3gp aac ac3 avc avi avs bmp divx dts dtshd dtshr dtsma eac3 evo flac flv h264 h265 hevc hvc jpg jpeg m2t m2ts m2v m4a m4v mka mkv mlp mov mp2 mp3 mp4 mpa mpeg mpg mpv mts ogg ogm opus pcm png pva raw rmvb thd thd+ac3 true-hd truehd ts vdr vob vpy w64 wav webm wmv y4m".Split(' ');
return "*." + String.Join(";*.", fileTypes) + "|*." + String.Join(";*.", fileTypes) + "|All Files|*.*";
}
}
public class StringLogicalComparer : IComparer, IComparer<string>
@@ -76,8 +70,6 @@ namespace mpvnet
static string ExeFilename = Path.GetFileName(Application.ExecutablePath);
static string ExeFilenameNoExt = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
static string[] Types;
public static string[] VideoTypes = "mpg avi vob mp4 mkv avs 264 mov wmv flv h264 asf webm mpeg mpv y4m avc hevc 265 h265 m2v m2ts vpy mts webm m4v".Split(" ".ToCharArray());
public static string[] AudioTypes = "mp2 mp3 ac3 wav w64 m4a dts dtsma dtshr dtshd eac3 thd thd+ac3 ogg mka aac opus flac mpa".Split(" ".ToCharArray());
public static void Register(string[] types)
{
@@ -96,9 +88,9 @@ namespace mpvnet
RegistryHelp.SetObject($"HKCR\\Applications\\{ExeFilename}\\SupportedTypes", "." + ext, "");
RegistryHelp.SetObject($"HKCR\\" + "." + ext, null, ExeFilenameNoExt + "." + ext);
RegistryHelp.SetObject($"HKCR\\" + "." + ext + "\\OpenWithProgIDs", ExeFilenameNoExt + "." + ext, "");
if (VideoTypes.Contains(ext))
if (App.VideoTypes.Contains(ext))
RegistryHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "video");
if (AudioTypes.Contains(ext))
if (App.AudioTypes.Contains(ext))
RegistryHelp.SetObject($"HKCR\\" + "." + ext, "PerceivedType", "audio");
RegistryHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open", null, "Play with " + Application.ProductName);
RegistryHelp.SetObject($"HKCR\\" + ExeFilenameNoExt + "." + ext + "\\shell\\open\\command", null, $"\"{ExePath}\" \"%1\"");
@@ -180,7 +172,6 @@ namespace mpvnet
public int ID { get; set; }
}
[Serializable]
public class CommandItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
@@ -207,30 +198,26 @@ namespace mpvnet
}
}
private static ObservableCollection<CommandItem> _Items;
public static ObservableCollection<CommandItem> Items {
get {
if (_Items is null)
public static ObservableCollection<CommandItem> GetItems(string content)
{
_Items = new ObservableCollection<CommandItem>();
var items = new ObservableCollection<CommandItem>();
if (File.Exists(mp.InputConfPath))
if (!string.IsNullOrEmpty(content))
{
foreach (string line in File.ReadAllLines(mp.InputConfPath))
foreach (string line in content.Split('\r', '\n'))
{
string val = line.Trim();
if (val.StartsWith("#")) continue;
if (!val.Contains(" ")) continue;
CommandItem item = new CommandItem();
item.Input = val.Substring(0, val.IndexOf(" ")).Replace("_", "");
item.Input = val.Substring(0, val.IndexOf(" "));
if (item.Input == "_") item.Input = "";
val = val.Substring(val.IndexOf(" ") + 1);
if (val.Contains("#menu:"))
{
item.Path = val.Substring(val.IndexOf("#menu:") + 6).Trim();
val = val.Substring(0, val.IndexOf("#menu:"));
if (item.Path.Contains(";"))
item.Path = item.Path.Substring(item.Path.IndexOf(";") + 1).Trim();
}
@@ -240,13 +227,41 @@ namespace mpvnet
continue;
if (item.Command.ToLower() == "ignore")
item.Command = "";
_Items.Add(item);
MigrateCommands(item);
items.Add(item);
}
}
return items;
}
private static ObservableCollection<CommandItem> _Items;
public static ObservableCollection<CommandItem> Items {
get {
if (_Items is null)
_Items = GetItems(File.ReadAllText(mp.InputConfPath));
return _Items;
}
}
public static void MigrateCommands(CommandItem item)
{
switch (item.Command)
{
case "script-message mpv.net show-prefs":
item.Command = "script-message mpv.net show-conf-editor";
break;
case "script-message mpv.net show-keys":
item.Command = "script-message mpv.net show-input-editor";
break;
case "script-message mpv.net history":
item.Command = "script-message mpv.net show-history";
break;
case "script-message mpv.net open-config-folder":
item.Command = "script-message open-conf-folder";
break;
}
}
}
public class CursorHelp

View File

@@ -24,12 +24,23 @@ namespace mpvnet
[DllImport("user32.dll")]
public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowLongPtrW(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
private static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);
public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
{
if (IntPtr.Size == 8)
return GetWindowLong64(hWnd, nIndex);
else
return GetWindowLong32(hWnd, nIndex);
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{

View File

@@ -32,7 +32,7 @@ namespace mpvnet
public static void AddWindowBorders(IntPtr hwnd, ref Native.RECT rc)
{
Native.AdjustWindowRect(ref rc, (uint)Native.GetWindowLongPtrW(hwnd, -16 /* GWL_STYLE */), false);
Native.AdjustWindowRect(ref rc, (uint)Native.GetWindowLongPtr(hwnd, -16 /* GWL_STYLE */), false);
}
}
}

View File

@@ -5,8 +5,6 @@ using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Threading.Tasks;
using Sys;
namespace mpvnet
{
public class PowerShellScript

View File

@@ -1,8 +1,6 @@
using System;
using System.Windows.Forms;
using Sys;
namespace mpvnet
{
static class Program
@@ -16,9 +14,9 @@ namespace mpvnet
if (args.Length == 3 && args[1] == "--reg-file-assoc")
{
if (args[2] == "audio") FileAssociation.Register(FileAssociation.AudioTypes);
if (args[2] == "video") FileAssociation.Register(FileAssociation.VideoTypes);
if (args[2] == "unregister") FileAssociation.Unregister();
if (args[2] == "audio") FileAssociation.Register(App.AudioTypes);
if (args[2] == "video") FileAssociation.Register(App.VideoTypes);
if (args[2] == "unreg") FileAssociation.Unregister();
return;
}

View File

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

View File

@@ -1,10 +1,12 @@
using System;
using System.Reflection;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
using Sys;
using PyRT = IronPython.Runtime;
using IronPython.Runtime;
using IronPython.Runtime.Operations;
namespace mpvnet
{
@@ -22,11 +24,15 @@ namespace mpvnet
scope.ImportModule("clr");
engine.Execute("import clr", scope);
engine.Execute("clr.AddReference(\"mpvnet\")", scope);
engine.Execute("import mpvnet", scope);
engine.Execute("from mpvnet import *", scope);
engine.Execute(code, scope);
}
catch (Exception ex)
{
if (ex is SyntaxErrorException e)
Msg.ShowError($"{e.Line}, {e.Column}: " + ex.Message);
else
Msg.ShowException(ex);
}
}
@@ -34,23 +40,20 @@ namespace mpvnet
public class PythonEventObject
{
public PyRT.PythonFunction PythonFunction { get; set; }
public PythonFunction PythonFunction { get; set; }
public EventInfo EventInfo { get; set; }
public Delegate Delegate { get; set; }
public void Invoke()
{
PyRT.Operations.PythonCalls.Call(PythonFunction);
}
public void Invoke() => PythonCalls.Call(PythonFunction);
public void InvokeEndFileEventMode(EndFileEventMode arg)
{
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
PythonCalls.Call(PythonFunction, new[] { arg });
}
public void InvokeStrings(string[] arg)
{
PyRT.Operations.PythonCalls.Call(PythonFunction, new[] { arg });
PythonCalls.Call(PythonFunction, new[] { arg });
}
}
}

View File

@@ -26,6 +26,7 @@
o script-message mpv.net open-files #menu: Open > Open Files...
u script-message mpv.net open-url #menu: Open > Open URL...
Ctrl+S script-message mpv.net show-media-search #menu: Open > Show media search...
_ ignore #menu: Open > -
Alt+a script-message mpv.net load-audio #menu: Open > Load external audio files...
Alt+s script-message mpv.net load-sub #menu: Open > Load external subtitle files...
@@ -90,8 +91,8 @@
KP7 script-message mpv.net cycle-audio #menu: Audio > Cycle/Next
_ ignore #menu: Audio > -
KP6 add audio-delay 0.100 #menu: Audio > Delay +0.1
KP9 add audio-delay -0.100 #menu: Audio > Delay -0.1
KP6 add audio-delay 0.1 #menu: Audio > Delay +0.1
KP9 add audio-delay -0.1 #menu: Audio > Delay -0.1
KP8 cycle sub #menu: Subtitle > Cycle/Next
v cycle sub-visibility #menu: Subtitle > Toggle Visibility
@@ -112,7 +113,7 @@
_ ignore #menu: Volume > -
m cycle mute #menu: Volume > Mute
[ multiply speed 0.9 #menu: Speed > -10%
[ multiply speed 1/1.1 #menu: Speed > -10%
] multiply speed 1.1 #menu: Speed > +10%
_ ignore #menu: Speed > -
{ multiply speed 0.5 #menu: Speed > Half
@@ -146,6 +147,7 @@
L cycle-values loop-file "inf" "no" #menu: Tools > Toggle infinite file looping
Ctrl+h cycle-values hwdec "auto" "no" #menu: Tools > Cycle Hardware Decoding
_ script-message mpv.net execute-mpv-command #menu: Tools > Execute mpv command...
_ script-message mpv.net manage-file-associations #menu: Tools > Manage File Associations...
_ script-message mpv.net shell-execute https://mpv.io/manual/stable/ #menu: Help > Show mpv manual
_ script-message mpv.net shell-execute https://github.com/mpv-player/mpv/blob/master/etc/input.conf #menu: Help > Show mpv default keys
@@ -174,3 +176,5 @@
Wheel_Down add volume -10
Prev playlist-prev
Next playlist-next
MBTN_LEFT_DBL cycle fullscreen

View File

@@ -1,659 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
namespace Sys
{
public class Msg
{
private static string ShownMessages;
public static string SupportURL { get; set; }
public static void Show(string mainInstruction, string content = null)
{
Msg.Show(mainInstruction, content, MsgIcon.Info, MsgButtons.Ok, MsgResult.None);
}
public static void ShowError(string mainInstruction, string content = null)
{
try
{
using (TaskDialog<string> td = new TaskDialog<string>())
{
td.AllowCancel = false;
if (string.IsNullOrEmpty(content))
{
if (mainInstruction.Length < 80)
td.MainInstruction = mainInstruction;
else
td.Content = mainInstruction;
}
else
{
td.MainInstruction = mainInstruction;
td.Content = content;
}
td.MainIcon = MsgIcon.Error;
td.Footer = "[Copy Message](copymsg)";
if (!string.IsNullOrEmpty(Msg.SupportURL))
td.Footer += $" [Contact Support]({SupportURL})";
td.Show();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public static void ShowException(Exception e)
{
try
{
using (TaskDialog<string> td = new TaskDialog<string>())
{
td.MainInstruction = e.GetType().Name;
td.Content = e.Message;
td.MainIcon = MsgIcon.Error;
td.ExpandedInformation = e.ToString();
td.Footer = "[Copy Message](copymsg)";
if (!string.IsNullOrEmpty(Msg.SupportURL))
td.Footer += $" [Contact Support]({SupportURL})";
td.Show();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public static void ShowWarning(string mainInstruction,
string content = null,
bool onlyOnce = false)
{
if (onlyOnce && Msg.ShownMessages != null &&
Msg.ShownMessages.Contains(mainInstruction + content))
return;
Msg.Show(mainInstruction, content, MsgIcon.Warning, MsgButtons.Ok, MsgResult.None);
if (!onlyOnce) return;
Msg.ShownMessages += mainInstruction + content;
}
public static MsgResult ShowQuestion(string mainInstruction,
MsgButtons buttons = MsgButtons.OkCancel)
{
return Msg.Show(mainInstruction, null, MsgIcon.None, buttons, MsgResult.None);
}
public static MsgResult ShowQuestion(string mainInstruction,
string content,
MsgButtons buttons = MsgButtons.OkCancel)
{
return Msg.Show(mainInstruction, content, MsgIcon.None, buttons, MsgResult.None);
}
public static MsgResult Show(string mainInstruction,
string content,
MsgIcon icon,
MsgButtons buttons,
MsgResult defaultButton = MsgResult.None)
{
try
{
using (TaskDialog<MsgResult> td = new TaskDialog<MsgResult>())
{
td.AllowCancel = false;
td.DefaultButton = defaultButton;
td.MainIcon = icon;
if (content == null)
{
if (mainInstruction.Length < 80)
td.MainInstruction = mainInstruction;
else
td.Content = mainInstruction;
}
else
{
td.MainInstruction = mainInstruction;
td.Content = content;
}
if (buttons == MsgButtons.OkCancel)
{
td.AddButton("OK", MsgResult.OK);
td.AddButton("Cancel", MsgResult.Cancel);
}
else
td.CommonButtons = buttons;
return td.Show();
}
}
catch (Exception ex)
{
return (MsgResult)MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public class TaskDialog<T> : TaskDialogNative, IDisposable
{
private Dictionary<int, T> IdValueDic;
private Dictionary<int, string> IdTextDic;
private List<int> CommandLinkShieldList;
private IntPtr ButtonArray;
private IntPtr RadioButtonArray;
private List<TaskDialogNative.TASKDIALOG_BUTTON> Buttons;
private List<TaskDialogNative.TASKDIALOG_BUTTON> RadioButtons;
private TaskDialogNative.TASKDIALOGCONFIG Config;
const int TDE_CONTENT = 0;
const int TDE_EXPANDED_INFORMATION = 1;
const int TDE_FOOTER = 2;
const int TDE_MAIN_INSTRUCTION = 3;
const int TDN_CREATED = 0;
const int TDN_NAVIGATED = 1;
const int TDN_BUTTON_CLICKED = 2;
const int TDN_HYPERLINK_CLICKED = 3;
const int TDN_TIMER = 4;
const int TDN_DESTROYED = 5;
const int TDN_RADIO_BUTTON_CLICKED = 6;
const int TDN_DIALOG_CONSTRUCTED = 7;
const int TDN_VERIFICATION_CLICKED = 8;
const int TDN_HELP = 9;
const int TDN_EXPANDO_BUTTON_CLICKED = 10;
const int TDM_NAVIGATE_PAGE = 1125;
const int TDM_CLICK_BUTTON = 1126;
const int TDM_SET_MARQUEE_PROGRESS_BAR = 1127;
const int TDM_SET_PROGRESS_BAR_STATE = 1128;
const int TDM_SET_PROGRESS_BAR_RANGE = 1129;
const int TDM_SET_PROGRESS_BAR_POS = 1130;
const int TDM_SET_PROGRESS_BAR_MARQUEE = 1131;
const int TDM_SET_ELEMENT_TEXT = 1132;
const int TDM_CLICK_RADIO_BUTTON = 1134;
const int TDM_ENABLE_BUTTON = 1135;
const int TDM_ENABLE_RADIO_BUTTON = 1136;
const int TDM_CLICK_VERIFICATION = 1137;
const int TDM_UPDATE_ELEMENT_TEXT = 1138;
const int TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = 1139;
const int TDM_UPDATE_ICON = 1140;
private T SelectedValueValue;
private string SelectedTextValue;
private int TimeoutValue;
private int ExitTickCount;
private bool disposed;
public TaskDialog()
{
IdValueDic = new Dictionary<int, T>();
IdTextDic = new Dictionary<int, string>();
CommandLinkShieldList = new List<int>();
Buttons = new List<TaskDialogNative.TASKDIALOG_BUTTON>();
RadioButtons = new List<TaskDialogNative.TASKDIALOG_BUTTON>();
_SelectedID = -1;
Config = new TaskDialogNative.TASKDIALOGCONFIG();
Config.cbSize = (uint)Marshal.SizeOf(Config);
Config.hwndParent = GetHandle();
Config.hInstance = IntPtr.Zero;
Config.dwFlags = TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
Config.dwCommonButtons = MsgButtons.None;
Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0);
Config.FooterIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0);
Config.cxWidth = 0U;
Config.cButtons = 0U;
Config.cRadioButtons = 0U;
Config.pButtons = IntPtr.Zero;
Config.pRadioButtons = IntPtr.Zero;
Config.nDefaultButton = 0;
Config.nDefaultRadioButton = 0;
Config.pszWindowTitle = ((AssemblyProductAttribute)Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0]).Product;
Config.pszMainInstruction = "";
Config.pszContent = "";
Config.pfCallback = new PFTASKDIALOGCALLBACK(this.DialogProc);
}
public IntPtr GetHandle()
{
StringBuilder lpszFileName = new StringBuilder(260);
IntPtr foregroundWindow = TaskDialogNative.GetForegroundWindow();
TaskDialogNative.GetWindowModuleFileName(foregroundWindow, lpszFileName, 260U);
if (Path.GetFileName(lpszFileName.ToString().Replace(".vshost", "")) ==
Path.GetFileName(Assembly.GetEntryAssembly().Location))
return foregroundWindow;
return IntPtr.Zero;
}
public bool AllowCancel {
set {
if (value)
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
else
Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
}
}
public string MainInstruction {
get => Config.pszMainInstruction;
set => Config.pszMainInstruction = value;
}
public string Content {
get => Config.pszContent;
set => Config.pszContent = ExpandMarkdownMarkup(value);
}
public string ExpandedInformation {
get => Config.pszExpandedInformation;
set => Config.pszExpandedInformation = ExpandMarkdownMarkup(value);
}
public string VerificationText {
get => Config.pszVerificationText;
set => Config.pszVerificationText = value;
}
public MsgResult DefaultButton {
get => (MsgResult)Config.nDefaultButton;
set => Config.nDefaultButton = (int)value;
}
public string Footer {
get => Config.pszFooter;
set => Config.pszFooter = ExpandMarkdownMarkup(value);
}
public MsgIcon MainIcon {
set => Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION((int)value);
}
private int _SelectedID;
public int SelectedID {
get => _SelectedID;
set {
foreach (var i in IdValueDic)
if (i.Key == value) _SelectedID = value;
}
}
public T SelectedValue {
get {
if (IdValueDic.ContainsKey(SelectedID))
return IdValueDic[SelectedID];
return SelectedValueValue;
}
set => SelectedValueValue = value;
}
public string SelectedText {
get {
if (IdTextDic.ContainsKey(SelectedID))
return IdTextDic[SelectedID];
return SelectedTextValue;
}
set => SelectedTextValue = value;
}
public bool CheckBoxChecked {
get => (Config.dwFlags & TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) == TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
set {
if (value)
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
else
Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
}
}
public MsgButtons CommonButtons {
get => Config.dwCommonButtons;
set => Config.dwCommonButtons = value;
}
public int Timeout {
get => Convert.ToInt32(TimeoutValue / 1000.0);
set {
TimeoutValue = value * 1000;
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER;
}
}
public void AddButton(string text, T value)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value;
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
}
public string ExpandMarkdownMarkup(string value)
{
if (value.Contains("["))
{
Regex regex = new Regex(@"\[(.+)\]\((.+)\)");
if (regex.Match(value).Success)
{
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS;
value = regex.Replace(value, "<a href=\"$2\">$1</a>");
}
}
return value;
}
public void AddCommandLink(string text, T value)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value == null ? (T)(object)text : value;
IdTextDic[n] = text;
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
}
public void AddCommandLink(string text, string description, T value, bool setShield = false)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value;
if (setShield) CommandLinkShieldList.Add(n);
if (!string.IsNullOrEmpty(description)) text += "\n" + description;
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
}
public void AddRadioButton(string text, T value)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value;
RadioButtons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
}
public T Show()
{
MarshalDialogControlStructs();
TaskDialogNative.TASKDIALOGCONFIG config = Config;
int errorCode = TaskDialogNative.TaskDialogIndirect(config, out int dummy1, out int dummy2, out bool isChecked);
if (errorCode < 0) Marshal.ThrowExceptionForHR(errorCode);
CheckBoxChecked = isChecked;
if (SelectedValue is MsgResult) SelectedValue = (T)(object)SelectedID;
return SelectedValue;
}
public int DialogProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, IntPtr lpRefData)
{
switch (msg)
{
case 0: //TDN_CREATED
foreach (var i in CommandLinkShieldList)
SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, new IntPtr(i), new IntPtr(1));
break;
case 2: //TDN_BUTTON_CLICKED
case 6: //TDN_RADIO_BUTTON_CLICKED
if (SelectedValue is MsgResult)
_SelectedID = wParam.ToInt32();
else
SelectedID = wParam.ToInt32();
break;
case 3: //TDN_HYPERLINK_CLICKED
string stringUni = Marshal.PtrToStringUni(lParam);
if (stringUni.StartsWith("mailto") || stringUni.StartsWith("http"))
Process.Start(stringUni);
if (stringUni == "copymsg")
{
Thread thread = new Thread((ThreadStart)(() => {
Clipboard.SetText(MainInstruction + "\r\n\r\n" + Content + "\r\n\r\n" + ExpandedInformation);
MessageBox.Show("Message was copied to clipboard.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
break;
case 4: //TDN_TIMER
if (ExitTickCount == 0) ExitTickCount = Environment.TickCount + Timeout * 1000;
if (Environment.TickCount > ExitTickCount)
TaskDialogNative.SendMessage(hwnd, 1126, new IntPtr(1), IntPtr.Zero);
break;
}
return 0;
}
public void MarshalDialogControlStructs()
{
if (Buttons != null && Buttons.Count > 0)
{
ButtonArray = TaskDialog<T>.AllocateAndMarshalButtons(Buttons);
Config.pButtons = ButtonArray;
Config.cButtons = (uint)Buttons.Count;
}
if (RadioButtons == null || RadioButtons.Count <= 0) return;
RadioButtonArray = TaskDialog<T>.AllocateAndMarshalButtons(RadioButtons);
Config.pRadioButtons = RadioButtonArray;
Config.cRadioButtons = (uint)RadioButtons.Count;
}
public static IntPtr AllocateAndMarshalButtons(List<TaskDialogNative.TASKDIALOG_BUTTON> structs)
{
var initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TASKDIALOG_BUTTON)) * structs.Count);
var currentPtr = initialPtr;
foreach (var button in structs)
{
Marshal.StructureToPtr(button, currentPtr, false);
currentPtr = (IntPtr)(currentPtr.ToInt64() + Marshal.SizeOf(button));
}
return initialPtr;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~TaskDialog()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;
if (ButtonArray != IntPtr.Zero)
{
Marshal.FreeHGlobal(ButtonArray);
ButtonArray = IntPtr.Zero;
}
if (RadioButtonArray != IntPtr.Zero)
{
Marshal.FreeHGlobal(RadioButtonArray);
RadioButtonArray = IntPtr.Zero;
}
}
}
public delegate int PFTASKDIALOGCALLBACK(
IntPtr hwnd,
uint msg,
IntPtr wParam,
IntPtr lParam,
IntPtr lpRefData);
public class TaskDialogNative
{
[DllImport("comctl32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int TaskDialogIndirect(
[In] TaskDialogNative.TASKDIALOGCONFIG pTaskConfig,
out int pnButton,
out int pnRadioButton,
[MarshalAs(UnmanagedType.Bool)] out bool pVerificationFlagChecked);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern uint GetWindowModuleFileName(
IntPtr hwnd,
StringBuilder lpszFileName,
uint cchFileNameMax);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(
IntPtr handle,
int message,
IntPtr wParam,
IntPtr lParam);
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
public class TASKDIALOGCONFIG
{
public uint cbSize;
public IntPtr hwndParent;
public IntPtr hInstance;
public TaskDialogNative.TASKDIALOG_FLAGS dwFlags;
public MsgButtons dwCommonButtons;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszWindowTitle;
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION MainIcon;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszMainInstruction;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszContent;
public uint cButtons;
public IntPtr pButtons;
public int nDefaultButton;
public uint cRadioButtons;
public IntPtr pRadioButtons;
public int nDefaultRadioButton;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszVerificationText;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszExpandedInformation;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszExpandedControlText;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszCollapsedControlText;
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION FooterIcon;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszFooter;
public PFTASKDIALOGCALLBACK pfCallback;
public IntPtr lpCallbackData;
public uint cxWidth;
}
public enum TASKDIALOG_FLAGS
{
NONE = 0,
TDF_ENABLE_HYPERLINKS = 1,
TDF_USE_HICON_MAIN = 2,
TDF_USE_HICON_FOOTER = 4,
TDF_ALLOW_DIALOG_CANCELLATION = 8,
TDF_USE_COMMAND_LINKS = 16,
TDF_USE_COMMAND_LINKS_NO_ICON = 32,
TDF_EXPAND_FOOTER_AREA = 64,
TDF_EXPANDED_BY_DEFAULT = 128,
TDF_VERIFICATION_FLAG_CHECKED = 256,
TDF_SHOW_PROGRESS_BAR = 512,
TDF_SHOW_MARQUEE_PROGRESS_BAR = 1024,
TDF_CALLBACK_TIMER = 2048,
TDF_POSITION_RELATIVE_TO_WINDOW = 4096,
TDF_RTL_LAYOUT = 8192,
TDF_NO_DEFAULT_RADIO_BUTTON = 16384,
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct TASKDIALOGCONFIG_ICON_UNION
{
[FieldOffset(0)]
public int hMainIcon;
[FieldOffset(0)]
public int pszIcon;
[FieldOffset(0)]
public IntPtr spacer;
public TASKDIALOGCONFIG_ICON_UNION(int i)
{
this = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION();
spacer = IntPtr.Zero;
pszIcon = 0;
hMainIcon = i;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
public struct TASKDIALOG_BUTTON
{
public int nButtonID;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszButtonText;
public TASKDIALOG_BUTTON(int n, string txt)
{
this = new TaskDialogNative.TASKDIALOG_BUTTON();
nButtonID = n;
pszButtonText = txt;
}
}
}
public enum MsgButtons
{
None = 0,
Ok = 1,
Yes = 2,
No = 4,
YesNo = 6,
Cancel = 8,
OkCancel = 9,
YesNoCancel = 14,
Retry = 16,
RetryCancel = 24,
Close = 32,
}
public enum MsgResult
{
None,
OK,
Cancel,
Abort,
Retry,
Ignore,
Yes,
No,
}
public enum MsgIcon
{
None = 0,
SecurityShieldGray = 65527,
SecuritySuccess = 65528,
SecurityError = 65529,
SecurityWarning = 65530,
SecurityShieldBlue = 65531,
Shield = 65532,
Info = 65533,
Error = 65534,
Warning = 65535,
}
}

656
mpv.net/TaskDialog.cs Normal file
View File

@@ -0,0 +1,656 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
public class Msg
{
private static string ShownMessages;
public static string SupportURL { get; set; }
public static void Show(string mainInstruction, string content = null)
{
Msg.Show(mainInstruction, content, MsgIcon.Info, MsgButtons.Ok, MsgResult.None);
}
public static void ShowError(string mainInstruction, string content = null)
{
try
{
using (TaskDialog<string> td = new TaskDialog<string>())
{
td.AllowCancel = false;
if (string.IsNullOrEmpty(content))
{
if (mainInstruction.Length < 80)
td.MainInstruction = mainInstruction;
else
td.Content = mainInstruction;
}
else
{
td.MainInstruction = mainInstruction;
td.Content = content;
}
td.MainIcon = MsgIcon.Error;
td.Footer = "[Copy Message](copymsg)";
if (!string.IsNullOrEmpty(Msg.SupportURL))
td.Footer += $" [Contact Support]({SupportURL})";
td.Show();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public static void ShowException(Exception e)
{
try
{
using (TaskDialog<string> td = new TaskDialog<string>())
{
td.MainInstruction = e.GetType().Name;
td.Content = e.Message;
td.MainIcon = MsgIcon.Error;
td.ExpandedInformation = e.ToString();
td.Footer = "[Copy Message](copymsg)";
if (!string.IsNullOrEmpty(Msg.SupportURL))
td.Footer += $" [Contact Support]({SupportURL})";
td.Show();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public static void ShowWarning(string mainInstruction,
string content = null,
bool onlyOnce = false)
{
if (onlyOnce && Msg.ShownMessages != null &&
Msg.ShownMessages.Contains(mainInstruction + content))
return;
Msg.Show(mainInstruction, content, MsgIcon.Warning, MsgButtons.Ok, MsgResult.None);
if (!onlyOnce) return;
Msg.ShownMessages += mainInstruction + content;
}
public static MsgResult ShowQuestion(string mainInstruction,
MsgButtons buttons = MsgButtons.OkCancel)
{
return Msg.Show(mainInstruction, null, MsgIcon.None, buttons, MsgResult.None);
}
public static MsgResult ShowQuestion(string mainInstruction,
string content,
MsgButtons buttons = MsgButtons.OkCancel)
{
return Msg.Show(mainInstruction, content, MsgIcon.None, buttons, MsgResult.None);
}
public static MsgResult Show(string mainInstruction,
string content,
MsgIcon icon,
MsgButtons buttons,
MsgResult defaultButton = MsgResult.None)
{
try
{
using (TaskDialog<MsgResult> td = new TaskDialog<MsgResult>())
{
td.AllowCancel = false;
td.DefaultButton = defaultButton;
td.MainIcon = icon;
if (content == null)
{
if (mainInstruction.Length < 80)
td.MainInstruction = mainInstruction;
else
td.Content = mainInstruction;
}
else
{
td.MainInstruction = mainInstruction;
td.Content = content;
}
if (buttons == MsgButtons.OkCancel)
{
td.AddButton("OK", MsgResult.OK);
td.AddButton("Cancel", MsgResult.Cancel);
}
else
td.CommonButtons = buttons;
return td.Show();
}
}
catch (Exception ex)
{
return (MsgResult)MessageBox.Show(ex.GetType().Name + "\n\n" + ex.Message + "\n\n" + ex.ToString(),
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public class TaskDialog<T> : TaskDialogNative, IDisposable
{
private Dictionary<int, T> IdValueDic;
private Dictionary<int, string> IdTextDic;
private List<int> CommandLinkShieldList;
private IntPtr ButtonArray;
private IntPtr RadioButtonArray;
private List<TaskDialogNative.TASKDIALOG_BUTTON> Buttons;
private List<TaskDialogNative.TASKDIALOG_BUTTON> RadioButtons;
private TaskDialogNative.TASKDIALOGCONFIG Config;
const int TDE_CONTENT = 0;
const int TDE_EXPANDED_INFORMATION = 1;
const int TDE_FOOTER = 2;
const int TDE_MAIN_INSTRUCTION = 3;
const int TDN_CREATED = 0;
const int TDN_NAVIGATED = 1;
const int TDN_BUTTON_CLICKED = 2;
const int TDN_HYPERLINK_CLICKED = 3;
const int TDN_TIMER = 4;
const int TDN_DESTROYED = 5;
const int TDN_RADIO_BUTTON_CLICKED = 6;
const int TDN_DIALOG_CONSTRUCTED = 7;
const int TDN_VERIFICATION_CLICKED = 8;
const int TDN_HELP = 9;
const int TDN_EXPANDO_BUTTON_CLICKED = 10;
const int TDM_NAVIGATE_PAGE = 1125;
const int TDM_CLICK_BUTTON = 1126;
const int TDM_SET_MARQUEE_PROGRESS_BAR = 1127;
const int TDM_SET_PROGRESS_BAR_STATE = 1128;
const int TDM_SET_PROGRESS_BAR_RANGE = 1129;
const int TDM_SET_PROGRESS_BAR_POS = 1130;
const int TDM_SET_PROGRESS_BAR_MARQUEE = 1131;
const int TDM_SET_ELEMENT_TEXT = 1132;
const int TDM_CLICK_RADIO_BUTTON = 1134;
const int TDM_ENABLE_BUTTON = 1135;
const int TDM_ENABLE_RADIO_BUTTON = 1136;
const int TDM_CLICK_VERIFICATION = 1137;
const int TDM_UPDATE_ELEMENT_TEXT = 1138;
const int TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = 1139;
const int TDM_UPDATE_ICON = 1140;
private T SelectedValueValue;
private string SelectedTextValue;
private int TimeoutValue;
private int ExitTickCount;
private bool disposed;
public TaskDialog()
{
IdValueDic = new Dictionary<int, T>();
IdTextDic = new Dictionary<int, string>();
CommandLinkShieldList = new List<int>();
Buttons = new List<TaskDialogNative.TASKDIALOG_BUTTON>();
RadioButtons = new List<TaskDialogNative.TASKDIALOG_BUTTON>();
_SelectedID = -1;
Config = new TaskDialogNative.TASKDIALOGCONFIG();
Config.cbSize = (uint)Marshal.SizeOf(Config);
Config.hwndParent = GetHandle();
Config.hInstance = IntPtr.Zero;
Config.dwFlags = TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
Config.dwCommonButtons = MsgButtons.None;
Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0);
Config.FooterIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION(0);
Config.cxWidth = 0U;
Config.cButtons = 0U;
Config.cRadioButtons = 0U;
Config.pButtons = IntPtr.Zero;
Config.pRadioButtons = IntPtr.Zero;
Config.nDefaultButton = 0;
Config.nDefaultRadioButton = 0;
Config.pszWindowTitle = ((AssemblyProductAttribute)Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true)[0]).Product;
Config.pszMainInstruction = "";
Config.pszContent = "";
Config.pfCallback = new PFTASKDIALOGCALLBACK(this.DialogProc);
}
public IntPtr GetHandle()
{
StringBuilder lpszFileName = new StringBuilder(260);
IntPtr foregroundWindow = TaskDialogNative.GetForegroundWindow();
TaskDialogNative.GetWindowModuleFileName(foregroundWindow, lpszFileName, 260U);
if (Path.GetFileName(lpszFileName.ToString().Replace(".vshost", "")) ==
Path.GetFileName(Assembly.GetEntryAssembly().Location))
return foregroundWindow;
return IntPtr.Zero;
}
public bool AllowCancel {
set {
if (value)
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
else
Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION;
}
}
public string MainInstruction {
get => Config.pszMainInstruction;
set => Config.pszMainInstruction = value;
}
public string Content {
get => Config.pszContent;
set => Config.pszContent = ExpandMarkdownMarkup(value);
}
public string ExpandedInformation {
get => Config.pszExpandedInformation;
set => Config.pszExpandedInformation = ExpandMarkdownMarkup(value);
}
public string VerificationText {
get => Config.pszVerificationText;
set => Config.pszVerificationText = value;
}
public MsgResult DefaultButton {
get => (MsgResult)Config.nDefaultButton;
set => Config.nDefaultButton = (int)value;
}
public string Footer {
get => Config.pszFooter;
set => Config.pszFooter = ExpandMarkdownMarkup(value);
}
public MsgIcon MainIcon {
set => Config.MainIcon = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION((int)value);
}
private int _SelectedID;
public int SelectedID {
get => _SelectedID;
set {
foreach (var i in IdValueDic)
if (i.Key == value) _SelectedID = value;
}
}
public T SelectedValue {
get {
if (IdValueDic.ContainsKey(SelectedID))
return IdValueDic[SelectedID];
return SelectedValueValue;
}
set => SelectedValueValue = value;
}
public string SelectedText {
get {
if (IdTextDic.ContainsKey(SelectedID))
return IdTextDic[SelectedID];
return SelectedTextValue;
}
set => SelectedTextValue = value;
}
public bool CheckBoxChecked {
get => (Config.dwFlags & TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) == TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
set {
if (value)
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
else
Config.dwFlags ^= TaskDialogNative.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED;
}
}
public MsgButtons CommonButtons {
get => Config.dwCommonButtons;
set => Config.dwCommonButtons = value;
}
public int Timeout {
get => Convert.ToInt32(TimeoutValue / 1000.0);
set {
TimeoutValue = value * 1000;
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER;
}
}
public void AddButton(string text, T value)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value;
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
}
public string ExpandMarkdownMarkup(string value)
{
if (value.Contains("["))
{
Regex regex = new Regex(@"\[(.+)\]\((.+)\)");
if (regex.Match(value).Success)
{
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS;
value = regex.Replace(value, "<a href=\"$2\">$1</a>");
}
}
return value;
}
public void AddCommandLink(string text, T value)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value == null ? (T)(object)text : value;
IdTextDic[n] = text;
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
}
public void AddCommandLink(string text, string description, T value, bool setShield = false)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value;
if (setShield) CommandLinkShieldList.Add(n);
if (!string.IsNullOrEmpty(description)) text += "\n" + description;
Buttons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
Config.dwFlags |= TaskDialogNative.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
}
public void AddRadioButton(string text, T value)
{
int n = 1000 + IdValueDic.Count + 1;
IdValueDic[n] = value;
RadioButtons.Add(new TaskDialogNative.TASKDIALOG_BUTTON(n, text));
}
public T Show()
{
MarshalDialogControlStructs();
TaskDialogNative.TASKDIALOGCONFIG config = Config;
int errorCode = TaskDialogNative.TaskDialogIndirect(config, out int dummy1, out int dummy2, out bool isChecked);
if (errorCode < 0) Marshal.ThrowExceptionForHR(errorCode);
CheckBoxChecked = isChecked;
if (SelectedValue is MsgResult) SelectedValue = (T)(object)SelectedID;
return SelectedValue;
}
public int DialogProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, IntPtr lpRefData)
{
switch (msg)
{
case 0: //TDN_CREATED
foreach (var i in CommandLinkShieldList)
SendMessage(hwnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, new IntPtr(i), new IntPtr(1));
break;
case 2: //TDN_BUTTON_CLICKED
case 6: //TDN_RADIO_BUTTON_CLICKED
if (SelectedValue is MsgResult)
_SelectedID = wParam.ToInt32();
else
SelectedID = wParam.ToInt32();
break;
case 3: //TDN_HYPERLINK_CLICKED
string stringUni = Marshal.PtrToStringUni(lParam);
if (stringUni.StartsWith("mailto") || stringUni.StartsWith("http"))
Process.Start(stringUni);
if (stringUni == "copymsg")
{
Thread thread = new Thread((ThreadStart)(() => {
Clipboard.SetText(MainInstruction + "\r\n\r\n" + Content + "\r\n\r\n" + ExpandedInformation);
MessageBox.Show("Message was copied to clipboard.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
break;
case 4: //TDN_TIMER
if (ExitTickCount == 0) ExitTickCount = Environment.TickCount + Timeout * 1000;
if (Environment.TickCount > ExitTickCount)
TaskDialogNative.SendMessage(hwnd, 1126, new IntPtr(1), IntPtr.Zero);
break;
}
return 0;
}
public void MarshalDialogControlStructs()
{
if (Buttons != null && Buttons.Count > 0)
{
ButtonArray = TaskDialog<T>.AllocateAndMarshalButtons(Buttons);
Config.pButtons = ButtonArray;
Config.cButtons = (uint)Buttons.Count;
}
if (RadioButtons == null || RadioButtons.Count <= 0) return;
RadioButtonArray = TaskDialog<T>.AllocateAndMarshalButtons(RadioButtons);
Config.pRadioButtons = RadioButtonArray;
Config.cRadioButtons = (uint)RadioButtons.Count;
}
public static IntPtr AllocateAndMarshalButtons(List<TaskDialogNative.TASKDIALOG_BUTTON> structs)
{
var initialPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TASKDIALOG_BUTTON)) * structs.Count);
var currentPtr = initialPtr;
foreach (var button in structs)
{
Marshal.StructureToPtr(button, currentPtr, false);
currentPtr = (IntPtr)(currentPtr.ToInt64() + Marshal.SizeOf(button));
}
return initialPtr;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~TaskDialog()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;
if (ButtonArray != IntPtr.Zero)
{
Marshal.FreeHGlobal(ButtonArray);
ButtonArray = IntPtr.Zero;
}
if (RadioButtonArray != IntPtr.Zero)
{
Marshal.FreeHGlobal(RadioButtonArray);
RadioButtonArray = IntPtr.Zero;
}
}
}
public delegate int PFTASKDIALOGCALLBACK(
IntPtr hwnd,
uint msg,
IntPtr wParam,
IntPtr lParam,
IntPtr lpRefData);
public class TaskDialogNative
{
[DllImport("comctl32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int TaskDialogIndirect(
[In] TaskDialogNative.TASKDIALOGCONFIG pTaskConfig,
out int pnButton,
out int pnRadioButton,
[MarshalAs(UnmanagedType.Bool)] out bool pVerificationFlagChecked);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern uint GetWindowModuleFileName(
IntPtr hwnd,
StringBuilder lpszFileName,
uint cchFileNameMax);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(
IntPtr handle,
int message,
IntPtr wParam,
IntPtr lParam);
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
public class TASKDIALOGCONFIG
{
public uint cbSize;
public IntPtr hwndParent;
public IntPtr hInstance;
public TaskDialogNative.TASKDIALOG_FLAGS dwFlags;
public MsgButtons dwCommonButtons;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszWindowTitle;
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION MainIcon;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszMainInstruction;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszContent;
public uint cButtons;
public IntPtr pButtons;
public int nDefaultButton;
public uint cRadioButtons;
public IntPtr pRadioButtons;
public int nDefaultRadioButton;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszVerificationText;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszExpandedInformation;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszExpandedControlText;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszCollapsedControlText;
public TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION FooterIcon;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszFooter;
public PFTASKDIALOGCALLBACK pfCallback;
public IntPtr lpCallbackData;
public uint cxWidth;
}
public enum TASKDIALOG_FLAGS
{
NONE = 0,
TDF_ENABLE_HYPERLINKS = 1,
TDF_USE_HICON_MAIN = 2,
TDF_USE_HICON_FOOTER = 4,
TDF_ALLOW_DIALOG_CANCELLATION = 8,
TDF_USE_COMMAND_LINKS = 16,
TDF_USE_COMMAND_LINKS_NO_ICON = 32,
TDF_EXPAND_FOOTER_AREA = 64,
TDF_EXPANDED_BY_DEFAULT = 128,
TDF_VERIFICATION_FLAG_CHECKED = 256,
TDF_SHOW_PROGRESS_BAR = 512,
TDF_SHOW_MARQUEE_PROGRESS_BAR = 1024,
TDF_CALLBACK_TIMER = 2048,
TDF_POSITION_RELATIVE_TO_WINDOW = 4096,
TDF_RTL_LAYOUT = 8192,
TDF_NO_DEFAULT_RADIO_BUTTON = 16384,
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct TASKDIALOGCONFIG_ICON_UNION
{
[FieldOffset(0)]
public int hMainIcon;
[FieldOffset(0)]
public int pszIcon;
[FieldOffset(0)]
public IntPtr spacer;
public TASKDIALOGCONFIG_ICON_UNION(int i)
{
this = new TaskDialogNative.TASKDIALOGCONFIG_ICON_UNION();
spacer = IntPtr.Zero;
pszIcon = 0;
hMainIcon = i;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
public struct TASKDIALOG_BUTTON
{
public int nButtonID;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszButtonText;
public TASKDIALOG_BUTTON(int n, string txt)
{
this = new TaskDialogNative.TASKDIALOG_BUTTON();
nButtonID = n;
pszButtonText = txt;
}
}
}
public enum MsgButtons
{
None = 0,
Ok = 1,
Yes = 2,
No = 4,
YesNo = 6,
Cancel = 8,
OkCancel = 9,
YesNoCancel = 14,
Retry = 16,
RetryCancel = 24,
Close = 32,
}
public enum MsgResult
{
None,
OK,
Cancel,
Abort,
Retry,
Ignore,
Yes,
No,
}
public enum MsgIcon
{
None = 0,
SecurityShieldGray = 65527,
SecuritySuccess = 65528,
SecurityError = 65529,
SecurityWarning = 65530,
SecurityShieldBlue = 65531,
Shield = 65532,
Info = 65533,
Error = 65534,
Warning = 65535,
}

View File

@@ -24,4 +24,85 @@
</Setter.Value>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Padding" Value="6 0 0 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftCol" Width="18" />
<ColumnDefinition x:Name="RightCol" Width="*" />
</Grid.ColumnDefinitions>
<Grid x:Name="PART_CHECKBOX">
<Ellipse
x:Name="normal"
Width="18"
Height="18"
Fill="{Binding Path=Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
Stroke="{x:Static WPF:WPF.ThemeBrush}"
StrokeThickness="2" />
<Ellipse
x:Name="Checked1"
Width="8"
Height="8"
Fill="{TemplateBinding Foreground}"
Opacity="0" />
<Ellipse
x:Name="disabled"
Width="18"
Height="18"
Fill="{DynamicResource SemiTransparentWhiteBrush}"
Opacity="0"
StrokeThickness="{TemplateBinding BorderThickness}" />
</Grid>
<ContentPresenter
x:Name="contentPresenter"
Grid.Column="1"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
RecognizesAccessKey="True" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="contentPresenter"
Storyboard.TargetProperty="(UIElement.Opacity)"
To=".55"
Duration="0" />
<DoubleAnimation
Storyboard.TargetName="disabled"
Storyboard.TargetProperty="(UIElement.Opacity)"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Checked1"
Storyboard.TargetProperty="(UIElement.Opacity)"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</ResourceDictionary>

View File

@@ -1,6 +1,8 @@
using Microsoft.Win32;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

View File

@@ -9,7 +9,6 @@ using System.Windows.Input;
using System.Windows.Media;
using DynamicGUI;
using Sys;
namespace mpvnet
{
@@ -115,7 +114,7 @@ namespace mpvnet
if (left.StartsWith("#"))
{
Comments[filePath][left.TrimStart("#".ToCharArray())] = right;
Comments[filePath][left.TrimStart('#')] = right;
continue;
}

View File

@@ -0,0 +1,23 @@
<Window x:Class="mpvnet.EverythingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Media File Search" Height="300" Width="600" ResizeMode="NoResize"
WindowStartupLocation="CenterOwner" Loaded="Window_Loaded" FontSize="13">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox Name="FilterTextBox" PreviewKeyDown="FilterTextBox_PreviewKeyDown" TextChanged="FilterTextBox_TextChanged"></TextBox>
<ListView Name="ListView" Grid.Row="1" MouseUp="ListView_MouseUp" PreviewKeyDown="ListView_PreviewKeyDown">
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Window>

View File

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

View File

@@ -7,7 +7,6 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using Sys;
namespace mpvnet
{
@@ -31,10 +30,19 @@ namespace mpvnet
if (App.IsDarkMode)
{
Foreground = Brushes.White;
Foreground2 = Brushes.Silver;
Background = Brushes.Black;
}
}
public Brush Foreground2 {
get { return (Brush)GetValue(Foreground2Property); }
set { SetValue(Foreground2Property, value); }
}
public static readonly DependencyProperty Foreground2Property =
DependencyProperty.Register("Foreground2", typeof(Brush), typeof(InputWindow), new PropertyMetadata(Brushes.DarkSlateGray));
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionView.Refresh();

View File

@@ -11,13 +11,9 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Sys;
using static mpvnet.libmpv;
using static mpvnet.Native;
using PyRT = IronPython.Runtime;
namespace mpvnet
{
public delegate void MpvBoolPropChangeHandler(string propName, bool value);
@@ -25,7 +21,7 @@ namespace mpvnet
public class mp
{
public static event Action VideoSizeChanged;
// Lua/JS evens libmpv events
// Lua/JS event libmpv event
// MPV_EVENT_NONE
public static event Action Shutdown; // shutdown MPV_EVENT_SHUTDOWN
@@ -78,9 +74,11 @@ namespace mpvnet
{
string portableFolder = Application.StartupPath + "\\portable_config\\";
string appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mpv\\";
string startupFolder = Application.StartupPath + "\\";
if (!Directory.Exists(appdataFolder) && !Directory.Exists(portableFolder) &&
Sys.IsDirectoryWritable(Application.StartupPath))
Sys.IsDirectoryWritable(Application.StartupPath) &&
!File.Exists(startupFolder + "mpv.conf"))
{
using (TaskDialog<string> td = new TaskDialog<string>())
{
@@ -88,15 +86,17 @@ namespace mpvnet
td.Content = "[MPV documentation about files on Windows.](https://mpv.io/manual/master/#files-on-windows)";
td.AddCommandLink("appdata", appdataFolder, appdataFolder);
td.AddCommandLink("portable", portableFolder, portableFolder);
td.AddCommandLink("startup", startupFolder, startupFolder);
td.AllowCancel = false;
_MpvConfFolder = td.Show();
}
}
else
if (Directory.Exists(portableFolder))
else if (Directory.Exists(portableFolder))
_MpvConfFolder = portableFolder;
else
else if (Directory.Exists(appdataFolder))
_MpvConfFolder = appdataFolder;
else if (File.Exists(Application.StartupPath + "\\mpv.conf"))
_MpvConfFolder = Application.StartupPath + "\\";
if (string.IsNullOrEmpty(_MpvConfFolder)) _MpvConfFolder = appdataFolder;
if (!Directory.Exists(_MpvConfFolder)) Directory.CreateDirectory(_MpvConfFolder);
@@ -345,7 +345,7 @@ namespace mpvnet
static List<PythonEventObject> PythonEventObjects = new List<PythonEventObject>();
public static void register_event(string name, PyRT.PythonFunction pyFunc)
public static void register_event(string name, IronPython.Runtime.PythonFunction pyFunc)
{
foreach (var eventInfo in typeof(mp).GetEvents())
{
@@ -380,7 +380,7 @@ namespace mpvnet
}
}
public static void unregister_event(PyRT.PythonFunction pyFunc)
public static void unregister_event(IronPython.Runtime.PythonFunction pyFunc)
{
foreach (var eventObjects in PythonEventObjects)
if (eventObjects.PythonFunction == pyFunc)
@@ -565,17 +565,15 @@ namespace mpvnet
if (get_property_int("playlist-count") == 1)
{
string path = get_property_string("path");
if (!Directory.Exists(Path.GetDirectoryName(path))) return;
string[] types = "264 265 3gp aac ac3 avc avi avs bmp divx dts dtshd dtshr dtsma eac3 evo flac flv h264 h265 hevc hvc jpg jpeg m2t m2ts m2v m4a m4v mka mkv mlp mov mp2 mp3 mp4 mpa mpeg mpg mpv mts ogg ogm opus pcm png pva raw rmvb thd thd+ac3 true-hd truehd ts vdr vob vpy w64 wav webm wmv y4m".Split(' ');
if (!File.Exists(path)) return;
List<string> files = Directory.GetFiles(Path.GetDirectoryName(path)).ToList();
files = files.Where((file) => types.Contains(Path.GetExtension(file).TrimStart(".".ToCharArray()).ToLower())).ToList();
files = files.Where((file) => App.VideoTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower()) ||
App.AudioTypes.Contains(Path.GetExtension(file).TrimStart('.').ToLower())).ToList();
files.Sort(new StringLogicalComparer());
int index = files.IndexOf(path);
files.Remove(path);
foreach (string i in files)
commandv("loadfile", i, "append");
if (index > 0)
commandv("playlist-move", "0", (index + 1).ToString());
}
@@ -665,7 +663,7 @@ namespace mpvnet
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(" ,".ToCharArray());
track.Text = "V: " + track.Text.Trim(' ', ',');
track.Type = "v";
track.ID = i + 1;
MediaTracks.Add(track);
@@ -685,7 +683,7 @@ namespace mpvnet
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(" ,".ToCharArray());
track.Text = "A: " + track.Text.Trim(' ', ',');
track.Type = "a";
track.ID = i + 1;
MediaTracks.Add(track);
@@ -702,7 +700,7 @@ namespace mpvnet
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(" ,".ToCharArray());
track.Text = "S: " + track.Text.Trim(' ', ',');
track.Type = "s";
track.ID = i + 1;
MediaTracks.Add(track);

View File

@@ -56,6 +56,46 @@
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="IKVM.Reflection, Version=7.2.4630.5, Culture=neutral, PublicKeyToken=13235d27fcbfff58, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -106,6 +146,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\EverythingWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\CommandPaletteWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -150,7 +194,10 @@
<Compile Include="NativeHelp.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sys\TaskDialog.cs" />
<Compile Include="TaskDialog.cs" />
<Compile Include="Windows\EverythingWindow.xaml.cs">
<DependentUpon>EverythingWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\CommandPaletteWindow.xaml.cs">
<DependentUpon>CommandPaletteWindow.xaml</DependentUpon>
</Compile>
@@ -205,7 +252,6 @@
</ItemGroup>
<ItemGroup>
<Content Include="Resources\inputConfHeader.txt" />
<Content Include="screenshot.jpg" />
<Content Include="Resources\inputConf.txt" />
</ItemGroup>
<ItemGroup>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 497 KiB

View File

@@ -1,7 +0,0 @@
$scriptDir = Split-Path -Path $PSCommandPath -Parent
$exePath = $scriptDir + "\mpv.net\bin\mpvnet.exe"
$version = [Diagnostics.FileVersionInfo]::GetVersionInfo($exePath).FileVersion
$desktopDir = [Environment]::GetFolderPath("Desktop")
$targetDir = $desktopDir + "\mpv.net-portable-x64-" + $version
Copy-Item $scriptDir\mpv.net\bin $targetDir -Recurse -Exclude System.Management.Automation.xml -Force
& "C:\Program Files\7-Zip\7z.exe" a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"

View File

@@ -1,18 +1,30 @@
#define MyAppName "mpv.net"
#define MyAppVersion GetFileVersion("mpv.net\bin\mpvnet.exe")
#define MyAppExeName "mpvnet.exe"
#define MyAppSourceDir "mpv.net\bin"
#ifndef arch
#define arch "x64"
#endif
#if arch == "x64"
#define MyAppSourceDir "mpv.net\bin\x64"
#define MyAppVersion GetFileVersion("mpv.net\bin\x64\mpvnet.exe")
#else
#define MyAppSourceDir "mpv.net\bin\x86"
#define MyAppVersion GetFileVersion("mpv.net\bin\x86\mpvnet.exe")
#endif
[Setup]
AppId={{9AA2B100-BEF3-44D0-B819-D8FC3C4D557D}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher=Frank Skare (stax76)
ArchitecturesInstallIn64BitMode=x64
#if arch == "x64"
ArchitecturesInstallIn64BitMode=x64
#endif
Compression=lzma2
DefaultDirName={pf}\{#MyAppName}
OutputBaseFilename=mpvnet-setup-x64-{#MyAppVersion}
OutputDir=C:\Users\frank\Desktop
DefaultDirName={commonpf}\{#MyAppName}
OutputBaseFilename=mpv.net-setup-{#arch}-{#MyAppVersion}
OutputDir={#GetEnv('USERPROFILE')}\Desktop
DefaultGroupName={#MyAppName}
SetupIconFile=mpv.net\mpvnet.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
@@ -29,4 +41,4 @@ Filename: "{app}\{#MyAppExeName}"; Description: "Associate video file extensions
Filename: "{app}\{#MyAppExeName}"; Description: "Associate audio file extensions?"; Flags: postinstall unchecked runascurrentuser runhidden nowait; Parameters: "--reg-file-assoc audio"
[UninstallRun]
Filename: "{app}\{#MyAppExeName}"; Flags: runascurrentuser runhidden; Parameters: "--reg-file-assoc unregister"
Filename: "{app}\{#MyAppExeName}"; Flags: runascurrentuser runhidden; Parameters: "--reg-file-assoc unreg"

51
setup.ps1 Normal file
View File

@@ -0,0 +1,51 @@
function CheckExitCode {
if ($LastExitCode -gt 0) {
Write-Host "`nExit code $LastExitCode was returned.`n" -ForegroundColor Red
exit
}
}
$msbuild = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
& $msbuild mpv.net.sln /p:Configuration=Debug /p:Platform=x64
CheckExitCode
& $msbuild mpv.net.sln /p:Configuration=Debug /p:Platform=x86
CheckExitCode
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /Darch="x64" setup.iss
CheckExitCode
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /Darch="x86" setup.iss
CheckExitCode
$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
& "C:\Program Files\7-Zip\7z.exe" a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
CheckExitCode
& "C:\Program Files\7-Zip\7z.exe" a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
CheckExitCode
$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
& "C:\Program Files\7-Zip\7z.exe" a -t7z -mx9 "$targetDir.7z" -r "$targetDir\*"
CheckExitCode
& "C:\Program Files\7-Zip\7z.exe" a -tzip -mx9 "$targetDir.zip" -r "$targetDir\*"
CheckExitCode