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 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;
|
||||
updateBookInfo();
|
||||
}
|
||||
|
||||
@ -80,6 +80,33 @@ namespace LibationWinForms.BookLiberation
|
||||
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)
|
||||
{
|
||||
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
|
||||
private static void wireUpEvents(IDecryptable decryptBook, LibraryBook libraryBook)
|
||||
private static void wireUpEvents(IDecryptable decryptBook, LibraryBook libraryBook, string actionName = "Decrypting")
|
||||
{
|
||||
#region create form
|
||||
var decryptDialog = new DecryptForm();
|
||||
#endregion
|
||||
|
||||
#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.SetNarratorNames(string.Join(", ", libraryBook.Book.NarratorNames));
|
||||
decryptDialog.SetCoverImage(
|
||||
@ -281,7 +308,7 @@ namespace LibationWinForms.BookLiberation
|
||||
#region define how model actions will affect form behavior
|
||||
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 narratorsDiscovered(object _, string narrators) => decryptDialog.SetNarratorNames(narrators);
|
||||
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.pdfsCountsLbl = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.addFilterBtn = new System.Windows.Forms.Button();
|
||||
this.convertAllM4bToMp3ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
@ -164,7 +165,8 @@
|
||||
//
|
||||
this.liberateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.beginBookBackupsToolStripMenuItem,
|
||||
this.beginPdfBackupsToolStripMenuItem});
|
||||
this.beginPdfBackupsToolStripMenuItem,
|
||||
this.convertAllM4bToMp3ToolStripMenuItem});
|
||||
this.liberateToolStripMenuItem.Name = "liberateToolStripMenuItem";
|
||||
this.liberateToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.liberateToolStripMenuItem.Text = "&Liberate";
|
||||
@ -299,6 +301,13 @@
|
||||
this.addFilterBtn.UseVisualStyleBackColor = true;
|
||||
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
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
@ -357,5 +366,6 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem noAccountsYetAddAccountToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
|
||||
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)
|
||||
=> 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);
|
||||
#endregion
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user