aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci-codeql-analysis.yml6
-rw-r--r--.github/workflows/ci-openapi.yml4
-rw-r--r--.github/workflows/ci-tests.yml12
-rw-r--r--Directory.Packages.props8
-rw-r--r--Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs18
-rw-r--r--Emby.Server.Implementations/Images/DynamicImageProvider.cs8
-rw-r--r--Emby.Server.Implementations/Library/ExclusiveLiveStream.cs7
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs6
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs34
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs4
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs22
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs45
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs18
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs8
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs51
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs25
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs17
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs29
-rw-r--r--Emby.Server.Implementations/Localization/Core/ab.json1
-rw-r--r--Emby.Server.Implementations/Localization/Core/fa.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/hy.json35
-rw-r--r--Emby.Server.Implementations/Localization/Core/tr.json2
-rw-r--r--Emby.Server.Implementations/Localization/countries.json2
-rw-r--r--Emby.Server.Implementations/Playlists/PlaylistsFolder.cs2
-rw-r--r--Jellyfin.Api/Controllers/GenresController.cs4
-rw-r--r--Jellyfin.Api/Controllers/ItemUpdateController.cs2
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs2
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs18
-rw-r--r--Jellyfin.Data/Enums/CollectionType.cs57
-rw-r--r--Jellyfin.Server.Implementations/Devices/DeviceManager.cs25
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs2
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs18
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs68
-rw-r--r--MediaBrowser.Controller/Library/ILiveStream.cs3
-rw-r--r--MediaBrowser.Controller/LiveTv/ITunerHost.cs2
-rw-r--r--MediaBrowser.Model/Devices/DeviceInfo.cs2
-rwxr-xr-xdeployment/build.centos.amd648
-rwxr-xr-xdeployment/build.debian.amd648
-rwxr-xr-xdeployment/build.debian.arm648
-rwxr-xr-xdeployment/build.debian.armhf8
-rwxr-xr-xdeployment/build.fedora.amd648
-rwxr-xr-xdeployment/build.linux.amd648
-rwxr-xr-xdeployment/build.linux.amd64-musl8
-rwxr-xr-xdeployment/build.linux.arm648
-rwxr-xr-xdeployment/build.linux.armhf8
-rwxr-xr-xdeployment/build.linux.musl-linux-arm648
-rwxr-xr-xdeployment/build.macos.amd648
-rwxr-xr-xdeployment/build.macos.arm648
-rwxr-xr-xdeployment/build.portable8
-rwxr-xr-xdeployment/build.ubuntu.amd648
-rwxr-xr-xdeployment/build.ubuntu.arm648
-rwxr-xr-xdeployment/build.ubuntu.armhf8
-rwxr-xr-xdeployment/build.windows.amd648
-rw-r--r--tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs2
-rw-r--r--tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs40
-rw-r--r--tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs32
-rw-r--r--tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs2
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json13
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json13
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-aac-srt-2600k.json102
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs3
-rw-r--r--tests/Jellyfin.Networking.Tests/Configuration/NetworkConfigurationTests.cs1
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs4
-rw-r--r--tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs5
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs2
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs4
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs2
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs4
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/SessionManager/SessionManagerTests.cs2
84 files changed, 593 insertions, 385 deletions
diff --git a/.github/workflows/ci-codeql-analysis.yml b/.github/workflows/ci-codeql-analysis.yml
index 89f9c59d7..7c0733598 100644
--- a/.github/workflows/ci-codeql-analysis.yml
+++ b/.github/workflows/ci-codeql-analysis.yml
@@ -27,11 +27,11 @@ jobs:
dotnet-version: '8.0.x'
- name: Initialize CodeQL
- uses: github/codeql-action/init@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
+ uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
with:
languages: ${{ matrix.language }}
queries: +security-extended
- name: Autobuild
- uses: github/codeql-action/autobuild@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
+ uses: github/codeql-action/autobuild@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
+ uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
diff --git a/.github/workflows/ci-openapi.yml b/.github/workflows/ci-openapi.yml
index 5ff9820cb..c9f17429a 100644
--- a/.github/workflows/ci-openapi.yml
+++ b/.github/workflows/ci-openapi.yml
@@ -78,12 +78,12 @@ jobs:
- openapi-base
steps:
- name: Download openapi-head
- uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0
+ uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0
with:
name: openapi-head
path: openapi-head
- name: Download openapi-base
- uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0
+ uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0
with:
name: openapi-base
path: openapi-base
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 60c0ef9cb..0dacbc5c6 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -19,9 +19,9 @@ jobs:
runs-on: "${{ matrix.os }}"
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4
+ - uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
with:
dotnet-version: ${{ env.SDK_VERSION }}
@@ -34,7 +34,7 @@ jobs:
--verbosity minimal
- name: Merge code coverage results
- uses: danielpalme/ReportGenerator-GitHub-Action@4d510cbed8a05af5aefea46c7fd6e05b95844c89 # 5
+ uses: danielpalme/ReportGenerator-GitHub-Action@4d510cbed8a05af5aefea46c7fd6e05b95844c89 # 5.2.0
with:
reports: "**/coverage.cobertura.xml"
targetdir: "merged/"
@@ -42,9 +42,3 @@ jobs:
# TODO - which action / tool to use to publish code coverage results?
# - name: Publish code coverage results
-
- - name: Publish OpenAPI Artifact
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4
- with:
- name: "OpenAPI Spec"
- path: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net*/openapi.json"
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ff76252f8..90280d98b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -15,7 +15,7 @@
<PackageVersion Include="Diacritics" Version="3.3.18" />
<PackageVersion Include="DiscUtils.Udf" Version="0.16.13" />
<PackageVersion Include="DotNet.Glob" Version="3.1.3" />
- <PackageVersion Include="EFCoreSecondLevelCacheInterceptor" Version="4.0.0" />
+ <PackageVersion Include="EFCoreSecondLevelCacheInterceptor" Version="4.1.1" />
<PackageVersion Include="FsCheck.Xunit" Version="2.16.6" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0" />
<PackageVersion Include="IDisposableAnalyzers" Version="4.0.4" />
@@ -70,7 +70,7 @@
<PackageVersion Include="SkiaSharp.HarfBuzz" Version="2.88.5" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.5" />
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
- <PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.507" />
+ <PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="Svg.Skia" Version="1.0.0.2" />
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.5.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.3" />
@@ -83,8 +83,8 @@
<PackageVersion Include="TMDbLib" Version="2.1.0" />
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
- <PackageVersion Include="xunit.runner.visualstudio" Version="2.5.3" />
+ <PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
- <PackageVersion Include="xunit" Version="2.6.1" />
+ <PackageVersion Include="xunit" Version="2.6.4" />
</ItemGroup>
</Project>
diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
index 6e8f77977..34c722e41 100644
--- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
+++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
@@ -32,26 +32,26 @@ namespace Emby.Server.Implementations.Images
switch (viewType)
{
- case CollectionType.Movies:
+ case CollectionType.movies:
includeItemTypes = new[] { BaseItemKind.Movie };
break;
- case CollectionType.TvShows:
+ case CollectionType.tvshows:
includeItemTypes = new[] { BaseItemKind.Series };
break;
- case CollectionType.Music:
+ case CollectionType.music:
includeItemTypes = new[] { BaseItemKind.MusicAlbum };
break;
- case CollectionType.MusicVideos:
+ case CollectionType.musicvideos:
includeItemTypes = new[] { BaseItemKind.MusicVideo };
break;
- case CollectionType.Books:
+ case CollectionType.books:
includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook };
break;
- case CollectionType.BoxSets:
+ case CollectionType.boxsets:
includeItemTypes = new[] { BaseItemKind.BoxSet };
break;
- case CollectionType.HomeVideos:
- case CollectionType.Photos:
+ case CollectionType.homevideos:
+ case CollectionType.photos:
includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Photo };
break;
default:
@@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Images
break;
}
- var recursive = viewType != CollectionType.Playlists;
+ var recursive = viewType != CollectionType.playlists;
return view.GetItemList(new InternalItemsQuery
{
diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs
index 5de53df73..6b2ae23b3 100644
--- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs
+++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs
@@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Images
var view = (UserView)item;
var isUsingCollectionStrip = IsUsingCollectionStrip(view);
- var recursive = isUsingCollectionStrip && view?.ViewType is not null && view.ViewType != CollectionType.BoxSets && view.ViewType != CollectionType.Playlists;
+ var recursive = isUsingCollectionStrip && view?.ViewType is not null && view.ViewType != CollectionType.boxsets && view.ViewType != CollectionType.playlists;
var result = view.GetItemList(new InternalItemsQuery
{
@@ -114,9 +114,9 @@ namespace Emby.Server.Implementations.Images
{
CollectionType[] collectionStripViewTypes =
{
- CollectionType.Movies,
- CollectionType.TvShows,
- CollectionType.Playlists
+ CollectionType.movies,
+ CollectionType.tvshows,
+ CollectionType.playlists
};
return view?.ViewType is not null && collectionStripViewTypes.Contains(view.ViewType.Value);
diff --git a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs
index 868071a99..b1649afad 100644
--- a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs
+++ b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs
@@ -12,7 +12,7 @@ using MediaBrowser.Model.Dto;
namespace Emby.Server.Implementations.Library
{
- public class ExclusiveLiveStream : ILiveStream
+ public sealed class ExclusiveLiveStream : ILiveStream
{
private readonly Func<Task> _closeFn;
@@ -51,5 +51,10 @@ namespace Emby.Server.Implementations.Library
{
return Task.CompletedTask;
}
+
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ }
}
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index f40177fa7..a79ffd9cb 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1514,7 +1514,7 @@ namespace Emby.Server.Implementations.Library
{
if (item is UserView view)
{
- if (view.ViewType == CollectionType.LiveTv)
+ if (view.ViewType == CollectionType.livetv)
{
return new[] { view.Id };
}
@@ -1543,7 +1543,7 @@ namespace Emby.Server.Implementations.Library
}
// Handle grouping
- if (user is not null && view.ViewType != CollectionType.Unknown && UserView.IsEligibleForGrouping(view.ViewType)
+ if (user is not null && view.ViewType != CollectionType.unknown && UserView.IsEligibleForGrouping(view.ViewType)
&& user.GetPreference(PreferenceKind.GroupedFolders).Length > 0)
{
return GetUserRootFolder()
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
index ac423ed09..dbf05c1db 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
@@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
List<FileSystemMetadata> files,
CollectionType? collectionType)
{
- if (collectionType == CollectionType.Books)
+ if (collectionType == CollectionType.books)
{
return ResolveMultipleAudio(parent, files, true);
}
@@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
var collectionType = args.GetCollectionType();
- var isBooksCollectionType = collectionType == CollectionType.Books;
+ var isBooksCollectionType = collectionType == CollectionType.books;
if (args.IsDirectory)
{
@@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
MediaBrowser.Controller.Entities.Audio.Audio item = null;
- var isMusicCollectionType = collectionType == CollectionType.Music;
+ var isMusicCollectionType = collectionType == CollectionType.music;
// Use regular audio type for mixed libraries, owned items and music
if (isMixedCollectionType ||
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index 06e292f4c..0bfb7fbe6 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -55,7 +55,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
protected override MusicAlbum Resolve(ItemResolveArgs args)
{
var collectionType = args.GetCollectionType();
- var isMusicMediaFolder = collectionType == CollectionType.Music;
+ var isMusicMediaFolder = collectionType == CollectionType.music;
// If there's a collection type and it's not music, don't allow it.
if (!isMusicMediaFolder)
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index 7d6f97b12..1bdae7f62 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
var collectionType = args.GetCollectionType();
- var isMusicMediaFolder = collectionType == CollectionType.Music;
+ var isMusicMediaFolder = collectionType == CollectionType.music;
// If there's a collection type and it's not music, it can't be a music artist
if (!isMusicMediaFolder)
diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
index b76bfe427..464a548ab 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
@@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
var collectionType = args.GetCollectionType();
// Only process items that are in a collection folder containing books
- if (collectionType != CollectionType.Books)
+ if (collectionType != CollectionType.books)
{
return null;
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 50fd8b877..1a210e3cc 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -31,11 +31,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
private static readonly CollectionType[] _validCollectionTypes = new[]
{
- CollectionType.Movies,
- CollectionType.HomeVideos,
- CollectionType.MusicVideos,
- CollectionType.TvShows,
- CollectionType.Photos
+ CollectionType.movies,
+ CollectionType.homevideos,
+ CollectionType.musicvideos,
+ CollectionType.tvshows,
+ CollectionType.photos
};
/// <summary>
@@ -100,12 +100,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
Video movie = null;
var files = args.GetActualFileSystemChildren().ToList();
- if (collectionType == CollectionType.MusicVideos)
+ if (collectionType == CollectionType.musicvideos)
{
movie = FindMovie<MusicVideo>(args, args.Path, args.Parent, files, DirectoryService, collectionType, false);
}
- if (collectionType == CollectionType.HomeVideos)
+ if (collectionType == CollectionType.homevideos)
{
movie = FindMovie<Video>(args, args.Path, args.Parent, files, DirectoryService, collectionType, false);
}
@@ -126,7 +126,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
movie = FindMovie<Movie>(args, args.Path, args.Parent, files, DirectoryService, collectionType, true);
}
- if (collectionType == CollectionType.Movies)
+ if (collectionType == CollectionType.movies)
{
movie = FindMovie<Movie>(args, args.Path, args.Parent, files, DirectoryService, collectionType, true);
}
@@ -147,17 +147,17 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
Video item = null;
- if (collectionType == CollectionType.MusicVideos)
+ if (collectionType == CollectionType.musicvideos)
{
item = ResolveVideo<MusicVideo>(args, false);
}
// To find a movie file, the collection type must be movies or boxsets
- else if (collectionType == CollectionType.Movies)
+ else if (collectionType == CollectionType.movies)
{
item = ResolveVideo<Movie>(args, true);
}
- else if (collectionType == CollectionType.HomeVideos || collectionType == CollectionType.Photos)
+ else if (collectionType == CollectionType.homevideos || collectionType == CollectionType.photos)
{
item = ResolveVideo<Video>(args, false);
}
@@ -195,12 +195,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return null;
}
- if (collectionType is CollectionType.MusicVideos)
+ if (collectionType is CollectionType.musicvideos)
{
return ResolveVideos<MusicVideo>(parent, files, true, collectionType, false);
}
- if (collectionType == CollectionType.HomeVideos || collectionType == CollectionType.Photos)
+ if (collectionType == CollectionType.homevideos || collectionType == CollectionType.photos)
{
return ResolveVideos<Video>(parent, files, false, collectionType, false);
}
@@ -221,12 +221,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return ResolveVideos<Movie>(parent, files, false, collectionType, true);
}
- if (collectionType == CollectionType.Movies)
+ if (collectionType == CollectionType.movies)
{
return ResolveVideos<Movie>(parent, files, true, collectionType, true);
}
- if (collectionType == CollectionType.TvShows)
+ if (collectionType == CollectionType.tvshows)
{
return ResolveVideos<Episode>(parent, files, false, collectionType, true);
}
@@ -403,7 +403,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
var multiDiscFolders = new List<FileSystemMetadata>();
var libraryOptions = args.LibraryOptions;
- var supportPhotos = collectionType == CollectionType.HomeVideos && libraryOptions.EnablePhotos;
+ var supportPhotos = collectionType == CollectionType.homevideos && libraryOptions.EnablePhotos;
var photos = new List<FileSystemMetadata>();
// Search for a folder rip
@@ -459,7 +459,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
var result = ResolveVideos<T>(parent, fileSystemEntries, SupportsMultiVersion, collectionType, parseName) ??
new MultiItemResolverResult();
- var isPhotosCollection = collectionType == CollectionType.HomeVideos || collectionType == CollectionType.Photos;
+ var isPhotosCollection = collectionType == CollectionType.homevideos || collectionType == CollectionType.photos;
if (!isPhotosCollection && result.Items.Count == 1)
{
var videoPath = result.Items[0].Path;
diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
index 29d540700..c0b00caaf 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
@@ -46,8 +46,8 @@ namespace Emby.Server.Implementations.Library.Resolvers
// Must be an image file within a photo collection
var collectionType = args.GetCollectionType();
- if (collectionType == CollectionType.Photos
- || (collectionType == CollectionType.HomeVideos && args.LibraryOptions.EnablePhotos))
+ if (collectionType == CollectionType.photos
+ || (collectionType == CollectionType.homevideos && args.LibraryOptions.EnablePhotos))
{
if (HasPhotos(args))
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index d166ac37f..0934555b2 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -61,8 +61,8 @@ namespace Emby.Server.Implementations.Library.Resolvers
// Must be an image file within a photo collection
var collectionType = args.CollectionType;
- if (collectionType == CollectionType.Photos
- || (collectionType == CollectionType.HomeVideos && args.LibraryOptions.EnablePhotos))
+ if (collectionType == CollectionType.photos
+ || (collectionType == CollectionType.homevideos && args.LibraryOptions.EnablePhotos))
{
if (IsImageFile(args.Path, _imageProcessor))
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
index d4b3722c9..a50435ae6 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
@@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
private CollectionType?[] _musicPlaylistCollectionTypes =
{
null,
- CollectionType.Music
+ CollectionType.music
};
/// <inheritdoc/>
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
index 8274881be..5fd23c9f5 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
@@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
// If the parent is a Season or Series and the parent is not an extras folder, then this is an Episode if the VideoResolver returns something
// Also handle flat tv folders
if (season is not null
- || args.GetCollectionType() == CollectionType.TvShows
+ || args.GetCollectionType() == CollectionType.tvshows
|| args.HasParent<Series>())
{
var episode = ResolveVideo<Episode>(args, false);
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 2ae1138a5..1484c34bc 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -60,11 +60,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
var seriesInfo = Naming.TV.SeriesResolver.Resolve(_namingOptions, args.Path);
var collectionType = args.GetCollectionType();
- if (collectionType == CollectionType.TvShows)
+ if (collectionType == CollectionType.tvshows)
{
// TODO refactor into separate class or something, this is copied from LibraryManager.GetConfiguredContentType
var configuredContentType = args.GetConfiguredContentType();
- if (configuredContentType != CollectionType.TvShows)
+ if (configuredContentType != CollectionType.tvshows)
{
return new Series
{
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index 113370fc3..1d662ed8d 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Library
var folderViewType = collectionFolder?.CollectionType;
// Playlist library requires special handling because the folder only references user playlists
- if (folderViewType == CollectionType.Playlists)
+ if (folderViewType == CollectionType.playlists)
{
var items = folder.GetItemList(new InternalItemsQuery(user)
{
@@ -99,14 +99,14 @@ namespace Emby.Server.Implementations.Library
}
}
- foreach (var viewType in new[] { CollectionType.Movies, CollectionType.TvShows })
+ foreach (var viewType in new[] { CollectionType.movies, CollectionType.tvshows })
{
var parents = groupedFolders.Where(i => i.CollectionType == viewType || i.CollectionType is null)
.ToList();
if (parents.Count > 0)
{
- var localizationKey = viewType == CollectionType.TvShows
+ var localizationKey = viewType == CollectionType.tvshows
? "TvShows"
: "Movies";
@@ -117,7 +117,7 @@ namespace Emby.Server.Implementations.Library
if (_config.Configuration.EnableFolderView)
{
var name = _localizationManager.GetLocalizedString("Folders");
- list.Add(_libraryManager.GetNamedView(name, CollectionType.Folders, string.Empty));
+ list.Add(_libraryManager.GetNamedView(name, CollectionType.folders, string.Empty));
}
if (query.IncludeExternalContent)
@@ -279,7 +279,7 @@ namespace Emby.Server.Implementations.Library
var isPlayed = request.IsPlayed;
- if (parents.OfType<ICollectionFolder>().Any(i => i.CollectionType == CollectionType.Music))
+ if (parents.OfType<ICollectionFolder>().Any(i => i.CollectionType == CollectionType.music))
{
isPlayed = null;
}
@@ -305,11 +305,11 @@ namespace Emby.Server.Implementations.Library
var hasCollectionType = parents.OfType<UserView>().ToArray();
if (hasCollectionType.Length > 0)
{
- if (hasCollectionType.All(i => i.CollectionType == CollectionType.Movies))
+ if (hasCollectionType.All(i => i.CollectionType == CollectionType.movies))
{
includeItemTypes = new[] { BaseItemKind.Movie };
}
- else if (hasCollectionType.All(i => i.CollectionType == CollectionType.TvShows))
+ else if (hasCollectionType.All(i => i.CollectionType == CollectionType.tvshows))
{
includeItemTypes = new[] { BaseItemKind.Episode };
}
@@ -324,18 +324,18 @@ namespace Emby.Server.Implementations.Library
{
switch (parent.CollectionType)
{
- case CollectionType.Books:
+ case CollectionType.books:
mediaTypes.Add(MediaType.Book);
mediaTypes.Add(MediaType.Audio);
break;
- case CollectionType.Music:
+ case CollectionType.music:
mediaTypes.Add(MediaType.Audio);
break;
- case CollectionType.Photos:
+ case CollectionType.photos:
mediaTypes.Add(MediaType.Photo);
mediaTypes.Add(MediaType.Video);
break;
- case CollectionType.HomeVideos:
+ case CollectionType.homevideos:
mediaTypes.Add(MediaType.Photo);
mediaTypes.Add(MediaType.Video);
break;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 49833de73..ddf7b882a 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
- public class DirectRecorder : IRecorder
+ public sealed class DirectRecorder : IRecorder
{
private readonly ILogger _logger;
private readonly IHttpClientFactory _httpClientFactory;
@@ -46,7 +46,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
- await using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ var output = new FileStream(
+ targetFile,
+ FileMode.CreateNew,
+ FileAccess.Write,
+ FileShare.Read,
+ IODefaults.FileStreamBufferSize,
+ FileOptions.Asynchronous);
+
+ await using (output.ConfigureAwait(false))
{
onStarted();
@@ -80,24 +88,31 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
- await using var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
+ var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
+ await using (output.ConfigureAwait(false))
+ {
+ onStarted();
- onStarted();
+ _logger.LogInformation("Copying recording stream to file {0}", targetFile);
- _logger.LogInformation("Copying recording stream to file {0}", targetFile);
+ // The media source if infinite so we need to handle stopping ourselves
+ using var durationToken = new CancellationTokenSource(duration);
+ using var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
+ cancellationToken = linkedCancellationToken.Token;
- // The media source if infinite so we need to handle stopping ourselves
- using var durationToken = new CancellationTokenSource(duration);
- using var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
- cancellationToken = linkedCancellationToken.Token;
+ await _streamHelper.CopyUntilCancelled(
+ await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false),
+ output,
+ IODefaults.CopyToBufferSize,
+ cancellationToken).ConfigureAwait(false);
- await _streamHelper.CopyUntilCancelled(
- await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false),
- output,
- IODefaults.CopyToBufferSize,
- cancellationToken).ConfigureAwait(false);
+ _logger.LogInformation("Recording completed to file {0}", targetFile);
+ }
+ }
- _logger.LogInformation("Recording completed to file {0}", targetFile);
+ /// <inheritdoc />
+ public void Dispose()
+ {
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 74b62ca3f..abe3ff349 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -37,12 +37,11 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
- public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable
+ public sealed class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable
{
public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
@@ -74,7 +73,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1);
- private bool _disposed = false;
+ private bool _disposed;
public EmbyTV(
IServerApplicationHost appHost,
@@ -1270,7 +1269,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
directStreamProvider = liveStreamResponse.Item2;
}
- var recorder = GetRecorder(mediaStreamInfo);
+ using var recorder = GetRecorder(mediaStreamInfo);
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
recordPath = EnsureFileUnique(recordPath, timer.Id);
@@ -2525,21 +2524,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
/// <inheritdoc />
public void Dispose()
{
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
if (_disposed)
{
return;
}
- if (disposing)
- {
- _recordingDeleteSemaphore.Dispose();
- }
+ _recordingDeleteSemaphore.Dispose();
foreach (var pair in _activeRecordings.ToList())
{
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 5369c9b3d..9a9fd0273 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -25,7 +25,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
- public class EncodedRecorder : IRecorder, IDisposable
+ public class EncodedRecorder : IRecorder
{
private readonly ILogger _logger;
private readonly IMediaEncoder _mediaEncoder;
@@ -34,10 +34,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private bool _hasExited;
- private Stream _logFileStream;
+ private FileStream _logFileStream;
private string _targetPath;
private Process _process;
- private bool _disposed = false;
+ private bool _disposed;
public EncodedRecorder(
ILogger logger,
@@ -308,7 +308,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private async Task StartStreamingLog(Stream source, Stream target)
+ private async Task StartStreamingLog(Stream source, FileStream target)
{
try
{
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
index 7705132da..de14d6d08 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
@@ -8,7 +8,7 @@ using MediaBrowser.Model.Dto;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
- public interface IRecorder
+ public interface IRecorder : IDisposable
{
/// <summary>
/// Records the specified media source.
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index 6b0520ad0..5be3a7488 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -287,7 +287,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
IsMovie = IsMovie(details),
Etag = programInfo.Md5,
IsLive = string.Equals(programInfo.LiveTapeDelay, "live", StringComparison.OrdinalIgnoreCase),
- IsPremiere = programInfo.Premiere || (programInfo.IsPremiereOrFinale ?? string.Empty).IndexOf("premiere", StringComparison.OrdinalIgnoreCase) != -1
+ IsPremiere = programInfo.Premiere || (programInfo.IsPremiereOrFinale ?? string.Empty).Contains("premiere", StringComparison.OrdinalIgnoreCase)
};
var showId = programId;
@@ -414,7 +414,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return null;
}
- if (uri.IndexOf("http", StringComparison.OrdinalIgnoreCase) != -1)
+ if (uri.Contains("http", StringComparison.OrdinalIgnoreCase))
{
return uri;
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index 066afb956..e60e9dcc1 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -84,38 +84,53 @@ namespace Emby.Server.Implementations.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);
- await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false);
+ var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+ await using (stream.ConfigureAwait(false))
+ {
+ return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false);
+ }
}
else
{
- await using var stream = AsyncFile.OpenRead(info.Path);
- return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false);
+ var stream = AsyncFile.OpenRead(info.Path);
+ await using (stream.ConfigureAwait(false))
+ {
+ return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false);
+ }
}
}
private async Task<string> UnzipIfNeededAndCopy(string originalUrl, Stream stream, string file, CancellationToken cancellationToken)
{
- await using var fileStream = new FileStream(file, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
-
- if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase))
+ var fileStream = new FileStream(
+ file,
+ FileMode.CreateNew,
+ FileAccess.Write,
+ FileShare.None,
+ IODefaults.FileStreamBufferSize,
+ FileOptions.Asynchronous);
+
+ await using (fileStream.ConfigureAwait(false))
{
- try
+ if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase))
{
- using var reader = new GZipStream(stream, CompressionMode.Decompress);
- await reader.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ using var reader = new GZipStream(stream, CompressionMode.Decompress);
+ await reader.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error extracting from gz file {File}", originalUrl);
+ }
}
- catch (Exception ex)
+ else
{
- _logger.LogError(ex, "Error extracting from gz file {File}", originalUrl);
+ await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
- }
- else
- {
- await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
- }
- return file;
+ return file;
+ }
}
public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index dd427c736..0544e2a4b 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1101,7 +1101,7 @@ namespace Emby.Server.Implementations.LiveTv
progress.Report(100);
}
- private async Task<Tuple<List<Guid>, List<Guid>>> RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken)
+ private async Task<Tuple<List<Guid>, List<Guid>>> RefreshChannelsInternal(ILiveTvService service, ActionableProgress<double> progress, CancellationToken cancellationToken)
{
progress.Report(10);
@@ -2168,7 +2168,7 @@ namespace Emby.Server.Implementations.LiveTv
public Folder GetInternalLiveTvFolder(CancellationToken cancellationToken)
{
var name = _localization.GetLocalizedString("HeaderLiveTV");
- return _libraryManager.GetNamedView(name, CollectionType.LiveTv, name);
+ return _libraryManager.GetNamedView(name, CollectionType.livetv, name);
}
public async Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
index ff25ee585..da597056a 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
@@ -67,7 +67,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return list;
}
- protected virtual List<TunerHostInfo> GetTunerHosts()
+ protected virtual IList<TunerHostInfo> GetTunerHosts()
{
return GetConfiguration().TunerHosts
.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase))
@@ -96,8 +96,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
try
{
Directory.CreateDirectory(Path.GetDirectoryName(channelCacheFile));
- await using var writeStream = AsyncFile.OpenWrite(channelCacheFile);
- await JsonSerializer.SerializeAsync(writeStream, channels, cancellationToken: cancellationToken).ConfigureAwait(false);
+ var writeStream = AsyncFile.OpenWrite(channelCacheFile);
+ await using (writeStream.ConfigureAwait(false))
+ {
+ await JsonSerializer.SerializeAsync(writeStream, channels, cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
}
catch (IOException)
{
@@ -112,10 +115,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
try
{
- await using var readStream = AsyncFile.OpenRead(channelCacheFile);
- var channels = await JsonSerializer.DeserializeAsync<List<ChannelInfo>>(readStream, cancellationToken: cancellationToken)
- .ConfigureAwait(false);
- list.AddRange(channels);
+ var readStream = AsyncFile.OpenRead(channelCacheFile);
+ await using (readStream.ConfigureAwait(false))
+ {
+ var channels = await JsonSerializer
+ .DeserializeAsync<List<ChannelInfo>>(readStream, cancellationToken: cancellationToken)
+ .ConfigureAwait(false);
+ list.AddRange(channels);
+ }
}
catch (IOException)
{
@@ -159,9 +166,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return new List<MediaSourceInfo>();
}
- protected abstract Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
+ protected abstract Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, IList<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
- public async Task<ILiveStream> GetChannelStream(string channelId, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
+ public async Task<ILiveStream> GetChannelStream(string channelId, string streamId, IList<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
ArgumentException.ThrowIfNullOrEmpty(channelId);
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs
index 42068cd34..39b357142 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs
@@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
var model = ModelNumber ?? string.Empty;
- if (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)
+ if (model.Contains("hdtc", StringComparison.OrdinalIgnoreCase))
{
return true;
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 8cd0c4ffb..79e15a82e 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -527,7 +527,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return list;
}
- protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
+ protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, IList<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
var tunerCount = tunerHost.TunerCount;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
index 767b94136..c18594a29 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
@@ -112,6 +112,21 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return stream;
}
+ /// <inheritdoc />
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool dispose)
+ {
+ if (dispose)
+ {
+ LiveStreamCancellationTokenSource?.Dispose();
+ }
+ }
+
protected async Task DeleteTempFiles(string path, int retryCount = 0)
{
if (retryCount == 0)
@@ -134,7 +149,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
}
}
- private void TrySeek(Stream stream, long offset)
+ private void TrySeek(FileStream stream, long offset)
{
if (!stream.CanSeek)
{
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index db5e81df5..11bf03b18 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return Task.FromResult(list);
}
- protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
+ protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, IList<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
var tunerCount = tunerHost.TunerCount;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
index 341782d9d..0b5575b99 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
@@ -66,7 +66,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
.ConfigureAwait(false);
response.EnsureSuccessStatusCode();
- return await response.Content.ReadAsStreamAsync(cancellationToken);
+ return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
}
private async Task<List<ChannelInfo>> GetChannelsAsync(TextReader reader, string channelIdPrefix, string tunerHostId)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index 51f46f4da..efb84a515 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -83,14 +83,27 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
Logger.LogInformation("Beginning {StreamType} stream to {FilePath}", GetType().Name, TempFilePath);
using (response)
{
- await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
- await StreamHelper.CopyToAsync(
- stream,
- fileStream,
- IODefaults.CopyToBufferSize,
- () => Resolve(openTaskCompletionSource),
- cancellationToken).ConfigureAwait(false);
+ var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+ await using (stream.ConfigureAwait(false))
+ {
+ var fileStream = new FileStream(
+ TempFilePath,
+ FileMode.Create,
+ FileAccess.Write,
+ FileShare.Read,
+ IODefaults.FileStreamBufferSize,
+ FileOptions.Asynchronous);
+
+ await using (fileStream.ConfigureAwait(false))
+ {
+ await StreamHelper.CopyToAsync(
+ stream,
+ fileStream,
+ IODefaults.CopyToBufferSize,
+ () => Resolve(openTaskCompletionSource),
+ cancellationToken).ConfigureAwait(false);
+ }
+ }
}
}
catch (OperationCanceledException ex)
diff --git a/Emby.Server.Implementations/Localization/Core/ab.json b/Emby.Server.Implementations/Localization/Core/ab.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/ab.json
@@ -0,0 +1 @@
+{}
diff --git a/Emby.Server.Implementations/Localization/Core/fa.json b/Emby.Server.Implementations/Localization/Core/fa.json
index 8e4bba25b..8364ce236 100644
--- a/Emby.Server.Implementations/Localization/Core/fa.json
+++ b/Emby.Server.Implementations/Localization/Core/fa.json
@@ -124,5 +124,7 @@
"TaskKeyframeExtractorDescription": "فریم های کلیدی را از فایل های ویدئویی استخراج می کند تا لیست های پخش HLS دقیق تری ایجاد کند. این کار ممکن است برای مدت طولانی اجرا شود.",
"TaskKeyframeExtractor": "استخراج کننده فریم کلیدی",
"External": "خارجی",
- "HearingImpaired": "مشکل شنوایی"
+ "HearingImpaired": "مشکل شنوایی",
+ "TaskRefreshTrickplayImages": "تولید تصاویر Trickplay",
+ "TaskRefreshTrickplayImagesDescription": "تولید پیش‌نمایش های trickplay برای ویدیو های فعال شده در کتابخانه."
}
diff --git a/Emby.Server.Implementations/Localization/Core/hy.json b/Emby.Server.Implementations/Localization/Core/hy.json
new file mode 100644
index 000000000..c348836fe
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/hy.json
@@ -0,0 +1,35 @@
+{
+ "TasksLibraryCategory": "Գրադարան",
+ "TasksApplicationCategory": "Հավելված",
+ "TaskCleanActivityLog": "Մաքրել ակտիվության մատյանը",
+ "Application": "Հավելված",
+ "AuthenticationSucceededWithUserName": "{0} հաջողությամբ վավերականացվել են",
+ "Books": "Գրքեր",
+ "CameraImageUploadedFrom": "Նոր լուսանկար է վերբեռնվել {0}-ի կողմից",
+ "Channels": "Ալիքներ",
+ "DeviceOfflineWithName": "{0}ը անջատվեց",
+ "External": "Արտաքին",
+ "FailedLoginAttemptWithUserName": "Ձախողված մուտքի փործ {0}-ի կողմից",
+ "Folders": "Պանակներ",
+ "HeaderContinueWatching": "Շարունակել դիտումը",
+ "Inherit": "Ժառանգել",
+ "ItemAddedWithName": "{0}ը ավացված է գրադարանի մեջ",
+ "ItemRemovedWithName": "{0}ը հեռացված է գրադարանից",
+ "LabelIpAddressValue": "IP հասցե` {0}",
+ "Movies": "Ֆիլմեր",
+ "Music": "Երաժշտություն",
+ "NameSeasonNumber": "Սեզոն {0}",
+ "Photos": "Լուսանկարներ",
+ "PluginInstalledWithName": "{0}ն տեղադրված է",
+ "Songs": "Երգեր",
+ "System": "Համակարգ",
+ "TvShows": "Հեռուստասերիալներ",
+ "User": "Օգտատեր",
+ "VersionNumber": "Տարբերակ {0}",
+ "TasksMaintenanceCategory": "Սպասարկում",
+ "TasksChannelsCategory": "Ինտերնետային ալիքներ",
+ "TaskRefreshPeople": "Թարմացնել մարդկանց",
+ "TaskRefreshChannels": "Թարմացնել ալիքները",
+ "TaskDownloadMissingSubtitles": "Ներբեռնել պակասող ենթագրերը",
+ "Albums": "Ալբոմներ"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json
index a4877f4b5..6a04115fa 100644
--- a/Emby.Server.Implementations/Localization/Core/tr.json
+++ b/Emby.Server.Implementations/Localization/Core/tr.json
@@ -89,7 +89,7 @@
"UserPolicyUpdatedWithName": "{0} için kullanıcı politikası güncellendi",
"UserStartedPlayingItemWithValues": "{0}, {2} cihazında {1} izliyor",
"UserStoppedPlayingItemWithValues": "{0}, {2} cihazında {1} izlemeyi bitirdi",
- "ValueHasBeenAddedToLibrary": "Medya kütüphanenize {0} eklendi",
+ "ValueHasBeenAddedToLibrary": "{0} medya kütüphanenize eklendi",
"ValueSpecialEpisodeName": "Özel - {0}",
"VersionNumber": "Sürüm {0}",
"TaskCleanCache": "Önbellek Dizinini Temizle",
diff --git a/Emby.Server.Implementations/Localization/countries.json b/Emby.Server.Implementations/Localization/countries.json
index 22ffc5e09..0a11b3e45 100644
--- a/Emby.Server.Implementations/Localization/countries.json
+++ b/Emby.Server.Implementations/Localization/countries.json
@@ -696,7 +696,7 @@
"TwoLetterISORegionName": "SI"
},
{
- "DisplayName": "Soomaaliya",
+ "DisplayName": "Somalia",
"Name": "SO",
"ThreeLetterISORegionName": "SOM",
"TwoLetterISORegionName": "SO"
diff --git a/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs b/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs
index 5c616d534..f65d609c7 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs
@@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Playlists
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
- public override CollectionType? CollectionType => Jellyfin.Data.Enums.CollectionType.Playlists;
+ public override CollectionType? CollectionType => Jellyfin.Data.Enums.CollectionType.playlists;
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs
index 062e1062d..6cb1993e4 100644
--- a/Jellyfin.Api/Controllers/GenresController.cs
+++ b/Jellyfin.Api/Controllers/GenresController.cs
@@ -131,8 +131,8 @@ public class GenresController : BaseJellyfinApiController
QueryResult<(BaseItem, ItemCounts)> result;
if (parentItem is ICollectionFolder parentCollectionFolder
- && (parentCollectionFolder.CollectionType == CollectionType.Music
- || parentCollectionFolder.CollectionType == CollectionType.MusicVideos))
+ && (parentCollectionFolder.CollectionType == CollectionType.music
+ || parentCollectionFolder.CollectionType == CollectionType.musicvideos))
{
result = _libraryManager.GetMusicGenres(query);
}
diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs
index 4e5ed60d5..9800248c6 100644
--- a/Jellyfin.Api/Controllers/ItemUpdateController.cs
+++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs
@@ -171,7 +171,7 @@ public class ItemUpdateController : BaseJellyfinApiController
info.ContentTypeOptions = GetContentTypeOptions(true).ToArray();
info.ContentType = configuredContentType;
- if (inheritedContentType is null || inheritedContentType == CollectionType.TvShows)
+ if (inheritedContentType is null || inheritedContentType == CollectionType.tvshows)
{
info.ContentTypeOptions = info.ContentTypeOptions
.Where(i => string.IsNullOrWhiteSpace(i.Value)
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index ae80d15e6..a1fc8e11b 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -279,7 +279,7 @@ public class ItemsController : BaseJellyfinApiController
collectionType = hasCollectionType.CollectionType;
}
- if (collectionType == CollectionType.Playlists)
+ if (collectionType == CollectionType.playlists)
{
recursive = true;
includeItemTypes = new[] { BaseItemKind.Playlist };
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index af9a93719..de057bbab 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -927,15 +927,15 @@ public class LibraryController : BaseJellyfinApiController
{
return contentType switch
{
- CollectionType.BoxSets => new[] { "BoxSet" },
- CollectionType.Playlists => new[] { "Playlist" },
- CollectionType.Movies => new[] { "Movie" },
- CollectionType.TvShows => new[] { "Series", "Season", "Episode" },
- CollectionType.Books => new[] { "Book" },
- CollectionType.Music => new[] { "MusicArtist", "MusicAlbum", "Audio", "MusicVideo" },
- CollectionType.HomeVideos => new[] { "Video", "Photo" },
- CollectionType.Photos => new[] { "Video", "Photo" },
- CollectionType.MusicVideos => new[] { "MusicVideo" },
+ CollectionType.boxsets => new[] { "BoxSet" },
+ CollectionType.playlists => new[] { "Playlist" },
+ CollectionType.movies => new[] { "Movie" },
+ CollectionType.tvshows => new[] { "Series", "Season", "Episode" },
+ CollectionType.books => new[] { "Book" },
+ CollectionType.music => new[] { "MusicArtist", "MusicAlbum", "Audio", "MusicVideo" },
+ CollectionType.homevideos => new[] { "Video", "Photo" },
+ CollectionType.photos => new[] { "Video", "Photo" },
+ CollectionType.musicvideos => new[] { "MusicVideo" },
_ => new[] { "Series", "Season", "Episode", "Movie" }
};
}
diff --git a/Jellyfin.Data/Enums/CollectionType.cs b/Jellyfin.Data/Enums/CollectionType.cs
index e2044a0bc..e3d3b07af 100644
--- a/Jellyfin.Data/Enums/CollectionType.cs
+++ b/Jellyfin.Data/Enums/CollectionType.cs
@@ -1,3 +1,4 @@
+#pragma warning disable SA1300 // The name of a C# element does not begin with an upper-case letter. - disabled due to legacy requirement.
using Jellyfin.Data.Attributes;
namespace Jellyfin.Data.Enums;
@@ -10,155 +11,155 @@ public enum CollectionType
/// <summary>
/// Unknown collection.
/// </summary>
- Unknown = 0,
+ unknown = 0,
/// <summary>
/// Movies collection.
/// </summary>
- Movies = 1,
+ movies = 1,
/// <summary>
/// Tv shows collection.
/// </summary>
- TvShows = 2,
+ tvshows = 2,
/// <summary>
/// Music collection.
/// </summary>
- Music = 3,
+ music = 3,
/// <summary>
/// Music videos collection.
/// </summary>
- MusicVideos = 4,
+ musicvideos = 4,
/// <summary>
/// Trailers collection.
/// </summary>
- Trailers = 5,
+ trailers = 5,
/// <summary>
/// Home videos collection.
/// </summary>
- HomeVideos = 6,
+ homevideos = 6,
/// <summary>
/// Box sets collection.
/// </summary>
- BoxSets = 7,
+ boxsets = 7,
/// <summary>
/// Books collection.
/// </summary>
- Books = 8,
+ books = 8,
/// <summary>
/// Photos collection.
/// </summary>
- Photos = 9,
+ photos = 9,
/// <summary>
/// Live tv collection.
/// </summary>
- LiveTv = 10,
+ livetv = 10,
/// <summary>
/// Playlists collection.
/// </summary>
- Playlists = 11,
+ playlists = 11,
/// <summary>
/// Folders collection.
/// </summary>
- Folders = 12,
+ folders = 12,
/// <summary>
/// Tv show series collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvShowSeries = 101,
+ tvshowseries = 101,
/// <summary>
/// Tv genres collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvGenres = 102,
+ tvgenres = 102,
/// <summary>
/// Tv genre collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvGenre = 103,
+ tvgenre = 103,
/// <summary>
/// Tv latest collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvLatest = 104,
+ tvlatest = 104,
/// <summary>
/// Tv next up collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvNextUp = 105,
+ tvnextup = 105,
/// <summary>
/// Tv resume collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvResume = 106,
+ tvresume = 106,
/// <summary>
/// Tv favorite series collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvFavoriteSeries = 107,
+ tvfavoriteseries = 107,
/// <summary>
/// Tv favorite episodes collection.
/// </summary>
[OpenApiIgnoreEnum]
- TvFavoriteEpisodes = 108,
+ tvfavoriteepisodes = 108,
/// <summary>
/// Latest movies collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieLatest = 109,
+ movielatest = 109,
/// <summary>
/// Movies to resume collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieResume = 110,
+ movieresume = 110,
/// <summary>
/// Movie movie collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieMovies = 111,
+ moviemovies = 111,
/// <summary>
/// Movie collections collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieCollections = 112,
+ moviecollection = 112,
/// <summary>
/// Movie favorites collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieFavorites = 113,
+ moviefavorites = 113,
/// <summary>
/// Movie genres collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieGenres = 114,
+ moviegenres = 114,
/// <summary>
/// Movie genre collection.
/// </summary>
[OpenApiIgnoreEnum]
- MovieGenre = 115
+ moviegenre = 115
}
diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
index a4b4c1959..d8eee1246 100644
--- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
+++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
@@ -110,21 +110,21 @@ namespace Jellyfin.Server.Implementations.Devices
/// <inheritdoc />
public async Task<DeviceInfo?> GetDevice(string id)
{
- Device? device;
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
await using (dbContext.ConfigureAwait(false))
{
- device = await dbContext.Devices
+ var device = await dbContext.Devices
.Where(d => d.DeviceId == id)
.OrderByDescending(d => d.DateLastActivity)
.Include(d => d.User)
+ .SelectMany(d => dbContext.DeviceOptions.Where(o => o.DeviceId == d.DeviceId).DefaultIfEmpty(), (d, o) => new { Device = d, Options = o })
.FirstOrDefaultAsync()
.ConfigureAwait(false);
- }
- var deviceInfo = device is null ? null : ToDeviceInfo(device);
+ var deviceInfo = device is null ? null : ToDeviceInfo(device.Device, device.Options);
- return deviceInfo;
+ return deviceInfo;
+ }
}
/// <inheritdoc />
@@ -172,15 +172,15 @@ namespace Jellyfin.Server.Implementations.Devices
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
await using (dbContext.ConfigureAwait(false))
{
- IAsyncEnumerable<Device> sessions = dbContext.Devices
+ var sessions = dbContext.Devices
.Include(d => d.User)
.OrderByDescending(d => d.DateLastActivity)
.ThenBy(d => d.DeviceId)
+ .SelectMany(d => dbContext.DeviceOptions.Where(o => o.DeviceId == d.DeviceId).DefaultIfEmpty(), (d, o) => new { Device = d, Options = o })
.AsAsyncEnumerable();
-
if (supportsSync.HasValue)
{
- sessions = sessions.Where(i => GetCapabilities(i.DeviceId).SupportsSync == supportsSync.Value);
+ sessions = sessions.Where(i => GetCapabilities(i.Device.DeviceId).SupportsSync == supportsSync.Value);
}
if (userId.HasValue)
@@ -191,10 +191,10 @@ namespace Jellyfin.Server.Implementations.Devices
throw new ResourceNotFoundException();
}
- sessions = sessions.Where(i => CanAccessDevice(user, i.DeviceId));
+ sessions = sessions.Where(i => CanAccessDevice(user, i.Device.DeviceId));
}
- var array = await sessions.Select(device => ToDeviceInfo(device)).ToArrayAsync().ConfigureAwait(false);
+ var array = await sessions.Select(device => ToDeviceInfo(device.Device, device.Options)).ToArrayAsync().ConfigureAwait(false);
return new QueryResult<DeviceInfo>(array);
}
@@ -226,7 +226,7 @@ namespace Jellyfin.Server.Implementations.Devices
|| !GetCapabilities(deviceId).SupportsPersistentIdentifier;
}
- private DeviceInfo ToDeviceInfo(Device authInfo)
+ private DeviceInfo ToDeviceInfo(Device authInfo, DeviceOptions? options = null)
{
var caps = GetCapabilities(authInfo.DeviceId);
@@ -239,7 +239,8 @@ namespace Jellyfin.Server.Implementations.Devices
LastUserName = authInfo.User.Username,
Name = authInfo.DeviceName,
DateLastActivity = authInfo.DateLastActivity,
- IconUrl = caps.IconUrl
+ IconUrl = caps.IconUrl,
+ CustomName = options?.CustomName,
};
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 98485f9a8..7c04fcbfc 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -724,7 +724,7 @@ namespace MediaBrowser.Controller.Entities
if (this is IHasCollectionType view)
{
- if (view.CollectionType == CollectionType.LiveTv)
+ if (view.CollectionType == CollectionType.livetv)
{
return true;
}
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 1f94cf767..eb026deb4 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -19,19 +19,19 @@ namespace MediaBrowser.Controller.Entities
{
private static readonly CollectionType?[] _viewTypesEligibleForGrouping =
{
- Jellyfin.Data.Enums.CollectionType.Movies,
- Jellyfin.Data.Enums.CollectionType.TvShows,
+ Jellyfin.Data.Enums.CollectionType.movies,
+ Jellyfin.Data.Enums.CollectionType.tvshows,
null
};
private static readonly CollectionType?[] _originalFolderViewTypes =
{
- Jellyfin.Data.Enums.CollectionType.Books,
- Jellyfin.Data.Enums.CollectionType.MusicVideos,
- Jellyfin.Data.Enums.CollectionType.HomeVideos,
- Jellyfin.Data.Enums.CollectionType.Photos,
- Jellyfin.Data.Enums.CollectionType.Music,
- Jellyfin.Data.Enums.CollectionType.BoxSets
+ Jellyfin.Data.Enums.CollectionType.books,
+ Jellyfin.Data.Enums.CollectionType.musicvideos,
+ Jellyfin.Data.Enums.CollectionType.homevideos,
+ Jellyfin.Data.Enums.CollectionType.photos,
+ Jellyfin.Data.Enums.CollectionType.music,
+ Jellyfin.Data.Enums.CollectionType.boxsets
};
public static ITVSeriesManager TVSeriesManager { get; set; }
@@ -161,7 +161,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- return collectionFolder.CollectionType == Jellyfin.Data.Enums.CollectionType.Playlists;
+ return collectionFolder.CollectionType == Jellyfin.Data.Enums.CollectionType.playlists;
}
public static bool IsEligibleForGrouping(Folder folder)
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 42431c832..a3525c862 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -58,58 +58,58 @@ namespace MediaBrowser.Controller.Entities
switch (viewType)
{
- case CollectionType.Folders:
+ case CollectionType.folders:
return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), query);
- case CollectionType.TvShows:
+ case CollectionType.tvshows:
return GetTvView(queryParent, user, query);
- case CollectionType.Movies:
+ case CollectionType.movies:
return GetMovieFolders(queryParent, user, query);
- case CollectionType.TvShowSeries:
+ case CollectionType.tvshowseries:
return GetTvSeries(queryParent, user, query);
- case CollectionType.TvGenres:
+ case CollectionType.tvgenres:
return GetTvGenres(queryParent, user, query);
- case CollectionType.TvGenre:
+ case CollectionType.tvgenre:
return GetTvGenreItems(queryParent, displayParent, user, query);
- case CollectionType.TvResume:
+ case CollectionType.tvresume:
return GetTvResume(queryParent, user, query);
- case CollectionType.TvNextUp:
+ case CollectionType.tvnextup:
return GetTvNextUp(queryParent, query);
- case CollectionType.TvLatest:
+ case CollectionType.tvlatest:
return GetTvLatest(queryParent, user, query);
- case CollectionType.MovieFavorites:
+ case CollectionType.moviefavorites:
return GetFavoriteMovies(queryParent, user, query);
- case CollectionType.MovieLatest:
+ case CollectionType.movielatest:
return GetMovieLatest(queryParent, user, query);
- case CollectionType.MovieGenres:
+ case CollectionType.moviegenres:
return GetMovieGenres(queryParent, user, query);
- case CollectionType.MovieGenre:
+ case CollectionType.moviegenre:
return GetMovieGenreItems(queryParent, displayParent, user, query);
- case CollectionType.MovieResume:
+ case CollectionType.movieresume:
return GetMovieResume(queryParent, user, query);
- case CollectionType.MovieMovies:
+ case CollectionType.moviemovies:
return GetMovieMovies(queryParent, user, query);
- case CollectionType.MovieCollections:
+ case CollectionType.moviecollection:
return GetMovieCollections(user, query);
- case CollectionType.TvFavoriteEpisodes:
+ case CollectionType.tvfavoriteepisodes:
return GetFavoriteEpisodes(queryParent, user, query);
- case CollectionType.TvFavoriteSeries:
+ case CollectionType.tvfavoriteseries:
return GetFavoriteSeries(queryParent, user, query);
default:
@@ -146,12 +146,12 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>
{
- GetUserView(CollectionType.MovieResume, "HeaderContinueWatching", "0", parent),
- GetUserView(CollectionType.MovieLatest, "Latest", "1", parent),
- GetUserView(CollectionType.MovieMovies, "Movies", "2", parent),
- GetUserView(CollectionType.MovieCollections, "Collections", "3", parent),
- GetUserView(CollectionType.MovieFavorites, "Favorites", "4", parent),
- GetUserView(CollectionType.MovieGenres, "Genres", "5", parent)
+ GetUserView(CollectionType.movieresume, "HeaderContinueWatching", "0", parent),
+ GetUserView(CollectionType.movielatest, "Latest", "1", parent),
+ GetUserView(CollectionType.moviemovies, "Movies", "2", parent),
+ GetUserView(CollectionType.moviecollection, "Collections", "3", parent),
+ GetUserView(CollectionType.moviefavorites, "Favorites", "4", parent),
+ GetUserView(CollectionType.moviegenres, "Genres", "5", parent)
};
return GetResult(list, query);
@@ -264,7 +264,7 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i is not null)
- .Select(i => GetUserViewWithName(CollectionType.MovieGenre, i.SortName, parent));
+ .Select(i => GetUserViewWithName(CollectionType.moviegenre, i.SortName, parent));
return GetResult(genres, query);
}
@@ -303,13 +303,13 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>
{
- GetUserView(CollectionType.TvResume, "HeaderContinueWatching", "0", parent),
- GetUserView(CollectionType.TvNextUp, "HeaderNextUp", "1", parent),
- GetUserView(CollectionType.TvLatest, "Latest", "2", parent),
- GetUserView(CollectionType.TvShowSeries, "Shows", "3", parent),
- GetUserView(CollectionType.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent),
- GetUserView(CollectionType.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent),
- GetUserView(CollectionType.TvGenres, "Genres", "6", parent)
+ GetUserView(CollectionType.tvresume, "HeaderContinueWatching", "0", parent),
+ GetUserView(CollectionType.tvnextup, "HeaderNextUp", "1", parent),
+ GetUserView(CollectionType.tvlatest, "Latest", "2", parent),
+ GetUserView(CollectionType.tvshowseries, "Shows", "3", parent),
+ GetUserView(CollectionType.tvfavoriteseries, "HeaderFavoriteShows", "4", parent),
+ GetUserView(CollectionType.tvfavoriteepisodes, "HeaderFavoriteEpisodes", "5", parent),
+ GetUserView(CollectionType.tvgenres, "Genres", "6", parent)
};
return GetResult(list, query);
@@ -330,7 +330,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
{
- var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows });
+ var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.tvshows });
var result = _tvSeriesManager.GetNextUp(
new NextUpQuery
@@ -392,7 +392,7 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i is not null)
- .Select(i => GetUserViewWithName(CollectionType.TvGenre, i.SortName, parent));
+ .Select(i => GetUserViewWithName(CollectionType.tvgenre, i.SortName, parent));
return GetResult(genres, query);
}
diff --git a/MediaBrowser.Controller/Library/ILiveStream.cs b/MediaBrowser.Controller/Library/ILiveStream.cs
index 4c44a17fd..bf64aca0f 100644
--- a/MediaBrowser.Controller/Library/ILiveStream.cs
+++ b/MediaBrowser.Controller/Library/ILiveStream.cs
@@ -2,6 +2,7 @@
#pragma warning disable CA1711, CS1591
+using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -9,7 +10,7 @@ using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
{
- public interface ILiveStream
+ public interface ILiveStream : IDisposable
{
int ConsumerCount { get; set; }
diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
index 24820abb9..b98309158 100644
--- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs
+++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
@@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="currentLiveStreams">The current live streams.</param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
/// <returns>Live stream wrapped in a task.</returns>
- Task<ILiveStream> GetChannelStream(string channelId, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
+ Task<ILiveStream> GetChannelStream(string channelId, string streamId, IList<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel stream media sources.
diff --git a/MediaBrowser.Model/Devices/DeviceInfo.cs b/MediaBrowser.Model/Devices/DeviceInfo.cs
index 7a1c7a738..4962992a0 100644
--- a/MediaBrowser.Model/Devices/DeviceInfo.cs
+++ b/MediaBrowser.Model/Devices/DeviceInfo.cs
@@ -15,6 +15,8 @@ namespace MediaBrowser.Model.Devices
public string Name { get; set; }
+ public string CustomName { get; set; }
+
/// <summary>
/// Gets or sets the access token.
/// </summary>
diff --git a/deployment/build.centos.amd64 b/deployment/build.centos.amd64
index 0374624d8..a0ab93e4e 100755
--- a/deployment/build.centos.amd64
+++ b/deployment/build.centos.amd64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove BuildRequires for dotnet, since it's installed manually
@@ -39,10 +39,10 @@ make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS
rpmbuild --rebuild -bb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm
# Move the artifacts out
-mv /root/rpmbuild/RPMS/x86_64/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/
+mv /root/rpmbuild/RPMS/x86_64/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
rm -f fedora/jellyfin*.tar.gz
@@ -51,7 +51,7 @@ if [[ ${IS_DOCKER} == YES ]]; then
pushd fedora
cp -a /tmp/spec.orig jellyfin.spec
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
popd
fi
diff --git a/deployment/build.debian.amd64 b/deployment/build.debian.amd64
index 7e968192b..1a59d02e9 100755
--- a/deployment/build.debian.amd64
+++ b/deployment/build.debian.amd64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove build-dep for dotnet-sdk-8.0, since it's installed manually
@@ -32,12 +32,12 @@ fi
# Build DEB
dpkg-buildpackage -us -uc --pre-clean --post-clean
-mkdir -p ${ARTIFACT_DIR}/
-mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
cp -a /tmp/control.orig debian/control
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.debian.arm64 b/deployment/build.debian.arm64
index 7b7b603d6..e1e30fab4 100755
--- a/deployment/build.debian.arm64
+++ b/deployment/build.debian.arm64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove build-dep for dotnet-sdk-8.0, since it's installed manually
@@ -33,12 +33,12 @@ fi
export CONFIG_SITE=/etc/dpkg-cross/cross-config.${ARCH}
dpkg-buildpackage -us -uc -a arm64 --pre-clean --post-clean
-mkdir -p ${ARTIFACT_DIR}/
-mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
cp -a /tmp/control.orig debian/control
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.debian.armhf b/deployment/build.debian.armhf
index 3d894ba20..e3e8ae004 100755
--- a/deployment/build.debian.armhf
+++ b/deployment/build.debian.armhf
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove build-dep for dotnet-sdk-8.0, since it's installed manually
@@ -33,12 +33,12 @@ fi
export CONFIG_SITE=/etc/dpkg-cross/cross-config.${ARCH}
dpkg-buildpackage -us -uc -a armhf --pre-clean --post-clean
-mkdir -p ${ARTIFACT_DIR}/
-mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
cp -a /tmp/control.orig debian/control
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.fedora.amd64 b/deployment/build.fedora.amd64
index 1b629289f..da345ec08 100755
--- a/deployment/build.fedora.amd64
+++ b/deployment/build.fedora.amd64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove BuildRequires for dotnet, since it's installed manually
@@ -39,10 +39,10 @@ make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS
rpmbuild -rb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm
# Move the artifacts out
-mv /root/rpmbuild/RPMS/x86_64/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/
+mv /root/rpmbuild/RPMS/x86_64/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
rm -f fedora/jellyfin*.tar.gz
@@ -51,7 +51,7 @@ if [[ ${IS_DOCKER} == YES ]]; then
pushd fedora
cp -a /tmp/spec.orig jellyfin.spec
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
popd
fi
diff --git a/deployment/build.linux.amd64 b/deployment/build.linux.amd64
index 05059e4ed..c6baa61f6 100755
--- a/deployment/build.linux.amd64
+++ b/deployment/build.linux.amd64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_linux-amd64.tar.gz -C dist jellyfin-server_$
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.linux.amd64-musl b/deployment/build.linux.amd64-musl
index 0ee4b05fb..6523f8319 100755
--- a/deployment/build.linux.amd64-musl
+++ b/deployment/build.linux.amd64-musl
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_linux-amd64-musl.tar.gz -C dist jellyfin-ser
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.linux.arm64 b/deployment/build.linux.arm64
index 6e36db0eb..6d6a8f803 100755
--- a/deployment/build.linux.arm64
+++ b/deployment/build.linux.arm64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_linux-arm64.tar.gz -C dist jellyfin-server_$
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.linux.armhf b/deployment/build.linux.armhf
index f83eeebf1..5167dfcb8 100755
--- a/deployment/build.linux.armhf
+++ b/deployment/build.linux.armhf
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_linux-armhf.tar.gz -C dist jellyfin-server_$
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.linux.musl-linux-arm64 b/deployment/build.linux.musl-linux-arm64
index 38826ae7f..57980314d 100755
--- a/deployment/build.linux.musl-linux-arm64
+++ b/deployment/build.linux.musl-linux-arm64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_linux-arm64-musl.tar.gz -C dist jellyfin-ser
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.macos.amd64 b/deployment/build.macos.amd64
index eac353877..c7711e82c 100755
--- a/deployment/build.macos.amd64
+++ b/deployment/build.macos.amd64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_macos-amd64.tar.gz -C dist jellyfin-server_$
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.macos.arm64 b/deployment/build.macos.arm64
index 42da07e2f..b07eaad4e 100755
--- a/deployment/build.macos.arm64
+++ b/deployment/build.macos.arm64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_macos-arm64.tar.gz -C dist jellyfin-server_$
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.portable b/deployment/build.portable
index 27e5e987f..ec151d295 100755
--- a/deployment/build.portable
+++ b/deployment/build.portable
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -21,11 +21,11 @@ tar -czf jellyfin-server_${version}_portable.tar.gz -C dist jellyfin-server_${ve
rm -rf dist/jellyfin-server_${version}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv jellyfin[-_]*.tar.gz "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.ubuntu.amd64 b/deployment/build.ubuntu.amd64
index 5f25cb610..17968a6e9 100755
--- a/deployment/build.ubuntu.amd64
+++ b/deployment/build.ubuntu.amd64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove build-dep for dotnet-sdk-8.0, since it's installed manually
@@ -32,12 +32,12 @@ fi
# Build DEB
dpkg-buildpackage -us -uc --pre-clean --post-clean
-mkdir -p ${ARTIFACT_DIR}/
-mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
cp -a /tmp/control.orig debian/control
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.ubuntu.arm64 b/deployment/build.ubuntu.arm64
index 334ced997..ee7da9bb9 100755
--- a/deployment/build.ubuntu.arm64
+++ b/deployment/build.ubuntu.arm64
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove build-dep for dotnet-sdk-8.0, since it's installed manually
@@ -33,12 +33,12 @@ fi
export CONFIG_SITE=/etc/dpkg-cross/cross-config.${ARCH}
dpkg-buildpackage -us -uc -a arm64 --pre-clean --post-clean
-mkdir -p ${ARTIFACT_DIR}/
-mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
cp -a /tmp/control.orig debian/control
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.ubuntu.armhf b/deployment/build.ubuntu.armhf
index 77e33c307..85c993282 100755
--- a/deployment/build.ubuntu.armhf
+++ b/deployment/build.ubuntu.armhf
@@ -6,7 +6,7 @@ set -o errexit
set -o xtrace
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
if [[ ${IS_DOCKER} == YES ]]; then
# Remove build-dep for dotnet-sdk-8.0, since it's installed manually
@@ -33,12 +33,12 @@ fi
export CONFIG_SITE=/etc/dpkg-cross/cross-config.${ARCH}
dpkg-buildpackage -us -uc -a armhf --pre-clean --post-clean
-mkdir -p ${ARTIFACT_DIR}/
-mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
cp -a /tmp/control.orig debian/control
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/deployment/build.windows.amd64 b/deployment/build.windows.amd64
index 0786358bd..20f976365 100755
--- a/deployment/build.windows.amd64
+++ b/deployment/build.windows.amd64
@@ -11,7 +11,7 @@ NSSM_URL="http://files.evilt.win/nssm/${NSSM_VERSION}.zip"
FFMPEG_URL="https://repo.jellyfin.org/releases/server/windows/ffmpeg/jellyfin-ffmpeg-portable_win64.zip";
# Move to source directory
-pushd ${SOURCE_DIR}
+pushd "${SOURCE_DIR}"
# Get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -42,11 +42,11 @@ popd
rm -rf ${output_dir}
# Move the artifacts out
-mkdir -p ${ARTIFACT_DIR}/
-mv dist/jellyfin[-_]*.zip ${ARTIFACT_DIR}/
+mkdir -p "${ARTIFACT_DIR}/"
+mv dist/jellyfin[-_]*.zip "${ARTIFACT_DIR}/"
if [[ ${IS_DOCKER} == YES ]]; then
- chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
+ chown -Rc $(stat -c %u:%g "${ARTIFACT_DIR}") "${ARTIFACT_DIR}"
fi
popd
diff --git a/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs b/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs
index 0254a1ec6..5034ad3c7 100644
--- a/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs
+++ b/tests/Jellyfin.Api.Tests/Controllers/ImageControllerTests.cs
@@ -27,7 +27,7 @@ public static class ImageControllerTests
[InlineData(null)]
[InlineData("")]
[InlineData("text/html")]
- public static void TryGetImageExtensionFromContentType_InValid_False(string contentType)
+ public static void TryGetImageExtensionFromContentType_InValid_False(string? contentType)
{
Assert.False(ImageController.TryGetImageExtensionFromContentType(contentType, out var ex));
Assert.Null(ex);
diff --git a/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs
index d46beedd9..95f9a5fcf 100644
--- a/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs
@@ -8,20 +8,18 @@ namespace Jellyfin.Extensions.Tests
{
public static TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>> CopyTo_Valid_Correct_TestData()
{
- var data = new TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>>();
-
- data.Add(
- new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 });
-
- data.Add(
- new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } );
+ var data = new TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>>
+ {
+ { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 } },
+ { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } }
+ };
return data;
}
[Theory]
[MemberData(nameof(CopyTo_Valid_Correct_TestData))]
- public static void CopyTo_Valid_Correct<T>(IReadOnlyList<T> source, IList<T> destination, int index, IList<T> expected)
+ public static void CopyTo_Valid_Correct(IReadOnlyList<int> source, IList<int> destination, int index, IList<int> expected)
{
source.CopyTo(destination, index);
Assert.Equal(expected, destination);
@@ -29,29 +27,21 @@ namespace Jellyfin.Extensions.Tests
public static TheoryData<IReadOnlyList<int>, IList<int>, int> CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData()
{
- var data = new TheoryData<IReadOnlyList<int>, IList<int>, int>();
-
- data.Add(
- new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 );
-
- data.Add(
- new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 );
-
- data.Add(
- new[] { 0, 1, 2 }, Array.Empty<int>(), 0 );
-
- data.Add(
- new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 );
-
- data.Add(
- new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 );
+ var data = new TheoryData<IReadOnlyList<int>, IList<int>, int>
+ {
+ { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 },
+ { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 },
+ { new[] { 0, 1, 2 }, Array.Empty<int>(), 0 },
+ { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 },
+ { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 }
+ };
return data;
}
[Theory]
[MemberData(nameof(CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData))]
- public static void CopyTo_Invalid_ThrowsArgumentOutOfRangeException<T>(IReadOnlyList<T> source, IList<T> destination, int index)
+ public static void CopyTo_Invalid_ThrowsArgumentOutOfRangeException(IReadOnlyList<int> source, IList<int> destination, int index)
{
Assert.Throws<ArgumentOutOfRangeException>(() => source.CopyTo(destination, index));
}
diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
index 210ce4a47..2f84fa544 100644
--- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
+++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
@@ -27,7 +27,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")]
- [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
+ [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450
[InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Firefox
@@ -38,7 +38,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")]
- [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
+ [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450
[InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Safari
@@ -89,7 +89,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome-NoHLS", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
[InlineData("Chrome-NoHLS", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode", "http")]
- [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
+ [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450
[InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// TranscodeMedia
@@ -177,7 +177,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode")]
- [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
+ [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450
[InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Firefox
@@ -187,7 +187,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode")]
- [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
+ [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450
[InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Safari
@@ -274,13 +274,16 @@ namespace Jellyfin.Model.Tests
[Theory]
// Chrome
[InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450
+ [InlineData("Chrome", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
[InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioIsExternal)] // #6450
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")]
// Firefox
[InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450
+ [InlineData("Firefox", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")]
// Yatse
[InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450
+ [InlineData("Yatse", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
[InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450
// RokuSSPlus
[InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
@@ -291,11 +294,13 @@ namespace Jellyfin.Model.Tests
[InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
[InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
// Tizen 3 Stereo
- [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
- [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
+ [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
// 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")]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")]
public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{
var options = await GetMediaOptions(deviceName, mediaSource);
@@ -419,14 +424,7 @@ namespace Jellyfin.Model.Tests
if (targetAudioStream?.IsExternal == false)
{
// Check expected audio codecs (1)
- if (streamInfo.TranscodeReasons.HasFlag(TranscodeReason.ContainerNotSupported))
- {
- Assert.Contains(targetAudioStream.Codec, streamInfo.AudioCodecs);
- }
- else
- {
- Assert.DoesNotContain(targetAudioStream.Codec, streamInfo.AudioCodecs);
- }
+ Assert.DoesNotContain(targetAudioStream.Codec, streamInfo.AudioCodecs);
}
}
else if (transcodeMode.Equals("Remux", StringComparison.Ordinal))
diff --git a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
index d39a22e30..f4c0d9fe8 100644
--- a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
+++ b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
@@ -192,7 +192,7 @@ namespace Jellyfin.Model.Tests.Entities
[InlineData(4090, 3070, false, "4K")]
[InlineData(7680, 4320, false, "8K")]
[InlineData(8190, 6140, false, "8K")]
- public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string expected)
+ public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string? expected)
{
var mediaStream = new MediaStream()
{
diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json
index 53637b793..2e3e6e6de 100644
--- a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json
+++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json
@@ -414,6 +414,19 @@
],
"CodecProfiles": [
{
+ "Type": "VideoAudio",
+ "Conditions": [
+ {
+ "Condition": "Equals",
+ "Property": "IsSecondaryAudio",
+ "Value": "false",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "CodecProfile"
+ },
+ {
"Type": "Video",
"Conditions": [
{
diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json
index d3ef22c25..156230471 100644
--- a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json
+++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json
@@ -414,6 +414,19 @@
],
"CodecProfiles": [
{
+ "Type": "VideoAudio",
+ "Conditions": [
+ {
+ "Condition": "Equals",
+ "Property": "IsSecondaryAudio",
+ "Value": "false",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "CodecProfile"
+ },
+ {
"Type": "Video",
"Conditions": [
{
diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-aac-srt-2600k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-aac-srt-2600k.json
new file mode 100644
index 000000000..9d819c4ad
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-aac-srt-2600k.json
@@ -0,0 +1,102 @@
+{
+ "Id": "a766d122b58e45d9492d17af77748bf5",
+ "Path": "/Media/MyVideo-720p.mp4",
+ "Container": "mov,mp4,m4a,3gp,3g2,mj2",
+ "Size": 835317696,
+ "Name": "MyVideo-720p",
+ "ETag": "579a34c6d5dfb21d81539a51220b6a23",
+ "RunTimeTicks": 25801230336,
+ "SupportsTranscoding": true,
+ "SupportsDirectStream": true,
+ "SupportsDirectPlay": true,
+ "SupportsProbing": true,
+ "MediaStreams": [
+ {
+ "Codec": "h264",
+ "CodecTag": "avc1",
+ "Language": "eng",
+ "TimeBase": "1/11988",
+ "VideoRange": "SDR",
+ "DisplayTitle": "720p H264 SDR",
+ "NalLengthSize": "0",
+ "BitRate": 2032876,
+ "BitDepth": 8,
+ "RefFrames": 1,
+ "IsDefault": true,
+ "Height": 720,
+ "Width": 1280,
+ "AverageFrameRate": 23.976,
+ "RealFrameRate": 23.976,
+ "Profile": "High",
+ "Type": 1,
+ "AspectRatio": "16:9",
+ "PixelFormat": "yuv420p",
+ "Level": 41
+ },
+ {
+ "Codec": "ac3",
+ "CodecTag": "ac-3",
+ "Language": "eng",
+ "TimeBase": "1/48000",
+ "DisplayTitle": "En - Dolby Digital - 5.1 - Default",
+ "ChannelLayout": "5.1",
+ "BitRate": 384000,
+ "Channels": 6,
+ "SampleRate": 48000,
+ "IsDefault": true,
+ "Index": 1,
+ "Score": 202
+ },
+ {
+ "Codec": "aac",
+ "CodecTag": "mp4a",
+ "Language": "eng",
+ "TimeBase": "1/48000",
+ "DisplayTitle": "En - AAC - Stereo - Default",
+ "ChannelLayout": "stereo",
+ "BitRate": 164741,
+ "Channels": 2,
+ "SampleRate": 48000,
+ "IsDefault": true,
+ "Profile": "LC",
+ "Index": 2,
+ "Score": 203
+ },
+ {
+ "Codec": "aac",
+ "CodecTag": "mp4a",
+ "Language": "rus",
+ "TimeBase": "1/48000",
+ "DisplayTitle": "Ru - AAC - Stereo - Default",
+ "ChannelLayout": "stereo",
+ "BitRate": 164741,
+ "Channels": 2,
+ "SampleRate": 48000,
+ "IsDefault": false,
+ "Profile": "LC",
+ "Index": 3,
+ "Score": 203
+ },
+ {
+ "Codec": "srt",
+ "Language": "eng",
+ "TimeBase": "1/1000000",
+ "localizedUndefined": "Undefined",
+ "localizedDefault": "Default",
+ "localizedForced": "Forced",
+ "DisplayTitle": "En - Default",
+ "BitRate": 92,
+ "IsDefault": true,
+ "Type": 2,
+ "Index": 4,
+ "Score": 6421,
+ "IsExternal": true,
+ "IsTextSubtitleStream": true,
+ "SupportsExternalStream": true,
+ "Path": "/Media/MyVideo-WEBDL-2160p.default.eng.srt"
+ }
+ ],
+ "Bitrate": 2590008,
+ "DefaultAudioStreamIndex": 1,
+ "DefaultSubtitleStreamIndex": 4
+}
diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs
index 62d60e5a4..5029a8793 100644
--- a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs
@@ -52,9 +52,8 @@ namespace Jellyfin.Naming.Tests.Video
[InlineData("My Movie 2013-12-09", "My Movie 2013-12-09", null)]
[InlineData("My Movie 20131209", "My Movie 20131209", null)]
[InlineData("My Movie 2013-12-09 2013", "My Movie 2013-12-09", 2013)]
- [InlineData(null, null, null)]
[InlineData("", "", null)]
- public void CleanDateTimeTest(string input, string expectedName, int? expectedYear)
+ public void CleanDateTimeTest(string input, string? expectedName, int? expectedYear)
{
input = Path.GetFileName(input);
diff --git a/tests/Jellyfin.Networking.Tests/Configuration/NetworkConfigurationTests.cs b/tests/Jellyfin.Networking.Tests/Configuration/NetworkConfigurationTests.cs
index 30726f1d3..f337fe20b 100644
--- a/tests/Jellyfin.Networking.Tests/Configuration/NetworkConfigurationTests.cs
+++ b/tests/Jellyfin.Networking.Tests/Configuration/NetworkConfigurationTests.cs
@@ -6,7 +6,6 @@ namespace Jellyfin.Networking.Tests.Configuration;
public static class NetworkConfigurationTests
{
[Theory]
- [InlineData("", null)]
[InlineData("", "")]
[InlineData("/Test", "/Test")]
[InlineData("/Test", "Test")]
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs
index 2bc686a33..85963e5de 100644
--- a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs
@@ -55,7 +55,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo
[InlineData("clearlogo.png", null, 1, ImageType.Logo, ImageFormat.Png)] // extract extension from name
[InlineData("backdrop", "image/bmp", 2, ImageType.Backdrop, ImageFormat.Bmp)] // extract extension from mimetype
[InlineData("poster", null, 3, ImageType.Primary, ImageFormat.Jpg)] // default extension to jpg
- public async void GetImage_Attachment_ReturnsCorrectSelection(string filename, string mimetype, int targetIndex, ImageType type, ImageFormat? expectedFormat)
+ public async void GetImage_Attachment_ReturnsCorrectSelection(string filename, string? mimetype, int targetIndex, ImageType type, ImageFormat? expectedFormat)
{
var attachments = new List<MediaAttachment>();
string pathPrefix = "path";
@@ -103,7 +103,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo
[InlineData(null, "mjpeg", 1, ImageType.Primary, ImageFormat.Jpg)]
[InlineData(null, "png", 1, ImageType.Primary, ImageFormat.Png)]
[InlineData(null, "webp", 1, ImageType.Primary, ImageFormat.Webp)]
- public async void GetImage_Embedded_ReturnsCorrectSelection(string label, string? codec, int targetIndex, ImageType type, ImageFormat? expectedFormat)
+ public async void GetImage_Embedded_ReturnsCorrectSelection(string? label, string? codec, int targetIndex, ImageType type, ImageFormat? expectedFormat)
{
var streams = new List<MediaStream>();
for (int i = 1; i <= targetIndex; i++)
diff --git a/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs b/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs
index efd2d9553..0bfa330cb 100644
--- a/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs
+++ b/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs
@@ -25,14 +25,11 @@ namespace Jellyfin.Providers.Tests.Tmdb
}
[Theory]
- [InlineData(null, null, null)]
- [InlineData(null, "en-US", null)]
- [InlineData("en", null, "en")]
[InlineData("en", "en-US", "en-US")]
[InlineData("fr-CA", "fr-BE", "fr-CA")]
[InlineData("fr-CA", "fr", "fr-CA")]
[InlineData("de", "en-US", "de")]
- public static void AdjustImageLanguage_Valid_Success(string imageLanguage, string requestLanguage, string expected)
+ public static void AdjustImageLanguage_Valid_Success(string imageLanguage, string requestLanguage, string? expected)
{
Assert.Equal(expected, TmdbUtils.AdjustImageLanguage(imageLanguage, requestLanguage));
}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs
index 16202aea9..5aa7c04f6 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs
@@ -63,7 +63,7 @@ public class AudioResolverTests
null,
Mock.Of<ILibraryManager>())
{
- CollectionType = CollectionType.Books,
+ CollectionType = CollectionType.books,
FileInfo = new FileSystemMetadata
{
FullName = parent,
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs
index 92bac722b..cc2e47c33 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs
@@ -29,7 +29,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library
null)
{
Parent = parent,
- CollectionType = CollectionType.TvShows,
+ CollectionType = CollectionType.tvshows,
FileInfo = new FileSystemMetadata
{
FullName = "All My Children/Season 01/Extras/All My Children S01E01 - Behind The Scenes.mkv"
@@ -52,7 +52,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library
null)
{
Parent = series,
- CollectionType = CollectionType.TvShows,
+ CollectionType = CollectionType.tvshows,
FileInfo = new FileSystemMetadata
{
FullName = "Extras/Extras S01E01.mkv"
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs
index 1c35eb3f5..d1be07aa2 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs
@@ -83,7 +83,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library
[InlineData(@"\home/jeff\myfile.mkv", '\\', @"\home\jeff\myfile.mkv")]
[InlineData(@"\home/jeff\myfile.mkv", '/', "/home/jeff/myfile.mkv")]
[InlineData("", '/', "")]
- public void NormalizePath_SpecifyingSeparator_Normalizes(string path, char separator, string expectedPath)
+ public void NormalizePath_SpecifyingSeparator_Normalizes(string? path, char separator, string? expectedPath)
{
Assert.Equal(expectedPath, path.NormalizePath(separator));
}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
index c32d89ea5..30f72f595 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
@@ -85,10 +85,10 @@ namespace Jellyfin.Server.Implementations.Tests.QuickConnect
}
[Fact]
- public void AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
+ public async Task AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
{
_config.QuickConnectAvailable = false;
- Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
+ await Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
}
[Fact]
diff --git a/tests/Jellyfin.Server.Implementations.Tests/SessionManager/SessionManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/SessionManager/SessionManagerTests.cs
index ebd3a3891..e463d838e 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/SessionManager/SessionManagerTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/SessionManager/SessionManagerTests.cs
@@ -21,7 +21,7 @@ public class SessionManagerTests
[Theory]
[InlineData("", typeof(ArgumentException))]
[InlineData(null, typeof(ArgumentNullException))]
- public async Task GetAuthorizationToken_Should_ThrowException(string deviceId, Type exceptionType)
+ public async Task GetAuthorizationToken_Should_ThrowException(string? deviceId, Type exceptionType)
{
await using var sessionManager = new Emby.Server.Implementations.Session.SessionManager(
NullLogger<Emby.Server.Implementations.Session.SessionManager>.Instance,