diff options
Diffstat (limited to 'Jellyfin.Api')
57 files changed, 300 insertions, 262 deletions
diff --git a/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs b/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs index 88af08dd3..d4b1ffb06 100644 --- a/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs +++ b/Jellyfin.Api/Auth/AnonymousLanAccessPolicy/AnonymousLanAccessHandler.cs @@ -32,7 +32,7 @@ namespace Jellyfin.Api.Auth.AnonymousLanAccessPolicy var ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress; // Loopback will be on LAN, so we can accept null. - if (ip == null || _networkManager.IsInLocalNetwork(ip)) + if (ip is null || _networkManager.IsInLocalNetwork(ip)) { context.Succeed(requirement); } diff --git a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs index 92ee1dd59..8e5e66d64 100644 --- a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs +++ b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs @@ -67,7 +67,7 @@ namespace Jellyfin.Api.Auth // Ensure userId links to a valid user. var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return false; } @@ -78,7 +78,7 @@ namespace Jellyfin.Api.Auth return false; } - var isInLocalNetwork = _httpContextAccessor.HttpContext != null + var isInLocalNetwork = _httpContextAccessor.HttpContext is not null && _networkManager.IsInLocalNetwork(_httpContextAccessor.HttpContext.GetNormalizedRemoteIp()); // User cannot access remotely and user is remote diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index c059cb198..c8ac2ed52 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -183,7 +183,7 @@ namespace Jellyfin.Api.Controllers { return null; } - }).Where(i => i != null).Select(i => i!.Id).ToArray(); + }).Where(i => i is not null).Select(i => i!.Id).ToArray(); } foreach (var filter in filters) @@ -386,7 +386,7 @@ namespace Jellyfin.Api.Controllers { return null; } - }).Where(i => i != null).Select(i => i!.Id).ToArray(); + }).Where(i => i is not null).Select(i => i!.Id).ToArray(); } foreach (var filter in filters) diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index bbe163312..a00ac1b0a 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -96,7 +96,7 @@ namespace Jellyfin.Api.Controllers var configurationType = _configurationManager.GetConfigurationType(key); var deserializedConfiguration = configuration.Deserialize(configurationType, _serializerOptions); - if (deserializedConfiguration == null) + if (deserializedConfiguration is null) { throw new ArgumentException("Body doesn't contain a valid configuration"); } diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index c8411f44b..3894e6c5f 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetDashboardConfigurationPage([FromQuery] string? name) { var altPage = GetPluginPages().FirstOrDefault(p => string.Equals(p.Item1.Name, name, StringComparison.OrdinalIgnoreCase)); - if (altPage == null) + if (altPage is null) { return NotFound(); } @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers IPlugin plugin = altPage.Item2; string resourcePath = altPage.Item1.EmbeddedResourcePath; Stream? stream = plugin.GetType().Assembly.GetManifestResourceStream(resourcePath); - if (stream == null) + if (stream is null) { _logger.LogError("Failed to get resource {Resource} from plugin {Plugin}", resourcePath, plugin.Name); return NotFound(); diff --git a/Jellyfin.Api/Controllers/DevicesController.cs b/Jellyfin.Api/Controllers/DevicesController.cs index 8292cf83b..aad60cf5c 100644 --- a/Jellyfin.Api/Controllers/DevicesController.cs +++ b/Jellyfin.Api/Controllers/DevicesController.cs @@ -64,7 +64,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult<DeviceInfo>> GetDeviceInfo([FromQuery, Required] string id) { var deviceInfo = await _deviceManager.GetDevice(id).ConfigureAwait(false); - if (deviceInfo == null) + if (deviceInfo is null) { return NotFound(); } @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult<DeviceOptions>> GetDeviceOptions([FromQuery, Required] string id) { var deviceInfo = await _deviceManager.GetDeviceOptions(id).ConfigureAwait(false); - if (deviceInfo == null) + if (deviceInfo is null) { return NotFound(); } @@ -123,7 +123,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> DeleteDevice([FromQuery, Required] string id) { var existingDevice = await _deviceManager.GetDevice(id).ConfigureAwait(false); - if (existingDevice == null) + if (existingDevice is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index 14fd7eb3c..67cceb4a8 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -178,7 +178,7 @@ namespace Jellyfin.Api.Controllers foreach (var key in displayPreferences.CustomPrefs.Keys.Where(key => key.StartsWith("homesection", StringComparison.OrdinalIgnoreCase))) { - var order = int.Parse(key.AsSpan().Slice("homesection".Length), NumberStyles.Any, CultureInfo.InvariantCulture); + var order = int.Parse(key.AsSpan().Slice("homesection".Length), CultureInfo.InvariantCulture); if (!Enum.TryParse<HomeSectionType>(displayPreferences.CustomPrefs[key], true, out var type)) { type = order < 8 ? defaults[order] : HomeSectionType.None; diff --git a/Jellyfin.Api/Controllers/DlnaController.cs b/Jellyfin.Api/Controllers/DlnaController.cs index 35c3a3d92..07e0590a1 100644 --- a/Jellyfin.Api/Controllers/DlnaController.cs +++ b/Jellyfin.Api/Controllers/DlnaController.cs @@ -63,7 +63,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<DeviceProfile> GetProfile([FromRoute, Required] string profileId) { var profile = _dlnaManager.GetProfile(profileId); - if (profile == null) + if (profile is null) { return NotFound(); } @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers public ActionResult DeleteProfile([FromRoute, Required] string profileId) { var existingDeviceProfile = _dlnaManager.GetProfile(profileId); - if (existingDeviceProfile == null) + if (existingDeviceProfile is null) { return NotFound(); } @@ -121,7 +121,7 @@ namespace Jellyfin.Api.Controllers public ActionResult UpdateProfile([FromRoute, Required] string profileId, [FromBody] DeviceProfile deviceProfile) { var existingDeviceProfile = _dlnaManager.GetProfile(profileId); - if (existingDeviceProfile == null) + if (existingDeviceProfile is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index 8859d6020..96c492b3e 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -274,7 +274,7 @@ namespace Jellyfin.Api.Controllers private ActionResult GetIconInternal(string fileName) { var icon = _dlnaManager.GetIcon(fileName); - if (icon == null) + if (icon is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 0f4d3c1eb..af43bb578 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -341,7 +341,7 @@ namespace Jellyfin.Api.Controllers job ??= _transcodingJobHelper.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); - if (job != null) + if (job is not null) { _transcodingJobHelper.OnTranscodeEndRequest(job); } @@ -1482,7 +1482,7 @@ namespace Jellyfin.Api.Controllers startTranscoding = true; segmentId = 0; } - else if (currentTranscodingIndex == null) + else if (currentTranscodingIndex is null) { _logger.LogDebug("Starting transcoding because currentTranscodingIndex=null"); startTranscoding = true; @@ -1533,7 +1533,7 @@ namespace Jellyfin.Api.Controllers else { job = _transcodingJobHelper.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); - if (job?.TranscodingThrottler != null) + if (job?.TranscodingThrottler is not null) { await job.TranscodingThrottler.UnpauseTranscoding().ConfigureAwait(false); } @@ -1665,7 +1665,7 @@ namespace Jellyfin.Api.Controllers /// <returns>The command line arguments for audio transcoding.</returns> private string GetAudioArguments(StreamState state) { - if (state.AudioStream == null) + if (state.AudioStream is null) { return string.Empty; } @@ -1762,7 +1762,7 @@ namespace Jellyfin.Api.Controllers /// <returns>The command line arguments for video transcoding.</returns> private string GetVideoArguments(StreamState state, int startNumber, bool isEventPlaylist) { - if (state.VideoStream == null) + if (state.VideoStream is null) { return string.Empty; } @@ -1806,7 +1806,7 @@ namespace Jellyfin.Api.Controllers if (EncodingHelper.IsCopyCodec(codec)) { // If h264_mp4toannexb is ever added, do not use it for live tv. - if (state.VideoStream != null && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) + if (state.VideoStream is not null && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { string bitStreamArgs = EncodingHelper.GetBitStreamArgs(state.VideoStream); if (!string.IsNullOrEmpty(bitStreamArgs)) @@ -1837,7 +1837,7 @@ namespace Jellyfin.Api.Controllers // -start_at_zero is necessary to use with -ss when seeking, // otherwise the target position cannot be determined. - if (state.SubtitleStream != null) + if (state.SubtitleStream is not null) { // Disable start_at_zero for external graphical subs if (!(state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)) @@ -1883,7 +1883,7 @@ namespace Jellyfin.Api.Controllers var segmentExists = System.IO.File.Exists(segmentPath); if (segmentExists) { - if (transcodingJob != null && transcodingJob.HasExited) + if (transcodingJob is not null && transcodingJob.HasExited) { // Transcoding job is over, so assume all existing files are ready _logger.LogDebug("serving up {0} as transcode is over", segmentPath); @@ -1901,7 +1901,7 @@ namespace Jellyfin.Api.Controllers } var nextSegmentPath = GetSegmentPath(state, playlistPath, segmentIndex + 1); - if (transcodingJob != null) + if (transcodingJob is not null) { while (!cancellationToken.IsCancellationRequested && !transcodingJob.HasExited) { @@ -1953,7 +1953,7 @@ namespace Jellyfin.Api.Controllers Response.OnCompleted(() => { _logger.LogDebug("Finished serving {SegmentPath}", segmentPath); - if (transcodingJob != null) + if (transcodingJob is not null) { transcodingJob.DownloadPositionTicks = Math.Max(transcodingJob.DownloadPositionTicks ?? segmentEndingPositionTicks, segmentEndingPositionTicks); _transcodingJobHelper.OnTranscodeEndRequest(transcodingJob); @@ -1969,14 +1969,14 @@ namespace Jellyfin.Api.Controllers { var job = _transcodingJobHelper.GetTranscodingJob(playlist, TranscodingJobType); - if (job == null || job.HasExited) + if (job is null || job.HasExited) { return null; } var file = GetLastTranscodingFile(playlist, segmentExtension, _fileSystem); - if (file == null) + if (file is null) { return null; } @@ -2011,7 +2011,7 @@ namespace Jellyfin.Api.Controllers { var file = GetLastTranscodingFile(playlistPath, segmentExtension, _fileSystem); - if (file != null) + if (file is not null) { DeleteFile(file.FullName, retryCount); } diff --git a/Jellyfin.Api/Controllers/EnvironmentController.cs b/Jellyfin.Api/Controllers/EnvironmentController.cs index b0b4b5af5..6c78a7987 100644 --- a/Jellyfin.Api/Controllers/EnvironmentController.cs +++ b/Jellyfin.Api/Controllers/EnvironmentController.cs @@ -104,7 +104,7 @@ namespace Jellyfin.Api.Controllers if (validatePathDto.ValidateWritable) { - if (validatePathDto.Path == null) + if (validatePathDto.Path is null) { throw new ResourceNotFoundException(nameof(validatePathDto.Path)); } diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 11808b1b8..b6780ee20 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers if ((recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder) { - genreQuery.AncestorIds = parentItem == null ? Array.Empty<Guid>() : new[] { parentItem.Id }; + genreQuery.AncestorIds = parentItem is null ? Array.Empty<Guid>() : new[] { parentItem.Id }; } else { diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 78634f0bf..50fee233a 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -167,7 +167,7 @@ namespace Jellyfin.Api.Controllers } } - return playlistPath == null + return playlistPath is null ? NotFound("Hls segment not found.") : GetFileResult(file, playlistPath); } @@ -178,7 +178,7 @@ namespace Jellyfin.Api.Controllers Response.OnCompleted(() => { - if (transcodingJob != null) + if (transcodingJob is not null) { _transcodingJobHelper.OnTranscodeEndRequest(transcodingJob); } diff --git a/Jellyfin.Api/Controllers/ImageByNameController.cs b/Jellyfin.Api/Controllers/ImageByNameController.cs index 89bbf22c9..c54851b96 100644 --- a/Jellyfin.Api/Controllers/ImageByNameController.cs +++ b/Jellyfin.Api/Controllers/ImageByNameController.cs @@ -77,7 +77,7 @@ namespace Jellyfin.Api.Controllers .Select(i => Path.GetFullPath(Path.Combine(_applicationPaths.GeneralPath, name, filename + i))) .FirstOrDefault(System.IO.File.Exists); - if (path == null) + if (path is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index f092bd882..49342ad5c 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -28,6 +28,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; namespace Jellyfin.Api.Controllers @@ -110,7 +111,7 @@ namespace Jellyfin.Api.Controllers // Handle image/png; charset=utf-8 var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username); - if (user.ProfileImage != null) + if (user.ProfileImage is not null) { await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false); } @@ -157,7 +158,7 @@ namespace Jellyfin.Api.Controllers // Handle image/png; charset=utf-8 var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username); - if (user.ProfileImage != null) + if (user.ProfileImage is not null) { await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false); } @@ -198,7 +199,7 @@ namespace Jellyfin.Api.Controllers } var user = _userManager.GetUserById(userId); - if (user?.ProfileImage == null) + if (user?.ProfileImage is null) { return NoContent(); } @@ -242,7 +243,7 @@ namespace Jellyfin.Api.Controllers } var user = _userManager.GetUserById(userId); - if (user?.ProfileImage == null) + if (user?.ProfileImage is null) { return NoContent(); } @@ -279,7 +280,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -307,7 +308,7 @@ namespace Jellyfin.Api.Controllers [FromRoute] int imageIndex) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -335,7 +336,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -371,7 +372,7 @@ namespace Jellyfin.Api.Controllers [FromRoute] int imageIndex) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -407,7 +408,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, Required] int newIndex) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -430,7 +431,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult<IEnumerable<ImageInfo>>> GetItemImageInfos([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -452,7 +453,7 @@ namespace Jellyfin.Api.Controllers { var info = GetImageInfo(item, image, null); - if (info != null) + if (info is not null) { list.Add(info); } @@ -470,7 +471,7 @@ namespace Jellyfin.Api.Controllers { var info = GetImageInfo(item, image, index); - if (info != null) + if (info is not null) { list.Add(info); } @@ -537,7 +538,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -620,7 +621,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -703,7 +704,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] int imageIndex) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -786,7 +787,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] int imageIndex) { var item = _libraryManager.GetArtist(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -869,7 +870,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var item = _libraryManager.GetGenre(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -952,7 +953,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer) { var item = _libraryManager.GetGenre(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1035,7 +1036,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var item = _libraryManager.GetMusicGenre(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1118,7 +1119,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer) { var item = _libraryManager.GetMusicGenre(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1201,7 +1202,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var item = _libraryManager.GetPerson(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1284,7 +1285,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer) { var item = _libraryManager.GetPerson(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1367,7 +1368,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var item = _libraryManager.GetStudio(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1450,7 +1451,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer) { var item = _libraryManager.GetStudio(name); - if (item == null) + if (item is null) { return NotFound(); } @@ -1533,7 +1534,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? imageIndex) { var user = _userManager.GetUserById(userId); - if (user?.ProfileImage == null) + if (user?.ProfileImage is null) { return NotFound(); } @@ -1634,7 +1635,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer) { var user = _userManager.GetUserById(userId); - if (user?.ProfileImage == null) + if (user?.ProfileImage is null) { return NotFound(); } @@ -1944,10 +1945,10 @@ namespace Jellyfin.Api.Controllers unplayedCount = null; } - if (imageInfo == null) + if (imageInfo is null) { imageInfo = item?.GetImageInfo(imageType, imageIndex ?? 0); - if (imageInfo == null) + if (imageInfo is null) { return NotFound(string.Format(NumberFormatInfo.InvariantInfo, "{0} does not have an image of type {1}", item?.Name, imageType)); } @@ -1968,7 +1969,7 @@ namespace Jellyfin.Api.Controllers { "realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*" } }; - if (!imageInfo.IsLocalFile && item != null) + if (!imageInfo.IsLocalFile && item is not null) { imageInfo = await _libraryManager.ConvertImageToLocal(item, imageInfo, imageIndex ?? 0).ConfigureAwait(false); } @@ -2026,8 +2027,13 @@ namespace Jellyfin.Api.Controllers } var acceptParam = Request.Query[HeaderNames.Accept]; + if (StringValues.IsNullOrEmpty(acceptParam)) + { + return Array.Empty<ImageFormat>(); + } - var supportsWebP = SupportsFormat(supportedFormats, acceptParam, ImageFormat.Webp, false); + // Can't be null, checked above + var supportsWebP = SupportsFormat(supportedFormats, acceptParam!, ImageFormat.Webp, false); if (!supportsWebP) { @@ -2049,7 +2055,8 @@ namespace Jellyfin.Api.Controllers formats.Add(ImageFormat.Jpg); formats.Add(ImageFormat.Png); - if (SupportsFormat(supportedFormats, acceptParam, ImageFormat.Gif, true)) + // Can't be null, checked above + if (SupportsFormat(supportedFormats, acceptParam!, ImageFormat.Gif, true)) { formats.Add(ImageFormat.Gif); } diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index c49f85616..34893d682 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -65,7 +65,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<IEnumerable<ExternalIdInfo>> GetExternalIdInfos([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs index 9340737b5..0dc3fbd05 100644 --- a/Jellyfin.Api/Controllers/ItemRefreshController.cs +++ b/Jellyfin.Api/Controllers/ItemRefreshController.cs @@ -61,7 +61,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool replaceAllImages = false) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index fd137f98f..af3d779f5 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -71,7 +71,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> UpdateItem([FromRoute, Required] Guid itemId, [FromBody, Required] BaseItemDto request) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -80,13 +80,13 @@ namespace Jellyfin.Api.Controllers var isLockedChanged = item.IsLocked != newLockData; var series = item as Series; - var displayOrderChanged = series != null && !string.Equals( + var displayOrderChanged = series is not null && !string.Equals( series.DisplayOrder ?? string.Empty, request.DisplayOrder ?? string.Empty, StringComparison.OrdinalIgnoreCase); // Do this first so that metadata savers can pull the updates from the database. - if (request.People != null) + if (request.People is not null) { _libraryManager.UpdatePeople( item, @@ -198,7 +198,7 @@ namespace Jellyfin.Api.Controllers public ActionResult UpdateItemContentType([FromRoute, Required] Guid itemId, [FromQuery] string? contentType) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -248,12 +248,12 @@ namespace Jellyfin.Api.Controllers item.Tags = request.Tags; - if (request.Taglines != null) + if (request.Taglines is not null) { item.Tagline = request.Taglines.FirstOrDefault(); } - if (request.Studios != null) + if (request.Studios is not null) { item.Studios = request.Studios.Select(x => x.Name).ToArray(); } @@ -269,7 +269,7 @@ namespace Jellyfin.Api.Controllers item.OfficialRating = string.IsNullOrWhiteSpace(request.OfficialRating) ? null : request.OfficialRating; item.CustomRating = request.CustomRating; - if (request.ProductionLocations != null) + if (request.ProductionLocations is not null) { item.ProductionLocations = request.ProductionLocations; } @@ -289,7 +289,7 @@ namespace Jellyfin.Api.Controllers item.IsLocked = request.LockData ?? false; - if (request.LockedFields != null) + if (request.LockedFields is not null) { item.LockedFields = request.LockedFields; } @@ -315,7 +315,7 @@ namespace Jellyfin.Api.Controllers video.Video3DFormat = request.Video3DFormat; } - if (request.AlbumArtists != null) + if (request.AlbumArtists is not null) { if (item is IHasAlbumArtist hasAlbumArtists) { @@ -326,7 +326,7 @@ namespace Jellyfin.Api.Controllers } } - if (request.ArtistItems != null) + if (request.ArtistItems is not null) { if (item is IHasArtist hasArtists) { @@ -349,7 +349,7 @@ namespace Jellyfin.Api.Controllers { series.Status = GetSeriesStatus(request); - if (request.AirDays != null) + if (request.AirDays is not null) { series.AirDays = request.AirDays; series.AirTime = request.AirTime; diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 3ee5b8d73..717ddc32b 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -447,7 +447,7 @@ namespace Jellyfin.Api.Controllers { return null; } - }).Where(i => i != null).Select(i => i!.Id).ToArray(); + }).Where(i => i is not null).Select(i => i!.Id).ToArray(); } // ExcludeArtistIds @@ -483,7 +483,7 @@ namespace Jellyfin.Api.Controllers { return null; } - }).Where(i => i != null).Select(i => i!.Id).ToArray(); + }).Where(i => i is not null).Select(i => i!.Id).ToArray(); } // Apply default sorting if none requested @@ -837,7 +837,7 @@ namespace Jellyfin.Api.Controllers if (excludeActiveSessions) { excludeItemIds = _sessionManager.Sessions - .Where(s => s.UserId.Equals(userId) && s.NowPlayingItem != null) + .Where(s => s.UserId.Equals(userId) && s.NowPlayingItem is not null) .Select(s => s.NowPlayingItem.Id) .ToArray(); } diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 7a57bf1a2..ab2020830 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -104,7 +104,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetFile([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -154,7 +154,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetUserRootFolder()) : _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound("Item not found."); } @@ -171,7 +171,7 @@ namespace Jellyfin.Api.Controllers } var parent = item.GetParent(); - if (parent == null) + if (parent is null) { break; } @@ -220,7 +220,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetUserRootFolder()) : _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound("Item not found."); } @@ -237,7 +237,7 @@ namespace Jellyfin.Api.Controllers } var parent = item.GetParent(); - if (parent == null) + if (parent is null) { break; } @@ -435,7 +435,7 @@ namespace Jellyfin.Api.Controllers { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound("Item not found"); } @@ -449,9 +449,9 @@ namespace Jellyfin.Api.Controllers var dtoOptions = new DtoOptions().AddClientFields(User); BaseItem? parent = item.GetParent(); - while (parent != null) + while (parent is not null) { - if (user != null) + if (user is not null) { parent = TranslateParentItem(parent, user); } @@ -610,14 +610,14 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> GetDownload([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } var user = _userManager.GetUserById(User.GetUserId()); - if (user != null) + if (user is not null) { if (!item.CanDownload(user)) { @@ -632,27 +632,15 @@ namespace Jellyfin.Api.Controllers } } - if (user != null) + if (user is not null) { await LogDownloadAsync(item, user).ConfigureAwait(false); } - var path = item.Path; + // Quotes are valid in linux. They'll possibly cause issues here. + var filename = Path.GetFileName(item.Path)?.Replace("\"", string.Empty, StringComparison.Ordinal); - // Quotes are valid in linux. They'll possibly cause issues here - var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty, StringComparison.Ordinal); - if (!string.IsNullOrWhiteSpace(filename)) - { - // Kestrel doesn't support non-ASCII characters in headers - if (Regex.IsMatch(filename, @"[^\p{IsBasicLatin}]")) - { - // Manually encoding non-ASCII characters, following https://tools.ietf.org/html/rfc5987#section-3.2.2 - filename = WebUtility.UrlEncode(filename); - } - } - - // TODO determine non-ASCII validity. - return PhysicalFile(path, MimeTypes.GetMimeType(path), filename, true); + return PhysicalFile(item.Path, MimeTypes.GetMimeType(item.Path), filename, true); } /// <summary> @@ -698,8 +686,8 @@ namespace Jellyfin.Api.Controllers .AddClientFields(User); var program = item as IHasProgramAttributes; - bool? isMovie = item is Movie || (program != null && program.IsMovie) || item is Trailer; - bool? isSeries = item is Series || (program != null && program.IsSeries); + bool? isMovie = item is Movie || (program is not null && program.IsMovie) || item is Trailer; + bool? isSeries = item is Series || (program is not null && program.IsSeries); var includeItemTypes = new List<BaseItemKind>(); if (isMovie.Value) diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs index ec1170411..1c2394055 100644 --- a/Jellyfin.Api/Controllers/LibraryStructureController.cs +++ b/Jellyfin.Api/Controllers/LibraryStructureController.cs @@ -82,7 +82,7 @@ namespace Jellyfin.Api.Controllers { var libraryOptions = libraryOptionsDto?.LibraryOptions ?? new LibraryOptions(); - if (paths != null && paths.Length > 0) + if (paths is not null && paths.Length > 0) { libraryOptions.PathInfos = paths.Select(i => new MediaPathInfo(i)).ToArray(); } diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 394df0f58..94710d78f 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -763,7 +763,7 @@ namespace Jellyfin.Api.Controllers await AssertUserCanManageLiveTv().ConfigureAwait(false); var item = _libraryManager.GetItemById(recordingId); - if (item == null) + if (item is null) { return NotFound(); } @@ -840,7 +840,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult<SeriesTimerInfoDto>> GetSeriesTimer([FromRoute, Required] string timerId) { var timer = await _liveTvManager.GetSeriesTimer(timerId, CancellationToken.None).ConfigureAwait(false); - if (timer == null) + if (timer is null) { return NotFound(); } @@ -1201,7 +1201,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetLiveStreamFile([FromRoute, Required] string streamId, [FromRoute, Required] string container) { var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfoByUniqueId(streamId); - if (liveStreamInfo == null) + if (liveStreamInfo is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index c111e9218..8115c3585 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -121,10 +121,10 @@ namespace Jellyfin.Api.Controllers var profile = playbackInfoDto?.DeviceProfile; _logger.LogDebug("GetPostedPlaybackInfo profile: {@Profile}", profile); - if (profile == null) + if (profile is null) { var caps = _deviceManager.GetCapabilities(User.GetDeviceId()); - if (caps != null) + if (caps is not null) { profile = caps.DeviceProfile; } @@ -154,12 +154,12 @@ namespace Jellyfin.Api.Controllers liveStreamId) .ConfigureAwait(false); - if (info.ErrorCode != null) + if (info.ErrorCode is not null) { return info; } - if (profile != null) + if (profile is not null) { // set device specific data var item = _libraryManager.GetItemById(itemId); @@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers { var mediaSource = string.IsNullOrWhiteSpace(mediaSourceId) ? info.MediaSources[0] : info.MediaSources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.Ordinal)); - if (mediaSource != null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) + if (mediaSource is not null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) { var openStreamResult = await _mediaInfoHelper.OpenMediaSource( HttpContext, diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 9690aead0..0aa7c2ac9 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -54,7 +54,7 @@ namespace Jellyfin.Api.Controllers assemblyGuid ?? default) .FirstOrDefault(); - if (result == null) + if (result is null) { return NotFound(); } @@ -110,7 +110,7 @@ namespace Jellyfin.Api.Controllers specificVersion: string.IsNullOrEmpty(version) ? null : Version.Parse(version)) .FirstOrDefault(); - if (package == null) + if (package is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index 42be969b2..09f7281ec 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -122,7 +122,7 @@ namespace Jellyfin.Api.Controllers .AddClientFields(User); var item = _libraryManager.GetPerson(name); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index fb045f891..e0c565da1 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -176,7 +176,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes) { var playlist = (Playlist)_libraryManager.GetItemById(playlistId); - if (playlist == null) + if (playlist is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 3a2ba033e..58f9b7d35 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -353,7 +353,7 @@ namespace Jellyfin.Api.Controllers if (method == PlayMethod.Transcode) { var job = string.IsNullOrWhiteSpace(playSessionId) ? null : _transcodingJobHelper.GetTranscodingJob(playSessionId); - if (job == null) + if (job is null) { return PlayMethod.DirectPlay; } diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index b227dba2d..6a729b237 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -71,7 +71,7 @@ namespace Jellyfin.Api.Controllers public ActionResult EnablePlugin([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) { var plugin = _pluginManager.GetPlugin(pluginId, version); - if (plugin == null) + if (plugin is null) { return NotFound(); } @@ -95,7 +95,7 @@ namespace Jellyfin.Api.Controllers public ActionResult DisablePlugin([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) { var plugin = _pluginManager.GetPlugin(pluginId, version); - if (plugin == null) + if (plugin is null) { return NotFound(); } @@ -119,7 +119,7 @@ namespace Jellyfin.Api.Controllers public ActionResult UninstallPluginByVersion([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) { var plugin = _pluginManager.GetPlugin(pluginId, version); - if (plugin == null) + if (plugin is null) { return NotFound(); } @@ -146,9 +146,9 @@ namespace Jellyfin.Api.Controllers var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)); // Select the un-instanced one first. - var plugin = plugins.FirstOrDefault(p => p.Instance == null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); + var plugin = plugins.FirstOrDefault(p => p.Instance is null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); - if (plugin != null) + if (plugin is not null) { _installationManager.UninstallPlugin(plugin); return NoContent(); @@ -202,7 +202,7 @@ namespace Jellyfin.Api.Controllers var configuration = (BasePluginConfiguration?)await JsonSerializer.DeserializeAsync(Request.Body, configPlugin.ConfigurationType, _serializerOptions) .ConfigureAwait(false); - if (configuration != null) + if (configuration is not null) { configPlugin.UpdateConfiguration(configuration); } @@ -225,13 +225,13 @@ namespace Jellyfin.Api.Controllers public ActionResult GetPluginImage([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version) { var plugin = _pluginManager.GetPlugin(pluginId, version); - if (plugin == null) + if (plugin is null) { return NotFound(); } var imagePath = Path.Combine(plugin.Path, plugin.Manifest.ImagePath ?? string.Empty); - if (plugin.Manifest.ImagePath == null || !System.IO.File.Exists(imagePath)) + if (plugin.Manifest.ImagePath is null || !System.IO.File.Exists(imagePath)) { return NotFound(); } @@ -254,7 +254,7 @@ namespace Jellyfin.Api.Controllers { var plugin = _pluginManager.GetPlugin(pluginId); - if (plugin != null) + if (plugin is not null) { return plugin.Manifest; } diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index dbee56e14..da9e8cf90 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool includeAllLanguages = false) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -127,7 +127,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<IEnumerable<ImageProviderInfo>> GetRemoteImageProviders([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -154,7 +154,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? imageUrl) { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/ScheduledTasksController.cs b/Jellyfin.Api/Controllers/ScheduledTasksController.cs index 68e4f0586..832e14505 100644 --- a/Jellyfin.Api/Controllers/ScheduledTasksController.cs +++ b/Jellyfin.Api/Controllers/ScheduledTasksController.cs @@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers var task = _taskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, taskId, StringComparison.OrdinalIgnoreCase)); - if (task == null) + if (task is null) { return NotFound(); } @@ -99,7 +99,7 @@ namespace Jellyfin.Api.Controllers var task = _taskManager.ScheduledTasks.FirstOrDefault(o => o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); - if (task == null) + if (task is null) { return NotFound(); } @@ -123,7 +123,7 @@ namespace Jellyfin.Api.Controllers var task = _taskManager.ScheduledTasks.FirstOrDefault(o => o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); - if (task == null) + if (task is null) { return NotFound(); } @@ -149,7 +149,7 @@ namespace Jellyfin.Api.Controllers { var task = _taskManager.ScheduledTasks.FirstOrDefault(o => o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); - if (task == null) + if (task is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index aeed0c0d6..3b7719f37 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary); - if (primaryImageTag != null) + if (primaryImageTag is not null) { result.PrimaryImageTag = primaryImageTag; result.PrimaryImageAspectRatio = _dtoService.GetPrimaryImageAspectRatio(item); @@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers MusicAlbum musicAlbum = song.AlbumEntity; - if (musicAlbum != null) + if (musicAlbum is not null) { result.Album = musicAlbum.Name; result.AlbumId = musicAlbum.Id; @@ -221,18 +221,18 @@ namespace Jellyfin.Api.Controllers { var itemWithImage = item.HasImage(ImageType.Thumb) ? item : null; - if (itemWithImage == null && item is Episode) + if (itemWithImage is null && item is Episode) { itemWithImage = GetParentWithImage<Series>(item, ImageType.Thumb); } itemWithImage ??= GetParentWithImage<BaseItem>(item, ImageType.Thumb); - if (itemWithImage != null) + if (itemWithImage is not null) { var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Thumb); - if (tag != null) + if (tag is not null) { hint.ThumbImageTag = tag; hint.ThumbImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture); @@ -245,11 +245,11 @@ namespace Jellyfin.Api.Controllers var itemWithImage = (item.HasImage(ImageType.Backdrop) ? item : null) ?? GetParentWithImage<BaseItem>(item, ImageType.Backdrop); - if (itemWithImage != null) + if (itemWithImage is not null) { var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Backdrop); - if (tag != null) + if (tag is not null) { hint.BackdropImageTag = tag; hint.BackdropImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture); diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 31b95162d..25f930135 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -294,10 +294,7 @@ namespace Jellyfin.Api.Controllers { var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); - if (command == null) - { - throw new ArgumentException("Request body may not be null"); - } + ArgumentNullException.ThrowIfNull(command); command.ControllingUserId = currentSession.UserId; diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs index c49bde93f..eec5779e6 100644 --- a/Jellyfin.Api/Controllers/StartupController.cs +++ b/Jellyfin.Api/Controllers/StartupController.cs @@ -132,7 +132,7 @@ namespace Jellyfin.Api.Controllers { var user = _userManager.Users.First(); - if (startupUserDto.Name != null) + if (startupUserDto.Name is not null) { user.Username = startupUserDto.Name; } diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 1258a9876..ff9bd095b 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -96,7 +96,7 @@ namespace Jellyfin.Api.Controllers { var item = _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } @@ -522,7 +522,7 @@ namespace Jellyfin.Api.Controllers .First(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); var fileSize = fontFile?.Length; - if (fontFile != null && fileSize != null && fileSize > 0) + if (fontFile is not null && fileSize is not null && fileSize > 0) { _logger.LogDebug("Fallback font size is {FileSize} Bytes", fileSize); return PhysicalFile(fontFile.FullName, MimeTypes.GetMimeType(fontFile.FullName)); diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index ea13ceb91..7f4f4d077 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -247,7 +247,7 @@ namespace Jellyfin.Api.Controllers .GetSeasons(user, dtoOptions) .FirstOrDefault(i => i.IndexNumber == season.Value); - episodes = seasonItem == null ? + episodes = seasonItem is null ? new List<BaseItem>() : ((Season)seasonItem).GetEpisodes(user, dtoOptions); } diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index ff653fe6b..002327d74 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -124,7 +124,7 @@ namespace Jellyfin.Api.Controllers { var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return NotFound("User not found"); } @@ -173,7 +173,7 @@ namespace Jellyfin.Api.Controllers { var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return NotFound("User not found"); } @@ -272,7 +272,7 @@ namespace Jellyfin.Api.Controllers var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return NotFound("User not found"); } @@ -292,7 +292,7 @@ namespace Jellyfin.Api.Controllers HttpContext.GetNormalizedRemoteIp().ToString(), false).ConfigureAwait(false); - if (success == null) + if (success is null) { return StatusCode(StatusCodes.Status403Forbidden, "Invalid user or password entered."); } @@ -333,7 +333,7 @@ namespace Jellyfin.Api.Controllers var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return NotFound("User not found"); } @@ -477,7 +477,7 @@ namespace Jellyfin.Api.Controllers var newUser = await _userManager.CreateUserAsync(request.Name).ConfigureAwait(false); // no need to authenticate password for new user - if (request.Password != null) + if (request.Password is not null) { await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false); } @@ -544,7 +544,7 @@ namespace Jellyfin.Api.Controllers } var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return BadRequest(); } diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 8a2d5a27d..c18fa29af 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -306,7 +306,7 @@ namespace Jellyfin.Api.Controllers var item = i.Item2[0]; var childCount = 0; - if (i.Item1 != null && (i.Item2.Count > 1 || i.Item1 is MusicAlbum)) + if (i.Item1 is not null && (i.Item2.Count > 1 || i.Item1 is MusicAlbum)) { item = i.Item1; childCount = i.Item2.Count; @@ -402,7 +402,7 @@ namespace Jellyfin.Api.Controllers { var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return NotFound(); } @@ -411,7 +411,7 @@ namespace Jellyfin.Api.Controllers ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 85d154cac..3aeb444df 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -117,7 +117,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<IEnumerable<SpecialViewOptionDto>> GetGroupingOptions([FromRoute, Required] Guid userId) { var user = _userManager.GetUserById(userId); - if (user == null) + if (user is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs index c2bb0dfff..bb3162614 100644 --- a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs +++ b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers try { var item = _libraryManager.GetItemById(videoId); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index bf08ad376..64d8fb498 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -149,7 +149,7 @@ namespace Jellyfin.Api.Controllers { var video = (Video)_libraryManager.GetItemById(itemId); - if (video == null) + if (video is null) { return NotFound("The video either does not exist or the id does not belong to a video."); } @@ -199,7 +199,7 @@ namespace Jellyfin.Api.Controllers } var primaryVersion = items.FirstOrDefault(i => i.MediaSourceCount > 1 && string.IsNullOrEmpty(i.PrimaryVersionId)); - if (primaryVersion == null) + if (primaryVersion is null) { primaryVersion = items .OrderBy(i => @@ -439,12 +439,12 @@ namespace Jellyfin.Api.Controllers cancellationTokenSource.Token) .ConfigureAwait(false); - if (@static.HasValue && @static.Value && state.DirectStreamProvider != null) + if (@static.HasValue && @static.Value && state.DirectStreamProvider is not null) { StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, state.Request.StartTimeTicks, Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); - if (liveStreamInfo == null) + if (liveStreamInfo is null) { return NotFound(); } @@ -472,7 +472,7 @@ namespace Jellyfin.Api.Controllers var outputPathExists = System.IO.File.Exists(outputPath); var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); - var isTranscodeCached = outputPathExists && transcodingJob != null; + var isTranscodeCached = outputPathExists && transcodingJob is not null; StreamingHelpers.AddDlnaHeaders(state, Response.Headers, (@static.HasValue && @static.Value) || isTranscodeCached, state.Request.StartTimeTicks, Request, _dlnaManager); diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index b732bdff3..cd85ba221 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -152,7 +152,7 @@ namespace Jellyfin.Api.Controllers var result = new QueryResult<BaseItemDto>( startIndex, ibnItemsArray.Count, - dtos.Where(i => i != null).ToArray()); + dtos.Where(i => i is not null).ToArray()); return result; } @@ -173,7 +173,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<BaseItemDto> GetYear([FromRoute, Required] int year, [FromQuery] Guid? userId) { var item = _libraryManager.GetYear(year); - if (item == null) + if (item is null) { return NotFound(); } diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index bc83ff48a..be410ebcd 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, StreamingRequestDto streamingRequest) { - if (_httpContextAccessor.HttpContext == null) + if (_httpContextAccessor.HttpContext is null) { throw new ResourceNotFoundException(nameof(_httpContextAccessor.HttpContext)); } @@ -111,12 +111,12 @@ namespace Jellyfin.Api.Helpers cancellationTokenSource.Token) .ConfigureAwait(false); - if (streamingRequest.Static && state.DirectStreamProvider != null) + if (streamingRequest.Static && state.DirectStreamProvider is not null) { StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); - if (liveStreamInfo == null) + if (liveStreamInfo is null) { throw new FileNotFoundException(); } @@ -144,7 +144,7 @@ namespace Jellyfin.Api.Helpers var outputPathExists = File.Exists(outputPath); var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); - var isTranscodeCached = outputPathExists && transcodingJob != null; + var isTranscodeCached = outputPathExists && transcodingJob is not null; StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, streamingRequest.Static || isTranscodeCached, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index fa392e567..010b181f7 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -117,7 +117,7 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, CancellationTokenSource cancellationTokenSource) { - if (_httpContextAccessor.HttpContext == null) + if (_httpContextAccessor.HttpContext is null) { throw new ResourceNotFoundException(nameof(_httpContextAccessor.HttpContext)); } @@ -183,7 +183,7 @@ namespace Jellyfin.Api.Helpers : null; // If we're burning in subtitles then don't add additional subs to the manifest - if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) + if (state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { subtitleGroup = null; } @@ -195,8 +195,15 @@ namespace Jellyfin.Api.Helpers var basicPlaylist = AppendPlaylist(builder, state, playlistUrl, totalBitrate, subtitleGroup); - if (state.VideoStream != null && state.VideoRequest != null) + if (state.VideoStream is not null && state.VideoRequest is not null) { + // Provide a workaround for the case issue between flac and fLaC. + var flacWaPlaylist = ApplyFlacCaseWorkaround(state, basicPlaylist.ToString()); + if (!string.IsNullOrEmpty(flacWaPlaylist)) + { + builder.Append(flacWaPlaylist); + } + // Provide SDR HEVC entrance for backward compatibility. if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec) && !string.IsNullOrEmpty(state.VideoStream.VideoRange) @@ -204,7 +211,7 @@ namespace Jellyfin.Api.Helpers && string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase)) { var requestedVideoProfiles = state.GetRequestedProfiles("hevc"); - if (requestedVideoProfiles != null && requestedVideoProfiles.Length > 0) + if (requestedVideoProfiles is not null && requestedVideoProfiles.Length > 0) { // Force HEVC Main Profile and disable video stream copy. state.OutputVideoCodec = "hevc"; @@ -215,7 +222,14 @@ namespace Jellyfin.Api.Helpers var sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0; var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate; - AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup); + var sdrPlaylist = AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup); + + // Provide a workaround for the case issue between flac and fLaC. + flacWaPlaylist = ApplyFlacCaseWorkaround(state, sdrPlaylist.ToString()); + if (!string.IsNullOrEmpty(flacWaPlaylist)) + { + builder.Append(flacWaPlaylist); + } // Restore the video codec state.OutputVideoCodec = "copy"; @@ -245,12 +259,19 @@ namespace Jellyfin.Api.Helpers state.VideoStream.Level = originalLevel; var newPlaylist = ReplacePlaylistCodecsField(basicPlaylist, playlistCodecsField, newPlaylistCodecsField); builder.Append(newPlaylist); + + // Provide a workaround for the case issue between flac and fLaC. + flacWaPlaylist = ApplyFlacCaseWorkaround(state, newPlaylist); + if (!string.IsNullOrEmpty(flacWaPlaylist)) + { + builder.Append(flacWaPlaylist); + } } } if (EnableAdaptiveBitrateStreaming(state, isLiveStream, enableAdaptiveBitrateStreaming, _httpContextAccessor.HttpContext.GetNormalizedRemoteIp())) { - var requestedVideoBitrate = state.VideoRequest == null ? 0 : state.VideoRequest.VideoBitRate ?? 0; + var requestedVideoBitrate = state.VideoRequest is null ? 0 : state.VideoRequest.VideoBitRate ?? 0; // By default, vary by just 200k var variation = GetBitrateVariation(totalBitrate); @@ -306,7 +327,7 @@ namespace Jellyfin.Api.Helpers /// <param name="state">StreamState of the current stream.</param> private void AppendPlaylistVideoRangeField(StringBuilder builder, StreamState state) { - if (state.VideoStream != null && !string.IsNullOrEmpty(state.VideoStream.VideoRange)) + if (state.VideoStream is not null && !string.IsNullOrEmpty(state.VideoStream.VideoRange)) { var videoRange = state.VideoStream.VideoRange; if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) @@ -404,7 +425,7 @@ namespace Jellyfin.Api.Helpers { framerate = Math.Round(state.TargetFramerate.GetValueOrDefault(), 3); } - else if (state.VideoStream?.RealFrameRate != null) + else if (state.VideoStream?.RealFrameRate is not null) { framerate = Math.Round(state.VideoStream.RealFrameRate.GetValueOrDefault(), 3); } @@ -462,7 +483,7 @@ namespace Jellyfin.Api.Helpers return; } - var selectedIndex = state.SubtitleStream == null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Hls ? (int?)null : state.SubtitleStream.Index; + var selectedIndex = state.SubtitleStream is null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Hls ? (int?)null : state.SubtitleStream.Index; const string Format = "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"{0}\",DEFAULT={1},FORCED={2},AUTOSELECT=YES,URI=\"{3}\",LANGUAGE=\"{4}\""; foreach (var stream in subtitles) @@ -502,7 +523,7 @@ namespace Jellyfin.Api.Helpers { string levelString = string.Empty; if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec) - && state.VideoStream != null + && state.VideoStream is not null && state.VideoStream.Level.HasValue) { levelString = state.VideoStream.Level.ToString() ?? string.Empty; @@ -603,6 +624,11 @@ namespace Jellyfin.Api.Helpers return HlsCodecStringHelpers.GetALACString(); } + if (string.Equals(state.ActualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)) + { + return HlsCodecStringHelpers.GetOPUSString(); + } + return string.Empty; } @@ -701,7 +727,19 @@ namespace Jellyfin.Api.Helpers return oldPlaylist.Replace( oldValue.ToString(), newValue.ToString(), - StringComparison.OrdinalIgnoreCase); + StringComparison.Ordinal); + } + + private string ApplyFlacCaseWorkaround(StreamState state, string srcPlaylist) + { + if (!string.Equals(state.ActualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase)) + { + return string.Empty; + } + + var newPlaylist = srcPlaylist.Replace(",flac\"", ",fLaC\"", StringComparison.Ordinal); + + return newPlaylist.Contains(",fLaC\"", StringComparison.Ordinal) ? newPlaylist : string.Empty; } } } diff --git a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs index a5369c441..cbe82979b 100644 --- a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Api.Helpers /// <summary> /// Codec name for FLAC. /// </summary> - public const string FLAC = "fLaC"; + public const string FLAC = "flac"; /// <summary> /// Codec name for ALAC. @@ -35,6 +35,11 @@ namespace Jellyfin.Api.Helpers public const string ALAC = "alac"; /// <summary> + /// Codec name for OPUS. + /// </summary> + public const string OPUS = "opus"; + + /// <summary> /// Gets a MP3 codec string. /// </summary> /// <returns>MP3 codec string.</returns> @@ -102,6 +107,15 @@ namespace Jellyfin.Api.Helpers } /// <summary> + /// Gets an OPUS codec string. + /// </summary> + /// <returns>OPUS codec string.</returns> + public static string GetOPUSString() + { + return OPUS; + } + + /// <summary> /// Gets a H.264 codec string. /// </summary> /// <param name="profile">H.264 profile.</param> diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 456762147..671107c1f 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -46,8 +46,8 @@ namespace Jellyfin.Api.Helpers while (!reader.EndOfStream) { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - if (line == null) + var line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false); + if (line is null) { // Nothing currently in buffer. break; diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 4441ae023..e8ce1ca2a 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -127,7 +127,7 @@ namespace Jellyfin.Api.Helpers // Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it // Should we move this directly into MediaSourceManager? var mediaSourcesClone = JsonSerializer.Deserialize<MediaSourceInfo[]>(JsonSerializer.SerializeToUtf8Bytes(mediaSources)); - if (mediaSourcesClone != null) + if (mediaSourcesClone is not null) { result.MediaSources = mediaSourcesClone; } @@ -247,7 +247,7 @@ namespace Jellyfin.Api.Helpers ? streamBuilder.BuildAudioItem(options) : streamBuilder.BuildVideoItem(options); - if (streamInfo != null) + if (streamInfo is not null) { streamInfo.PlaySessionId = playSessionId; streamInfo.StartPositionTicks = startTimeTicks; @@ -262,7 +262,7 @@ namespace Jellyfin.Api.Helpers mediaSource.SupportsTranscoding = streamInfo.PlayMethod == PlayMethod.DirectStream - || mediaSource.TranscodingContainer != null + || mediaSource.TranscodingContainer is not null || profile.TranscodingProfiles.Any(i => i.Type == streamInfo.MediaType && i.Context == options.Context); if (item is Audio) @@ -390,16 +390,16 @@ namespace Jellyfin.Api.Helpers var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); var profile = request.DeviceProfile; - if (profile == null) + if (profile is null) { var clientCapabilities = _deviceManager.GetCapabilities(httpContext.User.GetDeviceId()); - if (clientCapabilities != null) + if (clientCapabilities is not null) { profile = clientCapabilities.DeviceProfile; } } - if (profile != null) + if (profile is not null) { var item = _libraryManager.GetItemById(request.ItemId); @@ -431,7 +431,7 @@ namespace Jellyfin.Api.Helpers } } - // here was a check if (result.MediaSource != null) but Rider said it will never be null + // here was a check if (result.MediaSource is not null) but Rider said it will never be null NormalizeMediaSourceContainer(result.MediaSource, profile!, DlnaProfileType.Video); return result; diff --git a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs index 6f5b64ea8..dfeeea2b0 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs @@ -151,7 +151,7 @@ namespace Jellyfin.Api.Helpers { _stream.Dispose(); - if (_job != null) + if (_job is not null) { _transcodingJobHelper?.OnTranscodeEndRequest(_job); } @@ -166,7 +166,7 @@ namespace Jellyfin.Api.Helpers private void UpdateBytesWritten(int totalBytesRead) { - if (_job != null) + if (_job is not null) { _job.BytesDownloaded += totalBytesRead; } diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index 8c5af013a..035d84513 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -96,7 +96,7 @@ namespace Jellyfin.Api.Helpers httpContext.GetNormalizedRemoteIp().ToString(), user).ConfigureAwait(false); - if (session == null) + if (session is null) { throw new ArgumentException("Session not found."); } diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index c8e62999c..d4fc9c020 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -76,7 +76,7 @@ namespace Jellyfin.Api.Helpers } streamingRequest.StreamOptions = ParseStreamOptions(httpRequest.Query); - if (httpRequest.Path.Value == null) + if (httpRequest.Path.Value is null) { throw new ResourceNotFoundException(nameof(httpRequest.Path)); } @@ -137,12 +137,12 @@ namespace Jellyfin.Api.Helpers ? transcodingJobHelper.GetTranscodingJob(streamingRequest.PlaySessionId) : null; - if (currentJob != null) + if (currentJob is not null) { mediaSource = currentJob.MediaSource; } - if (mediaSource == null) + if (mediaSource is null) { var mediaSources = await mediaSourceManager.GetPlaybackMediaSources(libraryManager.GetItemById(streamingRequest.Id), null, false, false, cancellationToken).ConfigureAwait(false); @@ -150,7 +150,7 @@ namespace Jellyfin.Api.Helpers ? mediaSources[0] : mediaSources.Find(i => string.Equals(i.Id, streamingRequest.MediaSourceId, StringComparison.Ordinal)); - if (mediaSource == null && Guid.Parse(streamingRequest.MediaSourceId).Equals(streamingRequest.Id)) + if (mediaSource is null && Guid.Parse(streamingRequest.MediaSourceId).Equals(streamingRequest.Id)) { mediaSource = mediaSources[0]; } @@ -189,7 +189,7 @@ namespace Jellyfin.Api.Helpers state.OutputAudioChannels = encodingHelper.GetNumAudioChannelsParam(state, state.AudioStream, state.OutputAudioCodec); - if (state.VideoRequest != null) + if (state.VideoRequest is not null) { state.OutputVideoCodec = state.Request.VideoCodec; state.OutputVideoBitrate = encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec); @@ -204,7 +204,7 @@ namespace Jellyfin.Api.Helpers && !state.VideoRequest.MaxHeight.HasValue; if (isVideoResolutionNotRequested - && state.VideoStream != null + && state.VideoStream is not null && state.VideoRequest.VideoBitRate.HasValue && state.VideoStream.BitRate.HasValue && state.VideoRequest.VideoBitRate.Value >= state.VideoStream.BitRate.Value) @@ -281,7 +281,7 @@ namespace Jellyfin.Api.Helpers Convert.ToInt32(ms))); } - if (!isStaticallyStreamed && profile != null) + if (!isStaticallyStreamed && profile is not null) { AddTimeSeekResponseHeaders(state, responseHeaders, startTimeTicks); } @@ -364,9 +364,9 @@ namespace Jellyfin.Api.Helpers /// </summary> /// <param name="queryString">The query string.</param> /// <returns>A <see cref="Dictionary{String,String}"/> containing the stream options.</returns> - private static Dictionary<string, string> ParseStreamOptions(IQueryCollection queryString) + private static Dictionary<string, string?> ParseStreamOptions(IQueryCollection queryString) { - Dictionary<string, string> streamOptions = new Dictionary<string, string>(); + Dictionary<string, string?> streamOptions = new Dictionary<string, string?>(); foreach (var param in queryString) { if (char.IsLower(param.Key[0])) @@ -510,16 +510,16 @@ namespace Jellyfin.Api.Helpers { state.DeviceProfile = dlnaManager.GetProfile(deviceProfileId); - if (state.DeviceProfile == null) + if (state.DeviceProfile is null) { var caps = deviceManager.GetCapabilities(deviceProfileId); - state.DeviceProfile = caps == null ? dlnaManager.GetProfile(request.Headers) : caps.DeviceProfile; + state.DeviceProfile = caps is null ? dlnaManager.GetProfile(request.Headers) : caps.DeviceProfile; } } var profile = state.DeviceProfile; - if (profile == null) + if (profile is null) { // Don't use settings from the default profile. // Only use a specific profile if it was requested. @@ -553,7 +553,7 @@ namespace Jellyfin.Api.Helpers state.TargetVideoCodecTag, state.IsTargetAVC); - if (mediaProfile != null) + if (mediaProfile is not null) { state.MimeType = mediaProfile.MimeType; } @@ -562,13 +562,13 @@ namespace Jellyfin.Api.Helpers { var transcodingProfile = !state.IsVideoRequest ? profile.GetAudioTranscodingProfile(state.OutputContainer, audioCodec) : profile.GetVideoTranscodingProfile(state.OutputContainer, audioCodec, videoCodec); - if (transcodingProfile != null) + if (transcodingProfile is not null) { state.EstimateContentLength = transcodingProfile.EstimateContentLength; // state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - if (state.VideoRequest != null) + if (state.VideoRequest is not null) { state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; @@ -616,7 +616,7 @@ namespace Jellyfin.Api.Helpers request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); break; case 4: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.VideoCodec = val; } @@ -626,21 +626,21 @@ namespace Jellyfin.Api.Helpers request.AudioCodec = val; break; case 6: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture); } break; case 7: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture); } break; case 8: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.VideoBitRate = int.Parse(val, CultureInfo.InvariantCulture); } @@ -653,21 +653,21 @@ namespace Jellyfin.Api.Helpers request.MaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture); break; case 11: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.MaxFramerate = float.Parse(val, CultureInfo.InvariantCulture); } break; case 12: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.MaxWidth = int.Parse(val, CultureInfo.InvariantCulture); } break; case 13: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.MaxHeight = int.Parse(val, CultureInfo.InvariantCulture); } @@ -677,28 +677,28 @@ namespace Jellyfin.Api.Helpers request.StartTimeTicks = long.Parse(val, CultureInfo.InvariantCulture); break; case 15: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.Level = val; } break; case 16: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.MaxRefFrames = int.Parse(val, CultureInfo.InvariantCulture); } break; case 17: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.MaxVideoBitDepth = int.Parse(val, CultureInfo.InvariantCulture); } break; case 18: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.Profile = val; } @@ -720,14 +720,14 @@ namespace Jellyfin.Api.Helpers // Duplicating ItemId because of MediaMonkey break; case 24: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } break; case 25: - if (!string.IsNullOrWhiteSpace(val) && videoRequest != null) + if (!string.IsNullOrWhiteSpace(val) && videoRequest is not null) { if (Enum.TryParse(val, out SubtitleDeliveryMethod method)) { @@ -740,7 +740,7 @@ namespace Jellyfin.Api.Helpers request.TranscodingMaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture); break; case 27: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } @@ -750,7 +750,7 @@ namespace Jellyfin.Api.Helpers request.Tag = val; break; case 29: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.RequireAvc = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } @@ -760,14 +760,14 @@ namespace Jellyfin.Api.Helpers request.SubtitleCodec = val; break; case 31: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.RequireNonAnamorphic = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } break; case 32: - if (videoRequest != null) + if (videoRequest is not null) { videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index c663c6e31..77dd51860 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -136,10 +136,7 @@ namespace Jellyfin.Api.Helpers /// <exception cref="ArgumentNullException">Play session id is null.</exception> public void PingTranscodingJob(string playSessionId, bool? isUserPaused) { - if (string.IsNullOrEmpty(playSessionId)) - { - throw new ArgumentNullException(nameof(playSessionId)); - } + ArgumentException.ThrowIfNullOrEmpty(playSessionId); _logger.LogDebug("PingTranscodingJob PlaySessionId={0} isUsedPaused: {1}", playSessionId, isUserPaused); @@ -416,7 +413,7 @@ namespace Jellyfin.Api.Helpers } } - if (exs != null) + if (exs is not null) { throw new AggregateException("Error deleting HLS files", exs); } @@ -443,7 +440,7 @@ namespace Jellyfin.Api.Helpers { var ticks = transcodingPosition?.Ticks; - if (job != null) + if (job is not null) { job.Framerate = framerate; job.CompletionPercentage = percentComplete; @@ -510,11 +507,11 @@ namespace Jellyfin.Api.Helpers await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); - if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) + if (state.VideoRequest is not null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { var userId = request.HttpContext.User.GetUserId(); var user = userId.Equals(default) ? null : _userManager.GetUserById(userId); - if (user != null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) + if (user is not null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) { this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state); @@ -522,13 +519,10 @@ namespace Jellyfin.Api.Helpers } } - if (string.IsNullOrEmpty(_mediaEncoder.EncoderPath)) - { - throw new ArgumentException("FFmpeg path not set."); - } + ArgumentException.ThrowIfNullOrEmpty(_mediaEncoder.EncoderPath); // If subtitles get burned in fonts may need to be extracted from the media file - if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) + if (state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id); await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false); @@ -577,7 +571,7 @@ namespace Jellyfin.Api.Helpers _logger.LogInformation("{Filename} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); var logFilePrefix = "FFmpeg.Transcode-"; - if (state.VideoRequest != null + if (state.VideoRequest is not null && EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { logFilePrefix = EncodingHelper.IsCopyCodec(state.OutputAudioCodec) @@ -748,7 +742,7 @@ namespace Jellyfin.Api.Helpers { var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase)); - if (job != null) + if (job is not null) { _activeTranscodingJobs.Remove(job); } @@ -805,7 +799,7 @@ namespace Jellyfin.Api.Helpers _encodingHelper.AttachMediaSourceInfo(state, encodingOptions, liveStreamResponse.MediaSource, state.RequestedUrl); - if (state.VideoRequest != null) + if (state.VideoRequest is not null) { _encodingHelper.TryStreamCopy(state); } @@ -829,7 +823,7 @@ namespace Jellyfin.Api.Helpers { var job = _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && string.Equals(j.Path, path, StringComparison.OrdinalIgnoreCase)); - if (job == null) + if (job is null) { return null; } diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index a4502b612..0317a2f2b 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -6,19 +6,19 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> + <TargetFramework>net7.0</TargetFramework> <GenerateDocumentationFile>true</GenerateDocumentationFile> <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 --> <NoWarn>AD0001</NoWarn> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors> </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.11" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="7.0.0" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.4.0" /> </ItemGroup> diff --git a/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs b/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs index c04f3c721..75e47a71b 100644 --- a/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs +++ b/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Api.ModelBinders { var value = valueProviderResult.FirstValue; - if (value != null) + if (value is not null) { var splitValues = value.Split(',', StringSplitOptions.RemoveEmptyEntries); var typedValues = GetParsedResult(splitValues, elementType, converter); diff --git a/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs b/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs index 2ccfd0c06..da0addd0e 100644 --- a/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs +++ b/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Api.ModelBinders public IModelBinder? GetBinder(ModelBinderProviderContext context) { var nullableType = Nullable.GetUnderlyingType(context.Metadata.ModelType); - if (nullableType == null || !nullableType.IsEnum) + if (nullableType is null || !nullableType.IsEnum) { // Type isn't nullable or isn't an enum. return null; diff --git a/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs b/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs index 639ab0793..4257ba0e2 100644 --- a/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs +++ b/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Api.ModelBinders { var value = valueProviderResult.FirstValue; - if (value != null) + if (value is not null) { var splitValues = value.Split('|', StringSplitOptions.RemoveEmptyEntries); var typedValues = GetParsedResult(splitValues, elementType, converter); diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs index ab67c8732..9060500c8 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs @@ -189,7 +189,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos { lock (_timerLock) { - if (KillTimer != null) + if (KillTimer is not null) { KillTimer.Dispose(); KillTimer = null; @@ -220,7 +220,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos lock (_timerLock) { - if (KillTimer == null) + if (KillTimer is null) { Logger.LogDebug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); KillTimer = new Timer(new TimerCallback(callback), this, intervalMs, Timeout.Infinite); @@ -245,7 +245,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos lock (_timerLock) { - if (KillTimer != null) + if (KillTimer is not null) { var intervalMs = PingTimeout; diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 99376873c..9c4e377cd 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -210,7 +210,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos private void DisposeTimer() { - if (_timer != null) + if (_timer is not null) { _timer.Dispose(); _timer = null; diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs index 8182e3c9e..1fce1d20a 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs @@ -43,7 +43,7 @@ namespace Jellyfin.Api.Models.StreamingDtos set { BaseRequest = value; - IsVideoRequest = VideoRequest != null; + IsVideoRequest = VideoRequest is not null; } } |
