diff --git a/CRD/Downloader/Crunchyroll.cs b/CRD/Downloader/Crunchyroll.cs index c46e1dc..023d8b1 100644 --- a/CRD/Downloader/Crunchyroll.cs +++ b/CRD/Downloader/Crunchyroll.cs @@ -151,6 +151,7 @@ public class Crunchyroll{ CrunOptions.SelectedCalendarLanguage = "de"; CrunOptions.DlVideoOnce = true; CrunOptions.StreamEndpoint = "web/firefox"; + CrunOptions.SubsAddScaledBorder = ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; CrunOptions.History = true; @@ -1023,12 +1024,14 @@ public class Crunchyroll{ DownloadSpeed = 0, Doing = "Decrypting" }; + Queue.Refresh(); var assetIdRegexMatch = Regex.Match(chosenVideoSegments.segments[0].uri, @"/assets/(?:p/)?([^_,]+)"); var assetId = assetIdRegexMatch.Success ? assetIdRegexMatch.Groups[1].Value : null; var sessionId = Helpers.GenerateSessionId(); - Console.WriteLine("Decryption Needed, attempting to decrypt"); + //TODO change back from error + Console.Error.WriteLine("Decryption Needed, attempting to decrypt"); if (!_widevine.canDecrypt){ dlFailed = true; @@ -1057,8 +1060,9 @@ public class Crunchyroll{ var decRequestResponse = await HttpClientReq.Instance.SendHttpRequest(decRequest); if (!decRequestResponse.IsOk){ - Console.WriteLine("Request to DRM Authentication failed: "); + Console.Error.WriteLine("Request to DRM Authentication failed: "); MainWindow.Instance.ShowError("Request to DRM Authentication failed"); + dlFailed = true; return new DownloadResponse{ Data = files, Error = dlFailed, @@ -1066,7 +1070,8 @@ public class Crunchyroll{ ErrorText = "DRM Authentication failed" }; } - + //TODO change back from error + Console.Error.WriteLine("Request to DRM Authentication successful"); DrmAuthData authData = Helpers.Deserialize(decRequestResponse.ResponseContent, SettingsJsonSerializerSettings) ?? new DrmAuthData(); @@ -1076,7 +1081,8 @@ public class Crunchyroll{ var encryptionKeys = await _widevine.getKeys(chosenVideoSegments.pssh, "https://lic.drmtoday.com/license-proxy-widevine/cenc/", authDataDict); if (encryptionKeys.Count == 0){ - Console.WriteLine("Failed to get encryption keys"); + Console.Error.WriteLine("Failed to get encryption keys"); + dlFailed = true; return new DownloadResponse{ Data = files, Error = dlFailed, @@ -1093,7 +1099,8 @@ public class Crunchyroll{ var commandAudio = commandBase + $" \"{tempTsFile}.audio.enc.m4s\" \"{tempTsFile}.audio.m4s\""; if (videoDownloaded){ - Console.WriteLine("Started decrypting video"); + //TODO change back from error + Console.Error.WriteLine("Started decrypting video"); var decryptVideo = await Helpers.ExecuteCommandAsync("mp4decrypt", CfgManager.PathMP4Decrypt, commandVideo); if (!decryptVideo.IsOk){ @@ -1370,8 +1377,14 @@ public class Crunchyroll{ subsAssReqResponse.ResponseContent = '\ufeff' + subsAssReqResponse.ResponseContent; var sBodySplit = subsAssReqResponse.ResponseContent.Split(new[]{ "\r\n" }, StringSplitOptions.None).ToList(); // Insert 'ScaledBorderAndShadow: yes' after the second line - if (sBodySplit.Count > 2) - sBodySplit.Insert(2, "ScaledBorderAndShadow: yes"); + if (sBodySplit.Count > 2){ + if (options.SubsAddScaledBorder == ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes){ + sBodySplit.Insert(2, "ScaledBorderAndShadow: yes"); + }else if (options.SubsAddScaledBorder == ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo){ + sBodySplit.Insert(2, "ScaledBorderAndShadow: no"); + } + } + // Rejoin the lines back into a single string subsAssReqResponse.ResponseContent = string.Join("\r\n", sBodySplit); diff --git a/CRD/Utils/Enums/EnumCollection.cs b/CRD/Utils/Enums/EnumCollection.cs index 6080970..52fd597 100644 --- a/CRD/Utils/Enums/EnumCollection.cs +++ b/CRD/Utils/Enums/EnumCollection.cs @@ -165,6 +165,12 @@ public enum DownloadMediaType{ Subtitle, } +public enum ScaledBorderAndShadowSelection{ + DontAdd, + ScaledBorderAndShadowYes, + ScaledBorderAndShadowNo, +} + public enum SonarrCoverType{ Banner, FanArt, diff --git a/CRD/Utils/Helpers.cs b/CRD/Utils/Helpers.cs index a35d01e..d6373db 100644 --- a/CRD/Utils/Helpers.cs +++ b/CRD/Utils/Helpers.cs @@ -59,21 +59,18 @@ public class Helpers{ return milliseconds + highResTimestamp; } - public static void ConvertChapterFileForFFMPEG(string chapterFilePath) - { + public static void ConvertChapterFileForFFMPEG(string chapterFilePath){ var chapterLines = File.ReadAllLines(chapterFilePath); - var ffmpegChapterLines = new List { ";FFMETADATA1" }; + var ffmpegChapterLines = new List{ ";FFMETADATA1" }; - for (int i = 0; i < chapterLines.Length; i += 2) - { + for (int i = 0; i < chapterLines.Length; i += 2){ var timeLine = chapterLines[i]; var nameLine = chapterLines[i + 1]; var timeParts = timeLine.Split('='); var nameParts = nameLine.Split('='); - if (timeParts.Length == 2 && nameParts.Length == 2) - { + if (timeParts.Length == 2 && nameParts.Length == 2){ var startTime = TimeSpan.Parse(timeParts[1]).TotalMilliseconds; var endTime = i + 2 < chapterLines.Length ? TimeSpan.Parse(chapterLines[i + 2].Split('=')[1]).TotalMilliseconds : startTime + 10000; @@ -89,37 +86,42 @@ public class Helpers{ } public static async Task<(bool IsOk, int ErrorCode)> ExecuteCommandAsync(string type, string bin, string command){ - using (var process = new Process()){ - process.StartInfo.FileName = bin; - process.StartInfo.Arguments = command; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; - process.StartInfo.UseShellExecute = false; - process.StartInfo.CreateNoWindow = true; + try{ + using (var process = new Process()){ + process.StartInfo.FileName = bin; + process.StartInfo.Arguments = command; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; - process.OutputDataReceived += (sender, e) => { - if (!string.IsNullOrEmpty(e.Data)){ - Console.WriteLine(e.Data); - } - }; + process.OutputDataReceived += (sender, e) => { + if (!string.IsNullOrEmpty(e.Data)){ + Console.WriteLine(e.Data); + } + }; - process.ErrorDataReceived += (sender, e) => { - if (!string.IsNullOrEmpty(e.Data)){ - Console.WriteLine($"{e.Data}"); - } - }; + process.ErrorDataReceived += (sender, e) => { + if (!string.IsNullOrEmpty(e.Data)){ + Console.WriteLine($"{e.Data}"); + } + }; - process.Start(); + process.Start(); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); - await process.WaitForExitAsync(); + await process.WaitForExitAsync(); - // Define success condition more appropriately based on the application - bool isSuccess = process.ExitCode == 0; + // Define success condition more appropriately based on the application + bool isSuccess = process.ExitCode == 0; - return (IsOk: isSuccess, ErrorCode: process.ExitCode); + return (IsOk: isSuccess, ErrorCode: process.ExitCode); + } + } catch (Exception ex){ + Console.Error.WriteLine($"An error occurred: {ex.Message}"); + return (IsOk: false, ErrorCode: -1); } } diff --git a/CRD/Utils/Structs/CrDownloadOptions.cs b/CRD/Utils/Structs/CrDownloadOptions.cs index a7577a3..774ef6a 100644 --- a/CRD/Utils/Structs/CrDownloadOptions.cs +++ b/CRD/Utils/Structs/CrDownloadOptions.cs @@ -53,6 +53,9 @@ public class CrDownloadOptions{ [YamlMember(Alias = "mux_skip_subs", ApplyNamingConventions = false)] public bool SkipSubsMux{ get; set; } + [YamlMember(Alias = "subs_add_scaled_border", ApplyNamingConventions = false)] + public ScaledBorderAndShadowSelection SubsAddScaledBorder{ get; set; } + [YamlMember(Alias = "mux_mp4", ApplyNamingConventions = false)] public bool Mp4{ get; set; } diff --git a/CRD/ViewModels/SettingsPageViewModel.cs b/CRD/ViewModels/SettingsPageViewModel.cs index efeda38..e9d2d35 100644 --- a/CRD/ViewModels/SettingsPageViewModel.cs +++ b/CRD/ViewModels/SettingsPageViewModel.cs @@ -32,6 +32,17 @@ public partial class SettingsPageViewModel : ViewModelBase{ [ObservableProperty] private bool _downloadChapters = true; + + [ObservableProperty] + private bool _addScaledBorderAndShadow = false; + + [ObservableProperty] + private ComboBoxItem _selectedScaledBorderAndShadow; + + public ObservableCollection ScaledBorderAndShadow{ get; } = new(){ + new ComboBoxItem(){ Content = "ScaledBorderAndShadow: yes" }, + new ComboBoxItem(){ Content = "ScaledBorderAndShadow: no" }, + }; [ObservableProperty] private bool _muxToMp4; @@ -296,6 +307,9 @@ public partial class SettingsPageViewModel : ViewModelBase{ SonarrPort = props.Port + ""; SonarrApiKey = props.ApiKey + ""; } + + AddScaledBorderAndShadow = options.SubsAddScaledBorder is ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo or ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; + SelectedScaledBorderAndShadow = GetScaledBorderAndShadowFromOptions(options); DownloadVideo = !options.Novids; DownloadAudio = !options.Noaudio; @@ -362,6 +376,7 @@ public partial class SettingsPageViewModel : ViewModelBase{ Crunchyroll.Instance.CrunOptions.Numbers = LeadingNumbers; Crunchyroll.Instance.CrunOptions.FileName = FileName; + Crunchyroll.Instance.CrunOptions.SubsAddScaledBorder = GetScaledBorderAndShadowSelection(); List softSubs = new List(); foreach (var listBoxItem in SelectedSubLang){ @@ -434,6 +449,35 @@ public partial class SettingsPageViewModel : ViewModelBase{ CfgManager.WriteSettingsToFile(); } + + private ScaledBorderAndShadowSelection GetScaledBorderAndShadowSelection(){ + if (!AddScaledBorderAndShadow){ + return ScaledBorderAndShadowSelection.DontAdd; + } + + if (SelectedScaledBorderAndShadow.Content + "" == "ScaledBorderAndShadow: yes"){ + return ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; + } + + if (SelectedScaledBorderAndShadow.Content + "" == "ScaledBorderAndShadow: no"){ + return ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo; + } + + return ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes; + } + + private ComboBoxItem GetScaledBorderAndShadowFromOptions(CrDownloadOptions options){ + switch (options.SubsAddScaledBorder){ + case (ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes): + return ScaledBorderAndShadow.FirstOrDefault(a => a.Content != null && (string)a.Content == "ScaledBorderAndShadow: yes") ?? ScaledBorderAndShadow[0]; + case ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo: + return ScaledBorderAndShadow.FirstOrDefault(a => a.Content != null && (string)a.Content == "ScaledBorderAndShadow: no") ?? ScaledBorderAndShadow[0]; + default: + return ScaledBorderAndShadow[0]; + } + } + + private void UpdateSubAndDubString(){ if (SelectedSubLang.Count == 0){ SelectedSubs = "none"; @@ -626,6 +670,14 @@ public partial class SettingsPageViewModel : ViewModelBase{ partial void OnSelectedStreamEndpointChanged(ComboBoxItem value){ UpdateSettings(); } + + partial void OnAddScaledBorderAndShadowChanged(bool value){ + UpdateSettings(); + } + + partial void OnSelectedScaledBorderAndShadowChanged(ComboBoxItem value){ + UpdateSettings(); + } } public class MuxingParam{ diff --git a/CRD/Views/SettingsPageView.axaml b/CRD/Views/SettingsPageView.axaml index e10e123..595a556 100644 --- a/CRD/Views/SettingsPageView.axaml +++ b/CRD/Views/SettingsPageView.axaml @@ -45,7 +45,8 @@ + + + + + + + + + + - + - + @@ -182,7 +195,7 @@ - + @@ -226,13 +239,13 @@ - + - + - - + + - + - + - + +