diff options
| author | b5f0d6c3 <[email protected]> | 2021-10-22 14:45:22 +0800 |
|---|---|---|
| committer | b5f0d6c3 <[email protected]> | 2021-10-22 14:45:22 +0800 |
| commit | cc993e05efef9fb1a797d686a18161fb906676d4 (patch) | |
| tree | 6592579d71980d58fdc466fefcb3b9a7699c1783 /mkvtool-gui | |
| parent | 7fde5d4d448f64c2250ab003e2ecb75a7d268733 (diff) | |
add mkvtool-gui
Diffstat (limited to 'mkvtool-gui')
| -rw-r--r-- | mkvtool-gui/App.axaml | 11 | ||||
| -rw-r--r-- | mkvtool-gui/App.axaml.cs | 35 | ||||
| -rw-r--r-- | mkvtool-gui/CustomFontManagerImpl.cs | 73 | ||||
| -rw-r--r-- | mkvtool-gui/MainWindow.axaml | 218 | ||||
| -rw-r--r-- | mkvtool-gui/MainWindow.axaml.cs | 428 | ||||
| -rw-r--r-- | mkvtool-gui/Program.cs | 23 | ||||
| -rw-r--r-- | mkvtool-gui/mkvtool.csproj | 28 | ||||
| -rw-r--r-- | mkvtool-gui/sdk.cs | 135 |
8 files changed, 951 insertions, 0 deletions
diff --git a/mkvtool-gui/App.axaml b/mkvtool-gui/App.axaml new file mode 100644 index 0000000..9871dd1 --- /dev/null +++ b/mkvtool-gui/App.axaml @@ -0,0 +1,11 @@ +<Application xmlns="https://github.com/avaloniaui" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:Class="mkvtool.App"> + <Application.Styles> + <FluentTheme Mode="Light" /> + </Application.Styles> + <Application.Styles> + <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml" /> + <StyleInclude Source="avares://Avalonia.Controlz/Styles/Generic.axaml" /> + </Application.Styles> +</Application>
\ No newline at end of file diff --git a/mkvtool-gui/App.axaml.cs b/mkvtool-gui/App.axaml.cs new file mode 100644 index 0000000..44e12cf --- /dev/null +++ b/mkvtool-gui/App.axaml.cs @@ -0,0 +1,35 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; +using Avalonia.Platform; + +namespace mkvtool +{ + public class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + desktop.MainWindow = new MainWindow(); + } + + base.OnFrameworkInitializationCompleted(); + } + + /// <summary> + /// override RegisterServices register custom service + /// </summary> + public override void RegisterServices() + { + AvaloniaLocator.CurrentMutable.Bind<IFontManagerImpl>().ToConstant(new CustomFontManagerImpl()); + base.RegisterServices(); + } + + } +}
\ No newline at end of file diff --git a/mkvtool-gui/CustomFontManagerImpl.cs b/mkvtool-gui/CustomFontManagerImpl.cs new file mode 100644 index 0000000..c47fedb --- /dev/null +++ b/mkvtool-gui/CustomFontManagerImpl.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Avalonia.Media; +using Avalonia.Platform; +using Avalonia.Skia; +using SkiaSharp; + +namespace mkvtool +{ + public class CustomFontManagerImpl : IFontManagerImpl + { + private readonly Typeface[] _customTypefaces; + private readonly string _defaultFamilyName; + + private readonly Typeface _defaultTypeface = + new Typeface("Microsoft Yahei"); + + public CustomFontManagerImpl() + { + _customTypefaces = new[] {_defaultTypeface}; + _defaultFamilyName = _defaultTypeface.FontFamily.FamilyNames.PrimaryFamilyName; + } + + public string GetDefaultFontFamilyName() + { + return _defaultFamilyName; + } + + public IEnumerable<string> GetInstalledFontFamilyNames(bool checkForUpdates = false) + { + return _customTypefaces.Select(x => x.FontFamily.Name); + } + + private readonly string[] _bcp47 = + { + CultureInfo.CurrentCulture.ThreeLetterISOLanguageName, CultureInfo.CurrentCulture.TwoLetterISOLanguageName + }; + + public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fontWeight, FontFamily fontFamily, + CultureInfo culture, out Typeface typeface) + { + foreach (var customTypeface in _customTypefaces) + { + if (customTypeface.GlyphTypeface.GetGlyph((uint) codepoint) == 0) + { + continue; + } + + typeface = new Typeface(customTypeface.FontFamily.Name, fontStyle, fontWeight); + + return true; + } + + var fallback = SKFontManager.Default.MatchCharacter(fontFamily?.Name, (SKFontStyleWeight) fontWeight, + SKFontStyleWidth.Normal, (SKFontStyleSlant) fontStyle, _bcp47, codepoint); + + typeface = new Typeface(fallback?.FamilyName ?? _defaultFamilyName, fontStyle, fontWeight); + + return true; + } + + public IGlyphTypefaceImpl CreateGlyphTypeface(Typeface typeface) + { + SKTypeface skTypeface; + skTypeface = SKTypeface.FromFamilyName(_defaultTypeface.FontFamily.Name, + (SKFontStyleWeight) typeface.Weight, SKFontStyleWidth.Normal, (SKFontStyleSlant) typeface.Style); + + + return new GlyphTypefaceImpl(skTypeface); + } + } +}
\ No newline at end of file diff --git a/mkvtool-gui/MainWindow.axaml b/mkvtool-gui/MainWindow.axaml new file mode 100644 index 0000000..014010e --- /dev/null +++ b/mkvtool-gui/MainWindow.axaml @@ -0,0 +1,218 @@ +<Window xmlns="https://github.com/avaloniaui" + 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" d:DesignWidth="600" + d:DesignHeight="600" + Width="850" + Height="650" + x:Class="mkvtool.MainWindow" + WindowStartupLocation="CenterScreen" + xmlns:Controls="clr-namespace:Avalonia.Controlz.Controls;assembly=Avalonia.Controlz" + Title="MKV Tool" Opened="TopLevel_OnOpened"> + <DockPanel> + <TabControl DockPanel.Dock="Left"> + <TabItem Header="Subset"> + <StackPanel> + <Controls:GroupBox Header="Check subsetted" Margin="10"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> + <Button Content="File..." Click="CheckFileBtn_OnClick" Margin="5" /> + <Button Content="Folder..." Click="CheckFolderBtn_OnClick" Margin="5" /> + </StackPanel> + </Controls:GroupBox> + <Controls:GroupBox Header="Do subset" Margin="10"> + <StackPanel Margin="5" HorizontalAlignment="Center"> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="ASS subtitles:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="sa1" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="asses" Click="SubsetSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="Fonts:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="sa2" /> + </ScrollViewer> + </StackPanel> + </StackPanel> + <Button Content="Select..." Tag="fonts" Click="SubsetSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Output folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="sa3" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="output" Click="SubsetSelectBtns_OnClick" /> + </StackPanel> + <CheckBox Content="Output in sub folder" IsChecked="True" Name="sa4" /> + <Button Margin="10" Content="Go" Click="DoSubsetBtn_OnClick" /> + </StackPanel> + </Controls:GroupBox> + </StackPanel> + </TabItem> + <TabItem Header="Dump / Make"> + <StackPanel> + <Controls:GroupBox Header="Dump" Margin="10"> + <StackPanel Margin="5" HorizontalAlignment="Center"> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="File or folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="da1" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select file..." Tag="file" Click="DumpSelectBtns_OnClick" /> + <Button Content="Select folder..." Tag="folder" Click="DumpSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Output folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="da2" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="output" Click="DumpSelectBtns_OnClick" /> + </StackPanel> + <CheckBox Content="Subset" IsChecked="True" Name="da3" /> + <Button Margin="10" Content="Go" Click="DoDumpBtn_OnClick" /> + </StackPanel> + </Controls:GroupBox> + <Controls:GroupBox Header="Make" Margin="10"> + <StackPanel Margin="5" HorizontalAlignment="Center"> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="Video folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ma1" /> + </ScrollViewer> + </StackPanel> + </StackPanel> + <Button Content="Select..." Tag="dir" Click="MakeSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Data folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ma2" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="data" Click="MakeSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Output folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ma3" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="output" Click="MakeSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Default Subtitle language:" VerticalAlignment="Center" + TextAlignment="Center" /> + <TextBox Name="ma4" /> + </StackPanel> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Default Subtitle title:" VerticalAlignment="Center" + TextAlignment="Center" /> + <TextBox Name="ma5" /> + </StackPanel> + </StackPanel> + <Button Margin="10" Content="Go" Click="DoMakeBtn_OnClick" /> + </StackPanel> + </Controls:GroupBox> + </StackPanel> + </TabItem> + <TabItem Header="Create"> + <StackPanel> + <Controls:GroupBox Header="Do Create" Margin="10"> + <StackPanel Margin="5" HorizontalAlignment="Center"> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="Video folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ca1" /> + </ScrollViewer> + </StackPanel> + </StackPanel> + <Button Content="Select..." Tag="v" Click="CreateSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Subtitles folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ca2" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="s" Click="CreateSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Fonts folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ca3" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="f" Click="CreateSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Output folder:" /> + <ScrollViewer HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto"> + <TextBlock Name="ca4" /> + </ScrollViewer> + </StackPanel> + <Button Content="Select..." Tag="o" Click="CreateSelectBtns_OnClick" /> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Default Subtitle language:" VerticalAlignment="Center" + TextAlignment="Center" /> + <TextBox Name="ca5" /> + </StackPanel> + </StackPanel> + <StackPanel Orientation="Horizontal" Margin="5"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Default Subtitle title:" VerticalAlignment="Center" + TextAlignment="Center" /> + <TextBox Name="ca6" /> + </StackPanel> + </StackPanel> + <CheckBox Content="Clean old data" IsChecked="False" Name="ca7" /> + <Button Margin="10" Content="Go" Click="DoCreatetn_OnClick" /> + </StackPanel> + </Controls:GroupBox> + </StackPanel> + </TabItem> + </TabControl> + <Controls:GroupBox Header="Log" Margin="10" DockPanel.Dock="Right"> + <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> + <TextBox IsReadOnly="True" Name="logBox" Margin="10" /> + </ScrollViewer> + </Controls:GroupBox> + </DockPanel> +</Window>
\ No newline at end of file diff --git a/mkvtool-gui/MainWindow.axaml.cs b/mkvtool-gui/MainWindow.axaml.cs new file mode 100644 index 0000000..10b34de --- /dev/null +++ b/mkvtool-gui/MainWindow.axaml.cs @@ -0,0 +1,428 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using MessageBox.Avalonia; +using MEnums = MessageBox.Avalonia.Enums; + +namespace mkvtool +{ + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + private async void CheckFileBtn_OnClick(object? sender, RoutedEventArgs e) + { + string[] files = await ShowSelectFileDialog("MKV file", new string[] {"mkv"}, false); + if (files != null) + { + bool[] result = mkvlib.CheckSubset(files[0], lcb); + if (result[1]) + await MessageBoxManager.GetMessageBoxStandardWindow("Check result", + "Has error.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Error, WindowStartupLocation.CenterOwner).Show(); + else if (result[0]) + await MessageBoxManager.GetMessageBoxStandardWindow("Check result", + "This mkv file are subsetted.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + else + await MessageBoxManager.GetMessageBoxStandardWindow("Check result", + "This mkv file are not subsetted.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Warning, WindowStartupLocation.CenterOwner).Show(); + } + } + + private async void CheckFolderBtn_OnClick(object? sender, RoutedEventArgs e) + { + string dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + string[] list = mkvlib.QueryFolder(dir, lcb); + if (list != null && list.Length > 0) + { + lcb("Not subsetted file list:"); + lcb(" ----- Begin ----- "); + lcb(string.Join(Environment.NewLine, list)); + lcb(" ----- End ----- "); + } + else + lcb("All files are subseted."); + } + } + + void lcb(string str) + { + this.FindControl<TextBox>("logBox").Text += str + Environment.NewLine; + } + + private async void TopLevel_OnOpened(object? sender, EventArgs e) + { + if (!mkvlib.InitInstance(lcb)) + { + await MessageBoxManager.GetMessageBoxStandardWindow("Check result", + "Failed to init mkvlib.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Error, WindowStartupLocation.CenterOwner).Show(); + this.IsEnabled = false; + } + } + + class SubsetArg + { + public static string[] Asses { get; set; } + public static string Fonts { get; set; } + public static string Output { get; set; } + public static bool DirSafe { get; set; } + } + + private async void SubsetSelectBtns_OnClick(object? sender, RoutedEventArgs e) + { + Button btn = (Button) sender; + string dir; + switch (btn.Tag.ToString()) + { + case "asses": + SubsetArg.Asses = null; + this.FindControl<TextBlock>("sa1").Text = string.Empty; + string[] files = await ShowSelectFileDialog("ASS file(s)", new[] {"ass"}, true); + if (files != null && files.Length > 0) + { + SubsetArg.Asses = files; + this.FindControl<TextBlock>("sa1").Text = string.Join(Environment.NewLine, files); + } + + break; + case "fonts": + SubsetArg.Fonts = string.Empty; + this.FindControl<TextBlock>("sa2").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + SubsetArg.Fonts = dir; + this.FindControl<TextBlock>("sa2").Text = dir; + } + + break; + case "output": + SubsetArg.Output = string.Empty; + this.FindControl<TextBlock>("sa3").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + SubsetArg.Output = dir; + this.FindControl<TextBlock>("sa3").Text = dir; + } + + break; + } + } + + async Task<string[]> ShowSelectFileDialog(string name, string[] ext, bool multiple) + { + OpenFileDialog fileDialog = new OpenFileDialog(); + fileDialog.AllowMultiple = multiple; + FileDialogFilter filter = new FileDialogFilter(); + filter.Name = name; + filter.Extensions.AddRange(ext); + fileDialog.Filters.Add(filter); + string[] files = await fileDialog.ShowAsync(this); + return files; + } + + private async void DoSubsetBtn_OnClick(object? sender, RoutedEventArgs e) + { + if (SubsetArg.Asses != null && SubsetArg.Asses.Length > 0 && !string.IsNullOrEmpty(SubsetArg.Fonts) && + !string.IsNullOrEmpty(SubsetArg.Output)) + { + SubsetArg.DirSafe = this.FindControl<CheckBox>("sa4").IsChecked == true; + if (mkvlib.ASSFontSubset(SubsetArg.Asses, SubsetArg.Fonts, SubsetArg.Output, SubsetArg.DirSafe, lcb)) + { + await MessageBoxManager.GetMessageBoxStandardWindow("Subset result", + "Subset successfully.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + SubsetArg.Asses = null; + SubsetArg.Fonts = string.Empty; + SubsetArg.Output = string.Empty; + this.FindControl<TextBlock>("sa1").Text = string.Empty; + this.FindControl<TextBlock>("sa2").Text = string.Empty; + this.FindControl<TextBlock>("sa3").Text = string.Empty; + this.FindControl<CheckBox>("sa4").IsCancel = true; + } + else + await MessageBoxManager.GetMessageBoxStandardWindow("Subset result", + "Failed to subset.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + } + } + + class DumpArg + { + public static string Path { get; set; } + public static string Output { get; set; } + public static bool Subset { get; set; } + public static bool Dir { get; set; } + } + + private async void DumpSelectBtns_OnClick(object? sender, RoutedEventArgs e) + { + Button btn = (Button) sender; + string dir; + switch (btn.Tag.ToString()) + { + case "file": + DumpArg.Path = string.Empty; + DumpArg.Dir = false; + this.FindControl<TextBlock>("da1").Text = string.Empty; + string[] files = await ShowSelectFileDialog("MKV file", + new[] {"mkv"}, + false); + if (files != null && files.Length > 0) + { + DumpArg.Path = files[0]; + this.FindControl<TextBlock>("da1").Text = files[0]; + } + + break; + case "folder": + DumpArg.Path = string.Empty; + this.FindControl<TextBlock>("da1").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + DumpArg.Path = dir; + this.FindControl<TextBlock>("da1").Text = dir; + DumpArg.Dir = true; + } + + break; + case "output": + DumpArg.Output = string.Empty; + this.FindControl<TextBlock>("da2").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + DumpArg.Output = dir; + this.FindControl<TextBlock>("da2").Text = dir; + } + + break; + } + } + + private async void DoDumpBtn_OnClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(DumpArg.Path) && + !string.IsNullOrEmpty(DumpArg.Output)) + { + DumpArg.Subset = this.FindControl<CheckBox>("da3").IsChecked == true; + bool r = !DumpArg.Dir + ? mkvlib.DumpMKV(DumpArg.Path, DumpArg.Output, DumpArg.Subset, lcb) + : mkvlib.DumpMKVs(DumpArg.Path, DumpArg.Output, DumpArg.Subset, lcb); + if (r) + { + await MessageBoxManager.GetMessageBoxStandardWindow("Dump result", + "Dump successfully.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + DumpArg.Path = string.Empty; + DumpArg.Output = string.Empty; + DumpArg.Dir = false; + this.FindControl<TextBlock>("da1").Text = string.Empty; + this.FindControl<TextBlock>("da2").Text = string.Empty; + this.FindControl<CheckBox>("da3").IsCancel = true; + } + else + await MessageBoxManager.GetMessageBoxStandardWindow("Dump result", + "Failed to dump.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + } + } + + class MakeArg + { + public static string Dir { get; set; } + public static string Data { get; set; } + public static string Output { get; set; } + public static string slang { get; set; } + public static string stitle { get; set; } + } + + private async void MakeSelectBtns_OnClick(object? sender, RoutedEventArgs e) + { + Button btn = (Button) sender; + string dir; + switch (btn.Tag.ToString()) + { + case "dir": + MakeArg.Dir = string.Empty; + this.FindControl<TextBlock>("ma1").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + MakeArg.Dir = dir; + this.FindControl<TextBlock>("ma1").Text = dir; + } + + break; + case "data": + MakeArg.Data = string.Empty; + this.FindControl<TextBlock>("ma2").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + MakeArg.Data = dir; + this.FindControl<TextBlock>("ma2").Text = dir; + } + + break; + case "output": + MakeArg.Output = string.Empty; + this.FindControl<TextBlock>("ma3").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + MakeArg.Output = dir; + this.FindControl<TextBlock>("ma3").Text = dir; + } + + break; + } + } + + private async void DoMakeBtn_OnClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(MakeArg.Dir) && !string.IsNullOrEmpty(MakeArg.Data) && + !string.IsNullOrEmpty(MakeArg.Output)) + { + MakeArg.slang = this.FindControl<TextBox>("ma4").Text; + MakeArg.stitle = this.FindControl<TextBox>("ma5").Text; + if (mkvlib.MakeMKVs(MakeArg.Dir, MakeArg.Data, MakeArg.Output, MakeArg.slang, MakeArg.stitle, lcb)) + { + await MessageBoxManager.GetMessageBoxStandardWindow("Make result", + "Make successfully.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + MakeArg.Dir = string.Empty; + MakeArg.Data = string.Empty; + MakeArg.Output = string.Empty; + MakeArg.slang = string.Empty; + MakeArg.stitle = string.Empty; + this.FindControl<TextBlock>("ma1").Text = string.Empty; + this.FindControl<TextBlock>("ma2").Text = string.Empty; + this.FindControl<TextBlock>("ma3").Text = string.Empty; + this.FindControl<TextBox>("ma4").Text = string.Empty; + this.FindControl<TextBox>("ma5").Text = string.Empty; + } + else + await MessageBoxManager.GetMessageBoxStandardWindow("Make result", + "Failed to make.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + } + } + + class CreateArg + { + public static string vDir { get; set; } + public static string sDir { get; set; } + public static string fDir { get; set; } + public static string oDir { get; set; } + public static string slang { get; set; } + public static string stitle { get; set; } + public static bool clean { get; set; } + } + + private async void CreateSelectBtns_OnClick(object? sender, RoutedEventArgs e) + { + Button btn = (Button) sender; + string dir; + switch (btn.Tag.ToString()) + { + case "v": + CreateArg.vDir = string.Empty; + this.FindControl<TextBlock>("ca1").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + CreateArg.vDir = dir; + this.FindControl<TextBlock>("ca1").Text = dir; + } + + break; + case "s": + CreateArg.sDir = string.Empty; + this.FindControl<TextBlock>("ca2").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + CreateArg.sDir = dir; + this.FindControl<TextBlock>("ca2").Text = dir; + } + + break; + case "f": + CreateArg.fDir = string.Empty; + this.FindControl<TextBlock>("ca3").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + CreateArg.fDir = dir; + this.FindControl<TextBlock>("ca3").Text = dir; + } + + break; + case "o": + CreateArg.oDir = string.Empty; + this.FindControl<TextBlock>("ca4").Text = string.Empty; + dir = await new OpenFolderDialog().ShowAsync(this); + if (!string.IsNullOrEmpty(dir)) + { + CreateArg.oDir = dir; + this.FindControl<TextBlock>("ca4").Text = dir; + } + + break; + } + } + + private async void DoCreatetn_OnClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(CreateArg.vDir) && !string.IsNullOrEmpty(CreateArg.sDir) && + !string.IsNullOrEmpty(CreateArg.fDir) && !string.IsNullOrEmpty(CreateArg.oDir)) + { + CreateArg.slang = this.FindControl<TextBox>("ca5").Text; + CreateArg.stitle = this.FindControl<TextBox>("ca6").Text; + CreateArg.clean = this.FindControl<CheckBox>("ca7").IsChecked == true; + if (mkvlib.CreateMKVs(CreateArg.vDir, CreateArg.sDir, CreateArg.fDir, string.Empty, CreateArg.oDir, + CreateArg.slang, CreateArg.stitle, CreateArg.clean, lcb)) + { + await MessageBoxManager.GetMessageBoxStandardWindow("Create result", + "Create successfully.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + CreateArg.vDir = string.Empty; + CreateArg.sDir = string.Empty; + CreateArg.fDir = string.Empty; + CreateArg.oDir = string.Empty; + CreateArg.clean = false; + this.FindControl<TextBlock>("ca1").Text = string.Empty; + this.FindControl<TextBlock>("ca2").Text = string.Empty; + this.FindControl<TextBlock>("ca3").Text = string.Empty; + this.FindControl<TextBlock>("ca4").Text = string.Empty; + this.FindControl<TextBox>("ca5").Text = string.Empty; + this.FindControl<TextBox>("ca6").Text = string.Empty; + this.FindControl<CheckBox>("ca7").IsChecked = false; + } + else + await MessageBoxManager.GetMessageBoxStandardWindow("Create result", + "Failed to create.", MEnums.ButtonEnum.Ok, + MEnums.Icon.Info, WindowStartupLocation.CenterOwner).Show(); + } + } + } +}
\ No newline at end of file diff --git a/mkvtool-gui/Program.cs b/mkvtool-gui/Program.cs new file mode 100644 index 0000000..7eb68e0 --- /dev/null +++ b/mkvtool-gui/Program.cs @@ -0,0 +1,23 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; + +namespace mkvtool +{ + class Program + { + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure<App>() + .UsePlatformDetect() + .LogToTrace(); + } +}
\ No newline at end of file diff --git a/mkvtool-gui/mkvtool.csproj b/mkvtool-gui/mkvtool.csproj new file mode 100644 index 0000000..0791134 --- /dev/null +++ b/mkvtool-gui/mkvtool.csproj @@ -0,0 +1,28 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>WinExe</OutputType> + <TargetFramework>net5.0</TargetFramework> + <Nullable>enable</Nullable> + <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows> + <IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX> + <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux> + </PropertyGroup> + <PropertyGroup Condition="'$(IsWindows)'=='true'"> + <DefineConstants>Windows</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition="'$(IsOSX)'=='true'"> + <DefineConstants>OSX</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition="'$(IsLinux)'=='true'"> + <DefineConstants>Linux</DefineConstants> + </PropertyGroup> + <ItemGroup> + <None Remove=".gitignore" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Avalonia" Version="0.10.8" /> + <PackageReference Include="Avalonia.Desktop" Version="0.10.8" /> + <PackageReference Include="mameolan.Avalonia.Controlz" Version="1.0.0-CI-20211017-144151" /> + <PackageReference Include="MessageBox.Avalonia" Version="1.5.3" /> + </ItemGroup> +</Project> diff --git a/mkvtool-gui/sdk.cs b/mkvtool-gui/sdk.cs new file mode 100644 index 0000000..2be1922 --- /dev/null +++ b/mkvtool-gui/sdk.cs @@ -0,0 +1,135 @@ +using System; +using System.Runtime.InteropServices; +using System.Text.Json; + +public static class mkvlib +{ +#if OSX + const string so = "mkvlib_osx.so"; +#endif +#if Linux + const string so = "mkvlib_linux.so"; +#endif +#if Windows + const string so = "mkvlib_windows.so"; +#endif + + #region imports + + [DllImport(so)] + static extern bool InitInstance(logCallback lcb); + + [DllImport(so)] + static extern IntPtr GetMKVInfo(IntPtr ptr); + + [DllImport(so)] + static extern bool DumpMKV(IntPtr file, IntPtr output, bool subset, logCallback lcb); + + [DllImport(so)] + static extern IntPtr CheckSubset(IntPtr file, logCallback lcb); + + [DllImport(so)] + static extern bool CreateMKV(IntPtr file, IntPtr tracks, IntPtr attachments, IntPtr output, IntPtr slang, + IntPtr stitle, bool clean); + + [DllImport(so)] + static extern bool ASSFontSubset(IntPtr files, IntPtr fonts, IntPtr output, bool dirSafe, logCallback lcb); + + [DllImport(so)] + static extern IntPtr QueryFolder(IntPtr dir, logCallback lcb); + + [DllImport(so)] + static extern bool DumpMKVs(IntPtr dir, IntPtr output, bool subset, logCallback lcb); + + [DllImport(so)] + static extern bool CreateMKVs(IntPtr vDir, IntPtr sDir, IntPtr fDir, IntPtr tDir, IntPtr oDir, IntPtr slang, + IntPtr stitle, bool clean, logCallback lcb); + + [DllImport(so)] + static extern bool MakeMKVs(IntPtr dir, IntPtr data, IntPtr output, IntPtr slang, IntPtr stitle, logCallback lcb); + + #endregion + + public static bool InitInstance(Action<string> lcb) + { + return InitInstance(_lcb(lcb)); + } + + public static string GetMKVInfo(string file) + { + return css(GetMKVInfo(cs(file))); + } + + public static bool DumpMKV(string file, string output, bool subset, Action<string> lcb) + { + return DumpMKV(cs(file), cs(output), subset, _lcb(lcb)); + } + + public static bool[] CheckSubset(string file, Action<string> lcb) + { + string json = css(CheckSubset(cs(file), _lcb(lcb))); + JsonDocument doc = JsonDocument.Parse(json); + bool[] result = new bool[2]; + result[0] = doc.RootElement.GetProperty("subsetted").GetBoolean(); + result[1] = doc.RootElement.GetProperty("error").GetBoolean(); + return result; + } + + public static bool CreateMKV(string file, string[] tracks, string[] attachments, string output, string slang, + string stitle, bool clean) + { + string _tracks = JsonSerializer.Serialize<string[]>(tracks); + string _attachments = JsonSerializer.Serialize<string[]>(attachments); + return CreateMKV(cs(file), cs(_tracks), cs(_attachments), cs(output), cs(slang), cs(stitle), clean); + } + + public static bool ASSFontSubset(string[] files, string fonts, string output, bool dirSafe, Action<string> lcb) + { + string _files = JsonSerializer.Serialize<string[]>(files); + return ASSFontSubset(cs(_files), cs(fonts), cs(output), dirSafe, _lcb(lcb)); + } + + public static string[] QueryFolder(string dir, Action<string> lcb) + { + string result = css(QueryFolder(cs(dir), _lcb(lcb))); + return JsonSerializer.Deserialize<string[]>(result); + } + + public static bool DumpMKVs(string dir, string output, bool subset, Action<string> lcb) + { + return DumpMKVs(cs(dir), cs(output), subset, _lcb(lcb)); + } + + public static bool CreateMKVs(string vDir, string sDir, string fDir, string tDir, string oDir, string slang, + string stitle, bool clean, Action<string> lcb) + { + return CreateMKVs(cs(vDir), cs(sDir), cs(fDir), cs(tDir), cs(oDir), cs(slang), cs(stitle), clean, _lcb(lcb)); + } + + public static bool MakeMKVs(string dir, string data, string output, string slang, string stitle, Action<string> lcb) + { + return MakeMKVs(cs(dir), cs(data), cs(output), cs(slang), cs(stitle), _lcb(lcb)); + } + + + delegate void logCallback(IntPtr ptr); + + static logCallback _lcb(Action<string> lcb) + { + return (ptr) => + { + if (lcb != null) + lcb(css(ptr)); + }; + } + + static IntPtr cs(string str) + { + return Marshal.StringToCoTaskMemUTF8(str); + } + + static string css(IntPtr ptr) + { + return Marshal.PtrToStringUTF8(ptr); + } +}
\ No newline at end of file |
