< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.MediaInfo.ProbeProvider
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs
Line coverage
31%
Covered lines: 28
Uncovered lines: 61
Coverable lines: 89
Total lines: 299
Line coverage: 31.4%
Branch coverage
0%
Covered branches: 0
Total branches: 52
Branch coverage: 0%
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%
get_Name()100%210%
get_Order()100%210%
HasChanged(...)0%1056320%
FetchAsync(...)100%210%
FetchAsync(...)100%210%
FetchAsync(...)100%210%
FetchAsync(...)100%210%
FetchAsync(...)100%210%
FetchAsync(...)100%210%
FetchAsync(...)100%210%
FetchVideoInfo(...)0%156120%
NormalizeStrmLine(...)100%210%
FetchShortcutInfo(...)100%210%
FetchAudioInfo(...)0%7280%

File(s)

/srv/git/jellyfin/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs

#LineLine coverage
 1#nullable disable
 2
 3using System;
 4using System.Collections.Generic;
 5using System.IO;
 6using System.Linq;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Emby.Naming.Common;
 10using MediaBrowser.Controller.Chapters;
 11using MediaBrowser.Controller.Configuration;
 12using MediaBrowser.Controller.Entities;
 13using MediaBrowser.Controller.Entities.Audio;
 14using MediaBrowser.Controller.Entities.Movies;
 15using MediaBrowser.Controller.Entities.TV;
 16using MediaBrowser.Controller.Library;
 17using MediaBrowser.Controller.Lyrics;
 18using MediaBrowser.Controller.MediaEncoding;
 19using MediaBrowser.Controller.Persistence;
 20using MediaBrowser.Controller.Providers;
 21using MediaBrowser.Controller.Subtitles;
 22using MediaBrowser.Model.Entities;
 23using MediaBrowser.Model.Globalization;
 24using MediaBrowser.Model.IO;
 25using MediaBrowser.Model.MediaInfo;
 26using Microsoft.Extensions.Logging;
 27
 28namespace MediaBrowser.Providers.MediaInfo
 29{
 30    /// <summary>
 31    /// The probe provider.
 32    /// </summary>
 33    public class ProbeProvider : ICustomMetadataProvider<Episode>,
 34        ICustomMetadataProvider<MusicVideo>,
 35        ICustomMetadataProvider<Movie>,
 36        ICustomMetadataProvider<Trailer>,
 37        ICustomMetadataProvider<Video>,
 38        ICustomMetadataProvider<Audio>,
 39        ICustomMetadataProvider<AudioBook>,
 40        IHasOrder,
 41        IForcedProvider,
 42        IPreRefreshProvider,
 43        IHasItemChangeMonitor
 44    {
 45        private readonly ILogger<ProbeProvider> _logger;
 46        private readonly AudioResolver _audioResolver;
 47        private readonly SubtitleResolver _subtitleResolver;
 48        private readonly LyricResolver _lyricResolver;
 49        private readonly FFProbeVideoInfo _videoProber;
 50        private readonly AudioFileProber _audioProber;
 2151        private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
 52
 53        /// <summary>
 54        /// Initializes a new instance of the <see cref="ProbeProvider"/> class.
 55        /// </summary>
 56        /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
 57        /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
 58        /// <param name="blurayExaminer">Instance of the <see cref="IBlurayExaminer"/> interface.</param>
 59        /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
 60        /// <param name="chapterManager">Instance of the <see cref="IChapterManager"/> interface.</param>
 61        /// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
 62        /// <param name="subtitleManager">Instance of the <see cref="ISubtitleManager"/> interface.</param>
 63        /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 64        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/>.</param>
 65        /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 66        /// <param name="namingOptions">The <see cref="NamingOptions"/>.</param>
 67        /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param>
 68        /// <param name="mediaAttachmentRepository">Instance of the <see cref="IMediaAttachmentRepository"/> interface.<
 69        /// <param name="mediaStreamRepository">Instance of the <see cref="IMediaStreamRepository"/> interface.</param>
 70        public ProbeProvider(
 71            IMediaSourceManager mediaSourceManager,
 72            IMediaEncoder mediaEncoder,
 73            IBlurayExaminer blurayExaminer,
 74            ILocalizationManager localization,
 75            IChapterManager chapterManager,
 76            IServerConfigurationManager config,
 77            ISubtitleManager subtitleManager,
 78            ILibraryManager libraryManager,
 79            IFileSystem fileSystem,
 80            ILoggerFactory loggerFactory,
 81            NamingOptions namingOptions,
 82            ILyricManager lyricManager,
 83            IMediaAttachmentRepository mediaAttachmentRepository,
 84            IMediaStreamRepository mediaStreamRepository)
 85        {
 2186            _logger = loggerFactory.CreateLogger<ProbeProvider>();
 2187            _audioResolver = new AudioResolver(loggerFactory.CreateLogger<AudioResolver>(), localization, mediaEncoder, 
 2188            _subtitleResolver = new SubtitleResolver(loggerFactory.CreateLogger<SubtitleResolver>(), localization, media
 2189            _lyricResolver = new LyricResolver(loggerFactory.CreateLogger<LyricResolver>(), localization, mediaEncoder, 
 90
 2191            _videoProber = new FFProbeVideoInfo(
 2192                loggerFactory.CreateLogger<FFProbeVideoInfo>(),
 2193                mediaSourceManager,
 2194                mediaEncoder,
 2195                blurayExaminer,
 2196                localization,
 2197                chapterManager,
 2198                config,
 2199                subtitleManager,
 21100                libraryManager,
 21101                _audioResolver,
 21102                _subtitleResolver,
 21103                mediaAttachmentRepository,
 21104                mediaStreamRepository);
 105
 21106            _audioProber = new AudioFileProber(
 21107                loggerFactory.CreateLogger<AudioFileProber>(),
 21108                mediaSourceManager,
 21109                mediaEncoder,
 21110                libraryManager,
 21111                _lyricResolver,
 21112                lyricManager,
 21113                mediaStreamRepository);
 21114        }
 115
 116        /// <inheritdoc />
 0117        public string Name => "Probe Provider";
 118
 119        /// <inheritdoc />
 0120        public int Order => 100;
 121
 122        /// <inheritdoc />
 123        public bool HasChanged(BaseItem item, IDirectoryService directoryService)
 124        {
 0125            var video = item as Video;
 0126            if (video is null || video.VideoType == VideoType.VideoFile || video.VideoType == VideoType.Iso)
 127            {
 0128                var path = item.Path;
 129
 0130                if (!string.IsNullOrWhiteSpace(path) && item.IsFileProtocol)
 131                {
 0132                    var file = directoryService.GetFile(path);
 0133                    if (file is not null && file.LastWriteTimeUtc != item.DateModified && file.Length != item.Size)
 134                    {
 0135                        _logger.LogDebug("Refreshing {ItemPath} due to file system modification.", path);
 0136                        return true;
 137                    }
 138                }
 139            }
 140
 0141            if (video is not null
 0142                && item.SupportsLocalMetadata
 0143                && !video.IsPlaceHolder)
 144            {
 0145                var externalFiles = new HashSet<string>(_subtitleResolver.GetExternalFiles(video, directoryService, fals
 0146                if (!new HashSet<string>(video.SubtitleFiles, StringComparer.Ordinal).SetEquals(externalFiles))
 147                {
 0148                    _logger.LogDebug("Refreshing {ItemPath} due to external subtitles change.", item.Path);
 0149                    return true;
 150                }
 151
 0152                externalFiles = new HashSet<string>(_audioResolver.GetExternalFiles(video, directoryService, false).Sele
 0153                if (!new HashSet<string>(video.AudioFiles, StringComparer.Ordinal).SetEquals(externalFiles))
 154                {
 0155                    _logger.LogDebug("Refreshing {ItemPath} due to external audio change.", item.Path);
 0156                    return true;
 157                }
 158            }
 159
 0160            if (item is Audio audio
 0161                && item.SupportsLocalMetadata)
 162            {
 0163                var externalFiles = new HashSet<string>(_lyricResolver.GetExternalFiles(audio, directoryService, false).
 0164                if (!new HashSet<string>(audio.LyricFiles, StringComparer.Ordinal).SetEquals(externalFiles))
 165                {
 0166                    _logger.LogDebug("Refreshing {ItemPath} due to external lyrics change.", item.Path);
 0167                    return true;
 168                }
 169            }
 170
 0171            return false;
 172        }
 173
 174        /// <inheritdoc />
 175        public Task<ItemUpdateType> FetchAsync(Episode item, MetadataRefreshOptions options, CancellationToken cancellat
 176        {
 0177            return FetchVideoInfo(item, options, cancellationToken);
 178        }
 179
 180        /// <inheritdoc />
 181        public Task<ItemUpdateType> FetchAsync(MusicVideo item, MetadataRefreshOptions options, CancellationToken cancel
 182        {
 0183            return FetchVideoInfo(item, options, cancellationToken);
 184        }
 185
 186        /// <inheritdoc />
 187        public Task<ItemUpdateType> FetchAsync(Movie item, MetadataRefreshOptions options, CancellationToken cancellatio
 188        {
 0189            return FetchVideoInfo(item, options, cancellationToken);
 190        }
 191
 192        /// <inheritdoc />
 193        public Task<ItemUpdateType> FetchAsync(Trailer item, MetadataRefreshOptions options, CancellationToken cancellat
 194        {
 0195            return FetchVideoInfo(item, options, cancellationToken);
 196        }
 197
 198        /// <inheritdoc />
 199        public Task<ItemUpdateType> FetchAsync(Video item, MetadataRefreshOptions options, CancellationToken cancellatio
 200        {
 0201            return FetchVideoInfo(item, options, cancellationToken);
 202        }
 203
 204        /// <inheritdoc />
 205        public Task<ItemUpdateType> FetchAsync(Audio item, MetadataRefreshOptions options, CancellationToken cancellatio
 206        {
 0207            return FetchAudioInfo(item, options, cancellationToken);
 208        }
 209
 210        /// <inheritdoc />
 211        public Task<ItemUpdateType> FetchAsync(AudioBook item, MetadataRefreshOptions options, CancellationToken cancell
 212        {
 0213            return FetchAudioInfo(item, options, cancellationToken);
 214        }
 215
 216        /// <summary>
 217        /// Fetches video information for an item.
 218        /// </summary>
 219        /// <param name="item">The item.</param>
 220        /// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param>
 221        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
 222        /// <typeparam name="T">The type of item to resolve.</typeparam>
 223        /// <returns>A <see cref="Task"/> fetching the <see cref="ItemUpdateType"/> for an item.</returns>
 224        public Task<ItemUpdateType> FetchVideoInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancella
 225            where T : Video
 226        {
 0227            if (item.IsPlaceHolder)
 228            {
 0229                return _cachedTask;
 230            }
 231
 0232            if (!item.IsCompleteMedia)
 233            {
 0234                return _cachedTask;
 235            }
 236
 0237            if (item.IsVirtualItem)
 238            {
 0239                return _cachedTask;
 240            }
 241
 0242            if (!options.EnableRemoteContentProbe && !item.IsFileProtocol)
 243            {
 0244                return _cachedTask;
 245            }
 246
 0247            if (item.IsShortcut)
 248            {
 0249                FetchShortcutInfo(item);
 250            }
 251
 0252            return _videoProber.ProbeVideo(item, options, cancellationToken);
 253        }
 254
 255        private string NormalizeStrmLine(string line)
 256        {
 0257            return line.Replace("\t", string.Empty, StringComparison.Ordinal)
 0258                .Replace("\r", string.Empty, StringComparison.Ordinal)
 0259                .Replace("\n", string.Empty, StringComparison.Ordinal)
 0260                .Trim();
 261        }
 262
 263        private void FetchShortcutInfo(BaseItem item)
 264        {
 0265            item.ShortcutPath = File.ReadAllLines(item.Path)
 0266                .Select(NormalizeStrmLine)
 0267                .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith('#'));
 0268        }
 269
 270        /// <summary>
 271        /// Fetches audio information for an item.
 272        /// </summary>
 273        /// <param name="item">The item.</param>
 274        /// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param>
 275        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
 276        /// <typeparam name="T">The type of item to resolve.</typeparam>
 277        /// <returns>A <see cref="Task"/> fetching the <see cref="ItemUpdateType"/> for an item.</returns>
 278        public Task<ItemUpdateType> FetchAudioInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancella
 279            where T : Audio
 280        {
 0281            if (item.IsVirtualItem)
 282            {
 0283                return _cachedTask;
 284            }
 285
 0286            if (!options.EnableRemoteContentProbe && !item.IsFileProtocol)
 287            {
 0288                return _cachedTask;
 289            }
 290
 0291            if (item.IsShortcut)
 292            {
 0293                FetchShortcutInfo(item);
 294            }
 295
 0296            return _audioProber.Probe(item, options, cancellationToken);
 297        }
 298    }
 299}

Methods/Properties

.ctor(MediaBrowser.Controller.Library.IMediaSourceManager,MediaBrowser.Controller.MediaEncoding.IMediaEncoder,MediaBrowser.Model.MediaInfo.IBlurayExaminer,MediaBrowser.Model.Globalization.ILocalizationManager,MediaBrowser.Controller.Chapters.IChapterManager,MediaBrowser.Controller.Configuration.IServerConfigurationManager,MediaBrowser.Controller.Subtitles.ISubtitleManager,MediaBrowser.Controller.Library.ILibraryManager,MediaBrowser.Model.IO.IFileSystem,Microsoft.Extensions.Logging.ILoggerFactory,Emby.Naming.Common.NamingOptions,MediaBrowser.Controller.Lyrics.ILyricManager,MediaBrowser.Controller.Persistence.IMediaAttachmentRepository,MediaBrowser.Controller.Persistence.IMediaStreamRepository)
get_Name()
get_Order()
HasChanged(MediaBrowser.Controller.Entities.BaseItem,MediaBrowser.Controller.Providers.IDirectoryService)
FetchAsync(MediaBrowser.Controller.Entities.TV.Episode,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchAsync(MediaBrowser.Controller.Entities.MusicVideo,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchAsync(MediaBrowser.Controller.Entities.Movies.Movie,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchAsync(MediaBrowser.Controller.Entities.Trailer,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchAsync(MediaBrowser.Controller.Entities.Video,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchAsync(MediaBrowser.Controller.Entities.Audio.Audio,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchAsync(MediaBrowser.Controller.Entities.AudioBook,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
FetchVideoInfo(T,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)
NormalizeStrmLine(System.String)
FetchShortcutInfo(MediaBrowser.Controller.Entities.BaseItem)
FetchAudioInfo(T,MediaBrowser.Controller.Providers.MetadataRefreshOptions,System.Threading.CancellationToken)