Backport pull request #11762 from jellyfin/release-10.9.z

Mark Audio as RequiresDeserialization and backfill data

Original-merge: e2c909f50f

Merged-by: joshuaboniface <joshua@boniface.me>

Backported-by: Joshua M. Boniface <joshua@boniface.me>
pull/11877/head
Shadowghost 6 months ago committed by Joshua M. Boniface
parent 5d4880c497
commit 407dc9272c

@ -1298,16 +1298,15 @@ namespace Emby.Server.Implementations.Data
&& type != typeof(Book) && type != typeof(Book)
&& type != typeof(LiveTvProgram) && type != typeof(LiveTvProgram)
&& type != typeof(AudioBook) && type != typeof(AudioBook)
&& type != typeof(Audio)
&& type != typeof(MusicAlbum); && type != typeof(MusicAlbum);
} }
private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query) private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query)
{ {
return GetItem(reader, query, HasProgramAttributes(query), HasEpisodeAttributes(query), HasServiceName(query), HasStartDate(query), HasTrailerTypes(query), HasArtistFields(query), HasSeriesFields(query)); return GetItem(reader, query, HasProgramAttributes(query), HasEpisodeAttributes(query), HasServiceName(query), HasStartDate(query), HasTrailerTypes(query), HasArtistFields(query), HasSeriesFields(query), false);
} }
private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query, bool enableProgramAttributes, bool hasEpisodeAttributes, bool hasServiceName, bool queryHasStartDate, bool hasTrailerTypes, bool hasArtistFields, bool hasSeriesFields) private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query, bool enableProgramAttributes, bool hasEpisodeAttributes, bool hasServiceName, bool queryHasStartDate, bool hasTrailerTypes, bool hasArtistFields, bool hasSeriesFields, bool skipDeserialization)
{ {
var typeString = reader.GetString(0); var typeString = reader.GetString(0);
@ -1320,7 +1319,7 @@ namespace Emby.Server.Implementations.Data
BaseItem item = null; BaseItem item = null;
if (TypeRequiresDeserialization(type)) if (TypeRequiresDeserialization(type) && !skipDeserialization)
{ {
try try
{ {
@ -2562,7 +2561,7 @@ namespace Emby.Server.Implementations.Data
foreach (var row in statement.ExecuteQuery()) foreach (var row in statement.ExecuteQuery())
{ {
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields, query.SkipDeserialization);
if (item is not null) if (item is not null)
{ {
items.Add(item); items.Add(item);
@ -2774,7 +2773,7 @@ namespace Emby.Server.Implementations.Data
foreach (var row in statement.ExecuteQuery()) foreach (var row in statement.ExecuteQuery())
{ {
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields, false);
if (item is not null) if (item is not null)
{ {
list.Add(item); list.Add(item);
@ -5021,7 +5020,7 @@ AND Type = @InternalPersonType)");
foreach (var row in statement.ExecuteQuery()) foreach (var row in statement.ExecuteQuery())
{ {
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields, false);
if (item is not null) if (item is not null)
{ {
var countStartColumn = columns.Count - 1; var countStartColumn = columns.Count - 1;

@ -44,7 +44,8 @@ namespace Jellyfin.Server.Migrations
typeof(Routines.FixPlaylistOwner), typeof(Routines.FixPlaylistOwner),
typeof(Routines.MigrateRatingLevels), typeof(Routines.MigrateRatingLevels),
typeof(Routines.AddDefaultCastReceivers), typeof(Routines.AddDefaultCastReceivers),
typeof(Routines.UpdateDefaultPluginRepository) typeof(Routines.UpdateDefaultPluginRepository),
typeof(Routines.FixAudioData),
}; };
/// <summary> /// <summary>

@ -0,0 +1,104 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Server.Migrations.Routines
{
/// <summary>
/// Fixes the data column of audio types to be deserializable.
/// </summary>
internal class FixAudioData : IMigrationRoutine
{
private const string DbFilename = "library.db";
private readonly ILogger<FixAudioData> _logger;
private readonly IServerApplicationPaths _applicationPaths;
private readonly IItemRepository _itemRepository;
public FixAudioData(
IServerApplicationPaths applicationPaths,
ILoggerFactory loggerFactory,
IItemRepository itemRepository)
{
_applicationPaths = applicationPaths;
_itemRepository = itemRepository;
_logger = loggerFactory.CreateLogger<FixAudioData>();
}
/// <inheritdoc/>
public Guid Id => Guid.Parse("{CF6FABC2-9FBE-4933-84A5-FFE52EF22A58}");
/// <inheritdoc/>
public string Name => "FixAudioData";
/// <inheritdoc/>
public bool PerformOnNewInstall => false;
/// <inheritdoc/>
public void Perform()
{
var dbPath = Path.Combine(_applicationPaths.DataPath, DbFilename);
// Back up the database before modifying any entries
for (int i = 1; ; i++)
{
var bakPath = string.Format(CultureInfo.InvariantCulture, "{0}.bak{1}", dbPath, i);
if (!File.Exists(bakPath))
{
try
{
File.Copy(dbPath, bakPath);
_logger.LogInformation("Library database backed up to {BackupPath}", bakPath);
break;
}
catch (Exception ex)
{
_logger.LogError(ex, "Cannot make a backup of {Library} at path {BackupPath}", DbFilename, bakPath);
throw;
}
}
}
_logger.LogInformation("Backfilling audio lyrics data to database.");
var startIndex = 0;
var records = _itemRepository.GetCount(new InternalItemsQuery
{
IncludeItemTypes = [BaseItemKind.Audio],
});
while (startIndex < records)
{
var results = _itemRepository.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = [BaseItemKind.Audio],
StartIndex = startIndex,
Limit = 100,
SkipDeserialization = true
})
.Cast<Audio>()
.ToList();
foreach (var audio in results)
{
var lyricMediaStreams = audio.GetMediaStreams().Where(s => s.Type == MediaStreamType.Lyric).Select(s => s.Path).ToList();
if (lyricMediaStreams.Count > 0)
{
audio.HasLyrics = true;
audio.LyricFiles = lyricMediaStreams;
}
}
_itemRepository.SaveItems(results, CancellationToken.None);
startIndex += 100;
}
}
}
}

@ -51,6 +51,7 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = Array.Empty<TrailerType>(); TrailerTypes = Array.Empty<TrailerType>();
VideoTypes = Array.Empty<VideoType>(); VideoTypes = Array.Empty<VideoType>();
Years = Array.Empty<int>(); Years = Array.Empty<int>();
SkipDeserialization = false;
} }
public InternalItemsQuery(User? user) public InternalItemsQuery(User? user)
@ -358,6 +359,8 @@ namespace MediaBrowser.Controller.Entities
public string? SeriesTimerId { get; set; } public string? SeriesTimerId { get; set; }
public bool SkipDeserialization { get; set; }
public void SetUser(User user) public void SetUser(User user)
{ {
MaxParentalRating = user.MaxParentalAgeRating; MaxParentalRating = user.MaxParentalAgeRating;

Loading…
Cancel
Save