feat: modernize to .NET 8, split into Core/Cli/Gui (#3)

* feat: modernize to .NET 8, split into Core/Cli/Gui projects

Core: shared converter library (cross-platform)

Cli: console app with CLI args (cross-platform)

Gui: WinForms app (Windows only, uses Core library)

- Split into 3 projects sharing ConvertSRTto3DASS.Core

- Rewrite SrtConverter with clean public API

- Add CLI entry point with stdlib argument parsing

- Redesign GUI with GroupBox layout, flat buttons, modern fonts

- Update README with publish commands

* feat: add drag-and-drop to GUI

* refactor: rename GUI controls to proper PascalCase identifiers

---------

Co-authored-by: imrayya <imrayya@users.noreply.github.com>
This commit is contained in:
2026-06-24 18:02:05 +07:00
committed by GitHub
parent 743900f2f7
commit 40ce11d068
27 changed files with 961 additions and 1839 deletions
+151
View File
@@ -0,0 +1,151 @@
using System.Text;
namespace ConvertSRTto3DASS;
internal static class Cli
{
public static void Run(string[] args)
{
if (args.Length == 0 || args[0] is "--help" or "-h" or "/?")
{
PrintUsage();
return;
}
var inputPath = args[0];
if (!File.Exists(inputPath))
{
Console.Error.WriteLine($"Input file not found: {inputPath}");
return;
}
// Parse options
var options = new ConversionOptions
{
InputPath = inputPath,
Mode = "sbs",
ResX = 1280,
ResY = 720,
BaseResX = 1280,
BaseResY = 720,
FontSize = 16,
OffsetX = 4,
BottomOffset = 18,
SbsSideMargin = 640,
OuTopMargin = 385,
VerticalMargin = 25,
};
int i = 1;
while (i < args.Length)
{
var arg = args[i].Trim().ToLowerInvariant();
switch (arg)
{
case "--mode":
options.Mode = GetNextArg(i++);
break;
case "--resx":
options.ResX = ParseInt(i++);
break;
case "--resy":
options.ResY = ParseInt(i++);
break;
case "--baseresx":
options.BaseResX = ParseInt(i++);
break;
case "--baseresy":
options.BaseResY = ParseInt(i++);
break;
case "--fontsize":
options.FontSize = ParseInt(i++);
break;
case "--offsetx":
options.OffsetX = ParseInt(i++);
break;
case "--bottomoffset":
options.BottomOffset = ParseInt(i++);
break;
case "--sbssidemargin":
options.SbsSideMargin = ParseInt(i++);
break;
case "--outopmargin":
options.OuTopMargin = ParseInt(i++);
break;
case "--verticalmargin":
options.VerticalMargin = ParseInt(i++);
break;
case "--output":
options.OutputPath = GetNextArg(i++);
break;
default:
Console.Error.WriteLine($"Unknown argument: {args[i]}");
return;
}
i++;
}
// Default output path
if (string.IsNullOrEmpty(options.OutputPath))
{
options.OutputPath = Path.Combine(
Path.GetDirectoryName(options.InputPath) ?? ".",
Path.GetFileNameWithoutExtension(options.InputPath) + ".ass");
}
// Run conversion
try
{
Console.WriteLine($"Input: {options.InputPath}");
Console.WriteLine($"Output: {options.OutputPath}");
Console.WriteLine($"Mode: {options.Mode}");
Console.WriteLine($"Resolution: {options.ResX}x{options.ResY}");
Console.WriteLine($"Base resolution: {options.BaseResX}x{options.BaseResY}");
Console.WriteLine($"Font size: {options.FontSize}");
var result = SrtConverter.Convert(options);
Console.WriteLine($"Parsed: {result.SubtitleCount} subtitle blocks");
Console.WriteLine("Conversion complete.");
}
catch (Exception ex)
{
Console.Error.WriteLine($"ERROR: {ex.Message}");
Console.Error.WriteLine(ex.ToString());
}
string GetNextArg(int index) => index + 1 < args.Length ? args[index + 1] : throw new ArgumentException($"Missing value for {args[index]}");
int ParseInt(int index)
{
var val = index + 1 < args.Length ? args[index + 1] : throw new ArgumentException($"Missing value for {args[index]}");
return int.TryParse(val, out var n) ? n : throw new ArgumentException($"Invalid value for {args[index]}: {val}");
}
}
static void PrintUsage()
{
Console.WriteLine("Usage:");
Console.WriteLine(" ConvertSRTto3DASS.exe <input.srt> [options]");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine(" --mode sbs|ou|rg");
Console.WriteLine(" --resx <number>");
Console.WriteLine(" --resy <number>");
Console.WriteLine(" --baseresx <number> (scaling reference width, default 1280)");
Console.WriteLine(" --baseresy <number> (scaling reference height, default 720)");
Console.WriteLine(" --fontsize <number>");
Console.WriteLine(" --offsetx <number> (RG eye separation)");
Console.WriteLine(" --bottomoffset <number> (RG bottom offset)");
Console.WriteLine(" --sbssidemargin <number> (SBS side margin)");
Console.WriteLine(" --outopmargin <number> (OU top subtitle margin)");
Console.WriteLine(" --verticalmargin <number> (general vertical/bottom margin)");
Console.WriteLine(" --output <path>");
Console.WriteLine();
Console.WriteLine("Examples:");
Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode sbs");
Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode ou --resx 1280 --resy 720");
Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode rg --offsetx 6 --bottomoffset 24");
Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --resx 1920 --resy 1080 --baseresx 1280 --baseresy 720");
Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --sbssidemargin 220 --verticalmargin 16");
Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --outopmargin 180 --fontsize 20 --output ""movie_custom.ass""");
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Company>imrayya</Company>
<Copyright>Copyright © imrayya 2021-2026</Copyright>
<AssemblyName>ConvertSRTto3DASS</AssemblyName>
<RootNamespace>ConvertSRTto3DASS</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ConvertSRTto3DASS.Core\ConvertSRTto3DASS.Core.csproj" />
</ItemGroup>
</Project>
+6
View File
@@ -0,0 +1,6 @@
namespace ConvertSRTto3DASS;
internal static class Program
{
static void Main(string[] args) => Cli.Run(args);
}