Preserving IndexNumber parsed from path for AudioBookFile and using as Chapter

pull/11517/head
Samson50 1 month ago
parent de5cc7b72f
commit d693b2b575

@ -2,6 +2,8 @@
#pragma warning disable CS1591
using System;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Emby.Naming.Audio;
@ -50,7 +52,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.AudioBooks
protected override AudioBook Resolve(ItemResolveArgs args)
{
// We only care about audiobooks
// TODO: Change this to new CollectionType.audiobooks?
if (args.GetCollectionType() != CollectionType.books)
{
return null;
@ -64,26 +65,24 @@ namespace Emby.Server.Implementations.Library.Resolvers.AudioBooks
var audioBook = new AudioBook();
// TODO: Get title from path...
// TODO: Get title from path or from child file "Album" metadata
var bookFileName = Path.GetFileNameWithoutExtension(args.Path);
var name = MatchFor(bookFileName, "name");
if (name == null)
{
name = bookFileName;
}
name ??= bookFileName;
var year = MatchFor(bookFileName, "year");
audioBook.Name = name;
audioBook.ProductionYear = Convert.ToInt16(year, CultureInfo.InvariantCulture);
// Process directory to resolve single audio book
if (args.IsDirectory)
{
// Majority children must be audio files
int audioFiles = 0;
int nonAudioFiles = 0;
// TODO: What's the fancy C# way to do this?
for (var i = 0; i < args.FileSystemChildren.Length; i++)
foreach (var child in args.FileSystemChildren)
{
var child = args.FileSystemChildren[i];
if (AudioFileParser.IsAudioFile(child.FullName, _namingOptions))
{
audioFiles += 1;
@ -121,8 +120,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.AudioBooks
var extension = Path.GetExtension(args.Path);
audioBookFile.Container = extension.TrimStart('.');
audioBookFile.Chapter = 0;
// audioBookFile.path = args.path; ?
audioBookFile.IndexNumber = 0;
audioBookFile.Path = args.Path;
return audioBook;
}

@ -2,7 +2,6 @@
#pragma warning disable CS1591
using System;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
@ -64,9 +63,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.AudioBooks
audioBookFile.Container = extension.TrimStart('.');
audioBookFile.Chapter = ParseChapter(args.Path);
_logger.LogInformation("Chapter = {Chapter}", audioBookFile.Chapter);
audioBookFile.IndexNumber = ParseChapter(args.Path);
return audioBookFile;
}

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
@ -17,7 +16,6 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
// TODO: Use ChapterInfo?.
namespace MediaBrowser.Controller.Entities.AudioBooks
{
/// <summary>
@ -31,11 +29,12 @@ namespace MediaBrowser.Controller.Entities.AudioBooks
[JsonIgnore]
public override MediaType MediaType => MediaType.Audio;
public string BookTitle { get; set; }
// For audiobook file metadata, the title is often "[book title] - [chapter #]" and the album is the book title alone
public string BookTitle => Album;
public int Chapter { get; set; }
public int Chapter => IndexNumber.HasValue ? IndexNumber.Value : 0;
public IReadOnlyList<string> Authors { get; set; }
public IReadOnlyList<string> Authors => Artists;
[JsonIgnore]
public override bool SupportsPlayedStatus => true;
@ -103,6 +102,7 @@ namespace MediaBrowser.Controller.Entities.AudioBooks
return AudioBookEntity?.PresentationUniqueKey;
}
// TODO: Behavior may be more consistent if we use "Album" metadata and push up to parent
public string FindAudioBookName()
{
return AudioBookEntity is null ? "AudioBook Unknown" : AudioBookEntity.Name;
@ -114,13 +114,13 @@ namespace MediaBrowser.Controller.Entities.AudioBooks
}
/// <summary>
/// Creates the name of the sort.
/// Creates the string by which this item will be sorted amongst other children. Logically, AudioBookFiles
/// must already be named in a unique, indexable way so we can just return the name.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateSortName()
{
return (ParentIndexNumber is not null ? ParentIndexNumber.Value.ToString("000 - ", CultureInfo.InvariantCulture) : string.Empty)
+ (IndexNumber is not null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
return Name;
}
public override IEnumerable<FileSystemMetadata> GetDeletePaths()
@ -135,13 +135,15 @@ namespace MediaBrowser.Controller.Entities.AudioBooks
}.Concat(GetLocalMetadataFilesToDelete());
}
// TODO: I'm still not sure where this fits into the larger framework.
public new AudioBookFileInfo GetLookupInfo()
{
var id = GetItemLookupInfo<AudioBookFileInfo>();
id.BookTitle = BookTitle;
id.Authors = Authors;
id.BookTitle = Album;
id.Artists = Artists;
id.Container = Container;
id.Chapter = (int)IndexNumber;
return id;
}
@ -169,17 +171,10 @@ namespace MediaBrowser.Controller.Entities.AudioBooks
public void SetFilesPlayed(User user, IUserDataManager userDataManager)
{
// TEMP: Sort by name, mark played accoringly
// TODO: Mark played by chapter number
// TODO: Figure out why chapter is not stored/returned correctly
var chapters = AudioBookEntity.Chapters.OrderBy(s => s.Name);
bool afterCurrent = false;
foreach (var chapter in chapters)
foreach (var chapter in AudioBookEntity.Chapters)
{
if (chapter.Name == Name)
{
afterCurrent = true;
continue;
}
@ -187,13 +182,13 @@ namespace MediaBrowser.Controller.Entities.AudioBooks
var userData = userDataManager.GetUserData(user, chapter);
// TODO: DECISION: Should we leave PlaybackPositionTicks or set to 0?
if (afterCurrent && userData.Played)
if (chapter.Chapter > Chapter && userData.Played)
{
userData.Played = false;
userData.PlaybackPositionTicks = 0;
changed = true;
}
else if (!afterCurrent && !userData.Played)
else if (!userData.Played)
{
userData.Played = true;
userData.PlaybackPositionTicks = 0;

@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Providers
{
public AudioBookFileInfo()
{
Authors = Array.Empty<string>();
Artists = Array.Empty<string>();
}
public string BookTitle { get; set; }
@ -20,6 +20,6 @@ namespace MediaBrowser.Controller.Providers
public string Container { get; set; }
public IReadOnlyList<string> Authors { get; set; }
public IReadOnlyList<string> Artists { get; set; }
}
}

@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.Books
{
/// <summary>
/// The audio metadata service.
/// Class to register providers for individual AudioBook files.
/// </summary>
public class AudioBookFileMetadataService : MetadataService<AudioBookFile, AudioBookFileInfo>
{
@ -56,9 +56,9 @@ namespace MediaBrowser.Providers.Books
var sourceItem = source.Item;
var targetItem = target.Item;
if (replaceData || targetItem.Authors.Count == 0)
if (replaceData || targetItem.Artists.Count == 0)
{
targetItem.Authors = sourceItem.Authors;
targetItem.Artists = sourceItem.Artists;
}
if (replaceData || string.IsNullOrEmpty(targetItem.Album))
@ -67,6 +67,8 @@ namespace MediaBrowser.Providers.Books
}
// TODO: Create and register provider specific to book information and AudioBook information
// https://openlibrary.org/developers/api
// https://openlibrary.org/search.json?title=war&author=sebastian+junger
}
}
}

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.AudioBooks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Lyrics;
using MediaBrowser.Controller.MediaEncoding;
@ -309,7 +310,12 @@ namespace MediaBrowser.Providers.MediaInfo
if (options.ReplaceAllMetadata)
{
audio.Album = tags.Album;
audio.IndexNumber = Convert.ToInt32(tags.Track);
// We want to preserve the IndexNumber value parsed from AudioBookFile path if it exists
if (audio.GetType() != typeof(AudioBookFile) || !audio.IndexNumber.HasValue)
{
audio.IndexNumber = Convert.ToInt32(tags.Track);
}
audio.ParentIndexNumber = Convert.ToInt32(tags.Disc);
}
else

Loading…
Cancel
Save