diff --git a/Source/AaxDecrypter/AudiobookDownloadBase.cs b/Source/AaxDecrypter/AudiobookDownloadBase.cs index 44031193..932e7273 100644 --- a/Source/AaxDecrypter/AudiobookDownloadBase.cs +++ b/Source/AaxDecrypter/AudiobookDownloadBase.cs @@ -118,11 +118,7 @@ namespace AaxDecrypter public abstract Task CancelAsync(); protected abstract Task Step_DownloadAndDecryptAudiobookAsync(); - public virtual void SetCoverArt(byte[] coverArt) - { - if (coverArt is not null) - OnRetrievedCoverArt(coverArt); - } + public virtual void SetCoverArt(byte[] coverArt) { } protected void OnRetrievedTitle(string title) => RetrievedTitle?.Invoke(this, title); diff --git a/Source/AaxDecrypter/NetworkFileStream.cs b/Source/AaxDecrypter/NetworkFileStream.cs index 2a8be0de..a11351cd 100644 --- a/Source/AaxDecrypter/NetworkFileStream.cs +++ b/Source/AaxDecrypter/NetworkFileStream.cs @@ -127,6 +127,8 @@ namespace AaxDecrypter { ArgumentValidator.EnsureNotNullOrWhiteSpace(uriToSameFile?.AbsoluteUri, nameof(uriToSameFile)); + if (Path.GetFileName(uriToSameFile.LocalPath) != Path.GetFileName(Uri.LocalPath)) + throw new ArgumentException($"New uri to the same file must have the same file name."); if (uriToSameFile.Host != Uri.Host) throw new ArgumentException($"New uri to the same file must have the same host.\r\n Old Host :{Uri.Host}\r\nNew Host: {uriToSameFile.Host}"); if (DownloadTask is not null) diff --git a/Source/FileLiberator/DownloadDecryptBook.cs b/Source/FileLiberator/DownloadDecryptBook.cs index c2d9701a..9ecc8ae0 100644 --- a/Source/FileLiberator/DownloadDecryptBook.cs +++ b/Source/FileLiberator/DownloadDecryptBook.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using AaxDecrypter; using ApplicationServices; +using AudibleApi.Common; using DataLayer; using Dinah.Core; using Dinah.Core.ErrorHandling; @@ -124,12 +125,12 @@ namespace FileLiberator var quality = (AudibleApi.DownloadQuality)config.FileDownloadQuality; var api = await libraryBook.GetApiAsync(); var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, quality); - using var dlOptions = BuildDownloadOptions(libraryBook, config, contentLic); + using var dlOptions = BuildDownloadOptions(libraryBook, config, contentLic); var outFileName = AudibleFileStorage.Audio.GetInProgressFilename(libraryBook, dlOptions.OutputFormat.ToString().ToLower()); var cacheDir = AudibleFileStorage.DownloadsInProgressDirectory; - if (contentLic.DrmType != AudibleApi.Common.DrmType.Adrm) + if (contentLic.DrmType != DrmType.Adrm) abDownloader = new UnencryptedAudiobookDownloader(outFileName, cacheDir, dlOptions); else { @@ -152,16 +153,34 @@ namespace FileLiberator abDownloader.RetrievedCoverArt += AaxcDownloader_RetrievedCoverArt; abDownloader.FileCreated += (_, path) => OnFileCreated(libraryBook, path); - // REAL WORK DONE HERE - return await abDownloader.RunAsync(); + // REAL WORK DONE HERE + var success = await abDownloader.RunAsync(); + + if (success && config.SaveMetadataToFile) + { + var metadataFile = Templates.File.GetFilename(dlOptions.LibraryBookDto, Path.GetDirectoryName(outFileName), ".metadata.json"); + + saveMetadata(libraryBook, contentLic.ContentMetadata, metadataFile); + } + return success; } - private DownloadOptions BuildDownloadOptions(LibraryBook libraryBook, Configuration config, AudibleApi.Common.ContentLicense contentLic) + private void saveMetadata(LibraryBook libraryBook, ContentMetadata contentMetadata, string fileName) + { + var export = Newtonsoft.Json.Linq.JObject.FromObject(LibToDtos.ToDtos(new[] { libraryBook })[0]); + export.Add(nameof(contentMetadata.ChapterInfo), Newtonsoft.Json.Linq.JObject.FromObject(contentMetadata.ChapterInfo)); + export.Add(nameof(contentMetadata.ContentReference), Newtonsoft.Json.Linq.JObject.FromObject(contentMetadata.ContentReference)); + + File.WriteAllText(fileName, export.ToString()); + OnFileCreated(libraryBook, fileName); + } + + private DownloadOptions BuildDownloadOptions(LibraryBook libraryBook, Configuration config, ContentLicense contentLic) { //If DrmType != Adrm the delivered file is an unencrypted mp3. var outputFormat - = contentLic.DrmType != AudibleApi.Common.DrmType.Adrm || (config.AllowLibationFixup && config.DecryptToLossy) + = contentLic.DrmType != DrmType.Adrm || (config.AllowLibationFixup && config.DecryptToLossy) ? OutputFormat.Mp3 : OutputFormat.M4b; @@ -183,7 +202,11 @@ namespace FileLiberator RuntimeLength = TimeSpan.FromMilliseconds(contentLic?.ContentMetadata?.ChapterInfo?.RuntimeLengthMs ?? 0), }; - var chapters = flattenChapters(contentLic.ContentMetadata.ChapterInfo.Chapters).OrderBy(c => c.StartOffsetMs).ToList(); + var titleConcat = config.CombineNestedChapterTitles ? ": " : null; + var chapters + = flattenChapters(contentLic.ContentMetadata.ChapterInfo.Chapters, titleConcat) + .OrderBy(c => c.StartOffsetMs) + .ToList(); if (config.MergeOpeningAndEndCredits) combineCredits(chapters); @@ -280,14 +303,19 @@ namespace FileLiberator */ - public static List flattenChapters(IList chapters, string titleConcat = ": ") + public static List flattenChapters(IList chapters, string titleConcat = ": ") { - List chaps = new(); + List chaps = new(); foreach (var c in chapters) { if (c.Chapters is null) chaps.Add(c); + else if (titleConcat is null) + { + chaps.Add(c); + chaps.AddRange(flattenChapters(c.Chapters)); + } else { if (c.LengthMs < 10000) @@ -305,13 +333,12 @@ namespace FileLiberator child.Title = $"{c.Title}{titleConcat}{child.Title}"; chaps.AddRange(children); - c.Chapters = null; } } return chaps; } - public static void combineCredits(IList chapters) + public static void combineCredits(IList chapters) { if (chapters.Count > 1 && chapters[0].Title == "Opening Credits") { @@ -351,11 +378,15 @@ namespace FileLiberator private void AaxcDownloader_RetrievedCoverArt(object _, byte[] e) { + if (Configuration.Instance.AllowLibationFixup) + { + e = OnRequestCoverArt(); + abDownloader.SetCoverArt(e); + } + if (e is not null) OnCoverImageDiscovered(e); - else if (Configuration.Instance.AllowLibationFixup) - abDownloader.SetCoverArt(OnRequestCoverArt()); - } + } /// Move new files to 'Books' directory /// Return directory if audiobook file(s) were successfully created and can be located on disk. Else null. diff --git a/Source/LibationAvalonia/Controls/Settings/Audio.axaml b/Source/LibationAvalonia/Controls/Settings/Audio.axaml index 0972b388..23a8a10c 100644 --- a/Source/LibationAvalonia/Controls/Settings/Audio.axaml +++ b/Source/LibationAvalonia/Controls/Settings/Audio.axaml @@ -73,7 +73,15 @@ - + + + + + diff --git a/Source/LibationAvalonia/Controls/Settings/DownloadDecrypt.axaml b/Source/LibationAvalonia/Controls/Settings/DownloadDecrypt.axaml index ce9aa989..a075857d 100644 --- a/Source/LibationAvalonia/Controls/Settings/DownloadDecrypt.axaml +++ b/Source/LibationAvalonia/Controls/Settings/DownloadDecrypt.axaml @@ -165,18 +165,32 @@ - + Orientation="Horizontal"> - + - + + + + + + + + + diff --git a/Source/LibationAvalonia/ViewModels/MainVM.BackupCounts.cs b/Source/LibationAvalonia/ViewModels/MainVM.BackupCounts.cs index 48f719eb..b0a103ea 100644 --- a/Source/LibationAvalonia/ViewModels/MainVM.BackupCounts.cs +++ b/Source/LibationAvalonia/ViewModels/MainVM.BackupCounts.cs @@ -1,7 +1,10 @@ using ApplicationServices; using Avalonia.Threading; +using DataLayer; using LibationFileManager; using ReactiveUI; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace LibationAvalonia.ViewModels @@ -41,16 +44,17 @@ namespace LibationAvalonia.ViewModels private void Configure_BackupCounts() { - MainWindow.Loaded += setBackupCounts; - LibraryCommands.LibrarySizeChanged += setBackupCounts; - LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts; + MainWindow.LibraryLoaded += (_, e) => setBackupCounts(e.Where(l => !l.Book.IsEpisodeParent())); + LibraryCommands.LibrarySizeChanged += (_,_) => setBackupCounts(); + LibraryCommands.BookUserDefinedItemCommitted += (_, _) => setBackupCounts(); } - private async void setBackupCounts(object _, object __) + private async void setBackupCounts(IEnumerable libraryBooks = null) { if (updateCountsTask?.IsCompleted ?? true) { - updateCountsTask = Task.Run(() => LibraryCommands.GetCounts()); + libraryBooks ??= DbContexts.GetLibrary_Flat_NoTracking(); + updateCountsTask = Task.Run(() => LibraryCommands.GetCounts(libraryBooks)); var stats = await updateCountsTask; await Dispatcher.UIThread.InvokeAsync(() => LibraryStats = stats); diff --git a/Source/LibationAvalonia/ViewModels/ProcessBookViewModel.cs b/Source/LibationAvalonia/ViewModels/ProcessBookViewModel.cs index 80d16cf8..941310b8 100644 --- a/Source/LibationAvalonia/ViewModels/ProcessBookViewModel.cs +++ b/Source/LibationAvalonia/ViewModels/ProcessBookViewModel.cs @@ -264,9 +264,12 @@ namespace LibationAvalonia.ViewModels private byte[] AudioDecodable_RequestCoverArt(object sender, EventArgs e) { - byte[] coverData = PictureStorage - .GetPictureSynchronously( - new PictureDefinition(LibraryBook.Book.PictureId, PictureSize._500x500)); + var quality + = Configuration.Instance.FileDownloadQuality == Configuration.DownloadQuality.High + ? new PictureDefinition(LibraryBook.Book.PictureLarge, PictureSize.Native) + : new PictureDefinition(LibraryBook.Book.PictureId, PictureSize._500x500); + + byte[] coverData = PictureStorage.GetPictureSynchronously(quality); AudioDecodable_CoverImageDiscovered(this, coverData); return coverData; diff --git a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs index 8f6f1485..7797bd6e 100644 --- a/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs +++ b/Source/LibationAvalonia/ViewModels/ProductsDisplayViewModel.cs @@ -91,37 +91,21 @@ namespace LibationAvalonia.ViewModels #region Display Functions - internal void BindToGrid(List dbBooks) + internal async Task BindToGridAsync(List dbBooks) { GridEntries = new(SOURCE) { Filter = CollectionFilter }; - var geList = dbBooks - .Where(lb => lb.Book.IsProduct()) - .Select(b => new LibraryBookEntry(b)) - .ToList(); + var geList = await LibraryBookEntry.GetAllProductsAsync(dbBooks); - var episodes = dbBooks.Where(lb => lb.Book.IsEpisodeChild()).ToList(); + var seriesEntries = await SeriesEntry.GetAllSeriesEntriesAsync(dbBooks); - var seriesBooks = dbBooks.Where(lb => lb.Book.IsEpisodeParent()).ToList(); - - foreach (var parent in seriesBooks) - { - var seriesEpisodes = episodes.FindChildren(parent); - - if (!seriesEpisodes.Any()) continue; - - var seriesEntry = new SeriesEntry(parent, seriesEpisodes); - seriesEntry.Liberate.Expanded = false; - - geList.Add(seriesEntry); - } + SOURCE.AddRange(geList.Concat(seriesEntries).OrderDescending(new RowComparer(null))); //Create the filtered-in list before adding entries to avoid a refresh - FilteredInGridEntries = geList.Union(geList.OfType().SelectMany(s => s.Children)).FilterEntries(FilterString); - SOURCE.AddRange(geList.OrderDescending(new RowComparer(null))); + FilteredInGridEntries = geList.Union(seriesEntries.SelectMany(s => s.Children)).FilterEntries(FilterString); //Add all children beneath their parent - foreach (var series in SOURCE.OfType().ToList()) + foreach (var series in seriesEntries) { var seriesIndex = SOURCE.IndexOf(series); foreach (var child in series.Children) diff --git a/Source/LibationAvalonia/ViewModels/Settings/AudioSettingsVM.cs b/Source/LibationAvalonia/ViewModels/Settings/AudioSettingsVM.cs index ef418af6..f8f96dfb 100644 --- a/Source/LibationAvalonia/ViewModels/Settings/AudioSettingsVM.cs +++ b/Source/LibationAvalonia/ViewModels/Settings/AudioSettingsVM.cs @@ -44,6 +44,7 @@ namespace LibationAvalonia.ViewModels.Settings public void LoadSettings(Configuration config) { CreateCueSheet = config.CreateCueSheet; + CombineNestedChapterTitles = config.CombineNestedChapterTitles; AllowLibationFixup = config.AllowLibationFixup; DownloadCoverArt = config.DownloadCoverArt; RetainAaxFile = config.RetainAaxFile; @@ -71,6 +72,7 @@ namespace LibationAvalonia.ViewModels.Settings public void SaveSettings(Configuration config) { config.CreateCueSheet = CreateCueSheet; + config.CombineNestedChapterTitles = CombineNestedChapterTitles; config.AllowLibationFixup = AllowLibationFixup; config.DownloadCoverArt = DownloadCoverArt; config.RetainAaxFile = RetainAaxFile; @@ -99,7 +101,10 @@ namespace LibationAvalonia.ViewModels.Settings public AvaloniaList ClipBookmarkFormats { get; } = new(Enum.GetValues()); public string FileDownloadQualityText { get; } = Configuration.GetDescription(nameof(Configuration.FileDownloadQuality)); public string CreateCueSheetText { get; } = Configuration.GetDescription(nameof(Configuration.CreateCueSheet)); + public string CombineNestedChapterTitlesText { get; } = Configuration.GetDescription(nameof(Configuration.CombineNestedChapterTitles)); + public string CombineNestedChapterTitlesTip => Configuration.GetHelpText(nameof(CombineNestedChapterTitles)); public string AllowLibationFixupText { get; } = Configuration.GetDescription(nameof(Configuration.AllowLibationFixup)); + public string AllowLibationFixupTip => Configuration.GetHelpText(nameof(AllowLibationFixup)); public string DownloadCoverArtText { get; } = Configuration.GetDescription(nameof(Configuration.DownloadCoverArt)); public string RetainAaxFileText { get; } = Configuration.GetDescription(nameof(Configuration.RetainAaxFile)); public string SplitFilesByChapterText { get; } = Configuration.GetDescription(nameof(Configuration.SplitFilesByChapter)); @@ -110,6 +115,7 @@ namespace LibationAvalonia.ViewModels.Settings public string MoveMoovToBeginningText { get; } = Configuration.GetDescription(nameof(Configuration.MoveMoovToBeginning)); public bool CreateCueSheet { get; set; } + public bool CombineNestedChapterTitles { get; set; } public bool DownloadCoverArt { get; set; } public bool RetainAaxFile { get; set; } public bool DownloadClipsBookmarks { get => _downloadClipsBookmarks; set => this.RaiseAndSetIfChanged(ref _downloadClipsBookmarks, value); } diff --git a/Source/LibationAvalonia/ViewModels/Settings/DownloadDecryptSettingsVM.cs b/Source/LibationAvalonia/ViewModels/Settings/DownloadDecryptSettingsVM.cs index 4b0270d0..67ec2567 100644 --- a/Source/LibationAvalonia/ViewModels/Settings/DownloadDecryptSettingsVM.cs +++ b/Source/LibationAvalonia/ViewModels/Settings/DownloadDecryptSettingsVM.cs @@ -38,6 +38,7 @@ namespace LibationAvalonia.ViewModels.Settings ChapterFileTemplate = config.ChapterFileTemplate; InProgressDirectory = config.InProgress; UseCoverAsFolderIcon = config.UseCoverAsFolderIcon; + SaveMetadataToFile = config.SaveMetadataToFile; } public void SaveSettings(Configuration config) @@ -54,9 +55,11 @@ namespace LibationAvalonia.ViewModels.Settings config.InProgress = InProgressDirectory; config.UseCoverAsFolderIcon = UseCoverAsFolderIcon; + config.SaveMetadataToFile = SaveMetadataToFile; } public string UseCoverAsFolderIconText { get; } = Configuration.GetDescription(nameof(Configuration.UseCoverAsFolderIcon)); + public string SaveMetadataToFileText { get; } = Configuration.GetDescription(nameof(Configuration.SaveMetadataToFile)); public string BadBookGroupboxText { get; } = Configuration.GetDescription(nameof(Configuration.BadBook)); public string BadBookAskText { get; } = Configuration.BadBookAction.Ask.GetDescription(); public string BadBookAbortText { get; } = Configuration.BadBookAction.Abort.GetDescription(); @@ -72,6 +75,7 @@ namespace LibationAvalonia.ViewModels.Settings public string FileTemplate { get => _fileTemplate; set { this.RaiseAndSetIfChanged(ref _fileTemplate, value); } } public string ChapterFileTemplate { get => _chapterFileTemplate; set { this.RaiseAndSetIfChanged(ref _chapterFileTemplate, value); } } public bool UseCoverAsFolderIcon { get; set; } + public bool SaveMetadataToFile { get; set; } public bool BadBookAsk { get; set; } public bool BadBookAbort { get; set; } diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml.cs b/Source/LibationAvalonia/Views/MainWindow.axaml.cs index 96e0edb6..c708258c 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml.cs +++ b/Source/LibationAvalonia/Views/MainWindow.axaml.cs @@ -61,7 +61,7 @@ namespace LibationAvalonia.Views if (QuickFilters.UseDefault) await ViewModel.PerformFilter(QuickFilters.Filters.FirstOrDefault()); - ViewModel.ProductsDisplay.BindToGrid(dbBooks); + await ViewModel.ProductsDisplay.BindToGridAsync(dbBooks); } private void selectAndFocusSearchBox() diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml b/Source/LibationAvalonia/Views/ProductsDisplay.axaml index a7fb4bf9..2df7e0d1 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml @@ -84,13 +84,13 @@ - + - + diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs index c5313917..3349599e 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs @@ -51,7 +51,7 @@ namespace LibationAvalonia.Views catch { sampleEntries = new(); } var pdvm = new ProductsDisplayViewModel(); - pdvm.BindToGrid(sampleEntries); + _ = pdvm.BindToGridAsync(sampleEntries); DataContext = pdvm; return; @@ -78,163 +78,177 @@ namespace LibationAvalonia.Views public void ProductsGrid_CellContextMenuStripNeeded(object sender, DataGridCellContextMenuStripNeededEventArgs args) { - // stop light - if (args.Column.SortMemberPath == "Liberate") + if (args.Column.SortMemberPath is not "Liberate" and not "Cover") { - var entry = args.GridEntry; - - #region Liberate all Episodes - - if (entry.Liberate.IsSeries) - { - var liberateEpisodesMenuItem = new MenuItem() - { - Header = "_Liberate All Episodes", - IsEnabled = ((ISeriesEntry)entry).Children.Any(c => c.Liberate.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload) - }; - - args.ContextMenuItems.Add(liberateEpisodesMenuItem); - - liberateEpisodesMenuItem.Click += (_, _) => LiberateSeriesClicked?.Invoke(this, ((ISeriesEntry)entry)); - } - - #endregion - #region Set Download status to Downloaded - - var setDownloadMenuItem = new MenuItem() - { - Header = "Set Download status to '_Downloaded'", - IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated || entry.Liberate.IsSeries - }; - - args.ContextMenuItems.Add(setDownloadMenuItem); - - if (entry.Liberate.IsSeries) - setDownloadMenuItem.Click += (_, __) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.Liberated); - else - setDownloadMenuItem.Click += (_, __) => entry.LibraryBook.UpdateBookStatus(LiberatedStatus.Liberated); - - #endregion - #region Set Download status to Not Downloaded - - var setNotDownloadMenuItem = new MenuItem() - { - Header = "Set Download status to '_Not Downloaded'", - IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated || entry.Liberate.IsSeries - }; - - args.ContextMenuItems.Add(setNotDownloadMenuItem); - - if (entry.Liberate.IsSeries) - setNotDownloadMenuItem.Click += (_, __) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.NotLiberated); - else - setNotDownloadMenuItem.Click += (_, __) => entry.LibraryBook.UpdateBookStatus(LiberatedStatus.NotLiberated); - - #endregion - #region Remove from library - - var removeMenuItem = new MenuItem() { Header = "_Remove from library" }; - - args.ContextMenuItems.Add(removeMenuItem); - - if (entry.Liberate.IsSeries) - removeMenuItem.Click += async (_, __) => await ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).RemoveBooksAsync(); - else - removeMenuItem.Click += async (_, __) => await Task.Run(entry.LibraryBook.RemoveBook); - - #endregion - - if (!entry.Liberate.IsSeries) - { - #region Locate file - var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; - - args.ContextMenuItems.Add(locateFileMenuItem); - - locateFileMenuItem.Click += async (_, __) => - { - try - { - var window = this.GetParentWindow(); - - var openFileDialogOptions = new FilePickerOpenOptions - { - Title = $"Locate the audio file for '{entry.Book.TitleWithSubtitle}'", - AllowMultiple = false, - SuggestedStartLocation = await window.StorageProvider.TryGetFolderFromPathAsync(Configuration.Instance.Books.PathWithoutPrefix), - FileTypeFilter = new FilePickerFileType[] - { - new("All files (*.*)") { Patterns = new[] { "*" } }, - } - }; - - var selectedFiles = await window.StorageProvider.OpenFilePickerAsync(openFileDialogOptions); - var selectedFile = selectedFiles.SingleOrDefault()?.TryGetLocalPath(); - - if (selectedFile is not null) - FilePathCache.Insert(entry.AudibleProductId, selectedFile); - } - catch (Exception ex) - { - var msg = "Error saving book's location"; - await MessageBox.ShowAdminAlert(null, msg, msg, ex); - } - }; - - #endregion - #region Convert to Mp3 - var convertToMp3MenuItem = new MenuItem - { - Header = "_Convert to Mp3", - IsEnabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated - }; - args.ContextMenuItems.Add(convertToMp3MenuItem); - - convertToMp3MenuItem.Click += (_, _) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook); - - #endregion - } - - args.ContextMenuItems.Add(new Separator()); - - #region View Bookmarks/Clips - - if (!entry.Liberate.IsSeries) - { - - var bookRecordMenuItem = new MenuItem { Header = "View _Bookmarks/Clips" }; - - args.ContextMenuItems.Add(bookRecordMenuItem); - - bookRecordMenuItem.Click += async (_, _) => await new BookRecordsDialog(entry.LibraryBook).ShowDialog(VisualRoot as Window); - } - - #endregion - #region View All Series - - if (entry.Book.SeriesLink.Any()) - { - var header = entry.Liberate.IsSeries ? "View All Episodes in Series" : "View All Books in Series"; - var viewSeriesMenuItem = new MenuItem { Header = header }; - - args.ContextMenuItems.Add(viewSeriesMenuItem); - - viewSeriesMenuItem.Click += (_, _) => new SeriesViewDialog(entry.LibraryBook).Show(); - } - - #endregion - } - else - { - // any non-stop light column - // (except for the Cover column which does not have a context menu) var menuItem = new MenuItem { Header = "_Copy Cell Contents" }; menuItem.Click += async (s, e) => await App.MainWindow.Clipboard.SetTextAsync(args.CellClipboardContents); args.ContextMenuItems.Add(menuItem); + args.ContextMenuItems.Add(new Separator()); } + var entry = args.GridEntry; + + #region Liberate all Episodes + + if (entry.Liberate.IsSeries) + { + var liberateEpisodesMenuItem = new MenuItem() + { + Header = "_Liberate All Episodes", + IsEnabled = ((ISeriesEntry)entry).Children.Any(c => c.Liberate.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload) + }; + + args.ContextMenuItems.Add(liberateEpisodesMenuItem); + + liberateEpisodesMenuItem.Click += (_, _) => LiberateSeriesClicked?.Invoke(this, ((ISeriesEntry)entry)); + } + + #endregion + #region Set Download status to Downloaded + + var setDownloadMenuItem = new MenuItem() + { + Header = "Set Download status to '_Downloaded'", + IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated || entry.Liberate.IsSeries + }; + + args.ContextMenuItems.Add(setDownloadMenuItem); + + if (entry.Liberate.IsSeries) + setDownloadMenuItem.Click += (_, __) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.Liberated); + else + setDownloadMenuItem.Click += (_, __) => entry.LibraryBook.UpdateBookStatus(LiberatedStatus.Liberated); + + #endregion + #region Set Download status to Not Downloaded + + var setNotDownloadMenuItem = new MenuItem() + { + Header = "Set Download status to '_Not Downloaded'", + IsEnabled = entry.Book.UserDefinedItem.BookStatus != LiberatedStatus.NotLiberated || entry.Liberate.IsSeries + }; + + args.ContextMenuItems.Add(setNotDownloadMenuItem); + + if (entry.Liberate.IsSeries) + setNotDownloadMenuItem.Click += (_, __) => ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).UpdateBookStatus(LiberatedStatus.NotLiberated); + else + setNotDownloadMenuItem.Click += (_, __) => entry.LibraryBook.UpdateBookStatus(LiberatedStatus.NotLiberated); + + #endregion + #region Remove from library + + var removeMenuItem = new MenuItem() { Header = "_Remove from library" }; + + args.ContextMenuItems.Add(removeMenuItem); + + if (entry.Liberate.IsSeries) + removeMenuItem.Click += async (_, __) => await ((ISeriesEntry)entry).Children.Select(c => c.LibraryBook).RemoveBooksAsync(); + else + removeMenuItem.Click += async (_, __) => await Task.Run(entry.LibraryBook.RemoveBook); + + #endregion + + if (!entry.Liberate.IsSeries) + { + #region Locate file + var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; + + args.ContextMenuItems.Add(locateFileMenuItem); + + locateFileMenuItem.Click += async (_, __) => + { + try + { + var window = this.GetParentWindow(); + + var openFileDialogOptions = new FilePickerOpenOptions + { + Title = $"Locate the audio file for '{entry.Book.TitleWithSubtitle}'", + AllowMultiple = false, + SuggestedStartLocation = await window.StorageProvider.TryGetFolderFromPathAsync(Configuration.Instance.Books.PathWithoutPrefix), + FileTypeFilter = new FilePickerFileType[] + { + new("All files (*.*)") { Patterns = new[] { "*" } }, + } + }; + + var selectedFiles = await window.StorageProvider.OpenFilePickerAsync(openFileDialogOptions); + var selectedFile = selectedFiles.SingleOrDefault()?.TryGetLocalPath(); + + if (selectedFile is not null) + FilePathCache.Insert(entry.AudibleProductId, selectedFile); + } + catch (Exception ex) + { + var msg = "Error saving book's location"; + await MessageBox.ShowAdminAlert(null, msg, msg, ex); + } + }; + + #endregion + #region Convert to Mp3 + var convertToMp3MenuItem = new MenuItem + { + Header = "_Convert to Mp3", + IsEnabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated + }; + args.ContextMenuItems.Add(convertToMp3MenuItem); + + convertToMp3MenuItem.Click += (_, _) => ConvertToMp3Clicked?.Invoke(this, entry.LibraryBook); + + #endregion + } + + #region Force Re-Download + if (!entry.Liberate.IsSeries) + { + var reDownloadMenuItem = new MenuItem() + { + Header = "Re-download this audiobook", + IsEnabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated + }; + + args.ContextMenuItems.Add(reDownloadMenuItem); + reDownloadMenuItem.Click += (s, _) => + { + //No need to persist this change. It only needs to last long for the file to start downloading + entry.Book.UserDefinedItem.BookStatus = LiberatedStatus.NotLiberated; + LiberateClicked?.Invoke(s, entry.LibraryBook); + }; + } + #endregion + + args.ContextMenuItems.Add(new Separator()); + + #region View Bookmarks/Clips + + if (!entry.Liberate.IsSeries) + { + + var bookRecordMenuItem = new MenuItem { Header = "View _Bookmarks/Clips" }; + + args.ContextMenuItems.Add(bookRecordMenuItem); + + bookRecordMenuItem.Click += async (_, _) => await new BookRecordsDialog(entry.LibraryBook).ShowDialog(VisualRoot as Window); + } + + #endregion + #region View All Series + + if (entry.Book.SeriesLink.Any()) + { + var header = entry.Liberate.IsSeries ? "View All Episodes in Series" : "View All Books in Series"; + var viewSeriesMenuItem = new MenuItem { Header = header }; + + args.ContextMenuItems.Add(viewSeriesMenuItem); + + viewSeriesMenuItem.Click += (_, _) => new SeriesViewDialog(entry.LibraryBook).Show(); + } + + #endregion } #endregion diff --git a/Source/LibationFileManager/Configuration.HelpText.cs b/Source/LibationFileManager/Configuration.HelpText.cs new file mode 100644 index 00000000..a3c747bc --- /dev/null +++ b/Source/LibationFileManager/Configuration.HelpText.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace LibationFileManager +{ + public partial class Configuration + { + public static ReadOnlyDictionary HelpText { get; } = new Dictionary + { + { nameof(CombineNestedChapterTitles),""" + If the book has nested chapters, e.g. a chapter named "Part 1" + that contains chapters "Chapter 1" and "Chapter 2", then combine + the chapter titles like the following example: + + Part 1: Chapter 1 + Part 1: Chapter 2 + """}, + {nameof(AllowLibationFixup), """ + In addition to the options that are enabled if you allow + "fixing up" the audiobook, it does the following: + + * Sets the ©gen metadata tag for the genres. + * Adds the TCOM (@wrt in M4B files) metadata tag for the narrators. + * Unescapes the copyright symbol (replace © with ©) + * Replaces the recording copyright (P) string with ℗ + * Adds various other metadata tags recognized by AudiobookShelf + * Sets the embedded cover art image with cover art retrieved from Audible + """ }, + } + .AsReadOnly(); + + public static string GetHelpText(string settingName) + => HelpText.TryGetValue(settingName, out var value) ? value : null; + + } +} diff --git a/Source/LibationFileManager/Configuration.PersistentSettings.cs b/Source/LibationFileManager/Configuration.PersistentSettings.cs index d152944f..f54a15a7 100644 --- a/Source/LibationFileManager/Configuration.PersistentSettings.cs +++ b/Source/LibationFileManager/Configuration.PersistentSettings.cs @@ -73,9 +73,12 @@ namespace LibationFileManager public bool Exists(string propertyName) => persistentDictionary.Exists(propertyName); - [Description("Set cover art as the folder's icon. (Windows and macOS only)")] + [Description("Set cover art as the folder's icon.")] public bool UseCoverAsFolderIcon { get => GetNonString(defaultValue: false); set => SetNonString(value); } + [Description("Save audiobook metadata to metadata.json")] + public bool SaveMetadataToFile { get => GetNonString(defaultValue: false); set => SetNonString(value); } + [Description("Use the beta version of Libation\r\nNew and experimental features, but probably buggy.\r\n(requires restart to take effect)")] public bool BetaOptIn { get => GetNonString(defaultValue: false); set => SetNonString(value); } @@ -164,6 +167,9 @@ namespace LibationFileManager [Description("Save cover image alongside audiobook?")] public bool DownloadCoverArt { get => GetNonString(defaultValue: false); set => SetNonString(value); } + [Description("Combine nested chapter titles")] + public bool CombineNestedChapterTitles { get => GetNonString(defaultValue: false); set => SetNonString(value); } + [Description("Download clips and bookmarks?")] public bool DownloadClipsBookmarks { get => GetNonString(defaultValue: false); set => SetNonString(value); } diff --git a/Source/LibationUiBase/GridView/LibraryBookEntry[TStatus].cs b/Source/LibationUiBase/GridView/LibraryBookEntry[TStatus].cs index 93ef84d9..e8ee3f0e 100644 --- a/Source/LibationUiBase/GridView/LibraryBookEntry[TStatus].cs +++ b/Source/LibationUiBase/GridView/LibraryBookEntry[TStatus].cs @@ -1,6 +1,10 @@ using DataLayer; using System; +using System.Collections.Generic; using System.ComponentModel; +using System.Threading.Tasks; +using System.Threading; +using System.Linq; namespace LibationUiBase.GridView { @@ -29,6 +33,39 @@ namespace LibationUiBase.GridView LoadCover(); } + + public static async Task> GetAllProductsAsync(IEnumerable libraryBooks) + { + var products = libraryBooks.Where(lb => lb.Book.IsProduct()).ToArray(); + + int parallelism = int.Max(1, Environment.ProcessorCount - 1); + + (int numPer, int rem) = int.DivRem(products.Length, parallelism); + if (rem != 0) numPer++; + + var tasks = new Task[parallelism]; + var syncContext = SynchronizationContext.Current; + + for (int i = 0; i < parallelism; i++) + { + int start = i * numPer; + tasks[i] = Task.Run(() => + { + SynchronizationContext.SetSynchronizationContext(syncContext); + + int length = int.Min(numPer, products.Length - start); + var result = new IGridEntry[length]; + + for (int j = 0; j < length; j++) + result[j] = new LibraryBookEntry(products[start + j]); + + return result; + }); + } + + return (await Task.WhenAll(tasks)).SelectMany(a => a).ToList(); + } + protected override string GetBookTags() => string.Join("\r\n", Book.UserDefinedItem.TagsEnumerated); } } diff --git a/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs b/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs index eaf49fcb..7ca1f73e 100644 --- a/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs +++ b/Source/LibationUiBase/GridView/SeriesEntry[TStatus].cs @@ -1,7 +1,11 @@ using DataLayer; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; namespace LibationUiBase.GridView { @@ -54,6 +58,60 @@ namespace LibationUiBase.GridView LoadCover(); } + public static async Task> GetAllSeriesEntriesAsync(IEnumerable libraryBooks) + { + var seriesBooks = libraryBooks.Where(lb => lb.Book.IsEpisodeParent()).ToArray(); + var allEpisodes = libraryBooks.Where(lb => lb.Book.IsEpisodeChild()).ToArray(); + + int parallelism = int.Max(1, Environment.ProcessorCount - 1); + + var tasks = new Task[parallelism]; + var syncContext = SynchronizationContext.Current; + + var q = new BlockingCollection<(int, LibraryBook episode)>(); + + var seriesEntries = new ISeriesEntry[seriesBooks.Length]; + var seriesEpisodes = new ConcurrentBag[seriesBooks.Length]; + + for (int i = 0; i < parallelism; i++) + { + tasks[i] = Task.Run(() => + { + SynchronizationContext.SetSynchronizationContext(syncContext); + + while (q.TryTake(out var entry, -1)) + { + var parent = seriesEntries[entry.Item1]; + var episodeBag = seriesEpisodes[entry.Item1]; + episodeBag.Add(new LibraryBookEntry(entry.episode, parent)); + } + }); + } + + for (int i = 0; i (series, Enumerable.Empty()); + seriesEpisodes[i] = new ConcurrentBag(); + + foreach (var ep in allEpisodes.FindChildren(series)) + q.Add((i, ep)); + } + + q.CompleteAdding(); + + await Task.WhenAll(tasks); + + for (int i = 0; i < seriesBooks.Length; i++) + { + var series = seriesEntries[i]; + series.Children.AddRange(seriesEpisodes[i].OrderByDescending(c => c.SeriesOrder)); + series.UpdateLibraryBook(series.LibraryBook); + } + + return seriesEntries.Where(s => s.Children.Count != 0).ToList(); + } + public void RemoveChild(ILibraryBookEntry lbe) { Children.Remove(lbe); diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs index c82e75bc..32c1fc5e 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.AudioSettings.cs @@ -14,12 +14,16 @@ namespace LibationWinForms.Dialogs this.createCueSheetCbox.Text = desc(nameof(config.CreateCueSheet)); this.downloadCoverArtCbox.Text = desc(nameof(config.DownloadCoverArt)); this.retainAaxFileCbox.Text = desc(nameof(config.RetainAaxFile)); + this.combineNestedChapterTitlesCbox.Text = desc(nameof(config.CombineNestedChapterTitles)); this.splitFilesByChapterCbox.Text = desc(nameof(config.SplitFilesByChapter)); 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)); + toolTip.SetToolTip(combineNestedChapterTitlesCbox, Configuration.GetHelpText(nameof(config.CombineNestedChapterTitles))); + toolTip.SetToolTip(allowLibationFixupCbox, Configuration.GetHelpText(nameof(config.AllowLibationFixup))); + fileDownloadQualityCb.Items.AddRange( new object[] { @@ -55,6 +59,7 @@ namespace LibationWinForms.Dialogs fileDownloadQualityCb.SelectedItem = config.FileDownloadQuality; clipsBookmarksFormatCb.SelectedItem = config.ClipsBookmarksFileFormat; retainAaxFileCbox.Checked = config.RetainAaxFile; + combineNestedChapterTitlesCbox.Checked = config.CombineNestedChapterTitles; splitFilesByChapterCbox.Checked = config.SplitFilesByChapter; mergeOpeningEndCreditsCbox.Checked = config.MergeOpeningAndEndCredits; stripUnabridgedCbox.Checked = config.StripUnabridged; @@ -99,6 +104,7 @@ namespace LibationWinForms.Dialogs config.FileDownloadQuality = (Configuration.DownloadQuality)fileDownloadQualityCb.SelectedItem; config.ClipsBookmarksFileFormat = (Configuration.ClipBookmarkFormat)clipsBookmarksFormatCb.SelectedItem; config.RetainAaxFile = retainAaxFileCbox.Checked; + config.CombineNestedChapterTitles = combineNestedChapterTitlesCbox.Checked; config.SplitFilesByChapter = splitFilesByChapterCbox.Checked; config.MergeOpeningAndEndCredits = mergeOpeningEndCreditsCbox.Checked; config.StripUnabridged = stripUnabridgedCbox.Checked; diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs index 30c133f2..183a741f 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs @@ -64,6 +64,7 @@ autoScanCb = new System.Windows.Forms.CheckBox(); showImportedStatsCb = new System.Windows.Forms.CheckBox(); tab3DownloadDecrypt = new System.Windows.Forms.TabPage(); + saveMetadataToFileCbox = new System.Windows.Forms.CheckBox(); useCoverAsFolderIconCb = new System.Windows.Forms.CheckBox(); inProgressFilesGb = new System.Windows.Forms.GroupBox(); customFileNamingGb = new System.Windows.Forms.GroupBox(); @@ -80,6 +81,7 @@ tab4AudioFileOptions = new System.Windows.Forms.TabPage(); fileDownloadQualityCb = new System.Windows.Forms.ComboBox(); fileDownloadQualityLbl = new System.Windows.Forms.Label(); + combineNestedChapterTitlesCbox = new System.Windows.Forms.CheckBox(); clipsBookmarksFormatCb = new System.Windows.Forms.ComboBox(); downloadClipsBookmarksCbox = new System.Windows.Forms.CheckBox(); audiobookFixupsGb = new System.Windows.Forms.GroupBox(); @@ -148,30 +150,30 @@ // booksLocationDescLbl // booksLocationDescLbl.AutoSize = true; - booksLocationDescLbl.Location = new System.Drawing.Point(14, 38); - booksLocationDescLbl.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0); + booksLocationDescLbl.Location = new System.Drawing.Point(7, 19); + booksLocationDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); booksLocationDescLbl.Name = "booksLocationDescLbl"; - booksLocationDescLbl.Size = new System.Drawing.Size(137, 32); + booksLocationDescLbl.Size = new System.Drawing.Size(69, 15); booksLocationDescLbl.TabIndex = 1; booksLocationDescLbl.Text = "[book desc]"; // // inProgressDescLbl // inProgressDescLbl.AutoSize = true; - inProgressDescLbl.Location = new System.Drawing.Point(14, 38); - inProgressDescLbl.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0); + inProgressDescLbl.Location = new System.Drawing.Point(7, 19); + inProgressDescLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); inProgressDescLbl.Name = "inProgressDescLbl"; - inProgressDescLbl.Size = new System.Drawing.Size(201, 96); + inProgressDescLbl.Size = new System.Drawing.Size(100, 45); inProgressDescLbl.TabIndex = 18; inProgressDescLbl.Text = "[in progress desc]\r\n[line 2]\r\n[line 3]"; // // saveBtn // saveBtn.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; - saveBtn.Location = new System.Drawing.Point(1334, 982); - saveBtn.Margin = new System.Windows.Forms.Padding(8, 6, 8, 6); + saveBtn.Location = new System.Drawing.Point(668, 499); + saveBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); saveBtn.Name = "saveBtn"; - saveBtn.Size = new System.Drawing.Size(176, 54); + saveBtn.Size = new System.Drawing.Size(88, 27); saveBtn.TabIndex = 98; saveBtn.Text = "Save"; saveBtn.UseVisualStyleBackColor = true; @@ -181,10 +183,10 @@ // cancelBtn.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; cancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; - cancelBtn.Location = new System.Drawing.Point(1570, 982); - cancelBtn.Margin = new System.Windows.Forms.Padding(8, 6, 8, 6); + cancelBtn.Location = new System.Drawing.Point(786, 499); + cancelBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); cancelBtn.Name = "cancelBtn"; - cancelBtn.Size = new System.Drawing.Size(176, 54); + cancelBtn.Size = new System.Drawing.Size(88, 27); cancelBtn.TabIndex = 99; cancelBtn.Text = "Cancel"; cancelBtn.UseVisualStyleBackColor = true; @@ -193,10 +195,9 @@ // importEpisodesCb // importEpisodesCb.AutoSize = true; - importEpisodesCb.Location = new System.Drawing.Point(12, 112); - importEpisodesCb.Margin = new System.Windows.Forms.Padding(6); + importEpisodesCb.Location = new System.Drawing.Point(6, 56); importEpisodesCb.Name = "importEpisodesCb"; - importEpisodesCb.Size = new System.Drawing.Size(287, 36); + importEpisodesCb.Size = new System.Drawing.Size(146, 19); importEpisodesCb.TabIndex = 3; importEpisodesCb.Text = "[import episodes desc]"; importEpisodesCb.UseVisualStyleBackColor = true; @@ -204,10 +205,9 @@ // downloadEpisodesCb // downloadEpisodesCb.AutoSize = true; - downloadEpisodesCb.Location = new System.Drawing.Point(12, 162); - downloadEpisodesCb.Margin = new System.Windows.Forms.Padding(6); + downloadEpisodesCb.Location = new System.Drawing.Point(6, 81); downloadEpisodesCb.Name = "downloadEpisodesCb"; - downloadEpisodesCb.Size = new System.Drawing.Size(321, 36); + downloadEpisodesCb.Size = new System.Drawing.Size(163, 19); downloadEpisodesCb.TabIndex = 4; downloadEpisodesCb.Text = "[download episodes desc]"; downloadEpisodesCb.UseVisualStyleBackColor = true; @@ -219,11 +219,9 @@ badBookGb.Controls.Add(badBookRetryRb); badBookGb.Controls.Add(badBookAbortRb); badBookGb.Controls.Add(badBookAskRb); - badBookGb.Location = new System.Drawing.Point(14, 12); - badBookGb.Margin = new System.Windows.Forms.Padding(6); + badBookGb.Location = new System.Drawing.Point(7, 6); badBookGb.Name = "badBookGb"; - badBookGb.Padding = new System.Windows.Forms.Padding(6); - badBookGb.Size = new System.Drawing.Size(1668, 152); + badBookGb.Size = new System.Drawing.Size(836, 76); badBookGb.TabIndex = 13; badBookGb.TabStop = false; badBookGb.Text = "[bad book desc]"; @@ -231,10 +229,9 @@ // badBookIgnoreRb // badBookIgnoreRb.AutoSize = true; - badBookIgnoreRb.Location = new System.Drawing.Point(768, 94); - badBookIgnoreRb.Margin = new System.Windows.Forms.Padding(6); + badBookIgnoreRb.Location = new System.Drawing.Point(384, 47); badBookIgnoreRb.Name = "badBookIgnoreRb"; - badBookIgnoreRb.Size = new System.Drawing.Size(183, 36); + badBookIgnoreRb.Size = new System.Drawing.Size(94, 19); badBookIgnoreRb.TabIndex = 17; badBookIgnoreRb.TabStop = true; badBookIgnoreRb.Text = "[ignore desc]"; @@ -243,10 +240,9 @@ // badBookRetryRb // badBookRetryRb.AutoSize = true; - badBookRetryRb.Location = new System.Drawing.Point(10, 94); - badBookRetryRb.Margin = new System.Windows.Forms.Padding(6); + badBookRetryRb.Location = new System.Drawing.Point(5, 47); badBookRetryRb.Name = "badBookRetryRb"; - badBookRetryRb.Size = new System.Drawing.Size(163, 36); + badBookRetryRb.Size = new System.Drawing.Size(84, 19); badBookRetryRb.TabIndex = 16; badBookRetryRb.TabStop = true; badBookRetryRb.Text = "[retry desc]"; @@ -255,10 +251,9 @@ // badBookAbortRb // badBookAbortRb.AutoSize = true; - badBookAbortRb.Location = new System.Drawing.Point(768, 44); - badBookAbortRb.Margin = new System.Windows.Forms.Padding(6); + badBookAbortRb.Location = new System.Drawing.Point(384, 22); badBookAbortRb.Name = "badBookAbortRb"; - badBookAbortRb.Size = new System.Drawing.Size(170, 36); + badBookAbortRb.Size = new System.Drawing.Size(88, 19); badBookAbortRb.TabIndex = 15; badBookAbortRb.TabStop = true; badBookAbortRb.Text = "[abort desc]"; @@ -267,10 +262,9 @@ // badBookAskRb // badBookAskRb.AutoSize = true; - badBookAskRb.Location = new System.Drawing.Point(12, 44); - badBookAskRb.Margin = new System.Windows.Forms.Padding(6); + badBookAskRb.Location = new System.Drawing.Point(6, 22); badBookAskRb.Name = "badBookAskRb"; - badBookAskRb.Size = new System.Drawing.Size(148, 36); + badBookAskRb.Size = new System.Drawing.Size(77, 19); badBookAskRb.TabIndex = 14; badBookAskRb.TabStop = true; badBookAskRb.Text = "[ask desc]"; @@ -279,10 +273,9 @@ // stripAudibleBrandingCbox // stripAudibleBrandingCbox.AutoSize = true; - stripAudibleBrandingCbox.Location = new System.Drawing.Point(26, 144); - stripAudibleBrandingCbox.Margin = new System.Windows.Forms.Padding(6); + stripAudibleBrandingCbox.Location = new System.Drawing.Point(13, 72); stripAudibleBrandingCbox.Name = "stripAudibleBrandingCbox"; - stripAudibleBrandingCbox.Size = new System.Drawing.Size(279, 68); + stripAudibleBrandingCbox.Size = new System.Drawing.Size(143, 34); stripAudibleBrandingCbox.TabIndex = 13; stripAudibleBrandingCbox.Text = "[StripAudibleBranding\r\ndesc]"; stripAudibleBrandingCbox.UseVisualStyleBackColor = true; @@ -290,10 +283,9 @@ // splitFilesByChapterCbox // splitFilesByChapterCbox.AutoSize = true; - splitFilesByChapterCbox.Location = new System.Drawing.Point(26, 44); - splitFilesByChapterCbox.Margin = new System.Windows.Forms.Padding(6); + splitFilesByChapterCbox.Location = new System.Drawing.Point(13, 22); splitFilesByChapterCbox.Name = "splitFilesByChapterCbox"; - splitFilesByChapterCbox.Size = new System.Drawing.Size(319, 36); + splitFilesByChapterCbox.Size = new System.Drawing.Size(162, 19); splitFilesByChapterCbox.TabIndex = 13; splitFilesByChapterCbox.Text = "[SplitFilesByChapter desc]"; splitFilesByChapterCbox.UseVisualStyleBackColor = true; @@ -304,10 +296,9 @@ allowLibationFixupCbox.AutoSize = true; allowLibationFixupCbox.Checked = true; allowLibationFixupCbox.CheckState = System.Windows.Forms.CheckState.Checked; - allowLibationFixupCbox.Location = new System.Drawing.Point(38, 316); - allowLibationFixupCbox.Margin = new System.Windows.Forms.Padding(6); + allowLibationFixupCbox.Location = new System.Drawing.Point(19, 181); allowLibationFixupCbox.Name = "allowLibationFixupCbox"; - allowLibationFixupCbox.Size = new System.Drawing.Size(315, 36); + allowLibationFixupCbox.Size = new System.Drawing.Size(163, 19); allowLibationFixupCbox.TabIndex = 10; allowLibationFixupCbox.Text = "[AllowLibationFixup desc]"; allowLibationFixupCbox.UseVisualStyleBackColor = true; @@ -316,10 +307,9 @@ // convertLossyRb // convertLossyRb.AutoSize = true; - convertLossyRb.Location = new System.Drawing.Point(26, 316); - convertLossyRb.Margin = new System.Windows.Forms.Padding(6); + convertLossyRb.Location = new System.Drawing.Point(13, 159); convertLossyRb.Name = "convertLossyRb"; - convertLossyRb.Size = new System.Drawing.Size(659, 36); + convertLossyRb.Size = new System.Drawing.Size(329, 19); convertLossyRb.TabIndex = 12; convertLossyRb.Text = "Download my books as .MP3 files (transcode if necessary)"; convertLossyRb.UseVisualStyleBackColor = true; @@ -329,10 +319,9 @@ // convertLosslessRb.AutoSize = true; convertLosslessRb.Checked = true; - convertLosslessRb.Location = new System.Drawing.Point(26, 222); - convertLosslessRb.Margin = new System.Windows.Forms.Padding(6); + convertLosslessRb.Location = new System.Drawing.Point(13, 112); convertLosslessRb.Name = "convertLosslessRb"; - convertLosslessRb.Size = new System.Drawing.Size(670, 36); + convertLosslessRb.Size = new System.Drawing.Size(335, 19); convertLosslessRb.TabIndex = 11; convertLosslessRb.TabStop = true; convertLosslessRb.Text = "Download my books in the original audio format (Lossless)"; @@ -343,18 +332,17 @@ // inProgressSelectControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; inProgressSelectControl.AutoSize = true; - inProgressSelectControl.Location = new System.Drawing.Point(14, 136); - inProgressSelectControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + inProgressSelectControl.Location = new System.Drawing.Point(7, 68); + inProgressSelectControl.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); inProgressSelectControl.Name = "inProgressSelectControl"; - inProgressSelectControl.Size = new System.Drawing.Size(1656, 103); + inProgressSelectControl.Size = new System.Drawing.Size(830, 55); inProgressSelectControl.TabIndex = 19; // // logsBtn // - logsBtn.Location = new System.Drawing.Point(512, 522); - logsBtn.Margin = new System.Windows.Forms.Padding(6); + logsBtn.Location = new System.Drawing.Point(256, 261); logsBtn.Name = "logsBtn"; - logsBtn.Size = new System.Drawing.Size(264, 46); + logsBtn.Size = new System.Drawing.Size(132, 23); logsBtn.TabIndex = 5; logsBtn.Text = "Open log folder"; logsBtn.UseVisualStyleBackColor = true; @@ -363,19 +351,18 @@ // booksSelectControl // booksSelectControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - booksSelectControl.Location = new System.Drawing.Point(14, 46); - booksSelectControl.Margin = new System.Windows.Forms.Padding(6, 8, 6, 8); + booksSelectControl.Location = new System.Drawing.Point(7, 23); + booksSelectControl.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); booksSelectControl.Name = "booksSelectControl"; - booksSelectControl.Size = new System.Drawing.Size(1658, 204); + booksSelectControl.Size = new System.Drawing.Size(830, 102); booksSelectControl.TabIndex = 2; // // loggingLevelLbl // loggingLevelLbl.AutoSize = true; - loggingLevelLbl.Location = new System.Drawing.Point(12, 528); - loggingLevelLbl.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + loggingLevelLbl.Location = new System.Drawing.Point(6, 264); loggingLevelLbl.Name = "loggingLevelLbl"; - loggingLevelLbl.Size = new System.Drawing.Size(158, 32); + loggingLevelLbl.Size = new System.Drawing.Size(78, 15); loggingLevelLbl.TabIndex = 3; loggingLevelLbl.Text = "Logging level"; // @@ -383,10 +370,9 @@ // loggingLevelCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; loggingLevelCb.FormattingEnabled = true; - loggingLevelCb.Location = new System.Drawing.Point(180, 522); - loggingLevelCb.Margin = new System.Windows.Forms.Padding(6); + loggingLevelCb.Location = new System.Drawing.Point(90, 261); loggingLevelCb.Name = "loggingLevelCb"; - loggingLevelCb.Size = new System.Drawing.Size(254, 40); + loggingLevelCb.Size = new System.Drawing.Size(129, 23); loggingLevelCb.TabIndex = 4; // // tabControl @@ -396,11 +382,10 @@ tabControl.Controls.Add(tab2ImportLibrary); tabControl.Controls.Add(tab3DownloadDecrypt); tabControl.Controls.Add(tab4AudioFileOptions); - tabControl.Location = new System.Drawing.Point(24, 24); - tabControl.Margin = new System.Windows.Forms.Padding(6); + tabControl.Location = new System.Drawing.Point(12, 12); tabControl.Name = "tabControl"; tabControl.SelectedIndex = 0; - tabControl.Size = new System.Drawing.Size(1724, 946); + tabControl.Size = new System.Drawing.Size(864, 481); tabControl.TabIndex = 100; // // tab1ImportantSettings @@ -410,11 +395,10 @@ tab1ImportantSettings.Controls.Add(logsBtn); tab1ImportantSettings.Controls.Add(loggingLevelCb); tab1ImportantSettings.Controls.Add(loggingLevelLbl); - tab1ImportantSettings.Location = new System.Drawing.Point(8, 46); - tab1ImportantSettings.Margin = new System.Windows.Forms.Padding(6); + tab1ImportantSettings.Location = new System.Drawing.Point(4, 24); tab1ImportantSettings.Name = "tab1ImportantSettings"; - tab1ImportantSettings.Padding = new System.Windows.Forms.Padding(6); - tab1ImportantSettings.Size = new System.Drawing.Size(1708, 892); + tab1ImportantSettings.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3); + tab1ImportantSettings.Size = new System.Drawing.Size(856, 453); tab1ImportantSettings.TabIndex = 0; tab1ImportantSettings.Text = "Important settings"; tab1ImportantSettings.UseVisualStyleBackColor = true; @@ -424,10 +408,9 @@ betaOptInCbox.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; betaOptInCbox.AutoSize = true; betaOptInCbox.Enabled = false; - betaOptInCbox.Location = new System.Drawing.Point(26, 828); - betaOptInCbox.Margin = new System.Windows.Forms.Padding(6); + betaOptInCbox.Location = new System.Drawing.Point(13, 421); betaOptInCbox.Name = "betaOptInCbox"; - betaOptInCbox.Size = new System.Drawing.Size(210, 36); + betaOptInCbox.Size = new System.Drawing.Size(107, 19); betaOptInCbox.TabIndex = 6; betaOptInCbox.Text = "[Opt in to Beta]"; betaOptInCbox.UseVisualStyleBackColor = true; @@ -443,11 +426,9 @@ booksGb.Controls.Add(saveEpisodesToSeriesFolderCbox); booksGb.Controls.Add(booksSelectControl); booksGb.Controls.Add(booksLocationDescLbl); - booksGb.Location = new System.Drawing.Point(12, 12); - booksGb.Margin = new System.Windows.Forms.Padding(6); + booksGb.Location = new System.Drawing.Point(6, 6); booksGb.Name = "booksGb"; - booksGb.Padding = new System.Windows.Forms.Padding(6); - booksGb.Size = new System.Drawing.Size(1684, 498); + booksGb.Size = new System.Drawing.Size(844, 249); booksGb.TabIndex = 0; booksGb.TabStop = false; booksGb.Text = "Books location"; @@ -456,49 +437,46 @@ // lastWriteTimeCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; lastWriteTimeCb.FormattingEnabled = true; - lastWriteTimeCb.Location = new System.Drawing.Point(422, 428); - lastWriteTimeCb.Margin = new System.Windows.Forms.Padding(6); + lastWriteTimeCb.Location = new System.Drawing.Point(211, 214); lastWriteTimeCb.Name = "lastWriteTimeCb"; - lastWriteTimeCb.Size = new System.Drawing.Size(540, 40); + lastWriteTimeCb.Size = new System.Drawing.Size(272, 23); lastWriteTimeCb.TabIndex = 5; // // creationTimeCb // creationTimeCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; creationTimeCb.FormattingEnabled = true; - creationTimeCb.Location = new System.Drawing.Point(422, 370); - creationTimeCb.Margin = new System.Windows.Forms.Padding(6); + creationTimeCb.Location = new System.Drawing.Point(211, 185); creationTimeCb.Name = "creationTimeCb"; - creationTimeCb.Size = new System.Drawing.Size(540, 40); + creationTimeCb.Size = new System.Drawing.Size(272, 23); creationTimeCb.TabIndex = 5; // // lastWriteTimeLbl // lastWriteTimeLbl.AutoSize = true; - lastWriteTimeLbl.Location = new System.Drawing.Point(14, 434); - lastWriteTimeLbl.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0); + lastWriteTimeLbl.Location = new System.Drawing.Point(7, 217); + lastWriteTimeLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); lastWriteTimeLbl.Name = "lastWriteTimeLbl"; - lastWriteTimeLbl.Size = new System.Drawing.Size(233, 32); + lastWriteTimeLbl.Size = new System.Drawing.Size(116, 15); lastWriteTimeLbl.TabIndex = 4; lastWriteTimeLbl.Text = "[last write time desc]"; // // creationTimeLbl // creationTimeLbl.AutoSize = true; - creationTimeLbl.Location = new System.Drawing.Point(14, 376); - creationTimeLbl.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0); + creationTimeLbl.Location = new System.Drawing.Point(7, 188); + creationTimeLbl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); creationTimeLbl.Name = "creationTimeLbl"; - creationTimeLbl.Size = new System.Drawing.Size(224, 32); + creationTimeLbl.Size = new System.Drawing.Size(112, 15); creationTimeLbl.TabIndex = 4; creationTimeLbl.Text = "[creation time desc]"; // // overwriteExistingCbox // overwriteExistingCbox.AutoSize = true; - overwriteExistingCbox.Location = new System.Drawing.Point(14, 312); - overwriteExistingCbox.Margin = new System.Windows.Forms.Padding(6); + overwriteExistingCbox.Location = new System.Drawing.Point(7, 156); overwriteExistingCbox.Name = "overwriteExistingCbox"; - overwriteExistingCbox.Size = new System.Drawing.Size(251, 36); + overwriteExistingCbox.Size = new System.Drawing.Size(129, 19); overwriteExistingCbox.TabIndex = 3; overwriteExistingCbox.Text = "[Overwrite Existing]"; overwriteExistingCbox.UseVisualStyleBackColor = true; @@ -506,10 +484,9 @@ // saveEpisodesToSeriesFolderCbox // saveEpisodesToSeriesFolderCbox.AutoSize = true; - saveEpisodesToSeriesFolderCbox.Location = new System.Drawing.Point(14, 262); - saveEpisodesToSeriesFolderCbox.Margin = new System.Windows.Forms.Padding(6); + saveEpisodesToSeriesFolderCbox.Location = new System.Drawing.Point(7, 131); saveEpisodesToSeriesFolderCbox.Name = "saveEpisodesToSeriesFolderCbox"; - saveEpisodesToSeriesFolderCbox.Size = new System.Drawing.Size(386, 36); + saveEpisodesToSeriesFolderCbox.Size = new System.Drawing.Size(191, 19); saveEpisodesToSeriesFolderCbox.TabIndex = 3; saveEpisodesToSeriesFolderCbox.Text = "[Save Episodes To Series Folder]"; saveEpisodesToSeriesFolderCbox.UseVisualStyleBackColor = true; @@ -521,11 +498,10 @@ tab2ImportLibrary.Controls.Add(showImportedStatsCb); tab2ImportLibrary.Controls.Add(importEpisodesCb); tab2ImportLibrary.Controls.Add(downloadEpisodesCb); - tab2ImportLibrary.Location = new System.Drawing.Point(8, 46); - tab2ImportLibrary.Margin = new System.Windows.Forms.Padding(6); + tab2ImportLibrary.Location = new System.Drawing.Point(4, 24); tab2ImportLibrary.Name = "tab2ImportLibrary"; - tab2ImportLibrary.Padding = new System.Windows.Forms.Padding(6); - tab2ImportLibrary.Size = new System.Drawing.Size(1708, 892); + tab2ImportLibrary.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3); + tab2ImportLibrary.Size = new System.Drawing.Size(856, 453); tab2ImportLibrary.TabIndex = 1; tab2ImportLibrary.Text = "Import library"; tab2ImportLibrary.UseVisualStyleBackColor = true; @@ -533,10 +509,9 @@ // autoDownloadEpisodesCb // autoDownloadEpisodesCb.AutoSize = true; - autoDownloadEpisodesCb.Location = new System.Drawing.Point(12, 212); - autoDownloadEpisodesCb.Margin = new System.Windows.Forms.Padding(6); + autoDownloadEpisodesCb.Location = new System.Drawing.Point(6, 106); autoDownloadEpisodesCb.Name = "autoDownloadEpisodesCb"; - autoDownloadEpisodesCb.Size = new System.Drawing.Size(376, 36); + autoDownloadEpisodesCb.Size = new System.Drawing.Size(190, 19); autoDownloadEpisodesCb.TabIndex = 5; autoDownloadEpisodesCb.Text = "[auto download episodes desc]"; autoDownloadEpisodesCb.UseVisualStyleBackColor = true; @@ -544,10 +519,9 @@ // autoScanCb // autoScanCb.AutoSize = true; - autoScanCb.Location = new System.Drawing.Point(12, 12); - autoScanCb.Margin = new System.Windows.Forms.Padding(6); + autoScanCb.Location = new System.Drawing.Point(6, 6); autoScanCb.Name = "autoScanCb"; - autoScanCb.Size = new System.Drawing.Size(217, 36); + autoScanCb.Size = new System.Drawing.Size(112, 19); autoScanCb.TabIndex = 1; autoScanCb.Text = "[auto scan desc]"; autoScanCb.UseVisualStyleBackColor = true; @@ -555,36 +529,44 @@ // showImportedStatsCb // showImportedStatsCb.AutoSize = true; - showImportedStatsCb.Location = new System.Drawing.Point(12, 62); - showImportedStatsCb.Margin = new System.Windows.Forms.Padding(6); + showImportedStatsCb.Location = new System.Drawing.Point(6, 31); showImportedStatsCb.Name = "showImportedStatsCb"; - showImportedStatsCb.Size = new System.Drawing.Size(330, 36); + showImportedStatsCb.Size = new System.Drawing.Size(168, 19); showImportedStatsCb.TabIndex = 2; showImportedStatsCb.Text = "[show imported stats desc]"; showImportedStatsCb.UseVisualStyleBackColor = true; // // tab3DownloadDecrypt // + tab3DownloadDecrypt.Controls.Add(saveMetadataToFileCbox); tab3DownloadDecrypt.Controls.Add(useCoverAsFolderIconCb); tab3DownloadDecrypt.Controls.Add(inProgressFilesGb); tab3DownloadDecrypt.Controls.Add(customFileNamingGb); tab3DownloadDecrypt.Controls.Add(badBookGb); - tab3DownloadDecrypt.Location = new System.Drawing.Point(8, 46); - tab3DownloadDecrypt.Margin = new System.Windows.Forms.Padding(6); + tab3DownloadDecrypt.Location = new System.Drawing.Point(4, 24); tab3DownloadDecrypt.Name = "tab3DownloadDecrypt"; - tab3DownloadDecrypt.Padding = new System.Windows.Forms.Padding(6); - tab3DownloadDecrypt.Size = new System.Drawing.Size(1708, 892); + tab3DownloadDecrypt.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3); + tab3DownloadDecrypt.Size = new System.Drawing.Size(856, 453); tab3DownloadDecrypt.TabIndex = 2; tab3DownloadDecrypt.Text = "Download/Decrypt"; tab3DownloadDecrypt.UseVisualStyleBackColor = true; // + // saveMetadataToFileCbox + // + saveMetadataToFileCbox.AutoSize = true; + saveMetadataToFileCbox.Location = new System.Drawing.Point(482, 415); + saveMetadataToFileCbox.Name = "saveMetadataToFileCbox"; + saveMetadataToFileCbox.Size = new System.Drawing.Size(165, 19); + saveMetadataToFileCbox.TabIndex = 22; + saveMetadataToFileCbox.Text = "[SaveMetadataToFile desc]"; + saveMetadataToFileCbox.UseVisualStyleBackColor = true; + // // useCoverAsFolderIconCb // useCoverAsFolderIconCb.AutoSize = true; - useCoverAsFolderIconCb.Location = new System.Drawing.Point(14, 830); - useCoverAsFolderIconCb.Margin = new System.Windows.Forms.Padding(6); + useCoverAsFolderIconCb.Location = new System.Drawing.Point(7, 415); useCoverAsFolderIconCb.Name = "useCoverAsFolderIconCb"; - useCoverAsFolderIconCb.Size = new System.Drawing.Size(353, 36); + useCoverAsFolderIconCb.Size = new System.Drawing.Size(180, 19); useCoverAsFolderIconCb.TabIndex = 22; useCoverAsFolderIconCb.Text = "[UseCoverAsFolderIcon desc]"; useCoverAsFolderIconCb.UseVisualStyleBackColor = true; @@ -594,11 +576,9 @@ inProgressFilesGb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; inProgressFilesGb.Controls.Add(inProgressDescLbl); inProgressFilesGb.Controls.Add(inProgressSelectControl); - inProgressFilesGb.Location = new System.Drawing.Point(12, 562); - inProgressFilesGb.Margin = new System.Windows.Forms.Padding(6); + inProgressFilesGb.Location = new System.Drawing.Point(6, 281); inProgressFilesGb.Name = "inProgressFilesGb"; - inProgressFilesGb.Padding = new System.Windows.Forms.Padding(6); - inProgressFilesGb.Size = new System.Drawing.Size(1682, 256); + inProgressFilesGb.Size = new System.Drawing.Size(842, 128); inProgressFilesGb.TabIndex = 21; inProgressFilesGb.TabStop = false; inProgressFilesGb.Text = "In progress files"; @@ -616,11 +596,9 @@ customFileNamingGb.Controls.Add(folderTemplateBtn); customFileNamingGb.Controls.Add(folderTemplateTb); customFileNamingGb.Controls.Add(folderTemplateLbl); - customFileNamingGb.Location = new System.Drawing.Point(14, 176); - customFileNamingGb.Margin = new System.Windows.Forms.Padding(6); + customFileNamingGb.Location = new System.Drawing.Point(7, 88); customFileNamingGb.Name = "customFileNamingGb"; - customFileNamingGb.Padding = new System.Windows.Forms.Padding(6); - customFileNamingGb.Size = new System.Drawing.Size(1682, 374); + customFileNamingGb.Size = new System.Drawing.Size(842, 187); customFileNamingGb.TabIndex = 20; customFileNamingGb.TabStop = false; customFileNamingGb.Text = "Custom file naming"; @@ -628,10 +606,9 @@ // editCharreplacementBtn // editCharreplacementBtn.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - editCharreplacementBtn.Location = new System.Drawing.Point(10, 316); - editCharreplacementBtn.Margin = new System.Windows.Forms.Padding(6); + editCharreplacementBtn.Location = new System.Drawing.Point(5, 158); editCharreplacementBtn.Name = "editCharreplacementBtn"; - editCharreplacementBtn.Size = new System.Drawing.Size(562, 46); + editCharreplacementBtn.Size = new System.Drawing.Size(281, 23); editCharreplacementBtn.TabIndex = 8; editCharreplacementBtn.Text = "[edit char replacement desc]"; editCharreplacementBtn.UseVisualStyleBackColor = true; @@ -640,10 +617,9 @@ // chapterFileTemplateBtn // chapterFileTemplateBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - chapterFileTemplateBtn.Location = new System.Drawing.Point(1522, 248); - chapterFileTemplateBtn.Margin = new System.Windows.Forms.Padding(6); + chapterFileTemplateBtn.Location = new System.Drawing.Point(762, 124); chapterFileTemplateBtn.Name = "chapterFileTemplateBtn"; - chapterFileTemplateBtn.Size = new System.Drawing.Size(150, 46); + chapterFileTemplateBtn.Size = new System.Drawing.Size(75, 23); chapterFileTemplateBtn.TabIndex = 8; chapterFileTemplateBtn.Text = "Edit..."; chapterFileTemplateBtn.UseVisualStyleBackColor = true; @@ -652,30 +628,27 @@ // chapterFileTemplateTb // chapterFileTemplateTb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - chapterFileTemplateTb.Location = new System.Drawing.Point(12, 250); - chapterFileTemplateTb.Margin = new System.Windows.Forms.Padding(6); + chapterFileTemplateTb.Location = new System.Drawing.Point(6, 125); chapterFileTemplateTb.Name = "chapterFileTemplateTb"; chapterFileTemplateTb.ReadOnly = true; - chapterFileTemplateTb.Size = new System.Drawing.Size(1494, 39); + chapterFileTemplateTb.Size = new System.Drawing.Size(750, 23); chapterFileTemplateTb.TabIndex = 7; // // chapterFileTemplateLbl // chapterFileTemplateLbl.AutoSize = true; - chapterFileTemplateLbl.Location = new System.Drawing.Point(12, 214); - chapterFileTemplateLbl.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + chapterFileTemplateLbl.Location = new System.Drawing.Point(6, 107); chapterFileTemplateLbl.Name = "chapterFileTemplateLbl"; - chapterFileTemplateLbl.Size = new System.Drawing.Size(265, 32); + chapterFileTemplateLbl.Size = new System.Drawing.Size(132, 15); chapterFileTemplateLbl.TabIndex = 6; chapterFileTemplateLbl.Text = "[chapter template desc]"; // // fileTemplateBtn // fileTemplateBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - fileTemplateBtn.Location = new System.Drawing.Point(1522, 160); - fileTemplateBtn.Margin = new System.Windows.Forms.Padding(6); + fileTemplateBtn.Location = new System.Drawing.Point(762, 80); fileTemplateBtn.Name = "fileTemplateBtn"; - fileTemplateBtn.Size = new System.Drawing.Size(150, 46); + fileTemplateBtn.Size = new System.Drawing.Size(75, 23); fileTemplateBtn.TabIndex = 5; fileTemplateBtn.Text = "Edit..."; fileTemplateBtn.UseVisualStyleBackColor = true; @@ -684,30 +657,27 @@ // fileTemplateTb // fileTemplateTb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - fileTemplateTb.Location = new System.Drawing.Point(12, 162); - fileTemplateTb.Margin = new System.Windows.Forms.Padding(6); + fileTemplateTb.Location = new System.Drawing.Point(6, 81); fileTemplateTb.Name = "fileTemplateTb"; fileTemplateTb.ReadOnly = true; - fileTemplateTb.Size = new System.Drawing.Size(1494, 39); + fileTemplateTb.Size = new System.Drawing.Size(750, 23); fileTemplateTb.TabIndex = 4; // // fileTemplateLbl // fileTemplateLbl.AutoSize = true; - fileTemplateLbl.Location = new System.Drawing.Point(12, 126); - fileTemplateLbl.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + fileTemplateLbl.Location = new System.Drawing.Point(6, 63); fileTemplateLbl.Name = "fileTemplateLbl"; - fileTemplateLbl.Size = new System.Drawing.Size(218, 32); + fileTemplateLbl.Size = new System.Drawing.Size(108, 15); fileTemplateLbl.TabIndex = 3; fileTemplateLbl.Text = "[file template desc]"; // // folderTemplateBtn // folderTemplateBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - folderTemplateBtn.Location = new System.Drawing.Point(1520, 72); - folderTemplateBtn.Margin = new System.Windows.Forms.Padding(6); + folderTemplateBtn.Location = new System.Drawing.Point(762, 36); folderTemplateBtn.Name = "folderTemplateBtn"; - folderTemplateBtn.Size = new System.Drawing.Size(150, 46); + folderTemplateBtn.Size = new System.Drawing.Size(75, 23); folderTemplateBtn.TabIndex = 2; folderTemplateBtn.Text = "Edit..."; folderTemplateBtn.UseVisualStyleBackColor = true; @@ -716,20 +686,18 @@ // folderTemplateTb // folderTemplateTb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - folderTemplateTb.Location = new System.Drawing.Point(10, 74); - folderTemplateTb.Margin = new System.Windows.Forms.Padding(6); + folderTemplateTb.Location = new System.Drawing.Point(5, 37); folderTemplateTb.Name = "folderTemplateTb"; folderTemplateTb.ReadOnly = true; - folderTemplateTb.Size = new System.Drawing.Size(1494, 39); + folderTemplateTb.Size = new System.Drawing.Size(750, 23); folderTemplateTb.TabIndex = 1; // // folderTemplateLbl // folderTemplateLbl.AutoSize = true; - folderTemplateLbl.Location = new System.Drawing.Point(10, 38); - folderTemplateLbl.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + folderTemplateLbl.Location = new System.Drawing.Point(5, 19); folderTemplateLbl.Name = "folderTemplateLbl"; - folderTemplateLbl.Size = new System.Drawing.Size(248, 32); + folderTemplateLbl.Size = new System.Drawing.Size(123, 15); folderTemplateLbl.TabIndex = 0; folderTemplateLbl.Text = "[folder template desc]"; // @@ -737,6 +705,7 @@ // tab4AudioFileOptions.Controls.Add(fileDownloadQualityCb); tab4AudioFileOptions.Controls.Add(fileDownloadQualityLbl); + tab4AudioFileOptions.Controls.Add(combineNestedChapterTitlesCbox); tab4AudioFileOptions.Controls.Add(clipsBookmarksFormatCb); tab4AudioFileOptions.Controls.Add(downloadClipsBookmarksCbox); tab4AudioFileOptions.Controls.Add(audiobookFixupsGb); @@ -747,11 +716,10 @@ tab4AudioFileOptions.Controls.Add(downloadCoverArtCbox); tab4AudioFileOptions.Controls.Add(createCueSheetCbox); tab4AudioFileOptions.Controls.Add(allowLibationFixupCbox); - tab4AudioFileOptions.Location = new System.Drawing.Point(8, 46); - tab4AudioFileOptions.Margin = new System.Windows.Forms.Padding(6); + tab4AudioFileOptions.Location = new System.Drawing.Point(4, 24); tab4AudioFileOptions.Name = "tab4AudioFileOptions"; - tab4AudioFileOptions.Padding = new System.Windows.Forms.Padding(6); - tab4AudioFileOptions.Size = new System.Drawing.Size(1708, 892); + tab4AudioFileOptions.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3); + tab4AudioFileOptions.Size = new System.Drawing.Size(856, 453); tab4AudioFileOptions.TabIndex = 3; tab4AudioFileOptions.Text = "Audio File Options"; tab4AudioFileOptions.UseVisualStyleBackColor = true; @@ -760,39 +728,47 @@ // fileDownloadQualityCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; fileDownloadQualityCb.FormattingEnabled = true; - fileDownloadQualityCb.Location = new System.Drawing.Point(528, 16); - fileDownloadQualityCb.Margin = new System.Windows.Forms.Padding(6, 6, 10, 6); + fileDownloadQualityCb.Location = new System.Drawing.Point(264, 8); + fileDownloadQualityCb.Margin = new System.Windows.Forms.Padding(3, 3, 5, 3); fileDownloadQualityCb.Name = "fileDownloadQualityCb"; - fileDownloadQualityCb.Size = new System.Drawing.Size(172, 40); + fileDownloadQualityCb.Size = new System.Drawing.Size(88, 23); fileDownloadQualityCb.TabIndex = 23; // // fileDownloadQualityLbl // fileDownloadQualityLbl.AutoSize = true; - fileDownloadQualityLbl.Location = new System.Drawing.Point(38, 18); - fileDownloadQualityLbl.Margin = new System.Windows.Forms.Padding(0, 0, 4, 0); + fileDownloadQualityLbl.Location = new System.Drawing.Point(19, 9); + fileDownloadQualityLbl.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); fileDownloadQualityLbl.Name = "fileDownloadQualityLbl"; - fileDownloadQualityLbl.Size = new System.Drawing.Size(304, 32); + fileDownloadQualityLbl.Size = new System.Drawing.Size(152, 15); fileDownloadQualityLbl.TabIndex = 22; fileDownloadQualityLbl.Text = "[FileDownloadQuality desc]"; // + // combineNestedChapterTitlesCbox + // + combineNestedChapterTitlesCbox.AutoSize = true; + combineNestedChapterTitlesCbox.Location = new System.Drawing.Point(19, 157); + combineNestedChapterTitlesCbox.Name = "combineNestedChapterTitlesCbox"; + combineNestedChapterTitlesCbox.Size = new System.Drawing.Size(216, 19); + combineNestedChapterTitlesCbox.TabIndex = 13; + combineNestedChapterTitlesCbox.Text = "[CombineNestedChapterTitles desc]"; + combineNestedChapterTitlesCbox.UseVisualStyleBackColor = true; + // // clipsBookmarksFormatCb // clipsBookmarksFormatCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; clipsBookmarksFormatCb.FormattingEnabled = true; - clipsBookmarksFormatCb.Location = new System.Drawing.Point(570, 162); - clipsBookmarksFormatCb.Margin = new System.Windows.Forms.Padding(6); + clipsBookmarksFormatCb.Location = new System.Drawing.Point(285, 81); clipsBookmarksFormatCb.Name = "clipsBookmarksFormatCb"; - clipsBookmarksFormatCb.Size = new System.Drawing.Size(130, 40); + clipsBookmarksFormatCb.Size = new System.Drawing.Size(67, 23); clipsBookmarksFormatCb.TabIndex = 21; // // downloadClipsBookmarksCbox // downloadClipsBookmarksCbox.AutoSize = true; - downloadClipsBookmarksCbox.Location = new System.Drawing.Point(38, 164); - downloadClipsBookmarksCbox.Margin = new System.Windows.Forms.Padding(6); + downloadClipsBookmarksCbox.Location = new System.Drawing.Point(19, 82); downloadClipsBookmarksCbox.Name = "downloadClipsBookmarksCbox"; - downloadClipsBookmarksCbox.Size = new System.Drawing.Size(492, 36); + downloadClipsBookmarksCbox.Size = new System.Drawing.Size(248, 19); downloadClipsBookmarksCbox.TabIndex = 20; downloadClipsBookmarksCbox.Text = "Download Clips, Notes, and Bookmarks as"; downloadClipsBookmarksCbox.UseVisualStyleBackColor = true; @@ -806,11 +782,9 @@ audiobookFixupsGb.Controls.Add(convertLosslessRb); audiobookFixupsGb.Controls.Add(convertLossyRb); audiobookFixupsGb.Controls.Add(stripAudibleBrandingCbox); - audiobookFixupsGb.Location = new System.Drawing.Point(12, 382); - audiobookFixupsGb.Margin = new System.Windows.Forms.Padding(6); + audiobookFixupsGb.Location = new System.Drawing.Point(6, 200); audiobookFixupsGb.Name = "audiobookFixupsGb"; - audiobookFixupsGb.Padding = new System.Windows.Forms.Padding(6); - audiobookFixupsGb.Size = new System.Drawing.Size(806, 370); + audiobookFixupsGb.Size = new System.Drawing.Size(403, 182); audiobookFixupsGb.TabIndex = 19; audiobookFixupsGb.TabStop = false; audiobookFixupsGb.Text = "Audiobook Fix-ups"; @@ -818,10 +792,9 @@ // moveMoovAtomCbox // moveMoovAtomCbox.AutoSize = true; - moveMoovAtomCbox.Location = new System.Drawing.Point(46, 266); - moveMoovAtomCbox.Margin = new System.Windows.Forms.Padding(6); + moveMoovAtomCbox.Location = new System.Drawing.Point(23, 134); moveMoovAtomCbox.Name = "moveMoovAtomCbox"; - moveMoovAtomCbox.Size = new System.Drawing.Size(372, 36); + moveMoovAtomCbox.Size = new System.Drawing.Size(188, 19); moveMoovAtomCbox.TabIndex = 14; moveMoovAtomCbox.Text = "[MoveMoovToBeginning desc]"; moveMoovAtomCbox.UseVisualStyleBackColor = true; @@ -829,10 +802,9 @@ // stripUnabridgedCbox // stripUnabridgedCbox.AutoSize = true; - stripUnabridgedCbox.Location = new System.Drawing.Point(26, 94); - stripUnabridgedCbox.Margin = new System.Windows.Forms.Padding(6); + stripUnabridgedCbox.Location = new System.Drawing.Point(13, 47); stripUnabridgedCbox.Name = "stripUnabridgedCbox"; - stripUnabridgedCbox.Size = new System.Drawing.Size(288, 36); + stripUnabridgedCbox.Size = new System.Drawing.Size(147, 19); stripUnabridgedCbox.TabIndex = 13; stripUnabridgedCbox.Text = "[StripUnabridged desc]"; stripUnabridgedCbox.UseVisualStyleBackColor = true; @@ -841,11 +813,9 @@ // chapterTitleTemplateGb.Controls.Add(chapterTitleTemplateBtn); chapterTitleTemplateGb.Controls.Add(chapterTitleTemplateTb); - chapterTitleTemplateGb.Location = new System.Drawing.Point(6, 776); - chapterTitleTemplateGb.Margin = new System.Windows.Forms.Padding(6); + chapterTitleTemplateGb.Location = new System.Drawing.Point(3, 388); chapterTitleTemplateGb.Name = "chapterTitleTemplateGb"; - chapterTitleTemplateGb.Padding = new System.Windows.Forms.Padding(6); - chapterTitleTemplateGb.Size = new System.Drawing.Size(1694, 108); + chapterTitleTemplateGb.Size = new System.Drawing.Size(847, 54); chapterTitleTemplateGb.TabIndex = 18; chapterTitleTemplateGb.TabStop = false; chapterTitleTemplateGb.Text = "[chapter title template desc]"; @@ -853,10 +823,9 @@ // chapterTitleTemplateBtn // chapterTitleTemplateBtn.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - chapterTitleTemplateBtn.Location = new System.Drawing.Point(1538, 44); - chapterTitleTemplateBtn.Margin = new System.Windows.Forms.Padding(6); + chapterTitleTemplateBtn.Location = new System.Drawing.Point(769, 22); chapterTitleTemplateBtn.Name = "chapterTitleTemplateBtn"; - chapterTitleTemplateBtn.Size = new System.Drawing.Size(150, 46); + chapterTitleTemplateBtn.Size = new System.Drawing.Size(75, 23); chapterTitleTemplateBtn.TabIndex = 17; chapterTitleTemplateBtn.Text = "Edit..."; chapterTitleTemplateBtn.UseVisualStyleBackColor = true; @@ -865,11 +834,10 @@ // chapterTitleTemplateTb // chapterTitleTemplateTb.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - chapterTitleTemplateTb.Location = new System.Drawing.Point(12, 44); - chapterTitleTemplateTb.Margin = new System.Windows.Forms.Padding(6); + chapterTitleTemplateTb.Location = new System.Drawing.Point(6, 22); chapterTitleTemplateTb.Name = "chapterTitleTemplateTb"; chapterTitleTemplateTb.ReadOnly = true; - chapterTitleTemplateTb.Size = new System.Drawing.Size(1510, 39); + chapterTitleTemplateTb.Size = new System.Drawing.Size(757, 23); chapterTitleTemplateTb.TabIndex = 16; // // lameOptionsGb @@ -883,11 +851,9 @@ lameOptionsGb.Controls.Add(label1); lameOptionsGb.Controls.Add(lameQualityGb); lameOptionsGb.Controls.Add(groupBox2); - lameOptionsGb.Location = new System.Drawing.Point(830, 12); - lameOptionsGb.Margin = new System.Windows.Forms.Padding(6); + lameOptionsGb.Location = new System.Drawing.Point(415, 6); lameOptionsGb.Name = "lameOptionsGb"; - lameOptionsGb.Padding = new System.Windows.Forms.Padding(6); - lameOptionsGb.Size = new System.Drawing.Size(866, 696); + lameOptionsGb.Size = new System.Drawing.Size(433, 376); lameOptionsGb.TabIndex = 14; lameOptionsGb.TabStop = false; lameOptionsGb.Text = "Mp3 Encoding Options"; @@ -895,20 +861,18 @@ // label20 // label20.AutoSize = true; - label20.Location = new System.Drawing.Point(24, 156); - label20.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label20.Location = new System.Drawing.Point(12, 89); label20.Name = "label20"; - label20.Size = new System.Drawing.Size(204, 32); + label20.Size = new System.Drawing.Size(101, 15); label20.TabIndex = 3; label20.Text = "Max Sample Rate:"; // // label21 // label21.AutoSize = true; - label21.Location = new System.Drawing.Point(478, 156); - label21.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label21.Location = new System.Drawing.Point(239, 89); label21.Name = "label21"; - label21.Size = new System.Drawing.Size(188, 32); + label21.Size = new System.Drawing.Size(94, 15); label21.TabIndex = 3; label21.Text = "Encoder Quality:"; // @@ -916,28 +880,25 @@ // encoderQualityCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; encoderQualityCb.FormattingEnabled = true; - encoderQualityCb.Location = new System.Drawing.Point(674, 150); - encoderQualityCb.Margin = new System.Windows.Forms.Padding(6); + encoderQualityCb.Location = new System.Drawing.Point(337, 86); encoderQualityCb.Name = "encoderQualityCb"; - encoderQualityCb.Size = new System.Drawing.Size(176, 40); + encoderQualityCb.Size = new System.Drawing.Size(90, 23); encoderQualityCb.TabIndex = 2; // // maxSampleRateCb // maxSampleRateCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; maxSampleRateCb.FormattingEnabled = true; - maxSampleRateCb.Location = new System.Drawing.Point(238, 150); - maxSampleRateCb.Margin = new System.Windows.Forms.Padding(6); + maxSampleRateCb.Location = new System.Drawing.Point(119, 86); maxSampleRateCb.Name = "maxSampleRateCb"; - maxSampleRateCb.Size = new System.Drawing.Size(198, 40); + maxSampleRateCb.Size = new System.Drawing.Size(101, 23); maxSampleRateCb.TabIndex = 2; // // lameDownsampleMonoCbox // - lameDownsampleMonoCbox.Location = new System.Drawing.Point(474, 60); - lameDownsampleMonoCbox.Margin = new System.Windows.Forms.Padding(6); + lameDownsampleMonoCbox.Location = new System.Drawing.Point(237, 30); lameDownsampleMonoCbox.Name = "lameDownsampleMonoCbox"; - lameDownsampleMonoCbox.Size = new System.Drawing.Size(368, 68); + lameDownsampleMonoCbox.Size = new System.Drawing.Size(184, 34); lameDownsampleMonoCbox.TabIndex = 1; lameDownsampleMonoCbox.Text = "Downsample stereo to mono?\r\n(Recommended)\r\n"; lameDownsampleMonoCbox.UseVisualStyleBackColor = true; @@ -953,11 +914,9 @@ lameBitrateGb.Controls.Add(label11); lameBitrateGb.Controls.Add(label3); lameBitrateGb.Controls.Add(lameBitrateTb); - lameBitrateGb.Location = new System.Drawing.Point(12, 208); - lameBitrateGb.Margin = new System.Windows.Forms.Padding(6); + lameBitrateGb.Location = new System.Drawing.Point(6, 116); lameBitrateGb.Name = "lameBitrateGb"; - lameBitrateGb.Padding = new System.Windows.Forms.Padding(6); - lameBitrateGb.Size = new System.Drawing.Size(842, 204); + lameBitrateGb.Size = new System.Drawing.Size(421, 113); lameBitrateGb.TabIndex = 0; lameBitrateGb.TabStop = false; lameBitrateGb.Text = "Bitrate"; @@ -965,10 +924,9 @@ // LameMatchSourceBRCbox // LameMatchSourceBRCbox.AutoSize = true; - LameMatchSourceBRCbox.Location = new System.Drawing.Point(550, 152); - LameMatchSourceBRCbox.Margin = new System.Windows.Forms.Padding(6); + LameMatchSourceBRCbox.Location = new System.Drawing.Point(275, 76); LameMatchSourceBRCbox.Name = "LameMatchSourceBRCbox"; - LameMatchSourceBRCbox.Size = new System.Drawing.Size(277, 36); + LameMatchSourceBRCbox.Size = new System.Drawing.Size(140, 19); LameMatchSourceBRCbox.TabIndex = 3; LameMatchSourceBRCbox.Text = "Match source bitrate?"; LameMatchSourceBRCbox.UseVisualStyleBackColor = true; @@ -977,10 +935,9 @@ // lameConstantBitrateCbox // lameConstantBitrateCbox.AutoSize = true; - lameConstantBitrateCbox.Location = new System.Drawing.Point(12, 154); - lameConstantBitrateCbox.Margin = new System.Windows.Forms.Padding(6); + lameConstantBitrateCbox.Location = new System.Drawing.Point(6, 77); lameConstantBitrateCbox.Name = "lameConstantBitrateCbox"; - lameConstantBitrateCbox.Size = new System.Drawing.Size(431, 36); + lameConstantBitrateCbox.Size = new System.Drawing.Size(216, 19); lameConstantBitrateCbox.TabIndex = 2; lameConstantBitrateCbox.Text = "Restrict encoder to constant bitrate?"; lameConstantBitrateCbox.UseVisualStyleBackColor = true; @@ -989,10 +946,9 @@ // label7.AutoSize = true; label7.BackColor = System.Drawing.SystemColors.ControlLightLight; - label7.Location = new System.Drawing.Point(780, 104); - label7.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label7.Location = new System.Drawing.Point(390, 52); label7.Name = "label7"; - label7.Size = new System.Drawing.Size(53, 32); + label7.Size = new System.Drawing.Size(25, 15); label7.TabIndex = 1; label7.Text = "320"; // @@ -1000,10 +956,9 @@ // label6.AutoSize = true; label6.BackColor = System.Drawing.SystemColors.ControlLightLight; - label6.Location = new System.Drawing.Point(618, 104); - label6.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label6.Location = new System.Drawing.Point(309, 52); label6.Name = "label6"; - label6.Size = new System.Drawing.Size(53, 32); + label6.Size = new System.Drawing.Size(25, 15); label6.TabIndex = 1; label6.Text = "256"; // @@ -1011,10 +966,9 @@ // label5.AutoSize = true; label5.BackColor = System.Drawing.SystemColors.ControlLightLight; - label5.Location = new System.Drawing.Point(456, 104); - label5.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label5.Location = new System.Drawing.Point(228, 52); label5.Name = "label5"; - label5.Size = new System.Drawing.Size(53, 32); + label5.Size = new System.Drawing.Size(25, 15); label5.TabIndex = 1; label5.Text = "192"; // @@ -1022,10 +976,9 @@ // label4.AutoSize = true; label4.BackColor = System.Drawing.SystemColors.ControlLightLight; - label4.Location = new System.Drawing.Point(294, 104); - label4.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label4.Location = new System.Drawing.Point(147, 52); label4.Name = "label4"; - label4.Size = new System.Drawing.Size(53, 32); + label4.Size = new System.Drawing.Size(25, 15); label4.TabIndex = 1; label4.Text = "128"; // @@ -1033,10 +986,9 @@ // label11.AutoSize = true; label11.BackColor = System.Drawing.SystemColors.ControlLightLight; - label11.Location = new System.Drawing.Point(20, 104); - label11.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label11.Location = new System.Drawing.Point(10, 52); label11.Name = "label11"; - label11.Size = new System.Drawing.Size(40, 32); + label11.Size = new System.Drawing.Size(19, 15); label11.TabIndex = 1; label11.Text = "16"; // @@ -1044,10 +996,9 @@ // label3.AutoSize = true; label3.BackColor = System.Drawing.SystemColors.ControlLightLight; - label3.Location = new System.Drawing.Point(142, 104); - label3.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label3.Location = new System.Drawing.Point(71, 52); label3.Name = "label3"; - label3.Size = new System.Drawing.Size(40, 32); + label3.Size = new System.Drawing.Size(19, 15); label3.TabIndex = 1; label3.Text = "64"; // @@ -1055,12 +1006,11 @@ // lameBitrateTb.BackColor = System.Drawing.SystemColors.ControlLightLight; lameBitrateTb.LargeChange = 32; - lameBitrateTb.Location = new System.Drawing.Point(12, 44); - lameBitrateTb.Margin = new System.Windows.Forms.Padding(6); + lameBitrateTb.Location = new System.Drawing.Point(6, 22); lameBitrateTb.Maximum = 320; lameBitrateTb.Minimum = 16; lameBitrateTb.Name = "lameBitrateTb"; - lameBitrateTb.Size = new System.Drawing.Size(818, 90); + lameBitrateTb.Size = new System.Drawing.Size(409, 45); lameBitrateTb.SmallChange = 8; lameBitrateTb.TabIndex = 0; lameBitrateTb.TickFrequency = 16; @@ -1071,10 +1021,9 @@ label1.AutoSize = true; label1.Enabled = false; label1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point); - label1.Location = new System.Drawing.Point(12, 650); - label1.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label1.Location = new System.Drawing.Point(6, 355); label1.Name = "label1"; - label1.Size = new System.Drawing.Size(333, 32); + label1.Size = new System.Drawing.Size(172, 15); label1.TabIndex = 1; label1.Text = "Using L.A.M.E. encoding engine"; // @@ -1093,11 +1042,9 @@ lameQualityGb.Controls.Add(label14); lameQualityGb.Controls.Add(label2); lameQualityGb.Controls.Add(lameVBRQualityTb); - lameQualityGb.Location = new System.Drawing.Point(12, 424); - lameQualityGb.Margin = new System.Windows.Forms.Padding(6); + lameQualityGb.Location = new System.Drawing.Point(6, 235); lameQualityGb.Name = "lameQualityGb"; - lameQualityGb.Padding = new System.Windows.Forms.Padding(6); - lameQualityGb.Size = new System.Drawing.Size(842, 206); + lameQualityGb.Size = new System.Drawing.Size(421, 109); lameQualityGb.TabIndex = 0; lameQualityGb.TabStop = false; lameQualityGb.Text = "Quality"; @@ -1105,120 +1052,108 @@ // label19 // label19.AutoSize = true; - label19.Location = new System.Drawing.Point(698, 104); - label19.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label19.Location = new System.Drawing.Point(349, 52); label19.Name = "label19"; - label19.Size = new System.Drawing.Size(42, 32); + label19.Size = new System.Drawing.Size(20, 15); label19.TabIndex = 1; label19.Text = "V8"; // // label18 // label18.AutoSize = true; - label18.Location = new System.Drawing.Point(614, 104); - label18.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label18.Location = new System.Drawing.Point(307, 52); label18.Name = "label18"; - label18.Size = new System.Drawing.Size(42, 32); + label18.Size = new System.Drawing.Size(20, 15); label18.TabIndex = 1; label18.Text = "V7"; // // label17 // label17.AutoSize = true; - label17.Location = new System.Drawing.Point(530, 104); - label17.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label17.Location = new System.Drawing.Point(265, 52); label17.Name = "label17"; - label17.Size = new System.Drawing.Size(42, 32); + label17.Size = new System.Drawing.Size(20, 15); label17.TabIndex = 1; label17.Text = "V6"; // // label16 // label16.AutoSize = true; - label16.Location = new System.Drawing.Point(446, 104); - label16.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label16.Location = new System.Drawing.Point(223, 52); label16.Name = "label16"; - label16.Size = new System.Drawing.Size(42, 32); + label16.Size = new System.Drawing.Size(20, 15); label16.TabIndex = 1; label16.Text = "V5"; // // label12 // label12.AutoSize = true; - label12.Location = new System.Drawing.Point(364, 104); - label12.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label12.Location = new System.Drawing.Point(182, 52); label12.Name = "label12"; - label12.Size = new System.Drawing.Size(42, 32); + label12.Size = new System.Drawing.Size(20, 15); label12.TabIndex = 1; label12.Text = "V4"; // // label15 // label15.AutoSize = true; - label15.Location = new System.Drawing.Point(280, 104); - label15.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label15.Location = new System.Drawing.Point(140, 52); label15.Name = "label15"; - label15.Size = new System.Drawing.Size(42, 32); + label15.Size = new System.Drawing.Size(20, 15); label15.TabIndex = 1; label15.Text = "V3"; // // label9 // label9.AutoSize = true; - label9.Location = new System.Drawing.Point(194, 104); - label9.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label9.Location = new System.Drawing.Point(97, 52); label9.Name = "label9"; - label9.Size = new System.Drawing.Size(42, 32); + label9.Size = new System.Drawing.Size(20, 15); label9.TabIndex = 1; label9.Text = "V2"; // // label8 // label8.AutoSize = true; - label8.Location = new System.Drawing.Point(782, 104); - label8.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label8.Location = new System.Drawing.Point(391, 52); label8.Name = "label8"; - label8.Size = new System.Drawing.Size(42, 32); + label8.Size = new System.Drawing.Size(20, 15); label8.TabIndex = 1; label8.Text = "V9"; // // label13 // label13.AutoSize = true; - label13.Location = new System.Drawing.Point(752, 160); - label13.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label13.Location = new System.Drawing.Point(376, 80); label13.Name = "label13"; - label13.Size = new System.Drawing.Size(77, 32); + label13.Size = new System.Drawing.Size(39, 15); label13.TabIndex = 1; label13.Text = "Lower"; // // label10 // label10.AutoSize = true; - label10.Location = new System.Drawing.Point(12, 160); - label10.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label10.Location = new System.Drawing.Point(6, 80); label10.Name = "label10"; - label10.Size = new System.Drawing.Size(86, 32); + label10.Size = new System.Drawing.Size(43, 15); label10.TabIndex = 1; label10.Text = "Higher"; // // label14 // label14.AutoSize = true; - label14.Location = new System.Drawing.Point(112, 104); - label14.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label14.Location = new System.Drawing.Point(56, 52); label14.Name = "label14"; - label14.Size = new System.Drawing.Size(42, 32); + label14.Size = new System.Drawing.Size(20, 15); label14.TabIndex = 1; label14.Text = "V1"; // // label2 // label2.AutoSize = true; - label2.Location = new System.Drawing.Point(28, 104); - label2.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + label2.Location = new System.Drawing.Point(14, 52); label2.Name = "label2"; - label2.Size = new System.Drawing.Size(42, 32); + label2.Size = new System.Drawing.Size(20, 15); label2.TabIndex = 1; label2.Text = "V0"; // @@ -1226,11 +1161,10 @@ // lameVBRQualityTb.BackColor = System.Drawing.SystemColors.ControlLightLight; lameVBRQualityTb.LargeChange = 1; - lameVBRQualityTb.Location = new System.Drawing.Point(20, 44); - lameVBRQualityTb.Margin = new System.Windows.Forms.Padding(6); + lameVBRQualityTb.Location = new System.Drawing.Point(10, 22); lameVBRQualityTb.Maximum = 9; lameVBRQualityTb.Name = "lameVBRQualityTb"; - lameVBRQualityTb.Size = new System.Drawing.Size(810, 90); + lameVBRQualityTb.Size = new System.Drawing.Size(405, 45); lameVBRQualityTb.TabIndex = 0; lameVBRQualityTb.Value = 9; // @@ -1238,11 +1172,9 @@ // groupBox2.Controls.Add(lameTargetQualityRb); groupBox2.Controls.Add(lameTargetBitrateRb); - groupBox2.Location = new System.Drawing.Point(12, 44); - groupBox2.Margin = new System.Windows.Forms.Padding(6); + groupBox2.Location = new System.Drawing.Point(6, 22); groupBox2.Name = "groupBox2"; - groupBox2.Padding = new System.Windows.Forms.Padding(6); - groupBox2.Size = new System.Drawing.Size(428, 94); + groupBox2.Size = new System.Drawing.Size(214, 58); groupBox2.TabIndex = 0; groupBox2.TabStop = false; groupBox2.Text = "Target"; @@ -1250,10 +1182,9 @@ // lameTargetQualityRb // lameTargetQualityRb.AutoSize = true; - lameTargetQualityRb.Location = new System.Drawing.Point(278, 44); - lameTargetQualityRb.Margin = new System.Windows.Forms.Padding(6); + lameTargetQualityRb.Location = new System.Drawing.Point(139, 22); lameTargetQualityRb.Name = "lameTargetQualityRb"; - lameTargetQualityRb.Size = new System.Drawing.Size(121, 36); + lameTargetQualityRb.Size = new System.Drawing.Size(63, 19); lameTargetQualityRb.TabIndex = 0; lameTargetQualityRb.TabStop = true; lameTargetQualityRb.Text = "Quality"; @@ -1263,10 +1194,9 @@ // lameTargetBitrateRb // lameTargetBitrateRb.AutoSize = true; - lameTargetBitrateRb.Location = new System.Drawing.Point(12, 44); - lameTargetBitrateRb.Margin = new System.Windows.Forms.Padding(6); + lameTargetBitrateRb.Location = new System.Drawing.Point(6, 22); lameTargetBitrateRb.Name = "lameTargetBitrateRb"; - lameTargetBitrateRb.Size = new System.Drawing.Size(114, 36); + lameTargetBitrateRb.Size = new System.Drawing.Size(59, 19); lameTargetBitrateRb.TabIndex = 0; lameTargetBitrateRb.TabStop = true; lameTargetBitrateRb.Text = "Bitrate"; @@ -1276,10 +1206,9 @@ // mergeOpeningEndCreditsCbox // mergeOpeningEndCreditsCbox.AutoSize = true; - mergeOpeningEndCreditsCbox.Location = new System.Drawing.Point(38, 266); - mergeOpeningEndCreditsCbox.Margin = new System.Windows.Forms.Padding(6); + mergeOpeningEndCreditsCbox.Location = new System.Drawing.Point(19, 133); mergeOpeningEndCreditsCbox.Name = "mergeOpeningEndCreditsCbox"; - mergeOpeningEndCreditsCbox.Size = new System.Drawing.Size(392, 36); + mergeOpeningEndCreditsCbox.Size = new System.Drawing.Size(198, 19); mergeOpeningEndCreditsCbox.TabIndex = 13; mergeOpeningEndCreditsCbox.Text = "[MergeOpeningEndCredits desc]"; mergeOpeningEndCreditsCbox.UseVisualStyleBackColor = true; @@ -1287,10 +1216,9 @@ // retainAaxFileCbox // retainAaxFileCbox.AutoSize = true; - retainAaxFileCbox.Location = new System.Drawing.Point(38, 214); - retainAaxFileCbox.Margin = new System.Windows.Forms.Padding(6); + retainAaxFileCbox.Location = new System.Drawing.Point(19, 107); retainAaxFileCbox.Name = "retainAaxFileCbox"; - retainAaxFileCbox.Size = new System.Drawing.Size(256, 36); + retainAaxFileCbox.Size = new System.Drawing.Size(132, 19); retainAaxFileCbox.TabIndex = 10; retainAaxFileCbox.Text = "[RetainAaxFile desc]"; retainAaxFileCbox.UseVisualStyleBackColor = true; @@ -1301,10 +1229,9 @@ downloadCoverArtCbox.AutoSize = true; downloadCoverArtCbox.Checked = true; downloadCoverArtCbox.CheckState = System.Windows.Forms.CheckState.Checked; - downloadCoverArtCbox.Location = new System.Drawing.Point(38, 116); - downloadCoverArtCbox.Margin = new System.Windows.Forms.Padding(6); + downloadCoverArtCbox.Location = new System.Drawing.Point(19, 58); downloadCoverArtCbox.Name = "downloadCoverArtCbox"; - downloadCoverArtCbox.Size = new System.Drawing.Size(316, 36); + downloadCoverArtCbox.Size = new System.Drawing.Size(162, 19); downloadCoverArtCbox.TabIndex = 10; downloadCoverArtCbox.Text = "[DownloadCoverArt desc]"; downloadCoverArtCbox.UseVisualStyleBackColor = true; @@ -1315,10 +1242,9 @@ createCueSheetCbox.AutoSize = true; createCueSheetCbox.Checked = true; createCueSheetCbox.CheckState = System.Windows.Forms.CheckState.Checked; - createCueSheetCbox.Location = new System.Drawing.Point(38, 64); - createCueSheetCbox.Margin = new System.Windows.Forms.Padding(6); + createCueSheetCbox.Location = new System.Drawing.Point(19, 32); createCueSheetCbox.Name = "createCueSheetCbox"; - createCueSheetCbox.Size = new System.Drawing.Size(287, 36); + createCueSheetCbox.Size = new System.Drawing.Size(145, 19); createCueSheetCbox.TabIndex = 10; createCueSheetCbox.Text = "[CreateCueSheet desc]"; createCueSheetCbox.UseVisualStyleBackColor = true; @@ -1327,15 +1253,15 @@ // SettingsDialog // AcceptButton = saveBtn; - AutoScaleDimensions = new System.Drawing.SizeF(192F, 192F); + AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; CancelButton = cancelBtn; - ClientSize = new System.Drawing.Size(1772, 1060); + ClientSize = new System.Drawing.Size(888, 538); Controls.Add(tabControl); Controls.Add(cancelBtn); Controls.Add(saveBtn); FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - Margin = new System.Windows.Forms.Padding(8, 6, 8, 6); + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); MaximizeBox = false; MinimizeBox = false; Name = "SettingsDialog"; @@ -1475,5 +1401,7 @@ private System.Windows.Forms.Label lastWriteTimeLbl; private System.Windows.Forms.ComboBox fileDownloadQualityCb; private System.Windows.Forms.Label fileDownloadQualityLbl; + private System.Windows.Forms.CheckBox combineNestedChapterTitlesCbox; + private System.Windows.Forms.CheckBox saveMetadataToFileCbox; } } \ No newline at end of file diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.DownloadDecrypt.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.DownloadDecrypt.cs index c2299811..0aa15dfa 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.DownloadDecrypt.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.DownloadDecrypt.cs @@ -32,6 +32,7 @@ namespace LibationWinForms.Dialogs badBookRetryRb.Text = Configuration.BadBookAction.Retry.GetDescription(); badBookIgnoreRb.Text = Configuration.BadBookAction.Ignore.GetDescription(); useCoverAsFolderIconCb.Text = desc(nameof(config.UseCoverAsFolderIcon)); + saveMetadataToFileCbox.Text = desc(nameof(config.SaveMetadataToFile)); inProgressSelectControl.SetDirectoryItems(new() { @@ -60,6 +61,7 @@ namespace LibationWinForms.Dialogs fileTemplateTb.Text = config.FileTemplate; chapterFileTemplateTb.Text = config.ChapterFileTemplate; useCoverAsFolderIconCb.Checked = config.UseCoverAsFolderIcon; + saveMetadataToFileCbox.Checked = config.SaveMetadataToFile; } private void Save_DownloadDecrypt(Configuration config) @@ -77,6 +79,7 @@ namespace LibationWinForms.Dialogs config.FileTemplate = fileTemplateTb.Text; config.ChapterFileTemplate = chapterFileTemplateTb.Text; config.UseCoverAsFolderIcon = useCoverAsFolderIconCb.Checked; + config.SaveMetadataToFile = saveMetadataToFileCbox.Checked; } } } diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.cs index 17ac5d4e..81ba4d0c 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.cs @@ -9,6 +9,12 @@ namespace LibationWinForms.Dialogs { private Configuration config { get; } = Configuration.Instance; private Func desc { get; } = Configuration.GetDescription; + private readonly ToolTip toolTip = new ToolTip + { + InitialDelay = 300, + AutoPopDelay = 10000, + ReshowDelay = 0 + }; public SettingsDialog() { diff --git a/Source/LibationWinForms/Form1.BackupCounts.cs b/Source/LibationWinForms/Form1.BackupCounts.cs index 386c7afc..941cedf4 100644 --- a/Source/LibationWinForms/Form1.BackupCounts.cs +++ b/Source/LibationWinForms/Form1.BackupCounts.cs @@ -1,6 +1,8 @@ using ApplicationServices; +using DataLayer; using Dinah.Core; using Dinah.Core.Threading; +using System.Collections.Generic; namespace LibationWinForms { @@ -14,7 +16,6 @@ namespace LibationWinForms beginBookBackupsToolStripMenuItem.Format(0); beginPdfBackupsToolStripMenuItem.Format(0); - Load += setBackupCounts; LibraryCommands.LibrarySizeChanged += setBackupCounts; LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts; @@ -40,7 +41,11 @@ namespace LibationWinForms while (runBackupCountsAgain) { runBackupCountsAgain = false; - e.Result = LibraryCommands.GetCounts(); + + if (e.Argument is not IEnumerable lbs) + lbs = DbContexts.GetLibrary_Flat_NoTracking(); + + e.Result = LibraryCommands.GetCounts(lbs); } } diff --git a/Source/LibationWinForms/Form1.cs b/Source/LibationWinForms/Form1.cs index 956e53c0..45eecf66 100644 --- a/Source/LibationWinForms/Form1.cs +++ b/Source/LibationWinForms/Form1.cs @@ -4,10 +4,8 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using ApplicationServices; -using Dinah.Core; -using Dinah.Core.Threading; +using DataLayer; using LibationFileManager; -using LibationWinForms.Dialogs; namespace LibationWinForms { @@ -17,10 +15,6 @@ namespace LibationWinForms { InitializeComponent(); - // Pre-requisite: - // Before calling anything else, including subscribing to events, ensure database exists. If we wait and let it happen lazily, race conditions and errors are likely during new installs - using var _ = DbContexts.GetContext(); - this.RestoreSizeAndLocation(Configuration.Instance); this.FormClosing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance); @@ -57,8 +51,7 @@ namespace LibationWinForms // Configure_Grid(); // since it's just this, can keep here. If it needs more, then give grid it's own 'partial class Form1' { - this.Load += (_, __) => productsDisplay.Display(); - LibraryCommands.LibrarySizeChanged += (_, __) => this.UIThreadAsync(() => productsDisplay.Display()); + LibraryCommands.LibrarySizeChanged += (_, __) => Invoke(() => productsDisplay.DisplayAsync()); } Shown += Form1_Shown; } @@ -78,6 +71,13 @@ namespace LibationWinForms } } + public async Task InitLibraryAsync(List libraryBooks) + { + runBackupCountsAgain = true; + updateCountsBw.RunWorkerAsync(libraryBooks.Where(b => !b.Book.IsEpisodeParent())); + await productsDisplay.DisplayAsync(libraryBooks); + } + private void Form1_Load(object sender, EventArgs e) { if (this.DesignMode) diff --git a/Source/LibationWinForms/GridView/GridEntryBindingList.cs b/Source/LibationWinForms/GridView/GridEntryBindingList.cs index 571db313..38102266 100644 --- a/Source/LibationWinForms/GridView/GridEntryBindingList.cs +++ b/Source/LibationWinForms/GridView/GridEntryBindingList.cs @@ -30,7 +30,6 @@ namespace LibationWinForms.GridView { SearchEngineCommands.SearchEngineUpdated += SearchEngineCommands_SearchEngineUpdated; ListChanged += GridEntryBindingList_ListChanged; - refreshEntries(); } /// All items in the list, including those filtered out. diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.cs b/Source/LibationWinForms/GridView/ProductsDisplay.cs index 75996447..dc1460c7 100644 --- a/Source/LibationWinForms/GridView/ProductsDisplay.cs +++ b/Source/LibationWinForms/GridView/ProductsDisplay.cs @@ -206,6 +206,25 @@ namespace LibationWinForms.GridView #endregion } + #region Force Re-Download + if (!entry.Liberate.IsSeries) + { + var reDownloadMenuItem = new ToolStripMenuItem() + { + Text = "Re-download this audiobook", + Enabled = entry.Book.UserDefinedItem.BookStatus is LiberatedStatus.Liberated + }; + + ctxMenu.Items.Add(reDownloadMenuItem); + reDownloadMenuItem.Click += (s, _) => + { + //No need to persist this change. It only needs to last long for the file to start downloading + entry.Book.UserDefinedItem.BookStatus = LiberatedStatus.NotLiberated; + LiberateClicked?.Invoke(s, entry.LibraryBook); + }; + } + #endregion + ctxMenu.Items.Add(new ToolStripSeparator()); #region View Bookmarks/Clips @@ -306,22 +325,22 @@ namespace LibationWinForms.GridView #region UI display functions - public void Display() + public async Task DisplayAsync(List libraryBooks = null) { try { // don't return early if lib size == 0. this will not update correctly if all books are removed - var lib = DbContexts.GetLibrary_Flat_NoTracking(includeParents: true); + libraryBooks ??= DbContexts.GetLibrary_Flat_NoTracking(includeParents: true); if (!hasBeenDisplayed) { // bind - productsGrid.BindToGrid(lib); + await productsGrid.BindToGridAsync(libraryBooks); hasBeenDisplayed = true; InitialLoaded?.Invoke(this, new()); } else - productsGrid.UpdateGrid(lib); + productsGrid.UpdateGrid(libraryBooks); } catch (Exception ex) { diff --git a/Source/LibationWinForms/GridView/ProductsGrid.cs b/Source/LibationWinForms/GridView/ProductsGrid.cs index 50172673..7611bbee 100644 --- a/Source/LibationWinForms/GridView/ProductsGrid.cs +++ b/Source/LibationWinForms/GridView/ProductsGrid.cs @@ -5,8 +5,11 @@ using LibationUiBase.GridView; using System; using System.Collections.Generic; using System.Data; +using System.Diagnostics; using System.Drawing; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; namespace LibationWinForms.GridView @@ -53,15 +56,11 @@ namespace LibationWinForms.GridView if (e.RowIndex < 0) return; - // cover - else if (e.ColumnIndex == coverGVColumn.Index) - return; - e.ContextMenuStrip = new ContextMenuStrip(); - // any non-stop light - if (e.ColumnIndex != liberateGVColumn.Index) + // any column except cover & stop light + if (e.ColumnIndex != liberateGVColumn.Index && e.ColumnIndex != coverGVColumn.Index) { - e.ContextMenuStrip.Items.Add("Copy", null, (_, __) => + e.ContextMenuStrip.Items.Add("Copy Cell Contents", null, (_, __) => { try { @@ -70,14 +69,13 @@ namespace LibationWinForms.GridView Clipboard.SetDataObject(text, false, 5, 150); } catch { } - }); - } - else - { - var entry = getGridEntry(e.RowIndex); - var name = gridEntryDataGridView.Columns[e.ColumnIndex].DataPropertyName; - LiberateContextMenuStripNeeded?.Invoke(entry, e.ContextMenuStrip); + }); + e.ContextMenuStrip.Items.Add(new ToolStripSeparator()); } + + var entry = getGridEntry(e.RowIndex); + var name = gridEntryDataGridView.Columns[e.ColumnIndex].DataPropertyName; + LiberateContextMenuStripNeeded?.Invoke(entry, e.ContextMenuStrip); } private void EnableDoubleBuffering() @@ -160,27 +158,23 @@ namespace LibationWinForms.GridView } } - internal void BindToGrid(List dbBooks) + internal async Task BindToGridAsync(List dbBooks) { - var geList = dbBooks - .Where(lb => lb.Book.IsProduct()) - .Select(b => new LibraryBookEntry(b)) - .ToList(); + var geList = await LibraryBookEntry.GetAllProductsAsync(dbBooks); - var episodes = dbBooks.Where(lb => lb.Book.IsEpisodeChild()); + var seriesEntries = await SeriesEntry.GetAllSeriesEntriesAsync(dbBooks); - var seriesBooks = dbBooks.Where(lb => lb.Book.IsEpisodeParent()).ToList(); + geList.AddRange(seriesEntries); + //Sort descending by date (default sort property) + var comparer = new RowComparer(); + geList.Sort((a, b) => comparer.Compare(b, a)); - foreach (var parent in seriesBooks) + //Add all children beneath their parent + foreach (var series in seriesEntries) { - var seriesEpisodes = episodes.FindChildren(parent); - - if (!seriesEpisodes.Any()) continue; - - var seriesEntry = new SeriesEntry(parent, seriesEpisodes); - - geList.Add(seriesEntry); - geList.AddRange(seriesEntry.Children); + var seriesIndex = geList.IndexOf(series); + foreach (var child in series.Children) + geList.Insert(++seriesIndex, child); } bindingList = new GridEntryBindingList(geList); diff --git a/Source/LibationWinForms/ProcessQueue/ProcessBook.cs b/Source/LibationWinForms/ProcessQueue/ProcessBook.cs index ecb372f5..16fc8427 100644 --- a/Source/LibationWinForms/ProcessQueue/ProcessBook.cs +++ b/Source/LibationWinForms/ProcessQueue/ProcessBook.cs @@ -249,9 +249,12 @@ namespace LibationWinForms.ProcessQueue private byte[] AudioDecodable_RequestCoverArt(object sender, EventArgs e) { - byte[] coverData = PictureStorage - .GetPictureSynchronously( - new PictureDefinition(LibraryBook.Book.PictureId, PictureSize._500x500)); + var quality + = Configuration.Instance.FileDownloadQuality == Configuration.DownloadQuality.High + ? new PictureDefinition(LibraryBook.Book.PictureLarge, PictureSize.Native) + : new PictureDefinition(LibraryBook.Book.PictureId, PictureSize._500x500); + + byte[] coverData = PictureStorage.GetPictureSynchronously(quality); AudioDecodable_CoverImageDiscovered(this, coverData); return coverData; diff --git a/Source/LibationWinForms/Program.cs b/Source/LibationWinForms/Program.cs index 340c29b7..57c1437b 100644 --- a/Source/LibationWinForms/Program.cs +++ b/Source/LibationWinForms/Program.cs @@ -2,12 +2,13 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using System.Windows.Forms; +using ApplicationServices; using AppScaffolding; -using Dinah.Core; +using DataLayer; using LibationFileManager; using LibationWinForms.Dialogs; -using Serilog; namespace LibationWinForms { @@ -20,6 +21,7 @@ namespace LibationWinForms [STAThread] static void Main() { + Task> libraryLoadTask; try { //// Uncomment to see Console. Must be called before anything writes to Console. @@ -48,6 +50,17 @@ namespace LibationWinForms // migrations which require Forms or are long-running RunWindowsOnlyMigrations(config); + //*******************************************************************// + // // + // Start loading the library as soon as possible // + // // + // Before calling anything else, including subscribing to events, // + // to ensure database exists. If we wait and let it happen lazily, // + // race conditions and errors are likely during new installs // + // // + //*******************************************************************// + libraryLoadTask = Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking(includeParents: true)); + MessageBoxLib.VerboseLoggingWarning_ShowIfTrue(); // logging is init'd here @@ -71,7 +84,9 @@ namespace LibationWinForms // global exception handling (ShowAdminAlert) attempts to use logging. only call it after logging has been init'd postLoggingGlobalExceptionHandling(); - Application.Run(new Form1()); + var form1 = new Form1(); + form1.Load += async (_, _) => await form1.InitLibraryAsync(await libraryLoadTask); + Application.Run(form1); } private static void RunInstaller(Configuration config) diff --git a/Source/_Tests/FileLiberator.Tests/DownloadDecryptBookTests.cs b/Source/_Tests/FileLiberator.Tests/DownloadDecryptBookTests.cs index 1e6c02a7..e8fb8dfb 100644 --- a/Source/_Tests/FileLiberator.Tests/DownloadDecryptBookTests.cs +++ b/Source/_Tests/FileLiberator.Tests/DownloadDecryptBookTests.cs @@ -540,7 +540,6 @@ namespace FileLiberator.Tests value[i].StartOffsetMs.Should().Be(expected[i].StartOffsetMs); value[i].StartOffsetSec.Should().Be(expected[i].StartOffsetSec); value[i].LengthMs.Should().Be(expected[i].LengthMs); - value[i].Chapters.Should().BeNull(); } } }