< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.MediaInfo.AudioImageProvider
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
Line coverage
25%
Covered lines: 8
Uncovered lines: 23
Coverable lines: 31
Total lines: 157
Line coverage: 25.8%
Branch coverage
14%
Covered branches: 2
Total branches: 14
Branch coverage: 14.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%
get_AudioImagesPath()100%210%
get_Name()100%210%
GetSupportedImages(...)100%210%
GetImage(...)0%620%
GetAudioImagePath(...)0%7280%
Supports(...)50%5.02460%

File(s)

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

#LineLine coverage
 1#nullable disable
 2
 3using System;
 4using System.Collections.Generic;
 5using System.Globalization;
 6using System.IO;
 7using System.Linq;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using MediaBrowser.Common.Extensions;
 11using MediaBrowser.Controller.Configuration;
 12using MediaBrowser.Controller.Entities;
 13using MediaBrowser.Controller.Entities.Audio;
 14using MediaBrowser.Controller.Library;
 15using MediaBrowser.Controller.MediaEncoding;
 16using MediaBrowser.Controller.Persistence;
 17using MediaBrowser.Controller.Providers;
 18using MediaBrowser.Model.Entities;
 19using MediaBrowser.Model.IO;
 20
 21namespace MediaBrowser.Providers.MediaInfo
 22{
 23    /// <summary>
 24    /// Uses <see cref="IMediaEncoder"/> to extract embedded images.
 25    /// </summary>
 26    public class AudioImageProvider : IDynamicImageProvider
 27    {
 28        private readonly IMediaSourceManager _mediaSourceManager;
 29        private readonly IMediaEncoder _mediaEncoder;
 30        private readonly IServerConfigurationManager _config;
 31        private readonly IFileSystem _fileSystem;
 32
 33        /// <summary>
 34        /// Initializes a new instance of the <see cref="AudioImageProvider"/> class.
 35        /// </summary>
 36        /// <param name="mediaSourceManager">The media source manager for fetching item streams.</param>
 37        /// <param name="mediaEncoder">The media encoder for extracting embedded images.</param>
 38        /// <param name="config">The server configuration manager for getting image paths.</param>
 39        /// <param name="fileSystem">The filesystem.</param>
 40        public AudioImageProvider(IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IServerConfigurati
 41        {
 2242            _mediaSourceManager = mediaSourceManager;
 2243            _mediaEncoder = mediaEncoder;
 2244            _config = config;
 2245            _fileSystem = fileSystem;
 2246        }
 47
 048        private string AudioImagesPath => Path.Combine(_config.ApplicationPaths.CachePath, "extracted-audio-images");
 49
 50        /// <inheritdoc />
 051        public string Name => "Image Extractor";
 52
 53        /// <inheritdoc />
 54        public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
 55        {
 056            return new[] { ImageType.Primary };
 57        }
 58
 59        /// <inheritdoc />
 60        public Task<DynamicImageResponse> GetImage(BaseItem item, ImageType type, CancellationToken cancellationToken)
 61        {
 062            var imageStreams = _mediaSourceManager.GetMediaStreams(new MediaStreamQuery
 063            {
 064                ItemId = item.Id,
 065                Type = MediaStreamType.EmbeddedImage
 066            });
 67
 68            // Can't extract if we didn't find a video stream in the file
 069            if (imageStreams.Count == 0)
 70            {
 071                return Task.FromResult(new DynamicImageResponse { HasImage = false });
 72            }
 73
 074            return GetImage((Audio)item, imageStreams, cancellationToken);
 75        }
 76
 77        private async Task<DynamicImageResponse> GetImage(Audio item, List<MediaStream> imageStreams, CancellationToken 
 78        {
 79            var path = GetAudioImagePath(item);
 80
 81            if (!File.Exists(path))
 82            {
 83                Directory.CreateDirectory(Path.GetDirectoryName(path));
 84
 85                var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).Contains("front", StringC
 86                    imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).Contains("cover", StringComparison.Ordi
 87                    imageStreams.FirstOrDefault();
 88
 89                var imageStreamIndex = imageStream?.Index;
 90
 91                var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).Con
 92
 93                File.Copy(tempFile, path, true);
 94
 95                try
 96                {
 97                    _fileSystem.DeleteFile(tempFile);
 98                }
 99                catch
 100                {
 101                }
 102            }
 103
 104            return new DynamicImageResponse
 105            {
 106                HasImage = true,
 107                Path = path
 108            };
 109        }
 110
 111        private string GetAudioImagePath(Audio item)
 112        {
 113            string filename;
 114
 0115            if (item.GetType() == typeof(Audio))
 116            {
 0117                if (item.AlbumArtists.Count > 0
 0118                    && !string.IsNullOrWhiteSpace(item.Album)
 0119                    && !string.IsNullOrWhiteSpace(item.AlbumArtists[0]))
 120                {
 0121                    filename = (item.Album + "-" + item.AlbumArtists[0]).GetMD5().ToString("N", CultureInfo.InvariantCul
 122                }
 123                else
 124                {
 0125                    filename = item.Id.ToString("N", CultureInfo.InvariantCulture);
 126                }
 127
 0128                filename += ".jpg";
 129            }
 130            else
 131            {
 132                // If it's an audio book or audio podcast, allow unique image per item
 0133                filename = item.Id.ToString("N", CultureInfo.InvariantCulture) + ".jpg";
 134            }
 135
 0136            var prefix = filename.AsSpan().Slice(0, 1);
 137
 0138            return Path.Join(AudioImagesPath, prefix, filename);
 139        }
 140
 141        /// <inheritdoc />
 142        public bool Supports(BaseItem item)
 143        {
 46144            if (item.IsShortcut)
 145            {
 0146                return false;
 147            }
 148
 46149            if (!item.IsFileProtocol)
 150            {
 0151                return false;
 152            }
 153
 46154            return item is Audio;
 155        }
 156    }
 157}