This commit is contained in:
Robert McRackan 2021-07-28 10:02:27 -04:00
commit 4e6011711a
5 changed files with 427 additions and 281 deletions

View File

@ -0,0 +1,106 @@
using AAXClean;
using DataLayer;
using Dinah.Core.ErrorHandling;
using Dinah.Core.IO;
using FileManager;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace FileLiberator
{
public class ConvertToMp3 : IDecryptable
{
public event EventHandler<string> DecryptBegin;
public event EventHandler<string> TitleDiscovered;
public event EventHandler<string> AuthorsDiscovered;
public event EventHandler<string> NarratorsDiscovered;
public event EventHandler<byte[]> CoverImageFilepathDiscovered;
public event EventHandler<int> UpdateProgress;
public event EventHandler<TimeSpan> UpdateRemainingTime;
public event EventHandler<string> DecryptCompleted;
public event EventHandler<LibraryBook> Begin;
public event EventHandler<LibraryBook> Completed;
public event EventHandler<string> StatusUpdate;
public event EventHandler<Action<byte[]>> RequestCoverArt;
private Mp4File m4bBook;
private string Mp3FileName(LibraryBook libraryBook)
{
string m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
if (m4bPath is null)
return string.Empty;
return Path.Combine(Path.GetDirectoryName(m4bPath), Path.GetFileNameWithoutExtension(m4bPath) + ".mp3");
}
public void Cancel()
{
m4bBook?.Cancel();
}
public bool Validate(LibraryBook libraryBook) =>
AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId)?.ToLower()?.EndsWith(".m4b") == true &&
!File.Exists(Mp3FileName(libraryBook));
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
{
Begin?.Invoke(this, libraryBook);
DecryptBegin?.Invoke(this, $"Begin converting {libraryBook} to mp3");
try
{
var m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
m4bBook = new Mp4File(m4bPath, FileAccess.Read);
m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate;
TitleDiscovered?.Invoke(this, m4bBook.AppleTags.Title);
AuthorsDiscovered?.Invoke(this, m4bBook.AppleTags.FirstAuthor);
NarratorsDiscovered?.Invoke(this, m4bBook.AppleTags.Narrator);
CoverImageFilepathDiscovered?.Invoke(this, m4bBook.AppleTags.Cover);
var mp3File = File.OpenWrite(Path.GetTempFileName());
var result = await Task.Run(() => m4bBook.ConvertToMp3(mp3File));
m4bBook.InputStream.Close();
mp3File.Close();
var mp3Path = Mp3FileName(libraryBook);
FileExt.SafeMove(mp3File.Name, mp3Path);
var statusHandler = new StatusHandler();
if (result == ConversionResult.Failed)
statusHandler.AddError("Conversion failed");
return statusHandler;
}
finally
{
DecryptCompleted?.Invoke(this, $"Completed converting to mp3: {libraryBook.Book.Title}");
Completed?.Invoke(this, libraryBook);
}
}
private void M4bBook_ConversionProgressUpdate(object sender, ConversionProgressEventArgs e)
{
var duration = m4bBook.Duration;
double remainingSecsToProcess = (duration - e.ProcessPosition).TotalSeconds;
double estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed;
if (double.IsNormal(estTimeRemaining))
UpdateRemainingTime?.Invoke(this, TimeSpan.FromSeconds(estTimeRemaining));
double progressPercent = 100 * e.ProcessPosition.TotalSeconds / duration.TotalSeconds;
UpdateProgress?.Invoke(this, (int)progressPercent);
}
}
}

View File

@ -13,9 +13,9 @@ namespace LibationWinForms.BookLiberation
private string authorNames; private string authorNames;
private string narratorNames; private string narratorNames;
public void SetTitle(string title) public void SetTitle(string actionName, string title)
{ {
this.UIThread(() => this.Text = "Decrypting " + title); this.UIThread(() => this.Text = actionName + " " + title);
this.title = title; this.title = title;
updateBookInfo(); updateBookInfo();
} }

View File

@ -80,6 +80,33 @@ namespace LibationWinForms.BookLiberation
unsubscribeEvents(); unsubscribeEvents();
} }
public static async Task ConvertAllBooksAsync()
{
Serilog.Log.Logger.Information("Begin " + nameof(ConvertAllBooksAsync));
var convertBook = new ConvertToMp3();
convertBook.Begin += (_, l) => wireUpEvents(convertBook, l, "Converting");
convertBook.Completed += updateLiberatedStatus;
var automatedBackupsForm = new AutomatedBackupsForm();
var logMe = LogMe.RegisterForm(automatedBackupsForm);
void statusUpdate(object _, string str) => logMe.Info("- " + str);
void convertBookBegin(object _, LibraryBook libraryBook) => logMe.Info($"Convert Step, Begin: {libraryBook.Book}");
void convertBookCompleted(object _, LibraryBook libraryBook) => logMe.Info($"Convert Step, Completed: {libraryBook.Book}{Environment.NewLine}");
convertBook.Begin += convertBookBegin;
convertBook.StatusUpdate += statusUpdate;
convertBook.Completed += convertBookCompleted;
await new BackupLoop(logMe, convertBook, automatedBackupsForm).RunBackupAsync();
convertBook.Begin -= convertBookBegin;
convertBook.StatusUpdate -= statusUpdate;
convertBook.Completed -= convertBookCompleted;
convertBook.Completed -= updateLiberatedStatus;
}
private static BackupBook getWiredUpBackupBook(EventHandler<LibraryBook> completedAction) private static BackupBook getWiredUpBackupBook(EventHandler<LibraryBook> completedAction)
{ {
var backupBook = new BackupBook(); var backupBook = new BackupBook();
@ -261,14 +288,14 @@ namespace LibationWinForms.BookLiberation
} }
// subscribed to Begin event because a new form should be created+processed+closed on each iteration // subscribed to Begin event because a new form should be created+processed+closed on each iteration
private static void wireUpEvents(IDecryptable decryptBook, LibraryBook libraryBook) private static void wireUpEvents(IDecryptable decryptBook, LibraryBook libraryBook, string actionName = "Decrypting")
{ {
#region create form #region create form
var decryptDialog = new DecryptForm(); var decryptDialog = new DecryptForm();
#endregion #endregion
#region Set initially displayed book properties from library info. #region Set initially displayed book properties from library info.
decryptDialog.SetTitle(libraryBook.Book.Title); decryptDialog.SetTitle(actionName, libraryBook.Book.Title);
decryptDialog.SetAuthorNames(string.Join(", ", libraryBook.Book.Authors)); decryptDialog.SetAuthorNames(string.Join(", ", libraryBook.Book.Authors));
decryptDialog.SetNarratorNames(string.Join(", ", libraryBook.Book.NarratorNames)); decryptDialog.SetNarratorNames(string.Join(", ", libraryBook.Book.NarratorNames));
decryptDialog.SetCoverImage( decryptDialog.SetCoverImage(
@ -281,7 +308,7 @@ namespace LibationWinForms.BookLiberation
#region define how model actions will affect form behavior #region define how model actions will affect form behavior
void decryptBegin(object _, string __) => decryptDialog.Show(); void decryptBegin(object _, string __) => decryptDialog.Show();
void titleDiscovered(object _, string title) => decryptDialog.SetTitle(title); void titleDiscovered(object _, string title) => decryptDialog.SetTitle(actionName, title);
void authorsDiscovered(object _, string authors) => decryptDialog.SetAuthorNames(authors); void authorsDiscovered(object _, string authors) => decryptDialog.SetAuthorNames(authors);
void narratorsDiscovered(object _, string narrators) => decryptDialog.SetNarratorNames(narrators); void narratorsDiscovered(object _, string narrators) => decryptDialog.SetNarratorNames(narrators);
void coverImageFilepathDiscovered(object _, byte[] coverBytes) => decryptDialog.SetCoverImage(Dinah.Core.Drawing.ImageReader.ToImage(coverBytes)); void coverImageFilepathDiscovered(object _, byte[] coverBytes) => decryptDialog.SetCoverImage(Dinah.Core.Drawing.ImageReader.ToImage(coverBytes));

View File

@ -57,6 +57,7 @@
this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel(); this.backupsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel(); this.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
this.addFilterBtn = new System.Windows.Forms.Button(); this.addFilterBtn = new System.Windows.Forms.Button();
this.convertAllM4bToMp3ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout(); this.statusStrip1.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
@ -164,7 +165,8 @@
// //
this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.beginBookBackupsToolStripMenuItem, this.beginBookBackupsToolStripMenuItem,
this.beginPdfBackupsToolStripMenuItem}); this.beginPdfBackupsToolStripMenuItem,
this.convertAllM4bToMp3ToolStripMenuItem});
this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem"; this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem";
this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20); this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
this.liberateToolStripMenuItem.Text = "&Liberate"; this.liberateToolStripMenuItem.Text = "&Liberate";
@ -299,6 +301,13 @@
this.addFilterBtn.UseVisualStyleBackColor = true; this.addFilterBtn.UseVisualStyleBackColor = true;
this.addFilterBtn.Click += new System.EventHandler(this.AddFilterBtn_Click); this.addFilterBtn.Click += new System.EventHandler(this.AddFilterBtn_Click);
// //
// convertAllM4bToMp3ToolStripMenuItem
//
this.convertAllM4bToMp3ToolStripMenuItem.Name = "convertAllM4bToMp3ToolStripMenuItem";
this.convertAllM4bToMp3ToolStripMenuItem.Size = new System.Drawing.Size(248, 22);
this.convertAllM4bToMp3ToolStripMenuItem.Text = "Convert all M4b to Mp3";
this.convertAllM4bToMp3ToolStripMenuItem.Click += new System.EventHandler(this.convertAllM4bToMp3ToolStripMenuItem_Click);
//
// Form1 // Form1
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@ -357,5 +366,6 @@
private System.Windows.Forms.ToolStripMenuItem noAccountsYetAddAccountToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem noAccountsYetAddAccountToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportLibraryToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportLibraryToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem convertAllM4bToMp3ToolStripMenuItem;
} }
} }

View File

@ -390,6 +390,9 @@ namespace LibationWinForms
private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e) private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e)
=> await BookLiberation.ProcessorAutomationController.BackupAllPdfsAsync(updateGridRow); => await BookLiberation.ProcessorAutomationController.BackupAllPdfsAsync(updateGridRow);
private async void convertAllM4bToMp3ToolStripMenuItem_Click(object sender, EventArgs e)
=> await BookLiberation.ProcessorAutomationController.ConvertAllBooksAsync();
private void updateGridRow(object _, LibraryBook libraryBook) => currProductsGrid.RefreshRow(libraryBook.Book.AudibleProductId); private void updateGridRow(object _, LibraryBook libraryBook) => currProductsGrid.RefreshRow(libraryBook.Book.AudibleProductId);
#endregion #endregion