diff --git a/MediaBrowser.Controller/Lyrics/ILyricManager.cs b/MediaBrowser.Controller/Lyrics/ILyricManager.cs index c0f78d177d..dad0250f6b 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricManager.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricManager.cs @@ -1,23 +1,23 @@ -#pragma warning disable CS1591 - using MediaBrowser.Controller.Entities; -namespace MediaBrowser.Controller.Lyrics -{ - public interface ILyricManager - { - /// - /// Gets the lyrics. - /// - /// The media item. - /// Lyrics for passed item. - LyricResponse GetLyrics(BaseItem item); +namespace MediaBrowser.Controller.Lyrics; - /// - /// Checks if requested item has a matching local lyric file. - /// - /// The media item. - /// True if item has a matching lyric file; otherwise false. - bool HasLyricFile(BaseItem item); - } +/// +/// Interface ILyricManager. +/// +public interface ILyricManager +{ + /// + /// Gets the lyrics. + /// + /// The media item. + /// Lyrics for passed item. + LyricResponse GetLyrics(BaseItem item); + + /// + /// Checks if requested item has a matching local lyric file. + /// + /// The media item. + /// True if item has a matching lyric file; otherwise false. + bool HasLyricFile(BaseItem item); } diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs index 5e677ab26f..1b52de255f 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -1,29 +1,28 @@ using System.Collections.Generic; using MediaBrowser.Controller.Entities; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Interface ILyricsProvider. +/// +public interface ILyricProvider { /// - /// Interface ILyricsProvider. + /// Gets a value indicating the provider name. /// - public interface ILyricProvider - { - /// - /// Gets a value indicating the provider name. - /// - string Name { get; } + string Name { get; } - /// - /// Gets the supported media types for this provider. - /// - /// The supported media types. - IEnumerable SupportedMediaTypes { get; } + /// + /// Gets the supported media types for this provider. + /// + /// The supported media types. + IEnumerable SupportedMediaTypes { get; } - /// - /// Gets the lyrics. - /// - /// The media item. - /// If found, returns lyrics for passed item; otherwise, null. - LyricResponse? GetLyrics(BaseItem item); - } + /// + /// Gets the lyrics. + /// + /// The media item. + /// If found, returns lyrics for passed item; otherwise, null. + LyricResponse? GetLyrics(BaseItem item); } diff --git a/MediaBrowser.Controller/Lyrics/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs index 35cdabbb9b..f39fbb0221 100644 --- a/MediaBrowser.Controller/Lyrics/Lyric.cs +++ b/MediaBrowser.Controller/Lyrics/Lyric.cs @@ -1,18 +1,28 @@ -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Lyric model. +/// +public class Lyric { /// - /// Lyric model. + /// Initializes a new instance of the class. /// - public class Lyric + /// The lyric start time in ticks. + /// The lyric text. + public Lyric(string text, long? start = null) { - /// - /// Gets or sets the start time in ticks. - /// - public long? Start { get; set; } - - /// - /// Gets or sets the text. - /// - public string Text { get; set; } = string.Empty; + Start = start; + Text = text; } + + /// + /// Gets the start time in ticks. + /// + public long? Start { get; } + + /// + /// Gets the text. + /// + public string Text { get; } } diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index ae831b4d23..61e205b6cc 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -1,34 +1,29 @@ using System.IO; -using System.Linq; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Lyric helper methods. +/// +public static class LyricInfo { /// - /// Lyric helper methods. + /// Gets matching lyric file for a requested item. /// - public static class LyricInfo + /// The lyricProvider interface to use. + /// Path of requested item. + /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. + public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) { - /// - /// Gets matching lyric file for a requested item. - /// - /// The lyricProvider interface to use. - /// Path of requested item. - /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. - public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) + foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) { - if (lyricProvider.SupportedMediaTypes.Any()) + var lyricFilePath = Path.ChangeExtension(itemPath, lyricFileExtension); + if (File.Exists(lyricFilePath)) { - foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) - { - string lyricFilePath = @Path.ChangeExtension(itemPath, lyricFileExtension); - if (System.IO.File.Exists(lyricFilePath)) - { - return lyricFilePath; - } - } + return lyricFilePath; } - - return null; } + + return null; } } diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 796ca3bc36..e18cb1101e 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -1,22 +1,19 @@ -#nullable disable - using System.Collections.Generic; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// LyricResponse model. +/// +public class LyricResponse { /// - /// LyricResponse model. + /// Gets or sets Metadata. /// - public class LyricResponse - { - /// - /// Gets or sets Metadata. - /// - public IDictionary Metadata { get; set; } + public IDictionary? Metadata { get; set; } - /// - /// Gets or sets Lyrics. - /// - public IEnumerable Lyrics { get; set; } - } + /// + /// Gets or sets Lyrics. + /// + public IEnumerable? Lyrics { get; set; } } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 59a172cee2..9bacfc2964 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -1,112 +1,102 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Dynamic; using System.Globalization; using System.Linq; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -using Swashbuckle.AspNetCore.SwaggerGen; -namespace MediaBrowser.Providers.Lyric +namespace MediaBrowser.Providers.Lyric; + +/// +/// LRC Lyric Provider. +/// +public class LrcLyricProvider : ILyricProvider { - /// - /// LRC Lyric Provider. - /// - public class LrcLyricProvider : ILyricProvider - { - /// - /// Initializes a new instance of the class. - /// - public LrcLyricProvider() - { - Name = "LrcLyricProvider"; + /// + public string Name { get; } = "LrcLyricProvider"; - SupportedMediaTypes = new Collection + /// + public IEnumerable SupportedMediaTypes + { + get => new Collection { "lrc" }; - } + } - /// - /// Gets a value indicating the provider name. - /// - public string Name { get; } + /// + /// Opens lyric file for the requested item, and processes it for API return. + /// + /// The item to to process. + /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - /// - /// Gets a value indicating the File Extenstions this provider supports. - /// - public IEnumerable SupportedMediaTypes { get; } - - /// - /// Opens lyric file for the requested item, and processes it for API return. - /// - /// The item to to process. - /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. - public LyricResponse? GetLyrics(BaseItem item) + if (string.IsNullOrEmpty(lyricFilePath)) { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return null; - } - - List lyricList = new List(); - List sortedLyricData = new List(); - - IDictionary metaData = new Dictionary(); - string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); - - try - { - // Parse and sort lyric rows - LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); - Song lyricData = lrcLyricParser.Decode(lrcFileContent); - sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.ToArray()[0].Value).ToList(); - - // Parse metadata rows - var metaDataRows = lyricData.Lyrics - .Where(x => x.TimeTags.Count == 0) - .Where(x => x.Text.StartsWith("[", StringComparison.Ordinal) && x.Text.EndsWith("]", StringComparison.Ordinal)) - .Select(x => x.Text) - .ToList(); - - foreach (string metaDataRow in metaDataRows) - { - var metaDataField = metaDataRow.Split(":"); - - string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal).Trim(); - string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal).Trim(); - - metaData.Add(metaDataFieldName, metaDataFieldValue); - } - } - catch - { - return null; - } - - if (!sortedLyricData.Any()) - { - return null; - } - - for (int i = 0; i < sortedLyricData.Count; i++) - { - var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; - long ticks = Convert.ToInt64(timeData, new NumberFormatInfo()) * 10000; - lyricList.Add(new Controller.Lyrics.Lyric { Start = ticks, Text = sortedLyricData[i].Text }); - } - - if (metaData.Any()) - { - return new LyricResponse { Metadata = metaData, Lyrics = lyricList }; - } - - return new LyricResponse { Lyrics = lyricList }; + return null; } + + List lyricList = new List(); + List sortedLyricData = new List(); + + IDictionary metaData = new Dictionary(); + string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); + + try + { + // Parse and sort lyric rows + LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); + Song lyricData = lrcLyricParser.Decode(lrcFileContent); + sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.First().Value).ToList(); + + // Parse metadata rows + var metaDataRows = lyricData.Lyrics + .Where(x => x.TimeTags.Count == 0) + .Where(x => x.Text.StartsWith('[') && x.Text.EndsWith(']')) + .Select(x => x.Text) + .ToList(); + + foreach (string metaDataRow in metaDataRows) + { + var metaDataField = metaDataRow.Split(':'); + if (metaDataField.Length != 2) + { + continue; + } + + string metaDataFieldName = metaDataField[0][1..].Trim(); + string metaDataFieldValue = metaDataField[1][..^1].Trim(); + + metaData.Add(metaDataFieldName, metaDataFieldValue); + } + } + catch + { + return null; + } + + if (sortedLyricData.Count == 0) + { + return null; + } + + for (int i = 0; i < sortedLyricData.Count; i++) + { + var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; + long ticks = TimeSpan.FromMilliseconds((double)timeData).Ticks; + lyricList.Add(new Controller.Lyrics.Lyric(sortedLyricData[i].Text, ticks)); + } + + if (metaData.Any()) + { + return new LyricResponse { Metadata = metaData, Lyrics = lyricList }; + } + + return new LyricResponse { Lyrics = lyricList }; } } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index f5560b0542..06f913d079 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -1,55 +1,57 @@ -#nullable disable - -#pragma warning disable CS1591 - using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -namespace MediaBrowser.Providers.Lyric +namespace MediaBrowser.Providers.Lyric; + +/// +/// Lyric Manager. +/// +public class LyricManager : ILyricManager { - public class LyricManager : ILyricManager + private readonly ILyricProvider[] _lyricProviders; + + /// + /// Initializes a new instance of the class. + /// + /// All found lyricProviders. + public LyricManager(IEnumerable lyricProviders) { - private readonly ILyricProvider[] _lyricProviders; + _lyricProviders = lyricProviders.ToArray(); + } - public LyricManager(IEnumerable lyricProviders) + /// + public LyricResponse GetLyrics(BaseItem item) + { + foreach (ILyricProvider provider in _lyricProviders) { - _lyricProviders = lyricProviders.ToArray(); + var results = provider.GetLyrics(item); + if (results is not null) + { + return results; + } } - /// - public LyricResponse GetLyrics(BaseItem item) + return null; + } + + /// + public bool HasLyricFile(BaseItem item) + { + foreach (ILyricProvider provider in _lyricProviders) { - foreach (ILyricProvider provider in _lyricProviders) + if (item is null) { - var results = provider.GetLyrics(item); - if (results is not null) - { - return results; - } + continue; } - return null; - } - - /// - public bool HasLyricFile(BaseItem item) - { - foreach (ILyricProvider provider in _lyricProviders) + if (LyricInfo.GetLyricFilePath(provider, item.Path) is not null) { - if (item is null) - { - continue; - } - - if (LyricInfo.GetLyricFilePath(provider, item.Path) is not null) - { - return true; - } + return true; } - - return false; } + + return false; } } diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index 8a51d7277c..d417c85981 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -5,69 +5,53 @@ using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -namespace MediaBrowser.Providers.Lyric -{ - /// - /// TXT Lyric Provider. - /// - public class TxtLyricProvider : ILyricProvider - { - /// - /// Initializes a new instance of the class. - /// - public TxtLyricProvider() - { - Name = "TxtLyricProvider"; +namespace MediaBrowser.Providers.Lyric; - SupportedMediaTypes = new Collection +/// +/// TXT Lyric Provider. +/// +public class TxtLyricProvider : ILyricProvider +{ + /// + public string Name { get; } = "TxtLyricProvider"; + + /// + public IEnumerable SupportedMediaTypes + { + get => new Collection { "lrc", "txt" }; - } + } - /// - /// Gets a value indicating the provider name. - /// - public string Name { get; } + /// + /// Opens lyric file for the requested item, and processes it for API return. + /// + /// The item to to process. + /// If provider can determine lyrics, returns a ; otherwise, null. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - /// - /// Gets a value indicating the File Extenstions this provider supports. - /// - public IEnumerable SupportedMediaTypes { get; } - - /// - /// Opens lyric file for the requested item, and processes it for API return. - /// - /// The item to to process. - /// If provider can determine lyrics, returns a ; otherwise, null. - public LyricResponse? GetLyrics(BaseItem item) + if (string.IsNullOrEmpty(lyricFilePath)) { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return null; - } - - List lyricList = new List(); - - string lyricData = System.IO.File.ReadAllText(lyricFilePath); - - // Splitting on Environment.NewLine caused some new lines to be missed in Windows. - char[] newLineDelims = new[] { '\r', '\n' }; - string[] lyricTextLines = lyricData.Split(newLineDelims, StringSplitOptions.RemoveEmptyEntries); - - if (!lyricTextLines.Any()) - { - return null; - } - - foreach (string lyricTextLine in lyricTextLines) - { - lyricList.Add(new Controller.Lyrics.Lyric { Text = lyricTextLine }); - } - - return new LyricResponse { Lyrics = lyricList }; + return null; } + + string[] lyricTextLines = System.IO.File.ReadAllLines(lyricFilePath); + + List lyricList = new List(); + + if (lyricTextLines.Length == 0) + { + return null; + } + + foreach (string lyricTextLine in lyricTextLines) + { + lyricList.Add(new Controller.Lyrics.Lyric(lyricTextLine)); + } + + return new LyricResponse { Lyrics = lyricList }; } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 8514489f8a..e12776ba05 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -6,7 +6,6 @@ -