Merge pull request #460 from Mbucari/master

Upgrade AAXClean.Codecs to 0.5.12, add moov relocation, and fix #459
This commit is contained in:
rmcrackan 2023-01-23 22:46:20 -05:00 committed by GitHub
commit 933f663d22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 133 additions and 56 deletions

View File

@ -13,7 +13,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AAXClean.Codecs" Version="0.5.0" /> <PackageReference Include="AAXClean.Codecs" Version="0.5.12" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -10,6 +10,7 @@ namespace AaxDecrypter
public event EventHandler<AppleTags> RetrievedMetadata; public event EventHandler<AppleTags> RetrievedMetadata;
protected AaxFile AaxFile; protected AaxFile AaxFile;
protected Mp4Operation aaxConversion;
protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions) protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions)
: base(outFileName, cacheDirectory, dlOptions) { } : base(outFileName, cacheDirectory, dlOptions) { }
@ -101,9 +102,9 @@ namespace AaxDecrypter
public override async Task CancelAsync() public override async Task CancelAsync()
{ {
IsCanceled = true; IsCanceled = true;
if (AaxFile != null) if (aaxConversion != null)
await AaxFile.CancelAsync(); await aaxConversion.CancelAsync();
AaxFile?.Dispose(); AaxFile?.Close();
CloseInputFileStream(); CloseInputFileStream();
} }
} }

View File

@ -133,32 +133,37 @@ That naming may not be desirable for everyone, but it's an easy change to instea
try try
{ {
ConversionResult result;
AaxFile.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
if (DownloadOptions.OutputFormat == OutputFormat.M4b) if (DownloadOptions.OutputFormat == OutputFormat.M4b)
result = await ConvertToMultiMp4a(splitChapters); aaxConversion = ConvertToMultiMp4a(splitChapters);
else 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) catch(Exception ex)
{ {
Serilog.Log.Error(ex, "AAXClean Error"); Serilog.Log.Error(ex, "AAXClean Error");
workingFileStream?.Close(); workingFileStream?.Close();
if (workingFileStream?.Name is not null)
FileUtility.SaferDelete(workingFileStream.Name); FileUtility.SaferDelete(workingFileStream.Name);
return false; return false;
} }
finally finally
{ {
AaxFile.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate; if (aaxConversion is not null)
aaxConversion.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate;
Step_DownloadAudiobook_End(zeroProgress); Step_DownloadAudiobook_End(zeroProgress);
} }
} }
private Task<ConversionResult> ConvertToMultiMp4a(ChapterInfo splitChapters) private Mp4Operation ConvertToMultiMp4a(ChapterInfo splitChapters)
{ {
var chapterCount = 0; var chapterCount = 0;
return AaxFile.ConvertToMultiMp4aAsync 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<ConversionResult> ConvertToMultiMp3(ChapterInfo splitChapters) private Mp4Operation ConvertToMultiMp3(ChapterInfo splitChapters)
{ {
var chapterCount = 0; var chapterCount = 0;
return AaxFile.ConvertToMultiMp3Async 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, PartsTotal = splitChapters.Count,
Title = newSplitCallback?.Chapter?.Title, Title = newSplitCallback?.Chapter?.Title,
}; };
moveMoovToBeginning(workingFileStream?.Name);
newSplitCallback.OutputFile = createOutputFileStream(props); newSplitCallback.OutputFile = createOutputFileStream(props);
newSplitCallback.TrackTitle = DownloadOptions.GetMultipartTitleName(props); newSplitCallback.TrackTitle = DownloadOptions.GetMultipartTitleName(props);
newSplitCallback.TrackNumber = currentChapter; newSplitCallback.TrackNumber = currentChapter;
newSplitCallback.TrackCount = splitChapters.Count; 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) private FileStream createOutputFileStream(MultiConvertFileProperties multiConvertFileProperties)
{ {
var fileName = DownloadOptions.GetMultipartFileName(multiConvertFileProperties); var fileName = DownloadOptions.GetMultipartFileName(multiConvertFileProperties);

View File

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using AAXClean; using AAXClean;
using AAXClean.Codecs; using AAXClean.Codecs;
using FileManager; using FileManager;
using Mpeg4Lib.Util;
namespace AaxDecrypter namespace AaxDecrypter
{ {
@ -90,16 +91,29 @@ namespace AaxDecrypter
var outputFile = File.Open(OutputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); var outputFile = File.Open(OutputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
OnFileCreated(OutputFileName); OnFileCreated(OutputFileName);
AaxFile.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
try try
{ {
ConversionResult decryptionResult = await decryptAsync(outputFile); aaxConversion = decryptAsync(outputFile);
var success = decryptionResult == ConversionResult.NoErrorsDetected && !IsCanceled; aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
if (success) 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); base.OnFileCreated(OutputFileName);
return success; return aaxConversion.IsCompletedSuccessfully;
} }
catch(Exception ex) catch(Exception ex)
{ {
@ -110,13 +124,15 @@ namespace AaxDecrypter
finally finally
{ {
outputFile.Close(); outputFile.Close();
AaxFile.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate;
if (aaxConversion is not null)
aaxConversion.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate;
Step_DownloadAudiobook_End(zeroProgress); Step_DownloadAudiobook_End(zeroProgress);
} }
} }
private Task<ConversionResult> decryptAsync(Stream outputFile) private Mp4Operation decryptAsync(Stream outputFile)
=> DownloadOptions.OutputFormat == OutputFormat.Mp3 ? => DownloadOptions.OutputFormat == OutputFormat.Mp3 ?
AaxFile.ConvertToMp3Async AaxFile.ConvertToMp3Async
( (

View File

@ -24,6 +24,7 @@ namespace AaxDecrypter
NAudio.Lame.LameConfig LameConfig { get; } NAudio.Lame.LameConfig LameConfig { get; }
bool Downsample { get; } bool Downsample { get; }
bool MatchSourceBitrate { get; } bool MatchSourceBitrate { get; }
bool MoveMoovToBeginning { get; }
string GetMultipartFileName(MultiConvertFileProperties props); string GetMultipartFileName(MultiConvertFileProperties props);
string GetMultipartTitleName(MultiConvertFileProperties props); string GetMultipartTitleName(MultiConvertFileProperties props);
Task<string> SaveClipsAndBookmarks(string fileName); Task<string> SaveClipsAndBookmarks(string fileName);

View File

@ -15,12 +15,12 @@ namespace FileLiberator
public class ConvertToMp3 : AudioDecodable public class ConvertToMp3 : AudioDecodable
{ {
public override string Name => "Convert to Mp3"; public override string Name => "Convert to Mp3";
private Mp4File m4bBook; private Mp4Operation Mp4Operation;
private TimeSpan bookDuration;
private long fileSize; private long fileSize;
private static string Mp3FileName(string m4bPath) => Path.ChangeExtension(m4bPath ?? "", ".mp3"); 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) public static bool ValidateMp3(LibraryBook libraryBook)
{ {
@ -43,9 +43,9 @@ namespace FileLiberator
var proposedMp3Path = Mp3FileName(m4bPath); var proposedMp3Path = Mp3FileName(m4bPath);
if (File.Exists(proposedMp3Path) || !File.Exists(m4bPath)) continue; if (File.Exists(proposedMp3Path) || !File.Exists(m4bPath)) continue;
m4bBook = await Task.Run(() => new Mp4File(m4bPath, FileAccess.Read)); var m4bBook = await Task.Run(() => new Mp4File(m4bPath, FileAccess.Read));
m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate;
bookDuration = m4bBook.Duration;
fileSize = m4bBook.InputStream.Length; fileSize = m4bBook.InputStream.Length;
OnTitleDiscovered(m4bBook.AppleTags.Title); OnTitleDiscovered(m4bBook.AppleTags.Title);
@ -66,20 +66,20 @@ namespace FileLiberator
using var mp3File = File.OpenWrite(Path.GetTempFileName()); using var mp3File = File.OpenWrite(Path.GetTempFileName());
try 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); if (Mp4Operation.IsCanceled)
OnFileCreated(libraryBook, realMp3Path);
if (result == ConversionResult.Failed)
{
FileUtility.SaferDelete(mp3File.Name);
}
else if (result == ConversionResult.Cancelled)
{ {
FileUtility.SaferDelete(mp3File.Name); FileUtility.SaferDelete(mp3File.Name);
return new StatusHandler { "Cancelled" }; return new StatusHandler { "Cancelled" };
} }
else
{
var realMp3Path = FileUtility.SaferMoveToValidPath(mp3File.Name, proposedMp3Path, Configuration.Instance.ReplacementCharacters, "mp3");
OnFileCreated(libraryBook, realMp3Path);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -88,6 +88,9 @@ namespace FileLiberator
} }
finally finally
{ {
if (Mp4Operation is not null)
Mp4Operation.ConversionProgressUpdate -= M4bBook_ConversionProgressUpdate;
m4bBook.InputStream.Close(); m4bBook.InputStream.Close();
mp3File.Close(); mp3File.Close();
} }
@ -102,14 +105,13 @@ namespace FileLiberator
private void M4bBook_ConversionProgressUpdate(object sender, ConversionProgressEventArgs e) private void M4bBook_ConversionProgressUpdate(object sender, ConversionProgressEventArgs e)
{ {
var duration = m4bBook.Duration; var remainingSecsToProcess = (bookDuration - e.ProcessPosition).TotalSeconds;
var remainingSecsToProcess = (duration - e.ProcessPosition).TotalSeconds;
var estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed; var estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed;
if (double.IsNormal(estTimeRemaining)) if (double.IsNormal(estTimeRemaining))
OnStreamingTimeRemaining(TimeSpan.FromSeconds(estTimeRemaining)); OnStreamingTimeRemaining(TimeSpan.FromSeconds(estTimeRemaining));
double progressPercent = 100 * e.ProcessPosition.TotalSeconds / duration.TotalSeconds; double progressPercent = 100 * e.ProcessPosition.TotalSeconds / bookDuration.TotalSeconds;
OnStreamingProgressChanged( OnStreamingProgressChanged(
new DownloadProgress new DownloadProgress

View File

@ -160,6 +160,7 @@ namespace FileLiberator
AudibleKey = contentLic?.Voucher?.Key, AudibleKey = contentLic?.Voucher?.Key,
AudibleIV = contentLic?.Voucher?.Iv, AudibleIV = contentLic?.Voucher?.Iv,
OutputFormat = outputFormat, OutputFormat = outputFormat,
MoveMoovToBeginning = config.MoveMoovToBeginning,
TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio, TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio,
RetainEncryptedFile = config.RetainAaxFile && encrypted, RetainEncryptedFile = config.RetainAaxFile && encrypted,
StripUnabridged = config.AllowLibationFixup && config.StripUnabridged, StripUnabridged = config.AllowLibationFixup && config.StripUnabridged,

View File

@ -34,6 +34,8 @@ namespace FileLiberator
public bool MatchSourceBitrate { get; init; } public bool MatchSourceBitrate { get; init; }
public ReplacementCharacters ReplacementCharacters => Configuration.Instance.ReplacementCharacters; public ReplacementCharacters ReplacementCharacters => Configuration.Instance.ReplacementCharacters;
public bool MoveMoovToBeginning { get; init; }
public string GetMultipartFileName(MultiConvertFileProperties props) public string GetMultipartFileName(MultiConvertFileProperties props)
=> Templates.ChapterFile.GetFilename(LibraryBookDto, props); => Templates.ChapterFile.GetFilename(LibraryBookDto, props);

View File

@ -151,9 +151,9 @@ namespace FileManager
/// <br/>- Perform <see cref="SaferMove"/> /// <br/>- Perform <see cref="SaferMove"/>
/// <br/>- Return valid path /// <br/>- Return valid path
/// </summary> /// </summary>
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); destination = GetValidFilename(destination, replacements, extension);
SaferMove(source, destination); SaferMove(source, destination);
return destination; return destination;

View File

@ -526,15 +526,27 @@
Margin="0,5,0,5" Margin="0,5,0,5"
IsChecked="{Binding !AudioSettings.DecryptToLossy, Mode=TwoWay}"> IsChecked="{Binding !AudioSettings.DecryptToLossy, Mode=TwoWay}">
<StackPanel >
<TextBlock <TextBlock
TextWrapping="Wrap" TextWrapping="Wrap"
Text="Download my books in the original audio format (Lossless)" /> Text="Download my books in the original audio format (Lossless)" />
<CheckBox
Margin="0,0,0,5"
IsEnabled="{Binding !AudioSettings.DecryptToLossy}"
IsChecked="{Binding AudioSettings.MoveMoovToBeginning, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.MoveMoovToBeginningText}" />
</CheckBox>
</StackPanel>
</RadioButton> </RadioButton>
<RadioButton <RadioButton
Margin="0,5,0,5" Margin="0,5,0,5"
IsEnabled="{Binding AudioSettings.IsMp3Supported}"
IsChecked="{Binding AudioSettings.DecryptToLossy, Mode=TwoWay}"> IsChecked="{Binding AudioSettings.DecryptToLossy, Mode=TwoWay}">
<TextBlock <TextBlock
@ -548,7 +560,6 @@
<StackPanel <StackPanel
Grid.Row="0" Grid.Row="0"
IsVisible="{Binding AudioSettings.IsMp3Supported}"
Grid.Column="1"> Grid.Column="1">
<controls:GroupBox <controls:GroupBox

View File

@ -383,6 +383,7 @@ namespace LibationAvalonia.Dialogs
{ {
private bool _downloadClipsBookmarks; private bool _downloadClipsBookmarks;
private bool _decryptToLossy;
private bool _splitFilesByChapter; private bool _splitFilesByChapter;
private bool _allowLibationFixup; private bool _allowLibationFixup;
private bool _lameTargetBitrate; private bool _lameTargetBitrate;
@ -391,8 +392,6 @@ namespace LibationAvalonia.Dialogs
private int _lameVBRQuality; private int _lameVBRQuality;
private string _chapterTitleTemplate; private string _chapterTitleTemplate;
public bool IsMp3Supported => Configuration.IsLinux || Configuration.IsWindows;
public AudioSettings(Configuration config) public AudioSettings(Configuration config)
{ {
LoadSettings(config); LoadSettings(config);
@ -411,6 +410,7 @@ namespace LibationAvalonia.Dialogs
StripUnabridged = config.StripUnabridged; StripUnabridged = config.StripUnabridged;
ChapterTitleTemplate = config.ChapterTitleTemplate; ChapterTitleTemplate = config.ChapterTitleTemplate;
DecryptToLossy = config.DecryptToLossy; DecryptToLossy = config.DecryptToLossy;
MoveMoovToBeginning = config.MoveMoovToBeginning;
LameTargetBitrate = config.LameTargetBitrate; LameTargetBitrate = config.LameTargetBitrate;
LameDownsampleMono = config.LameDownsampleMono; LameDownsampleMono = config.LameDownsampleMono;
LameConstantBitrate = config.LameConstantBitrate; LameConstantBitrate = config.LameConstantBitrate;
@ -433,6 +433,7 @@ namespace LibationAvalonia.Dialogs
config.StripUnabridged = StripUnabridged; config.StripUnabridged = StripUnabridged;
config.ChapterTitleTemplate = ChapterTitleTemplate; config.ChapterTitleTemplate = ChapterTitleTemplate;
config.DecryptToLossy = DecryptToLossy; config.DecryptToLossy = DecryptToLossy;
config.MoveMoovToBeginning = MoveMoovToBeginning;
config.LameTargetBitrate = LameTargetBitrate; config.LameTargetBitrate = LameTargetBitrate;
config.LameDownsampleMono = LameDownsampleMono; config.LameDownsampleMono = LameDownsampleMono;
config.LameConstantBitrate = LameConstantBitrate; config.LameConstantBitrate = LameConstantBitrate;
@ -453,6 +454,7 @@ namespace LibationAvalonia.Dialogs
public string StripAudibleBrandingText { get; } = Configuration.GetDescription(nameof(Configuration.StripAudibleBrandAudio)); public string StripAudibleBrandingText { get; } = Configuration.GetDescription(nameof(Configuration.StripAudibleBrandAudio));
public string StripUnabridgedText { get; } = Configuration.GetDescription(nameof(Configuration.StripUnabridged)); public string StripUnabridgedText { get; } = Configuration.GetDescription(nameof(Configuration.StripUnabridged));
public string ChapterTitleTemplateText { get; } = Configuration.GetDescription(nameof(Configuration.ChapterTitleTemplate)); 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 CreateCueSheet { get; set; }
public bool DownloadCoverArt { get; set; } public bool DownloadCoverArt { get; set; }
@ -462,7 +464,8 @@ namespace LibationAvalonia.Dialogs
public bool MergeOpeningAndEndCredits { get; set; } public bool MergeOpeningAndEndCredits { get; set; }
public bool StripAudibleBrandAudio { get; set; } public bool StripAudibleBrandAudio { get; set; }
public bool StripUnabridged { 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 LameDownsampleMono { get; set; } = Design.IsDesignMode;
public bool LameConstantBitrate { get; set; } = Design.IsDesignMode; public bool LameConstantBitrate { get; set; } = Design.IsDesignMode;

View File

@ -115,6 +115,9 @@ namespace LibationFileManager
[Description("Decrypt to lossy format?")] [Description("Decrypt to lossy format?")]
public bool DecryptToLossy { get => GetNonString(defaultValue: false); set => SetNonString(value); } 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")] [Description("Lame encoder target. true = Bitrate, false = Quality")]
public bool LameTargetBitrate { get => GetNonString(defaultValue: false); set => SetNonString(value); } public bool LameTargetBitrate { get => GetNonString(defaultValue: false); set => SetNonString(value); }

View File

@ -107,9 +107,9 @@ namespace LibationFileManager
.GetFilePath(fileExtension).PathWithoutPrefix; .GetFilePath(fileExtension).PathWithoutPrefix;
public const string DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; public const string DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
private static Regex fileDateTagRegex { get; } = new Regex(@"<file\s*?date\s*?(?:\[([^\[\]]*?)\]){0,1}\s*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static Regex fileDateTagRegex { get; } = new Regex(@"<file\s*?date\s*?(?:\[([^\[\]]*?)\]\s*?)?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static Regex dateAddedTagRegex { get; } = new Regex(@"<date\s*?added\s*?(?:\[([^\[\]]*?)\]){0,1}\s*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static Regex dateAddedTagRegex { get; } = new Regex(@"<date\s*?added\s*?(?:\[([^\[\]]*?)\]\s*?)?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static Regex datePublishedTagRegex { get; } = new Regex(@"<pub\s*?date\s*?(?:\[([^\[\]]*?)\]){0,1}\s*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static Regex datePublishedTagRegex { get; } = new Regex(@"<pub\s*?date\s*?(?:\[([^\[\]]*?)\]\s*?)?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static Regex ifSeriesRegex { get; } = new Regex("<if series->(.*?)<-if series>", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static Regex ifSeriesRegex { get; } = new Regex("<if series->(.*?)<-if series>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
internal static FileNamingTemplate getFileNamingTemplate(LibraryBookDto libraryBookDto, string template, string dirFullPath, string extension, ReplacementCharacters replacements) internal static FileNamingTemplate getFileNamingTemplate(LibraryBookDto libraryBookDto, string template, string dirFullPath, string extension, ReplacementCharacters replacements)

View File

@ -16,6 +16,7 @@ namespace LibationWinForms.Dialogs
this.mergeOpeningEndCreditsCbox.Text = desc(nameof(config.MergeOpeningAndEndCredits)); this.mergeOpeningEndCreditsCbox.Text = desc(nameof(config.MergeOpeningAndEndCredits));
this.stripAudibleBrandingCbox.Text = desc(nameof(config.StripAudibleBrandAudio)); this.stripAudibleBrandingCbox.Text = desc(nameof(config.StripAudibleBrandAudio));
this.stripUnabridgedCbox.Text = desc(nameof(config.StripUnabridged)); this.stripUnabridgedCbox.Text = desc(nameof(config.StripUnabridged));
this.moveMoovAtomCbox.Text = desc(nameof(config.MoveMoovToBeginning));
clipsBookmarksFormatCb.Items.AddRange( clipsBookmarksFormatCb.Items.AddRange(
new object[] new object[]
@ -37,6 +38,7 @@ namespace LibationWinForms.Dialogs
stripAudibleBrandingCbox.Checked = config.StripAudibleBrandAudio; stripAudibleBrandingCbox.Checked = config.StripAudibleBrandAudio;
convertLosslessRb.Checked = !config.DecryptToLossy; convertLosslessRb.Checked = !config.DecryptToLossy;
convertLossyRb.Checked = config.DecryptToLossy; convertLossyRb.Checked = config.DecryptToLossy;
moveMoovAtomCbox.Checked = config.MoveMoovToBeginning;
lameTargetBitrateRb.Checked = config.LameTargetBitrate; lameTargetBitrateRb.Checked = config.LameTargetBitrate;
lameTargetQualityRb.Checked = !config.LameTargetBitrate; lameTargetQualityRb.Checked = !config.LameTargetBitrate;
@ -70,6 +72,7 @@ namespace LibationWinForms.Dialogs
config.StripUnabridged = stripUnabridgedCbox.Checked; config.StripUnabridged = stripUnabridgedCbox.Checked;
config.StripAudibleBrandAudio = stripAudibleBrandingCbox.Checked; config.StripAudibleBrandAudio = stripAudibleBrandingCbox.Checked;
config.DecryptToLossy = convertLossyRb.Checked; config.DecryptToLossy = convertLossyRb.Checked;
config.MoveMoovToBeginning = moveMoovAtomCbox.Checked;
config.LameTargetBitrate = lameTargetBitrateRb.Checked; config.LameTargetBitrate = lameTargetBitrateRb.Checked;
config.LameDownsampleMono = lameDownsampleMonoCbox.Checked; config.LameDownsampleMono = lameDownsampleMonoCbox.Checked;
@ -107,6 +110,7 @@ namespace LibationWinForms.Dialogs
private void convertFormatRb_CheckedChanged(object sender, EventArgs e) private void convertFormatRb_CheckedChanged(object sender, EventArgs e)
{ {
moveMoovAtomCbox.Enabled = convertLosslessRb.Checked;
lameTargetRb_CheckedChanged(sender, e); lameTargetRb_CheckedChanged(sender, e);
LameMatchSourceBRCbox_CheckedChanged(sender, e); LameMatchSourceBRCbox_CheckedChanged(sender, e);
} }

View File

@ -76,6 +76,7 @@
this.clipsBookmarksFormatCb = new System.Windows.Forms.ComboBox(); this.clipsBookmarksFormatCb = new System.Windows.Forms.ComboBox();
this.downloadClipsBookmarksCbox = new System.Windows.Forms.CheckBox(); this.downloadClipsBookmarksCbox = new System.Windows.Forms.CheckBox();
this.audiobookFixupsGb = new System.Windows.Forms.GroupBox(); this.audiobookFixupsGb = new System.Windows.Forms.GroupBox();
this.moveMoovAtomCbox = new System.Windows.Forms.CheckBox();
this.stripUnabridgedCbox = new System.Windows.Forms.CheckBox(); this.stripUnabridgedCbox = new System.Windows.Forms.CheckBox();
this.chapterTitleTemplateGb = new System.Windows.Forms.GroupBox(); this.chapterTitleTemplateGb = new System.Windows.Forms.GroupBox();
this.chapterTitleTemplateBtn = new System.Windows.Forms.Button(); this.chapterTitleTemplateBtn = new System.Windows.Forms.Button();
@ -294,7 +295,7 @@
// convertLossyRb // convertLossyRb
// //
this.convertLossyRb.AutoSize = true; 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.Name = "convertLossyRb";
this.convertLossyRb.Size = new System.Drawing.Size(329, 19); this.convertLossyRb.Size = new System.Drawing.Size(329, 19);
this.convertLossyRb.TabIndex = 12; this.convertLossyRb.TabIndex = 12;
@ -675,6 +676,7 @@
// //
// audiobookFixupsGb // audiobookFixupsGb
// //
this.audiobookFixupsGb.Controls.Add(this.moveMoovAtomCbox);
this.audiobookFixupsGb.Controls.Add(this.splitFilesByChapterCbox); this.audiobookFixupsGb.Controls.Add(this.splitFilesByChapterCbox);
this.audiobookFixupsGb.Controls.Add(this.stripUnabridgedCbox); this.audiobookFixupsGb.Controls.Add(this.stripUnabridgedCbox);
this.audiobookFixupsGb.Controls.Add(this.convertLosslessRb); this.audiobookFixupsGb.Controls.Add(this.convertLosslessRb);
@ -682,11 +684,21 @@
this.audiobookFixupsGb.Controls.Add(this.stripAudibleBrandingCbox); this.audiobookFixupsGb.Controls.Add(this.stripAudibleBrandingCbox);
this.audiobookFixupsGb.Location = new System.Drawing.Point(6, 169); this.audiobookFixupsGb.Location = new System.Drawing.Point(6, 169);
this.audiobookFixupsGb.Name = "audiobookFixupsGb"; 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.TabIndex = 19;
this.audiobookFixupsGb.TabStop = false; this.audiobookFixupsGb.TabStop = false;
this.audiobookFixupsGb.Text = "Audiobook Fix-ups"; 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 // stripUnabridgedCbox
// //
this.stripUnabridgedCbox.AutoSize = true; this.stripUnabridgedCbox.AutoSize = true;
@ -701,7 +713,7 @@
// //
this.chapterTitleTemplateGb.Controls.Add(this.chapterTitleTemplateBtn); this.chapterTitleTemplateGb.Controls.Add(this.chapterTitleTemplateBtn);
this.chapterTitleTemplateGb.Controls.Add(this.chapterTitleTemplateTb); 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.Name = "chapterTitleTemplateGb";
this.chapterTitleTemplateGb.Size = new System.Drawing.Size(842, 54); this.chapterTitleTemplateGb.Size = new System.Drawing.Size(842, 54);
this.chapterTitleTemplateGb.TabIndex = 18; this.chapterTitleTemplateGb.TabIndex = 18;
@ -738,7 +750,7 @@
this.lameOptionsGb.Controls.Add(this.groupBox2); this.lameOptionsGb.Controls.Add(this.groupBox2);
this.lameOptionsGb.Location = new System.Drawing.Point(415, 6); this.lameOptionsGb.Location = new System.Drawing.Point(415, 6);
this.lameOptionsGb.Name = "lameOptionsGb"; 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.TabIndex = 14;
this.lameOptionsGb.TabStop = false; this.lameOptionsGb.TabStop = false;
this.lameOptionsGb.Text = "Mp3 Encoding Options"; this.lameOptionsGb.Text = "Mp3 Encoding Options";
@ -1240,5 +1252,6 @@
private System.Windows.Forms.CheckBox useCoverAsFolderIconCb; private System.Windows.Forms.CheckBox useCoverAsFolderIconCb;
private System.Windows.Forms.ComboBox clipsBookmarksFormatCb; private System.Windows.Forms.ComboBox clipsBookmarksFormatCb;
private System.Windows.Forms.CheckBox downloadClipsBookmarksCbox; private System.Windows.Forms.CheckBox downloadClipsBookmarksCbox;
private System.Windows.Forms.CheckBox moveMoovAtomCbox;
} }
} }

View File

@ -153,6 +153,7 @@ namespace TemplatesTests
[DataRow("<filedate[h]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[h].m4b")] [DataRow("<filedate[h]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[h].m4b")]
[DataRow("< filedate[yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\ filedate[yyyy].m4b")] [DataRow("< filedate[yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\ filedate[yyyy].m4b")]
[DataRow("<filedate[yyyy][]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[yyyy][].m4b")] [DataRow("<filedate[yyyy][]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[yyyy][].m4b")]
[DataRow("<filedate[[yyyy]]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[[yyyy]].m4b")]
[DataRow("<filedate[yyyy[]]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[yyyy[]].m4b")] [DataRow("<filedate[yyyy[]]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate[yyyy[]].m4b")]
[DataRow("<filedate yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate yyyy].m4b")] [DataRow("<filedate yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate yyyy].m4b")]
[DataRow("<filedate ]yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate ]yyyy].m4b")] [DataRow("<filedate ]yyyy]>", @"C:\foo\bar", ".m4b", @"C:\foo\bar\filedate ]yyyy].m4b")]