diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 73aafe2732..044d02e23a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,18 +20,18 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1 - name: Setup .NET uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3 with: dotnet-version: '7.0.x' - name: Initialize CodeQL - uses: github/codeql-action/init@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9 + uses: github/codeql-action/init@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11 with: languages: ${{ matrix.language }} queries: +security-extended - name: Autobuild - uses: github/codeql-action/autobuild@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9 + uses: github/codeql-action/autobuild@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9 + uses: github/codeql-action/analyze@d186a2a36cc67bfa1b860e6170d37fb9634742c7 # v2.2.11 diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 236a11a137..cee70ad580 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -17,14 +17,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify as seen - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 with: token: ${{ secrets.JF_BOT_TOKEN }} comment-id: ${{ github.event.comment.id }} reactions: '+1' - name: Checkout the latest code - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1 with: token: ${{ secrets.JF_BOT_TOKEN }} fetch-depth: 0 @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify as seen - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 if: ${{ github.event.comment != null }} with: token: ${{ secrets.JF_BOT_TOKEN }} @@ -51,14 +51,14 @@ jobs: reactions: eyes - name: Checkout the latest code - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1 with: token: ${{ secrets.JF_BOT_TOKEN }} fetch-depth: 0 - name: Notify as running id: comment_running - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 if: ${{ github.event.comment != null }} with: token: ${{ secrets.JF_BOT_TOKEN }} @@ -93,7 +93,7 @@ jobs: exit ${retcode} - name: Notify with result success - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 if: ${{ github.event.comment != null && success() }} with: token: ${{ secrets.JF_BOT_TOKEN }} @@ -108,7 +108,7 @@ jobs: reactions: hooray - name: Notify with result failure - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 if: ${{ github.event.comment != null && failure() }} with: token: ${{ secrets.JF_BOT_TOKEN }} diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml index c68679cede..2192af2760 100644 --- a/.github/workflows/openapi.yml +++ b/.github/workflows/openapi.yml @@ -14,7 +14,7 @@ jobs: permissions: read-all steps: - name: Checkout repository - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1 with: ref: ${{ github.event.pull_request.head.sha }} repository: ${{ github.event.pull_request.head.repo.full_name }} @@ -39,7 +39,7 @@ jobs: permissions: read-all steps: - name: Checkout repository - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # v3.5.1 with: ref: ${{ github.event.pull_request.head.sha }} repository: ${{ github.event.pull_request.head.repo.full_name }} @@ -110,7 +110,7 @@ jobs: direction: last body-includes: openapi-diff-workflow-comment - name: Reply or edit difference comment (changed) - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 if: ${{ steps.read-diff.outputs.body != '' }} with: issue-number: ${{ github.event.pull_request.number }} @@ -125,7 +125,7 @@ jobs: - name: Edit difference comment (unchanged) - uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d # v2.1.1 + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 if: ${{ steps.read-diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }} with: issue-number: ${{ github.event.pull_request.number }} diff --git a/Directory.Packages.props b/Directory.Packages.props index f37eaa11e7..55948cb4a4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,13 +23,13 @@ - - + + - - - - + + + + @@ -38,8 +38,8 @@ - - + + diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index aab475153b..39cfc2d1d4 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -7,7 +7,6 @@ using System.Globalization; using System.Linq; using System.Net.Http; using System.Net.Sockets; -using System.Runtime.InteropServices; using System.Threading.Tasks; using Emby.Dlna.PlayTo; using Emby.Dlna.Ssdp; diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs index c463727329..6b2096d9dc 100644 --- a/Emby.Dlna/PlayTo/TransportCommands.cs +++ b/Emby.Dlna/PlayTo/TransportCommands.cs @@ -116,7 +116,7 @@ namespace Emby.Dlna.PlayTo return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString); } - public string BuildPost(ServiceAction action, string xmlNamesapce, object value, string commandParameter = "") + public string BuildPost(ServiceAction action, string xmlNamespace, object value, string commandParameter = "") { var stateString = string.Empty; @@ -137,10 +137,10 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString); } - public string BuildPost(ServiceAction action, string xmlNamesapce, object value, Dictionary dictionary) + public string BuildPost(ServiceAction action, string xmlNamespace, object value, Dictionary dictionary) { var stateString = string.Empty; @@ -150,9 +150,9 @@ namespace Emby.Dlna.PlayTo { stateString += BuildArgumentXml(arg, "0"); } - else if (dictionary.ContainsKey(arg.Name)) + else if (dictionary.TryGetValue(arg.Name, out var argValue)) { - stateString += BuildArgumentXml(arg, dictionary[arg.Name]); + stateString += BuildArgumentXml(arg, argValue); } else { @@ -160,7 +160,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString); } private string BuildArgumentXml(Argument argument, string? value, string commandParameter = "") diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 1d61667f86..bc520b86e7 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Data if (JournalSizeLimit.HasValue) { - WriteConnection.Execute("PRAGMA journal_size_limit=" + (int)JournalSizeLimit.Value); + WriteConnection.Execute("PRAGMA journal_size_limit=" + JournalSizeLimit.Value); } if (Synchronous.HasValue) @@ -166,18 +166,6 @@ namespace Emby.Server.Implementations.Data public IStatement PrepareStatement(IDatabaseConnection connection, string sql) => connection.PrepareStatement(sql); - public IStatement[] PrepareAll(IDatabaseConnection connection, IReadOnlyList sql) - { - int len = sql.Count; - IStatement[] statements = new IStatement[len]; - for (int i = 0; i < len; i++) - { - statements[i] = connection.PrepareStatement(sql[i]); - } - - return statements; - } - protected bool TableExists(ManagedConnection connection, string name) { return connection.RunInTransaction( diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index fcff5f98c6..71788a3e43 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -624,14 +624,8 @@ namespace Emby.Server.Implementations.Data private void SaveItemsInTransaction(IDatabaseConnection db, IEnumerable<(BaseItem Item, List AncestorIds, BaseItem TopParent, string UserDataKey, List InheritedTags)> tuples) { - var statements = PrepareAll(db, new string[] - { - SaveItemCommandText, - "delete from AncestorIds where ItemId=@ItemId" - }); - - using (var saveItemStatement = statements[0]) - using (var deleteAncestorsStatement = statements[1]) + using (var saveItemStatement = PrepareStatement(db, SaveItemCommandText)) + using (var deleteAncestorsStatement = PrepareStatement(db, "delete from AncestorIds where ItemId=@ItemId")) { var requiresReset = false; foreach (var tuple in tuples) @@ -1286,15 +1280,13 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); using (var connection = GetConnection(true)) + using (var statement = PrepareStatement(connection, _retrieveItemColumnsSelectQuery)) { - using (var statement = PrepareStatement(connection, _retrieveItemColumnsSelectQuery)) - { - statement.TryBind("@guid", id); + statement.TryBind("@guid", id); - foreach (var row in statement.ExecuteQuery()) - { - return GetItem(row, new InternalItemsQuery()); - } + foreach (var row in statement.ExecuteQuery()) + { + return GetItem(row, new InternalItemsQuery()); } } @@ -1309,7 +1301,8 @@ namespace Emby.Server.Implementations.Data { return false; } - else if (type == typeof(UserRootFolder)) + + if (type == typeof(UserRootFolder)) { return false; } @@ -1319,55 +1312,68 @@ namespace Emby.Server.Implementations.Data { return false; } - else if (type == typeof(MusicArtist)) + + if (type == typeof(MusicArtist)) { return false; } - else if (type == typeof(Person)) + + if (type == typeof(Person)) { return false; } - else if (type == typeof(MusicGenre)) + + if (type == typeof(MusicGenre)) { return false; } - else if (type == typeof(Genre)) + + if (type == typeof(Genre)) { return false; } - else if (type == typeof(Studio)) + + if (type == typeof(Studio)) { return false; } - else if (type == typeof(PlaylistsFolder)) + + if (type == typeof(PlaylistsFolder)) { return false; } - else if (type == typeof(PhotoAlbum)) + + if (type == typeof(PhotoAlbum)) { return false; } - else if (type == typeof(Year)) + + if (type == typeof(Year)) { return false; } - else if (type == typeof(Book)) + + if (type == typeof(Book)) { return false; } - else if (type == typeof(LiveTvProgram)) + + if (type == typeof(LiveTvProgram)) { return false; } - else if (type == typeof(AudioBook)) + + if (type == typeof(AudioBook)) { return false; } - else if (type == typeof(Audio)) + + if (type == typeof(Audio)) { return false; } - else if (type == typeof(MusicAlbum)) + + if (type == typeof(MusicAlbum)) { return false; } @@ -1958,22 +1964,19 @@ namespace Emby.Server.Implementations.Data { CheckDisposed(); + var chapters = new List(); using (var connection = GetConnection(true)) + using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc")) { - var chapters = new List(); + statement.TryBind("@ItemId", item.Id); - using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc")) + foreach (var row in statement.ExecuteQuery()) { - statement.TryBind("@ItemId", item.Id); - - foreach (var row in statement.ExecuteQuery()) - { - chapters.Add(GetChapter(row, item)); - } + chapters.Add(GetChapter(row, item)); } - - return chapters; } + + return chapters; } /// @@ -1982,16 +1985,14 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); using (var connection = GetConnection(true)) + using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex")) { - using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex")) - { - statement.TryBind("@ItemId", item.Id); - statement.TryBind("@ChapterIndex", index); + statement.TryBind("@ItemId", item.Id); + statement.TryBind("@ChapterIndex", index); - foreach (var row in statement.ExecuteQuery()) - { - return GetChapter(row, item); - } + foreach (var row in statement.ExecuteQuery()) + { + return GetChapter(row, item); } } @@ -2392,6 +2393,7 @@ namespace Emby.Server.Implementations.Data // genres, tags, studios, person, year? builder.Append("+ (Select count(1) * 10 from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from ItemValues where ItemId=@SimilarItemId))"); + builder.Append("+ (Select count(1) * 10 from People where ItemId=Guid and Name in (select Name from People where ItemId=@SimilarItemId))"); if (item is MusicArtist) { @@ -2843,13 +2845,10 @@ namespace Emby.Server.Implementations.Data connection.RunInTransaction( db => { - var itemQueryStatement = PrepareStatement(db, itemQuery); - var totalRecordCountQueryStatement = PrepareStatement(db, totalRecordCountQuery); - if (!isReturningZeroItems) { using (new QueryTimeLogger(Logger, itemQuery, "GetItems.ItemQuery")) - using (var statement = itemQueryStatement) + using (var statement = PrepareStatement(db, itemQuery)) { if (EnableJoinUserData(query)) { @@ -2884,7 +2883,7 @@ namespace Emby.Server.Implementations.Data if (query.EnableTotalRecordCount) { using (new QueryTimeLogger(Logger, totalRecordCountQuery, "GetItems.TotalRecordCount")) - using (var statement = totalRecordCountQueryStatement) + using (var statement = PrepareStatement(db, totalRecordCountQuery)) { if (EnableJoinUserData(query)) { @@ -4753,22 +4752,20 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type commandText.Append(" LIMIT ").Append(query.Limit); } + var list = new List(); using (var connection = GetConnection(true)) + using (var statement = PrepareStatement(connection, commandText.ToString())) { - var list = new List(); - using (var statement = PrepareStatement(connection, commandText.ToString())) + // Run this again to bind the params + GetPeopleWhereClauses(query, statement); + + foreach (var row in statement.ExecuteQuery()) { - // Run this again to bind the params - GetPeopleWhereClauses(query, statement); - - foreach (var row in statement.ExecuteQuery()) - { - list.Add(row.GetString(0)); - } + list.Add(row.GetString(0)); } - - return list; } + + return list; } public List GetPeople(InternalPeopleQuery query) @@ -4793,23 +4790,20 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type commandText += " LIMIT " + query.Limit; } + var list = new List(); using (var connection = GetConnection(true)) + using (var statement = PrepareStatement(connection, commandText)) { - var list = new List(); + // Run this again to bind the params + GetPeopleWhereClauses(query, statement); - using (var statement = PrepareStatement(connection, commandText)) + foreach (var row in statement.ExecuteQuery()) { - // Run this again to bind the params - GetPeopleWhereClauses(query, statement); - - foreach (var row in statement.ExecuteQuery()) - { - list.Add(GetPerson(row)); - } + list.Add(GetPerson(row)); } - - return list; } + + return list; } private List GetPeopleWhereClauses(InternalPeopleQuery query, IStatement statement) diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 8b66829032..8fa2f05662 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using Jellyfin.Api.Helpers; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Extensions; @@ -572,9 +571,7 @@ namespace Emby.Server.Implementations.Dto return null; } }).Where(i => i is not null) - .Where(i => user is null ? - true : - i.IsVisible(user)) + .Where(i => user is null || i.IsVisible(user)) .DistinctBy(x => x.Name, StringComparer.OrdinalIgnoreCase) .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index e5c520ca2b..75a1a5a4d8 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1503,6 +1503,12 @@ namespace Emby.Server.Implementations.Library }); query.TopParentIds = userViews.SelectMany(i => GetTopParentIdsForQuery(i, user)).ToArray(); + + // Prevent searching in all libraries due to empty filter + if (query.TopParentIds.Length == 0) + { + query.TopParentIds = new[] { Guid.NewGuid() }; + } } } @@ -1879,7 +1885,7 @@ namespace Emby.Server.Implementations.Library catch (Exception ex) { _logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path); - size = new ImageDimensions(0, 0); + size = default; image.Width = 0; image.Height = 0; } @@ -2743,9 +2749,7 @@ namespace Emby.Server.Implementations.Library } }) .Where(i => i is not null) - .Where(i => query.User is null ? - true : - i.IsVisible(query.User)) + .Where(i => query.User is null || i.IsVisible(query.User)) .ToList(); } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index eadfa5dfe9..c9a26a30f5 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -154,8 +154,8 @@ namespace Emby.Server.Implementations.Library // If file is strm or main media stream is missing, force a metadata refresh with remote probing if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder && (item.Path.EndsWith(".strm", StringComparison.OrdinalIgnoreCase) - || (item.MediaType == MediaType.Video && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Video)) - || (item.MediaType == MediaType.Audio && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio)))) + || (item.MediaType == MediaType.Video && mediaSources[0].MediaStreams.All(i => i.Type != MediaStreamType.Video)) + || (item.MediaType == MediaType.Audio && mediaSources[0].MediaStreams.All(i => i.Type != MediaStreamType.Audio)))) { await item.RefreshMetadata( new MetadataRefreshOptions(_directoryService) diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 4fac91bf1e..381796d0e3 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -78,7 +78,8 @@ namespace Emby.Server.Implementations.Library.Resolvers Set3DFormat(videoTmp); return videoTmp; } - else if (IsBluRayDirectory(filename)) + + if (IsBluRayDirectory(filename)) { var videoTmp = new TVideoType { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index e7f4d2f4eb..b9d0f170ac 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -627,10 +627,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _timerProvider.Update(existingTimer); return Task.FromResult(existingTimer.Id); } - else - { - throw new ArgumentException("A scheduled recording already exists for this program."); - } + + throw new ArgumentException("A scheduled recording already exists for this program."); } info.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); @@ -1866,8 +1864,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { await writer.WriteStartDocumentAsync(true).ConfigureAwait(false); await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false); - string id; - if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out id)) + if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out var id)) { await writer.WriteElementStringAsync(null, "id", null, id).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index b5e742f98f..ca3e45707b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -415,14 +415,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings { return null; } - else if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1) + + if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1) { return uri; } - else - { - return apiUrl + "/image/" + uri + "?token=" + token; - } + + return apiUrl + "/image/" + uri + "?token=" + token; } private static double GetAspectRatio(ImageDataDto i) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 81eb083f6f..7bc209d6bd 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public async Task CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken) { using var client = new TcpClient(); - await client.ConnectAsync(remoteIp, HdHomeRunPort).ConfigureAwait(false); + await client.ConnectAsync(remoteIp, HdHomeRunPort, cancellationToken).ConfigureAwait(false); using var stream = client.GetStream(); return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index f2020e05fe..b418162304 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -170,9 +170,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var nameInExtInf = nameParts.Length > 1 ? nameParts[^1].AsSpan().Trim() : ReadOnlySpan.Empty; string numberString = null; - string attributeValue; - if (attributes.TryGetValue("tvg-chno", out attributeValue) + if (attributes.TryGetValue("tvg-chno", out var attributeValue) && double.TryParse(attributeValue, CultureInfo.InvariantCulture, out _)) { numberString = attributeValue; diff --git a/Emby.Server.Implementations/Localization/Core/bn.json b/Emby.Server.Implementations/Localization/Core/bn.json index c3fbe24082..355fb3b21e 100644 --- a/Emby.Server.Implementations/Localization/Core/bn.json +++ b/Emby.Server.Implementations/Localization/Core/bn.json @@ -1,27 +1,27 @@ { "DeviceOnlineWithName": "{0}-এর সাথে সংযুক্ত হয়েছে", "DeviceOfflineWithName": "{0}-এর সাথে সংযোগ বিচ্ছিন্ন হয়েছে", - "Collections": "সংগ্রহ", + "Collections": "সংগ্রহশালা", "ChapterNameValue": "অধ্যায় {0}", - "Channels": "চ্যানেল", + "Channels": "চ্যানেলসমূহ", "CameraImageUploadedFrom": "{0} থেকে একটি নতুন ক্যামেরার চিত্র আপলোড করা হয়েছে", - "Books": "বই", + "Books": "পুস্তকসমূহ", "AuthenticationSucceededWithUserName": "{0} অনুমোদন সফল", - "Artists": "শিল্পীরা", + "Artists": "শিল্পীগণ", "Application": "অ্যাপ্লিকেশন", - "Albums": "অ্যালবামগুলো", + "Albums": "অ্যালবামসমূহ", "HeaderFavoriteEpisodes": "প্রিব পর্বগুলো", "HeaderFavoriteArtists": "প্রিয় শিল্পীরা", "HeaderFavoriteAlbums": "প্রিয় এলবামগুলো", "HeaderContinueWatching": "দেখতে থাকুন", - "HeaderAlbumArtists": "এলবাম শিল্পীবৃন্দ", - "Genres": "শৈলী", - "Folders": "ফোল্ডারগুলো", + "HeaderAlbumArtists": "অ্যালবাম শিল্পীবৃন্দ", + "Genres": "শৈলীধারাসমূহ", + "Folders": "ফোল্ডারসমূহ", "Favorites": "পছন্দসমূহ", "FailedLoginAttemptWithUserName": "{0} লগিন করতে ব্যর্থ হয়েছে", "AppDeviceValues": "অ্যাপ: {0}, ডিভাইস: {0}", "VersionNumber": "সংস্করণ {0}", - "ValueSpecialEpisodeName": "বিশেষ - {0}", + "ValueSpecialEpisodeName": "বিশেষ পর্ব - {0}", "ValueHasBeenAddedToLibrary": "আপনার লাইব্রেরিতে {0} যোগ করা হয়েছে", "UserStoppedPlayingItemWithValues": "{2}তে {1} বাজানো শেষ করেছেন {0}", "UserStartedPlayingItemWithValues": "{2}তে {1} বাজাচ্ছেন {0}", @@ -36,10 +36,10 @@ "User": "ব্যবহারকারী", "TvShows": "টিভি শোগুলো", "System": "সিস্টেম", - "Sync": "সিংক", + "Sync": "সমলয় স্থাপন", "SubtitleDownloadFailureFromForItem": "{2} থেকে {1} এর জন্য সাবটাইটেল ডাউনলোড ব্যর্থ", "StartupEmbyServerIsLoading": "জেলিফিন সার্ভার লোড হচ্ছে। দয়া করে একটু পরে আবার চেষ্টা করুন।", - "Songs": "গানগুলো", + "Songs": "সঙ্গীতসমূহ", "Shows": "টিভি পর্ব", "ServerNameNeedsToBeRestarted": "{0} রিস্টার্ট করা প্রয়োজন", "ScheduledTaskStartedWithName": "{0} শুরু হয়েছে", @@ -49,8 +49,8 @@ "PluginUninstalledWithName": "{0} বাদ দেয়া হয়েছে", "PluginInstalledWithName": "{0} ইন্সটল করা হয়েছে", "Plugin": "প্লাগিন", - "Playlists": "প্লেলিস্ট", - "Photos": "ছবিগুলো", + "Playlists": "প্লে লিস্ট সমূহ", + "Photos": "চিত্রসমূহ", "NotificationOptionVideoPlaybackStopped": "ভিডিও চলা বন্ধ", "NotificationOptionVideoPlayback": "ভিডিও চলা শুরু হয়েছে", "NotificationOptionUserLockedOut": "ব্যবহারকারী ঢুকতে পারছে না", @@ -71,9 +71,9 @@ "NameSeasonUnknown": "সিজন অজানা", "NameSeasonNumber": "সিজন {0}", "NameInstallFailed": "{0} ইন্সটল ব্যর্থ", - "MusicVideos": "গানের ভিডিও", + "MusicVideos": "সঙ্গীত ভিডিয়ো সমূহ", "Music": "গান", - "Movies": "চলচ্চিত্র", + "Movies": "চলচ্চিত্রসমূহ", "MixedContent": "মিশ্র কন্টেন্ট", "MessageServerConfigurationUpdated": "সার্ভারের কনফিগারেশন আপডেট করা হয়েছে", "HeaderRecordingGroups": "রেকর্ডিং দল", @@ -117,5 +117,11 @@ "Forced": "জোরকরে", "TaskCleanActivityLogDescription": "নির্ধারিত সময়ের আগের কাজের হিসাব মুছে দিন খালি করুন.", "TaskCleanActivityLog": "কাজের ফাইল খালি করুন", - "Default": "প্রাথমিক" + "Default": "প্রাথমিক", + "HearingImpaired": "দুর্বল শ্রবণক্ষমতাধরদের জন্য", + "TaskOptimizeDatabaseDescription": "তথ্যভাণ্ডার সুবিন্যস্ত করে ও অব্যবহৃত জায়গা ছেড়ে দেয়। লাইব্রেরী স্ক্যান অথবা যেকোনো তথ্যভাণ্ডার পরিবর্তনের পর এই প্রক্রিয়া চালালে তথ্যভাণ্ডারের তথ্য প্রদান দ্রুততর হতে পারে।", + "External": "বাহ্যিক", + "TaskOptimizeDatabase": "তথ্যভাণ্ডার সুবিন্যাস", + "TaskKeyframeExtractor": "কি-ফ্রেম নিষ্কাশক", + "TaskKeyframeExtractorDescription": "ভিডিয়ো থেকে কি-ফ্রেম নিষ্কাশনের মাধ্যমে অধিকতর সঠিক HLS প্লে লিস্ট তৈরী করে। এই প্রক্রিয়া দীর্ঘ সময় ধরে চলতে পারে।" } diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 0d0d0c8136..1b6eecdcfe 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -1,9 +1,9 @@ { - "Albums": "Albummer", + "Albums": "Album", "AppDeviceValues": "App: {0}, Enhed: {1}", "Application": "Applikation", "Artists": "Kunstnere", - "AuthenticationSucceededWithUserName": "{0} succesfuldt autentificeret", + "AuthenticationSucceededWithUserName": "{0} er logget ind", "Books": "Bøger", "CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}", "Channels": "Kanaler", @@ -11,17 +11,17 @@ "Collections": "Samlinger", "DeviceOfflineWithName": "{0} har afbrudt forbindelsen", "DeviceOnlineWithName": "{0} er forbundet", - "FailedLoginAttemptWithUserName": "Fejlet loginforsøg fra {0}", + "FailedLoginAttemptWithUserName": "Mislykket loginforsøg fra {0}", "Favorites": "Favoritter", "Folders": "Mapper", "Genres": "Genrer", - "HeaderAlbumArtists": "Albumkunstner", + "HeaderAlbumArtists": "Albums kunstnere", "HeaderContinueWatching": "Fortsæt afspilning", - "HeaderFavoriteAlbums": "Favoritalbummer", - "HeaderFavoriteArtists": "Favoritkunstnere", - "HeaderFavoriteEpisodes": "Favoritepisoder", - "HeaderFavoriteShows": "Favoritserier", - "HeaderFavoriteSongs": "Favoritsange", + "HeaderFavoriteAlbums": "Favorit albummer", + "HeaderFavoriteArtists": "Favorit kunstnere", + "HeaderFavoriteEpisodes": "Favorit afsnit", + "HeaderFavoriteShows": "Favorit serier", + "HeaderFavoriteSongs": "Favorit sange", "HeaderLiveTV": "Live-TV", "HeaderNextUp": "Næste", "HeaderRecordingGroups": "Optagelsesgrupper", @@ -39,90 +39,90 @@ "MixedContent": "Blandet indhold", "Movies": "Film", "Music": "Musik", - "MusicVideos": "Musik videoer", + "MusicVideos": "Musikvideoer", "NameInstallFailed": "{0} installationen mislykkedes", "NameSeasonNumber": "Sæson {0}", "NameSeasonUnknown": "Ukendt sæson", - "NewVersionIsAvailable": "En ny version af Jellyfin Server er tilgængelig til download.", - "NotificationOptionApplicationUpdateAvailable": "Opdatering til applikation tilgængelig", - "NotificationOptionApplicationUpdateInstalled": "Opdatering til applikation installeret", + "NewVersionIsAvailable": "En ny version af Jellyfin Server er tilgængelig.", + "NotificationOptionApplicationUpdateAvailable": "Opdatering til applikationen er tilgængelig", + "NotificationOptionApplicationUpdateInstalled": "Opdatering til applikationen blev installeret", "NotificationOptionAudioPlayback": "Lydafspilning påbegyndt", "NotificationOptionAudioPlaybackStopped": "Lydafspilning stoppet", "NotificationOptionCameraImageUploaded": "Kamerabillede uploadet", - "NotificationOptionInstallationFailed": "Installationen fejlede", + "NotificationOptionInstallationFailed": "Installationen mislykkedes", "NotificationOptionNewLibraryContent": "Nyt indhold tilføjet", - "NotificationOptionPluginError": "Pluginfejl", - "NotificationOptionPluginInstalled": "Plugin installeret", - "NotificationOptionPluginUninstalled": "Plugin afinstalleret", - "NotificationOptionPluginUpdateInstalled": "Opdatering til plugin installeret", - "NotificationOptionServerRestartRequired": "Genstart af server påkrævet", - "NotificationOptionTaskFailed": "Planlagt opgave fejlet", - "NotificationOptionUserLockedOut": "Bruger låst ude", + "NotificationOptionPluginError": "Plugin fejl", + "NotificationOptionPluginInstalled": "Plugin blev installeret", + "NotificationOptionPluginUninstalled": "Plugin blev afinstalleret", + "NotificationOptionPluginUpdateInstalled": "Opdatering til plugin blev installeret", + "NotificationOptionServerRestartRequired": "Genstart af serveren er påkrævet", + "NotificationOptionTaskFailed": "Planlagt opgave er fejlet", + "NotificationOptionUserLockedOut": "Bruger er låst ude", "NotificationOptionVideoPlayback": "Videoafspilning påbegyndt", - "NotificationOptionVideoPlaybackStopped": "Videoafspilning stoppet", - "Photos": "Fotoer", + "NotificationOptionVideoPlaybackStopped": "Videoafspilning blev stoppet", + "Photos": "Fotos", "Playlists": "Afspilningslister", "Plugin": "Plugin", "PluginInstalledWithName": "{0} blev installeret", "PluginUninstalledWithName": "{0} blev afinstalleret", "PluginUpdatedWithName": "{0} blev opdateret", "ProviderValue": "Udbyder: {0}", - "ScheduledTaskFailedWithName": "{0} fejlet", - "ScheduledTaskStartedWithName": "{0} påbegyndt", + "ScheduledTaskFailedWithName": "{0} mislykkedes", + "ScheduledTaskStartedWithName": "{0} påbegyndte", "ServerNameNeedsToBeRestarted": "{0} skal genstartes", "Shows": "Serier", "Songs": "Sange", - "StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte op. Prøv venligst igen om lidt.", + "StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte. Forsøg igen om et øjeblik.", "SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}", - "SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke downloades fra {0} til {1}", - "Sync": "Synk", + "SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke hentes fra {0} til {1}", + "Sync": "Synkroniser", "System": "System", - "TvShows": "Tv-serier", + "TvShows": "TV-serier", "User": "Bruger", "UserCreatedWithName": "Bruger {0} er blevet oprettet", - "UserDeletedWithName": "Brugeren {0} er blevet slettet", - "UserDownloadingItemWithValues": "{0} downloader {1}", + "UserDeletedWithName": "Brugeren {0} er nu slettet", + "UserDownloadingItemWithValues": "{0} henter {1}", "UserLockedOutWithName": "Brugeren {0} er blevet låst ude", "UserOfflineFromDevice": "{0} har afbrudt fra {1}", "UserOnlineFromDevice": "{0} er online fra {1}", - "UserPasswordChangedWithName": "Adgangskode er ændret for bruger {0}", - "UserPolicyUpdatedWithName": "Brugerpolitik er blevet opdateret for {0}", + "UserPasswordChangedWithName": "Adgangskode er ændret for brugeren {0}", + "UserPolicyUpdatedWithName": "Brugerpolitikken er blevet opdateret for {0}", "UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}", "UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}", "ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek", "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}", - "TaskDownloadMissingSubtitlesDescription": "Søger på internettet efter manglende undertekster baseret på metadata konfiguration.", - "TaskDownloadMissingSubtitles": "Download manglende undertekster", - "TaskUpdatePluginsDescription": "Downloader og installere opdateringer for plugins som er konfigureret til at opdatere automatisk.", + "TaskDownloadMissingSubtitlesDescription": "Søger på internettet efter manglende undertekster baseret på metadata konfigurationen.", + "TaskDownloadMissingSubtitles": "Hent manglende undertekster", + "TaskUpdatePluginsDescription": "Henter og installerer opdateringer for plugins, som er indstillet til at blive opdateret automatisk.", "TaskUpdatePlugins": "Opdater Plugins", - "TaskCleanLogsDescription": "Sletter log filer som er mere end {0} dage gammle.", - "TaskCleanLogs": "Ryd Log Mappe", - "TaskRefreshLibraryDescription": "Scanner dit medie bibliotek for nye filer og opdaterer metadata.", + "TaskCleanLogsDescription": "Sletter log filer som er mere end {0} dage gamle.", + "TaskCleanLogs": "Ryd Log mappe", + "TaskRefreshLibraryDescription": "Scanner dit medie bibliotek for nye filer og opdateret metadata.", "TaskRefreshLibrary": "Scan Medie Bibliotek", - "TaskCleanCacheDescription": "Sletter cache filer som systemet ikke har brug for længere.", - "TaskCleanCache": "Ryd Cache Mappe", + "TaskCleanCacheDescription": "Sletter cache filer som systemet ikke længere bruger.", + "TaskCleanCache": "Ryd Cache mappe", "TasksChannelsCategory": "Internet Kanaler", "TasksApplicationCategory": "Applikation", "TasksLibraryCategory": "Bibliotek", "TasksMaintenanceCategory": "Vedligeholdelse", - "TaskRefreshChapterImages": "Udtræk Kapitel billeder", + "TaskRefreshChapterImages": "Udtræk kapitel billeder", "TaskRefreshChapterImagesDescription": "Lav miniaturebilleder for videoer der har kapitler.", - "TaskRefreshChannelsDescription": "Genopfrisker internet kanal information.", - "TaskRefreshChannels": "Genopfrisk Kanaler", - "TaskCleanTranscodeDescription": "Fjern transcode filer som er mere end en dag gammel.", - "TaskCleanTranscode": "Rengør Transcode Mappen", - "TaskRefreshPeople": "Genopfrisk Personer", - "TaskRefreshPeopleDescription": "Opdatere metadata for skuespillere og instruktører i dit bibliotek.", - "TaskCleanActivityLogDescription": "Sletter linjer i aktivitetsloggen ældre end den konfigureret alder.", + "TaskRefreshChannelsDescription": "Opdater internet kanal information.", + "TaskRefreshChannels": "Opdater Kanaler", + "TaskCleanTranscodeDescription": "Fjern transcode filer som er mere end 1 dag gammel.", + "TaskCleanTranscode": "Tøm Transcode mappen", + "TaskRefreshPeople": "Opdater Personer", + "TaskRefreshPeopleDescription": "Opdaterer metadata for skuespillere og instruktører i dit mediebibliotek.", + "TaskCleanActivityLogDescription": "Sletter linjer i aktivitetsloggen ældre end den konfigurerede alder.", "TaskCleanActivityLog": "Ryd Aktivitetslog", "Undefined": "Udefineret", "Forced": "Tvunget", "Default": "Standard", - "TaskOptimizeDatabaseDescription": "Kompakter database og forkorter fri plads. Ved at køre denne proces efter at scanne biblioteket eller efter at ændre noget som kunne have indflydelse på databasen, kan forbedre ydeevne.", + "TaskOptimizeDatabaseDescription": "Komprimerer databasen og frigør plads. Denne handling køres efter at have scannet mediebiblioteket, eller efter at have lavet ændringer til databasen, for at højne ydeevnen.", "TaskOptimizeDatabase": "Optimér database", - "TaskKeyframeExtractorDescription": "Udtrækker billeder fra videofiler for at lave mere præcise HLS playlister. Denne opgave kan godt tage lang tid.", - "TaskKeyframeExtractor": "Billedramme udtrækker", + "TaskKeyframeExtractorDescription": "Udtrækker billeder fra videofiler for at lave mere præcise HLS playlister. Denne opgave kan tage lang tid.", + "TaskKeyframeExtractor": "Nøglebillede udtræk", "External": "Ekstern", "HearingImpaired": "Hørehæmmet" } diff --git a/Emby.Server.Implementations/Localization/Core/hi.json b/Emby.Server.Implementations/Localization/Core/hi.json index a0e2f04a16..cc0a926d03 100644 --- a/Emby.Server.Implementations/Localization/Core/hi.json +++ b/Emby.Server.Implementations/Localization/Core/hi.json @@ -73,5 +73,25 @@ "Songs": "गाने", "UserStartedPlayingItemWithValues": "{0} {2} पर {1} खेल रहे हैं", "UserStoppedPlayingItemWithValues": "{0} ने {2} पर {1} खेलना खत्म किया", - "StartupEmbyServerIsLoading": "जेलीफ़िन सर्वर लोड हो रहा है। कृपया शीघ्र ही पुन: प्रयास करें।" + "StartupEmbyServerIsLoading": "जेलीफ़िन सर्वर लोड हो रहा है। कृपया शीघ्र ही पुन: प्रयास करें।", + "ServerNameNeedsToBeRestarted": "{0} रीस्टार्ट करने की आवश्यकता है", + "UserCreatedWithName": "उपयोगकर्ता {0} बनाया गया", + "UserDownloadingItemWithValues": "{0} डाउनलोड हो रहा है", + "UserOfflineFromDevice": "{0} {1} से डिस्कनेक्ट हो गया है", + "Undefined": "अनिर्धारित", + "UserOnlineFromDevice": "{0} {1} से ऑनलाइन है", + "Shows": "शो", + "UserPasswordChangedWithName": "उपयोगकर्ता {0} के लिए पासवर्ड बदल दिया गया है", + "UserDeletedWithName": "उपयोगकर्ता {0} हटा दिया गया", + "UserPolicyUpdatedWithName": "{0} के लिए उपयोगकर्ता नीति अपडेट कर दी गई है", + "User": "उपयोगकर्ता", + "SubtitleDownloadFailureFromForItem": "{1} के लिए {0} से उपशीर्षक डाउनलोड करने में विफल", + "ProviderValue": "प्रदाता: {0}", + "ScheduledTaskFailedWithName": "{0}असफल", + "UserLockedOutWithName": "उपयोगकर्ता {0} को लॉक आउट कर दिया गया है", + "System": "प्रणाली", + "TvShows": "टीवी शो", + "HearingImpaired": "मूक बधिर", + "ValueSpecialEpisodeName": "विशेष", + "TasksMaintenanceCategory": "रखरखाव" } diff --git a/Emby.Server.Implementations/Localization/Core/pa.json b/Emby.Server.Implementations/Localization/Core/pa.json index 4ac57b630d..1f982feaf4 100644 --- a/Emby.Server.Implementations/Localization/Core/pa.json +++ b/Emby.Server.Implementations/Localization/Core/pa.json @@ -28,22 +28,22 @@ "ValueHasBeenAddedToLibrary": "{0} ਤੁਹਾਡੀ ਮੀਡੀਆ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ", "UserStoppedPlayingItemWithValues": "{0} ਨੇ {2} 'ਤੇ {1} ਖੇਡਣਾ ਪੂਰਾ ਕਰ ਲਿਆ ਹੈ", "UserStartedPlayingItemWithValues": "{0} {2} 'ਤੇ {1} ਖੇਡ ਰਿਹਾ ਹੈ", - "UserPolicyUpdatedWithName": "ਉਪਭੋਗਤਾ ਨੀਤੀ ਨੂੰ {0} ਲਈ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", - "UserPasswordChangedWithName": "ਪਾਸਵਰਡ ਯੂਜ਼ਰ ਲਈ ਬਦਲਿਆ ਗਿਆ ਹੈ {0}", - "UserOnlineFromDevice": "{0} ਤੋਂ isਨਲਾਈਨ ਹੈ {1}", + "UserPolicyUpdatedWithName": "ਵਰਤੋਂਕਾਰ ਨੀਤੀ ਨੂੰ {0} ਲਈ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ ਹੈ", + "UserPasswordChangedWithName": "{0} ਵਰਤੋਂਕਾਰ ਲਈ ਪਾਸਵਰਡ ਬਦਲਿਆ ਗਿਆ ਸੀ", + "UserOnlineFromDevice": "{0} ਨੂੰ {1} ਤੋਂ ਆਨਲਾਈਨ ਹੈ", "UserOfflineFromDevice": "{0} ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ {1}", - "UserLockedOutWithName": "ਯੂਜ਼ਰ {0} ਨੂੰ ਲਾਕ ਆਉਟ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ", - "UserDownloadingItemWithValues": "{0} ਡਾ{ਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ {1}", - "UserDeletedWithName": "ਯੂਜ਼ਰ {0} ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ", - "UserCreatedWithName": "ਯੂਜ਼ਰ {0} ਬਣਾਇਆ ਗਿਆ ਹੈ", - "User": "ਯੂਜ਼ਰ", + "UserLockedOutWithName": "ਵਰਤੋਂਕਾਰ {0} ਨੂੰ ਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ", + "UserDownloadingItemWithValues": "{0} {1} ਨੂੰ ਡਾਊਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ", + "UserDeletedWithName": "ਵਰਤੋਂਕਾਰ {0} ਨੂੰ ਹਟਾਇਆ ਗਿਆ", + "UserCreatedWithName": "ਵਰਤੋਂਕਾਰ {0} ਬਣਾਇਆ ਗਿਆ ਹੈ", + "User": "ਵਰਤੋਂਕਾਰ", "Undefined": "ਪਰਿਭਾਸ਼ਤ", - "TvShows": "ਟੀਵੀ ਸ਼ੋਅਜ਼", + "TvShows": "ਟੀਵੀ ਸ਼ੋਅ", "System": "ਸਿਸਟਮ", "Sync": "ਸਿੰਕ", - "SubtitleDownloadFailureFromForItem": "ਉਪਸਿਰਲੇਖ {1} ਲਈ {0} ਤੋਂ ਡਾ toਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਹੇ", - "StartupEmbyServerIsLoading": "ਜੈਲੀਫਿਨ ਸਰਵਰ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ. ਕਿਰਪਾ ਕਰਕੇ ਜਲਦੀ ਹੀ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ.", - "Songs": "ਗਾਣੇਂ", + "SubtitleDownloadFailureFromForItem": "ਉਪਸਿਰਲੇਖ {1} ਲਈ {0} ਤੋਂ ਡਾਊਨਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਫਲ ਰਹੇ", + "StartupEmbyServerIsLoading": "Jellyfin ਸਰਵਰ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ। ਛੇਤੀ ਹੀ ਫ਼ੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", + "Songs": "ਗਾਣੇ", "Shows": "ਸ਼ੋਅ", "ServerNameNeedsToBeRestarted": "{0} ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ", "ScheduledTaskStartedWithName": "{0} ਸ਼ੁਰੂ ਹੋਇਆ", @@ -57,12 +57,12 @@ "Photos": "ਫੋਟੋਆਂ", "NotificationOptionVideoPlaybackStopped": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਰੋਕਿਆ ਗਿਆ", "NotificationOptionVideoPlayback": "ਵੀਡੀਓ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋਇਆ", - "NotificationOptionUserLockedOut": "ਉਪਭੋਗਤਾ ਨੂੰ ਲਾਕ ਆਉਟ ਕੀਤਾ ਗਿਆ", + "NotificationOptionUserLockedOut": "ਵਰਤੋਂਕਾਰ ਨੂੰ ਲਾਕ ਕੀਤਾ", "NotificationOptionTaskFailed": "ਨਿਰਧਾਰਤ ਕਾਰਜ ਅਸਫਲਤਾ", "NotificationOptionServerRestartRequired": "ਸਰਵਰ ਨੂੰ ਮੁੜ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ", "NotificationOptionPluginUpdateInstalled": "ਪਲੱਗਇਨ ਅਪਡੇਟ ਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ", "NotificationOptionPluginUninstalled": "ਪਲੱਗਇਨ ਅਣਇੰਸਟੌਲ ਕੀਤਾ", - "NotificationOptionPluginInstalled": "ਪਲੱਗਇਨ ਸਥਾਪਿਤ ਕੀਤਾ", + "NotificationOptionPluginInstalled": "ਪਲੱਗਇਨ ਇੰਸਟਾਲ ਕੀਤੀ", "NotificationOptionPluginError": "ਪਲੱਗਇਨ ਅਸਫਲ", "NotificationOptionNewLibraryContent": "ਨਵੀਂ ਸਮੱਗਰੀ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ", "NotificationOptionInstallationFailed": "ਇੰਸਟਾਲੇਸ਼ਨ ਅਸਫਲ", @@ -92,7 +92,7 @@ "HomeVideos": "ਘਰੇਲੂ ਵੀਡੀਓ", "HeaderRecordingGroups": "ਰਿਕਾਰਡਿੰਗ ਸਮੂਹ", "HeaderNextUp": "ਅੱਗੇ", - "HeaderLiveTV": "ਲਾਈਵ ਟੀ", + "HeaderLiveTV": "ਲਾਈਵ ਟੀਵੀ", "HeaderFavoriteSongs": "ਮਨਪਸੰਦ ਗਾਣੇ", "HeaderFavoriteShows": "ਮਨਪਸੰਦ ਸ਼ੋਅ", "HeaderFavoriteEpisodes": "ਮਨਪਸੰਦ ਐਪੀਸੋਡ", @@ -102,20 +102,22 @@ "HeaderAlbumArtists": "ਐਲਬਮ ਕਲਾਕਾਰ", "Genres": "ਸ਼ੈਲੀਆਂ", "Forced": "ਮਜਬੂਰ", - "Folders": "ਫੋਲਡਰਸ", + "Folders": "ਫੋਲਡਰ", "Favorites": "ਮਨਪਸੰਦ", - "FailedLoginAttemptWithUserName": "ਤੋਂ ਲਾਗਇਨ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ {0}", + "FailedLoginAttemptWithUserName": "{0} ਤੋਂ ਲਾਗਇਨ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ", "DeviceOnlineWithName": "{0} ਜੁੜਿਆ ਹੋਇਆ ਹੈ", "DeviceOfflineWithName": "{0} ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ", "Default": "ਡਿਫੌਲਟ", "Collections": "ਸੰਗ੍ਰਹਿਣ", - "ChapterNameValue": "ਅਧਿਆਇ {0}", + "ChapterNameValue": "ਚੈਪਟਰ {0}", "Channels": "ਚੈਨਲ", - "CameraImageUploadedFrom": "ਤੋਂ ਇੱਕ ਨਵਾਂ ਕੈਮਰਾ ਚਿੱਤਰ ਅਪਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ {0}", + "CameraImageUploadedFrom": "{0} ਤੋਂ ਇੱਕ ਨਵਾਂ ਕੈਮਰਾ ਚਿੱਤਰ ਅਪਲੋਡ ਕੀਤਾ ਗਿਆ ਹੈ", "Books": "ਕਿਤਾਬਾਂ", "AuthenticationSucceededWithUserName": "{0} ਸਫਲਤਾਪੂਰਕ ਪ੍ਰਮਾਣਿਤ", "Artists": "ਕਲਾਕਾਰ", "Application": "ਐਪਲੀਕੇਸ਼ਨ", "AppDeviceValues": "ਐਪ: {0}, ਜੰਤਰ: {1}", - "Albums": "ਐਲਬਮਾਂ" + "Albums": "ਐਲਬਮਾਂ", + "TaskOptimizeDatabase": "ਡਾਟਾਬੇਸ ਅਨੁਕੂਲ ਬਣਾਓ", + "External": "ਬਾਹਰੀ" } diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json index 92e0d34aec..2281e80c8a 100644 --- a/Emby.Server.Implementations/Localization/Core/pt.json +++ b/Emby.Server.Implementations/Localization/Core/pt.json @@ -122,5 +122,6 @@ "TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.", "External": "Externo", "HearingImpaired": "Problemas auditivos", - "TaskKeyframeExtractor": "Extrator de quadro-chave" + "TaskKeyframeExtractor": "Extrator de quadro-chave", + "TaskKeyframeExtractorDescription": "Retira frames chave do video para criar listas HLS precisas. Esta tarefa pode correr durante algum tempo." } diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index 839bbcb6d3..421513341a 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -42,7 +42,7 @@ "MusicVideos": "Муз. видео", "NameInstallFailed": "Установка {0} неудачна", "NameSeasonNumber": "Сезон {0}", - "NameSeasonUnknown": "Сезон неопознан", + "NameSeasonUnknown": "Сезон не опознан", "NewVersionIsAvailable": "Новая версия Jellyfin Server доступна для загрузки.", "NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения", "NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено", @@ -96,7 +96,7 @@ "TaskRefreshChannels": "Обновление каналов", "TaskCleanTranscode": "Очистка каталога перекодировки", "TaskUpdatePlugins": "Обновление плагинов", - "TaskRefreshPeople": "Подновление людей", + "TaskRefreshPeople": "Обновление информации о персонах", "TaskCleanLogs": "Очистка каталога журналов", "TaskRefreshLibrary": "Сканирование медиатеки", "TaskRefreshChapterImages": "Извлечение изображений сцен", diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json index cdc25ec7c7..b08119d0a6 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-HK.json +++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json @@ -5,12 +5,12 @@ "Artists": "藝人", "AuthenticationSucceededWithUserName": "{0} 授權成功", "Books": "圖書", - "CameraImageUploadedFrom": "{0} 成功上傳一張新相片", + "CameraImageUploadedFrom": "{0} 成功上傳一張新照片", "Channels": "頻道", - "ChapterNameValue": "章節 {0}", + "ChapterNameValue": "第 {0} 章", "Collections": "合輯", - "DeviceOfflineWithName": "{0} 已經斷開連接", - "DeviceOnlineWithName": "{0} 已經連接", + "DeviceOfflineWithName": "{0} 已斷開連接", + "DeviceOnlineWithName": "{0} 已連接", "FailedLoginAttemptWithUserName": "{0} 登入失敗", "Favorites": "我的最愛", "Folders": "資料夾", @@ -23,43 +23,43 @@ "HeaderFavoriteShows": "最愛的節目", "HeaderFavoriteSongs": "最愛的歌曲", "HeaderLiveTV": "電視直播", - "HeaderNextUp": "接下來", + "HeaderNextUp": "接著播放", "HeaderRecordingGroups": "錄製組", "HomeVideos": "家庭影片", "Inherit": "繼承", - "ItemAddedWithName": "{0} 已添加至媒體庫", + "ItemAddedWithName": "{0} 已被添加至媒體庫", "ItemRemovedWithName": "{0} 已從媒體庫移除", "LabelIpAddressValue": "IP 地址: {0}", "LabelRunningTimeValue": "運行時間: {0}", "Latest": "最新", - "MessageApplicationUpdated": "Jellyfin 伺服器已更新", - "MessageApplicationUpdatedTo": "Jellyfin 伺服器已更新至 {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 已更新", - "MessageServerConfigurationUpdated": "伺服器設定已經更新", + "MessageApplicationUpdated": "Jellyfin 已被更新", + "MessageApplicationUpdatedTo": "Jellyfin 已被更新至 {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 已被更新", + "MessageServerConfigurationUpdated": "伺服器設定已經被更新", "MixedContent": "混合內容", "Movies": "電影", "Music": "音樂", - "MusicVideos": "音樂影片", + "MusicVideos": "MV", "NameInstallFailed": "{0} 安裝失敗", "NameSeasonNumber": "第 {0} 季", - "NameSeasonUnknown": "未知季數", - "NewVersionIsAvailable": "新版本的 Jellyfin 伺服器可供下載。", + "NameSeasonUnknown": "未知的季度", + "NewVersionIsAvailable": "有較新版本的 Jellyfin 可供下載。", "NotificationOptionApplicationUpdateAvailable": "有可用的更新", - "NotificationOptionApplicationUpdateInstalled": "應用程式已更新", + "NotificationOptionApplicationUpdateInstalled": "應用程式已被更新", "NotificationOptionAudioPlayback": "開始播放音訊", - "NotificationOptionAudioPlaybackStopped": "已停止播放音訊", - "NotificationOptionCameraImageUploaded": "相片已上傳", + "NotificationOptionAudioPlaybackStopped": "停止播放音訊", + "NotificationOptionCameraImageUploaded": "相片已被上傳", "NotificationOptionInstallationFailed": "安裝失敗", "NotificationOptionNewLibraryContent": "已添加新内容", - "NotificationOptionPluginError": "擴充元件錯誤", - "NotificationOptionPluginInstalled": "擴充元件已安裝", - "NotificationOptionPluginUninstalled": "擴充元件已移除", - "NotificationOptionPluginUpdateInstalled": "擴充元件更新已安裝", - "NotificationOptionServerRestartRequired": "伺服器需要重啓", - "NotificationOptionTaskFailed": "計劃任務失敗", - "NotificationOptionUserLockedOut": "用家已鎖定", - "NotificationOptionVideoPlayback": "開始播放視頻", - "NotificationOptionVideoPlaybackStopped": "已停止播放視頻", + "NotificationOptionPluginError": "插件出現錯誤", + "NotificationOptionPluginInstalled": "插件已被安裝", + "NotificationOptionPluginUninstalled": "插件已被移除", + "NotificationOptionPluginUpdateInstalled": "插件已被更新", + "NotificationOptionServerRestartRequired": "伺服器需要重啟", + "NotificationOptionTaskFailed": "排程任務執行失敗", + "NotificationOptionUserLockedOut": "用戶已被鎖定", + "NotificationOptionVideoPlayback": "開始播放影片", + "NotificationOptionVideoPlaybackStopped": "已停止播放影片", "Photos": "相片", "Playlists": "播放清單", "Plugin": "插件", @@ -69,51 +69,51 @@ "ProviderValue": "提供者: {0}", "ScheduledTaskFailedWithName": "{0} 任務失敗", "ScheduledTaskStartedWithName": "{0} 任務開始", - "ServerNameNeedsToBeRestarted": "{0} 需要重啓", + "ServerNameNeedsToBeRestarted": "{0} 需要重啟", "Shows": "節目", "Songs": "歌曲", - "StartupEmbyServerIsLoading": "Jellyfin 伺服器載入中,請稍後再試。", + "StartupEmbyServerIsLoading": "Jellyfin 載入中,請稍後再試。", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的字幕", "Sync": "同步", "System": "系統", "TvShows": "電視節目", - "User": "使用者", - "UserCreatedWithName": "使用者 {0} 已創建", - "UserDeletedWithName": "使用者 {0} 已移除", + "User": "用戶", + "UserCreatedWithName": "用戶 {0} 已被建立", + "UserDeletedWithName": "用戶 {0} 已被移除", "UserDownloadingItemWithValues": "{0} 正在下載 {1}", "UserLockedOutWithName": "使用者 {0} 已被鎖定", - "UserOfflineFromDevice": "{0} 已從 {1} 斷開", - "UserOnlineFromDevice": "{0} 已連綫,來自 {1}", - "UserPasswordChangedWithName": "使用者 {0} 的密碼已變更", + "UserOfflineFromDevice": "{0} 從 {1} 斷開連接", + "UserOnlineFromDevice": "{0} 從 {1} 連線", + "UserPasswordChangedWithName": "{0} 的密碼已被變改", "UserPolicyUpdatedWithName": "使用者協議已更新為 {0}", "UserStartedPlayingItemWithValues": "{0} 正在 {2} 上播放 {1}", - "UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}", - "ValueHasBeenAddedToLibrary": "{0} 已添加到你的媒體庫", + "UserStoppedPlayingItemWithValues": "{0} 已停止在 {2} 上播放 {1}", + "ValueHasBeenAddedToLibrary": "已添加 {0} 到你的媒體庫", "ValueSpecialEpisodeName": "特典 - {0}", - "VersionNumber": "版本{0}", - "TaskDownloadMissingSubtitles": "下載遺失的字幕", + "VersionNumber": "版本 {0}", + "TaskDownloadMissingSubtitles": "下載缺少的字幕", "TaskUpdatePlugins": "更新插件", "TasksApplicationCategory": "應用程式", - "TaskRefreshLibraryDescription": "掃描媒體庫以查找新文件並刷新metadata。", + "TaskRefreshLibraryDescription": "掃描媒體庫以加入新增檔案及重新載入 metadata。", "TasksMaintenanceCategory": "維護", - "TaskDownloadMissingSubtitlesDescription": "根據metadata配置在互聯網上搜索缺少的字幕。", - "TaskRefreshChannelsDescription": "刷新互聯網頻道信息。", - "TaskRefreshChannels": "刷新頻道", + "TaskDownloadMissingSubtitlesDescription": "根據元數據中的設定,在互聯網上搜索缺少的字幕。", + "TaskRefreshChannelsDescription": "重新載入網絡頻道的資訊。", + "TaskRefreshChannels": "重新載入頻道", "TaskCleanTranscodeDescription": "刪除超過一天的轉碼文件。", "TaskCleanTranscode": "清理轉碼目錄", - "TaskUpdatePluginsDescription": "下載並安裝配置為自動更新的插件的更新。", + "TaskUpdatePluginsDescription": "下載並更新能夠被自動更新的插件。", "TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的元數據。", "TaskCleanLogsDescription": "刪除超過{0}天的日誌文件。", "TaskCleanLogs": "清理日誌目錄", "TaskRefreshLibrary": "掃描媒體庫", - "TaskRefreshChapterImagesDescription": "為帶有章節的視頻創建縮略圖。", + "TaskRefreshChapterImagesDescription": "為帶有章節的影片建立縮圖。", "TaskRefreshChapterImages": "提取章節圖像", "TaskCleanCacheDescription": "刪除系統不再需要的緩存文件。", "TaskCleanCache": "清理緩存目錄", - "TasksChannelsCategory": "互聯網頻道", + "TasksChannelsCategory": "網絡頻道", "TasksLibraryCategory": "庫", - "TaskRefreshPeople": "刷新人物", + "TaskRefreshPeople": "重新載入人物", "TaskCleanActivityLog": "清理活動記錄", "Undefined": "未定義", "Forced": "強制", @@ -121,7 +121,7 @@ "TaskOptimizeDatabaseDescription": "壓縮數據庫並截斷可用空間。在掃描媒體庫或執行其他數據庫的修改後運行此任務可能會提高性能。", "TaskOptimizeDatabase": "最佳化數據庫", "TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。", - "TaskKeyframeExtractorDescription": "提取關鍵格以創建更準確的HLS播放列表。次指示可能用時很長。", + "TaskKeyframeExtractorDescription": "提取關鍵幀以建立更準確的 HLS 播放列表。此工作或需要使用較長時間來完成。", "TaskKeyframeExtractor": "關鍵幀提取器", "External": "外部", "HearingImpaired": "聽力障礙" diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json index 4949c5ab6d..36f4df93d1 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-TW.json +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -91,14 +91,14 @@ "HeaderRecordingGroups": "錄製組", "Inherit": "繼承", "SubtitleDownloadFailureFromForItem": "無法為 {1} 從 {0} 下載字幕", - "TaskDownloadMissingSubtitlesDescription": "透過中繼資料從網路上搜尋遺失的字幕。", + "TaskDownloadMissingSubtitlesDescription": "透過媒體資訊從網路上搜尋遺失的字幕。", "TaskDownloadMissingSubtitles": "下載遺失的字幕", "TaskRefreshChannels": "重新整理頻道", "TaskUpdatePlugins": "更新附加元件", "TaskRefreshPeople": "更新人物", "TaskCleanLogsDescription": "刪除超過 {0} 天的日誌文件。", "TaskCleanLogs": "清空日誌資料夾", - "TaskRefreshLibraryDescription": "重新掃描媒體庫的新檔案並更新中繼資料。", + "TaskRefreshLibraryDescription": "重新掃描媒體庫的新檔案並更新媒體資訊。", "TaskRefreshLibrary": "重新掃描媒體庫", "TaskRefreshChapterImages": "擷取章節圖片", "TaskCleanCacheDescription": "刪除系統已不需要的快取。", @@ -108,7 +108,7 @@ "TaskCleanTranscodeDescription": "刪除超過一天的轉碼檔案。", "TaskCleanTranscode": "清除轉碼資料夾", "TaskUpdatePluginsDescription": "為已設置為自動更新的附加元件下載並安裝更新。", - "TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的中繼資料。", + "TaskRefreshPeopleDescription": "更新媒體庫中演員和導演的資訊。", "TaskRefreshChapterImagesDescription": "為有章節的影片建立縮圖。", "TasksChannelsCategory": "網路頻道", "TasksApplicationCategory": "應用程式", diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 166b71b4a3..96f4353998 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -198,25 +198,25 @@ namespace Emby.Server.Implementations.Localization } // Minimum rating possible - if (!ratings.Any(x => x.Value == 0)) + if (ratings.All(x => x.Value != 0)) { ratings.Add(new ParentalRating("Approved", 0)); } // Matches PG (this has different age restrictions depending on country) - if (!ratings.Any(x => x.Value == 10)) + if (ratings.All(x => x.Value != 10)) { ratings.Add(new ParentalRating("10", 10)); } // Matches PG-13 - if (!ratings.Any(x => x.Value == 13)) + if (ratings.All(x => x.Value != 13)) { ratings.Add(new ParentalRating("13", 13)); } // Matches TV-14 - if (!ratings.Any(x => x.Value == 14)) + if (ratings.All(x => x.Value != 14)) { ratings.Add(new ParentalRating("14", 14)); } @@ -229,13 +229,13 @@ namespace Emby.Server.Implementations.Localization } // A lot of countries don't excplicitly have a seperate rating for adult content - if (!ratings.Any(x => x.Value == 1000)) + if (ratings.All(x => x.Value != 1000)) { ratings.Add(new ParentalRating("XXX", 1000)); } // A lot of countries don't excplicitly have a seperate rating for banned content - if (!ratings.Any(x => x.Value == 1001)) + if (ratings.All(x => x.Value != 1001)) { ratings.Add(new ParentalRating("Banned", 1001)); } diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index c6a7f45464..2d2ad26d29 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -309,7 +309,7 @@ namespace Emby.Server.Implementations.Plugins // If no version is given, return the current instance. var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList(); - plugin = plugins.FirstOrDefault(p => p.Instance is not null) ?? plugins.OrderByDescending(p => p.Version).FirstOrDefault(); + plugin = plugins.FirstOrDefault(p => p.Instance is not null) ?? plugins.MaxBy(p => p.Version); } else { diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index afa3721b88..5f6dc93fb3 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -606,7 +606,7 @@ namespace Emby.Server.Implementations.Session } catch (Exception ex) { - _logger.LogDebug("Error calling OnPlaybackStopped", ex); + _logger.LogDebug(ex, "Error calling OnPlaybackStopped"); } } @@ -953,7 +953,7 @@ namespace Emby.Server.Implementations.Session } catch (Exception ex) { - _logger.LogError("Error closing live stream", ex); + _logger.LogError(ex, "Error closing live stream"); } } diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index 051fa5b3cf..cdc736950e 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -69,9 +69,7 @@ namespace Emby.Server.Implementations.Session T data, CancellationToken cancellationToken) { - var socket = GetActiveSockets() - .OrderByDescending(i => i.LastActivityDate) - .FirstOrDefault(); + var socket = GetActiveSockets().MaxBy(i => i.LastActivityDate); if (socket is null) { diff --git a/Emby.Server.Implementations/SyncPlay/Group.cs b/Emby.Server.Implementations/SyncPlay/Group.cs index 7d7ea58106..da8f949326 100644 --- a/Emby.Server.Implementations/SyncPlay/Group.cs +++ b/Emby.Server.Implementations/SyncPlay/Group.cs @@ -620,10 +620,8 @@ namespace Emby.Server.Implementations.SyncPlay RestartCurrentItem(); return true; } - else - { - return false; - } + + return false; } /// @@ -637,10 +635,8 @@ namespace Emby.Server.Implementations.SyncPlay RestartCurrentItem(); return true; } - else - { - return false; - } + + return false; } /// diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs index 63c4a15564..00c655634a 100644 --- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs +++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs @@ -339,10 +339,8 @@ namespace Emby.Server.Implementations.SyncPlay { return sessionsCounter > 0; } - else - { - return false; - } + + return false; } /// diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 42a7ac2b16..09cf7303e7 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -20,7 +20,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.MediaEncoding.Encoder; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; @@ -2030,8 +2029,7 @@ public class DynamicHlsController : BaseJellyfinApiController { return fileSystem.GetFiles(folder, new[] { segmentExtension }, true, false) .Where(i => Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase)) - .OrderByDescending(fileSystem.GetLastWriteTimeUtc) - .FirstOrDefault(); + .MaxBy(fileSystem.GetLastWriteTimeUtc); } catch (IOException) { diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index dac07429ff..d51a5325f5 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 4726cf0663..72ad14a281 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -146,7 +146,7 @@ public class PluginsController : BaseJellyfinApiController var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)).ToList(); // Select the un-instanced one first. - var plugin = plugins.FirstOrDefault(p => p.Instance is null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); + var plugin = plugins.FirstOrDefault(p => p.Instance is null) ?? plugins.MinBy(p => p.Manifest.Status); if (plugin is not null) { diff --git a/Jellyfin.Api/Controllers/QuickConnectController.cs b/Jellyfin.Api/Controllers/QuickConnectController.cs index d7e54b5b6a..14f5265aa7 100644 --- a/Jellyfin.Api/Controllers/QuickConnectController.cs +++ b/Jellyfin.Api/Controllers/QuickConnectController.cs @@ -1,8 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; -using Jellyfin.Api.Constants; -using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Authentication; diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index f638c31c39..387b3ea5a6 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -3,7 +3,6 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; -using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index e384213380..b3e9d62972 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -533,10 +533,8 @@ public class SubtitleController : BaseJellyfinApiController _logger.LogDebug("Fallback font size is {FileSize} Bytes", fileSize); return PhysicalFile(fontFile.FullName, MimeTypes.GetMimeType(fontFile.FullName)); } - else - { - _logger.LogWarning("The selected font is null or empty"); - } + + _logger.LogWarning("The selected font is null or empty"); } else { diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 12d033ae63..2e9035d24f 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Attributes; -using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.StreamingDtos; diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index f406e27a6d..a6d5252ffc 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -500,10 +500,8 @@ namespace Jellyfin.Networking.Manager { return true; } - else - { - return address.IsPrivateAddressRange(); - } + + return address.IsPrivateAddressRange(); } /// @@ -1171,13 +1169,15 @@ namespace Jellyfin.Networking.Manager bindPreference = addr.Value; break; } - else if ((addr.Key.Address.Equals(IPAddress.Any) || addr.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet) + + if ((addr.Key.Address.Equals(IPAddress.Any) || addr.Key.Address.Equals(IPAddress.IPv6Any)) && isInExternalSubnet) { // External. bindPreference = addr.Value; break; } - else if (addr.Key.Contains(source)) + + if (addr.Key.Contains(source)) { // Match ip address. bindPreference = addr.Value; @@ -1256,8 +1256,7 @@ namespace Jellyfin.Networking.Manager // Look for the best internal address. bindAddress = addresses .Where(p => IsInLocalNetwork(p) && (p.Contains(source) || p.Equals(IPAddress.None))) - .OrderBy(p => p.Tag) - .FirstOrDefault()?.Address; + .MinBy(p => p.Tag)?.Address; } if (bindAddress is not null) diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 63d3e8a04c..700e639700 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Net; using System.Threading.Tasks; -using EFCoreSecondLevelCacheInterceptor; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 40cd5a0446..939376dd8d 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -22,7 +22,6 @@ using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Activity; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index 7c4ffdbc00..8fe2b087d9 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -133,9 +133,7 @@ namespace Jellyfin.Server.Migrations.Routines SkipBackwardLength = dto.CustomPrefs.TryGetValue("skipBackLength", out length) && int.TryParse(length, out var skipBackwardLength) ? skipBackwardLength : 10000, - EnableNextVideoInfoOverlay = dto.CustomPrefs.TryGetValue("enableNextVideoInfoOverlay", out var enabled) && !string.IsNullOrEmpty(enabled) - ? bool.Parse(enabled) - : true, + EnableNextVideoInfoOverlay = !dto.CustomPrefs.TryGetValue("enableNextVideoInfoOverlay", out var enabled) || string.IsNullOrEmpty(enabled) || bool.Parse(enabled), DashboardTheme = dto.CustomPrefs.TryGetValue("dashboardtheme", out var theme) ? theme : string.Empty, TvHome = dto.CustomPrefs.TryGetValue("tvhome", out var home) ? home : string.Empty }; diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 155f9fc8c1..56f5c4796e 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -4,7 +4,6 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Mime; -using System.Runtime.InteropServices; using System.Text; using Jellyfin.Api.Middleware; using Jellyfin.MediaEncoding.Hls.Extensions; diff --git a/Jellyfin.sln.DotSettings b/Jellyfin.sln.DotSettings index b567416480..2ef037485c 100644 --- a/Jellyfin.sln.DotSettings +++ b/Jellyfin.sln.DotSettings @@ -1,3 +1,4 @@  + True True True \ No newline at end of file diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index 152fa8b4a2..116e9cef80 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Common.Plugins if (Version is not null && !Directory.Exists(dataFolderPath)) { // Try again with the version number appended to the folder name. - dataFolderPath += "_" + Version.ToString(); + dataFolderPath += "_" + Version; } SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a04f02bf91..adc7b2f953 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -801,16 +801,14 @@ namespace MediaBrowser.Controller.Entities { return allowed.Contains(ChannelId); } - else - { - var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders); - foreach (var folder in collectionFolders) + var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders); + + foreach (var folder in collectionFolders) + { + if (allowed.Contains(folder.Id)) { - if (allowed.Contains(folder.Id)) - { - return true; - } + return true; } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 514323238e..c721fb7785 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -197,10 +197,8 @@ namespace MediaBrowser.Controller.LiveTv { return 2.0 / 3; } - else - { - return 16.0 / 9; - } + + return 16.0 / 9; } public override string GetClientTypeName() diff --git a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs index 6091ede52a..c4f0334892 100644 --- a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs +++ b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs @@ -1,5 +1,3 @@ -using System; - namespace MediaBrowser.Controller.Lyrics; /// diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index f7ee3c1732..53f48d9598 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -138,14 +138,10 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.IsNullOrEmpty(hwType) && encodingOptions.EnableHardwareEncoding - && codecMap.ContainsKey(hwType)) + && codecMap.TryGetValue(hwType, out var preferredEncoder) + && _mediaEncoder.SupportsEncoder(preferredEncoder)) { - var preferredEncoder = codecMap[hwType]; - - if (_mediaEncoder.SupportsEncoder(preferredEncoder)) - { - return preferredEncoder; - } + return preferredEncoder; } } @@ -561,7 +557,8 @@ namespace MediaBrowser.Controller.MediaEncoding { return Array.FindIndex(_videoProfilesH264, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase)); } - else if (string.Equals("hevc", videoCodec, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals("hevc", videoCodec, StringComparison.OrdinalIgnoreCase)) { return Array.FindIndex(_videoProfilesH265, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase)); } @@ -842,39 +839,38 @@ namespace MediaBrowser.Controller.MediaEncoding } var filterDevArgs = GetFilterHwDeviceArgs(VaapiAlias); + var doOclTonemap = isHwTonemapAvailable && IsOpenclFullSupported(); - if (isHwTonemapAvailable && IsOpenclFullSupported()) + if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965) { - if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965) + if (doOclTonemap && !isVaapiDecoder) { - if (!isVaapiDecoder) - { - args.Append(GetOpenclDeviceArgs(0, null, VaapiAlias, OpenclAlias)); - filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); - } - } - else if (_mediaEncoder.IsVaapiDeviceAmd) - { - if (!IsVulkanFullSupported() - || !_mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier - || Environment.OSVersion.Version < _minKernelVersionAmdVkFmtModifier) - { - args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias)); - filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); - } - else - { - // libplacebo wants an explicitly set vulkan filter device. - args.Append(GetVulkanDeviceArgs(0, null, VaapiAlias, VulkanAlias)); - filterDevArgs = GetFilterHwDeviceArgs(VulkanAlias); - } - } - else - { - args.Append(GetOpenclDeviceArgs(0, null, null, OpenclAlias)); + args.Append(GetOpenclDeviceArgs(0, null, VaapiAlias, OpenclAlias)); filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); } } + else if (_mediaEncoder.IsVaapiDeviceAmd) + { + if (IsVulkanFullSupported() + && _mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier + && Environment.OSVersion.Version >= _minKernelVersionAmdVkFmtModifier) + { + // libplacebo wants an explicitly set vulkan filter device. + args.Append(GetVulkanDeviceArgs(0, null, VaapiAlias, VulkanAlias)); + filterDevArgs = GetFilterHwDeviceArgs(VulkanAlias); + } + else if (doOclTonemap) + { + // ROCm/ROCr OpenCL runtime + args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias)); + filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); + } + } + else if (doOclTonemap) + { + args.Append(GetOpenclDeviceArgs(0, null, null, OpenclAlias)); + filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); + } args.Append(filterDevArgs); } @@ -1114,19 +1110,19 @@ namespace MediaBrowser.Controller.MediaEncoding { return "-bsf:v h264_mp4toannexb"; } - else if (IsH265(stream)) + + if (IsH265(stream)) { return "-bsf:v hevc_mp4toannexb"; } - else if (IsAAC(stream)) + + if (IsAAC(stream)) { // Convert adts header(mpegts) to asc header(mp4). return "-bsf:a aac_adtstoasc"; } - else - { - return null; - } + + return null; } public static string GetAudioBitStreamArguments(EncodingJobInfo state, string segmentContainer, string mediaSourceContainer) @@ -1204,10 +1200,8 @@ namespace MediaBrowser.Controller.MediaEncoding { return FormattableString.Invariant($" -rc_mode CBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); } - else - { - return FormattableString.Invariant($" -rc_mode VBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); - } + + return FormattableString.Invariant($" -rc_mode VBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); } return FormattableString.Invariant($" -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); @@ -2619,8 +2613,8 @@ namespace MediaBrowser.Controller.MediaEncoding if (outputWidth > maximumWidth || outputHeight > maximumHeight) { - var scaleW = (double)maximumWidth / (double)outputWidth; - var scaleH = (double)maximumHeight / (double)outputHeight; + var scaleW = (double)maximumWidth / outputWidth; + var scaleH = (double)maximumHeight / outputHeight; var scale = Math.Min(scaleW, scaleH); outputWidth = Math.Min(maximumWidth, (int)(outputWidth * scale)); outputHeight = Math.Min(maximumHeight, (int)(outputHeight * scale)); @@ -2767,79 +2761,76 @@ namespace MediaBrowser.Controller.MediaEncoding widthParam, heightParam); } - else - { - return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, requestedHeight.Value); - } + + return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, requestedHeight.Value); } // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size - else if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue) + + if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue) { var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); return string.Format( - CultureInfo.InvariantCulture, - "scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2", - maxWidthParam, - maxHeightParam, - scaleVal); + CultureInfo.InvariantCulture, + "scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2", + maxWidthParam, + maxHeightParam, + scaleVal); } // If a fixed width was requested - else if (requestedWidth.HasValue) + if (requestedWidth.HasValue) { if (threedFormat.HasValue) { // This method can handle 0 being passed in for the requested height return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, 0); } - else - { - var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture); - return string.Format( - CultureInfo.InvariantCulture, - "scale={0}:trunc(ow/a/2)*2", - widthParam); - } + var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture); + + return string.Format( + CultureInfo.InvariantCulture, + "scale={0}:trunc(ow/a/2)*2", + widthParam); } // If a fixed height was requested - else if (requestedHeight.HasValue) + if (requestedHeight.HasValue) { var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture); return string.Format( - CultureInfo.InvariantCulture, - "scale=trunc(oh*a/{1})*{1}:{0}", - heightParam, - scaleVal); + CultureInfo.InvariantCulture, + "scale=trunc(oh*a/{1})*{1}:{0}", + heightParam, + scaleVal); } // If a max width was requested - else if (requestedMaxWidth.HasValue) + if (requestedMaxWidth.HasValue) { var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); return string.Format( - CultureInfo.InvariantCulture, - "scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2", - maxWidthParam, - scaleVal); + CultureInfo.InvariantCulture, + "scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2", + maxWidthParam, + scaleVal); } // If a max height was requested - else if (requestedMaxHeight.HasValue) + if (requestedMaxHeight.HasValue) { var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); return string.Format( - CultureInfo.InvariantCulture, - "scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})", - maxHeightParam, - scaleVal); + CultureInfo.InvariantCulture, + "scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})", + maxHeightParam, + scaleVal); } return string.Empty; @@ -2913,18 +2904,21 @@ namespace MediaBrowser.Controller.MediaEncoding "yadif_cuda={0}:-1:0", doubleRateDeint ? "1" : "0"); } - else if (hwDeintSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase)) + + if (hwDeintSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase)) { return string.Format( CultureInfo.InvariantCulture, "deinterlace_vaapi=rate={0}", doubleRateDeint ? "field" : "frame"); } - else if (hwDeintSuffix.Contains("qsv", StringComparison.OrdinalIgnoreCase)) + + if (hwDeintSuffix.Contains("qsv", StringComparison.OrdinalIgnoreCase)) { return "deinterlace_qsv=mode=2"; } - else if (hwDeintSuffix.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase)) + + if (hwDeintSuffix.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase)) { return string.Format( CultureInfo.InvariantCulture, @@ -2955,7 +2949,8 @@ namespace MediaBrowser.Controller.MediaEncoding options.VppTonemappingBrightness, options.VppTonemappingContrast); } - else if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase)) { args = "libplacebo=format={1}:tonemapping={2}:color_primaries=bt709:color_trc=bt709:colorspace=bt709:peak_detect=0:upscaler=none:downscaler=none"; @@ -4269,7 +4264,8 @@ namespace MediaBrowser.Controller.MediaEncoding // sw => hw if (doVkTonemap) { - mainFilters.Add("hwupload_vaapi"); + mainFilters.Add("hwupload=derive_device=vaapi"); + mainFilters.Add("format=vaapi"); mainFilters.Add("hwmap=derive_device=vulkan"); mainFilters.Add("format=vulkan"); } @@ -4380,12 +4376,15 @@ namespace MediaBrowser.Controller.MediaEncoding // prefer vaapi hwupload to vulkan hwupload, // Mesa RADV does not support a dedicated transfer queue. - subFilters.Add("hwupload_vaapi"); + subFilters.Add("hwupload=derive_device=vaapi"); + subFilters.Add("format=vaapi"); subFilters.Add("hwmap=derive_device=vulkan"); subFilters.Add("format=vulkan"); overlayFilters.Add("overlay_vulkan=eof_action=endall:shortest=1:repeatlast=0"); - overlayFilters.Add("scale_vulkan=format=nv12"); + + // TODO: figure out why libplacebo can sync without vaSyncSurface VPP support in radeonsi. + overlayFilters.Add("libplacebo=format=nv12:apply_filmgrain=0:apply_dolbyvision=0:upscaler=none:downscaler=none:dithering=none"); // OUTPUT vaapi(nv12/bgra) surface(vram) // reverse-mapping via vaapi-vulkan interop. @@ -4827,26 +4826,27 @@ namespace MediaBrowser.Controller.MediaEncoding { return videoStream.BitDepth.Value; } - else if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase)) { return 8; } - else if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase)) { return 10; } - else if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase)) { return 12; } - else - { - return 8; - } + + return 8; } return 0; @@ -5078,11 +5078,9 @@ namespace MediaBrowser.Controller.MediaEncoding return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty) + (nvdecNoInternalCopy ? " -hwaccel_flags +unsafe_output" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty); } - else - { - // cuvid decoder doesn't have threading issue. - return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty); - } + + // cuvid decoder doesn't have threading issue. + return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty); } } @@ -5440,7 +5438,8 @@ namespace MediaBrowser.Controller.MediaEncoding // Automatically set thread count return mustSetThreadCount ? Math.Max(Environment.ProcessorCount - 1, 1) : 0; } - else if (threads >= Environment.ProcessorCount) + + if (threads >= Environment.ProcessorCount) { return Environment.ProcessorCount; } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index eefc5d222e..0c4719a0e5 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities.Security; -using Jellyfin.Data.Events; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Session; diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs index b86e482435..fcfc18a644 100644 --- a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs +++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs @@ -1,7 +1,6 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs index 2164945560..dcc06db1ed 100644 --- a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs +++ b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs @@ -533,11 +533,9 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates _logger.LogWarning("Session {SessionId} is seeking to wrong position, correcting.", session.Id); return; } - else - { - // Session is ready. - context.SetBuffering(session, false); - } + + // Session is ready. + context.SetBuffering(session, false); if (!context.IsBuffering()) { diff --git a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs index ddbfeb8de8..bdebbbfd49 100644 --- a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs +++ b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs @@ -313,17 +313,13 @@ namespace MediaBrowser.Controller.SyncPlay.Queue return true; } - else - { - // Restoring playing item. - SetPlayingItemByPlaylistId(playingItem.PlaylistItemId); - return false; - } - } - else - { + + // Restoring playing item. + SetPlayingItemByPlaylistId(playingItem.PlaylistItemId); return false; } + + return false; } /// @@ -528,10 +524,8 @@ namespace MediaBrowser.Controller.SyncPlay.Queue { return _shuffledPlaylist; } - else - { - return _sortedPlaylist; - } + + return _sortedPlaylist; } /// @@ -544,14 +538,13 @@ namespace MediaBrowser.Controller.SyncPlay.Queue { return null; } - else if (ShuffleMode.Equals(GroupShuffleMode.Shuffle)) + + if (ShuffleMode.Equals(GroupShuffleMode.Shuffle)) { return _shuffledPlaylist[PlayingItemIndex]; } - else - { - return _sortedPlaylist[PlayingItemIndex]; - } + + return _sortedPlaylist[PlayingItemIndex]; } } } diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 7eab00be4d..cb369d8377 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -73,10 +73,7 @@ namespace MediaBrowser.LocalMetadata.Parsers foreach (var info in idInfos) { var id = info.Key + "Id"; - if (!_validProviderIds.ContainsKey(id)) - { - _validProviderIds.Add(id, info.Key); - } + _validProviderIds.TryAdd(id, info.Key); } // Additional Mappings diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index a6fcdb9e17..f913b2320d 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -375,7 +375,7 @@ namespace MediaBrowser.LocalMetadata.Savers await writer.WriteStartElementAsync(null, "Person", null).ConfigureAwait(false); await writer.WriteElementStringAsync(null, "Name", null, person.Name).ConfigureAwait(false); await writer.WriteElementStringAsync(null, "Type", null, person.Type.ToString()).ConfigureAwait(false); - await writer.WriteElementStringAsync(null, "Role", null, person.Role.ToString()).ConfigureAwait(false); + await writer.WriteElementStringAsync(null, "Role", null, person.Role).ConfigureAwait(false); if (person.SortOrder.HasValue) { diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 80091bf5a8..989e386a51 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -231,10 +231,8 @@ namespace MediaBrowser.MediaEncoding.Attachments throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath)); } - else - { - _logger.LogInformation("ffmpeg attachment extraction completed for {Path} to {Path}", inputPath, outputPath); - } + + _logger.LogInformation("ffmpeg attachment extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath); } private async Task GetAttachmentStream( @@ -376,10 +374,8 @@ namespace MediaBrowser.MediaEncoding.Attachments throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath)); } - else - { - _logger.LogInformation("ffmpeg attachment extraction completed for {Path} to {Path}", inputPath, outputPath); - } + + _logger.LogInformation("ffmpeg attachment extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath); } private string GetAttachmentCachePath(string mediaPath, MediaSourceInfo mediaSource, int attachmentStreamIndex) diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index ea520b1d6b..fca17d4c05 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using BDInfo.IO; @@ -105,7 +104,7 @@ public class BdInfoDirectoryInfo : IDirectoryInfo _impl.FullName, new[] { searchPattern }, false, - (searchOption & SearchOption.AllDirectories) == SearchOption.AllDirectories) + searchOption == SearchOption.AllDirectories) .Select(x => new BdInfoFileInfo(x)) .ToArray(); } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 3980353d15..d3843796f7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -217,12 +217,14 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - else if (version < MinVersion) // Version is below what we recommend + + if (version < MinVersion) // Version is below what we recommend { _logger.LogWarning("FFmpeg validation: The minimum recommended version is {MinVersion}", MinVersion); return false; } - else if (MaxVersion is not null && version > MaxVersion) // Version is above what we recommend + + if (MaxVersion is not null && version > MaxVersion) // Version is above what we recommend { _logger.LogWarning("FFmpeg validation: The maximum recommended version is {MaxVersion}", MaxVersion); return false; @@ -491,7 +493,6 @@ namespace MediaBrowser.MediaEncoding.Encoder var found = Regex .Matches(output, @"^\s\S{6}\s(?[\w|-]+)\s+.+$", RegexOptions.Multiline) - .Cast() .Select(x => x.Groups["codec"].Value) .Where(x => required.Contains(x)); @@ -520,7 +521,6 @@ namespace MediaBrowser.MediaEncoding.Encoder var found = Regex .Matches(output, @"^\s\S{3}\s(?[\w|-]+)\s+.+$", RegexOptions.Multiline) - .Cast() .Select(x => x.Groups["filter"].Value) .Where(x => _requiredFilters.Contains(x)); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 90bc491322..794906c3b4 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -449,7 +449,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { try { - _logger.LogInformation("Deleting converted subtitle due to failure: ", outputPath); + _logger.LogInformation("Deleting converted subtitle due to failure: {Path}", outputPath); _fileSystem.DeleteFile(outputPath); } catch (IOException ex) @@ -624,10 +624,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new FfmpegException( string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle extraction failed for {0} to {1}", inputPath, outputPath)); } - else - { - _logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath); - } + + _logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath); if (string.Equals(outputCodec, "ass", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 7cb07a2f7a..07f02d1879 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -2,7 +2,6 @@ #pragma warning disable CA1819 using System; -using System.Collections.Generic; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Updates; diff --git a/MediaBrowser.Model/Cryptography/PasswordHash.cs b/MediaBrowser.Model/Cryptography/PasswordHash.cs index 80a30684ab..ccb361c132 100644 --- a/MediaBrowser.Model/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Model/Cryptography/PasswordHash.cs @@ -80,7 +80,8 @@ namespace MediaBrowser.Model.Cryptography { throw new FormatException("Hash string must contain a valid id"); } - else if (nextSegment == -1) + + if (nextSegment == -1) { return new PasswordHash(hashString.ToString(), Array.Empty()); } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index db892a22c6..df185e40c5 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1075,31 +1075,38 @@ namespace MediaBrowser.Model.Dlna { return 128000; } - else if (totalBitrate <= 2000000) + + if (totalBitrate <= 2000000) { return 384000; } - else if (totalBitrate <= 3000000) + + if (totalBitrate <= 3000000) { return 448000; } - else if (totalBitrate <= 4000000) + + if (totalBitrate <= 4000000) { return 640000; } - else if (totalBitrate <= 5000000) + + if (totalBitrate <= 5000000) { return 768000; } - else if (totalBitrate <= 10000000) + + if (totalBitrate <= 10000000) { return 1536000; } - else if (totalBitrate <= 15000000) + + if (totalBitrate <= 15000000) { return 2304000; } - else if (totalBitrate <= 20000000) + + if (totalBitrate <= 20000000) { return 3584000; } @@ -1443,7 +1450,8 @@ namespace MediaBrowser.Model.Dlna { return false; } - else if (ContainerProfile.ContainsContainer(normalizedContainers, "mkv") + + if (ContainerProfile.ContainsContainer(normalizedContainers, "mkv") || ContainerProfile.ContainsContainer(normalizedContainers, "matroska")) { return true; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 886b64a248..a78a28e13a 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -430,7 +430,7 @@ namespace MediaBrowser.Model.Dlna return totalBitrate.HasValue ? Convert.ToInt64(totalBitrate.Value * totalSeconds) : - (long?)null; + null; } return null; diff --git a/MediaBrowser.Model/MediaInfo/AudioCodec.cs b/MediaBrowser.Model/MediaInfo/AudioCodec.cs index 7b83b1b9df..4c22af4498 100644 --- a/MediaBrowser.Model/MediaInfo/AudioCodec.cs +++ b/MediaBrowser.Model/MediaInfo/AudioCodec.cs @@ -17,11 +17,13 @@ namespace MediaBrowser.Model.MediaInfo { return "Dolby Digital"; } - else if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) { return "Dolby Digital+"; } - else if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase)) { return "DTS"; } diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index 96a9e9dcf3..a9099d1927 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index ebd653e349..bcc9b809c2 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -882,10 +882,7 @@ namespace MediaBrowser.Providers.Manager var key = providerId.Key; // Don't replace existing Id's. - if (!lookupInfo.ProviderIds.ContainsKey(key)) - { - lookupInfo.ProviderIds[key] = providerId.Value; - } + lookupInfo.ProviderIds.TryAdd(key, providerId.Value); } } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index d8122511ee..1028da32ba 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -780,10 +780,7 @@ namespace MediaBrowser.Providers.Manager { foreach (var providerId in result.ProviderIds) { - if (!existingMatch.ProviderIds.ContainsKey(providerId.Key)) - { - existingMatch.ProviderIds.Add(providerId.Key, providerId.Value); - } + existingMatch.ProviderIds.TryAdd(providerId.Key, providerId.Value); } if (string.IsNullOrWhiteSpace(existingMatch.ImageUrl)) diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 111d0c5cbc..5b68924acb 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -100,10 +100,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers foreach (var info in idInfos) { var id = info.Key + "Id"; - if (!_validProviderIds.ContainsKey(id)) - { - _validProviderIds.Add(id, info.Key); - } + _validProviderIds.TryAdd(id, info.Key); } // Additional Mappings diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index 6b6c13d996..1949a9df33 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -221,10 +221,8 @@ namespace Rssdp.Infrastructure { return trimmedSegment.Substring(1, trimmedSegment.Length - 2); } - else - { - return trimmedSegment; - } + + return trimmedSegment; } } } diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index a3e100796d..a1b4627a93 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -64,8 +64,7 @@ namespace Rssdp.Infrastructure } message.Method = new HttpMethod(parts[0].Trim()); - Uri requestUri; - if (Uri.TryCreate(parts[1].Trim(), UriKind.RelativeOrAbsolute, out requestUri)) + if (Uri.TryCreate(parts[1].Trim(), UriKind.RelativeOrAbsolute, out var requestUri)) { message.RequestUri = requestUri; } diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs index 3e361465d7..71b7a7b990 100644 --- a/RSSDP/HttpResponseParser.cs +++ b/RSSDP/HttpResponseParser.cs @@ -77,8 +77,7 @@ namespace Rssdp.Infrastructure message.Version = ParseHttpVersion(parts[0].Trim()); - int statusCode = -1; - if (!Int32.TryParse(parts[1].Trim(), out statusCode)) + if (!Int32.TryParse(parts[1].Trim(), out var statusCode)) { throw new ArgumentException("data status line is invalid. Status code is not a valid integer.", nameof(data)); } diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index c826830f1d..3e4261b6a9 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -171,10 +171,8 @@ namespace Rssdp { return "uuid:" + this.Uuid; } - else - { - return _Udn; - } + + return _Udn; } set diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index 681ef0a5c1..7afd325819 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -483,8 +483,7 @@ namespace Rssdp.Infrastructure } } - Uri retVal; - Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out retVal); + Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out var retVal); return retVal; } @@ -501,8 +500,7 @@ namespace Rssdp.Infrastructure } } - Uri retVal; - Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out retVal); + Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out var retVal); return retVal; } @@ -587,10 +585,8 @@ namespace Rssdp.Infrastructure { return OneSecond; } - else - { - return searchWaitTime.Subtract(OneSecond); - } + + return searchWaitTime.Subtract(OneSecond); } private DiscoveredSsdpDevice FindExistingDeviceNotification(IEnumerable devices, string notificationType, string usn) diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index a7767b3c04..be66f5947d 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -244,7 +244,6 @@ namespace Rssdp.Infrastructure // Wait on random interval up to MX, as per SSDP spec. // Also, as per UPnP 1.1/SSDP spec ignore missing/bank MX header. If over 120, assume random value between 0 and 120. // Using 16 as minimum as that's often the minimum system clock frequency anyway. - int maxWaitInterval = 0; if (String.IsNullOrEmpty(mx)) { // Windows Explorer is poorly behaved and doesn't supply an MX header value. @@ -254,7 +253,7 @@ namespace Rssdp.Infrastructure // return; } - if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0) + if (!Int32.TryParse(mx, out var maxWaitInterval) || maxWaitInterval <= 0) { return; } @@ -572,17 +571,14 @@ namespace Rssdp.Infrastructure { return nonzeroCacheLifetimesQuery.Min(); } - else - { - return TimeSpan.Zero; - } + + return TimeSpan.Zero; } private string GetFirstHeaderValue(System.Net.Http.Headers.HttpRequestHeaders httpRequestHeaders, string headerName) { string retVal = null; - IEnumerable values = null; - if (httpRequestHeaders.TryGetValues(headerName, out values) && values != null) + if (httpRequestHeaders.TryGetValues(headerName, out var values) && values != null) { retVal = values.FirstOrDefault(); } @@ -644,7 +640,7 @@ namespace Rssdp.Infrastructure public string Key { - get { return this.SearchTarget + ":" + this.EndPoint.ToString(); } + get { return this.SearchTarget + ":" + this.EndPoint; } } public bool IsOld() diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 36435194ff..16bb99a3d0 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index c8943a3993..275b379b3d 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget make # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 7b9a3de4e3..b440a21421 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -17,7 +17,7 @@ RUN apt-get update -yqq \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 32695e3f12..f195d70045 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 8ffbeafade..0fb59d5ca1 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/bda88810-e1a6-4cf0-8139-7fd7fe7b2c7a/7a9ffa3e12e5f1c3d8b640e326c1eb14/dotnet-sdk-7.0.202-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/ebfd0bf8-79bd-480a-9e81-0b217463738d/9adc6bf0614ce02670101e278a2d8555/dotnet-sdk-7.0.203-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 6da77ad959..2d980db181 100644 --- a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -120,8 +120,18 @@ public class SkiaEncoder : IImageEncoder if (extension.Equals(".svg", StringComparison.OrdinalIgnoreCase)) { var svg = new SKSvg(); - svg.Load(path); - return new ImageDimensions(Convert.ToInt32(svg.Picture.CullRect.Width), Convert.ToInt32(svg.Picture.CullRect.Height)); + try + { + svg.Load(path); + return new ImageDimensions(Convert.ToInt32(svg.Picture.CullRect.Width), Convert.ToInt32(svg.Picture.CullRect.Height)); + } + catch (FormatException skiaColorException) + { + // This exception is known to be thrown on vector images that define custom styles + // Skia SVG is not able to handle that and as the repository is quite stale and has not received updates we just catch them + _logger.LogDebug(skiaColorException, "There was a issue loading the requested svg file"); + return default; + } } using var codec = SKCodec.Create(path, out SKCodecResult result); @@ -132,10 +142,10 @@ public class SkiaEncoder : IImageEncoder return new ImageDimensions(info.Width, info.Height); case SKCodecResult.Unimplemented: _logger.LogDebug("Image format not supported: {FilePath}", path); - return new ImageDimensions(0, 0); + return default; default: _logger.LogError("Unable to determine image dimensions for {FilePath}: {SkCodecResult}", path, result); - return new ImageDimensions(0, 0); + return default; } } diff --git a/src/Jellyfin.Extensions/AlphanumericComparator.cs b/src/Jellyfin.Extensions/AlphanumericComparator.cs index 6e451d40e9..299e2f94ae 100644 --- a/src/Jellyfin.Extensions/AlphanumericComparator.cs +++ b/src/Jellyfin.Extensions/AlphanumericComparator.cs @@ -20,11 +20,13 @@ namespace Jellyfin.Extensions { return 0; } - else if (s1 is null) + + if (s1 is null) { return -1; } - else if (s2 is null) + + if (s2 is null) { return 1; } @@ -37,11 +39,13 @@ namespace Jellyfin.Extensions { return 0; } - else if (len1 == 0) + + if (len1 == 0) { return -1; } - else if (len2 == 0) + + if (len2 == 0) { return 1; } @@ -82,7 +86,8 @@ namespace Jellyfin.Extensions { return -1; } - else if (span1Len > span2Len) + + if (span1Len > span2Len) { return 1; } diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs index 2936fe4d6d..6895eadb86 100644 --- a/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonBoolStringConverter.cs @@ -1,7 +1,6 @@ using System; using System.Buffers; using System.Buffers.Text; -using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs index 7c61248757..b22eb7c4ea 100644 --- a/src/Jellyfin.Extensions/StringExtensions.cs +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Globalization; -using System.Text; using System.Text.RegularExpressions; namespace Jellyfin.Extensions diff --git a/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs index 6669a6689c..1ea1797ba1 100644 --- a/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupPolicy/FirstTimeSetupHandlerTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using AutoFixture; using AutoFixture.AutoMoq; -using Jellyfin.Api.Auth.DefaultAuthorizationPolicy; using Jellyfin.Api.Auth.FirstTimeSetupPolicy; using Jellyfin.Api.Constants; using MediaBrowser.Common.Configuration; diff --git a/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs b/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs index d6428fb2cd..0254a1ec6e 100644 --- a/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs +++ b/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs @@ -1,4 +1,3 @@ -using System; using Jellyfin.Api.Controllers; using Xunit; diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs index f05a0152e0..c30dad6f90 100644 --- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs +++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs @@ -162,7 +162,7 @@ namespace Jellyfin.Model.Tests [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] - public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "") + public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "") { var options = await GetMediaOptions(deviceName, mediaSource); BuildVideoItemSimpleTest(options, playMethod, why, transcodeMode, transcodeProtocol); @@ -260,7 +260,7 @@ namespace Jellyfin.Model.Tests [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] - public async Task BuildVideoItemWithFirstExplicitStream(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "") + public async Task BuildVideoItemWithFirstExplicitStream(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "") { var options = await GetMediaOptions(deviceName, mediaSource); options.AudioStreamIndex = 1; @@ -296,7 +296,7 @@ namespace Jellyfin.Model.Tests // Tizen 4 4K 5.1 [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] - public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "") + public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "") { var options = await GetMediaOptions(deviceName, mediaSource); var streamCount = options.MediaSources[0].MediaStreams.Count; diff --git a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs index e18faa422d..ec4df9981c 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs @@ -238,9 +238,6 @@ namespace Jellyfin.Providers.Tests.Manager } }; - object? result; - List actual; - // overwrite provider id var overwriteNewValue = new List { @@ -249,9 +246,9 @@ namespace Jellyfin.Providers.Tests.Manager Name = "Name 2" } }; - Assert.False(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, null, false, out result)); + Assert.False(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, null, false, out var result)); // People not already in target are not merged into it from source - actual = (List)result!; + List actual = (List)result!; Assert.Single(actual); Assert.Equal("Name 1", actual[0].Name); diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs index 542324e78b..f680d2dcc5 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs @@ -90,7 +90,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers }; _parser.Fetch(result, path, CancellationToken.None); - var item = (Series)result.Item; + var item = result.Item; Assert.Equal(id, item.ProviderIds[provider]); }