diff --git a/Source/AaxDecrypter/AaxDecrypter.csproj b/Source/AaxDecrypter/AaxDecrypter.csproj index aea11238..3e8af26e 100644 --- a/Source/AaxDecrypter/AaxDecrypter.csproj +++ b/Source/AaxDecrypter/AaxDecrypter.csproj @@ -13,7 +13,7 @@ - + diff --git a/Source/AaxDecrypter/AaxcDownloadConvertBase.cs b/Source/AaxDecrypter/AaxcDownloadConvertBase.cs index c42fc4d4..994c07ae 100644 --- a/Source/AaxDecrypter/AaxcDownloadConvertBase.cs +++ b/Source/AaxDecrypter/AaxcDownloadConvertBase.cs @@ -10,6 +10,7 @@ namespace AaxDecrypter public event EventHandler RetrievedMetadata; protected AaxFile AaxFile; + protected Mp4Operation aaxConversion; protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions) : base(outFileName, cacheDirectory, dlOptions) { } @@ -101,9 +102,9 @@ namespace AaxDecrypter public override async Task CancelAsync() { IsCanceled = true; - if (AaxFile != null) - await AaxFile.CancelAsync(); - AaxFile?.Dispose(); + if (aaxConversion != null) + await aaxConversion.CancelAsync(); + AaxFile?.Close(); CloseInputFileStream(); } } diff --git a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs index a1fdb7bd..8b198665 100644 --- a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs +++ b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs @@ -133,32 +133,37 @@ That naming may not be desirable for everyone, but it's an easy change to instea try { - ConversionResult result; - - AaxFile.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate; if (DownloadOptions.OutputFormat == OutputFormat.M4b) - result = await ConvertToMultiMp4a(splitChapters); + aaxConversion = ConvertToMultiMp4a(splitChapters); else - result = await ConvertToMultiMp3(splitChapters); + aaxConversion = ConvertToMultiMp3(splitChapters); - return result == ConversionResult.NoErrorsDetected; + aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate; + await aaxConversion; + + if (aaxConversion.IsCompletedSuccessfully) + moveMoovToBeginning(workingFileStream?.Name); + + return aaxConversion.IsCompletedSuccessfully; } catch(Exception ex) { Serilog.Log.Error(ex, "AAXClean Error"); workingFileStream?.Close(); - FileUtility.SaferDelete(workingFileStream.Name); + if (workingFileStream?.Name is not null) + FileUtility.SaferDelete(workingFileStream.Name); return false; } finally { - AaxFile.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate; + if (aaxConversion is not null) + aaxConversion.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate; Step_DownloadAudiobook_End(zeroProgress); } } - private Task ConvertToMultiMp4a(ChapterInfo splitChapters) + private Mp4Operation ConvertToMultiMp4a(ChapterInfo splitChapters) { var chapterCount = 0; return AaxFile.ConvertToMultiMp4aAsync @@ -169,7 +174,7 @@ That naming may not be desirable for everyone, but it's an easy change to instea ); } - private Task ConvertToMultiMp3(ChapterInfo splitChapters) + private Mp4Operation ConvertToMultiMp3(ChapterInfo splitChapters) { var chapterCount = 0; return AaxFile.ConvertToMultiMp3Async @@ -194,12 +199,26 @@ That naming may not be desirable for everyone, but it's an easy change to instea PartsTotal = splitChapters.Count, Title = newSplitCallback?.Chapter?.Title, }; + + moveMoovToBeginning(workingFileStream?.Name); + newSplitCallback.OutputFile = createOutputFileStream(props); newSplitCallback.TrackTitle = DownloadOptions.GetMultipartTitleName(props); newSplitCallback.TrackNumber = currentChapter; newSplitCallback.TrackCount = splitChapters.Count; } + private void moveMoovToBeginning(string filename) + { + if (DownloadOptions.OutputFormat is OutputFormat.M4b + && DownloadOptions.MoveMoovToBeginning + && filename is not null + && File.Exists(filename)) + { + Mp4File.RelocateMoovAsync(filename).GetAwaiter().GetResult(); + } + } + private FileStream createOutputFileStream(MultiConvertFileProperties multiConvertFileProperties) { var fileName = DownloadOptions.GetMultipartFileName(multiConvertFileProperties); diff --git a/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs b/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs index 288c06af..bc549b44 100644 --- a/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs +++ b/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using AAXClean; using AAXClean.Codecs; using FileManager; +using Mpeg4Lib.Util; namespace AaxDecrypter { @@ -90,16 +91,29 @@ namespace AaxDecrypter var outputFile = File.Open(OutputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); OnFileCreated(OutputFileName); - AaxFile.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate; try { - ConversionResult decryptionResult = await decryptAsync(outputFile); - var success = decryptionResult == ConversionResult.NoErrorsDetected && !IsCanceled; - if (success) + aaxConversion = decryptAsync(outputFile); + aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate; + await aaxConversion; + + outputFile.Close(); + + if (aaxConversion.IsCompletedSuccessfully + && DownloadOptions.OutputFormat is OutputFormat.M4b + && DownloadOptions.MoveMoovToBeginning) + { + aaxConversion.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate; + aaxConversion = Mp4File.RelocateMoovAsync(OutputFileName); + aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate; + await aaxConversion; + } + + if (aaxConversion.IsCompletedSuccessfully) base.OnFileCreated(OutputFileName); - return success; + return aaxConversion.IsCompletedSuccessfully; } catch(Exception ex) { @@ -110,13 +124,15 @@ namespace AaxDecrypter finally { outputFile.Close(); - AaxFile.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate; + + if (aaxConversion is not null) + aaxConversion.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate; Step_DownloadAudiobook_End(zeroProgress); } } - private Task decryptAsync(Stream outputFile) + private Mp4Operation decryptAsync(Stream outputFile) => DownloadOptions.OutputFormat == OutputFormat.Mp3 ? AaxFile.ConvertToMp3Async ( diff --git a/Source/AaxDecrypter/IDownloadOptions.cs b/Source/AaxDecrypter/IDownloadOptions.cs index 6972f067..f67e2040 100644 --- a/Source/AaxDecrypter/IDownloadOptions.cs +++ b/Source/AaxDecrypter/IDownloadOptions.cs @@ -24,6 +24,7 @@ namespace AaxDecrypter NAudio.Lame.LameConfig LameConfig { get; } bool Downsample { get; } bool MatchSourceBitrate { get; } + bool MoveMoovToBeginning { get; } string GetMultipartFileName(MultiConvertFileProperties props); string GetMultipartTitleName(MultiConvertFileProperties props); Task SaveClipsAndBookmarks(string fileName); diff --git a/Source/FileLiberator/ConvertToMp3.cs b/Source/FileLiberator/ConvertToMp3.cs index 5ec07045..1296037a 100644 --- a/Source/FileLiberator/ConvertToMp3.cs +++ b/Source/FileLiberator/ConvertToMp3.cs @@ -15,12 +15,12 @@ namespace FileLiberator public class ConvertToMp3 : AudioDecodable { public override string Name => "Convert to Mp3"; - private Mp4File m4bBook; - + private Mp4Operation Mp4Operation; + private TimeSpan bookDuration; private long fileSize; private static string Mp3FileName(string m4bPath) => Path.ChangeExtension(m4bPath ?? "", ".mp3"); - public override Task CancelAsync() => m4bBook?.CancelAsync() ?? Task.CompletedTask; + public override Task CancelAsync() => Mp4Operation?.CancelAsync() ?? Task.CompletedTask; public static bool ValidateMp3(LibraryBook libraryBook) { @@ -43,9 +43,9 @@ namespace FileLiberator var proposedMp3Path = Mp3FileName(m4bPath); if (File.Exists(proposedMp3Path) || !File.Exists(m4bPath)) continue; - m4bBook = await Task.Run(() => new Mp4File(m4bPath, FileAccess.Read)); - m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate; + var m4bBook = await Task.Run(() => new Mp4File(m4bPath, FileAccess.Read)); + bookDuration = m4bBook.Duration; fileSize = m4bBook.InputStream.Length; OnTitleDiscovered(m4bBook.AppleTags.Title); @@ -66,20 +66,20 @@ namespace FileLiberator using var mp3File = File.OpenWrite(Path.GetTempFileName()); try { - var result = await m4bBook.ConvertToMp3Async(mp3File, lameConfig); + Mp4Operation = m4bBook.ConvertToMp3Async(mp3File, lameConfig); + Mp4Operation.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate; + await Mp4Operation; - var realMp3Path = FileUtility.SaferMoveToValidPath(mp3File.Name, proposedMp3Path, Configuration.Instance.ReplacementCharacters); - OnFileCreated(libraryBook, realMp3Path); - - if (result == ConversionResult.Failed) - { - FileUtility.SaferDelete(mp3File.Name); - } - else if (result == ConversionResult.Cancelled) + if (Mp4Operation.IsCanceled) { FileUtility.SaferDelete(mp3File.Name); return new StatusHandler { "Cancelled" }; } + else + { + var realMp3Path = FileUtility.SaferMoveToValidPath(mp3File.Name, proposedMp3Path, Configuration.Instance.ReplacementCharacters, "mp3"); + OnFileCreated(libraryBook, realMp3Path); + } } catch (Exception ex) { @@ -88,6 +88,9 @@ namespace FileLiberator } finally { + if (Mp4Operation is not null) + Mp4Operation.ConversionProgressUpdate -= M4bBook_ConversionProgressUpdate; + m4bBook.InputStream.Close(); mp3File.Close(); } @@ -102,14 +105,13 @@ namespace FileLiberator private void M4bBook_ConversionProgressUpdate(object sender, ConversionProgressEventArgs e) { - var duration = m4bBook.Duration; - var remainingSecsToProcess = (duration - e.ProcessPosition).TotalSeconds; + var remainingSecsToProcess = (bookDuration - e.ProcessPosition).TotalSeconds; var estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed; - + if (double.IsNormal(estTimeRemaining)) OnStreamingTimeRemaining(TimeSpan.FromSeconds(estTimeRemaining)); - double progressPercent = 100 * e.ProcessPosition.TotalSeconds / duration.TotalSeconds; + double progressPercent = 100 * e.ProcessPosition.TotalSeconds / bookDuration.TotalSeconds; OnStreamingProgressChanged( new DownloadProgress diff --git a/Source/FileLiberator/DownloadDecryptBook.cs b/Source/FileLiberator/DownloadDecryptBook.cs index ea430c5d..d0010170 100644 --- a/Source/FileLiberator/DownloadDecryptBook.cs +++ b/Source/FileLiberator/DownloadDecryptBook.cs @@ -160,6 +160,7 @@ namespace FileLiberator AudibleKey = contentLic?.Voucher?.Key, AudibleIV = contentLic?.Voucher?.Iv, OutputFormat = outputFormat, + MoveMoovToBeginning = config.MoveMoovToBeginning, TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio, RetainEncryptedFile = config.RetainAaxFile && encrypted, StripUnabridged = config.AllowLibationFixup && config.StripUnabridged, diff --git a/Source/FileLiberator/DownloadOptions.cs b/Source/FileLiberator/DownloadOptions.cs index 7520ed15..c43d1bcd 100644 --- a/Source/FileLiberator/DownloadOptions.cs +++ b/Source/FileLiberator/DownloadOptions.cs @@ -34,6 +34,8 @@ namespace FileLiberator public bool MatchSourceBitrate { get; init; } public ReplacementCharacters ReplacementCharacters => Configuration.Instance.ReplacementCharacters; + public bool MoveMoovToBeginning { get; init; } + public string GetMultipartFileName(MultiConvertFileProperties props) => Templates.ChapterFile.GetFilename(LibraryBookDto, props); diff --git a/Source/FileManager/FileUtility.cs b/Source/FileManager/FileUtility.cs index a3f46de3..0b83866b 100644 --- a/Source/FileManager/FileUtility.cs +++ b/Source/FileManager/FileUtility.cs @@ -151,9 +151,9 @@ namespace FileManager ///
- Perform ///
- Return valid path /// - public static string SaferMoveToValidPath(LongPath source, LongPath destination, ReplacementCharacters replacements) + public static string SaferMoveToValidPath(LongPath source, LongPath destination, ReplacementCharacters replacements, string extension = null) { - var extension = Path.GetExtension(source); + extension = extension ?? Path.GetExtension(source); destination = GetValidFilename(destination, replacements, extension); SaferMove(source, destination); return destination; diff --git a/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml b/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml index ba5d1d62..04e1b655 100644 --- a/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml +++ b/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml @@ -526,15 +526,27 @@ Margin="0,5,0,5" IsChecked="{Binding !AudioSettings.DecryptToLossy, Mode=TwoWay}"> - + + + + + + + + + Configuration.IsLinux || Configuration.IsWindows; - public AudioSettings(Configuration config) { LoadSettings(config); @@ -411,6 +410,7 @@ namespace LibationAvalonia.Dialogs StripUnabridged = config.StripUnabridged; ChapterTitleTemplate = config.ChapterTitleTemplate; DecryptToLossy = config.DecryptToLossy; + MoveMoovToBeginning = config.MoveMoovToBeginning; LameTargetBitrate = config.LameTargetBitrate; LameDownsampleMono = config.LameDownsampleMono; LameConstantBitrate = config.LameConstantBitrate; @@ -433,6 +433,7 @@ namespace LibationAvalonia.Dialogs config.StripUnabridged = StripUnabridged; config.ChapterTitleTemplate = ChapterTitleTemplate; config.DecryptToLossy = DecryptToLossy; + config.MoveMoovToBeginning = MoveMoovToBeginning; config.LameTargetBitrate = LameTargetBitrate; config.LameDownsampleMono = LameDownsampleMono; config.LameConstantBitrate = LameConstantBitrate; @@ -453,6 +454,7 @@ namespace LibationAvalonia.Dialogs public string StripAudibleBrandingText { get; } = Configuration.GetDescription(nameof(Configuration.StripAudibleBrandAudio)); public string StripUnabridgedText { get; } = Configuration.GetDescription(nameof(Configuration.StripUnabridged)); public string ChapterTitleTemplateText { get; } = Configuration.GetDescription(nameof(Configuration.ChapterTitleTemplate)); + public string MoveMoovToBeginningText { get; } = Configuration.GetDescription(nameof(Configuration.MoveMoovToBeginning)); public bool CreateCueSheet { get; set; } public bool DownloadCoverArt { get; set; } @@ -462,7 +464,8 @@ namespace LibationAvalonia.Dialogs public bool MergeOpeningAndEndCredits { get; set; } public bool StripAudibleBrandAudio { get; set; } public bool StripUnabridged { get; set; } - public bool DecryptToLossy { get; set; } + public bool DecryptToLossy { get => _decryptToLossy; set => this.RaiseAndSetIfChanged(ref _decryptToLossy, value); } + public bool MoveMoovToBeginning { get; set; } public bool LameDownsampleMono { get; set; } = Design.IsDesignMode; public bool LameConstantBitrate { get; set; } = Design.IsDesignMode; diff --git a/Source/LibationFileManager/Configuration.PersistentSettings.cs b/Source/LibationFileManager/Configuration.PersistentSettings.cs index 0482a96a..e5745713 100644 --- a/Source/LibationFileManager/Configuration.PersistentSettings.cs +++ b/Source/LibationFileManager/Configuration.PersistentSettings.cs @@ -115,6 +115,9 @@ namespace LibationFileManager [Description("Decrypt to lossy format?")] public bool DecryptToLossy { get => GetNonString(defaultValue: false); set => SetNonString(value); } + [Description("Move the mp4 moov atom to the beginning of the file?")] + public bool MoveMoovToBeginning { get => GetNonString(defaultValue: false); set => SetNonString(value); } + [Description("Lame encoder target. true = Bitrate, false = Quality")] public bool LameTargetBitrate { get => GetNonString(defaultValue: false); set => SetNonString(value); } diff --git a/Source/LibationFileManager/Templates.cs b/Source/LibationFileManager/Templates.cs index 8880efd1..e1d33236 100644 --- a/Source/LibationFileManager/Templates.cs +++ b/Source/LibationFileManager/Templates.cs @@ -107,9 +107,9 @@ namespace LibationFileManager .GetFilePath(fileExtension).PathWithoutPrefix; public const string DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; - private static Regex fileDateTagRegex { get; } = new Regex(@"", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static Regex dateAddedTagRegex { get; } = new Regex(@"", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static Regex datePublishedTagRegex { get; } = new Regex(@"", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static Regex fileDateTagRegex { get; } = new Regex(@"", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static Regex dateAddedTagRegex { get; } = new Regex(@"", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static Regex datePublishedTagRegex { get; } = new Regex(@"", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static Regex ifSeriesRegex { get; } = new Regex("(.*?)<-if series>", RegexOptions.Compiled | RegexOptions.IgnoreCase); internal static FileNamingTemplate getFileNamingTemplate(LibraryBookDto libraryBookDto, string template, string dirFullPath, string extension, ReplacementCharacters replacements) diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs index f7aa4cf4..d26c7448 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs @@ -16,6 +16,7 @@ namespace LibationWinForms.Dialogs this.mergeOpeningEndCreditsCbox.Text = desc(nameof(config.MergeOpeningAndEndCredits)); this.stripAudibleBrandingCbox.Text = desc(nameof(config.StripAudibleBrandAudio)); this.stripUnabridgedCbox.Text = desc(nameof(config.StripUnabridged)); + this.moveMoovAtomCbox.Text = desc(nameof(config.MoveMoovToBeginning)); clipsBookmarksFormatCb.Items.AddRange( new object[] @@ -37,6 +38,7 @@ namespace LibationWinForms.Dialogs stripAudibleBrandingCbox.Checked = config.StripAudibleBrandAudio; convertLosslessRb.Checked = !config.DecryptToLossy; convertLossyRb.Checked = config.DecryptToLossy; + moveMoovAtomCbox.Checked = config.MoveMoovToBeginning; lameTargetBitrateRb.Checked = config.LameTargetBitrate; lameTargetQualityRb.Checked = !config.LameTargetBitrate; @@ -70,6 +72,7 @@ namespace LibationWinForms.Dialogs config.StripUnabridged = stripUnabridgedCbox.Checked; config.StripAudibleBrandAudio = stripAudibleBrandingCbox.Checked; config.DecryptToLossy = convertLossyRb.Checked; + config.MoveMoovToBeginning = moveMoovAtomCbox.Checked; config.LameTargetBitrate = lameTargetBitrateRb.Checked; config.LameDownsampleMono = lameDownsampleMonoCbox.Checked; @@ -107,6 +110,7 @@ namespace LibationWinForms.Dialogs private void convertFormatRb_CheckedChanged(object sender, EventArgs e) { + moveMoovAtomCbox.Enabled = convertLosslessRb.Checked; lameTargetRb_CheckedChanged(sender, e); LameMatchSourceBRCbox_CheckedChanged(sender, e); } diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs index 3c828c52..719a6e2c 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs @@ -76,6 +76,7 @@ this.clipsBookmarksFormatCb = new System.Windows.Forms.ComboBox(); this.downloadClipsBookmarksCbox = new System.Windows.Forms.CheckBox(); this.audiobookFixupsGb = new System.Windows.Forms.GroupBox(); + this.moveMoovAtomCbox = new System.Windows.Forms.CheckBox(); this.stripUnabridgedCbox = new System.Windows.Forms.CheckBox(); this.chapterTitleTemplateGb = new System.Windows.Forms.GroupBox(); this.chapterTitleTemplateBtn = new System.Windows.Forms.Button(); @@ -294,7 +295,7 @@ // convertLossyRb // this.convertLossyRb.AutoSize = true; - this.convertLossyRb.Location = new System.Drawing.Point(13, 136); + this.convertLossyRb.Location = new System.Drawing.Point(13, 158); this.convertLossyRb.Name = "convertLossyRb"; this.convertLossyRb.Size = new System.Drawing.Size(329, 19); this.convertLossyRb.TabIndex = 12; @@ -675,6 +676,7 @@ // // audiobookFixupsGb // + this.audiobookFixupsGb.Controls.Add(this.moveMoovAtomCbox); this.audiobookFixupsGb.Controls.Add(this.splitFilesByChapterCbox); this.audiobookFixupsGb.Controls.Add(this.stripUnabridgedCbox); this.audiobookFixupsGb.Controls.Add(this.convertLosslessRb); @@ -682,11 +684,21 @@ this.audiobookFixupsGb.Controls.Add(this.stripAudibleBrandingCbox); this.audiobookFixupsGb.Location = new System.Drawing.Point(6, 169); this.audiobookFixupsGb.Name = "audiobookFixupsGb"; - this.audiobookFixupsGb.Size = new System.Drawing.Size(403, 160); + this.audiobookFixupsGb.Size = new System.Drawing.Size(403, 185); this.audiobookFixupsGb.TabIndex = 19; this.audiobookFixupsGb.TabStop = false; this.audiobookFixupsGb.Text = "Audiobook Fix-ups"; // + // moveMoovAtomCbox + // + this.moveMoovAtomCbox.AutoSize = true; + this.moveMoovAtomCbox.Location = new System.Drawing.Point(23, 133); + this.moveMoovAtomCbox.Name = "moveMoovAtomCbox"; + this.moveMoovAtomCbox.Size = new System.Drawing.Size(188, 19); + this.moveMoovAtomCbox.TabIndex = 14; + this.moveMoovAtomCbox.Text = "[MoveMoovToBeginning desc]"; + this.moveMoovAtomCbox.UseVisualStyleBackColor = true; + // // stripUnabridgedCbox // this.stripUnabridgedCbox.AutoSize = true; @@ -701,7 +713,7 @@ // this.chapterTitleTemplateGb.Controls.Add(this.chapterTitleTemplateBtn); this.chapterTitleTemplateGb.Controls.Add(this.chapterTitleTemplateTb); - this.chapterTitleTemplateGb.Location = new System.Drawing.Point(6, 335); + this.chapterTitleTemplateGb.Location = new System.Drawing.Point(6, 360); this.chapterTitleTemplateGb.Name = "chapterTitleTemplateGb"; this.chapterTitleTemplateGb.Size = new System.Drawing.Size(842, 54); this.chapterTitleTemplateGb.TabIndex = 18; @@ -738,7 +750,7 @@ this.lameOptionsGb.Controls.Add(this.groupBox2); this.lameOptionsGb.Location = new System.Drawing.Point(415, 6); this.lameOptionsGb.Name = "lameOptionsGb"; - this.lameOptionsGb.Size = new System.Drawing.Size(433, 323); + this.lameOptionsGb.Size = new System.Drawing.Size(433, 348); this.lameOptionsGb.TabIndex = 14; this.lameOptionsGb.TabStop = false; this.lameOptionsGb.Text = "Mp3 Encoding Options"; @@ -1240,5 +1252,6 @@ private System.Windows.Forms.CheckBox useCoverAsFolderIconCb; private System.Windows.Forms.ComboBox clipsBookmarksFormatCb; private System.Windows.Forms.CheckBox downloadClipsBookmarksCbox; + private System.Windows.Forms.CheckBox moveMoovAtomCbox; } } \ No newline at end of file diff --git a/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs b/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs index 400565d3..da1760c6 100644 --- a/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs +++ b/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs @@ -153,6 +153,7 @@ namespace TemplatesTests [DataRow("", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate[h]>.m4b")] [DataRow("< filedate[yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\< filedate[yyyy]>.m4b")] [DataRow("", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate[yyyy][]>.m4b")] + [DataRow("", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate[[yyyy]]>.m4b")] [DataRow("", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate[yyyy[]]>.m4b")] [DataRow("", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate yyyy]>.m4b")] [DataRow("", @"C:\foo\bar", ".m4b", @"C:\foo\bar\<filedate ]yyyy]>.m4b")]