From 77e61479cfb655d3823d2e32a7daf7031a837dd8 Mon Sep 17 00:00:00 2001 From: Robert McRackan Date: Thu, 21 Jul 2022 08:37:04 -0400 Subject: [PATCH] New feature #284 : Add bitrate, sample rate, and channels to template options and to exports --- Source/ApplicationServices/LibraryExporter.cs | 62 ++++++++++--------- Source/DataLayer/EfClasses/AudioFormat.cs | 1 - Source/FileLiberator/UtilityExtensions.cs | 6 +- Source/LibationFileManager/LibraryBookDto.cs | 4 ++ Source/LibationFileManager/TemplateTags.cs | 3 + Source/LibationFileManager/Templates.cs | 3 + .../Dialogs/EditTemplateDialog.cs | 5 +- .../FileNamingTemplateTests.cs | 2 +- .../TemplatesTests.cs | 58 ++++++++++------- 9 files changed, 89 insertions(+), 55 deletions(-) diff --git a/Source/ApplicationServices/LibraryExporter.cs b/Source/ApplicationServices/LibraryExporter.cs index 3f948e66..7f751f5f 100644 --- a/Source/ApplicationServices/LibraryExporter.cs +++ b/Source/ApplicationServices/LibraryExporter.cs @@ -100,6 +100,9 @@ namespace ApplicationServices [Name("Content Type")] public string ContentType { get; set; } + + [Name("Audio Format")] + public string AudioFormat { get; set; } } public static class LibToDtos { @@ -132,7 +135,8 @@ namespace ApplicationServices MyLibationTags = a.Book.UserDefinedItem.Tags, BookStatus = a.Book.UserDefinedItem.BookStatus.ToString(), PdfStatus = a.Book.UserDefinedItem.PdfStatus.ToString(), - ContentType = a.Book.ContentType.ToString() + ContentType = a.Book.ContentType.ToString(), + AudioFormat = a.Book.AudioFormat.ToString() }).ToList(); } public static class LibraryExporter @@ -176,33 +180,34 @@ namespace ApplicationServices var row = sheet.CreateRow(rowIndex); var columns = new[] { - nameof (ExportDto.Account), - nameof (ExportDto.DateAdded), - nameof (ExportDto.AudibleProductId), - nameof (ExportDto.Locale), - nameof (ExportDto.Title), - nameof (ExportDto.AuthorNames), - nameof (ExportDto.NarratorNames), - nameof (ExportDto.LengthInMinutes), - nameof (ExportDto.Description), - nameof (ExportDto.Publisher), - nameof (ExportDto.HasPdf), - nameof (ExportDto.SeriesNames), - nameof (ExportDto.SeriesOrder), - nameof (ExportDto.CommunityRatingOverall), - nameof (ExportDto.CommunityRatingPerformance), - nameof (ExportDto.CommunityRatingStory), - nameof (ExportDto.PictureId), - nameof (ExportDto.IsAbridged), - nameof (ExportDto.DatePublished), - nameof (ExportDto.CategoriesNames), - nameof (ExportDto.MyRatingOverall), - nameof (ExportDto.MyRatingPerformance), - nameof (ExportDto.MyRatingStory), - nameof (ExportDto.MyLibationTags), - nameof (ExportDto.BookStatus), - nameof (ExportDto.PdfStatus), - nameof (ExportDto.ContentType) + nameof(ExportDto.Account), + nameof(ExportDto.DateAdded), + nameof(ExportDto.AudibleProductId), + nameof(ExportDto.Locale), + nameof(ExportDto.Title), + nameof(ExportDto.AuthorNames), + nameof(ExportDto.NarratorNames), + nameof(ExportDto.LengthInMinutes), + nameof(ExportDto.Description), + nameof(ExportDto.Publisher), + nameof(ExportDto.HasPdf), + nameof(ExportDto.SeriesNames), + nameof(ExportDto.SeriesOrder), + nameof(ExportDto.CommunityRatingOverall), + nameof(ExportDto.CommunityRatingPerformance), + nameof(ExportDto.CommunityRatingStory), + nameof(ExportDto.PictureId), + nameof(ExportDto.IsAbridged), + nameof(ExportDto.DatePublished), + nameof(ExportDto.CategoriesNames), + nameof(ExportDto.MyRatingOverall), + nameof(ExportDto.MyRatingPerformance), + nameof(ExportDto.MyRatingStory), + nameof(ExportDto.MyLibationTags), + nameof(ExportDto.BookStatus), + nameof(ExportDto.PdfStatus), + nameof(ExportDto.ContentType), + nameof(ExportDto.AudioFormat) }; var col = 0; foreach (var c in columns) @@ -268,6 +273,7 @@ namespace ApplicationServices row.CreateCell(col++).SetCellValue(dto.BookStatus); row.CreateCell(col++).SetCellValue(dto.PdfStatus); row.CreateCell(col++).SetCellValue(dto.ContentType); + row.CreateCell(col++).SetCellValue(dto.AudioFormat); rowIndex++; } diff --git a/Source/DataLayer/EfClasses/AudioFormat.cs b/Source/DataLayer/EfClasses/AudioFormat.cs index 2d2f9d19..fc78c70a 100644 --- a/Source/DataLayer/EfClasses/AudioFormat.cs +++ b/Source/DataLayer/EfClasses/AudioFormat.cs @@ -17,7 +17,6 @@ namespace DataLayer public class AudioFormat : IComparable, IComparable { - internal int AudioFormatID { get; private set; } public int Bitrate { get; private init; } public int SampleRate { get; private init; } diff --git a/Source/FileLiberator/UtilityExtensions.cs b/Source/FileLiberator/UtilityExtensions.cs index b6516ba9..692eef94 100644 --- a/Source/FileLiberator/UtilityExtensions.cs +++ b/Source/FileLiberator/UtilityExtensions.cs @@ -37,7 +37,11 @@ namespace FileLiberator Narrators = libraryBook.Book.Narrators.Select(c => c.Name).ToList(), SeriesName = libraryBook.Book.SeriesLink.FirstOrDefault()?.Series.Name, - SeriesNumber = libraryBook.Book.SeriesLink.FirstOrDefault()?.Order + SeriesNumber = libraryBook.Book.SeriesLink.FirstOrDefault()?.Order, + + BitRate = libraryBook.Book.AudioFormat.Bitrate, + SampleRate = libraryBook.Book.AudioFormat.SampleRate, + Channels = libraryBook.Book.AudioFormat.Channels, }; } } diff --git a/Source/LibationFileManager/LibraryBookDto.cs b/Source/LibationFileManager/LibraryBookDto.cs index a3d0c690..bd17048e 100644 --- a/Source/LibationFileManager/LibraryBookDto.cs +++ b/Source/LibationFileManager/LibraryBookDto.cs @@ -20,6 +20,10 @@ namespace LibationFileManager public string SeriesName { get; set; } public string SeriesNumber { get; set; } + + public int BitRate { get; set; } + public int SampleRate { get; set; } + public int Channels { get; set; } } public class LibraryBookDto : BookDto diff --git a/Source/LibationFileManager/TemplateTags.cs b/Source/LibationFileManager/TemplateTags.cs index ac5005d2..ee081b14 100644 --- a/Source/LibationFileManager/TemplateTags.cs +++ b/Source/LibationFileManager/TemplateTags.cs @@ -34,6 +34,9 @@ namespace LibationFileManager public static TemplateTags Series { get; } = new TemplateTags("series", "Name of series"); // can't also have a leading zeros version. Too many weird edge cases. Eg: "1-4" public static TemplateTags SeriesNumber { get; } = new TemplateTags("series#", "Number order in series"); + public static TemplateTags Bitrate { get; } = new TemplateTags("bitrate", "File's orig. bitrate"); + public static TemplateTags SampleRate { get; } = new TemplateTags("samplerate", "File's orig. sample rate"); + public static TemplateTags Channels { get; } = new TemplateTags("channels", "Number of audio channels"); public static TemplateTags Account { get; } = new TemplateTags("account", "Audible account of this book"); public static TemplateTags Locale { get; } = new TemplateTags("locale", "Region/country"); diff --git a/Source/LibationFileManager/Templates.cs b/Source/LibationFileManager/Templates.cs index f9a4d06f..69c992c9 100644 --- a/Source/LibationFileManager/Templates.cs +++ b/Source/LibationFileManager/Templates.cs @@ -137,6 +137,9 @@ namespace LibationFileManager fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstNarrator, libraryBookDto.FirstNarrator); fileNamingTemplate.AddParameterReplacement(TemplateTags.Series, libraryBookDto.SeriesName); fileNamingTemplate.AddParameterReplacement(TemplateTags.SeriesNumber, libraryBookDto.SeriesNumber); + fileNamingTemplate.AddParameterReplacement(TemplateTags.Bitrate, libraryBookDto.BitRate); + fileNamingTemplate.AddParameterReplacement(TemplateTags.SampleRate, libraryBookDto.SampleRate); + fileNamingTemplate.AddParameterReplacement(TemplateTags.Channels, libraryBookDto.Channels); fileNamingTemplate.AddParameterReplacement(TemplateTags.Account, libraryBookDto.Account); fileNamingTemplate.AddParameterReplacement(TemplateTags.Locale, libraryBookDto.Locale); diff --git a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs index a1ecee98..25551906 100644 --- a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs +++ b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs @@ -79,7 +79,10 @@ namespace LibationWinForms.Dialogs Authors = new List { "Arthur Conan Doyle", "Stephen Fry - introductions" }, Narrators = new List { "Stephen Fry" }, SeriesName = "Sherlock Holmes", - SeriesNumber = "1" + SeriesNumber = "1", + BitRate = 128, + SampleRate = 44100, + Channels = 2 }; var chapterName = "A Flight for Life"; var chapterNumber = 4; diff --git a/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs b/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs index 8db45ca4..9a2d8a30 100644 --- a/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs +++ b/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs @@ -21,7 +21,7 @@ namespace FileNamingTemplateTests sb.Append('0', 300); var longText = sb.ToString(); - var expectedNew = "C:\\foo\\bar\\my꞉ book 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 [ID123456].txt"; + var expectedNew = @"C:\foo\bar\my꞉ book 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 [ID123456].txt"; var f2 = NEW_GetValidFilename_FileNamingTemplate(@"C:\foo\bar", "my: book " + longText, "txt", "ID123456"); f2.Should().Be(expectedNew); diff --git a/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs b/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs index f598c8cc..fb0bff88 100644 --- a/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs +++ b/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs @@ -12,19 +12,30 @@ using static TemplatesTests.Shared; namespace TemplatesTests { + ///////////////////////////////////////////////// + // // + // add general tag replacement tests to: // + // // + // getFileNamingTemplate.Tests // + // // + ///////////////////////////////////////////////// + public static class Shared { - public static LibraryBookDto GetLibraryBook(string asin, string seriesName = "Sherlock Holmes") + public static LibraryBookDto GetLibraryBook(string seriesName = "Sherlock Holmes") => new() { Account = "my account", - AudibleProductId = asin, + AudibleProductId = "asin", Title = "A Study in Scarlet: A Sherlock Holmes Novel", Locale = "us", Authors = new List { "Arthur Conan Doyle", "Stephen Fry - introductions" }, Narrators = new List { "Stephen Fry" }, SeriesName = seriesName ?? "", - SeriesNumber = "1" + SeriesNumber = "1", + BitRate = 128, + SampleRate = 44100, + Channels = 2 }; } @@ -56,48 +67,49 @@ namespace TemplatesTests [TestMethod] - [DataRow(null, "asin", @"C:\", "ext")] + [DataRow(null, @"C:\", "ext")] [ExpectedException(typeof(ArgumentNullException))] - public void arg_null_exception(string template, string asin, string dirFullPath, string extension) - => Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension); + public void arg_null_exception(string template, string dirFullPath, string extension) + => Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension); [TestMethod] - [DataRow("", "asin", @"C:\foo\bar", "ext")] - [DataRow(" ", "asin", @"C:\foo\bar", "ext")] + [DataRow("", @"C:\foo\bar", "ext")] + [DataRow(" ", @"C:\foo\bar", "ext")] [ExpectedException(typeof(ArgumentException))] - public void arg_exception(string template, string asin, string dirFullPath, string extension) - => Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension); + public void arg_exception(string template, string dirFullPath, string extension) + => Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension); [TestMethod] - public void null_extension() => Tests("f.txt", "asin", @"C:\foo\bar", null, @"C:\foo\bar\f.txt"); + public void null_extension() => Tests("f.txt", @"C:\foo\bar", null, @"C:\foo\bar\f.txt"); [TestMethod] - [DataRow("f.txt", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext")] - [DataRow("f", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext")] - [DataRow("", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext")] - public void Tests(string template, string asin, string dirFullPath, string extension, string expected) - => Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension) + [DataRow("f.txt", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext")] + [DataRow("f", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext")] + [DataRow("", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext")] + [DataRow(" - - ", @"C:\foo\bar", "ext", @"C:\foo\bar\128 - 44100 - 2.ext")] + public void Tests(string template, string dirFullPath, string extension, string expected) + => Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension) .GetFilePath(Replacements) .PathWithoutPrefix .Should().Be(expected); [TestMethod] public void IfSeries_empty() - => Templates.getFileNamingTemplate(GetLibraryBook("asin", "Sherlock Holmes"), "foo<-if series>bar", @"C:\a\b", "ext") + => Templates.getFileNamingTemplate(GetLibraryBook(), "foo<-if series>bar", @"C:\a\b", "ext") .GetFilePath(Replacements) .PathWithoutPrefix .Should().Be(@"C:\a\b\foobar.ext"); [TestMethod] public void IfSeries_no_series() - => Templates.getFileNamingTemplate(GetLibraryBook("asin", ""), "foo---<-if series>bar", @"C:\a\b", "ext") + => Templates.getFileNamingTemplate(GetLibraryBook(null), "foo---<-if series>bar", @"C:\a\b", "ext") .GetFilePath(Replacements) .PathWithoutPrefix .Should().Be(@"C:\a\b\foobar.ext"); [TestMethod] public void IfSeries_with_series() - => Templates.getFileNamingTemplate(GetLibraryBook("asin", "Sherlock Holmes"), "foo---<-if series>bar", @"C:\a\b", "ext") + => Templates.getFileNamingTemplate(GetLibraryBook(), "foo---<-if series>bar", @"C:\a\b", "ext") .GetFilePath(Replacements) .PathWithoutPrefix .Should().Be(@"C:\a\b\foo-Sherlock Holmes-asin-bar.ext"); @@ -394,10 +406,10 @@ namespace Templates_ChapterFile_Tests static readonly ReplacementCharacters Default = ReplacementCharacters.Default; [TestMethod] - [DataRow("asin", "[] of - ", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\[asin] 06 of 10 - chap.txt")] - [DataRow("asin", "", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\6.txt")] - public void Tests(string asin, string template, string dir, string ext, int pos, int total, string chapter, string expected) - => Templates.ChapterFile.GetPortionFilename(GetLibraryBook(asin), template, new() { OutputFileName = $"xyz.{ext}", PartsPosition = pos, PartsTotal = total, Title = chapter }, dir, Default) + [DataRow("[] of - ", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\[asin] 06 of 10 - chap.txt")] + [DataRow("", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\6.txt")] + public void Tests(string template, string dir, string ext, int pos, int total, string chapter, string expected) + => Templates.ChapterFile.GetPortionFilename(GetLibraryBook(), template, new() { OutputFileName = $"xyz.{ext}", PartsPosition = pos, PartsTotal = total, Title = chapter }, dir, Default) .Should().Be(expected); } }