< 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: 128
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 MediaBrowser.Controller.Entities;
 8using MediaBrowser.Controller.Library;
 9using MediaBrowser.Controller.Trickplay;
 10using MediaBrowser.Model.IO;
 11using Microsoft.Extensions.Logging;
 12
 13namespace Jellyfin.Server.Migrations.Routines;
 14
 15/// <summary>
 16/// Migration to move trickplay files to the new directory.
 17/// </summary>
 18#pragma warning disable CS0618 // Type or member is obsolete
 19[JellyfinMigration("2025-04-20T23:00:00", nameof(MoveTrickplayFiles), RunMigrationOnSetup = true)]
 20public class MoveTrickplayFiles : IMigrationRoutine
 21#pragma warning restore CS0618 // Type or member is obsolete
 22{
 23    private readonly ITrickplayManager _trickplayManager;
 24    private readonly IFileSystem _fileSystem;
 25    private readonly ILibraryManager _libraryManager;
 26    private readonly ILogger<MoveTrickplayFiles> _logger;
 27
 28    /// <summary>
 29    /// Initializes a new instance of the <see cref="MoveTrickplayFiles"/> class.
 30    /// </summary>
 31    /// <param name="trickplayManager">Instance of the <see cref="ITrickplayManager"/> interface.</param>
 32    /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 33    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 34    /// <param name="logger">The logger.</param>
 35    public MoveTrickplayFiles(
 36        ITrickplayManager trickplayManager,
 37        IFileSystem fileSystem,
 38        ILibraryManager libraryManager,
 39        ILogger<MoveTrickplayFiles> logger)
 40    {
 2141        _trickplayManager = trickplayManager;
 2142        _fileSystem = fileSystem;
 2143        _libraryManager = libraryManager;
 2144        _logger = logger;
 2145    }
 46
 47    /// <inheritdoc />
 48    public void Perform()
 49    {
 50        const int Limit = 5000;
 4251        int itemCount = 0, offset = 0, previousCount;
 52
 2153        var sw = Stopwatch.StartNew();
 2154        var trickplayQuery = new InternalItemsQuery
 2155        {
 2156            MediaTypes = [MediaType.Video],
 2157            SourceTypes = [SourceType.Library],
 2158            IsVirtualItem = false,
 2159            IsFolder = false
 2160        };
 61
 62        do
 63        {
 2164            var trickplayInfos = _trickplayManager.GetTrickplayItemsAsync(Limit, offset).GetAwaiter().GetResult();
 2165            trickplayQuery.ItemIds = trickplayInfos.Select(i => i.ItemId).Distinct().ToArray();
 2166            var items = _libraryManager.GetItemList(trickplayQuery);
 4267            foreach (var trickplayInfo in trickplayInfos)
 68            {
 069                var item = items.OfType<Video>().FirstOrDefault(i => i.Id.Equals(trickplayInfo.ItemId));
 070                if (item is null)
 71                {
 72                    continue;
 73                }
 74
 075                var moved = false;
 076                var oldPath = GetOldTrickplayDirectory(item, trickplayInfo.Width);
 077                var newPath = _trickplayManager.GetTrickplayDirectory(item, trickplayInfo.TileWidth, trickplayInfo.TileH
 078                if (_fileSystem.DirectoryExists(oldPath))
 79                {
 080                    _fileSystem.MoveDirectory(oldPath, newPath);
 081                    moved = true;
 82                }
 83
 084                oldPath = GetNewOldTrickplayDirectory(item, trickplayInfo.TileWidth, trickplayInfo.TileHeight, trickplay
 085                if (_fileSystem.DirectoryExists(oldPath))
 86                {
 087                    _fileSystem.MoveDirectory(oldPath, newPath);
 088                    moved = true;
 89                }
 90
 091                if (moved)
 92                {
 093                    itemCount++;
 94                }
 95            }
 96
 2197            offset += Limit;
 2198            previousCount = trickplayInfos.Count;
 99
 21100            _logger.LogInformation("Checked: {Checked} - Moved: {Count} - Time: {Time}", offset, itemCount, sw.Elapsed);
 21101        } while (previousCount == Limit);
 102
 21103        _logger.LogInformation("Moved {Count} items in {Time}", itemCount, sw.Elapsed);
 21104    }
 105
 106    private string GetOldTrickplayDirectory(BaseItem item, int? width = null)
 107    {
 0108        var path = Path.Combine(item.GetInternalMetadataPath(), "trickplay");
 109
 0110        return width.HasValue ? Path.Combine(path, width.Value.ToString(CultureInfo.InvariantCulture)) : path;
 111    }
 112
 113    private string GetNewOldTrickplayDirectory(BaseItem item, int tileWidth, int tileHeight, int width, bool saveWithMed
 114    {
 0115        var path = saveWithMedia
 0116            ? Path.Combine(item.ContainingFolderPath, Path.ChangeExtension(item.Path, ".trickplay"))
 0117            : Path.Combine(item.GetInternalMetadataPath(), "trickplay");
 118
 0119        var subdirectory = string.Format(
 0120            CultureInfo.InvariantCulture,
 0121            "{0} - {1}x{2}",
 0122            width.ToString(CultureInfo.InvariantCulture),
 0123            tileWidth.ToString(CultureInfo.InvariantCulture),
 0124            tileHeight.ToString(CultureInfo.InvariantCulture));
 125
 0126        return Path.Combine(path, subdirectory);
 127    }
 128}