diff options
59 files changed, 229 insertions, 153 deletions
diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index dd484d564..58fa62ec9 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-ef": { - "version": "9.0.0", + "version": "9.0.1", "commands": [ "dotnet-ef" ] diff --git a/.github/workflows/ci-codeql-analysis.yml b/.github/workflows/ci-codeql-analysis.yml index e35396936..a5c4667ec 100644 --- a/.github/workflows/ci-codeql-analysis.yml +++ b/.github/workflows/ci-codeql-analysis.yml @@ -22,16 +22,16 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup .NET - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 with: dotnet-version: '9.0.x' - name: Initialize CodeQL - uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/init@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 with: languages: ${{ matrix.language }} queries: +security-extended - name: Autobuild - uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/autobuild@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/analyze@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 diff --git a/.github/workflows/ci-compat.yml b/.github/workflows/ci-compat.yml index 2f9a68f41..3372d73ce 100644 --- a/.github/workflows/ci-compat.yml +++ b/.github/workflows/ci-compat.yml @@ -17,7 +17,7 @@ jobs: repository: ${{ github.event.pull_request.head.repo.full_name }} - name: Setup .NET - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 with: dotnet-version: '9.0.x' @@ -26,7 +26,7 @@ jobs: dotnet build Jellyfin.Server -o ./out - name: Upload Head - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: abi-head retention-days: 14 @@ -47,7 +47,7 @@ jobs: fetch-depth: 0 - name: Setup .NET - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 with: dotnet-version: '9.0.x' @@ -65,7 +65,7 @@ jobs: dotnet build Jellyfin.Server -o ./out - name: Upload Head - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: abi-base retention-days: 14 diff --git a/.github/workflows/ci-openapi.yml b/.github/workflows/ci-openapi.yml index 25b4b9f81..b4d5fa962 100644 --- a/.github/workflows/ci-openapi.yml +++ b/.github/workflows/ci-openapi.yml @@ -21,13 +21,13 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} repository: ${{ github.event.pull_request.head.repo.full_name }} - name: Setup .NET - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 with: dotnet-version: '9.0.x' - name: Generate openapi.json run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - name: Upload openapi.json - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: openapi-head retention-days: 14 @@ -55,13 +55,13 @@ jobs: ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF) git checkout --progress --force $ANCESTOR_REF - name: Setup .NET - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 with: dotnet-version: '9.0.x' - name: Generate openapi.json run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - name: Upload openapi.json - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: openapi-base retention-days: 14 diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 30aacc7a0..8f9f605c3 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 + - uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 with: dotnet-version: ${{ env.SDK_VERSION }} @@ -34,7 +34,7 @@ jobs: --verbosity minimal - name: Merge code coverage results - uses: danielpalme/ReportGenerator-GitHub-Action@810356ce07a94200154301fb73d878e327b2dd58 # v5.4.1 + uses: danielpalme/ReportGenerator-GitHub-Action@c38c522d4b391c1b0da979cbb2e902c0a252a7dc # v5.4.3 with: reports: "**/coverage.cobertura.xml" targetdir: "merged/" diff --git a/.github/workflows/issue-stale.yml b/.github/workflows/issue-stale.yml index 5a1ca9f7a..624ea564f 100644 --- a/.github/workflows/issue-stale.yml +++ b/.github/workflows/issue-stale.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest if: ${{ contains(github.repository, 'jellyfin/') }} steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 with: repo-token: ${{ secrets.JF_BOT_TOKEN }} ascending: true diff --git a/.github/workflows/pull-request-conflict.yml b/.github/workflows/pull-request-conflict.yml index 5d342b7f8..411ebf829 100644 --- a/.github/workflows/pull-request-conflict.yml +++ b/.github/workflows/pull-request-conflict.yml @@ -15,7 +15,7 @@ jobs: if: ${{ github.repository == 'jellyfin/jellyfin' }} steps: - name: Apply label - uses: eps1lon/actions-label-merge-conflict@1b1b1fcde06a9b3d089f3464c96417961dde1168 # v3.0.2 + uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3 if: ${{ github.event_name == 'push' || github.event_name == 'pull_request_target'}} with: dirtyLabel: 'merge conflict' diff --git a/.github/workflows/pull-request-stale.yaml b/.github/workflows/pull-request-stale.yaml index d01b3f4a1..7ce5b0fa6 100644 --- a/.github/workflows/pull-request-stale.yaml +++ b/.github/workflows/pull-request-stale.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest if: ${{ contains(github.repository, 'jellyfin/') }} steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 with: repo-token: ${{ secrets.JF_BOT_TOKEN }} ascending: true diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index eccc3b0ce..ae1a2fd71 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -268,3 +268,4 @@ - [0x25CBFC4F](https://github.com/0x25CBFC4F) - [Robert Lützner](https://github.com/rluetzner) - [Nathan McCrina](https://github.com/nfmccrina) + - [Martin Reuter](https://github.com/reuterma24) diff --git a/Directory.Packages.props b/Directory.Packages.props index 38ae4acbf..aa622129b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,41 +12,41 @@ <PackageVersion Include="BlurHashSharp.SkiaSharp" Version="1.3.3" /> <PackageVersion Include="BlurHashSharp" Version="1.3.3" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" /> - <PackageVersion Include="coverlet.collector" Version="6.0.2" /> + <PackageVersion Include="coverlet.collector" Version="6.0.4" /> <PackageVersion Include="Diacritics" Version="3.3.29" /> <PackageVersion Include="DiscUtils.Udf" Version="0.16.13" /> <PackageVersion Include="DotNet.Glob" Version="3.1.3" /> - <PackageVersion Include="FsCheck.Xunit" Version="2.16.6" /> + <PackageVersion Include="FsCheck.Xunit" Version="3.0.1" /> <PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0.3" /> <PackageVersion Include="ICU4N.Transliterator" Version="60.1.0-alpha.356" /> <PackageVersion Include="IDisposableAnalyzers" Version="4.0.8" /> <PackageVersion Include="Jellyfin.XmlTv" Version="10.8.0" /> - <PackageVersion Include="libse" Version="4.0.8" /> + <PackageVersion Include="libse" Version="4.0.10" /> <PackageVersion Include="LrcParser" Version="2024.0728.2" /> <PackageVersion Include="MetaBrainz.MusicBrainz" Version="6.1.0" /> - <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.0" /> - <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" /> + <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.1" /> + <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.1" /> <PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" /> - <PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.0" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" /> - <PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0" /> + <PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.1" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.1" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.1" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.1" /> + <PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.1" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" /> <PackageVersion Include="MimeTypes" Version="2.5.2" /> <PackageVersion Include="Mono.Nat" Version="3.0.4" /> @@ -65,7 +65,7 @@ <PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageVersion Include="Serilog.Sinks.Graylog" Version="3.1.1" /> <PackageVersion Include="SerilogAnalyzer" Version="0.15.0" /> - <PackageVersion Include="SharpFuzz" Version="2.1.1" /> + <PackageVersion Include="SharpFuzz" Version="2.2.0" /> <PackageVersion Include="SkiaSharp" Version="2.88.9" /> <PackageVersion Include="SkiaSharp.HarfBuzz" Version="2.88.9" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" /> @@ -76,16 +76,16 @@ <PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageVersion Include="System.Globalization" Version="4.3.0" /> <PackageVersion Include="System.Linq.Async" Version="6.0.1" /> - <PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.0" /> - <PackageVersion Include="System.Text.Json" Version="9.0.0" /> - <PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.0" /> + <PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.1" /> + <PackageVersion Include="System.Text.Json" Version="9.0.1" /> + <PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.1" /> <PackageVersion Include="TagLibSharp" Version="2.3.0" /> - <PackageVersion Include="z440.atl.core" Version="6.9.0" /> + <PackageVersion Include="z440.atl.core" Version="6.13.0" /> <PackageVersion Include="TMDbLib" Version="2.2.0" /> <PackageVersion Include="UTF.Unknown" Version="2.5.1" /> <PackageVersion Include="Xunit.Priority" Version="1.1.6" /> <PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" /> <PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" /> - <PackageVersion Include="xunit" Version="2.9.2" /> + <PackageVersion Include="xunit" Version="2.9.3" /> </ItemGroup> </Project>
\ No newline at end of file diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 9e98d5ce0..9bc3a0204 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Threading; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; @@ -19,7 +20,7 @@ namespace Emby.Server.Implementations.AppBase public abstract class BaseConfigurationManager : IConfigurationManager { private readonly ConcurrentDictionary<string, object> _configurations = new(); - private readonly object _configurationSyncLock = new(); + private readonly Lock _configurationSyncLock = new(); private ConfigurationStore[] _configurationStores = Array.Empty<ConfigurationStore>(); private IConfigurationFactory[] _configurationFactories = Array.Empty<IConfigurationFactory>(); diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index 2459178d8..0b3c3bbd4 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -4,6 +4,7 @@ using System; using System.Globalization; using System.IO; using System.Text; +using System.Threading; using MediaBrowser.Common.Configuration; using Microsoft.Extensions.Logging; @@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Devices { private readonly IApplicationPaths _appPaths; private readonly ILogger<DeviceId> _logger; - private readonly object _syncLock = new object(); + private readonly Lock _syncLock = new(); private string? _id; diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 4c668379c..fb0a55135 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -34,7 +34,7 @@ public sealed class LibraryChangedNotifier : IHostedService, IDisposable private readonly IUserManager _userManager; private readonly ILogger<LibraryChangedNotifier> _logger; - private readonly object _libraryChangedSyncLock = new(); + private readonly Lock _libraryChangedSyncLock = new(); private readonly List<Folder> _foldersAddedTo = new(); private readonly List<Folder> _foldersRemovedFrom = new(); private readonly List<BaseItem> _itemsAdded = new(); diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 9646f13e9..fc174b7c1 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IUserManager _userManager; private readonly Dictionary<Guid, List<BaseItem>> _changedItems = new(); - private readonly object _syncLock = new(); + private readonly Lock _syncLock = new(); private Timer? _updateTimer; diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index e75cab64c..7378cf885 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -18,8 +18,8 @@ namespace Emby.Server.Implementations.IO private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _configurationManager; - private readonly List<string> _affectedPaths = new List<string>(); - private readonly object _timerLock = new object(); + private readonly List<string> _affectedPaths = new(); + private readonly Lock _timerLock = new(); private Timer? _timer; private bool _disposed; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7b37011cb..93ee47fe8 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -82,8 +82,8 @@ namespace Emby.Server.Implementations.Library /// <summary> /// The _root folder sync lock. /// </summary> - private readonly object _rootFolderSyncLock = new object(); - private readonly object _userRootFolderSyncLock = new object(); + private readonly Lock _rootFolderSyncLock = new(); + private readonly Lock _userRootFolderSyncLock = new(); private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24); diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index e9c095c67..5388f6f9a 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -16,7 +16,7 @@ "Folders": "المجلدات", "Genres": "التصنيفات", "HeaderAlbumArtists": "فناني الألبوم", - "HeaderContinueWatching": "استئناف المشاهدة", + "HeaderContinueWatching": "إستئناف المشاهدة", "HeaderFavoriteAlbums": "الألبومات المفضلة", "HeaderFavoriteArtists": "الفنانون المفضلون", "HeaderFavoriteEpisodes": "الحلقات المفضلة", @@ -31,7 +31,7 @@ "ItemRemovedWithName": "أُزيل {0} من المكتبة", "LabelIpAddressValue": "عنوان الآي بي: {0}", "LabelRunningTimeValue": "مدة التشغيل: {0}", - "Latest": "أحدث", + "Latest": "الأحدث", "MessageApplicationUpdated": "حُدث خادم Jellyfin", "MessageApplicationUpdatedTo": "حُدث خادم Jellyfin إلى {0}", "MessageNamedServerConfigurationUpdatedWithValue": "حُدثت إعدادات الخادم في قسم {0}", @@ -52,7 +52,7 @@ "NotificationOptionInstallationFailed": "فشل في التثبيت", "NotificationOptionNewLibraryContent": "أُضيف محتوى جديدا", "NotificationOptionPluginError": "فشل في الملحق", - "NotificationOptionPluginInstalled": "ثُبتت المكونات الإضافية", + "NotificationOptionPluginInstalled": "ثُبتت الملحق", "NotificationOptionPluginUninstalled": "تمت إزالة الملحق", "NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق", "NotificationOptionServerRestartRequired": "يجب إعادة تشغيل الخادم", @@ -90,10 +90,10 @@ "UserStartedPlayingItemWithValues": "قام {0} ببدء تشغيل {1} على {2}", "UserStoppedPlayingItemWithValues": "قام {0} بإيقاف تشغيل {1} على {2}", "ValueHasBeenAddedToLibrary": "تمت اضافت {0} إلى مكتبة الوسائط", - "ValueSpecialEpisodeName": "حلقه خاصه - {0}", + "ValueSpecialEpisodeName": "حلقة خاصه - {0}", "VersionNumber": "الإصدار {0}", "TaskCleanCacheDescription": "يحذف الملفات المؤقتة التي لم يعد النظام بحاجة إليها.", - "TaskCleanCache": "احذف ما بمجلد الملفات المؤقتة", + "TaskCleanCache": "حذف الملفات المؤقتة", "TasksChannelsCategory": "قنوات الإنترنت", "TasksLibraryCategory": "مكتبة", "TasksMaintenanceCategory": "صيانة", @@ -129,7 +129,7 @@ "TaskRefreshTrickplayImagesDescription": "يُنشئ معاينات Trickplay لمقاطع الفيديو في المكتبات المُمكّنة.", "TaskCleanCollectionsAndPlaylists": "حذف المجموعات وقوائم التشغيل", "TaskCleanCollectionsAndPlaylistsDescription": "حذف عناصر من المجموعات وقوائم التشغيل التي لم تعد موجودة.", - "TaskAudioNormalization": "تطبيع الصوت", + "TaskAudioNormalization": "تسوية الصوت", "TaskAudioNormalizationDescription": "مسح الملفات لتطبيع بيانات الصوت.", "TaskDownloadMissingLyrics": "تنزيل عبارات القصيدة", "TaskDownloadMissingLyricsDescription": "كلمات", diff --git a/Emby.Server.Implementations/Localization/Core/bn.json b/Emby.Server.Implementations/Localization/Core/bn.json index 4724bba3b..268a141ff 100644 --- a/Emby.Server.Implementations/Localization/Core/bn.json +++ b/Emby.Server.Implementations/Localization/Core/bn.json @@ -125,5 +125,11 @@ "TaskKeyframeExtractor": "কি-ফ্রেম নিষ্কাশক", "TaskKeyframeExtractorDescription": "ভিডিয়ো থেকে কি-ফ্রেম নিষ্কাশনের মাধ্যমে অধিকতর সঠিক HLS প্লে লিস্ট তৈরী করে। এই প্রক্রিয়া দীর্ঘ সময় ধরে চলতে পারে।", "TaskRefreshTrickplayImages": "ট্রিকপ্লে ইমেজ তৈরি করুন", - "TaskRefreshTrickplayImagesDescription": "সক্ষম লাইব্রেরিতে ভিডিওর জন্য ট্রিকপ্লে প্রিভিউ তৈরি করে।" + "TaskRefreshTrickplayImagesDescription": "সক্ষম লাইব্রেরিতে ভিডিওর জন্য ট্রিকপ্লে প্রিভিউ তৈরি করে।", + "TaskDownloadMissingLyricsDescription": "গানের লিরিক্স ডাউনলোড করে", + "TaskCleanCollectionsAndPlaylists": "সংগ্রহ এবং প্লেলিস্ট পরিষ্কার করুন", + "TaskCleanCollectionsAndPlaylistsDescription": "সংগ্রহ এবং প্লেলিস্ট থেকে আইটেমগুলি সরিয়ে দেয় যা আর বিদ্যমান নেই।", + "TaskExtractMediaSegments": "মিডিয়া সেগমেন্ট স্ক্যান", + "TaskExtractMediaSegmentsDescription": "MediaSegment সক্ষম প্লাগইনগুলি থেকে মিডিয়া সেগমেন্টগুলি বের করে বা প্রাপ্ত করে।", + "TaskDownloadMissingLyrics": "অনুপস্থিত গান ডাউনলোড করুন" } diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index 629efdd04..2cbc594b0 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -133,5 +133,8 @@ "TaskAudioNormalizationDescription": "Escaneja arxius per dades de normalització d'àudio.", "TaskDownloadMissingLyricsDescription": "Baixar lletres de les cançons", "TaskDownloadMissingLyrics": "Baixar lletres que falten", - "TaskExtractMediaSegments": "Escaneig de segments multimèdia" + "TaskExtractMediaSegments": "Escaneig de segments multimèdia", + "TaskExtractMediaSegmentsDescription": "Extreu o obté segments multimèdia usant els connectors MediaSegment activats.", + "TaskMoveTrickplayImages": "Migra la ubicació de la imatge de Trickplay", + "TaskMoveTrickplayImagesDescription": "Mou els fitxers trickplay existents segons la configuració de la biblioteca." } diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index c17fbc414..d43d4097f 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -1,5 +1,5 @@ { - "Albums": "Album", + "Albums": "Albummer", "AppDeviceValues": "App: {0}, Enhed: {1}", "Application": "Applikation", "Artists": "Kunstnere", diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 51c9e87d5..c38af5bf4 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -5,7 +5,7 @@ "Artists": "Interpreten", "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert", "Books": "Bücher", - "CameraImageUploadedFrom": "Ein neues Kamerafoto wurde von {0} hochgeladen", + "CameraImageUploadedFrom": "Ein neues Kamerabild wurde von {0} hochgeladen", "Channels": "Kanäle", "ChapterNameValue": "Kapitel {0}", "Collections": "Sammlungen", @@ -18,7 +18,7 @@ "HeaderAlbumArtists": "Album-Interpreten", "HeaderContinueWatching": "Weiterschauen", "HeaderFavoriteAlbums": "Lieblingsalben", - "HeaderFavoriteArtists": "Lieblings-Interpreten", + "HeaderFavoriteArtists": "Lieblingsinterpreten", "HeaderFavoriteEpisodes": "Lieblingsepisoden", "HeaderFavoriteShows": "Lieblingsserien", "HeaderFavoriteSongs": "Lieblingslieder", diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json index f2f657b04..cf31960f9 100644 --- a/Emby.Server.Implementations/Localization/Core/es-AR.json +++ b/Emby.Server.Implementations/Localization/Core/es-AR.json @@ -15,7 +15,7 @@ "Favorites": "Favoritos", "Folders": "Carpetas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas de álbum", + "HeaderAlbumArtists": "Artistas del álbum", "HeaderContinueWatching": "Seguir viendo", "HeaderFavoriteAlbums": "Álbumes favoritos", "HeaderFavoriteArtists": "Artistas favoritos", diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index 51f45fb89..297b3abce 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -135,5 +135,6 @@ "TaskDownloadMissingLyrics": "Scarica testi mancanti", "TaskMoveTrickplayImages": "Sposta le immagini Trickplay", "TaskMoveTrickplayImagesDescription": "Sposta le immagini Trickplay esistenti secondo la configurazione della libreria.", - "TaskExtractMediaSegmentsDescription": "contenuti" + "TaskExtractMediaSegmentsDescription": "Estrae o ottiene segmenti multimediali dai plugin abilitati MediaSegment.", + "TaskExtractMediaSegments": "Scansiona Segmento Media" } diff --git a/Emby.Server.Implementations/Localization/Core/ja.json b/Emby.Server.Implementations/Localization/Core/ja.json index 10f4aee25..14a576592 100644 --- a/Emby.Server.Implementations/Localization/Core/ja.json +++ b/Emby.Server.Implementations/Localization/Core/ja.json @@ -134,5 +134,6 @@ "TaskExtractMediaSegments": "メディアセグメントを読み取る", "TaskMoveTrickplayImages": "Trickplayの画像を移動", "TaskMoveTrickplayImagesDescription": "ライブラリ設定によりTrickplayのファイルを移動。", - "TaskDownloadMissingLyrics": "記録されていない歌詞をダウンロード" + "TaskDownloadMissingLyrics": "失われた歌詞をダウンロード", + "TaskExtractMediaSegmentsDescription": "MediaSegment 対応プラグインからメディア セグメントを抽出または取得します。" } diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json index 95f738bd5..46fc49f5e 100644 --- a/Emby.Server.Implementations/Localization/Core/lt-LT.json +++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json @@ -94,14 +94,14 @@ "VersionNumber": "Version {0}", "TaskUpdatePluginsDescription": "Atsisiųsti ir įdiegti atnaujinimus priedams kuriem yra nustatytas automatiškas atnaujinimas.", "TaskUpdatePlugins": "Atnaujinti Priedus", - "TaskDownloadMissingSubtitlesDescription": "Ieško internete trūkstamų subtitrų remiantis metaduomenų konfigūracija.", + "TaskDownloadMissingSubtitlesDescription": "Ieško trūkstamų subtitrų internete remiantis metaduomenų konfigūracija.", "TaskCleanTranscodeDescription": "Ištrina dienos senumo perkodavimo failus.", "TaskCleanTranscode": "Išvalyti Perkodavimo Direktorija", "TaskRefreshLibraryDescription": "Ieškoti naujų failų jūsų mediatekoje ir atnaujina metaduomenis.", "TaskRefreshLibrary": "Skenuoti Mediateka", "TaskDownloadMissingSubtitles": "Atsisiųsti trūkstamus subtitrus", - "TaskRefreshChannelsDescription": "Atnaujina internetinių kanalų informacija.", - "TaskRefreshChannels": "Atnaujinti Kanalus", + "TaskRefreshChannelsDescription": "Atnaujina internetinių kanalų informaciją.", + "TaskRefreshChannels": "Atnaujinti kanalus", "TaskRefreshPeopleDescription": "Atnaujina metaduomenis apie aktorius ir režisierius jūsų mediatekoje.", "TaskRefreshPeople": "Atnaujinti Žmones", "TaskCleanLogsDescription": "Ištrina žurnalo failus kurie yra senesni nei {0} dienos.", @@ -119,22 +119,22 @@ "Forced": "Priverstas", "Default": "Numatytas", "TaskCleanActivityLogDescription": "Ištrina veiklos žuranlo įrašus, kurie yra senesni nei nustatytas amžius.", - "TaskOptimizeDatabase": "Optimizuoti duomenų bazės", + "TaskOptimizeDatabase": "Optimizuoti duomenų bazę", "TaskKeyframeExtractorDescription": "Iš vaizdo įrašo paruošia reikšminius kadrus, kad būtų sukuriamas tikslenis HLS grojaraštis. Šios užduoties vykdymas gali ilgai užtrukti.", - "TaskKeyframeExtractor": "Pagrindinių kadrų ištraukėjas", - "TaskOptimizeDatabaseDescription": "Suspaudžia duomenų bazę ir atlaisvina vietą. Paleidžiant šią užduotį, po bibliotekos skenavimo arba kitų veiksmų kurie galimai modifikuoja duomenų bazė, gali pagerinti greitaveiką.", + "TaskKeyframeExtractor": "Pagrindinių kadrų išgavėjas", + "TaskOptimizeDatabaseDescription": "Suspaudžia duomenų bazę ir atlaisvina vietą. Paleidžiant šią užduotį, po bibliotekos skenavimo arba kitų veiksmų kurie galimai modifikuoja duomenų bazę, gali pagerinti greitaveiką.", "External": "Išorinis", "HearingImpaired": "Su klausos sutrikimais", "TaskRefreshTrickplayImages": "Generuoti Trickplay atvaizdus", "TaskRefreshTrickplayImagesDescription": "Sukuria trickplay peržiūras vaizdo įrašams įgalintose bibliotekose.", - "TaskCleanCollectionsAndPlaylists": "Sutvarko duomenis jūsų kolekcijose ir grojaraščiuose", - "TaskCleanCollectionsAndPlaylistsDescription": "Pašalina nebeegzistuojančius elementus iš kolekcijų ir grojaraščių.", + "TaskCleanCollectionsAndPlaylists": "Išvalo duomenis kolekcijose ir grojaraščiuose", + "TaskCleanCollectionsAndPlaylistsDescription": "Pašalina neegzistuojančius elementus iš kolekcijų ir grojaraščių.", "TaskAudioNormalization": "Garso Normalizavimas", "TaskAudioNormalizationDescription": "Skenuoti garso normalizavimo informacijos failuose.", - "TaskExtractMediaSegments": "Medijos Segmentų Nuskaitymas", + "TaskExtractMediaSegments": "Medijos segmentų nuskaitymas", "TaskDownloadMissingLyrics": "Parsisiųsti trūkstamus dainų tekstus", "TaskExtractMediaSegmentsDescription": "Ištraukia arba gauna medijos segmentus iš MediaSegment ijungtų papildinių.", - "TaskMoveTrickplayImages": "Migruoti Trickplay Vaizdų Vietą", - "TaskMoveTrickplayImagesDescription": "Perkelia egzisuojančius trickplay failus pagal bibliotekos nustatymus.", + "TaskMoveTrickplayImages": "Pakeisti Trickplay vaizdų vietą", + "TaskMoveTrickplayImagesDescription": "Perkelia egzistuojančius trickplay failus pagal bibliotekos nustatymus.", "TaskDownloadMissingLyricsDescription": "Parsisiųsti dainų žodžius" } diff --git a/Emby.Server.Implementations/Localization/Core/lv.json b/Emby.Server.Implementations/Localization/Core/lv.json index 62277fd94..31aa46520 100644 --- a/Emby.Server.Implementations/Localization/Core/lv.json +++ b/Emby.Server.Implementations/Localization/Core/lv.json @@ -123,7 +123,7 @@ "External": "Ārējais", "HearingImpaired": "Ar dzirdes traucējumiem", "TaskKeyframeExtractor": "Atslēgkadru ekstraktors", - "TaskKeyframeExtractorDescription": "Ekstraktē atslēgkadrus no video failiem lai izveidotu precīzākus HLS atskaņošanas sarakstus. Šis process var būt ilgs.", + "TaskKeyframeExtractorDescription": "Izvelk atslēgkadrus no video failiem lai izveidotu precīzākus HLS atskaņošanas sarakstus. Šis process var būt ilgs.", "TaskRefreshTrickplayImages": "Ģenerēt partīšanas attēlus", "TaskRefreshTrickplayImagesDescription": "Izveido priekšskatījumus videoklipu pārtīšanai iespējotajās bibliotēkās.", "TaskAudioNormalization": "Audio normalizācija", diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json index ebd3f7560..c64bcda04 100644 --- a/Emby.Server.Implementations/Localization/Core/ms.json +++ b/Emby.Server.Implementations/Localization/Core/ms.json @@ -11,7 +11,7 @@ "Collections": "Koleksi", "DeviceOfflineWithName": "{0} telah diputuskan sambungan", "DeviceOnlineWithName": "{0} telah disambung", - "FailedLoginAttemptWithUserName": "Cubaan log masuk gagal dari {0}", + "FailedLoginAttemptWithUserName": "Percubaan log masuk daripada {0} gagal", "Favorites": "Kegemaran", "Folders": "Fail-fail", "Genres": "Genre-genre", @@ -126,5 +126,15 @@ "TaskKeyframeExtractor": "Ekstrak bingkai kunci", "TaskKeyframeExtractorDescription": "Ekstrak bingkai kunci dari fail video untuk membina HLS playlist yang lebih tepat. Tugas ini mungkin perlukan masa yang panjang.", "TaskRefreshTrickplayImagesDescription": "Jana gambar prebiu Trickplay untuk video dalam perpustakaan.", - "TaskRefreshTrickplayImages": "Jana gambar Trickplay" + "TaskRefreshTrickplayImages": "Jana gambar Trickplay", + "TaskExtractMediaSegments": "Imbasan Segmen Media", + "TaskExtractMediaSegmentsDescription": "Mengekstrak atau mendapatkan segmen media daripada pemalam yang didayakan MediaSegment.", + "TaskMoveTrickplayImagesDescription": "Mengalihkan fail trickplay sedia ada mengikut tetapan pustakan digital.", + "TaskDownloadMissingLyrics": "Muat turun lirik yang hilang", + "TaskDownloadMissingLyricsDescription": "Memuat turun lirik-lirik untuk lagu-lagu", + "TaskMoveTrickplayImages": "Alih Lokasi Imej Trickplay", + "TaskCleanCollectionsAndPlaylists": "Bersihkan koleksi dan senarai audio video", + "TaskAudioNormalization": "Normalisasi Audio", + "TaskAudioNormalizationDescription": "Mengimbas fail-fail untuk data normalisasi audio.", + "TaskCleanCollectionsAndPlaylistsDescription": "Mengalih keluar item daripada koleksi dan senarai audio video yang tidak wujud lagi." } diff --git a/Emby.Server.Implementations/Localization/Core/mt.json b/Emby.Server.Implementations/Localization/Core/mt.json index c3da37c58..f7501ab40 100644 --- a/Emby.Server.Implementations/Localization/Core/mt.json +++ b/Emby.Server.Implementations/Localization/Core/mt.json @@ -12,7 +12,7 @@ "DeviceOfflineWithName": "{0} tneħħa", "DeviceOnlineWithName": "{0} tqabbad", "External": "Estern", - "FailedLoginAttemptWithUserName": "Attentat ta' login minn {0}", + "FailedLoginAttemptWithUserName": "Attentat fallut ta' login minn {0}", "Favorites": "Favoriti", "Forced": "Sfurzat", "Genres": "Ġeneri", @@ -38,10 +38,10 @@ "Inherit": "Jiret", "ItemAddedWithName": "{0} żdied fil-librerija", "ItemRemovedWithName": "{0} tneħħa mil-librerija", - "LabelIpAddressValue": "Indirizz IP: {0}", + "LabelIpAddressValue": "Indirizz tal-IP: {0}", "Latest": "Tal-Aħħar", - "MessageApplicationUpdated": "Jellyfin Server ġie aġġornat", - "MessageApplicationUpdatedTo": "JellyFin Server ġie aġġornat għal {0}", + "MessageApplicationUpdated": "Il-Jellyfin Server ġie aġġornat", + "MessageApplicationUpdatedTo": "Il-JellyFin Server ġie aġġornat għal {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Is-sezzjoni {0} tal-konfigurazzjoni tas-server ġiet aġġornata", "MessageServerConfigurationUpdated": "Il-konfigurazzjoni tas-server ġiet aġġornata", "MixedContent": "Kontenut imħallat", @@ -51,26 +51,26 @@ "NameInstallFailed": "L-installazzjoni ta' {0} falliet", "NameSeasonNumber": "Staġun {0}", "NameSeasonUnknown": "Staġun Mhux Magħruf", - "NewVersionIsAvailable": "Verżjoni ġdida ta' Jellyfin Server hija disponibbli biex titniżżel.", - "NotificationOptionApplicationUpdateAvailable": "Aġġornament tal-applikazzjoni disponibbli", - "NotificationOptionCameraImageUploaded": "Immaġini tal-kamera mtella'", + "NewVersionIsAvailable": "Verżjoni ġdida tal-Jellyfin Server hija disponibbli biex titniżżel.", + "NotificationOptionApplicationUpdateAvailable": "Hemm aġġornament tal-applikazzjoni", + "NotificationOptionCameraImageUploaded": "Ritratt tal-kamera mtella'", "LabelRunningTimeValue": "Tul: {0}", "NotificationOptionApplicationUpdateInstalled": "Aġġornament tal-applikazzjoni ġie installat", - "NotificationOptionAudioPlayback": "Il-playback tal-awdjo beda", + "NotificationOptionAudioPlayback": "Beda l-playback tal-awdjo", "NotificationOptionAudioPlaybackStopped": "Il-playback tal-awdjo twaqqaf", - "NotificationOptionInstallationFailed": "Falliment tal-Installazzjoni", + "NotificationOptionInstallationFailed": "L-Installazzjoni falliet", "NotificationOptionNewLibraryContent": "Kontenut ġdid żdied", "NotificationOptionPluginError": "Falliment fil-plugin", "NotificationOptionPluginInstalled": "Plugin installat", "NotificationOptionPluginUninstalled": "Plugin tneħħa", - "NotificationOptionServerRestartRequired": "Hemm bżonn li tagħmel restart lis-server", + "NotificationOptionServerRestartRequired": "Hemm bżonn li tagħmel restart tas-server", "NotificationOptionTaskFailed": "Falliment tat-task skedat", "NotificationOptionUserLockedOut": "Utent imsakkar", "Photos": "Ritratti", "Playlists": "Playlists", "Plugin": "Plugin", "PluginInstalledWithName": "{0} ġie installat", - "PluginUninstalledWithName": "{0} ġie mneħħi", + "PluginUninstalledWithName": "{0} tneħħa", "PluginUpdatedWithName": "{0} ġie aġġornat", "ProviderValue": "Fornitur: {0}", "ScheduledTaskFailedWithName": "{0} falla", diff --git a/Emby.Server.Implementations/Localization/Core/pa.json b/Emby.Server.Implementations/Localization/Core/pa.json index a25099ee0..6062d9700 100644 --- a/Emby.Server.Implementations/Localization/Core/pa.json +++ b/Emby.Server.Implementations/Localization/Core/pa.json @@ -120,5 +120,20 @@ "Albums": "ਐਲਬਮਾਂ", "TaskOptimizeDatabase": "ਡਾਟਾਬੇਸ ਅਨੁਕੂਲ ਬਣਾਓ", "External": "ਬਾਹਰੀ", - "HearingImpaired": "ਸੁਨਣ ਵਿਚ ਕਮਜ਼ੋਰ" + "HearingImpaired": "ਸੁਨਣ ਵਿਚ ਕਮਜ਼ੋਰ", + "TaskAudioNormalizationDescription": "ਆਵਾਜ਼ ਸਧਾਰਣੀਕਰਨ ਡਾਟਾ ਲਈ ਫਾਇਲਾਂ ਖੋਜੋ।", + "TaskRefreshTrickplayImages": "ਟ੍ਰਿਕਪਲੇ ਤਸਵੀਰਾਂ ਤਿਆਰ ਕਰੋ", + "TaskExtractMediaSegments": "ਮੀਡੀਆ ਸੈਗਮੈਂਟ ਸਕੈਨ", + "TaskMoveTrickplayImagesDescription": "ਟ੍ਰਿਕਪਲੇ ਤਸਵੀਰਾਂ ਦੀ ਜਗਾ ਨੂੰ ਲਾਇਬ੍ਰੇਰੀ ਸੈਟਿੰਗਜ਼ ਅਨੁਸਾਰ ਬਦਲੋ।", + "TaskOptimizeDatabaseDescription": "ਡੇਟਾਬੇਸ ਨੂੰ ਸੰਗ੍ਰਹਿਤ ਕਰਦਾ ਹੈ ਅਤੇ ਖਾਲੀ ਜਗ੍ਹਾ ਘਟਾਉਂਦਾ ਹੈ। ਲਾਇਬ੍ਰੇਰੀ ਸਕੈਨ ਕਰਨ ਜਾਂ ਡੇਟਾਬੇਸ ਵਿੱਚ ਸੋਧਾਂ ਕਰਨ ਤੋਂ ਬਾਅਦ ਇਸ ਕੰਮ ਨੂੰ ਚਲਾਉਣਾ ਪ੍ਰਦਰਸ਼ਨ ਵਿੱਚ ਸੁਧਾਰ ਕਰ ਸਕਦਾ ਹੈ।", + "TaskExtractMediaSegmentsDescription": "ਮੀਡੀਆ ਸੈਗਮੈਂਟ ਨੂੰ ਮੀਡੀਆਸੈਗਮੈਂਟ ਯੋਗ ਪਲੱਗਇਨਾਂ ਤੋਂ ਨਿਕਾਲਦਾ ਜਾਂ ਪ੍ਰਾਪਤ ਕਰਦਾ ਹੈ।", + "TaskMoveTrickplayImages": "ਟ੍ਰਿਕਪਲੇ ਤਸਵੀਰਾਂ ਦੀ ਜਗਾ ਬਦਲੋ", + "TaskDownloadMissingLyrics": "ਅਧੂਰੇ ਬੋਲ ਡਾਊਨਲੋਡ ਕਰੋ", + "TaskDownloadMissingLyricsDescription": "ਗੀਤਾਂ ਲਈ ਡਾਊਨਲੋਡ ਕਿਤੇ ਬੋਲ", + "TaskKeyframeExtractor": "ਕੀ-ਫ੍ਰੇਮ ਐਕਸਟ੍ਰੈਕਟਰ", + "TaskCleanCollectionsAndPlaylistsDescription": "ਕਲੈਕਸ਼ਨਾਂ ਅਤੇ ਪਲੇਲਿਸਟਾਂ ਵਿੱਚੋਂ ਉਹ ਆਈਟਮ ਹਟਾਉਂਦਾ ਹੈ ਜੋ ਹੁਣ ਮੌਜੂਦ ਨਹੀਂ ਹਨ।", + "TaskCleanCollectionsAndPlaylists": "ਕਲੈਕਸ਼ਨਾਂ ਅਤੇ ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਸਾਫ ਕਰੋ", + "TaskAudioNormalization": "ਆਵਾਜ਼ ਸਧਾਰਣੀਕਰਨ", + "TaskRefreshTrickplayImagesDescription": "ਚਲ ਰਹੀ ਲਾਇਬ੍ਰੇਰੀਆਂ ਵਿੱਚ ਵੀਡੀਓਜ਼ ਲਈ ਟ੍ਰਿਕਪਲੇ ਪ੍ਰੀਵਿਊ ਬਣਾਉਂਦਾ ਹੈ।", + "TaskKeyframeExtractorDescription": "ਕੀ-ਫ੍ਰੇਮਜ਼ ਨੂੰ ਵੀਡੀਓ ਫਾਈਲਾਂ ਵਿੱਚੋਂ ਨਿਕਾਲਦਾ ਹੈ ਤਾਂ ਜੋ ਹੋਰ ਜ਼ਿਆਦਾ ਸਟਿਕ ਹੋਣ ਵਾਲੀਆਂ HLS ਪਲੇਲਿਸਟਾਂ ਬਣਾਈਆਂ ਜਾ ਸਕਣ। ਇਹ ਕੰਮ ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਚੱਲ ਸਕਦਾ ਹੈ।" } diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json index 2812832ca..0bf0491be 100644 --- a/Emby.Server.Implementations/Localization/Core/pt.json +++ b/Emby.Server.Implementations/Localization/Core/pt.json @@ -13,7 +13,7 @@ "HeaderContinueWatching": "Continuar a ver", "HeaderAlbumArtists": "Artistas do Álbum", "Genres": "Géneros", - "Folders": "Diretórios", + "Folders": "Pastas", "Favorites": "Favoritos", "Channels": "Canais", "UserDownloadingItemWithValues": "{0} está sendo baixado {1}", diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index 19be1a23e..b17e7ae55 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -126,5 +126,15 @@ "TaskKeyframeExtractorDescription": "Iz video datoteke Izvleče ključne sličice, da ustvari bolj natančne sezname predvajanja HLS. Proces lahko traja dolgo časa.", "HearingImpaired": "Oslabljen sluh", "TaskRefreshTrickplayImages": "Ustvari Trickplay slike", - "TaskRefreshTrickplayImagesDescription": "Ustvari trickplay predoglede za posnetke v omogočenih knjižnicah." + "TaskRefreshTrickplayImagesDescription": "Ustvari trickplay predoglede za posnetke v omogočenih knjižnicah.", + "TaskExtractMediaSegmentsDescription": "Ekstrahira ali pridobi medijske segmente iz vtičnikov, ki podpirajo MediaSegment.", + "TaskMoveTrickplayImagesDescription": "Premakne obstoječe datoteke trickplay v skladu z nastavitvami knjižnice.", + "TaskExtractMediaSegments": "Skeniranje segmentov v medijih", + "TaskMoveTrickplayImages": "Preseli lokacijo Trickplay slik", + "TaskDownloadMissingLyrics": "Prenesi manjkajoča besedila pesmi", + "TaskDownloadMissingLyricsDescription": "Prenesi besedila za pesmi", + "TaskCleanCollectionsAndPlaylists": "Počisti zbirke in sezname predvajanja", + "TaskAudioNormalization": "Normalizacija zvoka", + "TaskAudioNormalizationDescription": "Pregled datotek za podatke o normalizaciji zvoka.", + "TaskCleanCollectionsAndPlaylistsDescription": "Odstrani elemente iz zbirk in seznamov predvajanja, ki ne obstajajo več." } diff --git a/Emby.Server.Implementations/Localization/Core/sr.json b/Emby.Server.Implementations/Localization/Core/sr.json index 9739358df..af40b5e5a 100644 --- a/Emby.Server.Implementations/Localization/Core/sr.json +++ b/Emby.Server.Implementations/Localization/Core/sr.json @@ -78,7 +78,7 @@ "Genres": "Жанрови", "Folders": "Фасцикле", "Favorites": "Омиљено", - "FailedLoginAttemptWithUserName": "Неуспела пријава са {0}", + "FailedLoginAttemptWithUserName": "Неуспели покушај пријавe са {0}", "DeviceOnlineWithName": "{0} је повезан", "DeviceOfflineWithName": "{0} је прекинуо везу", "Collections": "Колекције", @@ -121,7 +121,10 @@ "TaskOptimizeDatabase": "Оптимизуј банку података", "TaskOptimizeDatabaseDescription": "Сажима базу података и скраћује слободан простор. Покретање овог задатка након скенирања библиотеке или других промена које подразумевају измене базе података које могу побољшати перформансе.", "External": "Спољно", - "TaskKeyframeExtractorDescription": "Екстрактује кљулне сличице из видео датотека да би креирао више преицзну HLS плеј-листу. Овај задатак може да потраје дуже време.", + "TaskKeyframeExtractorDescription": "Екстрактује кључне сличице из видео датотека да би креирао више прецизнију HLS плејлисту. Овај задатак може да потраје дуже време.", "TaskKeyframeExtractor": "Екстрактор кључних сличица", - "HearingImpaired": "ослабљен слух" + "HearingImpaired": "ослабљен слух", + "TaskAudioNormalization": "Нормализација звука", + "TaskCleanCollectionsAndPlaylists": "Очистите колекције и плејлисте", + "TaskAudioNormalizationDescription": "Скенира датотеке за податке о нормализацији звука." } diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json index 81d5b83d6..a4ee68fc4 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-TW.json +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -8,7 +8,7 @@ "CameraImageUploadedFrom": "已從 {0} 成功上傳一張相片", "Channels": "頻道", "ChapterNameValue": "章節 {0}", - "Collections": "系列", + "Collections": "系列作", "DeviceOfflineWithName": "{0} 已中斷連接", "DeviceOnlineWithName": "{0} 已連接", "FailedLoginAttemptWithUserName": "來自使用者 {0} 的登入失敗嘗試", @@ -126,8 +126,8 @@ "HearingImpaired": "聽力障礙", "TaskRefreshTrickplayImages": "生成快轉縮圖", "TaskRefreshTrickplayImagesDescription": "為啟用快轉縮圖的媒體庫生成快轉縮圖。", - "TaskCleanCollectionsAndPlaylists": "清理系列和播放清單", - "TaskCleanCollectionsAndPlaylistsDescription": "清理系列和播放清單中已不存在的項目。", + "TaskCleanCollectionsAndPlaylists": "清理系列作和播放清單", + "TaskCleanCollectionsAndPlaylistsDescription": "清理系列作品與播放清單中已不存在的項目。", "TaskAudioNormalization": "音量標準化", "TaskAudioNormalizationDescription": "掃描文件以找出音量標準化資料。", "TaskDownloadMissingLyrics": "下載缺少的歌詞", diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index fe769baf9..0bc67bc47 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.ScheduledTasks private readonly IApplicationPaths _applicationPaths; private readonly ILogger _logger; private readonly ITaskManager _taskManager; - private readonly object _lastExecutionResultSyncLock = new(); + private readonly Lock _lastExecutionResultSyncLock = new(); private bool _readFromFile; private TaskResult _lastExecutionResult; private Task _currentTask; diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index aba51de8f..c4f6a6285 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Session /// <summary> /// Lock used for accessing the WebSockets watchlist. /// </summary> - private readonly object _webSocketsLock = new object(); + private readonly Lock _webSocketsLock = new(); private readonly ISessionManager _sessionManager; private readonly ILogger<SessionWebSocketListener> _logger; diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs index 00c655634..fdfff8f3b 100644 --- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs +++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs @@ -67,7 +67,7 @@ namespace Emby.Server.Implementations.SyncPlay /// <remarks> /// This lock has priority on locks made on <see cref="Group"/>. /// </remarks> - private readonly object _groupsLock = new object(); + private readonly Lock _groupsLock = new(); private bool _disposed = false; diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index ce3d6cab8..c4d697be5 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.Updates /// </summary> /// <value>The application host.</value> private readonly IServerApplicationHost _applicationHost; - private readonly object _currentInstallationsLock = new object(); + private readonly Lock _currentInstallationsLock = new(); /// <summary> /// The current installations. diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 9da1dce93..e5df873f5 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -395,7 +395,7 @@ public class SubtitleController : BaseJellyfinApiController var url = string.Format( CultureInfo.InvariantCulture, - "stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}", + "stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&ApiKey={2}", positionTicks.ToString(CultureInfo.InvariantCulture), endPositionTicks.ToString(CultureInfo.InvariantCulture), accessToken); diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 0e620e72a..9802be7f4 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -550,7 +550,7 @@ public class DynamicHlsHelper var url = string.Format( CultureInfo.InvariantCulture, - "{0}/Subtitles/{1}/subtitles.m3u8?SegmentLength={2}&api_key={3}", + "{0}/Subtitles/{1}/subtitles.m3u8?SegmentLength={2}&ApiKey={3}", state.Request.MediaSourceId, stream.Index.ToString(CultureInfo.InvariantCulture), 30.ToString(CultureInfo.InvariantCulture), @@ -587,7 +587,7 @@ public class DynamicHlsHelper var url = string.Format( CultureInfo.InvariantCulture, - "Trickplay/{0}/tiles.m3u8?MediaSourceId={1}&api_key={2}", + "Trickplay/{0}/tiles.m3u8?MediaSourceId={1}&ApiKey={2}", width.ToString(CultureInfo.InvariantCulture), state.Request.MediaSourceId, user.GetToken()); diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 2ae722982..ae9040489 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Queries; using Jellyfin.Extensions; using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; @@ -22,17 +23,20 @@ namespace Jellyfin.Server.Implementations.Security private readonly IUserManager _userManager; private readonly IDeviceManager _deviceManager; private readonly IServerApplicationHost _serverApplicationHost; + private readonly IServerConfigurationManager _configurationManager; public AuthorizationContext( IDbContextFactory<JellyfinDbContext> jellyfinDb, IUserManager userManager, IDeviceManager deviceManager, - IServerApplicationHost serverApplicationHost) + IServerApplicationHost serverApplicationHost, + IServerConfigurationManager configurationManager) { _jellyfinDbProvider = jellyfinDb; _userManager = userManager; _deviceManager = deviceManager; _serverApplicationHost = serverApplicationHost; + _configurationManager = configurationManager; } public Task<AuthorizationInfo> GetAuthorizationInfo(HttpContext requestContext) @@ -85,12 +89,12 @@ namespace Jellyfin.Server.Implementations.Security auth.TryGetValue("Token", out token); } - if (string.IsNullOrEmpty(token)) + if (_configurationManager.Configuration.EnableLegacyAuthorization && string.IsNullOrEmpty(token)) { token = headers["X-Emby-Token"]; } - if (string.IsNullOrEmpty(token)) + if (_configurationManager.Configuration.EnableLegacyAuthorization && string.IsNullOrEmpty(token)) { token = headers["X-MediaBrowser-Token"]; } @@ -100,8 +104,7 @@ namespace Jellyfin.Server.Implementations.Security token = queryString["ApiKey"]; } - // TODO deprecate this query parameter. - if (string.IsNullOrEmpty(token)) + if (_configurationManager.Configuration.EnableLegacyAuthorization && string.IsNullOrEmpty(token)) { token = queryString["api_key"]; } @@ -128,10 +131,7 @@ namespace Jellyfin.Server.Implementations.Security await using (dbContext.ConfigureAwait(false)) { var device = _deviceManager.GetDevices( - new DeviceQuery - { - AccessToken = token - }).Items.FirstOrDefault(); + new DeviceQuery { AccessToken = token }).Items.FirstOrDefault(); if (device is not null) { @@ -227,13 +227,13 @@ namespace Jellyfin.Server.Implementations.Security /// </summary> /// <param name="httpReq">The HTTP request.</param> /// <returns>Dictionary{System.StringSystem.String}.</returns> - private static Dictionary<string, string>? GetAuthorizationDictionary(HttpRequest httpReq) + private Dictionary<string, string>? GetAuthorizationDictionary(HttpRequest httpReq) { - var auth = httpReq.Headers["X-Emby-Authorization"]; + var auth = httpReq.Headers[HeaderNames.Authorization]; - if (string.IsNullOrEmpty(auth)) + if (_configurationManager.Configuration.EnableLegacyAuthorization && string.IsNullOrEmpty(auth)) { - auth = httpReq.Headers[HeaderNames.Authorization]; + auth = httpReq.Headers["X-Emby-Authorization"]; } return auth.Count > 0 ? GetAuthorization(auth[0]) : null; @@ -244,7 +244,7 @@ namespace Jellyfin.Server.Implementations.Security /// </summary> /// <param name="authorizationHeader">The authorization header.</param> /// <returns>Dictionary{System.StringSystem.String}.</returns> - private static Dictionary<string, string>? GetAuthorization(ReadOnlySpan<char> authorizationHeader) + private Dictionary<string, string>? GetAuthorization(ReadOnlySpan<char> authorizationHeader) { var firstSpace = authorizationHeader.IndexOf(' '); @@ -256,8 +256,10 @@ namespace Jellyfin.Server.Implementations.Security var name = authorizationHeader[..firstSpace]; - if (!name.Equals("MediaBrowser", StringComparison.OrdinalIgnoreCase) - && !name.Equals("Emby", StringComparison.OrdinalIgnoreCase)) + var validName = name.Equals("MediaBrowser", StringComparison.OrdinalIgnoreCase); + validName = validName || (_configurationManager.Configuration.EnableLegacyAuthorization && name.Equals("Emby", StringComparison.OrdinalIgnoreCase)); + + if (!validName) { return null; } diff --git a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs index 23ff06ff5..cd73d67c3 100644 --- a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs +++ b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs @@ -536,7 +536,7 @@ public class TrickplayManager : ITrickplayManager if (trickplayInfo.ThumbnailCount > 0) { - const string urlFormat = "{0}.jpg?MediaSourceId={1}&api_key={2}"; + const string urlFormat = "{0}.jpg?MediaSourceId={1}&ApiKey={2}"; const string decimalFormat = "{0:0.###}"; var resolution = $"{trickplayInfo.Width}x{trickplayInfo.Height}"; diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index bf2f12cb9..58992ecd7 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using System.Threading; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; @@ -20,12 +21,12 @@ namespace MediaBrowser.Common.Plugins /// <summary> /// The configuration sync lock. /// </summary> - private readonly object _configurationSyncLock = new object(); + private readonly Lock _configurationSyncLock = new(); /// <summary> /// The configuration save lock. /// </summary> - private readonly object _configurationSaveLock = new object(); + private readonly Lock _configurationSaveLock = new(); /// <summary> /// The configuration. diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 00b06dc79..a02802f41 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> public class AggregateFolder : Folder { - private readonly object _childIdsLock = new object(); + private readonly Lock _childIdsLock = new(); /// <summary> /// The _virtual children. diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index 7cf447fb8..7ae4a4a2c 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> public class UserRootFolder : Folder { - private readonly object _childIdsLock = new object(); + private readonly Lock _childIdsLock = new(); private List<Guid> _childrenIds = null; /// <summary> diff --git a/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs b/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs index fefa66cdb..56990d0b8 100644 --- a/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs +++ b/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs @@ -12,8 +12,8 @@ namespace MediaBrowser.Controller.MediaEncoding; public sealed class TranscodingJob : IDisposable { private readonly ILogger<TranscodingJob> _logger; - private readonly object _processLock = new(); - private readonly object _timerLock = new(); + private readonly Lock _processLock = new(); + private readonly Lock _timerLock = new(); private Timer? _killTimer; diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index a47d2fa45..4757bfa30 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Net SingleWriter = false }); - private readonly object _activeConnectionsLock = new(); + private readonly Lock _activeConnectionsLock = new(); /// <summary> /// The _active connections. diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 3ba1bfce4..cbef5d011 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Session private readonly ISessionManager _sessionManager; private readonly ILogger _logger; - private readonly object _progressLock = new(); + private readonly Lock _progressLock = new(); private Timer _progressTimer; private PlaybackProgressInfo _lastProgressInfo; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a34238cd6..e084bda27 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly AsyncNonKeyedLocker _thumbnailResourcePool; - private readonly object _runningProcessesLock = new object(); + private readonly Lock _runningProcessesLock = new(); private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>(); // MediaEncoder is registered as a Singleton diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index bc4e6ef73..623a901c9 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -276,4 +276,9 @@ public class ServerConfiguration : BaseApplicationConfiguration /// </summary> /// <value>The trickplay options.</value> public TrickplayOptions TrickplayOptions { get; set; } = new TrickplayOptions(); + + /// <summary> + /// Gets or sets a value indicating whether old authorization methods are allowed. + /// </summary> + public bool EnableLegacyAuthorization { get; set; } = true; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 1ae4e1962..e44152213 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -979,7 +979,7 @@ public class StreamInfo } list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); - list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); + list.Add(new NameValuePair("ApiKey", accessToken ?? string.Empty)); string? liveStreamId = item.MediaSource?.LiveStreamId; list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); @@ -1189,7 +1189,7 @@ public class StreamInfo if (!string.IsNullOrEmpty(accessToken)) { - info.Url += "?api_key=" + accessToken; + info.Url += "?ApiKey=" + accessToken; } info.IsExternalUrl = false; diff --git a/MediaBrowser.Model/Extensions/ContainerHelper.cs b/MediaBrowser.Model/Extensions/ContainerHelper.cs index c86328ba6..39e5358ba 100644 --- a/MediaBrowser.Model/Extensions/ContainerHelper.cs +++ b/MediaBrowser.Model/Extensions/ContainerHelper.cs @@ -14,7 +14,8 @@ public static class ContainerHelper /// in <paramref name="profileContainers"/>. /// </summary> /// <param name="profileContainers">The comma-delimited string being searched. - /// If the parameter begins with the <c>-</c> character, the operation is reversed.</param> + /// If the parameter begins with the <c>-</c> character, the operation is reversed. + /// If the parameter is empty or null, all containers in <paramref name="inputContainer"/> will be accepted.</param> /// <param name="inputContainer">The comma-delimited string being matched.</param> /// <returns>The result of the operation.</returns> public static bool ContainsContainer(string? profileContainers, string? inputContainer) @@ -34,7 +35,8 @@ public static class ContainerHelper /// in <paramref name="profileContainers"/>. /// </summary> /// <param name="profileContainers">The comma-delimited string being searched. - /// If the parameter begins with the <c>-</c> character, the operation is reversed.</param> + /// If the parameter begins with the <c>-</c> character, the operation is reversed. + /// If the parameter is empty or null, all containers in <paramref name="inputContainer"/> will be accepted.</param> /// <param name="inputContainer">The comma-delimited string being matched.</param> /// <returns>The result of the operation.</returns> public static bool ContainsContainer(string? profileContainers, ReadOnlySpan<char> inputContainer) @@ -53,7 +55,8 @@ public static class ContainerHelper /// Compares two containers, returning <paramref name="isNegativeList"/> if an item in <paramref name="inputContainer"/> /// does not exist in <paramref name="profileContainers"/>. /// </summary> - /// <param name="profileContainers">The comma-delimited string being searched.</param> + /// <param name="profileContainers">The comma-delimited string being searched. + /// If the parameter is empty or null, all containers in <paramref name="inputContainer"/> will be accepted.</param> /// <param name="isNegativeList">The boolean result to return if a match is not found.</param> /// <param name="inputContainer">The comma-delimited string being matched.</param> /// <returns>The result of the operation.</returns> @@ -71,7 +74,8 @@ public static class ContainerHelper /// Compares two containers, returning <paramref name="isNegativeList"/> if an item in <paramref name="inputContainer"/> /// does not exist in <paramref name="profileContainers"/>. /// </summary> - /// <param name="profileContainers">The comma-delimited string being searched.</param> + /// <param name="profileContainers">The comma-delimited string being searched. + /// If the parameter is empty or null, all containers in <paramref name="inputContainer"/> will be accepted.</param> /// <param name="isNegativeList">The boolean result to return if a match is not found.</param> /// <param name="inputContainer">The comma-delimited string being matched.</param> /// <returns>The result of the operation.</returns> @@ -106,7 +110,8 @@ public static class ContainerHelper /// Compares two containers, returning <paramref name="isNegativeList"/> if an item in <paramref name="inputContainer"/> /// does not exist in <paramref name="profileContainers"/>. /// </summary> - /// <param name="profileContainers">The profile containers being matched searched.</param> + /// <param name="profileContainers">The profile containers being matched searched. + /// If the parameter is empty or null, all containers in <paramref name="inputContainer"/> will be accepted.</param> /// <param name="isNegativeList">The boolean result to return if a match is not found.</param> /// <param name="inputContainer">The comma-delimited string being matched.</param> /// <returns>The result of the operation.</returns> diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 7e36467de..6813cfa91 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Manager /// </summary> public class ProviderManager : IProviderManager, IDisposable { - private readonly object _refreshQueueLock = new(); + private readonly Lock _refreshQueueLock = new(); private readonly ILogger<ProviderManager> _logger; private readonly IHttpClientFactory _httpClientFactory; private readonly ILibraryMonitor _libraryMonitor; diff --git a/src/Jellyfin.LiveTv/Listings/ListingsManager.cs b/src/Jellyfin.LiveTv/Listings/ListingsManager.cs index 3df2d0d2c..39c2bd375 100644 --- a/src/Jellyfin.LiveTv/Listings/ListingsManager.cs +++ b/src/Jellyfin.LiveTv/Listings/ListingsManager.cs @@ -230,10 +230,15 @@ public class ListingsManager : IListingsManager var listingsProviderInfo = config.ListingProviders .First(info => string.Equals(providerId, info.Id, StringComparison.OrdinalIgnoreCase)); + var channelMappingExists = listingsProviderInfo.ChannelMappings + .Any(pair => string.Equals(pair.Name, tunerChannelNumber, StringComparison.OrdinalIgnoreCase) + && string.Equals(pair.Value, providerChannelNumber, StringComparison.OrdinalIgnoreCase)); + listingsProviderInfo.ChannelMappings = listingsProviderInfo.ChannelMappings .Where(pair => !string.Equals(pair.Name, tunerChannelNumber, StringComparison.OrdinalIgnoreCase)).ToArray(); - if (!string.Equals(tunerChannelNumber, providerChannelNumber, StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(tunerChannelNumber, providerChannelNumber, StringComparison.OrdinalIgnoreCase) + && !channelMappingExists) { var newItem = new NameValuePair { diff --git a/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs b/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs index 7dc30f727..7938b7a6e 100644 --- a/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs +++ b/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs @@ -84,10 +84,11 @@ namespace Jellyfin.LiveTv.Listings _logger.LogInformation("Downloading xmltv listings from {Path}", info.Path); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(info.Path, cancellationToken).ConfigureAwait(false); + var redirectedUrl = response.RequestMessage?.RequestUri?.ToString() ?? info.Path; var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using (stream.ConfigureAwait(false)) { - return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false); + return await UnzipIfNeededAndCopy(redirectedUrl, stream, cacheFile, cancellationToken).ConfigureAwait(false); } } else @@ -112,7 +113,8 @@ namespace Jellyfin.LiveTv.Listings await using (fileStream.ConfigureAwait(false)) { - if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase)) + if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase) || + Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gzip", StringComparison.OrdinalIgnoreCase)) { try { diff --git a/src/Jellyfin.LiveTv/Timers/ItemDataProvider.cs b/src/Jellyfin.LiveTv/Timers/ItemDataProvider.cs index 9e7323f5b..6a68b8c25 100644 --- a/src/Jellyfin.LiveTv/Timers/ItemDataProvider.cs +++ b/src/Jellyfin.LiveTv/Timers/ItemDataProvider.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.Json; +using System.Threading; using Jellyfin.Extensions.Json; using Microsoft.Extensions.Logging; @@ -15,7 +16,7 @@ namespace Jellyfin.LiveTv.Timers where T : class { private readonly string _dataPath; - private readonly object _fileDataLock = new object(); + private readonly Lock _fileDataLock = new(); private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private T[]? _items; diff --git a/src/Jellyfin.Networking/Manager/NetworkManager.cs b/src/Jellyfin.Networking/Manager/NetworkManager.cs index 10aed673b..b1fc5d406 100644 --- a/src/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/src/Jellyfin.Networking/Manager/NetworkManager.cs @@ -27,7 +27,7 @@ public class NetworkManager : INetworkManager, IDisposable /// <summary> /// Threading lock for network properties. /// </summary> - private readonly object _initLock; + private readonly Lock _initLock; private readonly ILogger<NetworkManager> _logger; @@ -35,7 +35,7 @@ public class NetworkManager : INetworkManager, IDisposable private readonly IConfiguration _startupConfig; - private readonly object _networkEventLock; + private readonly Lock _networkEventLock; /// <summary> /// Holds the published server URLs and the IPs to use them on. @@ -93,7 +93,7 @@ public class NetworkManager : INetworkManager, IDisposable _interfaces = new List<IPData>(); _macAddresses = new List<PhysicalAddress>(); _publishedServerUrls = new List<PublishedServerUriOverride>(); - _networkEventLock = new object(); + _networkEventLock = new(); _remoteAddressFilter = new List<IPNetwork>(); _ = bool.TryParse(startupConfig[DetectNetworkChangeKey], out var detectNetworkChange); diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs index 125229ff9..d58a62cc8 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs @@ -1,5 +1,6 @@ using System.Text.Json; using FsCheck; +using FsCheck.Fluent; using FsCheck.Xunit; using Jellyfin.Extensions.Json.Converters; using Xunit; diff --git a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs index 0a4e060df..c710df082 100644 --- a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs +++ b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs @@ -1,5 +1,6 @@ using System; using FsCheck; +using FsCheck.Fluent; using FsCheck.Xunit; using MediaBrowser.Model.Extensions; using Xunit; diff --git a/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs b/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs index 01546aa2b..4ebd54786 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs @@ -1,4 +1,5 @@ using FsCheck; +using FsCheck.Fluent; using FsCheck.Xunit; using MediaBrowser.Common.Net; using Xunit; |
