< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.Lyric.LrcLyricParser
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/Lyric/LrcLyricParser.cs
Line coverage
85%
Covered lines: 35
Uncovered lines: 6
Coverable lines: 41
Total lines: 112
Line coverage: 85.3%
Branch coverage
83%
Covered branches: 10
Total branches: 12
Branch coverage: 83.3%
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
.cctor()100%11100%
.ctor()100%11100%
get_Name()100%210%
get_Priority()100%11100%
ParseLyrics(...)83.33%121286.11%

File(s)

/srv/git/jellyfin/MediaBrowser.Providers/Lyric/LrcLyricParser.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using System.Text.RegularExpressions;
 6using Jellyfin.Extensions;
 7using LrcParser.Model;
 8using LrcParser.Parser;
 9using MediaBrowser.Controller.Lyrics;
 10using MediaBrowser.Controller.Resolvers;
 11using MediaBrowser.Model.Lyrics;
 12
 13namespace MediaBrowser.Providers.Lyric;
 14
 15/// <summary>
 16/// LRC Lyric Parser.
 17/// </summary>
 18public partial class LrcLyricParser : ILyricParser
 19{
 20    private readonly LyricParser _lrcLyricParser;
 21
 122    private static readonly string[] _supportedMediaTypes = [".lrc", ".elrc"];
 23
 24    /// <summary>
 25    /// Initializes a new instance of the <see cref="LrcLyricParser"/> class.
 26    /// </summary>
 27    public LrcLyricParser()
 28    {
 2229        _lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser();
 2230    }
 31
 32    /// <inheritdoc />
 033    public string Name => "LrcLyricProvider";
 34
 35    /// <summary>
 36    /// Gets the priority.
 37    /// </summary>
 38    /// <value>The priority.</value>
 2139    public ResolverPriority Priority => ResolverPriority.Fourth;
 40
 41    /// <inheritdoc />
 42    public LyricDto? ParseLyrics(LyricFile lyrics)
 43    {
 144        if (!_supportedMediaTypes.Contains(Path.GetExtension(lyrics.Name.AsSpan()), StringComparison.OrdinalIgnoreCase))
 45        {
 046            return null;
 47        }
 48
 49        Song lyricData;
 50
 51        try
 52        {
 153            lyricData = _lrcLyricParser.Decode(lyrics.Content);
 154        }
 055        catch (Exception)
 56        {
 57            // Failed to parse, return null so the next parser will be tried
 058            return null;
 59        }
 60
 161        List<LrcParser.Model.Lyric> sortedLyricData = lyricData.Lyrics.OrderBy(x => x.StartTime).ToList();
 62
 163        if (sortedLyricData.Count == 0)
 64        {
 065            return null;
 66        }
 67
 168        List<LyricLine> lyricList = [];
 6469        for (var l = 0; l < sortedLyricData.Count; l++)
 70        {
 3171            var cues = new List<LyricLineCue>();
 3172            var lyric = sortedLyricData[l];
 73
 3174            if (lyric.TimeTags.Count != 0)
 75            {
 3176                var keys = lyric.TimeTags.Keys.ToList();
 6277                int current = 0, next = 1;
 34178                while (next < keys.Count)
 79                {
 31080                    var currentKey = keys[current];
 31081                    var currentMs = lyric.TimeTags[currentKey] ?? 0;
 31082                    var nextMs = lyric.TimeTags[keys[next]] ?? 0;
 83
 31084                    cues.Add(new LyricLineCue(
 31085                        position: Math.Max(currentKey.Index, 0),
 31086                        start: TimeSpan.FromMilliseconds(currentMs).Ticks,
 31087                        end: TimeSpan.FromMilliseconds(nextMs).Ticks));
 88
 31089                    current++;
 31090                    next++;
 91                }
 92
 3193                var lastKey = keys[current];
 3194                var lastMs = lyric.TimeTags[lastKey] ?? 0;
 95
 3196                cues.Add(new LyricLineCue(
 3197                    position: Math.Max(lastKey.Index, 0),
 3198                    start: TimeSpan.FromMilliseconds(lastMs).Ticks,
 3199                    end: l + 1 < sortedLyricData.Count ? TimeSpan.FromMilliseconds(sortedLyricData[l + 1].StartTime).Tic
 100            }
 101
 31102            long lyricStartTicks = TimeSpan.FromMilliseconds(lyric.StartTime).Ticks;
 31103            lyricList.Add(new LyricLine(WhitespaceRegex().Replace(lyric.Text.Trim(), " "), lyricStartTicks, cues));
 104        }
 105
 1106        return new LyricDto { Lyrics = lyricList };
 0107    }
 108
 109    // Replacement is required until https://github.com/karaoke-dev/LrcParser/issues/83 is resolved.
 110    [GeneratedRegex(@"\s+")]
 111    private static partial Regex WhitespaceRegex();
 112}