< Summary - Jellyfin

Information
Class: Jellyfin.Server.Migrations.Routines.MoveTrickplayFiles
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/MoveTrickplayFiles.cs
Line coverage
48%
Covered lines: 24
Uncovered lines: 26
Coverable lines: 50
Total lines: 129
Line coverage: 48%
Branch coverage
31%
Covered branches: 5
Total branches: 16
Branch coverage: 31.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Perform()41.66%231257.57%
GetOldTrickplayDirectory(...)0%620%
GetNewOldTrickplayDirectory(...)0%620%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/MoveTrickplayFiles.cs

#LineLine coverage
 1using System;
 2using System.Diagnostics;
 3using System.Globalization;
 4using System.IO;
 5using System.Linq;
 6using Jellyfin.Data.Enums;
 7using Jellyfin.Server.ServerSetupApp;
 8using MediaBrowser.Controller.Entities;
 9using MediaBrowser.Controller.Library;
 10using MediaBrowser.Controller.Trickplay;
 11using MediaBrowser.Model.IO;
 12using Microsoft.Extensions.Logging;
 13
 14namespace Jellyfin.Server.Migrations.Routines;
 15
 16/// <summary>
 17/// Migration to move trickplay files to the new directory.
 18/// </summary>
 19#pragma warning disable CS0618 // Type or member is obsolete
 20[JellyfinMigration("2025-04-20T23:00:00", nameof(MoveTrickplayFiles), RunMigrationOnSetup = true)]
 21public class MoveTrickplayFiles : IMigrationRoutine
 22#pragma warning restore CS0618 // Type or member is obsolete
 23{
 24    private readonly ITrickplayManager _trickplayManager;
 25    private readonly IFileSystem _fileSystem;
 26    private readonly ILibraryManager _libraryManager;
 27    private readonly IStartupLogger _logger;
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="MoveTrickplayFiles"/> class.
 31    /// </summary>
 32    /// <param name="trickplayManager">Instance of the <see cref="ITrickplayManager"/> interface.</param>
 33    /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 34    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 35    /// <param name="logger">The logger.</param>
 36    public MoveTrickplayFiles(
 37        ITrickplayManager trickplayManager,
 38        IFileSystem fileSystem,
 39        ILibraryManager libraryManager,
 40        IStartupLogger logger)
 41    {
 2142        _trickplayManager = trickplayManager;
 2143        _fileSystem = fileSystem;
 2144        _libraryManager = libraryManager;
 2145        _logger = logger;
 2146    }
 47
 48    /// <inheritdoc />
 49    public void Perform()
 50    {
 51        const int Limit = 5000;
 4252        int itemCount = 0, offset = 0, previousCount;
 53
 2154        var sw = Stopwatch.StartNew();
 2155        var trickplayQuery = new InternalItemsQuery
 2156        {
 2157            MediaTypes = [MediaType.Video],
 2158            SourceTypes = [SourceType.Library],
 2159            IsVirtualItem = false,
 2160            IsFolder = false
 2161        };
 62
 63        do
 64        {
 2165            var trickplayInfos = _trickplayManager.GetTrickplayItemsAsync(Limit, offset).GetAwaiter().GetResult();
 2166            trickplayQuery.ItemIds = trickplayInfos.Select(i => i.ItemId).Distinct().ToArray();
 2167            var items = _libraryManager.GetItemList(trickplayQuery);
 4268            foreach (var trickplayInfo in trickplayInfos)
 69            {
 070                var item = items.OfType<Video>().FirstOrDefault(i => i.Id.Equals(trickplayInfo.ItemId));
 071                if (item is null)
 72                {
 73                    continue;
 74                }
 75
 076                var moved = false;
 077                var oldPath = GetOldTrickplayDirectory(item, trickplayInfo.Width);
 078                var newPath = _trickplayManager.GetTrickplayDirectory(item, trickplayInfo.TileWidth, trickplayInfo.TileH
 079                if (_fileSystem.DirectoryExists(oldPath))
 80                {
 081                    _fileSystem.MoveDirectory(oldPath, newPath);
 082                    moved = true;
 83                }
 84
 085                oldPath = GetNewOldTrickplayDirectory(item, trickplayInfo.TileWidth, trickplayInfo.TileHeight, trickplay
 086                if (_fileSystem.DirectoryExists(oldPath))
 87                {
 088                    _fileSystem.MoveDirectory(oldPath, newPath);
 089                    moved = true;
 90                }
 91
 092                if (moved)
 93                {
 094                    itemCount++;
 95                }
 96            }
 97
 2198            offset += Limit;
 2199            previousCount = trickplayInfos.Count;
 100
 21101            _logger.LogInformation("Checked: {Checked} - Moved: {Count} - Time: {Time}", offset, itemCount, sw.Elapsed);
 21102        } while (previousCount == Limit);
 103
 21104        _logger.LogInformation("Moved {Count} items in {Time}", itemCount, sw.Elapsed);
 21105    }
 106
 107    private string GetOldTrickplayDirectory(BaseItem item, int? width = null)
 108    {
 0109        var path = Path.Combine(item.GetInternalMetadataPath(), "trickplay");
 110
 0111        return width.HasValue ? Path.Combine(path, width.Value.ToString(CultureInfo.InvariantCulture)) : path;
 112    }
 113
 114    private string GetNewOldTrickplayDirectory(BaseItem item, int tileWidth, int tileHeight, int width, bool saveWithMed
 115    {
 0116        var path = saveWithMedia
 0117            ? Path.Combine(item.ContainingFolderPath, Path.ChangeExtension(item.Path, ".trickplay"))
 0118            : Path.Combine(item.GetInternalMetadataPath(), "trickplay");
 119
 0120        var subdirectory = string.Format(
 0121            CultureInfo.InvariantCulture,
 0122            "{0} - {1}x{2}",
 0123            width.ToString(CultureInfo.InvariantCulture),
 0124            tileWidth.ToString(CultureInfo.InvariantCulture),
 0125            tileHeight.ToString(CultureInfo.InvariantCulture));
 126
 0127        return Path.Combine(path, subdirectory);
 128    }
 129}