Skip to content

Commit

Permalink
Mark Audio as RequiresDeserialization and backfill data
Browse files Browse the repository at this point in the history
  • Loading branch information
Shadowghost committed May 20, 2024
1 parent 76854b5 commit 7d983ae
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 8 deletions.
13 changes: 6 additions & 7 deletions Emby.Server.Implementations/Data/SqliteItemRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,16 +1298,15 @@ private bool TypeRequiresDeserialization(Type type)
&& type != typeof(Book)
&& type != typeof(LiveTvProgram)
&& type != typeof(AudioBook)
&& type != typeof(Audio)
&& type != typeof(MusicAlbum);
}

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);

Expand All @@ -1320,7 +1319,7 @@ private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query, bool

BaseItem item = null;

if (TypeRequiresDeserialization(type))
if (TypeRequiresDeserialization(type) && !skipDeserialization)
{
try
{
Expand Down Expand Up @@ -2562,7 +2561,7 @@ public List<BaseItem> GetItemList(InternalItemsQuery query)

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)
{
items.Add(item);
Expand Down Expand Up @@ -2774,7 +2773,7 @@ public QueryResult<BaseItem> GetItems(InternalItemsQuery query)

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)
{
list.Add(item);
Expand Down Expand Up @@ -5021,7 +5020,7 @@ private List<string> GetItemValueNames(int[] itemValueTypes, IReadOnlyList<strin

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)
{
var countStartColumn = columns.Count - 1;
Expand Down
3 changes: 2 additions & 1 deletion Jellyfin.Server/Migrations/MigrationRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public sealed class MigrationRunner
typeof(Routines.FixPlaylistOwner),
typeof(Routines.MigrateRatingLevels),
typeof(Routines.AddDefaultCastReceivers),
typeof(Routines.UpdateDefaultPluginRepository)
typeof(Routines.UpdateDefaultPluginRepository),
typeof(Routines.FixAudioData),
};

/// <summary>
Expand Down
104 changes: 104 additions & 0 deletions Jellyfin.Server/Migrations/Routines/FixAudioData.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
3 changes: 3 additions & 0 deletions MediaBrowser.Controller/Entities/InternalItemsQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public InternalItemsQuery()
TrailerTypes = Array.Empty<TrailerType>();
VideoTypes = Array.Empty<VideoType>();
Years = Array.Empty<int>();
SkipDeserialization = false;
}

public InternalItemsQuery(User? user)
Expand Down Expand Up @@ -358,6 +359,8 @@ public BaseItem? Parent

public string? SeriesTimerId { get; set; }

public bool SkipDeserialization { get; set; }

public void SetUser(User user)
{
MaxParentalRating = user.MaxParentalAgeRating;
Expand Down

0 comments on commit 7d983ae

Please sign in to comment.