< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.Library.PathManager
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/Library/PathManager.cs
Line coverage
10%
Covered lines: 4
Uncovered lines: 35
Coverable lines: 39
Total lines: 129
Line coverage: 10.2%
Branch coverage
0%
Covered branches: 0
Total branches: 14
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 2/13/2026 - 12:11:21 AM Line coverage: 11.5% (3/26) Branch coverage: 0% (0/2) Total lines: 1015/13/2026 - 12:15:27 AM Line coverage: 10.2% (4/39) Branch coverage: 0% (0/14) Total lines: 129 2/13/2026 - 12:11:21 AM Line coverage: 11.5% (3/26) Branch coverage: 0% (0/2) Total lines: 1015/13/2026 - 12:15:27 AM Line coverage: 10.2% (4/39) Branch coverage: 0% (0/14) Total lines: 129

Coverage delta

Coverage delta 2 -2

Metrics

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/Library/PathManager.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Globalization;
 4using System.IO;
 5using MediaBrowser.Common.Configuration;
 6using MediaBrowser.Controller.Configuration;
 7using MediaBrowser.Controller.Entities;
 8using MediaBrowser.Controller.IO;
 9using Microsoft.Extensions.Logging;
 10
 11namespace Emby.Server.Implementations.Library;
 12
 13/// <summary>
 14/// IPathManager implementation.
 15/// </summary>
 16public class PathManager : IPathManager
 17{
 18    private readonly ILogger<PathManager> _logger;
 19    private readonly IServerConfigurationManager _config;
 20    private readonly IApplicationPaths _appPaths;
 21
 22    /// <summary>
 23    /// Initializes a new instance of the <see cref="PathManager"/> class.
 24    /// </summary>
 25    /// <param name="logger">The logger.</param>
 26    /// <param name="config">The server configuration manager.</param>
 27    /// <param name="appPaths">The application paths.</param>
 28    public PathManager(
 29        ILogger<PathManager> logger,
 30        IServerConfigurationManager config,
 31        IApplicationPaths appPaths)
 32    {
 2133        _logger = logger;
 2134        _config = config;
 2135        _appPaths = appPaths;
 2136    }
 37
 038    private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles");
 39
 040    private string AttachmentCachePath => Path.Combine(_appPaths.DataPath, "attachments");
 41
 42    /// <inheritdoc />
 43    public string? GetAttachmentPath(string mediaSourceId, string fileName)
 44    {
 045        var folder = GetAttachmentFolderPath(mediaSourceId);
 046        return folder is null ? null : Path.Combine(folder, fileName);
 47    }
 48
 49    /// <inheritdoc />
 50    public string? GetAttachmentFolderPath(string mediaSourceId)
 51    {
 052        if (!Guid.TryParse(mediaSourceId, out var parsed))
 53        {
 054            _logger.LogDebug("MediaSource Id '{MediaSourceId}' is not a GUID; no on-disk attachment folder.", mediaSourc
 055            return null;
 56        }
 57
 058        var id = parsed.ToString("D", CultureInfo.InvariantCulture).AsSpan();
 059        return Path.Join(AttachmentCachePath, id[..2], id);
 60    }
 61
 62    /// <inheritdoc />
 63    public string? GetSubtitleFolderPath(string mediaSourceId)
 64    {
 065        if (!Guid.TryParse(mediaSourceId, out var parsed))
 66        {
 067            _logger.LogDebug("MediaSource Id '{MediaSourceId}' is not a GUID; no on-disk subtitle folder.", mediaSourceI
 068            return null;
 69        }
 70
 071        var id = parsed.ToString("D", CultureInfo.InvariantCulture).AsSpan();
 072        return Path.Join(SubtitleCachePath, id[..2], id);
 73    }
 74
 75    /// <inheritdoc />
 76    public string? GetSubtitlePath(string mediaSourceId, int streamIndex, string extension)
 77    {
 078        var folder = GetSubtitleFolderPath(mediaSourceId);
 079        return folder is null ? null : Path.Combine(folder, streamIndex.ToString(CultureInfo.InvariantCulture) + extensi
 80    }
 81
 82    /// <inheritdoc />
 83    public string GetTrickplayDirectory(BaseItem item, bool saveWithMedia = false)
 84    {
 085        var id = item.Id.ToString("D", CultureInfo.InvariantCulture).AsSpan();
 86
 087        return saveWithMedia
 088            ? Path.Combine(item.ContainingFolderPath, Path.ChangeExtension(Path.GetFileName(item.Path), ".trickplay"))
 089            : Path.Join(_config.ApplicationPaths.TrickplayPath, id[..2], id);
 90    }
 91
 92    /// <inheritdoc/>
 93    public string GetChapterImageFolderPath(BaseItem item)
 94    {
 095        return Path.Combine(item.GetInternalMetadataPath(), "chapters");
 96    }
 97
 98    /// <inheritdoc/>
 99    public string GetChapterImagePath(BaseItem item, long chapterPositionTicks)
 100    {
 0101        var filename = item.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + "_" + chapterPositionTicks.ToStr
 102
 0103        return Path.Combine(GetChapterImageFolderPath(item), filename);
 104    }
 105
 106    /// <inheritdoc/>
 107    public IReadOnlyList<string> GetExtractedDataPaths(BaseItem item)
 108    {
 0109        var mediaSourceId = item.Id.ToString("N", CultureInfo.InvariantCulture);
 0110        List<string> paths = [];
 0111        var attachmentFolder = GetAttachmentFolderPath(mediaSourceId);
 0112        if (attachmentFolder is not null)
 113        {
 0114            paths.Add(attachmentFolder);
 115        }
 116
 0117        var subtitleFolder = GetSubtitleFolderPath(mediaSourceId);
 0118        if (subtitleFolder is not null)
 119        {
 0120            paths.Add(subtitleFolder);
 121        }
 122
 0123        paths.Add(GetTrickplayDirectory(item, false));
 0124        paths.Add(GetTrickplayDirectory(item, true));
 0125        paths.Add(GetChapterImageFolderPath(item));
 126
 0127        return paths;
 128    }
 129}