Merge branch 'master' of https://github.com/rmcrackan/Libation
This commit is contained in:
commit
4e6011711a
106
FileLiberator/ConvertToMp3.cs
Normal file
106
FileLiberator/ConvertToMp3.cs
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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));
|
||||||
|
|||||||
12
LibationWinForms/Form1.Designer.cs
generated
12
LibationWinForms/Form1.Designer.cs
generated
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user