- Add Book.IsSpatial property and add it to search index - Read audio format of actual output files and store it in UserDefinedItem. Now works with MP3s. - Store last downloaded audio file version - Add IsSpatial, file version, and Audio Format to library exports and to template tags. Updated docs. - Add last downloaded audio file version and format info to the Last Downloaded tab - Migrated the DB - Update AAXClean with some bug fixes - Fixed error converting xHE-AAC audio files to mp3 when splitting by chapter (or trimming the audible branding from the beginning of the file) - Improve mp3 ID# tags support. Chapter titles are now preserved. - Add support for reading EC-3 and AC-4 audio format metadata
158 lines
5.3 KiB
C#
158 lines
5.3 KiB
C#
using AaxDecrypter;
|
|
using FileManager;
|
|
using System;
|
|
using System.IO;
|
|
|
|
#nullable enable
|
|
namespace LibationFileManager.Templates
|
|
{
|
|
public interface ITemplateEditor
|
|
{
|
|
bool IsFolder { get; }
|
|
bool IsFilePath { get; }
|
|
LongPath BaseDirectory { get; }
|
|
string DefaultTemplate { get; }
|
|
string TemplateName { get; }
|
|
string TemplateDescription { get; }
|
|
Templates EditingTemplate { get; }
|
|
bool SetTemplateText(string templateText);
|
|
string? GetFolderName();
|
|
string? GetFileName();
|
|
string? GetName();
|
|
}
|
|
|
|
public class TemplateEditor<T> : ITemplateEditor where T : Templates, ITemplate, new()
|
|
{
|
|
public bool IsFolder => EditingTemplate is Templates.FolderTemplate;
|
|
public bool IsFilePath => EditingTemplate is not Templates.ChapterTitleTemplate;
|
|
public LongPath BaseDirectory { get; private init; }
|
|
public string DefaultTemplate { get; private init; }
|
|
public string TemplateName { get; private init; }
|
|
public string TemplateDescription { get; private init; }
|
|
private Templates? Folder { get; set; }
|
|
private Templates? File { get; set; }
|
|
private Templates? Name { get; set; }
|
|
public Templates EditingTemplate
|
|
{
|
|
get => _editingTemplate;
|
|
private set => _editingTemplate = !IsFilePath ? Name = value : IsFolder ? Folder = value : File = value;
|
|
}
|
|
|
|
private Templates _editingTemplate;
|
|
|
|
public bool SetTemplateText(string templateText)
|
|
{
|
|
if (Templates.TryGetTemplate<T>(templateText, out var template))
|
|
{
|
|
EditingTemplate = template;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public LibraryBookDto FolderBook { get; }
|
|
public LibraryBookDto LibraryBook { get; }
|
|
|
|
private static readonly LibraryBookDto DefaultLibraryBook
|
|
= new()
|
|
{
|
|
Account = "myaccount@example.co",
|
|
AccountNickname = "my account",
|
|
DateAdded = new DateTime(2022, 6, 9, 0, 0, 0),
|
|
DatePublished = new DateTime(2017, 2, 27, 0, 0, 0),
|
|
AudibleProductId = "B06WLMWF2S",
|
|
Title = "A Study in Scarlet",
|
|
TitleWithSubtitle = "A Study in Scarlet: A Sherlock Holmes Novel",
|
|
Subtitle = "A Sherlock Holmes Novel",
|
|
Locale = "us",
|
|
YearPublished = 2017,
|
|
Authors = [new("Arthur Conan Doyle", "B000AQ43GQ"), new("Stephen Fry - introductions", "B000APAGVS")],
|
|
Narrators = [new("Stephen Fry", null)],
|
|
Series = [new("Sherlock Holmes", 1, "B08376S3R2"), new("Some Other Series", 1, "B000000000")],
|
|
Codec = "AAC-LC",
|
|
LibationVersion = Configuration.LibationVersion?.ToString(3),
|
|
FileVersion = "36217811",
|
|
BitRate = 128,
|
|
SampleRate = 44100,
|
|
Channels = 2,
|
|
Language = "English"
|
|
};
|
|
|
|
private static readonly MultiConvertFileProperties DefaultMultipartProperties
|
|
= new()
|
|
{
|
|
OutputFileName = "",
|
|
PartsPosition = 4,
|
|
PartsTotal = 10,
|
|
Title = "A Flight for Life"
|
|
};
|
|
|
|
public string? GetFolderName()
|
|
{
|
|
/*
|
|
* Path must be rooted for windows to allow long file paths. This is
|
|
* only necessary for folder templates because they may contain several
|
|
* subdirectories. Without rooting, we won't be allowed to create a
|
|
* relative path longer than MAX_PATH.
|
|
*/
|
|
var dir = Folder?.GetFilename(FolderBook, BaseDirectory, "");
|
|
if (dir is null) return null;
|
|
return Path.GetRelativePath(BaseDirectory, dir);
|
|
}
|
|
|
|
public string? GetFileName()
|
|
=> File?.GetFilename(LibraryBook, DefaultMultipartProperties, "", "");
|
|
public string? GetName()
|
|
=> Name?.GetName(LibraryBook, DefaultMultipartProperties);
|
|
|
|
private TemplateEditor(
|
|
LibraryBookDto? folderDto,
|
|
LibraryBookDto? fileDto,
|
|
Templates editingTemplate,
|
|
LongPath baseDirectory,
|
|
string defaultTemplate,
|
|
string templateName,
|
|
string templateDescription)
|
|
{
|
|
FolderBook = folderDto ?? DefaultLibraryBook;
|
|
LibraryBook = fileDto ?? DefaultLibraryBook;
|
|
_editingTemplate = editingTemplate;
|
|
BaseDirectory = baseDirectory;
|
|
DefaultTemplate = defaultTemplate;
|
|
TemplateName = templateName;
|
|
TemplateDescription = templateDescription;
|
|
}
|
|
|
|
public static ITemplateEditor CreateFilenameEditor(LongPath baseDir, string templateText, LibraryBookDto? folderDto = null, LibraryBookDto? fileDto = null)
|
|
{
|
|
if (!Templates.TryGetTemplate<T>(templateText, out var template))
|
|
throw new ArgumentException($"Failed to parse {nameof(templateText)}");
|
|
|
|
var templateEditor = new TemplateEditor<T>(folderDto, fileDto, template, baseDir, T.DefaultTemplate, T.Name, T.Description);
|
|
|
|
if (!templateEditor.IsFolder && !templateEditor.IsFilePath)
|
|
throw new InvalidOperationException($"This method is only for File and Folder templates. Use {nameof(CreateNameEditor)} for name templates");
|
|
|
|
if (templateEditor.IsFolder)
|
|
templateEditor.File = Templates.File;
|
|
else
|
|
templateEditor.Folder = Templates.Folder;
|
|
|
|
return templateEditor;
|
|
}
|
|
|
|
public static ITemplateEditor CreateNameEditor(string templateText, LibraryBookDto? libraryBookDto = null)
|
|
{
|
|
if (!Templates.TryGetTemplate<T>(templateText, out var nameTemplate))
|
|
throw new ArgumentException($"Failed to parse {nameof(templateText)}");
|
|
|
|
var templateEditor = new TemplateEditor<T>(null, libraryBookDto, nameTemplate, "", T.DefaultTemplate, T.Name, T.Description);
|
|
|
|
if (templateEditor.IsFolder || templateEditor.IsFilePath)
|
|
throw new InvalidOperationException($"This method is only for name templates. Use {nameof(CreateFilenameEditor)} for file templates");
|
|
|
|
return templateEditor;
|
|
}
|
|
}
|
|
}
|