From 215c539920a0c4de9fb00acb00bb8addc9a70ab1 Mon Sep 17 00:00:00 2001 From: Robert McRackan Date: Mon, 12 Apr 2021 14:52:19 -0400 Subject: [PATCH] Bug fix: first line in cue file was incorrectly formatted --- AaxDecrypter/UNTESTED/AaxToM4bConverter.cs | 48 ++++++---------- AaxDecrypter/UNTESTED/Chapters.cs | 32 ++--------- AaxDecrypter/UNTESTED/Cue.cs | 65 ++++++++++++++++++++++ AaxDecrypter/UNTESTED/NFO.cs | 46 ++++++++------- FileLiberator/UNTESTED/DecryptBook.cs | 22 +++++--- LibationLauncher/LibationLauncher.csproj | 2 +- LibationLauncher/UNTESTED/Program.cs | 12 +++- 7 files changed, 133 insertions(+), 94 deletions(-) create mode 100644 AaxDecrypter/UNTESTED/Cue.cs diff --git a/AaxDecrypter/UNTESTED/AaxToM4bConverter.cs b/AaxDecrypter/UNTESTED/AaxToM4bConverter.cs index 18a7e68c..c1b00d11 100644 --- a/AaxDecrypter/UNTESTED/AaxToM4bConverter.cs +++ b/AaxDecrypter/UNTESTED/AaxToM4bConverter.cs @@ -102,8 +102,8 @@ namespace AaxDecrypter var defaultFilename = Path.Combine( Path.GetDirectoryName(inputFileName), - getASCIITag(tags.author), - getASCIITag(tags.title) + ".m4b" + PathLib.ToPathSafeString(tags.author), + PathLib.ToPathSafeString(tags.title) + ".m4b" ); // set default name @@ -111,12 +111,6 @@ namespace AaxDecrypter await Task.Run(() => saveCover(inputFileName)); } - private string getASCIITag(string property) - { - foreach (char ch in new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars())) - property = property.Replace(ch.ToString(), ""); - return property; - } private void saveCover(string aaxFile) { @@ -126,19 +120,14 @@ namespace AaxDecrypter private void printPrelim() { - Console.WriteLine("Audible Book ID = " + tags.id); + Console.WriteLine($"Audible Book ID = {tags.id}"); - Console.WriteLine("Book: " + tags.title); - Console.WriteLine("Author: " + tags.author); - Console.WriteLine("Narrator: " + tags.narrator); - Console.WriteLine("Year: " + tags.year); - Console.WriteLine("Total Time: " - + tags.duration.GetTotalTimeFormatted() - + " in " + chapters.Count() + " chapters"); - Console.WriteLine("WARNING-Source is " - + encodingInfo.originalBitrate + " kbits @ " - + encodingInfo.sampleRate + "Hz, " - + encodingInfo.channels + " channels"); + Console.WriteLine($"Book: {tags.title}"); + Console.WriteLine($"Author: {tags.author}"); + Console.WriteLine($"Narrator: {tags.narrator}"); + Console.WriteLine($"Year: {tags.year}"); + Console.WriteLine($"Total Time: {tags.duration.GetTotalTimeFormatted()} in {chapters.Count} chapters"); + Console.WriteLine($"WARNING-Source is {encodingInfo.originalBitrate} kbits @ {encodingInfo.sampleRate}Hz, {encodingInfo.channels} channels"); } public bool Run() @@ -159,19 +148,14 @@ namespace AaxDecrypter public void SetOutputFilename(string outFileName) { - outputFileName = outFileName; - - if (Path.GetExtension(outputFileName) != ".m4b") - outputFileName = outputFileWithNewExt(".m4b"); - - if (File.Exists(outputFileName)) - File.Delete(outputFileName); - + outputFileName = PathLib.ReplaceExtension(outFileName, ".m4b"); outDir = Path.GetDirectoryName(outputFileName); + + if (File.Exists(outputFileName)) + File.Delete(outputFileName); } - private string outputFileWithNewExt(string extension) - => Path.Combine(outDir, Path.GetFileNameWithoutExtension(outputFileName) + '.' + extension.Trim('.')); + private string outputFileWithNewExt(string extension) => PathLib.ReplaceExtension(outputFileName, extension); public bool Step1_CreateDir() { @@ -349,13 +333,13 @@ namespace AaxDecrypter public bool End_CreateCue() { - File.WriteAllText(outputFileWithNewExt(".cue"), chapters.GetCuefromChapters(Path.GetFileName(outputFileName))); + File.WriteAllText(outputFileWithNewExt(".cue"), Cue.CreateContents(Path.GetFileName(outputFileName), chapters)); return true; } public bool End_CreateNfo() { - File.WriteAllText(outputFileWithNewExt(".nfo"), NFO.CreateNfoContents(AppName, tags, encodingInfo, chapters)); + File.WriteAllText(outputFileWithNewExt(".nfo"), NFO.CreateContents(AppName, tags, encodingInfo, chapters)); return true; } } diff --git a/AaxDecrypter/UNTESTED/Chapters.cs b/AaxDecrypter/UNTESTED/Chapters.cs index 146e5b05..d83ef3f2 100644 --- a/AaxDecrypter/UNTESTED/Chapters.cs +++ b/AaxDecrypter/UNTESTED/Chapters.cs @@ -41,40 +41,20 @@ namespace AaxDecrypter return chapters; } - // subtract 1 b/c end time marker is a real entry but isn't a real chapter - public int Count() => markers.Count - 1; + // subtract 1 b/c end time marker is a real entry but isn't a real chapter. ie: fencepost + public int Count => markers.Count - 1; - public string GetCuefromChapters(string fileName) + public IEnumerable GetBeginningTimes() { - var stringBuilder = new StringBuilder(); - if (fileName != "") - { - stringBuilder.Append("FILE \"" + fileName + "\" MP4\n"); - } - - for (var i = 0; i < Count(); i++) - { - var chapter = i + 1; - - var timeSpan = TimeSpan.FromSeconds(markers[i]); - var minutes = Math.Floor(timeSpan.TotalMinutes).ToString(); - var seconds = timeSpan.Seconds.ToString("D2"); - var milliseconds = (timeSpan.Milliseconds / 10).ToString("D2"); - string str = minutes + ":" + seconds + ":" + milliseconds; - - stringBuilder.Append("TRACK " + chapter + " AUDIO\n"); - stringBuilder.Append(" TITLE \"Chapter " + chapter.ToString("D2") + "\"\n"); - stringBuilder.Append(" INDEX 01 " + str + "\n"); - } - - return stringBuilder.ToString(); + for (var i = 0; i < Count; i++) + yield return TimeSpan.FromSeconds(markers[i]); } public string GenerateFfmpegChapters() { var stringBuilder = new StringBuilder(); - for (var i = 0; i < Count(); i++) + for (var i = 0; i < Count; i++) { var chapter = i + 1; diff --git a/AaxDecrypter/UNTESTED/Cue.cs b/AaxDecrypter/UNTESTED/Cue.cs new file mode 100644 index 00000000..5401dc25 --- /dev/null +++ b/AaxDecrypter/UNTESTED/Cue.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using Dinah.Core; + +namespace AaxDecrypter +{ + public static class Cue + { + public static string CreateContents(string filePath, Chapters chapters) + { + var stringBuilder = new StringBuilder(); + + stringBuilder.AppendLine(GetFileLine(filePath, "MP3")); + + var beginningTimes = chapters.GetBeginningTimes().ToList(); + for (var i = 0; i < beginningTimes.Count; i++) + { + var chapter = i + 1; + + var timeSpan = beginningTimes[i]; + var minutes = Math.Floor(timeSpan.TotalMinutes).ToString(); + var seconds = timeSpan.Seconds.ToString("D2"); + var milliseconds = (timeSpan.Milliseconds / 10).ToString("D2"); + var time = minutes + ":" + seconds + ":" + milliseconds; + + stringBuilder.AppendLine($"TRACK {chapter} AUDIO"); + stringBuilder.AppendLine($" TITLE \"Chapter {chapter:D2}\""); + stringBuilder.AppendLine($" INDEX 01 {time}"); + } + + return stringBuilder.ToString(); + } + + public static void UpdateFileName(FileInfo cueFileInfo, string audioFilePath) + => UpdateFileName(cueFileInfo.FullName, audioFilePath); + + public static void UpdateFileName(string cueFilePath, FileInfo audioFileInfo) + => UpdateFileName(cueFilePath, audioFileInfo.FullName); + + public static void UpdateFileName(FileInfo cueFileInfo, FileInfo audioFileInfo) + => UpdateFileName(cueFileInfo.FullName, audioFileInfo.FullName); + + public static void UpdateFileName(string cueFilePath, string audioFilePath) + { + var cueContents = File.ReadAllLines(cueFilePath); + + for (var i = 0; i < cueContents.Length; i++) + { + var line = cueContents[i]; + if (!line.Trim().StartsWith("FILE") || !line.Contains(" ")) + continue; + + var fileTypeBegins = line.LastIndexOf(" ") + 1; + cueContents[i] = GetFileLine(audioFilePath, line[fileTypeBegins..]); + break; + } + + File.WriteAllLines(cueFilePath, cueContents); + } + + private static string GetFileLine(string filePath, string audioType) => $"FILE {Path.GetFileName(filePath).SurroundWithQuotes()} {audioType}"; + } +} diff --git a/AaxDecrypter/UNTESTED/NFO.cs b/AaxDecrypter/UNTESTED/NFO.cs index 4e80a1ef..906cee38 100644 --- a/AaxDecrypter/UNTESTED/NFO.cs +++ b/AaxDecrypter/UNTESTED/NFO.cs @@ -2,48 +2,46 @@ { public static class NFO { - public static string CreateNfoContents(string ripper, Tags tags, EncodingInfo encodingInfo, Chapters chapters) + public static string CreateContents(string ripper, Tags tags, EncodingInfo encodingInfo, Chapters chapters) { - int _hours = (int)tags.duration.TotalHours; - string myDuration + var _hours = (int)tags.duration.TotalHours; + var myDuration = (_hours > 0 ? _hours + " hours, " : "") + tags.duration.Minutes + " minutes, " + tags.duration.Seconds + " seconds"; - string str4 + var header = "General Information\r\n" + "===================\r\n" - + " Title: " + tags.title + "\r\n" - + " Author: " + tags.author + "\r\n" - + " Read By: " + tags.narrator + "\r\n" - + " Copyright: " + tags.year + "\r\n" - + " Audiobook Copyright: " + tags.year + "\r\n"; + + $" Title: {tags.title}\r\n" + + $" Author: {tags.author}\r\n" + + $" Read By: {tags.narrator}\r\n" + + $" Copyright: {tags.year}\r\n" + + $" Audiobook Copyright: {tags.year}\r\n"; if (tags.genre != "") - { - str4 = str4 + " Genre: " + tags.genre + "\r\n"; - } + header += $" Genre: {tags.genre}\r\n"; - string s - = str4 - + " Publisher: " + tags.publisher + "\r\n" - + " Duration: " + myDuration + "\r\n" - + " Chapters: " + chapters.Count() + "\r\n" + var s + = header + + $" Publisher: {tags.publisher}\r\n" + + $" Duration: {myDuration}\r\n" + + $" Chapters: {chapters.Count}\r\n" + "\r\n" + "\r\n" + "Media Information\r\n" + "=================\r\n" + " Source Format: Audible AAX\r\n" - + " Source Sample Rate: " + encodingInfo.sampleRate + " Hz\r\n" - + " Source Channels: " + encodingInfo.channels + "\r\n" - + " Source Bitrate: " + encodingInfo.originalBitrate + " kbits\r\n" + + $" Source Sample Rate: {encodingInfo.sampleRate} Hz\r\n" + + $" Source Channels: {encodingInfo.channels}\r\n" + + $" Source Bitrate: {encodingInfo.originalBitrate} kbits\r\n" + "\r\n" + " Lossless Encode: Yes\r\n" + " Encoded Codec: AAC / M4B\r\n" - + " Encoded Sample Rate: " + encodingInfo.sampleRate + " Hz\r\n" - + " Encoded Channels: " + encodingInfo.channels + "\r\n" - + " Encoded Bitrate: " + encodingInfo.originalBitrate + " kbits\r\n" + + $" Encoded Sample Rate: {encodingInfo.sampleRate} Hz\r\n" + + $" Encoded Channels: {encodingInfo.channels}\r\n" + + $" Encoded Bitrate: {encodingInfo.originalBitrate} kbits\r\n" + "\r\n" - + " Ripper: " + ripper + "\r\n" + + $" Ripper: {ripper}\r\n" + "\r\n" + "\r\n" + "Book Description\r\n" diff --git a/FileLiberator/UNTESTED/DecryptBook.cs b/FileLiberator/UNTESTED/DecryptBook.cs index fbf06850..685d9c41 100644 --- a/FileLiberator/UNTESTED/DecryptBook.cs +++ b/FileLiberator/UNTESTED/DecryptBook.cs @@ -144,15 +144,21 @@ namespace FileLiberator var musicFileExt = Path.GetExtension(outputAudioFilename).Trim('.'); - foreach (var f in sortedFiles) - { - var dest = AudibleFileStorage.Audio.IsFileTypeMatch(f) - // audio filename: safetitle_limit50char + " [" + productId + "]." + audio_ext - ? FileUtility.GetValidFilename(destinationDir, product.Title, musicFileExt, product.AudibleProductId) - // non-audio filename: safetitle_limit50char + " [" + productId + "][" + audio_ext +"]." + non_audio_ext - : FileUtility.GetValidFilename(destinationDir, product.Title, f.Extension, product.AudibleProductId, musicFileExt); + // audio filename: safetitle_limit50char + " [" + productId + "]." + audio_ext + var audioFileName = FileUtility.GetValidFilename(destinationDir, product.Title, musicFileExt, product.AudibleProductId); - File.Move(f.FullName, dest); + foreach (var f in sortedFiles) + { + var dest + = AudibleFileStorage.Audio.IsFileTypeMatch(f) + ? audioFileName + // non-audio filename: safetitle_limit50char + " [" + productId + "][" + audio_ext +"]." + non_audio_ext + : FileUtility.GetValidFilename(destinationDir, product.Title, f.Extension, product.AudibleProductId, musicFileExt); + + if (Path.GetExtension(dest).Trim('.').ToLower() == "cue") + Cue.UpdateFileName(f, audioFileName); + + File.Move(f.FullName, dest); } return destinationDir; diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj index 2c534211..a022d679 100644 --- a/LibationLauncher/LibationLauncher.csproj +++ b/LibationLauncher/LibationLauncher.csproj @@ -13,7 +13,7 @@ win-x64 - 4.2.3.1 + 4.2.4.1 diff --git a/LibationLauncher/UNTESTED/Program.cs b/LibationLauncher/UNTESTED/Program.cs index 3271296a..dc53641f 100644 --- a/LibationLauncher/UNTESTED/Program.cs +++ b/LibationLauncher/UNTESTED/Program.cs @@ -380,19 +380,25 @@ namespace LibationLauncher try { LibationWinForms.BookLiberation.ProcessorAutomationController.DownloadFileAsync(zipUrl, selectedPath).GetAwaiter().GetResult(); - MessageBox.Show($"File downloaded"); + MessageBox.Show("File downloaded"); } catch (Exception ex) { - MessageBox.Show($"ERROR: {ex.Message}\r\n{ex.StackTrace}"); + Error(ex, "Error downloading update"); } } catch (Exception ex) { - MessageBox.Show($"Error checking for update. ERROR: {ex.Message}\r\n{ex.StackTrace}"); + Error(ex, "Error checking for update"); } } + private static void Error(Exception ex, string message) + { + Log.Logger.Error(ex, message); + MessageBox.Show($"{message}\r\nSee log for details"); + } + private static void logStartupState() { var config = Configuration.Instance;