using AAXClean; using DataLayer; using Dinah.Core.ErrorHandling; using Dinah.Core.IO; using FileManager; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FileLiberator { public class ConvertToMp3 : IDecryptable { private Mp4File m4bBook; public event EventHandler DecryptBegin; public event EventHandler TitleDiscovered; public event EventHandler AuthorsDiscovered; public event EventHandler NarratorsDiscovered; public event EventHandler CoverImageFilepathDiscovered; public event EventHandler UpdateProgress; public event EventHandler UpdateRemainingTime; public event EventHandler DecryptCompleted; public event EventHandler Begin; public event EventHandler Completed; public event EventHandler StatusUpdate; public event EventHandler> RequestCoverArt; private string Mp3FileName(LibraryBook libraryBook) { string m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); 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 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); } } }