diff --git a/Source/AaxDecrypter/AaxDecrypter.csproj b/Source/AaxDecrypter/AaxDecrypter.csproj
index 5498c67f..3e8af26e 100644
--- a/Source/AaxDecrypter/AaxDecrypter.csproj
+++ b/Source/AaxDecrypter/AaxDecrypter.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs
index 325bdd8c..8b198665 100644
--- a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs
+++ b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs
@@ -140,6 +140,10 @@ That naming may not be desirable for everyone, but it's an easy change to instea
aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
await aaxConversion;
+
+ if (aaxConversion.IsCompletedSuccessfully)
+ moveMoovToBeginning(workingFileStream?.Name);
+
return aaxConversion.IsCompletedSuccessfully;
}
catch(Exception ex)
@@ -195,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 e41389a6..b0348f7d 100644
--- a/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs
+++ b/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs
@@ -98,12 +98,21 @@ namespace AaxDecrypter
aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
await aaxConversion;
- if (aaxConversion.IsCompletedSuccessfully)
+ outputFile.Close();
+
+ if (aaxConversion.IsCompletedSuccessfully
+ && DownloadOptions.OutputFormat is OutputFormat.M4b
+ && DownloadOptions.MoveMoovToBeginning)
{
- outputFile.Close();
- base.OnFileCreated(OutputFileName);
+ aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
+ aaxConversion = Mp4File.RelocateMoovAsync(OutputFileName);
+ aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
+ await aaxConversion;
}
+ if (aaxConversion.IsCompletedSuccessfully)
+ base.OnFileCreated(OutputFileName);
+
return aaxConversion.IsCompletedSuccessfully;
}
catch(Exception ex)
@@ -117,7 +126,7 @@ namespace AaxDecrypter
outputFile.Close();
if (aaxConversion is not null)
- aaxConversion.ConversionProgressUpdate += AaxFile_ConversionProgressUpdate;
+ aaxConversion.ConversionProgressUpdate -= AaxFile_ConversionProgressUpdate;
Step_DownloadAudiobook_End(zeroProgress);
}
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/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/LibationAvalonia/Dialogs/SettingsDialog.axaml b/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml
index ba5d1d62..b1e973ff 100644
--- a/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml
+++ b/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml
@@ -2,8 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d" d:DesignWidth="850" d:DesignHeight="620"
- MinWidth="800" MinHeight="620"
+ mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="680"
+ MinWidth="900" MinHeight="680"
x:Class="LibationAvalonia.Dialogs.SettingsDialog"
xmlns:controls="clr-namespace:LibationAvalonia.Controls"
Title="Edit Settings"
@@ -34,6 +34,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -117,7 +489,6 @@
-
@@ -390,367 +761,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml.cs b/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml.cs
index 468be111..48edebec 100644
--- a/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml.cs
+++ b/Source/LibationAvalonia/Dialogs/SettingsDialog.axaml.cs
@@ -383,6 +383,7 @@ namespace LibationAvalonia.Dialogs
{
private bool _downloadClipsBookmarks;
+ private bool _decryptToLossy;
private bool _splitFilesByChapter;
private bool _allowLibationFixup;
private bool _lameTargetBitrate;
@@ -391,8 +392,6 @@ namespace LibationAvalonia.Dialogs
private int _lameVBRQuality;
private string _chapterTitleTemplate;
- public bool IsMp3Supported => 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/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