diff options
| author | 1hitsong <3330318+1hitsong@users.noreply.github.com> | 2022-09-15 19:45:26 -0400 |
|---|---|---|
| committer | 1hitsong <3330318+1hitsong@users.noreply.github.com> | 2022-09-15 19:45:26 -0400 |
| commit | d9be3874ba3842d5888c5cbbe583614ed990849e (patch) | |
| tree | f9a5264a402548f531e83891a70dd0a2bd7fc35d | |
| parent | 7520a1998569f0ba58008016c10de21d66b6b836 (diff) | |
Auto stash before merge of "lyric-lrc-file-support" and "origin/lyric-lrc-file-support"
| -rw-r--r-- | Emby.Server.Implementations/ApplicationHost.cs | 2 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Dto/DtoService.cs | 9 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/UserLibraryController.cs | 5 | ||||
| -rw-r--r-- | Jellyfin.Api/Helpers/ItemHelper.cs | 106 | ||||
| -rw-r--r-- | Jellyfin.Api/Jellyfin.Api.csproj | 1 | ||||
| -rw-r--r-- | Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs | 34 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Lyrics/ILyricsProvider.cs | 24 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Lyrics/Lyric.cs (renamed from Jellyfin.Api/Models/UserDtos/Lyric.cs) | 2 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Lyrics/LyricInfo.cs | 87 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Lyrics/LyricResponse.cs | 15 | ||||
| -rw-r--r-- | MediaBrowser.Model/Dto/BaseItemDto.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs (renamed from Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs) | 39 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs (renamed from Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs) | 35 | ||||
| -rw-r--r-- | MediaBrowser.Providers/MediaBrowser.Providers.csproj | 2 |
14 files changed, 173 insertions, 190 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3e9c540e7..5487e5e02 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -68,6 +68,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Notifications; @@ -95,6 +96,7 @@ using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; using MediaBrowser.Providers.Chapters; +using MediaBrowser.Providers.Lyric; using MediaBrowser.Providers.Manager; using MediaBrowser.Providers.Plugins.Tmdb; using MediaBrowser.Providers.Subtitles; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 96717cff5..bed82a4bb 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -19,6 +19,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; @@ -51,6 +52,8 @@ namespace Emby.Server.Implementations.Dto private readonly IMediaSourceManager _mediaSourceManager; private readonly Lazy<ILiveTvManager> _livetvManagerFactory; + private readonly IEnumerable<ILyricsProvider> _lyricProviders; + public DtoService( ILogger<DtoService> logger, ILibraryManager libraryManager, @@ -60,7 +63,8 @@ namespace Emby.Server.Implementations.Dto IProviderManager providerManager, IApplicationHost appHost, IMediaSourceManager mediaSourceManager, - Lazy<ILiveTvManager> livetvManagerFactory) + Lazy<ILiveTvManager> livetvManagerFactory, + IEnumerable<ILyricsProvider> lyricProviders) { _logger = logger; _libraryManager = libraryManager; @@ -71,6 +75,7 @@ namespace Emby.Server.Implementations.Dto _appHost = appHost; _mediaSourceManager = mediaSourceManager; _livetvManagerFactory = livetvManagerFactory; + _lyricProviders = lyricProviders; } private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; @@ -142,7 +147,7 @@ namespace Emby.Server.Implementations.Dto } else if (item is Audio) { - dto.HasLocalLyricsFile = ItemHelper.HasLyricFile(item.Path); + dto.HasLyrics = MediaBrowser.Controller.Lyrics.LyricInfo.HasLyricFile(_lyricProviders, item.Path); } if (item is IItemByName itemByName diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 123c5e079..3da78c116 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -13,6 +13,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -414,8 +415,8 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - // Super nieve implementation. I would suggest building a lyric service of some sort and doing this there. - foreach (var provider in _lyricProviders) + var result = MediaBrowser.Controller.Lyrics.LyricInfo.GetLyricData(_lyricProviders, item); + if (result is not null) { provider.Process(item); if (provider.HasData) diff --git a/Jellyfin.Api/Helpers/ItemHelper.cs b/Jellyfin.Api/Helpers/ItemHelper.cs deleted file mode 100644 index 49bb8af8e..000000000 --- a/Jellyfin.Api/Helpers/ItemHelper.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Globalization; -using System.IO; -using System.Linq; -using Jellyfin.Api.Models.UserDtos; -using LrcParser.Model; -using LrcParser.Parser; -using MediaBrowser.Controller.Entities; - -namespace Jellyfin.Api.Helpers -{ - /// <summary> - /// Item helper. - /// </summary> - public static class ItemHelper - { - /// <summary> - /// Opens lyrics file, converts to a List of Lyrics, and returns it. - /// </summary> - /// <param name="item">Requested Item.</param> - /// <returns>Collection of Lyrics.</returns> - internal static object? GetLyricData(BaseItem item) - { - // Find all classes that implement ILyricsProvider Interface - var foundLyricProviders = System.Reflection.Assembly.GetExecutingAssembly() - .GetTypes() - .Where(type => typeof(ILyricsProvider).IsAssignableFrom(type) && !type.IsInterface); - - if (!foundLyricProviders.Any()) - { - return null; - } - - foreach (var provider in foundLyricProviders) - { - ILyricsProvider? newProvider = Activator.CreateInstance(provider) as ILyricsProvider; - if (newProvider is not null) - { - newProvider.Process(item); - if (newProvider.HasData) - { - return newProvider.Data; - } - } - } - - return null; - } - - /// <summary> - /// Checks if requested item has a matching lyric file. - /// </summary> - /// <param name="itemPath">Path of requested item.</param> - /// <returns>True if item has a matching lyrics file.</returns> - public static string? GetLyricFilePath(string itemPath) - { - // Find all classes that implement ILyricsProvider Interface - var foundLyricProviders = System.Reflection.Assembly.GetExecutingAssembly() - .GetTypes() - .Where(type => typeof(ILyricsProvider).IsAssignableFrom(type) && !type.IsInterface); - - if (!foundLyricProviders.Any()) - { - return null; - } - - // Iterate over all found lyric providers - foreach (var provider in foundLyricProviders) - { - ILyricsProvider? foundProvider = Activator.CreateInstance(provider) as ILyricsProvider; - if (foundProvider?.FileExtensions is null) - { - continue; - } - - if (foundProvider.FileExtensions.Any()) - { - foreach (string lyricFileExtension in foundProvider.FileExtensions) - { - string lyricFilePath = @Path.ChangeExtension(itemPath, lyricFileExtension); - if (System.IO.File.Exists(lyricFilePath)) - { - return lyricFilePath; - } - } - } - } - - return null; - } - - - /// <summary> - /// Checks if requested item has a matching local lyric file. - /// </summary> - /// <param name="itemPath">Path of requested item.</param> - /// <returns>True if item has a matching lyrics file; otherwise false.</returns> - public static bool HasLyricFile(string itemPath) - { - string? lyricFilePath = GetLyricFilePath(itemPath); - return !string.IsNullOrEmpty(lyricFilePath); - } - } -} diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 972387e02..894d87138 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -17,7 +17,6 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="LrcParser" Version="2022.529.1" /> <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.8" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> diff --git a/Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs b/Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs deleted file mode 100644 index 37f1f5bbe..000000000 --- a/Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.ObjectModel; -using MediaBrowser.Controller.Entities; - -namespace Jellyfin.Api.Models.UserDtos -{ - /// <summary> - /// Interface ILyricsProvider. - /// </summary> - public interface ILyricsProvider - { - /// <summary> - /// Gets a value indicating the File Extenstions this provider works with. - /// </summary> - public Collection<string>? FileExtensions { get; } - - /// <summary> - /// Gets a value indicating whether Process() generated data. - /// </summary> - /// <returns><c>true</c> if data generated; otherwise, <c>false</c>.</returns> - bool HasData { get; } - - /// <summary> - /// Gets Data object generated by Process() method. - /// </summary> - /// <returns><c>Object</c> with data if no error occured; otherwise, <c>null</c>.</returns> - object? Data { get; } - - /// <summary> - /// Opens lyric file for [the specified item], and processes it for API return. - /// </summary> - /// <param name="item">The item to to process.</param> - void Process(BaseItem item); - } -} diff --git a/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs new file mode 100644 index 000000000..bac32a398 --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Lyrics +{ + /// <summary> + /// Interface ILyricsProvider. + /// </summary> + public interface ILyricsProvider + { + /// <summary> + /// Gets the supported media types for this provider. + /// </summary> + /// <value>The supported media types.</value> + IEnumerable<string> SupportedMediaTypes { get; } + + /// <summary> + /// Gets the lyrics. + /// </summary> + /// <param name="item">The item to to process.</param> + /// <returns>Task{LyricResponse}.</returns> + LyricResponse? GetLyrics(BaseItem item); + } +} diff --git a/Jellyfin.Api/Models/UserDtos/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs index f83fc9839..d44546dd3 100644 --- a/Jellyfin.Api/Models/UserDtos/Lyric.cs +++ b/MediaBrowser.Controller/Lyrics/Lyric.cs @@ -1,4 +1,4 @@ -namespace Jellyfin.Api.Models.UserDtos +namespace MediaBrowser.Controller.Lyrics { /// <summary> /// Lyric dto. diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs new file mode 100644 index 000000000..83a10701a --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; +using MediaBrowser.Controller.Net; +using Microsoft.AspNetCore.Mvc; + +namespace MediaBrowser.Controller.Lyrics +{ + /// <summary> + /// Item helper. + /// </summary> + public class LyricInfo + { + /// <summary> + /// Opens lyrics file, converts to a List of Lyrics, and returns it. + /// </summary> + /// <param name="lyricProviders">Collection of all registered <see cref="ILyricsProvider"/> interfaces.</param> + /// <param name="item">Requested Item.</param> + /// <returns>Collection of Lyrics.</returns> + public static LyricResponse? GetLyricData(IEnumerable<ILyricsProvider> lyricProviders, BaseItem item) + { + + foreach (var provider in lyricProviders) + { + var result = provider.GetLyrics(item); + if (result is not null) + { + return result; + } + } + + return new LyricResponse + { + Lyrics = new List<Lyric> + { + new Lyric { Start = 0, Text = "Test" } + } + }; + } + + /// <summary> + /// Checks if requested item has a matching lyric file. + /// </summary> + /// <param name="lyricProvider">The current lyricProvider interface.</param> + /// <param name="itemPath">Path of requested item.</param> + /// <returns>True if item has a matching lyrics file.</returns> + public static string? GetLyricFilePath(ILyricsProvider lyricProvider, string itemPath) + { + if (lyricProvider.SupportedMediaTypes.Any()) + { + foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) + { + string lyricFilePath = @Path.ChangeExtension(itemPath, lyricFileExtension); + if (System.IO.File.Exists(lyricFilePath)) + { + return lyricFilePath; + } + } + } + + return null; + } + + /// <summary> + /// Checks if requested item has a matching local lyric file. + /// </summary> + /// <param name="lyricProviders">Collection of all registered <see cref="ILyricsProvider"/> interfaces.</param> + /// <param name="itemPath">Path of requested item.</param> + /// <returns>True if item has a matching lyrics file; otherwise false.</returns> + public static bool HasLyricFile(IEnumerable<ILyricsProvider> lyricProviders, string itemPath) + { + foreach (var provider in lyricProviders) + { + if (GetLyricFilePath(provider, itemPath) is not null) + { + return true; + } + } + + return false; + } + } +} diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs new file mode 100644 index 000000000..e312638ec --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -0,0 +1,15 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Lyrics +{ + public class LyricResponse + { + public IDictionary<string, object> MetaData { get; set; } + + public IEnumerable<Lyric> Lyrics { get; set; } + } +} diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index b40a0210a..2a86fded2 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -76,7 +76,7 @@ namespace MediaBrowser.Model.Dto public bool? CanDownload { get; set; } - public bool? HasLocalLyricsFile { get; set; } + public bool? HasLyrics { get; set; } public bool? HasSubtitles { get; set; } diff --git a/Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs index 029acd6ca..e30d56308 100644 --- a/Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs @@ -4,11 +4,14 @@ using System.Collections.ObjectModel; using System.Dynamic; using System.Globalization; using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Api.Helpers; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; -namespace Jellyfin.Api.Models.UserDtos +namespace MediaBrowser.Providers.Lyric { /// <summary> /// LRC File Lyric Provider. @@ -20,7 +23,7 @@ namespace Jellyfin.Api.Models.UserDtos /// </summary> public LrcLyricsProvider() { - FileExtensions = new Collection<string> + SupportedMediaTypes = new Collection<string> { "lrc" }; @@ -29,13 +32,7 @@ namespace Jellyfin.Api.Models.UserDtos /// <summary> /// Gets a value indicating the File Extenstions this provider works with. /// </summary> - public Collection<string>? FileExtensions { get; } - - /// <summary> - /// Gets or Sets a value indicating whether Process() generated data. - /// </summary> - /// <returns><c>true</c> if data generated; otherwise, <c>false</c>.</returns> - public bool HasData { get; set; } + public IEnumerable<string> SupportedMediaTypes { get; } /// <summary> /// Gets or Sets Data object generated by Process() method. @@ -47,16 +44,17 @@ namespace Jellyfin.Api.Models.UserDtos /// Opens lyric file for [the specified item], and processes it for API return. /// </summary> /// <param name="item">The item to to process.</param> - public void Process(BaseItem item) + /// <returns><placeholder>A <see cref="Task"/> representing the asynchronous operation.</placeholder></returns> + public LyricResponse? GetLyrics(BaseItem item) { - string? lyricFilePath = Helpers.ItemHelper.GetLyricFilePath(item.Path); + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); if (string.IsNullOrEmpty(lyricFilePath)) { - return; + return null; } - List<Lyric> lyricsList = new List<Lyric>(); + List<MediaBrowser.Controller.Lyrics.Lyric> lyricsList = new List<MediaBrowser.Controller.Lyrics.Lyric>(); List<LrcParser.Model.Lyric> sortedLyricData = new List<LrcParser.Model.Lyric>(); var metaData = new ExpandoObject() as IDictionary<string, object>; @@ -88,30 +86,27 @@ namespace Jellyfin.Api.Models.UserDtos } catch { - return; + return null; } if (!sortedLyricData.Any()) { - return; + return null; } for (int i = 0; i < sortedLyricData.Count; i++) { var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; - lyricsList.Add(new Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); + lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); } - this.HasData = true; if (metaData.Any()) { - this.Data = new { MetaData = metaData, lyrics = lyricsList }; - } - else - { - this.Data = new { lyrics = lyricsList }; + return new LyricResponse { MetaData = metaData, Lyrics = lyricsList }; } + + return new LyricResponse { Lyrics = lyricsList }; } } } diff --git a/Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs index 03cce1ffb..2a5da4e4d 100644 --- a/Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs @@ -1,14 +1,13 @@ 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 System.Threading.Tasks; +using Jellyfin.Api.Helpers; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; -namespace Jellyfin.Api.Models.UserDtos +namespace MediaBrowser.Providers.Lyric { /// <summary> /// TXT File Lyric Provider. @@ -20,7 +19,7 @@ namespace Jellyfin.Api.Models.UserDtos /// </summary> public TxtLyricsProvider() { - FileExtensions = new Collection<string> + SupportedMediaTypes = new Collection<string> { "lrc", "txt" }; @@ -29,13 +28,7 @@ namespace Jellyfin.Api.Models.UserDtos /// <summary> /// Gets a value indicating the File Extenstions this provider works with. /// </summary> - public Collection<string>? FileExtensions { get; } - - /// <summary> - /// Gets or Sets a value indicating whether Process() generated data. - /// </summary> - /// <returns><c>true</c> if data generated; otherwise, <c>false</c>.</returns> - public bool HasData { get; set; } + public IEnumerable<string> SupportedMediaTypes { get; } /// <summary> /// Gets or Sets Data object generated by Process() method. @@ -47,16 +40,17 @@ namespace Jellyfin.Api.Models.UserDtos /// Opens lyric file for [the specified item], and processes it for API return. /// </summary> /// <param name="item">The item to to process.</param> - public void Process(BaseItem item) + /// <returns><placeholder>A <see cref="Task"/> representing the asynchronous operation.</placeholder></returns> + public LyricResponse? GetLyrics(BaseItem item) { - string? lyricFilePath = Helpers.ItemHelper.GetLyricFilePath(item.Path); + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); if (string.IsNullOrEmpty(lyricFilePath)) { - return; + return null; } - List<Lyric> lyricsList = new List<Lyric>(); + List<MediaBrowser.Controller.Lyrics.Lyric> lyricsList = new List<MediaBrowser.Controller.Lyrics.Lyric>(); string lyricData = System.IO.File.ReadAllText(lyricFilePath); @@ -66,16 +60,15 @@ namespace Jellyfin.Api.Models.UserDtos if (!lyricTextLines.Any()) { - return; + return null; } foreach (string lyricLine in lyricTextLines) { - lyricsList.Add(new Lyric { Text = lyricLine }); + lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Text = lyricLine }); } - this.HasData = true; - this.Data = new { lyrics = lyricsList }; + return new LyricResponse { Lyrics = lyricsList }; } } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 9864db9ac..8514489f8 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -6,6 +6,7 @@ </PropertyGroup> <ItemGroup> + <ProjectReference Include="..\Jellyfin.Api\Jellyfin.Api.csproj" /> <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> <ProjectReference Include="..\DvdLib\DvdLib.csproj" /> @@ -16,6 +17,7 @@ </ItemGroup> <ItemGroup> + <PackageReference Include="LrcParser" Version="2022.529.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> |
