From 44e71774b17942034691d6a2c630cd687b23bceb Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 10 Apr 2021 16:17:36 -0400 Subject: Rewrite device manager using EF Core --- Emby.Server.Implementations/ApplicationHost.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3846de5fd..f2ed20fbc 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -644,8 +644,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); -- cgit v1.2.3 From 2e98de90628e9a4e42fb182f2d5a2a296acfd827 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Wed, 5 May 2021 12:51:14 +0100 Subject: Code Clean up: Convert to null-coalescing operator ?? (#5845) Co-authored-by: Cody Robibero Co-authored-by: Patrick Barron <18354464+barronpm@users.noreply.github.com> --- Emby.Server.Implementations/ApplicationHost.cs | 10 +---- Emby.Server.Implementations/Dto/DtoService.cs | 15 ++------ .../Library/LibraryManager.cs | 5 +-- .../Library/Resolvers/TV/EpisodeResolver.cs | 14 ++----- .../LiveTv/EmbyTV/EmbyTV.cs | 10 ++--- .../LiveTv/Listings/SchedulesDirect.cs | 7 +--- .../LiveTv/LiveTvManager.cs | 15 ++------ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 5 +-- .../Plugins/PluginManager.cs | 13 +------ .../ScheduledTasks/ScheduledTaskWorker.cs | 7 +--- .../Session/SessionManager.cs | 5 +-- Jellyfin.Api/Controllers/PluginsController.cs | 7 +--- Jellyfin.Api/Controllers/SearchController.cs | 5 +-- Jellyfin.Api/Helpers/StreamingHelpers.cs | 5 +-- MediaBrowser.Common/Net/IPHost.cs | 5 +-- MediaBrowser.Common/Plugins/BasePluginOfT.cs | 5 +-- MediaBrowser.Controller/Entities/BaseItem.cs | 26 ++++--------- MediaBrowser.Controller/Entities/UserView.cs | 5 +-- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 5 +-- MediaBrowser.Controller/Playlists/Playlist.cs | 5 +-- .../Providers/MetadataRefreshOptions.cs | 5 +-- .../Providers/MetadataResult.cs | 16 +++----- .../Probing/ProbeResultNormalizer.cs | 45 ++++++---------------- .../Entities/ProviderIdsExtensions.cs | 5 +-- .../MediaInfo/FFProbeVideoInfo.cs | 5 +-- .../Subtitles/SubtitleManager.cs | 5 +-- RSSDP/SsdpCommunicationsServer.cs | 5 +-- 27 files changed, 60 insertions(+), 200 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 703f8d20d..75d8fc113 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -335,10 +335,7 @@ namespace Emby.Server.Implementations { get { - if (_deviceId == null) - { - _deviceId = new DeviceId(ApplicationPaths, LoggerFactory); - } + _deviceId ??= new DeviceId(ApplicationPaths, LoggerFactory); return _deviceId.Value; } @@ -370,10 +367,7 @@ namespace Emby.Server.Implementations /// System.Object. protected object CreateInstanceSafe(Type type) { - if (_creatingInstances == null) - { - _creatingInstances = new List(); - } + _creatingInstances ??= new List(); if (_creatingInstances.IndexOf(type) != -1) { diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 54b18a8c8..4ae35039a 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -665,10 +665,7 @@ namespace Emby.Server.Implementations.Dto var tag = GetImageCacheTag(item, image); if (!string.IsNullOrEmpty(image.BlurHash)) { - if (dto.ImageBlurHashes == null) - { - dto.ImageBlurHashes = new Dictionary>(); - } + dto.ImageBlurHashes ??= new Dictionary>(); if (!dto.ImageBlurHashes.ContainsKey(image.Type)) { @@ -702,10 +699,7 @@ namespace Emby.Server.Implementations.Dto if (hashes.Count > 0) { - if (dto.ImageBlurHashes == null) - { - dto.ImageBlurHashes = new Dictionary>(); - } + dto.ImageBlurHashes ??= new Dictionary>(); dto.ImageBlurHashes[imageType] = hashes; } @@ -898,10 +892,7 @@ namespace Emby.Server.Implementations.Dto dto.Taglines = new string[] { item.Tagline }; } - if (dto.Taglines == null) - { - dto.Taglines = Array.Empty(); - } + dto.Taglines ??= Array.Empty(); } dto.Type = item.GetBaseItemKind(); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index a44edad16..4d207471a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -176,10 +176,7 @@ namespace Emby.Server.Implementations.Library { lock (_rootFolderSyncLock) { - if (_rootFolder == null) - { - _rootFolder = CreateRootFolder(); - } + _rootFolder ??= CreateRootFolder(); } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 9b4cd7a3d..6f29bc649 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -35,14 +35,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - var season = parent as Season; - // Just in case the user decided to nest episodes. // Not officially supported but in some cases we can handle it. - if (season == null) - { - season = parent.GetParents().OfType().FirstOrDefault(); - } + + var season = parent as Season ?? parent.GetParents().OfType().FirstOrDefault(); // 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 @@ -55,11 +51,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if (episode != null) { - var series = parent as Series; - if (series == null) - { - series = parent.GetParents().OfType().FirstOrDefault(); - } + var series = parent as Series ?? parent.GetParents().OfType().FirstOrDefault(); if (series != null) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 665fbfa0f..28a2095e1 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2237,14 +2237,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var enabledTimersForSeries = new List(); foreach (var timer in allTimers) { - var existingTimer = _timerProvider.GetTimer(timer.Id); - - if (existingTimer == null) - { - existingTimer = string.IsNullOrWhiteSpace(timer.ProgramId) + var existingTimer = _timerProvider.GetTimer(timer.Id) + ?? (string.IsNullOrWhiteSpace(timer.ProgramId) ? null - : _timerProvider.GetTimerByProgramId(timer.ProgramId); - } + : _timerProvider.GetTimerByProgramId(timer.ProgramId)); if (existingTimer == null) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 1926e738f..9af65cabb 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -787,14 +787,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var channelNumber = GetChannelNumber(channel); - var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)); - if (station == null) - { - station = new ScheduleDirect.Station + var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)) + ?? new ScheduleDirect.Station { stationID = channel.stationID }; - } var channelInfo = new ChannelInfo { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 63a3146aa..1145d8aa1 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -987,10 +987,7 @@ namespace Emby.Server.Implementations.LiveTv var externalProgramId = programTuple.Item2; string externalSeriesId = programTuple.Item3; - if (timerList == null) - { - timerList = (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; - } + timerList ??= (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, externalProgramId, StringComparison.OrdinalIgnoreCase)); var foundSeriesTimer = false; @@ -1018,10 +1015,7 @@ namespace Emby.Server.Implementations.LiveTv continue; } - if (seriesTimerList == null) - { - seriesTimerList = (await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false)).Items; - } + seriesTimerList ??= (await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false)).Items; var seriesTimer = seriesTimerList.FirstOrDefault(i => string.Equals(i.SeriesId, externalSeriesId, StringComparison.OrdinalIgnoreCase)); @@ -1974,10 +1968,7 @@ namespace Emby.Server.Implementations.LiveTv }; } - if (service == null) - { - service = _services[0]; - } + service ??= _services[0]; var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c32ca2fb6..4aa5832b1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -421,10 +421,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun string audioCodec = channelInfo.AudioCodec; - if (!videoBitrate.HasValue) - { - videoBitrate = isHd ? 15000000 : 2000000; - } + videoBitrate ??= isHd ? 15000000 : 2000000; int? audioBitrate = isHd ? 448000 : 192000; diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index fd2ee6b7a..14df20936 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -44,12 +44,7 @@ namespace Emby.Server.Implementations.Plugins { get { - if (_httpClientFactory == null) - { - _httpClientFactory = _appHost.Resolve(); - } - - return _httpClientFactory; + return _httpClientFactory ?? (_httpClientFactory = _appHost.Resolve()); } } @@ -276,11 +271,7 @@ namespace Emby.Server.Implementations.Plugins // If no version is given, return the current instance. var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList(); - plugin = plugins.FirstOrDefault(p => p.Instance != null); - if (plugin == null) - { - plugin = plugins.OrderByDescending(p => p.Version).FirstOrDefault(); - } + plugin = plugins.FirstOrDefault(p => p.Instance != null) ?? plugins.OrderByDescending(p => p.Version).FirstOrDefault(); } else { diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 61dccaa19..101d9b537 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -301,12 +301,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { get { - if (_id == null) - { - _id = ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture); - } - - return _id; + return _id ??= ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture); } } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 6f21ec31e..6844152ea 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1475,10 +1475,7 @@ namespace Emby.Server.Implementations.Session user = _userManager.GetUserById(request.UserId); } - if (user == null) - { - user = _userManager.GetUserByName(request.Username); - } + user ??= _userManager.GetUserByName(request.Username); if (enforcePassword) { diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index adec86a10..7a6130719 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -207,12 +207,7 @@ 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); - if (plugin == null) - { - // Then by the status. - plugin = plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); - } + var plugin = plugins.FirstOrDefault(p => p.Instance == null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); if (plugin != null) { diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 6c22050a7..73bdf9018 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -228,10 +228,7 @@ namespace Jellyfin.Api.Controllers itemWithImage = GetParentWithImage(item, ImageType.Thumb); } - if (itemWithImage == null) - { - itemWithImage = GetParentWithImage(item, ImageType.Thumb); - } + itemWithImage ??= GetParentWithImage(item, ImageType.Thumb); if (itemWithImage != null) { diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 583e613b4..8cffe9c4c 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -292,10 +292,7 @@ namespace Jellyfin.Api.Helpers } } - if (profile == null) - { - profile = dlnaManager.GetDefaultProfile(); - } + profile ??= dlnaManager.GetDefaultProfile(); var audioCodec = state.ActualOutputAudioCodec; diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index fb3ef9b12..7156ce618 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -400,10 +400,7 @@ namespace MediaBrowser.Common.Net private bool ResolveHost() { // When was the last time we resolved? - if (_lastResolved == null) - { - _lastResolved = DateTime.UtcNow; - } + _lastResolved ??= DateTime.UtcNow; // If we haven't resolved before, or our timer has run out... if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout))) diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index 99c226f50..e074cc6a0 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -105,10 +105,7 @@ namespace MediaBrowser.Common.Plugins { lock (_configurationSyncLock) { - if (_configuration == null) - { - _configuration = LoadConfiguration(); - } + _configuration ??= LoadConfiguration(); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1b69c6646..32ae15498 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -106,15 +106,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (_themeSongIds == null) - { - _themeSongIds = GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) - .Select(song => song.Id) - .ToArray(); - } - - return _themeSongIds; + return _themeSongIds ??= GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) + .Select(song => song.Id) + .ToArray(); } private set @@ -128,15 +123,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (_themeVideoIds == null) - { - _themeVideoIds = GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) - .Select(song => song.Id) - .ToArray(); - } - - return _themeVideoIds; + return _themeVideoIds ??= GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) + .Select(song => song.Id) + .ToArray(); } private set diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index b1da4d64c..fec83dd94 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -75,10 +75,7 @@ namespace MediaBrowser.Controller.Entities public override List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { - if (query == null) - { - query = new InternalItemsQuery(user); - } + query ??= new InternalItemsQuery(user); query.EnableTotalRecordCount = false; var result = GetItemList(query); diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index f86f7df25..f9086066d 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -147,10 +147,7 @@ namespace MediaBrowser.Controller.Library throw new ArgumentException("The path was empty or null.", nameof(path)); } - if (AdditionalLocations == null) - { - AdditionalLocations = new List(); - } + AdditionalLocations ??= new List(); AdditionalLocations.Add(path); } diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index c9c168c4c..3c93cfc79 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -126,10 +126,7 @@ namespace MediaBrowser.Controller.Playlists private List GetPlayableItems(User user, InternalItemsQuery query) { - if (query == null) - { - query = new InternalItemsQuery(user); - } + query ??= new InternalItemsQuery(user); query.IsFolder = false; diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index b92b83701..db0ef7072 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -45,10 +45,7 @@ namespace MediaBrowser.Controller.Providers if (copy.RefreshPaths != null && copy.RefreshPaths.Length > 0) { - if (RefreshPaths == null) - { - RefreshPaths = Array.Empty(); - } + RefreshPaths ??= Array.Empty(); RefreshPaths = copy.RefreshPaths.ToArray(); } diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 864cb3050..98c7eadfe 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -37,10 +37,7 @@ namespace MediaBrowser.Controller.Providers public void AddPerson(PersonInfo p) { - if (People == null) - { - People = new List(); - } + People ??= new List(); PeopleHelper.AddPerson(People, p); } @@ -54,16 +51,15 @@ namespace MediaBrowser.Controller.Providers { People = new List(); } - - People.Clear(); + else + { + People.Clear(); + } } public UserItemData GetOrAddUserData(string userId) { - if (UserDataList == null) - { - UserDataList = new List(); - } + UserDataList ??= new List(); UserItemData userData = null; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ee2e5fcde..2e96f8cb0 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1187,43 +1187,28 @@ namespace MediaBrowser.MediaEncoding.Probing FetchStudios(audio, tags, "label"); // These support mulitple values, but for now we only store the first. - var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); - } + var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } @@ -1290,15 +1275,7 @@ namespace MediaBrowser.MediaEncoding.Probing private IEnumerable GetSplitWhitelist() { - if (_splitWhiteList == null) - { - _splitWhiteList = new List - { - "AC/DC" - }; - } - - return _splitWhiteList; + return _splitWhiteList ??= new List { "AC/DC" }; } /// diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 09d14dc6a..ce4b0ec92 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -123,10 +123,7 @@ namespace MediaBrowser.Model.Entities else { // Ensure it exists - if (instance.ProviderIds == null) - { - instance.ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } + instance.ProviderIds ??= new Dictionary(StringComparer.OrdinalIgnoreCase); instance.ProviderIds[name] = value; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 74849a522..f049cc81f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -111,10 +111,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - if (streamFileNames == null) - { - streamFileNames = Array.Empty(); - } + streamFileNames ??= Array.Empty(); mediaInfoResult = await GetMediaInfo(item, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 1f3d9acff..8d62343cb 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -256,10 +256,7 @@ namespace MediaBrowser.Providers.Subtitles } catch (Exception ex) { - if (exceptionToThrow == null) - { - exceptionToThrow = ex; - } + exceptionToThrow ??= ex; } finally { diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 8f1f0fa61..f448ad38b 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -415,10 +415,7 @@ namespace Rssdp.Infrastructure { lock (_SendSocketSynchroniser) { - if (_sendSockets == null) - { - _sendSockets = CreateSocketAndListenForResponsesAsync(); - } + _sendSockets ??= CreateSocketAndListenForResponsesAsync(); } } } -- cgit v1.2.3 From 7e8428e588b3f0a0574da44081098c64fe1a47d7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 20 May 2021 21:28:18 +0200 Subject: Enable nullable reference types for Emby.Server.Implementations --- .../AppBase/BaseApplicationPaths.cs | 8 ++------ .../AppBase/BaseConfigurationManager.cs | 2 ++ .../AppBase/ConfigurationHelper.cs | 2 -- Emby.Server.Implementations/ApplicationHost.cs | 2 ++ .../Channels/ChannelManager.cs | 2 ++ .../Collections/CollectionImageProvider.cs | 4 ++-- .../Collections/CollectionManager.cs | 2 ++ .../Configuration/ServerConfigurationManager.cs | 2 ++ .../Cryptography/CryptographyProvider.cs | 2 -- .../Data/BaseSqliteRepository.cs | 2 ++ .../Data/ManagedConnection.cs | 2 +- Emby.Server.Implementations/Data/SqliteExtensions.cs | 1 + .../Data/SqliteItemRepository.cs | 2 ++ .../Data/SqliteUserDataRepository.cs | 2 ++ Emby.Server.Implementations/Data/TypeMapper.cs | 6 +++--- Emby.Server.Implementations/Devices/DeviceId.cs | 2 ++ Emby.Server.Implementations/Devices/DeviceManager.cs | 2 ++ Emby.Server.Implementations/Dto/DtoService.cs | 2 ++ .../Emby.Server.Implementations.csproj | 1 + .../EntryPoints/ExternalPortForwarding.cs | 2 ++ .../EntryPoints/LibraryChangedNotifier.cs | 2 ++ .../EntryPoints/RecordingNotifier.cs | 2 ++ .../EntryPoints/UdpServerEntryPoint.cs | 2 -- .../EntryPoints/UserDataChangeNotifier.cs | 2 ++ .../HttpServer/Security/AuthorizationContext.cs | 20 ++++++++++---------- .../HttpServer/Security/SessionContext.cs | 4 ++-- .../HttpServer/WebSocketConnection.cs | 2 -- .../HttpServer/WebSocketManager.cs | 2 ++ Emby.Server.Implementations/IO/FileRefresher.cs | 2 ++ Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 ++ Emby.Server.Implementations/IO/ManagedFileSystem.cs | 6 +++--- .../IO/MbLinkShortcutHandler.cs | 2 +- Emby.Server.Implementations/IO/StreamHelper.cs | 2 +- Emby.Server.Implementations/IStartupOptions.cs | 1 - .../Images/BaseDynamicImageProvider.cs | 2 ++ .../Images/CollectionFolderImageProvider.cs | 2 ++ .../Images/DynamicImageProvider.cs | 2 ++ .../Images/FolderImageProvider.cs | 2 ++ .../Images/GenreImageProvider.cs | 2 ++ .../Images/PlaylistImageProvider.cs | 2 ++ .../Library/ExclusiveLiveStream.cs | 2 ++ .../Library/IgnorePatterns.cs | 2 -- .../Library/LibraryManager.cs | 2 ++ .../Library/LiveStreamHelper.cs | 2 ++ .../Library/MediaSourceManager.cs | 2 ++ .../Library/MediaStreamSelector.cs | 2 ++ Emby.Server.Implementations/Library/MusicManager.cs | 2 ++ .../Library/PathExtensions.cs | 2 -- .../Library/ResolverHelper.cs | 2 -- .../Library/Resolvers/Audio/AudioResolver.cs | 2 ++ .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 2 ++ .../Library/Resolvers/Audio/MusicArtistResolver.cs | 2 ++ .../Library/Resolvers/BaseVideoResolver.cs | 2 ++ .../Library/Resolvers/Books/BookResolver.cs | 2 ++ .../Library/Resolvers/FolderResolver.cs | 2 ++ .../Library/Resolvers/ItemResolver.cs | 2 ++ .../Library/Resolvers/Movies/BoxSetResolver.cs | 2 ++ .../Library/Resolvers/Movies/MovieResolver.cs | 2 ++ .../Library/Resolvers/PhotoAlbumResolver.cs | 2 ++ .../Library/Resolvers/PhotoResolver.cs | 2 ++ .../Library/Resolvers/PlaylistResolver.cs | 2 ++ .../Library/Resolvers/SpecialFolderResolver.cs | 2 ++ .../Library/Resolvers/TV/EpisodeResolver.cs | 2 ++ .../Library/Resolvers/TV/SeasonResolver.cs | 2 ++ .../Library/Resolvers/TV/SeriesResolver.cs | 2 ++ .../Library/Resolvers/VideoResolver.cs | 2 ++ Emby.Server.Implementations/Library/SearchEngine.cs | 2 ++ .../Library/UserDataManager.cs | 2 ++ .../Library/UserViewManager.cs | 2 ++ .../LiveTv/EmbyTV/DirectRecorder.cs | 2 ++ Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 2 ++ .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 ++ .../LiveTv/EmbyTV/EpgChannelData.cs | 7 +++---- .../LiveTv/EmbyTV/ItemDataProvider.cs | 2 ++ .../LiveTv/EmbyTV/RecordingHelper.cs | 2 ++ .../LiveTv/EmbyTV/TimerManager.cs | 2 ++ .../LiveTv/Listings/SchedulesDirect.cs | 2 ++ .../LiveTv/Listings/XmlTvListingsProvider.cs | 2 ++ .../LiveTv/LiveTvDtoService.cs | 2 ++ Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 2 ++ .../LiveTv/LiveTvMediaSourceProvider.cs | 2 ++ .../LiveTv/TunerHosts/BaseTunerHost.cs | 2 ++ .../LiveTv/TunerHosts/HdHomerun/Channels.cs | 2 ++ .../LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs | 2 ++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 ++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs | 2 ++ .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 ++ .../LiveTv/TunerHosts/LiveStream.cs | 2 ++ .../LiveTv/TunerHosts/M3UTunerHost.cs | 2 ++ .../LiveTv/TunerHosts/M3uParser.cs | 2 ++ .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 ++ .../Localization/LocalizationManager.cs | 2 ++ .../MediaEncoder/EncodingManager.cs | 2 ++ Emby.Server.Implementations/Net/SocketFactory.cs | 2 ++ Emby.Server.Implementations/Net/UdpSocket.cs | 2 ++ .../Playlists/PlaylistManager.cs | 2 ++ Emby.Server.Implementations/Plugins/PluginManager.cs | 2 -- .../QuickConnect/QuickConnectManager.cs | 2 ++ .../ScheduledTasks/ScheduledTaskWorker.cs | 2 ++ .../ScheduledTasks/TaskManager.cs | 2 ++ .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 6 ++++-- .../ScheduledTasks/Tasks/CleanActivityLogTask.cs | 4 ++-- .../ScheduledTasks/Triggers/DailyTrigger.cs | 2 ++ .../ScheduledTasks/Triggers/IntervalTrigger.cs | 2 ++ .../ScheduledTasks/Triggers/StartupTrigger.cs | 2 ++ .../ScheduledTasks/Triggers/WeeklyTrigger.cs | 2 ++ .../Security/AuthenticationRepository.cs | 2 ++ .../Serialization/MyXmlSerializer.cs | 10 ++++++---- .../Session/SessionManager.cs | 2 ++ .../Session/SessionWebSocketListener.cs | 2 ++ .../Session/WebSocketController.cs | 1 - .../Sorting/AiredEpisodeOrderComparer.cs | 2 +- .../Sorting/AlbumArtistComparer.cs | 4 ++-- Emby.Server.Implementations/Sorting/AlbumComparer.cs | 4 ++-- .../Sorting/ArtistComparer.cs | 4 ++-- .../Sorting/CommunityRatingComparer.cs | 2 +- .../Sorting/CriticRatingComparer.cs | 6 +++--- .../Sorting/DateCreatedComparer.cs | 2 +- .../Sorting/DateLastMediaAddedComparer.cs | 1 + .../Sorting/DatePlayedComparer.cs | 2 ++ .../Sorting/IsFavoriteOrLikeComparer.cs | 1 + .../Sorting/IsFolderComparer.cs | 6 +++--- .../Sorting/IsPlayedComparer.cs | 2 ++ .../Sorting/IsUnplayedComparer.cs | 2 ++ Emby.Server.Implementations/Sorting/NameComparer.cs | 2 +- .../Sorting/OfficialRatingComparer.cs | 2 +- .../Sorting/PlayCountComparer.cs | 2 ++ .../Sorting/PremiereDateComparer.cs | 9 +++++++-- .../Sorting/ProductionYearComparer.cs | 9 +++++++-- .../Sorting/RandomComparer.cs | 2 +- .../Sorting/RuntimeComparer.cs | 2 ++ .../Sorting/SeriesSortNameComparer.cs | 2 ++ .../Sorting/SortNameComparer.cs | 2 ++ .../Sorting/StartDateComparer.cs | 2 ++ .../Sorting/StudioComparer.cs | 2 ++ Emby.Server.Implementations/SyncPlay/Group.cs | 2 ++ .../SyncPlay/SyncPlayManager.cs | 2 ++ Emby.Server.Implementations/TV/TVSeriesManager.cs | 2 ++ Emby.Server.Implementations/Udp/UdpServer.cs | 2 ++ .../Updates/InstallationManager.cs | 2 ++ Jellyfin.Api/Controllers/DynamicHlsController.cs | 4 ++-- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 4 +++- .../Models/PlaybackDtos/TranscodingThrottler.cs | 3 ++- Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs | 11 +++++++---- .../Extensions/StringExtensions.cs | 1 + MediaBrowser.Controller/Net/ISessionContext.cs | 4 ++-- MediaBrowser.Controller/Sorting/IBaseItemComparer.cs | 2 +- MediaBrowser.Model/IO/IFileSystem.cs | 7 +++---- MediaBrowser.Model/IO/IShortcutHandler.cs | 2 +- MediaBrowser.Model/IO/IStreamHelper.cs | 2 +- MediaBrowser.Model/Tasks/ITaskTrigger.cs | 2 +- 151 files changed, 300 insertions(+), 99 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index 660bbb2de..6edfad575 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.AppBase CachePath = cacheDirectoryPath; WebPath = webDirectoryPath; - DataPath = Path.Combine(ProgramDataPath, "data"); + _dataPath = Directory.CreateDirectory(Path.Combine(ProgramDataPath, "data")).FullName; } /// @@ -55,11 +55,7 @@ namespace Emby.Server.Implementations.AppBase /// Gets the folder path to the data directory. /// /// The data directory. - public string DataPath - { - get => _dataPath; - private set => _dataPath = Directory.CreateDirectory(value).FullName; - } + public string DataPath => _dataPath; /// public string VirtualDataPath => "%AppDataPath%"; diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 4f72c8ce1..8c919db43 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 29bac6634..de770f59e 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.IO; using System.Linq; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 75d8fc113..82995deb3 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 7324b0ee9..448f12403 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Globalization; diff --git a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs index c69a07e83..ca8409402 100644 --- a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs @@ -82,9 +82,9 @@ namespace Emby.Server.Implementations.Collections return null; }) .Where(i => i != null) - .GroupBy(x => x.Id) + .GroupBy(x => x!.Id) // We removed the null values .Select(x => x.First()) - .ToList(); + .ToList()!; // Again... the list doesn't contain any null values } /// diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index c56f33448..82d80fc83 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index 7a8ed8c29..ff5602f24 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Globalization; using System.IO; diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index 12a9e44e7..4a9b28085 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Security.Cryptography; diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index c331a6112..6f23a0888 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Data/ManagedConnection.cs b/Emby.Server.Implementations/Data/ManagedConnection.cs index 5c094ddd2..10c6f837e 100644 --- a/Emby.Server.Implementations/Data/ManagedConnection.cs +++ b/Emby.Server.Implementations/Data/ManagedConnection.cs @@ -9,7 +9,7 @@ namespace Emby.Server.Implementations.Data { public class ManagedConnection : IDisposable { - private SQLiteDatabaseConnection _db; + private SQLiteDatabaseConnection? _db; private readonly SemaphoreSlim _writeLock; private bool _disposed = false; diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs index a8f3feb58..e532825af 100644 --- a/Emby.Server.Implementations/Data/SqliteExtensions.cs +++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index b3d8860a9..5b4bbb339 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index e0ebd0a6c..1756bcae0 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Data/TypeMapper.cs b/Emby.Server.Implementations/Data/TypeMapper.cs index 7044b1d19..7f1306d15 100644 --- a/Emby.Server.Implementations/Data/TypeMapper.cs +++ b/Emby.Server.Implementations/Data/TypeMapper.cs @@ -13,7 +13,7 @@ namespace Emby.Server.Implementations.Data /// This holds all the types in the running assemblies /// so that we can de-serialize properly when we don't have strong types. /// - private readonly ConcurrentDictionary _typeMap = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _typeMap = new ConcurrentDictionary(); /// /// Gets the type. @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.Data /// Name of the type. /// Type. /// typeName is null. - public Type GetType(string typeName) + public Type? GetType(string typeName) { if (string.IsNullOrEmpty(typeName)) { @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Data /// /// Name of the type. /// Type. - private Type LookupType(string typeName) + private Type? LookupType(string typeName) { return AppDomain.CurrentDomain.GetAssemblies() .Select(a => a.GetType(typeName)) diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index fa6ac95fd..3d15b3e76 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index da5047d24..2637addce 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 4ae35039a..7411239a1 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 14f6f565c..113863519 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -44,6 +44,7 @@ false true true + enable AD0001 AllEnabledByDefault diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 14201ead2..cc3e4a2c2 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index ae1b51b4c..5bb4100ba 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index 824bb85f4..e0ca02d98 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 3624e079f..211941f44 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Net.Sockets; using System.Threading; diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 1989e9ed2..332fb3385 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index fbf9254d1..c87f7dbbd 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached)) { - return (AuthorizationInfo)cached; + return (AuthorizationInfo)cached!; // Cache should never contain null } return GetAuthorization(requestContext); @@ -55,15 +55,15 @@ namespace Emby.Server.Implementations.HttpServer.Security } private AuthorizationInfo GetAuthorizationInfoFromDictionary( - in Dictionary auth, + in Dictionary? auth, in IHeaderDictionary headers, in IQueryCollection queryString) { - string deviceId = null; - string device = null; - string client = null; - string version = null; - string token = null; + string? deviceId = null; + string? device = null; + string? client = null; + string? version = null; + string? token = null; if (auth != null) { @@ -206,7 +206,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The HTTP req. /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorizationDictionary(HttpContext httpReq) + private Dictionary? GetAuthorizationDictionary(HttpContext httpReq) { var auth = httpReq.Request.Headers["X-Emby-Authorization"]; @@ -223,7 +223,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The HTTP req. /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorizationDictionary(HttpRequest httpReq) + private Dictionary? GetAuthorizationDictionary(HttpRequest httpReq) { var auth = httpReq.Headers["X-Emby-Authorization"]; @@ -240,7 +240,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The authorization header. /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorization(ReadOnlySpan authorizationHeader) + private Dictionary? GetAuthorization(ReadOnlySpan authorizationHeader) { if (authorizationHeader == null) { diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs index dd77b45d8..c375f36ce 100644 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs @@ -36,14 +36,14 @@ namespace Emby.Server.Implementations.HttpServer.Security return GetSession((HttpContext)requestContext); } - public User GetUser(HttpContext requestContext) + public User? GetUser(HttpContext requestContext) { var session = GetSession(requestContext); return session == null || session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId); } - public User GetUser(object requestContext) + public User? GetUser(object requestContext) { return GetUser(((HttpRequest)requestContext).HttpContext); } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 06acb5606..8f7d60669 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Buffers; using System.IO.Pipelines; diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index 1bee1ac31..861c0a95e 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 7435e9d0b..47a83d77c 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 3353fae9d..aa80bccd7 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 27096ed33..6a554e68a 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.IO /// The filename. /// System.String. /// filename - public virtual string ResolveShortcut(string filename) + public virtual string? ResolveShortcut(string filename) { if (string.IsNullOrEmpty(filename)) { @@ -601,7 +601,7 @@ namespace Emby.Server.Implementations.IO return GetFiles(path, null, false, recursive); } - public virtual IEnumerable GetFiles(string path, IReadOnlyList extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public virtual IEnumerable GetFiles(string path, IReadOnlyList? extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var enumerationOptions = GetEnumerationOptions(recursive); @@ -655,7 +655,7 @@ namespace Emby.Server.Implementations.IO return GetFilePaths(path, null, false, recursive); } - public virtual IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public virtual IEnumerable GetFilePaths(string path, string[]? extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var enumerationOptions = GetEnumerationOptions(recursive); diff --git a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs index e6696b8c4..76c58d5dc 100644 --- a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs +++ b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.IO public string Extension => ".mblink"; - public string Resolve(string shortcutPath) + public string? Resolve(string shortcutPath) { if (string.IsNullOrEmpty(shortcutPath)) { diff --git a/Emby.Server.Implementations/IO/StreamHelper.cs b/Emby.Server.Implementations/IO/StreamHelper.cs index c16ebd61b..e4f5f4cf0 100644 --- a/Emby.Server.Implementations/IO/StreamHelper.cs +++ b/Emby.Server.Implementations/IO/StreamHelper.cs @@ -11,7 +11,7 @@ namespace Emby.Server.Implementations.IO { public class StreamHelper : IStreamHelper { - public async Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken) + public async Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action? onStarted, CancellationToken cancellationToken) { byte[] buffer = ArrayPool.Shared.Rent(bufferSize); try diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index f719dc5f8..a430b9e72 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -1,5 +1,4 @@ #pragma warning disable CS1591 -#nullable enable namespace Emby.Server.Implementations { diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index 6fa3c1c61..833fb0b7a 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index 161b4c452..ff5f26ce0 100644 --- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index 50c531482..900b3fd9c 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Images/FolderImageProvider.cs b/Emby.Server.Implementations/Images/FolderImageProvider.cs index 0224ab32a..859017f86 100644 --- a/Emby.Server.Implementations/Images/FolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/FolderImageProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System.Collections.Generic; diff --git a/Emby.Server.Implementations/Images/GenreImageProvider.cs b/Emby.Server.Implementations/Images/GenreImageProvider.cs index 381788231..6da431c68 100644 --- a/Emby.Server.Implementations/Images/GenreImageProvider.cs +++ b/Emby.Server.Implementations/Images/GenreImageProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System.Collections.Generic; diff --git a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs index a4c106e87..b8f0f0d65 100644 --- a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System.Collections.Generic; diff --git a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs index 236453e80..6c65b5899 100644 --- a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs +++ b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/IgnorePatterns.cs b/Emby.Server.Implementations/Library/IgnorePatterns.cs index e30a67593..5384c04b3 100644 --- a/Emby.Server.Implementations/Library/IgnorePatterns.cs +++ b/Emby.Server.Implementations/Library/IgnorePatterns.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Linq; using DotNet.Globbing; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 4d207471a..f8d8197d4 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index c2951dd15..4ef7923db 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 85d6d3043..38e81d14c 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/MediaStreamSelector.cs b/Emby.Server.Implementations/Library/MediaStreamSelector.cs index 28fa06239..b833122ea 100644 --- a/Emby.Server.Implementations/Library/MediaStreamSelector.cs +++ b/Emby.Server.Implementations/Library/MediaStreamSelector.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs index f8bae4fd1..06300adeb 100644 --- a/Emby.Server.Implementations/Library/MusicManager.cs +++ b/Emby.Server.Implementations/Library/MusicManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 0de4edb7e..86b8039fa 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Diagnostics.CodeAnalysis; using MediaBrowser.Common.Providers; diff --git a/Emby.Server.Implementations/Library/ResolverHelper.cs b/Emby.Server.Implementations/Library/ResolverHelper.cs index 1d9b44874..ac75e5d3a 100644 --- a/Emby.Server.Implementations/Library/ResolverHelper.cs +++ b/Emby.Server.Implementations/Library/ResolverHelper.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.IO; using System.Linq; diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index 4ad84579d..e893d6335 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index bf32381eb..8e1eccb10 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index 60f82806f..3d2ae95d2 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Linq; using System.Threading.Tasks; diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 16050185f..a3dcdc944 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 0525c7e30..68076730b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs index 7dbce7a6e..7aaee017d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs index 92fb2a753..fa45ccf84 100644 --- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index 295e9e120..69d71d0d9 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.IO; using MediaBrowser.Controller.Entities; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 16bf4dc4a..02c528764 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index 204c8a62e..534bc80dd 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 3cb6542cf..57bf40e9e 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index 5f051321f..ecd44be47 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 99f304190..7b4e14334 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 6f29bc649..d6ae91056 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Linq; using MediaBrowser.Controller.Entities; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 768e2e4f5..7d707df18 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System.Globalization; using Emby.Naming.TV; using MediaBrowser.Controller.Entities.TV; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 8fc3e3e75..a1562abd3 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs index 62268fce9..9599faea4 100644 --- a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using MediaBrowser.Controller.Entities; diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index bcdf854ca..26e615fa0 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 827e3c64b..667e46613 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index ac041bcf6..e2da672a3 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 7a6b1d8b6..3fcadf5b1 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 28a2095e1..797063120 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 9372b0f6c..26e4ef1ed 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs index 8c27ca76e..0ec52a959 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.LiveTv; namespace Emby.Server.Implementations.LiveTv.EmbyTV { - internal class EpgChannelData { @@ -39,13 +38,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - public ChannelInfo GetChannelById(string id) + public ChannelInfo? GetChannelById(string id) => _channelsById.GetValueOrDefault(id); - public ChannelInfo GetChannelByNumber(string number) + public ChannelInfo? GetChannelByNumber(string number) => _channelsByNumber.GetValueOrDefault(number); - public ChannelInfo GetChannelByName(string name) + public ChannelInfo? GetChannelByName(string name) => _channelsByName.GetValueOrDefault(name); public static string NormalizeName(string value) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 1cac9cb96..bdab8c3e4 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 32245f899..108863869 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 1efa90e25..6c52a9a73 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 9af65cabb..00d02873c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 6824aa442..ebad4eddf 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 6af49dd45..21e1409ac 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1145d8aa1..1f1628900 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 3a738fd5d..ecd28097d 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index fbcd4ef37..00a37bb02 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/Channels.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/Channels.cs index 740cbb66e..0f0453189 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/Channels.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/Channels.cs @@ -1,3 +1,5 @@ +#nullable disable + namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { internal class Channels diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs index 09d77f838..42068cd34 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/DiscoverResponse.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index bbac6e055..c5700db71 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index a7fda1d72..3016eeda2 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index b16ccc561..50a2d9abb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index f8baf55da..96a678c1d 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 4b170b2e4..69035dac9 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 84d416149..48a0c3cd3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index eeb2426f4..137ed27e2 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 220e423bf..dd5dee1d1 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 031b5d2e7..8aaa1f7bb 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 0781a0e33..137728616 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 4e25768cf..a8b18d292 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 2d1a559f1..9a1ca9946 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 14df20936..48281b75f 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Globalization; diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index 0259dc436..7cfd1fced 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Concurrent; using System.Globalization; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 101d9b537..ccbd4289e 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index af316e108..4f0df75bf 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 2312c85d9..baeb86a22 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -140,8 +140,10 @@ namespace Emby.Server.Implementations.ScheduledTasks previouslyFailedImages.Add(key); var parentPath = Path.GetDirectoryName(failHistoryPath); - - Directory.CreateDirectory(parentPath); + if (parentPath != null) + { + Directory.CreateDirectory(parentPath); + } string text = string.Join('|', previouslyFailedImages); File.WriteAllText(failHistoryPath, text); diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs index 4abbf784b..50ba9bc89 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -75,4 +75,4 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks return Enumerable.Empty(); } } -} \ No newline at end of file +} diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index 3b40320ab..3b63536a4 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Threading; using MediaBrowser.Model.Tasks; diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs index b04fd7c7e..e13782fe0 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Linq; using System.Threading; diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs index 7cd5493da..ced14195b 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs index 0c0ebec08..a67f940b7 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Threading; using MediaBrowser.Model.Tasks; diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs index 76f863c95..30823ab8f 100644 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs b/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs index 27024e4e1..8d8b82f0a 100644 --- a/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs +++ b/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs @@ -19,7 +19,9 @@ namespace Emby.Server.Implementations.Serialization new ConcurrentDictionary(); private static XmlSerializer GetSerializer(Type type) - => _serializers.GetOrAdd(type.FullName, _ => new XmlSerializer(type)); + => _serializers.GetOrAdd( + type.FullName ?? throw new ArgumentException($"Invalid type {type}."), + _ => new XmlSerializer(type)); /// /// Serializes to writer. @@ -38,7 +40,7 @@ namespace Emby.Server.Implementations.Serialization /// The type. /// The stream. /// System.Object. - public object DeserializeFromStream(Type type, Stream stream) + public object? DeserializeFromStream(Type type, Stream stream) { using (var reader = XmlReader.Create(stream)) { @@ -81,7 +83,7 @@ namespace Emby.Server.Implementations.Serialization /// The type. /// The file. /// System.Object. - public object DeserializeFromFile(Type type, string file) + public object? DeserializeFromFile(Type type, string file) { using (var stream = File.OpenRead(file)) { @@ -95,7 +97,7 @@ namespace Emby.Server.Implementations.Serialization /// The type. /// The buffer. /// System.Object. - public object DeserializeFromBytes(Type type, byte[] buffer) + public object? DeserializeFromBytes(Type type, byte[] buffer) { using (var stream = new MemoryStream(buffer, 0, buffer.Length, false, true)) { diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 6844152ea..ef467da7e 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 39c369a01..e9e3ca7f4 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index a653b58c2..ed1dfca59 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 #pragma warning disable SA1600 -#nullable enable using System; using System.Collections.Generic; diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 60698e803..2b0ab536f 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { if (x == null) { diff --git a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs index 7657cc74e..42e644970 100644 --- a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); } @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Sorting /// /// The x. /// System.String. - private static string GetValue(BaseItem x) + private static string? GetValue(BaseItem? x) { var audio = x as IHasAlbumArtist; diff --git a/Emby.Server.Implementations/Sorting/AlbumComparer.cs b/Emby.Server.Implementations/Sorting/AlbumComparer.cs index 7dfdd9ecf..1db3f5e9c 100644 --- a/Emby.Server.Implementations/Sorting/AlbumComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumComparer.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); } @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Sorting /// /// The x. /// System.String. - private static string GetValue(BaseItem x) + private static string? GetValue(BaseItem? x) { var audio = x as Audio; diff --git a/Emby.Server.Implementations/Sorting/ArtistComparer.cs b/Emby.Server.Implementations/Sorting/ArtistComparer.cs index 756d3c5b6..98bee3fd9 100644 --- a/Emby.Server.Implementations/Sorting/ArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/ArtistComparer.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting public string Name => ItemSortBy.Artist; /// - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); } @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Sorting /// /// The x. /// System.String. - private static string GetValue(BaseItem x) + private static string? GetValue(BaseItem? x) { if (!(x is Audio audio)) { diff --git a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs index 980954ba0..5f142fa4b 100644 --- a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { if (x == null) { diff --git a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs index fa136c36d..d20dedc2d 100644 --- a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs @@ -15,14 +15,14 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return GetValue(x).CompareTo(GetValue(y)); } - private static float GetValue(BaseItem x) + private static float GetValue(BaseItem? x) { - return x.CriticRating ?? 0; + return x?.CriticRating ?? 0; } /// diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index cbca300d2..d3f10f78c 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { if (x == null) { diff --git a/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs b/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs index 03ff19d21..b1cb123ce 100644 --- a/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs index 16bd2aff8..08a44319f 100644 --- a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Entities; diff --git a/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs b/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs index 0c4e82d01..73e628cf7 100644 --- a/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using Jellyfin.Data.Entities; diff --git a/Emby.Server.Implementations/Sorting/IsFolderComparer.cs b/Emby.Server.Implementations/Sorting/IsFolderComparer.cs index a35192eff..3c5ddeefa 100644 --- a/Emby.Server.Implementations/Sorting/IsFolderComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsFolderComparer.cs @@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return GetValue(x).CompareTo(GetValue(y)); } @@ -30,9 +30,9 @@ namespace Emby.Server.Implementations.Sorting /// /// The x. /// System.String. - private static int GetValue(BaseItem x) + private static int GetValue(BaseItem? x) { - return x.IsFolder ? 0 : 1; + return x?.IsFolder ?? true ? 0 : 1; } } } diff --git a/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs b/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs index d95948406..7d77a8bc5 100644 --- a/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using Jellyfin.Data.Entities; diff --git a/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs b/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs index 1632c5a7a..926835f90 100644 --- a/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using Jellyfin.Data.Entities; diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index da020d8d8..4de81a69e 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { if (x == null) { diff --git a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs index 76bb798b5..a81f78ebf 100644 --- a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { if (x == null) { diff --git a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs index 5c2830322..04e4865cb 100644 --- a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + using Jellyfin.Data.Entities; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; diff --git a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs index 92ac04dc6..c98f97bf1 100644 --- a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return GetDate(x).CompareTo(GetDate(y)); } @@ -26,8 +26,13 @@ namespace Emby.Server.Implementations.Sorting /// /// The x. /// DateTime. - private static DateTime GetDate(BaseItem x) + private static DateTime GetDate(BaseItem? x) { + if (x == null) + { + return DateTime.MinValue; + } + if (x.PremiereDate.HasValue) { return x.PremiereDate.Value; diff --git a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs index e2857df0b..df9f9957d 100644 --- a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs +++ b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return GetValue(x).CompareTo(GetValue(y)); } @@ -25,8 +25,13 @@ namespace Emby.Server.Implementations.Sorting /// /// The x. /// DateTime. - private static int GetValue(BaseItem x) + private static int GetValue(BaseItem? x) { + if (x == null) + { + return 0; + } + if (x.ProductionYear.HasValue) { return x.ProductionYear.Value; diff --git a/Emby.Server.Implementations/Sorting/RandomComparer.cs b/Emby.Server.Implementations/Sorting/RandomComparer.cs index 7739d0418..af3bc2750 100644 --- a/Emby.Server.Implementations/Sorting/RandomComparer.cs +++ b/Emby.Server.Implementations/Sorting/RandomComparer.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting /// The x. /// The y. /// System.Int32. - public int Compare(BaseItem x, BaseItem y) + public int Compare(BaseItem? x, BaseItem? y) { return Guid.NewGuid().CompareTo(Guid.NewGuid()); } diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index dde44333d..129315303 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; diff --git a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs index b9205ee07..4123a59f8 100644 --- a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index f745e193b..8d30716d3 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; diff --git a/Emby.Server.Implementations/Sorting/StartDateComparer.cs b/Emby.Server.Implementations/Sorting/StartDateComparer.cs index 558a3d351..c3df7c47e 100644 --- a/Emby.Server.Implementations/Sorting/StartDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/StartDateComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 5766dc542..01445c525 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/SyncPlay/Group.cs b/Emby.Server.Implementations/SyncPlay/Group.cs index 7c2ad2477..12efff261 100644 --- a/Emby.Server.Implementations/SyncPlay/Group.cs +++ b/Emby.Server.Implementations/SyncPlay/Group.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs index 72c0a838e..993456196 100644 --- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs +++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 829df64bf..a837f09ca 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index db5265e79..750f00168 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Net; using System.Net.Sockets; diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 653b1381b..2351b7d8c 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -1,3 +1,5 @@ +#nullable disable + #nullable enable using System; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index b4154b361..45559fce9 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1762,9 +1762,9 @@ namespace Jellyfin.Api.Controllers private static FileSystemMetadata? GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem) { - var folder = Path.GetDirectoryName(playlist); + var folder = Path.GetDirectoryName(playlist) ?? throw new ArgumentException("Path can't be a root directory.", nameof(playlist)); - var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty; + var filePrefix = Path.GetFileNameWithoutExtension(playlist); try { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 0879cbd18..7cb015993 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -380,7 +380,9 @@ namespace Jellyfin.Api.Helpers /// The output file path. private void DeleteHlsPartialStreamFiles(string outputFilePath) { - var directory = Path.GetDirectoryName(outputFilePath); + var directory = Path.GetDirectoryName(outputFilePath) + ?? throw new ArgumentException("Path can't be a root directory.", nameof(outputFilePath)); + var name = Path.GetFileNameWithoutExtension(outputFilePath); var filesToDelete = _fileSystem.GetFilePaths(directory) diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index e33e552ed..7b32d76ba 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -145,7 +145,8 @@ namespace Jellyfin.Api.Models.PlaybackDtos var transcodingPositionTicks = job.TranscodingPositionTicks ?? 0; var downloadPositionTicks = job.DownloadPositionTicks ?? 0; - var path = job.Path; + var path = job.Path ?? throw new ArgumentException("Path can't be null."); + var gapLengthInTicks = TimeSpan.FromSeconds(thresholdSeconds).Ticks; if (downloadPositionTicks > 0 && transcodingPositionTicks > 0) diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index a15a38177..96bd2ccc4 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -82,11 +82,14 @@ namespace Jellyfin.Server.Migrations.Routines var userDataDir = Path.Combine(_paths.UserConfigurationDirectoryPath, mockup.Name); - var config = File.Exists(Path.Combine(userDataDir, "config.xml")) - ? (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), Path.Combine(userDataDir, "config.xml")) + var configPath = Path.Combine(userDataDir, "config.xml"); + var config = File.Exists(configPath) + ? (UserConfiguration?)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), configPath) ?? new UserConfiguration() : new UserConfiguration(); - var policy = File.Exists(Path.Combine(userDataDir, "policy.xml")) - ? (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), Path.Combine(userDataDir, "policy.xml")) + + var policyPath = Path.Combine(userDataDir, "policy.xml"); + var policy = File.Exists(policyPath) + ? (UserPolicy?)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), policyPath) ?? new UserPolicy() : new UserPolicy(); policy.AuthenticationProviderId = policy.AuthenticationProviderId?.Replace( "Emby.Server.Implementations.Library", diff --git a/MediaBrowser.Controller/Extensions/StringExtensions.cs b/MediaBrowser.Controller/Extensions/StringExtensions.cs index 48bd9522a..1853896ee 100644 --- a/MediaBrowser.Controller/Extensions/StringExtensions.cs +++ b/MediaBrowser.Controller/Extensions/StringExtensions.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; diff --git a/MediaBrowser.Controller/Net/ISessionContext.cs b/MediaBrowser.Controller/Net/ISessionContext.cs index a60dc2ea1..6b896b41f 100644 --- a/MediaBrowser.Controller/Net/ISessionContext.cs +++ b/MediaBrowser.Controller/Net/ISessionContext.cs @@ -10,10 +10,10 @@ namespace MediaBrowser.Controller.Net { SessionInfo GetSession(object requestContext); - User GetUser(object requestContext); + User? GetUser(object requestContext); SessionInfo GetSession(HttpContext requestContext); - User GetUser(HttpContext requestContext); + User? GetUser(HttpContext requestContext); } } diff --git a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs index 727cbe639..07fe1ea8a 100644 --- a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs +++ b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Controller.Sorting /// /// Interface IBaseItemComparer. /// - public interface IBaseItemComparer : IComparer + public interface IBaseItemComparer : IComparer { /// /// Gets the name. diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index e5c26430a..be4f1e16b 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -25,7 +24,7 @@ namespace MediaBrowser.Model.IO /// /// The filename. /// System.String. - string ResolveShortcut(string filename); + string? ResolveShortcut(string filename); /// /// Creates the shortcut. @@ -160,7 +159,7 @@ namespace MediaBrowser.Model.IO /// All found files. IEnumerable GetFiles(string path, bool recursive = false); - IEnumerable GetFiles(string path, IReadOnlyList extensions, bool enableCaseSensitiveExtensions, bool recursive); + IEnumerable GetFiles(string path, IReadOnlyList? extensions, bool enableCaseSensitiveExtensions, bool recursive); /// /// Gets the file system entries. @@ -186,7 +185,7 @@ namespace MediaBrowser.Model.IO /// IEnumerable<System.String>. IEnumerable GetFilePaths(string path, bool recursive = false); - IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive); + IEnumerable GetFilePaths(string path, string[]? extensions, bool enableCaseSensitiveExtensions, bool recursive); /// /// Gets the file system entry paths. diff --git a/MediaBrowser.Model/IO/IShortcutHandler.cs b/MediaBrowser.Model/IO/IShortcutHandler.cs index 14d5c4b62..2c364a962 100644 --- a/MediaBrowser.Model/IO/IShortcutHandler.cs +++ b/MediaBrowser.Model/IO/IShortcutHandler.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Model.IO /// /// The shortcut path. /// System.String. - string Resolve(string shortcutPath); + string? Resolve(string shortcutPath); /// /// Creates the specified shortcut path. diff --git a/MediaBrowser.Model/IO/IStreamHelper.cs b/MediaBrowser.Model/IO/IStreamHelper.cs index 0e09db16e..f900da556 100644 --- a/MediaBrowser.Model/IO/IStreamHelper.cs +++ b/MediaBrowser.Model/IO/IStreamHelper.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.IO { public interface IStreamHelper { - Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken); + Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action? onStarted, CancellationToken cancellationToken); Task CopyToAsync(Stream source, Stream destination, int bufferSize, int emptyReadLimit, CancellationToken cancellationToken); diff --git a/MediaBrowser.Model/Tasks/ITaskTrigger.cs b/MediaBrowser.Model/Tasks/ITaskTrigger.cs index cbd60cca1..db9fba696 100644 --- a/MediaBrowser.Model/Tasks/ITaskTrigger.cs +++ b/MediaBrowser.Model/Tasks/ITaskTrigger.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Tasks /// /// Fires when the trigger condition is satisfied and the task should run. /// - event EventHandler Triggered; + event EventHandler? Triggered; /// /// Gets or sets the options of this task. -- cgit v1.2.3 From a0c6f7276211ac0429877fafa400368aba1430a9 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 20 May 2021 23:56:59 -0400 Subject: Migrate authentication db to EF Core --- Emby.Server.Implementations/ApplicationHost.cs | 10 +- .../HttpServer/Security/AuthService.cs | 5 +- .../HttpServer/Security/AuthorizationContext.cs | 291 ---------- .../HttpServer/Security/SessionContext.cs | 12 +- .../HttpServer/WebSocketManager.cs | 2 +- .../Security/AuthenticationRepository.cs | 407 ------------- .../Session/SessionManager.cs | 80 +-- Jellyfin.Api/Auth/CustomAuthenticationHandler.cs | 10 +- Jellyfin.Api/Controllers/CollectionController.cs | 2 +- Jellyfin.Api/Controllers/DevicesController.cs | 18 +- Jellyfin.Api/Controllers/ImageController.cs | 8 +- Jellyfin.Api/Controllers/LibraryController.cs | 10 +- Jellyfin.Api/Controllers/MediaInfoController.cs | 2 +- Jellyfin.Api/Controllers/PlaystateController.cs | 6 +- Jellyfin.Api/Controllers/SessionController.cs | 6 +- Jellyfin.Api/Controllers/SubtitleController.cs | 2 +- .../Controllers/UniversalAudioController.cs | 4 +- Jellyfin.Api/Controllers/UserController.cs | 42 +- Jellyfin.Api/Controllers/UserViewsController.cs | 5 +- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 2 +- Jellyfin.Api/Helpers/RequestHelpers.cs | 6 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../Devices/DeviceManager.cs | 73 +++ Jellyfin.Server.Implementations/JellyfinDb.cs | 9 + .../20210521032224_AddDevices.Designer.cs | 645 +++++++++++++++++++++ .../Migrations/20210521032224_AddDevices.cs | 126 ++++ .../Migrations/JellyfinDbModelSnapshot.cs | 114 +++- .../Security/AuthorizationContext.cs | 283 +++++++++ .../Users/DeviceAccessEntryPoint.cs | 22 +- Jellyfin.Server/CoreAppHost.cs | 3 + MediaBrowser.Controller/Devices/IDeviceManager.cs | 19 + MediaBrowser.Controller/Net/IAuthService.cs | 3 +- .../Net/IAuthorizationContext.cs | 9 +- .../Security/AuthenticationInfoQuery.cs | 53 -- .../Security/IAuthenticationRepository.cs | 39 -- MediaBrowser.Controller/Session/ISessionManager.cs | 19 +- MediaBrowser.Model/Devices/DeviceInfo.cs | 5 + .../Auth/CustomAuthenticationHandlerTests.cs | 2 +- 39 files changed, 1408 insertions(+), 952 deletions(-) delete mode 100644 Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs delete mode 100644 Emby.Server.Implementations/Security/AuthenticationRepository.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.Designer.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.cs create mode 100644 Jellyfin.Server.Implementations/Security/AuthorizationContext.cs delete mode 100644 MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs delete mode 100644 MediaBrowser.Controller/Security/IAuthenticationRepository.cs (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 213890c67..a69c4d035 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -36,7 +36,6 @@ using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.Plugins; using Emby.Server.Implementations.QuickConnect; using Emby.Server.Implementations.ScheduledTasks; -using Emby.Server.Implementations.Security; using Emby.Server.Implementations.Serialization; using Emby.Server.Implementations.Session; using Emby.Server.Implementations.SyncPlay; @@ -57,7 +56,6 @@ using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -73,7 +71,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.QuickConnect; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Subtitles; @@ -599,8 +596,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); @@ -657,8 +652,7 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + ServiceCollection.AddScoped(); ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); @@ -687,8 +681,6 @@ namespace Emby.Server.Implementations _mediaEncoder = Resolve(); _sessionManager = Resolve(); - ((AuthenticationRepository)Resolve()).Initialize(); - SetStaticProperties(); var userDataRepo = (SqliteUserDataRepository)Resolve(); diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 9afabf527..e2ad07177 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System.Threading.Tasks; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Net; @@ -17,9 +18,9 @@ namespace Emby.Server.Implementations.HttpServer.Security _authorizationContext = authorizationContext; } - public AuthorizationInfo Authenticate(HttpRequest request) + public async Task Authenticate(HttpRequest request) { - var auth = _authorizationContext.GetAuthorizationInfo(request); + var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false); if (!auth.HasToken) { diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs deleted file mode 100644 index 024404ceb..000000000 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ /dev/null @@ -1,291 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Security; -using Microsoft.AspNetCore.Http; -using Microsoft.Net.Http.Headers; - -namespace Emby.Server.Implementations.HttpServer.Security -{ - public class AuthorizationContext : IAuthorizationContext - { - private readonly IAuthenticationRepository _authRepo; - private readonly IUserManager _userManager; - - public AuthorizationContext(IAuthenticationRepository authRepo, IUserManager userManager) - { - _authRepo = authRepo; - _userManager = userManager; - } - - public AuthorizationInfo GetAuthorizationInfo(HttpContext requestContext) - { - if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached)) - { - return (AuthorizationInfo)cached; - } - - return GetAuthorization(requestContext); - } - - public AuthorizationInfo GetAuthorizationInfo(HttpRequest requestContext) - { - var auth = GetAuthorizationDictionary(requestContext); - var authInfo = GetAuthorizationInfoFromDictionary(auth, requestContext.Headers, requestContext.Query); - return authInfo; - } - - /// - /// Gets the authorization. - /// - /// The HTTP req. - /// Dictionary{System.StringSystem.String}. - private AuthorizationInfo GetAuthorization(HttpContext httpReq) - { - var auth = GetAuthorizationDictionary(httpReq); - var authInfo = GetAuthorizationInfoFromDictionary(auth, httpReq.Request.Headers, httpReq.Request.Query); - - httpReq.Request.HttpContext.Items["AuthorizationInfo"] = authInfo; - return authInfo; - } - - private AuthorizationInfo GetAuthorizationInfoFromDictionary( - in Dictionary auth, - in IHeaderDictionary headers, - in IQueryCollection queryString) - { - string deviceId = null; - string device = null; - string client = null; - string version = null; - string token = null; - - if (auth != null) - { - auth.TryGetValue("DeviceId", out deviceId); - auth.TryGetValue("Device", out device); - auth.TryGetValue("Client", out client); - auth.TryGetValue("Version", out version); - auth.TryGetValue("Token", out token); - } - - if (string.IsNullOrEmpty(token)) - { - token = headers["X-Emby-Token"]; - } - - if (string.IsNullOrEmpty(token)) - { - token = headers["X-MediaBrowser-Token"]; - } - - if (string.IsNullOrEmpty(token)) - { - token = queryString["ApiKey"]; - } - - // TODO deprecate this query parameter. - if (string.IsNullOrEmpty(token)) - { - token = queryString["api_key"]; - } - - var authInfo = new AuthorizationInfo - { - Client = client, - Device = device, - DeviceId = deviceId, - Version = version, - Token = token, - IsAuthenticated = false, - HasToken = false - }; - - if (string.IsNullOrWhiteSpace(token)) - { - // Request doesn't contain a token. - return authInfo; - } - - authInfo.HasToken = true; - var result = _authRepo.Get(new AuthenticationInfoQuery - { - AccessToken = token - }); - - if (result.Items.Count > 0) - { - authInfo.IsAuthenticated = true; - } - - var originalAuthenticationInfo = result.Items.Count > 0 ? result.Items[0] : null; - - if (originalAuthenticationInfo != null) - { - var updateToken = false; - - // TODO: Remove these checks for IsNullOrWhiteSpace - if (string.IsNullOrWhiteSpace(authInfo.Client)) - { - authInfo.Client = originalAuthenticationInfo.AppName; - } - - if (string.IsNullOrWhiteSpace(authInfo.DeviceId)) - { - authInfo.DeviceId = originalAuthenticationInfo.DeviceId; - } - - // Temporary. TODO - allow clients to specify that the token has been shared with a casting device - var allowTokenInfoUpdate = authInfo.Client == null || authInfo.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1; - - if (string.IsNullOrWhiteSpace(authInfo.Device)) - { - authInfo.Device = originalAuthenticationInfo.DeviceName; - } - else if (!string.Equals(authInfo.Device, originalAuthenticationInfo.DeviceName, StringComparison.OrdinalIgnoreCase)) - { - if (allowTokenInfoUpdate) - { - updateToken = true; - originalAuthenticationInfo.DeviceName = authInfo.Device; - } - } - - if (string.IsNullOrWhiteSpace(authInfo.Version)) - { - authInfo.Version = originalAuthenticationInfo.AppVersion; - } - else if (!string.Equals(authInfo.Version, originalAuthenticationInfo.AppVersion, StringComparison.OrdinalIgnoreCase)) - { - if (allowTokenInfoUpdate) - { - updateToken = true; - originalAuthenticationInfo.AppVersion = authInfo.Version; - } - } - - if ((DateTime.UtcNow - originalAuthenticationInfo.DateLastActivity).TotalMinutes > 3) - { - originalAuthenticationInfo.DateLastActivity = DateTime.UtcNow; - updateToken = true; - } - - if (!originalAuthenticationInfo.UserId.Equals(Guid.Empty)) - { - authInfo.User = _userManager.GetUserById(originalAuthenticationInfo.UserId); - - if (authInfo.User != null && !string.Equals(authInfo.User.Username, originalAuthenticationInfo.UserName, StringComparison.OrdinalIgnoreCase)) - { - originalAuthenticationInfo.UserName = authInfo.User.Username; - updateToken = true; - } - - authInfo.IsApiKey = false; - } - else - { - authInfo.IsApiKey = true; - } - - if (updateToken) - { - _authRepo.Update(originalAuthenticationInfo); - } - } - - return authInfo; - } - - /// - /// Gets the auth. - /// - /// The HTTP req. - /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorizationDictionary(HttpContext httpReq) - { - var auth = httpReq.Request.Headers["X-Emby-Authorization"]; - - if (string.IsNullOrEmpty(auth)) - { - auth = httpReq.Request.Headers[HeaderNames.Authorization]; - } - - return GetAuthorization(auth); - } - - /// - /// Gets the auth. - /// - /// The HTTP req. - /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorizationDictionary(HttpRequest httpReq) - { - var auth = httpReq.Headers["X-Emby-Authorization"]; - - if (string.IsNullOrEmpty(auth)) - { - auth = httpReq.Headers[HeaderNames.Authorization]; - } - - return GetAuthorization(auth); - } - - /// - /// Gets the authorization. - /// - /// The authorization header. - /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorization(string authorizationHeader) - { - if (authorizationHeader == null) - { - return null; - } - - var parts = authorizationHeader.Split(' ', 2); - - // There should be at least to parts - if (parts.Length != 2) - { - return null; - } - - var acceptedNames = new[] { "MediaBrowser", "Emby" }; - - // It has to be a digest request - if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase)) - { - return null; - } - - // Remove uptil the first space - authorizationHeader = parts[1]; - parts = authorizationHeader.Split(','); - - var result = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var item in parts) - { - var param = item.Trim().Split('=', 2); - - if (param.Length == 2) - { - var value = NormalizeValue(param[1].Trim('"')); - result[param[0]] = value; - } - } - - return result; - } - - private static string NormalizeValue(string value) - { - return string.IsNullOrEmpty(value) ? value : WebUtility.HtmlEncode(value); - } - } -} diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs index 414ba7ca0..cd1b9cba0 100644 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs @@ -24,12 +24,18 @@ namespace Emby.Server.Implementations.HttpServer.Security _sessionManager = sessionManager; } - public Task GetSession(HttpContext requestContext) + public async Task GetSession(HttpContext requestContext) { - var authorization = _authContext.GetAuthorizationInfo(requestContext); + var authorization = await _authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); var user = authorization.User; - return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp().ToString(), user); + return await _sessionManager.LogSessionActivity( + authorization.Client, + authorization.Version, + authorization.DeviceId, + authorization.Device, + requestContext.GetNormalizedRemoteIp().ToString(), + user).ConfigureAwait(false); } public Task GetSession(object requestContext) diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index 1bee1ac31..b71ffdaee 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.HttpServer /// public async Task WebSocketRequestHandler(HttpContext context) { - _ = _authService.Authenticate(context.Request); + _ = await _authService.Authenticate(context.Request).ConfigureAwait(false); try { _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress); diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs deleted file mode 100644 index 0d0a2b1df..000000000 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ /dev/null @@ -1,407 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using Emby.Server.Implementations.Data; -using Jellyfin.Data.Entities.Security; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Security; -using MediaBrowser.Model.Querying; -using Microsoft.Extensions.Logging; -using SQLitePCL.pretty; - -namespace Emby.Server.Implementations.Security -{ - public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository - { - public AuthenticationRepository(ILogger logger, IServerConfigurationManager config) - : base(logger) - { - DbFilePath = Path.Combine(config.ApplicationPaths.DataPath, "authentication.db"); - } - - public void Initialize() - { - string[] queries = - { - "create table if not exists Tokens (Id INTEGER PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, DeviceName TEXT NOT NULL, UserId TEXT, UserName TEXT, IsActive BIT NOT NULL, DateCreated DATETIME NOT NULL, DateLastActivity DATETIME NOT NULL)", - "create table if not exists Devices (Id TEXT NOT NULL PRIMARY KEY, CustomName TEXT, Capabilities TEXT)", - "drop index if exists idx_AccessTokens", - "drop index if exists Tokens1", - "drop index if exists Tokens2", - - "create index if not exists Tokens3 on Tokens (AccessToken, DateLastActivity)", - "create index if not exists Tokens4 on Tokens (Id, DateLastActivity)", - "create index if not exists Devices1 on Devices (Id)" - }; - - using (var connection = GetConnection()) - { - var tableNewlyCreated = !TableExists(connection, "Tokens"); - - connection.RunQueries(queries); - - TryMigrate(connection, tableNewlyCreated); - } - } - - private void TryMigrate(ManagedConnection connection, bool tableNewlyCreated) - { - try - { - if (tableNewlyCreated && TableExists(connection, "AccessTokens")) - { - connection.RunInTransaction( - db => - { - var existingColumnNames = GetColumnNames(db, "AccessTokens"); - - AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames); - AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames); - AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames); - }, TransactionMode); - - connection.RunQueries(new[] - { - "update accesstokens set DateLastActivity=DateCreated where DateLastActivity is null", - "update accesstokens set DeviceName='Unknown' where DeviceName is null", - "update accesstokens set AppName='Unknown' where AppName is null", - "update accesstokens set AppVersion='1' where AppVersion is null", - "INSERT INTO Tokens (AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity) SELECT AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity FROM AccessTokens where deviceid not null and devicename not null and appname not null and isactive=1" - }); - } - } - catch (Exception ex) - { - Logger.LogError(ex, "Error migrating authentication database"); - } - } - - public void Create(AuthenticationInfo info) - { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - - using (var connection = GetConnection()) - { - connection.RunInTransaction( - db => - { - using (var statement = db.PrepareStatement("insert into Tokens (AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity) values (@AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @UserName, @IsActive, @DateCreated, @DateLastActivity)")) - { - statement.TryBind("@AccessToken", info.AccessToken); - - statement.TryBind("@DeviceId", info.DeviceId); - statement.TryBind("@AppName", info.AppName); - statement.TryBind("@AppVersion", info.AppVersion); - statement.TryBind("@DeviceName", info.DeviceName); - statement.TryBind("@UserId", info.UserId.Equals(Guid.Empty) ? null : info.UserId.ToString("N", CultureInfo.InvariantCulture)); - statement.TryBind("@UserName", info.UserName); - statement.TryBind("@IsActive", true); - statement.TryBind("@DateCreated", info.DateCreated.ToDateTimeParamValue()); - statement.TryBind("@DateLastActivity", info.DateLastActivity.ToDateTimeParamValue()); - - statement.MoveNext(); - } - }, TransactionMode); - } - } - - public void Update(AuthenticationInfo info) - { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - - using (var connection = GetConnection()) - { - connection.RunInTransaction( - db => - { - using (var statement = db.PrepareStatement("Update Tokens set AccessToken=@AccessToken, DeviceId=@DeviceId, AppName=@AppName, AppVersion=@AppVersion, DeviceName=@DeviceName, UserId=@UserId, UserName=@UserName, DateCreated=@DateCreated, DateLastActivity=@DateLastActivity where Id=@Id")) - { - statement.TryBind("@Id", info.Id); - - statement.TryBind("@AccessToken", info.AccessToken); - - statement.TryBind("@DeviceId", info.DeviceId); - statement.TryBind("@AppName", info.AppName); - statement.TryBind("@AppVersion", info.AppVersion); - statement.TryBind("@DeviceName", info.DeviceName); - statement.TryBind("@UserId", info.UserId.Equals(Guid.Empty) ? null : info.UserId.ToString("N", CultureInfo.InvariantCulture)); - statement.TryBind("@UserName", info.UserName); - statement.TryBind("@DateCreated", info.DateCreated.ToDateTimeParamValue()); - statement.TryBind("@DateLastActivity", info.DateLastActivity.ToDateTimeParamValue()); - - statement.MoveNext(); - } - }, TransactionMode); - } - } - - public void Delete(AuthenticationInfo info) - { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - - using (var connection = GetConnection()) - { - connection.RunInTransaction( - db => - { - using (var statement = db.PrepareStatement("Delete from Tokens where Id=@Id")) - { - statement.TryBind("@Id", info.Id); - - statement.MoveNext(); - } - }, TransactionMode); - } - } - - private const string BaseSelectText = "select Tokens.Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, DateCreated, DateLastActivity, Devices.CustomName from Tokens left join Devices on Tokens.DeviceId=Devices.Id"; - - private static void BindAuthenticationQueryParams(AuthenticationInfoQuery query, IStatement statement) - { - if (!string.IsNullOrEmpty(query.AccessToken)) - { - statement.TryBind("@AccessToken", query.AccessToken); - } - - if (!query.UserId.Equals(Guid.Empty)) - { - statement.TryBind("@UserId", query.UserId.ToString("N", CultureInfo.InvariantCulture)); - } - - if (!string.IsNullOrEmpty(query.DeviceId)) - { - statement.TryBind("@DeviceId", query.DeviceId); - } - } - - public QueryResult Get(AuthenticationInfoQuery query) - { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } - - var commandText = BaseSelectText; - - var whereClauses = new List(); - - if (!string.IsNullOrEmpty(query.AccessToken)) - { - whereClauses.Add("AccessToken=@AccessToken"); - } - - if (!string.IsNullOrEmpty(query.DeviceId)) - { - whereClauses.Add("DeviceId=@DeviceId"); - } - - if (!query.UserId.Equals(Guid.Empty)) - { - whereClauses.Add("UserId=@UserId"); - } - - if (query.HasUser.HasValue) - { - if (query.HasUser.Value) - { - whereClauses.Add("UserId not null"); - } - else - { - whereClauses.Add("UserId is null"); - } - } - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereTextWithoutPaging; - - commandText += " ORDER BY DateLastActivity desc"; - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - commandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - commandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - var statementTexts = new[] - { - commandText, - "select count (Id) from Tokens" + whereTextWithoutPaging - }; - - var list = new List(); - var result = new QueryResult(); - using (var connection = GetConnection(true)) - { - connection.RunInTransaction( - db => - { - var statements = PrepareAll(db, statementTexts); - - using (var statement = statements[0]) - { - BindAuthenticationQueryParams(query, statement); - - foreach (var row in statement.ExecuteQuery()) - { - list.Add(Get(row)); - } - - using (var totalCountStatement = statements[1]) - { - BindAuthenticationQueryParams(query, totalCountStatement); - - result.TotalRecordCount = totalCountStatement.ExecuteQuery() - .SelectScalarInt() - .First(); - } - } - }, - ReadTransactionMode); - } - - result.Items = list; - return result; - } - - private static AuthenticationInfo Get(IReadOnlyList reader) - { - var info = new AuthenticationInfo - { - Id = reader[0].ToInt64(), - AccessToken = reader[1].ToString() - }; - - if (reader[2].SQLiteType != SQLiteType.Null) - { - info.DeviceId = reader[2].ToString(); - } - - if (reader[3].SQLiteType != SQLiteType.Null) - { - info.AppName = reader[3].ToString(); - } - - if (reader[4].SQLiteType != SQLiteType.Null) - { - info.AppVersion = reader[4].ToString(); - } - - if (reader[5].SQLiteType != SQLiteType.Null) - { - info.DeviceName = reader[5].ToString(); - } - - if (reader[6].SQLiteType != SQLiteType.Null) - { - info.UserId = new Guid(reader[6].ToString()); - } - - if (reader[7].SQLiteType != SQLiteType.Null) - { - info.UserName = reader[7].ToString(); - } - - info.DateCreated = reader[8].ReadDateTime(); - - if (reader[9].SQLiteType != SQLiteType.Null) - { - info.DateLastActivity = reader[9].ReadDateTime(); - } - else - { - info.DateLastActivity = info.DateCreated; - } - - if (reader[10].SQLiteType != SQLiteType.Null) - { - info.DeviceName = reader[10].ToString(); - } - - return info; - } - - public DeviceOptions GetDeviceOptions(string deviceId) - { - using (var connection = GetConnection(true)) - { - return connection.RunInTransaction( - db => - { - using (var statement = base.PrepareStatement(db, "select CustomName from Devices where Id=@DeviceId")) - { - statement.TryBind("@DeviceId", deviceId); - - var result = new DeviceOptions(deviceId); - - foreach (var row in statement.ExecuteQuery()) - { - if (row[0].SQLiteType != SQLiteType.Null) - { - result.CustomName = row[0].ToString(); - } - } - - return result; - } - }, ReadTransactionMode); - } - } - - public void UpdateDeviceOptions(string deviceId, DeviceOptions options) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - using (var connection = GetConnection()) - { - connection.RunInTransaction( - db => - { - using (var statement = db.PrepareStatement("replace into devices (Id, CustomName, Capabilities) VALUES (@Id, @CustomName, (Select Capabilities from Devices where Id=@Id))")) - { - statement.TryBind("@Id", deviceId); - - if (string.IsNullOrWhiteSpace(options.CustomName)) - { - statement.TryBindNull("@CustomName"); - } - else - { - statement.TryBind("@CustomName", options.CustomName); - } - - statement.MoveNext(); - } - }, TransactionMode); - } - } - } -} diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 2fb5040f9..92ef65bf1 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -11,6 +11,7 @@ using Jellyfin.Data.Entities; using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Data.Queries; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; @@ -23,7 +24,6 @@ using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Session; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -52,7 +52,6 @@ namespace Emby.Server.Implementations.Session private readonly IImageProcessor _imageProcessor; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerApplicationHost _appHost; - private readonly IAuthenticationRepository _authRepo; private readonly IDeviceManager _deviceManager; /// @@ -75,7 +74,6 @@ namespace Emby.Server.Implementations.Session IDtoService dtoService, IImageProcessor imageProcessor, IServerApplicationHost appHost, - IAuthenticationRepository authRepo, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager) { @@ -88,7 +86,6 @@ namespace Emby.Server.Implementations.Session _dtoService = dtoService; _imageProcessor = imageProcessor; _appHost = appHost; - _authRepo = authRepo; _deviceManager = deviceManager; _mediaSourceManager = mediaSourceManager; @@ -1486,7 +1483,7 @@ namespace Emby.Server.Implementations.Session throw new SecurityException("User is at their maximum number of sessions."); } - var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName); + var token = await GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName).ConfigureAwait(false); var session = await LogSessionActivity( request.App, @@ -1509,21 +1506,21 @@ namespace Emby.Server.Implementations.Session return returnResult; } - private string GetAuthorizationToken(User user, string deviceId, string app, string appVersion, string deviceName) + private async Task GetAuthorizationToken(User user, string deviceId, string app, string appVersion, string deviceName) { - var existing = _authRepo.Get( - new AuthenticationInfoQuery + var existing = (await _deviceManager.GetDevices( + new DeviceQuery { DeviceId = deviceId, UserId = user.Id, Limit = 1 - }).Items.FirstOrDefault(); + }).ConfigureAwait(false)).Items.FirstOrDefault(); - var allExistingForDevice = _authRepo.Get( - new AuthenticationInfoQuery + var allExistingForDevice = (await _deviceManager.GetDevices( + new DeviceQuery { DeviceId = deviceId - }).Items; + }).ConfigureAwait(false)).Items; foreach (var auth in allExistingForDevice) { @@ -1531,7 +1528,7 @@ namespace Emby.Server.Implementations.Session { try { - Logout(auth); + await Logout(auth).ConfigureAwait(false); } catch (Exception ex) { @@ -1546,29 +1543,14 @@ namespace Emby.Server.Implementations.Session return existing.AccessToken; } - var now = DateTime.UtcNow; - - var newToken = new AuthenticationInfo - { - AppName = app, - AppVersion = appVersion, - DateCreated = now, - DateLastActivity = now, - DeviceId = deviceId, - DeviceName = deviceName, - UserId = user.Id, - AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture), - UserName = user.Username - }; - _logger.LogInformation("Creating new access token for user {0}", user.Id); - _authRepo.Create(newToken); + var device = await _deviceManager.CreateDevice(new Device(user.Id, app, appVersion, deviceName, deviceId)).ConfigureAwait(false); - return newToken.AccessToken; + return device.AccessToken; } /// - public void Logout(string accessToken) + public async Task Logout(string accessToken) { CheckDisposed(); @@ -1577,27 +1559,27 @@ namespace Emby.Server.Implementations.Session throw new ArgumentNullException(nameof(accessToken)); } - var existing = _authRepo.Get( - new AuthenticationInfoQuery + var existing = (await _deviceManager.GetDevices( + new DeviceQuery { Limit = 1, AccessToken = accessToken - }).Items; + }).ConfigureAwait(false)).Items; if (existing.Count > 0) { - Logout(existing[0]); + await Logout(existing[0]).ConfigureAwait(false); } } /// - public void Logout(AuthenticationInfo existing) + public async Task Logout(Device existing) { CheckDisposed(); _logger.LogInformation("Logging out access token {0}", existing.AccessToken); - _authRepo.Delete(existing); + await _deviceManager.DeleteDevice(existing).ConfigureAwait(false); var sessions = Sessions .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase)) @@ -1617,30 +1599,24 @@ namespace Emby.Server.Implementations.Session } /// - public void RevokeUserTokens(Guid userId, string currentAccessToken) + public async Task RevokeUserTokens(Guid userId, string currentAccessToken) { CheckDisposed(); - var existing = _authRepo.Get(new AuthenticationInfoQuery + var existing = await _deviceManager.GetDevices(new DeviceQuery { UserId = userId - }); + }).ConfigureAwait(false); foreach (var info in existing.Items) { if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase)) { - Logout(info); + await Logout(info).ConfigureAwait(false); } } } - /// - public void RevokeToken(string token) - { - Logout(token); - } - /// /// Reports the capabilities. /// @@ -1792,7 +1768,7 @@ namespace Emby.Server.Implementations.Session } /// - public Task GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion) + public Task GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion) { if (info == null) { @@ -1825,20 +1801,20 @@ namespace Emby.Server.Implementations.Session } /// - public Task GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint) + public async Task GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint) { - var items = _authRepo.Get(new AuthenticationInfoQuery + var items = (await _deviceManager.GetDevices(new DeviceQuery { AccessToken = token, Limit = 1 - }).Items; + }).ConfigureAwait(false)).Items; if (items.Count == 0) { return null; } - return GetSessionByAuthenticationToken(items[0], deviceId, remoteEndpoint, null); + return await GetSessionByAuthenticationToken(items[0], deviceId, remoteEndpoint, null).ConfigureAwait(false); } /// diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs index c56233794..369e846ae 100644 --- a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs +++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs @@ -40,11 +40,11 @@ namespace Jellyfin.Api.Auth } /// - protected override Task HandleAuthenticateAsync() + protected override async Task HandleAuthenticateAsync() { try { - var authorizationInfo = _authService.Authenticate(Request); + var authorizationInfo = await _authService.Authenticate(Request).ConfigureAwait(false); var role = UserRoles.User; if (authorizationInfo.IsApiKey || authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator)) { @@ -68,16 +68,16 @@ namespace Jellyfin.Api.Auth var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); - return Task.FromResult(AuthenticateResult.Success(ticket)); + return AuthenticateResult.Success(ticket); } catch (AuthenticationException ex) { _logger.LogDebug(ex, "Error authenticating with {Handler}", nameof(CustomAuthenticationHandler)); - return Task.FromResult(AuthenticateResult.NoResult()); + return AuthenticateResult.NoResult(); } catch (SecurityException ex) { - return Task.FromResult(AuthenticateResult.Fail(ex)); + return AuthenticateResult.Fail(ex); } } } diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 852d1e9cb..8a98d856c 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -58,7 +58,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] Guid? parentId, [FromQuery] bool isLocked = false) { - var userId = _authContext.GetAuthorizationInfo(Request).UserId; + var userId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).UserId; var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions { diff --git a/Jellyfin.Api/Controllers/DevicesController.cs b/Jellyfin.Api/Controllers/DevicesController.cs index 4cfae568a..8af7b8f73 100644 --- a/Jellyfin.Api/Controllers/DevicesController.cs +++ b/Jellyfin.Api/Controllers/DevicesController.cs @@ -3,8 +3,8 @@ using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Data.Entities.Security; +using Jellyfin.Data.Queries; using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Devices; using MediaBrowser.Model.Querying; @@ -21,22 +21,18 @@ namespace Jellyfin.Api.Controllers public class DevicesController : BaseJellyfinApiController { private readonly IDeviceManager _deviceManager; - private readonly IAuthenticationRepository _authenticationRepository; private readonly ISessionManager _sessionManager; /// /// Initializes a new instance of the class. /// /// Instance of interface. - /// Instance of interface. /// Instance of interface. public DevicesController( IDeviceManager deviceManager, - IAuthenticationRepository authenticationRepository, ISessionManager sessionManager) { _deviceManager = deviceManager; - _authenticationRepository = authenticationRepository; _sessionManager = sessionManager; } @@ -111,7 +107,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, Required] string id, [FromBody, Required] DeviceOptions deviceOptions) { - var existingDeviceOptions = _deviceManager.GetDeviceOptions(id); + var existingDeviceOptions = await _deviceManager.GetDeviceOptions(id).ConfigureAwait(false); if (existingDeviceOptions == null) { return NotFound(); @@ -131,19 +127,19 @@ namespace Jellyfin.Api.Controllers [HttpDelete] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteDevice([FromQuery, Required] string id) + public async Task DeleteDevice([FromQuery, Required] string id) { - var existingDevice = _deviceManager.GetDevice(id); + var existingDevice = await _deviceManager.GetDevice(id).ConfigureAwait(false); if (existingDevice == null) { return NotFound(); } - var sessions = _authenticationRepository.Get(new AuthenticationInfoQuery { DeviceId = id }).Items; + var sessions = await _deviceManager.GetDevices(new DeviceQuery { DeviceId = id }).ConfigureAwait(false); - foreach (var session in sessions) + foreach (var session in sessions.Items) { - _sessionManager.Logout(session); + await _sessionManager.Logout(session).ConfigureAwait(false); } return NoContent(); diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 8f7500ac6..9dc280e13 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromQuery] int? index = null) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); } @@ -144,7 +144,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromRoute] int index) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); } @@ -190,7 +190,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromQuery] int? index = null) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); } @@ -234,7 +234,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromRoute] int index) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); } diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 4ed15e1d5..504f58790 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -331,10 +331,10 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public ActionResult DeleteItem(Guid itemId) + public async Task DeleteItem(Guid itemId) { var item = _libraryManager.GetItemById(itemId); - var auth = _authContext.GetAuthorizationInfo(Request); + var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var user = auth.User; if (!item.CanDelete(user)) @@ -361,7 +361,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public ActionResult DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) + public async Task DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) { if (ids.Length == 0) { @@ -371,7 +371,7 @@ namespace Jellyfin.Api.Controllers foreach (var i in ids) { var item = _libraryManager.GetItemById(i); - var auth = _authContext.GetAuthorizationInfo(Request); + var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var user = auth.User; if (!item.CanDelete(user)) @@ -627,7 +627,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var auth = _authContext.GetAuthorizationInfo(Request); + var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var user = auth.User; diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index e330f02b6..6c29e6bb8 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -123,7 +123,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, ParameterObsolete] bool? allowAudioStreamCopy, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] PlaybackInfoDto? playbackInfoDto) { - var authInfo = _authContext.GetAuthorizationInfo(Request); + var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var profile = playbackInfoDto?.DeviceProfile; _logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", profile); diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index cc8c630b3..6dee1c219 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -171,7 +171,8 @@ namespace Jellyfin.Api.Controllers _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) { - await _transcodingJobHelper.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); + var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); + await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); @@ -320,7 +321,8 @@ namespace Jellyfin.Api.Controllers _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) { - await _transcodingJobHelper.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); + var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); + await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 116d669e4..3a04cb3a4 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -471,11 +471,11 @@ namespace Jellyfin.Api.Controllers [HttpPost("Sessions/Logout")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult ReportSessionEnded() + public async Task ReportSessionEnded() { - AuthorizationInfo auth = _authContext.GetAuthorizationInfo(Request); + AuthorizationInfo auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - _sessionManager.Logout(auth.Token); + await _sessionManager.Logout(auth.Token).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 1669a659d..2d5339b16 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -361,7 +361,7 @@ namespace Jellyfin.Api.Controllers long positionTicks = 0; - var accessToken = _authContext.GetAuthorizationInfo(Request).Token; + var accessToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; while (positionTicks < runtime) { diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 679f055bc..20a02bf4a 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -116,9 +116,9 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableRedirection = true) { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); - _authorizationContext.GetAuthorizationInfo(Request).DeviceId = deviceId; + (await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId = deviceId; - var authInfo = _authorizationContext.GetAuthorizationInfo(Request); + var authInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false); _logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", deviceProfile); diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index b13db4baa..8e2298bb7 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -77,11 +77,11 @@ namespace Jellyfin.Api.Controllers [HttpGet] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetUsers( + public async Task>> GetUsers( [FromQuery] bool? isHidden, [FromQuery] bool? isDisabled) { - var users = Get(isHidden, isDisabled, false, false); + var users = await Get(isHidden, isDisabled, false, false).ConfigureAwait(false); return Ok(users); } @@ -92,15 +92,15 @@ namespace Jellyfin.Api.Controllers /// An containing the public users. [HttpGet("Public")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetPublicUsers() + public async Task>> GetPublicUsers() { // If the startup wizard hasn't been completed then just return all users if (!_config.Configuration.IsStartupWizardCompleted) { - return Ok(Get(false, false, false, false)); + return Ok(await Get(false, false, false, false).ConfigureAwait(false)); } - return Ok(Get(false, false, true, true)); + return Ok(await Get(false, false, true, true).ConfigureAwait(false)); } /// @@ -141,7 +141,7 @@ namespace Jellyfin.Api.Controllers public async Task DeleteUser([FromRoute, Required] Guid userId) { var user = _userManager.GetUserById(userId); - _sessionManager.RevokeUserTokens(user.Id, null); + await _sessionManager.RevokeUserTokens(user.Id, null).ConfigureAwait(false); await _userManager.DeleteUserAsync(userId).ConfigureAwait(false); return NoContent(); } @@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public async Task> AuthenticateUserByName([FromBody, Required] AuthenticateUserByName request) { - var auth = _authContext.GetAuthorizationInfo(Request); + var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); try { @@ -230,7 +230,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public async Task> AuthenticateWithQuickConnect([FromBody, Required] QuickConnectDto request) { - var auth = _authContext.GetAuthorizationInfo(Request); + var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); try { @@ -271,7 +271,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UpdateUserPassword request) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the password."); } @@ -303,9 +303,9 @@ namespace Jellyfin.Api.Controllers await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false); - var currentToken = _authContext.GetAuthorizationInfo(Request).Token; + var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; - _sessionManager.RevokeUserTokens(user.Id, currentToken); + await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); } return NoContent(); @@ -325,11 +325,11 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateUserEasyPassword( + public async Task UpdateUserEasyPassword( [FromRoute, Required] Guid userId, [FromBody, Required] UpdateUserEasyPassword request) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the easy password."); } @@ -343,11 +343,11 @@ namespace Jellyfin.Api.Controllers if (request.ResetPassword) { - _userManager.ResetEasyPassword(user); + await _userManager.ResetEasyPassword(user).ConfigureAwait(false); } else { - _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword); + await _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword).ConfigureAwait(false); } return NoContent(); @@ -371,7 +371,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UserDto updateUser) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User update not allowed."); } @@ -431,8 +431,8 @@ namespace Jellyfin.Api.Controllers return StatusCode(StatusCodes.Status403Forbidden, "There must be at least one enabled user in the system."); } - var currentToken = _authContext.GetAuthorizationInfo(Request).Token; - _sessionManager.RevokeUserTokens(user.Id, currentToken); + var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); } await _userManager.UpdatePolicyAsync(userId, newPolicy).ConfigureAwait(false); @@ -456,7 +456,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UserConfiguration userConfig) { - if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false)) + if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) { return StatusCode(StatusCodes.Status403Forbidden, "User configuration update not allowed"); } @@ -555,7 +555,7 @@ namespace Jellyfin.Api.Controllers return _userManager.GetUserDto(user); } - private IEnumerable Get(bool? isHidden, bool? isDisabled, bool filterByDevice, bool filterByNetwork) + private async Task> Get(bool? isHidden, bool? isDisabled, bool filterByDevice, bool filterByNetwork) { var users = _userManager.Users; @@ -571,7 +571,7 @@ namespace Jellyfin.Api.Controllers if (filterByDevice) { - var deviceId = _authContext.GetAuthorizationInfo(Request).DeviceId; + var deviceId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId; if (!string.IsNullOrWhiteSpace(deviceId)) { diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 7bc5ecdf1..3d27371f6 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; +using System.Threading.Tasks; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.UserViewDtos; @@ -64,7 +65,7 @@ namespace Jellyfin.Api.Controllers /// An containing the user views. [HttpGet("Users/{userId}/Views")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetUserViews( + public async Task>> GetUserViews( [FromRoute, Required] Guid userId, [FromQuery] bool? includeExternalContent, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] presetViews, @@ -86,7 +87,7 @@ namespace Jellyfin.Api.Controllers query.PresetViews = presetViews; } - var app = _authContext.GetAuthorizationInfo(Request).Client ?? string.Empty; + var app = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Client ?? string.Empty; if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1) { query.PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows }; diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 295cfaf08..3b8dc7e31 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -468,7 +468,7 @@ namespace Jellyfin.Api.Helpers /// A containing the . public async Task OpenMediaSource(HttpRequest httpRequest, LiveStreamRequest request) { - var authInfo = _authContext.GetAuthorizationInfo(httpRequest); + var authInfo = await _authContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index 3810f7477..0efd3443b 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -60,9 +60,9 @@ namespace Jellyfin.Api.Helpers /// The user id. /// Whether to restrict the user preferences. /// A whether the user can update the entry. - internal static bool AssertCanUpdateUser(IAuthorizationContext authContext, HttpRequest requestContext, Guid userId, bool restrictUserPreferences) + internal static async Task AssertCanUpdateUser(IAuthorizationContext authContext, HttpRequest requestContext, Guid userId, bool restrictUserPreferences) { - var auth = authContext.GetAuthorizationInfo(requestContext); + var auth = await authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); var authenticatedUser = auth.User; @@ -78,7 +78,7 @@ namespace Jellyfin.Api.Helpers internal static async Task GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) { - var authorization = authContext.GetAuthorizationInfo(request); + var authorization = await authContext.GetAuthorizationInfo(request).ConfigureAwait(false); var user = authorization.User; var session = await sessionManager.LogSessionActivity( authorization.Client, diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 8cffe9c4c..cecbd36c1 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -17,9 +17,7 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; @@ -101,7 +99,7 @@ namespace Jellyfin.Api.Helpers EnableDlnaHeaders = enableDlnaHeaders }; - var auth = authorizationContext.GetAuthorizationInfo(httpRequest); + var auth = await authorizationContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); if (!auth.UserId.Equals(Guid.Empty)) { state.User = userManager.GetUserById(auth.UserId); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 0879cbd18..242077963 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -489,7 +489,7 @@ namespace Jellyfin.Api.Helpers if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { - var auth = _authorizationContext.GetAuthorizationInfo(request); + var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false); if (auth.User != null && !auth.User.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) { this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state); diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs index bde8eb86e..9fd2e5ad4 100644 --- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs +++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs @@ -6,6 +6,7 @@ using Jellyfin.Data.Entities; using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Data.Queries; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Devices; @@ -55,6 +56,17 @@ namespace Jellyfin.Server.Implementations.Devices DeviceOptionsUpdated?.Invoke(this, new GenericEventArgs>(new Tuple(deviceId, options))); } + /// + public async Task CreateDevice(Device device) + { + await using var dbContext = _dbProvider.CreateContext(); + + dbContext.Devices.Add(device); + + await dbContext.SaveChangesAsync().ConfigureAwait(false); + return device; + } + /// public async Task GetDeviceOptions(string deviceId) { @@ -90,6 +102,61 @@ namespace Jellyfin.Server.Implementations.Devices return deviceInfo; } + /// + public async Task> GetDevices(DeviceQuery query) + { + await using var dbContext = _dbProvider.CreateContext(); + + var devices = dbContext.Devices.AsQueryable(); + + if (query.UserId.HasValue) + { + devices = devices.Where(device => device.UserId == query.UserId.Value); + } + + if (query.DeviceId != null) + { + devices = devices.Where(device => device.DeviceId == query.DeviceId); + } + + if (query.AccessToken != null) + { + devices = devices.Where(device => device.AccessToken == query.AccessToken); + } + + if (query.Skip.HasValue) + { + devices = devices.Skip(query.Skip.Value); + } + + var count = await devices.CountAsync().ConfigureAwait(false); + + if (query.Limit.HasValue) + { + devices = devices.Take(query.Limit.Value); + } + + return new QueryResult + { + Items = await devices.ToListAsync().ConfigureAwait(false), + StartIndex = query.Skip ?? 0, + TotalRecordCount = count + }; + } + + /// + public async Task> GetDeviceInfos(DeviceQuery query) + { + var devices = await GetDevices(query).ConfigureAwait(false); + + return new QueryResult + { + Items = devices.Items.Select(ToDeviceInfo).ToList(), + StartIndex = devices.StartIndex, + TotalRecordCount = devices.TotalRecordCount + }; + } + /// public async Task> GetDevicesForUser(Guid? userId, bool? supportsSync) { @@ -117,6 +184,12 @@ namespace Jellyfin.Server.Implementations.Devices return new QueryResult(array); } + /// + public async Task DeleteDevice(Device device) + { + await using var dbContext = _dbProvider.CreateContext(); + } + /// public bool CanAccessDevice(User user, string deviceId) { diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index 059e884e5..6f35a2c1c 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -214,6 +214,15 @@ namespace Jellyfin.Server.Implementations modelBuilder.Entity() .HasIndex(entity => new { entity.DeviceId, entity.DateLastActivity }); + modelBuilder.Entity() + .HasIndex(entity => new { entity.AccessToken, entity.DateLastActivity }); + + modelBuilder.Entity() + .HasIndex(entity => new { entity.UserId, entity.DeviceId }); + + modelBuilder.Entity() + .HasIndex(entity => entity.DeviceId); + modelBuilder.Entity() .HasIndex(entity => entity.DeviceId) .IsUnique(); diff --git a/Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.Designer.cs new file mode 100644 index 000000000..e1faef7a2 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.Designer.cs @@ -0,0 +1,645 @@ +#pragma warning disable CS1591 +// +using System; +using Jellyfin.Server.Implementations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Jellyfin.Server.Implementations.Migrations +{ + [DbContext(typeof(JellyfinDb))] + [Migration("20210521032224_AddDevices")] + partial class AddDevices + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("jellyfin") + .HasAnnotation("ProductVersion", "5.0.5"); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DayOfWeek") + .HasColumnType("INTEGER"); + + b.Property("EndHour") + .HasColumnType("REAL"); + + b.Property("StartHour") + .HasColumnType("REAL"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccessSchedules"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("LogSeverity") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("ShortOverview") + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ActivityLogs"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemId", "Client", "Key") + .IsUnique(); + + b.ToTable("CustomItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChromecastVersion") + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("DashboardTheme") + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("EnableNextVideoInfoOverlay") + .HasColumnType("INTEGER"); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("ScrollDirection") + .HasColumnType("INTEGER"); + + b.Property("ShowBackdrop") + .HasColumnType("INTEGER"); + + b.Property("ShowSidebar") + .HasColumnType("INTEGER"); + + b.Property("SkipBackwardLength") + .HasColumnType("INTEGER"); + + b.Property("SkipForwardLength") + .HasColumnType("INTEGER"); + + b.Property("TvHome") + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemId", "Client") + .IsUnique(); + + b.ToTable("DisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DisplayPreferencesId") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DisplayPreferencesId"); + + b.ToTable("HomeSection"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ImageInfos"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("RememberIndexing") + .HasColumnType("INTEGER"); + + b.Property("RememberSorting") + .HasColumnType("INTEGER"); + + b.Property("SortBy") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("ViewType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Permission_Permissions_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "Kind") + .IsUnique() + .HasFilter("[UserId] IS NOT NULL"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Preference_Preferences_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "Kind") + .IsUnique() + .HasFilter("[UserId] IS NOT NULL"); + + b.ToTable("Preferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccessToken") + .HasColumnType("TEXT"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AccessToken") + .IsUnique(); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AppName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("AppVersion") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("DateLastActivity") + .HasColumnType("TEXT"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("DeviceName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId"); + + b.HasIndex("AccessToken", "DateLastActivity"); + + b.HasIndex("DeviceId", "DateLastActivity"); + + b.HasIndex("UserId", "DeviceId"); + + b.ToTable("Devices"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CustomName") + .HasColumnType("TEXT"); + + b.Property("DeviceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId") + .IsUnique(); + + b.ToTable("DeviceOptions"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AudioLanguagePreference") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("AuthenticationProviderId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("DisplayCollectionsView") + .HasColumnType("INTEGER"); + + b.Property("DisplayMissingEpisodes") + .HasColumnType("INTEGER"); + + b.Property("EasyPassword") + .HasMaxLength(65535) + .HasColumnType("TEXT"); + + b.Property("EnableAutoLogin") + .HasColumnType("INTEGER"); + + b.Property("EnableLocalPassword") + .HasColumnType("INTEGER"); + + b.Property("EnableNextEpisodeAutoPlay") + .HasColumnType("INTEGER"); + + b.Property("EnableUserPreferenceAccess") + .HasColumnType("INTEGER"); + + b.Property("HidePlayedInLatest") + .HasColumnType("INTEGER"); + + b.Property("InternalId") + .HasColumnType("INTEGER"); + + b.Property("InvalidLoginAttemptCount") + .HasColumnType("INTEGER"); + + b.Property("LastActivityDate") + .HasColumnType("TEXT"); + + b.Property("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property("LoginAttemptsBeforeLockout") + .HasColumnType("INTEGER"); + + b.Property("MaxActiveSessions") + .HasColumnType("INTEGER"); + + b.Property("MaxParentalAgeRating") + .HasColumnType("INTEGER"); + + b.Property("MustUpdatePassword") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasMaxLength(65535) + .HasColumnType("TEXT"); + + b.Property("PasswordResetProviderId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("PlayDefaultAudioTrack") + .HasColumnType("INTEGER"); + + b.Property("RememberAudioSelections") + .HasColumnType("INTEGER"); + + b.Property("RememberSubtitleSelections") + .HasColumnType("INTEGER"); + + b.Property("RemoteClientBitrateLimit") + .HasColumnType("INTEGER"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("SubtitleLanguagePreference") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property("SyncPlayAccess") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT") + .UseCollation("NOCASE"); + + b.HasKey("Id"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("AccessSchedules") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("DisplayPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) + .WithMany("HomeSections") + .HasForeignKey("DisplayPreferencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("ProfileImage") + .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("ItemDisplayPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Permissions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Preferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => + { + b.HasOne("Jellyfin.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Navigation("HomeSections"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Navigation("AccessSchedules"); + + b.Navigation("DisplayPreferences"); + + b.Navigation("ItemDisplayPreferences"); + + b.Navigation("Permissions"); + + b.Navigation("Preferences"); + + b.Navigation("ProfileImage"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.cs b/Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.cs new file mode 100644 index 000000000..2da8d3788 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20210521032224_AddDevices.cs @@ -0,0 +1,126 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1601 +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Jellyfin.Server.Implementations.Migrations +{ + public partial class AddDevices : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApiKeys", + schema: "jellyfin", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DateCreated = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", maxLength: 64, nullable: false), + AccessToken = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiKeys", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "DeviceOptions", + schema: "jellyfin", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DeviceId = table.Column(type: "TEXT", nullable: false), + CustomName = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_DeviceOptions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Devices", + schema: "jellyfin", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "TEXT", nullable: false), + AccessToken = table.Column(type: "TEXT", nullable: false), + AppName = table.Column(type: "TEXT", maxLength: 64, nullable: false), + AppVersion = table.Column(type: "TEXT", maxLength: 32, nullable: false), + DeviceName = table.Column(type: "TEXT", maxLength: 64, nullable: false), + DeviceId = table.Column(type: "TEXT", maxLength: 256, nullable: false), + IsActive = table.Column(type: "INTEGER", nullable: false), + DateCreated = table.Column(type: "TEXT", nullable: false), + DateLastActivity = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Devices", x => x.Id); + table.ForeignKey( + name: "FK_Devices_Users_UserId", + column: x => x.UserId, + principalSchema: "jellyfin", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApiKeys_AccessToken", + schema: "jellyfin", + table: "ApiKeys", + column: "AccessToken", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DeviceOptions_DeviceId", + schema: "jellyfin", + table: "DeviceOptions", + column: "DeviceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Devices_AccessToken_DateLastActivity", + schema: "jellyfin", + table: "Devices", + columns: new[] { "AccessToken", "DateLastActivity" }); + + migrationBuilder.CreateIndex( + name: "IX_Devices_DeviceId", + schema: "jellyfin", + table: "Devices", + column: "DeviceId"); + + migrationBuilder.CreateIndex( + name: "IX_Devices_DeviceId_DateLastActivity", + schema: "jellyfin", + table: "Devices", + columns: new[] { "DeviceId", "DateLastActivity" }); + + migrationBuilder.CreateIndex( + name: "IX_Devices_UserId_DeviceId", + schema: "jellyfin", + table: "Devices", + columns: new[] { "UserId", "DeviceId" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApiKeys", + schema: "jellyfin"); + + migrationBuilder.DropTable( + name: "DeviceOptions", + schema: "jellyfin"); + + migrationBuilder.DropTable( + name: "Devices", + schema: "jellyfin"); + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index 286eb7468..8a1ae16f8 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -15,7 +15,7 @@ namespace Jellyfin.Server.Implementations.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "5.0.3"); + .HasAnnotation("ProductVersion", "5.0.5"); modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => { @@ -332,6 +332,107 @@ namespace Jellyfin.Server.Implementations.Migrations b.ToTable("Preferences"); }); + modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccessToken") + .HasColumnType("TEXT"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AccessToken") + .IsUnique(); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccessToken") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AppName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("AppVersion") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("DateLastActivity") + .HasColumnType("TEXT"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("DeviceName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId"); + + b.HasIndex("AccessToken", "DateLastActivity"); + + b.HasIndex("DeviceId", "DateLastActivity"); + + b.HasIndex("UserId", "DeviceId"); + + b.ToTable("Devices"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CustomName") + .HasColumnType("TEXT"); + + b.Property("DeviceId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId") + .IsUnique(); + + b.ToTable("DeviceOptions"); + }); + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => { b.Property("Id") @@ -505,6 +606,17 @@ namespace Jellyfin.Server.Implementations.Migrations .OnDelete(DeleteBehavior.Cascade); }); + modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => + { + b.HasOne("Jellyfin.Data.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => { b.Navigation("HomeSections"); diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs new file mode 100644 index 000000000..775edafc2 --- /dev/null +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -0,0 +1,283 @@ +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; +using Microsoft.AspNetCore.Http; +using Microsoft.Net.Http.Headers; + +namespace Jellyfin.Server.Implementations.Security +{ + public class AuthorizationContext : IAuthorizationContext + { + private readonly JellyfinDb _jellyfinDb; + private readonly IUserManager _userManager; + + public AuthorizationContext(JellyfinDb jellyfinDb, IUserManager userManager) + { + _jellyfinDb = jellyfinDb; + _userManager = userManager; + } + + public Task GetAuthorizationInfo(HttpContext requestContext) + { + if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached) && cached != null) + { + return Task.FromResult((AuthorizationInfo)cached); + } + + return GetAuthorization(requestContext); + } + + public async Task GetAuthorizationInfo(HttpRequest requestContext) + { + var auth = GetAuthorizationDictionary(requestContext); + var authInfo = await GetAuthorizationInfoFromDictionary(auth, requestContext.Headers, requestContext.Query).ConfigureAwait(false); + return authInfo; + } + + /// + /// Gets the authorization. + /// + /// The HTTP req. + /// Dictionary{System.StringSystem.String}. + private async Task GetAuthorization(HttpContext httpReq) + { + var auth = GetAuthorizationDictionary(httpReq); + var authInfo = await GetAuthorizationInfoFromDictionary(auth, httpReq.Request.Headers, httpReq.Request.Query).ConfigureAwait(false); + + httpReq.Request.HttpContext.Items["AuthorizationInfo"] = authInfo; + return authInfo; + } + + private async Task GetAuthorizationInfoFromDictionary( + IReadOnlyDictionary? auth, + IHeaderDictionary headers, + IQueryCollection queryString) + { + string? deviceId = null; + string? deviceName = null; + string? client = null; + string? version = null; + string? token = null; + + if (auth != null) + { + auth.TryGetValue("DeviceId", out deviceId); + auth.TryGetValue("Device", out deviceName); + auth.TryGetValue("Client", out client); + auth.TryGetValue("Version", out version); + auth.TryGetValue("Token", out token); + } + +#pragma warning disable CA1508 + // headers can return StringValues.Empty + if (string.IsNullOrEmpty(token)) + { + token = headers["X-Emby-Token"]; + } + + if (string.IsNullOrEmpty(token)) + { + token = headers["X-MediaBrowser-Token"]; + } + + if (string.IsNullOrEmpty(token)) + { + token = queryString["ApiKey"]; + } + + // TODO deprecate this query parameter. + if (string.IsNullOrEmpty(token)) + { + token = queryString["api_key"]; + } + + var authInfo = new AuthorizationInfo + { + Client = client, + Device = deviceName, + DeviceId = deviceId, + Version = version, + Token = token, + IsAuthenticated = false, + HasToken = false + }; + + if (string.IsNullOrWhiteSpace(token)) + { + // Request doesn't contain a token. + return authInfo; + } +#pragma warning restore CA1508 + + authInfo.HasToken = true; + var device = await _jellyfinDb.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false); + + if (device != null) + { + authInfo.IsAuthenticated = true; + } + + if (device != null) + { + var updateToken = false; + + // TODO: Remove these checks for IsNullOrWhiteSpace + if (string.IsNullOrWhiteSpace(authInfo.Client)) + { + authInfo.Client = device.AppName; + } + + if (string.IsNullOrWhiteSpace(authInfo.DeviceId)) + { + authInfo.DeviceId = device.DeviceId; + } + + // Temporary. TODO - allow clients to specify that the token has been shared with a casting device + var allowTokenInfoUpdate = !authInfo.Client.Contains("chromecast", StringComparison.OrdinalIgnoreCase); + + if (string.IsNullOrWhiteSpace(authInfo.Device)) + { + authInfo.Device = device.DeviceName; + } + else if (!string.Equals(authInfo.Device, device.DeviceName, StringComparison.OrdinalIgnoreCase)) + { + if (allowTokenInfoUpdate) + { + updateToken = true; + device.DeviceName = authInfo.Device; + } + } + + if (string.IsNullOrWhiteSpace(authInfo.Version)) + { + authInfo.Version = device.AppVersion; + } + else if (!string.Equals(authInfo.Version, device.AppVersion, StringComparison.OrdinalIgnoreCase)) + { + if (allowTokenInfoUpdate) + { + updateToken = true; + device.AppVersion = authInfo.Version; + } + } + + if ((DateTime.UtcNow - device.DateLastActivity).TotalMinutes > 3) + { + device.DateLastActivity = DateTime.UtcNow; + updateToken = true; + } + + if (!device.UserId.Equals(Guid.Empty)) + { + authInfo.User = _userManager.GetUserById(device.UserId); + authInfo.IsApiKey = false; + } + else + { + authInfo.IsApiKey = true; + } + + if (updateToken) + { + _jellyfinDb.Devices.Update(device); + await _jellyfinDb.SaveChangesAsync().ConfigureAwait(false); + } + } + + return authInfo; + } + + /// + /// Gets the auth. + /// + /// The HTTP req. + /// Dictionary{System.StringSystem.String}. + private Dictionary? GetAuthorizationDictionary(HttpContext httpReq) + { + var auth = httpReq.Request.Headers["X-Emby-Authorization"]; + + if (string.IsNullOrEmpty(auth)) + { + auth = httpReq.Request.Headers[HeaderNames.Authorization]; + } + + return GetAuthorization(auth); + } + + /// + /// Gets the auth. + /// + /// The HTTP req. + /// Dictionary{System.StringSystem.String}. + private Dictionary? GetAuthorizationDictionary(HttpRequest httpReq) + { + var auth = httpReq.Headers["X-Emby-Authorization"]; + + if (string.IsNullOrEmpty(auth)) + { + auth = httpReq.Headers[HeaderNames.Authorization]; + } + + return GetAuthorization(auth); + } + + /// + /// Gets the authorization. + /// + /// The authorization header. + /// Dictionary{System.StringSystem.String}. + private Dictionary? GetAuthorization(string? authorizationHeader) + { + if (authorizationHeader == null) + { + return null; + } + + var parts = authorizationHeader.Split(' ', 2); + + // There should be at least to parts + if (parts.Length != 2) + { + return null; + } + + var acceptedNames = new[] { "MediaBrowser", "Emby" }; + + // It has to be a digest request + if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase)) + { + return null; + } + + // Remove uptil the first space + authorizationHeader = parts[1]; + parts = authorizationHeader.Split(','); + + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var item in parts) + { + var param = item.Trim().Split('=', 2); + + if (param.Length == 2) + { + var value = NormalizeValue(param[1].Trim('"')); + result[param[0]] = value; + } + } + + return result; + } + + private static string NormalizeValue(string value) + { + return string.IsNullOrEmpty(value) ? value : WebUtility.HtmlEncode(value); + } + } +} diff --git a/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs b/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs index dbba80c21..a471ea1d5 100644 --- a/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs +++ b/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs @@ -4,10 +4,10 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Data.Queries; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; namespace Jellyfin.Server.Implementations.Users @@ -15,14 +15,12 @@ namespace Jellyfin.Server.Implementations.Users public sealed class DeviceAccessEntryPoint : IServerEntryPoint { private readonly IUserManager _userManager; - private readonly IAuthenticationRepository _authRepo; private readonly IDeviceManager _deviceManager; private readonly ISessionManager _sessionManager; - public DeviceAccessEntryPoint(IUserManager userManager, IAuthenticationRepository authRepo, IDeviceManager deviceManager, ISessionManager sessionManager) + public DeviceAccessEntryPoint(IUserManager userManager, IDeviceManager deviceManager, ISessionManager sessionManager) { _userManager = userManager; - _authRepo = authRepo; _deviceManager = deviceManager; _sessionManager = sessionManager; } @@ -38,27 +36,27 @@ namespace Jellyfin.Server.Implementations.Users { } - private void OnUserUpdated(object? sender, GenericEventArgs e) + private async void OnUserUpdated(object? sender, GenericEventArgs e) { var user = e.Argument; if (!user.HasPermission(PermissionKind.EnableAllDevices)) { - UpdateDeviceAccess(user); + await UpdateDeviceAccess(user).ConfigureAwait(false); } } - private void UpdateDeviceAccess(User user) + private async Task UpdateDeviceAccess(User user) { - var existing = _authRepo.Get(new AuthenticationInfoQuery + var existing = (await _deviceManager.GetDevices(new DeviceQuery { UserId = user.Id - }).Items; + }).ConfigureAwait(false)).Items; - foreach (var authInfo in existing) + foreach (var device in existing) { - if (!string.IsNullOrEmpty(authInfo.DeviceId) && !_deviceManager.CanAccessDevice(user, authInfo.DeviceId)) + if (!string.IsNullOrEmpty(device.DeviceId) && !_deviceManager.CanAccessDevice(user, device.DeviceId)) { - _sessionManager.Logout(authInfo); + await _sessionManager.Logout(device).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b20acae32..362be8531 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,6 +11,7 @@ using Jellyfin.Server.Implementations; using Jellyfin.Server.Implementations.Activity; using Jellyfin.Server.Implementations.Devices; using Jellyfin.Server.Implementations.Events; +using Jellyfin.Server.Implementations.Security; using Jellyfin.Server.Implementations.Users; using MediaBrowser.Controller; using MediaBrowser.Controller.BaseItemManager; @@ -94,6 +95,8 @@ namespace Jellyfin.Server ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); + ServiceCollection.AddScoped(); + base.RegisterServices(); } diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs index 28612cea3..6ff4422d2 100644 --- a/MediaBrowser.Controller/Devices/IDeviceManager.cs +++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Events; +using Jellyfin.Data.Queries; using MediaBrowser.Model.Devices; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Session; @@ -17,6 +18,13 @@ namespace MediaBrowser.Controller.Devices { event EventHandler>> DeviceOptionsUpdated; + /// + /// Creates a new device. + /// + /// The device to create. + /// A representing the creation of the device. + Task CreateDevice(Device device); + /// /// Saves the capabilities. /// @@ -38,6 +46,15 @@ namespace MediaBrowser.Controller.Devices /// DeviceInfo. Task GetDevice(string id); + /// + /// Gets devices based on the provided query. + /// + /// The device query. + /// A representing the retrieval of the devices. + Task> GetDevices(DeviceQuery query); + + Task> GetDeviceInfos(DeviceQuery query); + /// /// Gets the devices. /// @@ -46,6 +63,8 @@ namespace MediaBrowser.Controller.Devices /// IEnumerable<DeviceInfo>. Task> GetDevicesForUser(Guid? userId, bool? supportsSync); + Task DeleteDevice(Device device); + /// /// Determines whether this instance [can access device] the specified user identifier. /// diff --git a/MediaBrowser.Controller/Net/IAuthService.cs b/MediaBrowser.Controller/Net/IAuthService.cs index d15c6d318..a7da740e0 100644 --- a/MediaBrowser.Controller/Net/IAuthService.cs +++ b/MediaBrowser.Controller/Net/IAuthService.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net @@ -12,6 +13,6 @@ namespace MediaBrowser.Controller.Net /// /// The request. /// Authorization information. Null if unauthenticated. - AuthorizationInfo Authenticate(HttpRequest request); + Task Authenticate(HttpRequest request); } } diff --git a/MediaBrowser.Controller/Net/IAuthorizationContext.cs b/MediaBrowser.Controller/Net/IAuthorizationContext.cs index 0d310548d..5c6ca43d1 100644 --- a/MediaBrowser.Controller/Net/IAuthorizationContext.cs +++ b/MediaBrowser.Controller/Net/IAuthorizationContext.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net @@ -11,14 +12,14 @@ namespace MediaBrowser.Controller.Net /// Gets the authorization information. /// /// The request context. - /// AuthorizationInfo. - AuthorizationInfo GetAuthorizationInfo(HttpContext requestContext); + /// A task containing the authorization info. + Task GetAuthorizationInfo(HttpContext requestContext); /// /// Gets the authorization information. /// /// The request context. - /// AuthorizationInfo. - AuthorizationInfo GetAuthorizationInfo(HttpRequest requestContext); + /// A containing the authorization info. + Task GetAuthorizationInfo(HttpRequest requestContext); } } diff --git a/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs b/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs deleted file mode 100644 index 3af6a525c..000000000 --- a/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs +++ /dev/null @@ -1,53 +0,0 @@ -#nullable disable - -#pragma warning disable CS1591 - -using System; - -namespace MediaBrowser.Controller.Security -{ - public class AuthenticationInfoQuery - { - /// - /// Gets or sets the device identifier. - /// - /// The device identifier. - public string DeviceId { get; set; } - - /// - /// Gets or sets the user identifier. - /// - /// The user identifier. - public Guid UserId { get; set; } - - /// - /// Gets or sets the access token. - /// - /// The access token. - public string AccessToken { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is active. - /// - /// null if [is active] contains no value, true if [is active]; otherwise, false. - public bool? IsActive { get; set; } - - /// - /// Gets or sets a value indicating whether this instance has user. - /// - /// null if [has user] contains no value, true if [has user]; otherwise, false. - public bool? HasUser { get; set; } - - /// - /// Gets or sets the start index. - /// - /// The start index. - public int? StartIndex { get; set; } - - /// - /// Gets or sets the limit. - /// - /// The limit. - public int? Limit { get; set; } - } -} diff --git a/MediaBrowser.Controller/Security/IAuthenticationRepository.cs b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs deleted file mode 100644 index 9685005ba..000000000 --- a/MediaBrowser.Controller/Security/IAuthenticationRepository.cs +++ /dev/null @@ -1,39 +0,0 @@ -#nullable disable - -#pragma warning disable CS1591 - -using Jellyfin.Data.Entities.Security; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Controller.Security -{ - public interface IAuthenticationRepository - { - /// - /// Creates the specified information. - /// - /// The information. - /// Task. - void Create(AuthenticationInfo info); - - /// - /// Updates the specified information. - /// - /// The information. - /// Task. - void Update(AuthenticationInfo info); - - /// - /// Gets the specified query. - /// - /// The query. - /// QueryResult{AuthenticationInfo}. - QueryResult Get(AuthenticationInfoQuery query); - - void Delete(AuthenticationInfo info); - - DeviceOptions GetDeviceOptions(string deviceId); - - void UpdateDeviceOptions(string deviceId, DeviceOptions options); - } -} diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 30a83d6e7..1000da247 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -6,10 +6,12 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Events; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Security; +using MediaBrowser.Model.Devices; using MediaBrowser.Model.Session; using MediaBrowser.Model.SyncPlay; @@ -325,26 +327,23 @@ namespace MediaBrowser.Controller.Session /// The remote endpoint. /// The application version. /// Task<SessionInfo>. - Task GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion); + Task GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion); /// /// Logouts the specified access token. /// /// The access token. - void Logout(string accessToken); + /// A representing the log out process. + Task Logout(string accessToken); - void Logout(AuthenticationInfo accessToken); + Task Logout(Device accessToken); /// /// Revokes the user tokens. /// - void RevokeUserTokens(Guid userId, string currentAccessToken); - - /// - /// Revokes the token. - /// - /// The identifier. - void RevokeToken(string id); + /// The user's id. + /// The current access token. + Task RevokeUserTokens(Guid userId, string currentAccessToken); void CloseIfNeeded(SessionInfo session); } diff --git a/MediaBrowser.Model/Devices/DeviceInfo.cs b/MediaBrowser.Model/Devices/DeviceInfo.cs index 0cccf931c..7a1c7a738 100644 --- a/MediaBrowser.Model/Devices/DeviceInfo.cs +++ b/MediaBrowser.Model/Devices/DeviceInfo.cs @@ -15,6 +15,11 @@ namespace MediaBrowser.Model.Devices public string Name { get; set; } + /// + /// Gets or sets the access token. + /// + public string AccessToken { get; set; } + /// /// Gets or sets the identifier. /// diff --git a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs index de03aa5f5..cd03958b6 100644 --- a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs @@ -136,7 +136,7 @@ namespace Jellyfin.Api.Tests.Auth _jellyfinAuthServiceMock.Setup( a => a.Authenticate( It.IsAny())) - .Returns(authorizationInfo); + .Returns(Task.FromResult(authorizationInfo)); return authorizationInfo; } -- cgit v1.2.3 From b91c4be74c7181319f45b9f1b2f157d4952f4f0d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Jul 2021 22:36:50 +0200 Subject: Remove old "has update available" code This is the job of a package manager (or maybe the tray app for windows) --- Emby.Notifications/NotificationEntryPoint.cs | 21 --------------------- Emby.Server.Implementations/ApplicationHost.cs | 21 --------------------- MediaBrowser.Controller/IServerApplicationHost.cs | 8 -------- MediaBrowser.Model/System/SystemInfo.cs | 1 + 4 files changed, 1 insertion(+), 50 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Notifications/NotificationEntryPoint.cs b/Emby.Notifications/NotificationEntryPoint.cs index 7433d3c8a..e8ae14ff2 100644 --- a/Emby.Notifications/NotificationEntryPoint.cs +++ b/Emby.Notifications/NotificationEntryPoint.cs @@ -77,7 +77,6 @@ namespace Emby.Notifications { _libraryManager.ItemAdded += OnLibraryManagerItemAdded; _appHost.HasPendingRestartChanged += OnAppHostHasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged += OnAppHostHasUpdateAvailableChanged; _activityManager.EntryCreated += OnActivityManagerEntryCreated; return Task.CompletedTask; @@ -132,25 +131,6 @@ namespace Emby.Notifications return _config.GetConfiguration("notifications"); } - private async void OnAppHostHasUpdateAvailableChanged(object? sender, EventArgs e) - { - if (!_appHost.HasUpdateAvailable) - { - return; - } - - var type = NotificationType.ApplicationUpdateAvailable.ToString(); - - var notification = new NotificationRequest - { - Description = "Please see jellyfin.org for details.", - NotificationType = type, - Name = _localization.GetLocalizedString("NewVersionIsAvailable") - }; - - await SendNotification(notification, null).ConfigureAwait(false); - } - private void OnLibraryManagerItemAdded(object? sender, ItemChangeEventArgs e) { if (!FilterItem(e.Item)) @@ -325,7 +305,6 @@ namespace Emby.Notifications _libraryManager.ItemAdded -= OnLibraryManagerItemAdded; _appHost.HasPendingRestartChanged -= OnAppHostHasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged -= OnAppHostHasUpdateAvailableChanged; _activityManager.EntryCreated -= OnActivityManagerEntryCreated; _disposed = true; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 82995deb3..7ad7a2732 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1102,7 +1102,6 @@ namespace Emby.Server.Implementations OperatingSystemDisplayName = OperatingSystem.Name, CanSelfRestart = CanSelfRestart, CanLaunchWebBrowser = CanLaunchWebBrowser, - HasUpdateAvailable = HasUpdateAvailable, TranscodingTempPath = ConfigurationManager.GetTranscodePath(), ServerName = FriendlyName, LocalAddress = GetSmartApiUrl(source), @@ -1252,26 +1251,6 @@ namespace Emby.Server.Implementations protected abstract void ShutdownInternal(); - public event EventHandler HasUpdateAvailableChanged; - - private bool _hasUpdateAvailable; - - public bool HasUpdateAvailable - { - get => _hasUpdateAvailable; - set - { - var fireEvent = value && !_hasUpdateAvailable; - - _hasUpdateAvailable = value; - - if (fireEvent) - { - HasUpdateAvailableChanged?.Invoke(this, EventArgs.Empty); - } - } - } - public IEnumerable GetApiPluginAssemblies() { var assemblies = _allConcreteTypes diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 094923842..753c18bc7 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -16,8 +16,6 @@ namespace MediaBrowser.Controller /// public interface IServerApplicationHost : IApplicationHost { - event EventHandler HasUpdateAvailableChanged; - bool CoreStartupHasCompleted { get; } bool CanLaunchWebBrowser { get; } @@ -39,12 +37,6 @@ namespace MediaBrowser.Controller /// bool ListenWithHttps { get; } - /// - /// Gets a value indicating whether this instance has update available. - /// - /// true if this instance has update available; otherwise, false. - bool HasUpdateAvailable { get; } - /// /// Gets the name of the friendly. /// diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index d75ae91c0..e45b2f33a 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -130,6 +130,7 @@ namespace MediaBrowser.Model.System /// Gets or sets a value indicating whether this instance has update available. /// /// true if this instance has update available; otherwise, false. + [Obsolete("This should be handled by the package manager")] public bool HasUpdateAvailable { get; set; } public FFmpegLocation EncoderLocation { get; set; } -- cgit v1.2.3 From 915141f196d6ec20f3f0a398d9b328f25ae71241 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Jul 2021 22:32:06 +0200 Subject: Fix some warnings --- Emby.Server.Implementations/ApplicationHost.cs | 12 +-- .../Library/LibraryManager.cs | 5 +- .../ScheduledTasks/Tasks/CleanActivityLogTask.cs | 2 +- MediaBrowser.Common/Net/IPHost.cs | 13 +--- MediaBrowser.Controller/Entities/BaseItem.cs | 16 +--- MediaBrowser.Controller/Entities/UserView.cs | 85 +++++++++++----------- .../FFprobeParserTests.cs | 5 +- 7 files changed, 62 insertions(+), 76 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 82995deb3..b73b6bb00 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1118,7 +1118,7 @@ namespace Emby.Server.Implementations .Select(i => new WakeOnLanInfo(i)) .ToList(); - public PublicSystemInfo GetPublicSystemInfo(IPAddress source) + public PublicSystemInfo GetPublicSystemInfo(IPAddress address) { return new PublicSystemInfo { @@ -1127,7 +1127,7 @@ namespace Emby.Server.Implementations Id = SystemId, OperatingSystem = OperatingSystem.Id.ToString(), ServerName = FriendlyName, - LocalAddress = GetSmartApiUrl(source), + LocalAddress = GetSmartApiUrl(address), StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted }; } @@ -1136,7 +1136,7 @@ namespace Emby.Server.Implementations public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps; /// - public string GetSmartApiUrl(IPAddress ipAddress, int? port = null) + public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null) { // Published server ends with a / if (!string.IsNullOrEmpty(PublishedServerUrl)) @@ -1145,7 +1145,7 @@ namespace Emby.Server.Implementations return PublishedServerUrl.Trim('/'); } - string smart = NetManager.GetBindInterface(ipAddress, out port); + string smart = NetManager.GetBindInterface(remoteAddr, out port); // If the smartAPI doesn't start with http then treat it as a host or ip. if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { @@ -1208,14 +1208,14 @@ namespace Emby.Server.Implementations } /// - public string GetLocalApiUrl(string host, string scheme = null, int? port = null) + public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null) { // NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does // not. For consistency, always trim the trailing slash. return new UriBuilder { Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp), - Host = host, + Host = hostname, Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort), Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl }.ToString().TrimEnd('/'); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d80637332..13fb8b2fd 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2540,9 +2540,10 @@ namespace Emby.Server.Implementations.Library { episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming); // Resolve from parent folder if it's not the Season folder - if (episodeInfo == null && episode.Parent.GetType() == typeof(Folder)) + var parent = episode.GetParent(); + if (episodeInfo == null && parent.GetType() == typeof(Folder)) { - episodeInfo = resolver.Resolve(episode.Parent.Path, true, null, null, isAbsoluteNaming); + episodeInfo = resolver.Resolve(parent.Path, true, null, null, isAbsoluteNaming); if (episodeInfo != null) { // add the container diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs index 50ba9bc89..19600b1e6 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs @@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks throw new Exception($"Activity Log Retention days must be at least 0. Currently: {retentionDays}"); } - var startDate = DateTime.UtcNow.AddDays(retentionDays.Value * -1); + var startDate = DateTime.UtcNow.AddDays(-retentionDays.Value); return _activityManager.CleanAsync(startDate); } diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index 5db8817ee..d78d7def2 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -79,16 +79,11 @@ namespace MediaBrowser.Common.Net /// public override byte PrefixLength { - get - { - return (byte)(ResolveHost() ? 128 : 32); - } + get => (byte)(ResolveHost() ? 128 : 32); - set - { - // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length, - // which is automatically determined by it's IP type. Anything else is meaningless. - } + // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length, + // which is automatically determined by it's IP type. Anything else is meaningless. + set => throw new NotImplementedException(); } /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index e5be5421a..23b97f70c 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -771,19 +771,6 @@ namespace MediaBrowser.Controller.Entities [JsonIgnore] public Guid ParentId { get; set; } - /// - /// Gets or sets the parent. - /// - /// The parent. - [JsonIgnore] - public Folder Parent - { - get => GetParent() as Folder; - set - { - } - } - public void SetParent(Folder parent) { ParentId = parent == null ? Guid.Empty : parent.Id; @@ -822,8 +809,7 @@ namespace MediaBrowser.Controller.Entities { foreach (var parent in GetParents()) { - var item = parent as T; - if (item != null) + if (parent is T item) { return item; } diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 57dc9b59b..62f3c4b55 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -15,6 +15,25 @@ namespace MediaBrowser.Controller.Entities { public class UserView : Folder, IHasCollectionType { + private static readonly string[] _viewTypesEligibleForGrouping = new string[] + { + Model.Entities.CollectionType.Movies, + Model.Entities.CollectionType.TvShows, + string.Empty + }; + + private static readonly string[] _originalFolderViewTypes = new string[] + { + Model.Entities.CollectionType.Books, + Model.Entities.CollectionType.MusicVideos, + Model.Entities.CollectionType.HomeVideos, + Model.Entities.CollectionType.Photos, + Model.Entities.CollectionType.Music, + Model.Entities.CollectionType.BoxSets + }; + + public static ITVSeriesManager TVSeriesManager { get; set; } + /// /// Gets or sets the view type. /// @@ -30,12 +49,22 @@ namespace MediaBrowser.Controller.Entities /// public Guid? UserId { get; set; } - public static ITVSeriesManager TVSeriesManager; - /// [JsonIgnore] public string CollectionType => ViewType; + /// + [JsonIgnore] + public override bool SupportsInheritedParentImages => false; + + /// + [JsonIgnore] + public override bool SupportsPlayedStatus => false; + + /// + [JsonIgnore] + public override bool SupportsPeople => false; + /// public override IEnumerable GetIdsForAncestorQuery() { @@ -53,17 +82,13 @@ namespace MediaBrowser.Controller.Entities } } - [JsonIgnore] - public override bool SupportsInheritedParentImages => false; - - [JsonIgnore] - public override bool SupportsPlayedStatus => false; - + /// public override int GetChildCount(User user) { return GetChildren(user, true).Count; } + /// protected override QueryResult GetItemsInternal(InternalItemsQuery query) { var parent = this as Folder; @@ -81,6 +106,7 @@ namespace MediaBrowser.Controller.Entities .GetUserItems(parent, this, CollectionType, query); } + /// public override List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { query ??= new InternalItemsQuery(user); @@ -91,16 +117,19 @@ namespace MediaBrowser.Controller.Entities return result.ToList(); } + /// public override bool CanDelete() { return false; } + /// public override bool IsSaveLocalMetadataEnabled() { return true; } + /// public override IEnumerable GetRecursiveChildren(User user, InternalItemsQuery query) { query.SetUser(user); @@ -111,32 +140,26 @@ namespace MediaBrowser.Controller.Entities return GetItemList(query); } + /// protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user) { return GetChildren(user, false); } - private static readonly string[] UserSpecificViewTypes = new string[] - { - Model.Entities.CollectionType.Playlists - }; - public static bool IsUserSpecific(Folder folder) { - var collectionFolder = folder as ICollectionFolder; - - if (collectionFolder == null) + if (folder is not ICollectionFolder collectionFolder) { return false; } - var supportsUserSpecific = folder as ISupportsUserSpecificView; - if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView) + if (folder is ISupportsUserSpecificView supportsUserSpecific + && supportsUserSpecific.EnableUserSpecificView) { return true; } - return UserSpecificViewTypes.Contains(collectionFolder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return string.Equals(Model.Entities.CollectionType.Playlists, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase); } public static bool IsEligibleForGrouping(Folder folder) @@ -145,39 +168,19 @@ namespace MediaBrowser.Controller.Entities && IsEligibleForGrouping(collectionFolder.CollectionType); } - private static string[] ViewTypesEligibleForGrouping = new string[] - { - Model.Entities.CollectionType.Movies, - Model.Entities.CollectionType.TvShows, - string.Empty - }; - public static bool IsEligibleForGrouping(string viewType) { - return ViewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); } - private static string[] OriginalFolderViewTypes = new string[] - { - Model.Entities.CollectionType.Books, - Model.Entities.CollectionType.MusicVideos, - Model.Entities.CollectionType.HomeVideos, - Model.Entities.CollectionType.Photos, - Model.Entities.CollectionType.Music, - Model.Entities.CollectionType.BoxSets - }; - public static bool EnableOriginalFolder(string viewType) { - return OriginalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); } protected override Task ValidateChildrenInternal(IProgress progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken) { return Task.CompletedTask; } - - [JsonIgnore] - public override bool SupportsPeople => false; } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 45808375f..2955104a2 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -14,9 +14,10 @@ namespace Jellyfin.MediaEncoding.Tests public async Task Test(string fileName) { var path = Path.Join("Test Data", fileName); - using (var stream = File.OpenRead(path)) + await using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync(stream, JsonDefaults.Options).ConfigureAwait(false); + var res = await JsonSerializer.DeserializeAsync(stream, JsonDefaults.Options).ConfigureAwait(false); + Assert.NotNull(res); } } } -- cgit v1.2.3 From 8528e9bddb4c2dd9e1e3294649e39c7ec609bdf5 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 12 Jul 2021 20:20:50 +0200 Subject: Improve platform checks --- Emby.Dlna/Main/DlnaEntryPoint.cs | 13 ++++++++----- Emby.Server.Implementations/ApplicationHost.cs | 17 +++++------------ Emby.Server.Implementations/IO/ManagedFileSystem.cs | 7 +++---- Jellyfin.Api/Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 3 +-- Jellyfin.Api/Helpers/HlsHelpers.cs | 3 +-- Jellyfin.Server/Program.cs | 8 ++++---- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 17 ++++++++--------- .../IO/ManagedFileSystemTests.cs | 6 +++--- .../Location/MovieNfoLocationTests.cs | 8 ++++---- .../Parsers/MovieNfoParserTests.cs | 2 +- 11 files changed, 39 insertions(+), 47 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 0309926ab..5d252d8dc 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -27,11 +27,9 @@ using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Net; -using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; using Rssdp; using Rssdp.Infrastructure; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Dlna.Main { @@ -204,8 +202,8 @@ namespace Emby.Dlna.Main { if (_communicationsServer == null) { - var enableMultiSocketBinding = OperatingSystem.Id == OperatingSystemId.Windows || - OperatingSystem.Id == OperatingSystemId.Linux; + var enableMultiSocketBinding = OperatingSystem.IsWindows() || + OperatingSystem.IsLinux(); _communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger, enableMultiSocketBinding) { @@ -268,7 +266,12 @@ namespace Emby.Dlna.Main try { - _publisher = new SsdpDevicePublisher(_communicationsServer, _networkManager, OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost) + _publisher = new SsdpDevicePublisher( + _communicationsServer, + _networkManager, + MediaBrowser.Common.System.OperatingSystem.Name, + Environment.OSVersion.VersionString, + _config.GetDlnaConfiguration().SendOnlyMatchedHost) { LogFunction = LogMessage, SupportPnpRootDevice = false diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7ad7a2732..0523a3c52 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -103,7 +103,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Prometheus.DotNetRuntime; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; using WebSocketManager = Emby.Server.Implementations.HttpServer.WebSocketManager; namespace Emby.Server.Implementations @@ -150,13 +149,7 @@ namespace Emby.Server.Implementations return false; } - if (OperatingSystem.Id == OperatingSystemId.Windows - || OperatingSystem.Id == OperatingSystemId.Darwin) - { - return true; - } - - return false; + return OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); } } @@ -721,7 +714,7 @@ namespace Emby.Server.Implementations logger.LogInformation("Environment Variables: {EnvVars}", relevantEnvVars); logger.LogInformation("Arguments: {Args}", commandLineArgs); - logger.LogInformation("Operating system: {OS}", OperatingSystem.Name); + logger.LogInformation("Operating system: {OS}", MediaBrowser.Common.System.OperatingSystem.Name); logger.LogInformation("Architecture: {Architecture}", RuntimeInformation.OSArchitecture); logger.LogInformation("64-Bit Process: {Is64Bit}", Environment.Is64BitProcess); logger.LogInformation("User Interactive: {IsUserInteractive}", Environment.UserInteractive); @@ -1098,8 +1091,8 @@ namespace Emby.Server.Implementations ItemsByNamePath = ApplicationPaths.InternalMetadataPath, InternalMetadataPath = ApplicationPaths.InternalMetadataPath, CachePath = ApplicationPaths.CachePath, - OperatingSystem = OperatingSystem.Id.ToString(), - OperatingSystemDisplayName = OperatingSystem.Name, + OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(), + OperatingSystemDisplayName = MediaBrowser.Common.System.OperatingSystem.Name, CanSelfRestart = CanSelfRestart, CanLaunchWebBrowser = CanLaunchWebBrowser, TranscodingTempPath = ConfigurationManager.GetTranscodePath(), @@ -1124,7 +1117,7 @@ namespace Emby.Server.Implementations Version = ApplicationVersionString, ProductName = ApplicationProductName, Id = SystemId, - OperatingSystem = OperatingSystem.Id.ToString(), + OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(), ServerName = FriendlyName, LocalAddress = GetSmartApiUrl(source), StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index ca028a3ca..7c3c7da23 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -11,7 +11,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Server.Implementations.IO { @@ -24,7 +23,7 @@ namespace Emby.Server.Implementations.IO private readonly List _shortcutHandlers = new List(); private readonly string _tempPath; - private static readonly bool _isEnvironmentCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows(); public ManagedFileSystem( ILogger logger, @@ -402,7 +401,7 @@ namespace Emby.Server.Implementations.IO public virtual void SetHidden(string path, bool isHidden) { - if (OperatingSystem.Id != OperatingSystemId.Windows) + if (!OperatingSystem.IsWindows()) { return; } @@ -426,7 +425,7 @@ namespace Emby.Server.Implementations.IO public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly) { - if (OperatingSystem.Id != OperatingSystemId.Windows) + if (!OperatingSystem.IsWindows()) { return; } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 62283d038..dcf262e32 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1380,7 +1380,7 @@ namespace Jellyfin.Api.Controllers } else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase)) { - var outputFmp4HeaderArg = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) switch + var outputFmp4HeaderArg = OperatingSystem.IsWindows() switch { // on Windows, the path of fmp4 header file needs to be configured true => " -hls_fmp4_init_filename \"" + outputPrefix + "-1" + outputExtension + "\"", diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 6a720b1a4..1e0329821 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -366,8 +366,7 @@ namespace Jellyfin.Api.Controllers else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase)) { var outputFmp4HeaderArg = string.Empty; - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - if (isWindows) + if (OperatingSystem.IsWindows()) { // on Windows, the path of fmp4 header file needs to be configured outputFmp4HeaderArg = " -hls_fmp4_init_filename \"" + outputPrefix + "-1" + outputExtension + "\""; diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index d0666034e..d1cdaf867 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -99,8 +99,7 @@ namespace Jellyfin.Api.Helpers return fmp4InitFileName; } - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - if (isWindows) + if (OperatingSystem.IsWindows()) { // on Windows // #EXT-X-MAP:URI="X:\transcodes\prefix-1.mp4" diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 3a3d7415b..934372a94 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -318,8 +318,8 @@ namespace Jellyfin.Server } } - // Bind to unix socket (only on macOS and Linux) - if (startupConfig.UseUnixSocket() && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + // Bind to unix socket (only on unix systems) + if (startupConfig.UseUnixSocket() && Environment.OSVersion.Platform == PlatformID.Unix) { var socketPath = startupConfig.GetUnixSocketPath(); if (string.IsNullOrEmpty(socketPath)) @@ -404,7 +404,7 @@ namespace Jellyfin.Server { if (options.DataDir != null || Directory.Exists(Path.Combine(dataDir, "config")) - || RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + || OperatingSystem.IsWindows()) { // Hang config folder off already set dataDir configDir = Path.Combine(dataDir, "config"); @@ -442,7 +442,7 @@ namespace Jellyfin.Server if (string.IsNullOrEmpty(cacheDir)) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (OperatingSystem.IsWindows()) { // Hang cache folder off already set dataDir cacheDir = Path.Combine(dataDir, "cache"); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 26b0bc3de..160d9d691 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -143,8 +143,7 @@ namespace MediaBrowser.Controller.MediaEncoding } // Hybrid VPP tonemapping for QSV with VAAPI - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - if (isLinux && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (OperatingSystem.IsLinux() && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { // Limited to HEVC for now since the filter doesn't accept master data from VP9. return IsColorDepth10(state) @@ -503,9 +502,9 @@ namespace MediaBrowser.Controller.MediaEncoding var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase); var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + var isWindows = OperatingSystem.IsWindows(); + var isLinux = OperatingSystem.IsLinux(); + var isMacOS = OperatingSystem.IsMacOS(); var isTonemappingSupported = IsTonemappingSupported(state, encodingOptions); var isVppTonemappingSupported = IsVppTonemappingSupported(state, encodingOptions); @@ -1983,7 +1982,7 @@ namespace MediaBrowser.Controller.MediaEncoding var videoSizeParam = string.Empty; var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty; - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isLinux = OperatingSystem.IsLinux(); var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiH264Encoder = outputVideoCodec.IndexOf("h264_vaapi", StringComparison.OrdinalIgnoreCase) != -1; @@ -2528,7 +2527,7 @@ namespace MediaBrowser.Controller.MediaEncoding var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1; var isLibX265Encoder = outputVideoCodec.IndexOf("libx265", StringComparison.OrdinalIgnoreCase) != -1; - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isLinux = OperatingSystem.IsLinux(); var isColorDepth10 = IsColorDepth10(state); var isTonemappingSupported = IsTonemappingSupported(state, options); var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); @@ -3572,8 +3571,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec, bool isColorDepth10) { - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isWindows = OperatingSystem.IsWindows(); + var isLinux = OperatingSystem.IsLinux(); var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1); var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va"); var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase); diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index 30e6542f9..d991f5574 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -1,10 +1,10 @@ +using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using AutoFixture; using AutoFixture.AutoMoq; using Emby.Server.Implementations.IO; -using MediaBrowser.Model.System; using Xunit; namespace Jellyfin.Server.Implementations.Tests.IO @@ -31,7 +31,7 @@ namespace Jellyfin.Server.Implementations.Tests.IO { var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath); - if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows) + if (OperatingSystem.IsWindows()) { var expectedWindowsPath = expectedAbsolutePath.Replace('/', '\\'); Assert.Equal(expectedWindowsPath, generatedPath.Split(':')[1]); @@ -55,7 +55,7 @@ namespace Jellyfin.Server.Implementations.Tests.IO [SkippableFact] public void GetFileInfo_DanglingSymlink_ExistsFalse() { - Skip.If(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); + Skip.If(OperatingSystem.IsWindows()); string testFileDir = Path.Combine(Path.GetTempPath(), "jellyfin-test-data"); string testFileName = Path.Combine(testFileDir, Path.GetRandomFileName() + "-danglingsym.link"); diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs index 357d61c0b..8019e0ab3 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs @@ -1,8 +1,8 @@ -using System.Linq; +using System; +using System.Linq; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.System; using MediaBrowser.XbmcMetadata.Savers; using Xunit; @@ -28,7 +28,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Location var path2 = "/media/movies/Avengers Endgame/movie.nfo"; // uses ContainingFolderPath which uses Operating system specific paths - if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows) + if (OperatingSystem.IsWindows()) { movie.Path = movie.Path.Replace('/', '\\'); path1 = path1.Replace('/', '\\'); @@ -49,7 +49,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Location var path2 = "/media/movies/Avengers Endgame/VIDEO_TS/VIDEO_TS.nfo"; // uses ContainingFolderPath which uses Operating system specific paths - if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows) + if (OperatingSystem.IsWindows()) { movie.Path = movie.Path.Replace('/', '\\'); path1 = path1.Replace('/', '\\'); diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 30a48857a..cbcce73eb 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -59,7 +59,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _localImageFileMetadata = new FileSystemMetadata() { Exists = true, - FullName = MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows ? + FullName = OperatingSystem.IsWindows() ? "C:\\media\\movies\\Justice League (2017).jpg" : "/media/movies/Justice League (2017).jpg" }; -- cgit v1.2.3 From cba07b1ca6862ef8450021b0e60ce2f366ff0d33 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 28 Aug 2021 16:32:50 -0600 Subject: Remove more and more warnings --- Emby.Dlna/ContentDirectory/ServerItem.cs | 2 +- Emby.Dlna/Didl/DidlBuilder.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 3 +- .../Channels/ChannelManager.cs | 6 +- .../Data/BaseSqliteRepository.cs | 2 +- .../Data/SqliteItemRepository.cs | 9 +- .../Data/SqliteUserDataRepository.cs | 8 +- Emby.Server.Implementations/Dto/DtoService.cs | 41 +- .../EntryPoints/LibraryChangedNotifier.cs | 4 +- .../EntryPoints/UdpServerEntryPoint.cs | 3 + .../HttpServer/Security/AuthorizationContext.cs | 2 + .../HttpServer/WebSocketConnection.cs | 4 +- Emby.Server.Implementations/IStartupOptions.cs | 2 +- .../Images/CollectionFolderImageProvider.cs | 12 +- .../Library/LibraryManager.cs | 8 +- .../Library/Resolvers/Audio/AudioResolver.cs | 12 +- .../Library/Resolvers/BaseVideoResolver.cs | 26 +- .../Library/Resolvers/GenericVideoResolver.cs | 18 + .../Library/Resolvers/ItemResolver.cs | 2 +- .../Library/Resolvers/Movies/MovieResolver.cs | 4 +- .../Library/Resolvers/PlaylistResolver.cs | 3 +- .../Library/Resolvers/VideoResolver.cs | 18 - .../Library/Validators/StudiosValidator.cs | 9 +- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/EmbyTV/EpgChannelData.cs | 1 - .../LiveTv/Listings/SchedulesDirect.cs | 620 ++++----------------- .../Listings/SchedulesDirectDtos/BroadcasterDto.cs | 36 ++ .../Listings/SchedulesDirectDtos/CaptionDto.cs | 24 + .../LiveTv/Listings/SchedulesDirectDtos/CastDto.cs | 48 ++ .../Listings/SchedulesDirectDtos/ChannelDto.cs | 31 ++ .../SchedulesDirectDtos/ContentRatingDto.cs | 24 + .../LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs | 42 ++ .../LiveTv/Listings/SchedulesDirectDtos/DayDto.cs | 39 ++ .../SchedulesDirectDtos/Description1000Dto.cs | 24 + .../SchedulesDirectDtos/Description100Dto.cs | 24 + .../SchedulesDirectDtos/DescriptionsProgramDto.cs | 25 + .../SchedulesDirectDtos/EventDetailsDto.cs | 18 + .../Listings/SchedulesDirectDtos/GracenoteDto.cs | 24 + .../Listings/SchedulesDirectDtos/HeadendsDto.cs | 37 ++ .../Listings/SchedulesDirectDtos/ImageDataDto.cs | 69 +++ .../Listings/SchedulesDirectDtos/LineupDto.cs | 42 ++ .../Listings/SchedulesDirectDtos/LineupsDto.cs | 37 ++ .../LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs | 36 ++ .../LiveTv/Listings/SchedulesDirectDtos/MapDto.cs | 48 ++ .../Listings/SchedulesDirectDtos/MetadataDto.cs | 30 + .../SchedulesDirectDtos/MetadataProgramsDto.cs | 18 + .../SchedulesDirectDtos/MetadataScheduleDto.cs | 42 ++ .../Listings/SchedulesDirectDtos/MovieDto.cs | 31 ++ .../Listings/SchedulesDirectDtos/MultipartDto.cs | 24 + .../SchedulesDirectDtos/ProgramDetailsDto.cs | 157 ++++++ .../Listings/SchedulesDirectDtos/ProgramDto.cs | 91 +++ .../SchedulesDirectDtos/QualityRatingDto.cs | 42 ++ .../Listings/SchedulesDirectDtos/RatingDto.cs | 24 + .../SchedulesDirectDtos/RecommendationDto.cs | 24 + .../RequestScheduleForChannelDto.cs | 25 + .../Listings/SchedulesDirectDtos/ShowImagesDto.cs | 22 + .../Listings/SchedulesDirectDtos/StationDto.cs | 67 +++ .../Listings/SchedulesDirectDtos/TitleDto.cs | 18 + .../Listings/SchedulesDirectDtos/TokenDto.cs | 36 ++ .../LiveTv/LiveTvManager.cs | 6 +- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 1 + .../Playlists/PlaylistManager.cs | 4 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 3 +- .../Sorting/ArtistComparer.cs | 2 +- Jellyfin.Api/Controllers/ItemUpdateController.cs | 10 +- Jellyfin.Api/Controllers/ItemsController.cs | 4 +- Jellyfin.Api/Controllers/LibraryController.cs | 2 +- Jellyfin.Api/Controllers/TvShowsController.cs | 8 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 - MediaBrowser.Controller/Entities/BaseItem.cs | 4 +- MediaBrowser.Controller/Entities/Folder.cs | 10 +- MediaBrowser.Controller/Entities/TV/Series.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 12 +- .../MediaEncoding/EncodingJobInfo.cs | 6 +- .../Images/LocalImageProvider.cs | 2 +- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 8 +- MediaBrowser.Model/Dlna/MediaFormatProfile.cs | 2 +- MediaBrowser.Model/Dlna/ResolutionNormalizer.cs | 4 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 33 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 2 +- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- MediaBrowser.Model/IO/IFileSystem.cs | 4 +- MediaBrowser.Providers/Manager/ImageSaver.cs | 2 +- .../Manager/ItemImageProvider.cs | 4 +- MediaBrowser.Providers/Manager/MetadataService.cs | 6 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 10 +- MediaBrowser.Providers/Manager/ProviderUtils.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 6 +- MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs | 2 +- 90 files changed, 1572 insertions(+), 699 deletions(-) create mode 100644 Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs delete mode 100644 Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs create mode 100644 Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Dlna/ContentDirectory/ServerItem.cs b/Emby.Dlna/ContentDirectory/ServerItem.cs index 34244000c..ff30e6e4a 100644 --- a/Emby.Dlna/ContentDirectory/ServerItem.cs +++ b/Emby.Dlna/ContentDirectory/ServerItem.cs @@ -17,7 +17,7 @@ namespace Emby.Dlna.ContentDirectory { Item = item; - if (item is IItemByName && !(item is Folder)) + if (item is IItemByName && item is not Folder) { StubType = Dlna.ContentDirectory.StubType.Folder; } diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 2982ce97e..c00078499 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -748,7 +748,7 @@ namespace Emby.Dlna.Didl AddValue(writer, "upnp", "publisher", studio, NsUpnp); } - if (!(item is Folder)) + if (item is not Folder) { if (filter.Contains("dc:description")) { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bf7ddace2..b640f06c6 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -456,6 +456,7 @@ namespace Emby.Server.Implementations /// /// Runs the startup tasks. /// + /// The cancellation token. /// . public async Task RunStartupTasksAsync(CancellationToken cancellationToken) { @@ -469,7 +470,7 @@ namespace Emby.Server.Implementations _mediaEncoder.SetFFmpegPath(); - Logger.LogInformation("ServerId: {0}", SystemId); + Logger.LogInformation("ServerId: {ServerId}", SystemId); var entryPoints = GetExports(); diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index aa54510a7..41d1f9b39 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Channels var internalChannel = _libraryManager.GetItemById(item.ChannelId); var channel = Channels.FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(internalChannel.Id)); - return !(channel is IDisableMediaSourceDisplay); + return channel is not IDisableMediaSourceDisplay; } /// @@ -1079,11 +1079,11 @@ namespace Emby.Server.Implementations.Channels // was used for status // if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal)) - //{ + // { // item.ExternalEtag = info.Etag; // forceUpdate = true; // _logger.LogDebug("Forcing update due to ExternalEtag {0}", item.Name); - //} + // } if (!internalChannelId.Equals(item.ChannelId)) { diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 6f23a0888..01c9fbca8 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Data protected virtual int? CacheSize => null; /// - /// Gets the journal mode. + /// Gets the journal mode. . /// /// The journal mode. protected virtual string JournalMode => "TRUNCATE"; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 2cb10765f..ab1b55164 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -72,9 +72,16 @@ namespace Emby.Server.Implementations.Data _mediaAttachmentInsertPrefix = queryPrefixText.ToString(); } + /// /// Initializes a new instance of the class. /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// config is null. public SqliteItemRepository( IServerConfigurationManager config, IServerApplicationHost appHost, @@ -4879,7 +4886,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type foreach (var t in _knownTypes) { - dict[t.Name] = t.FullName ; + dict[t.Name] = t.FullName; } dict["Program"] = typeof(LiveTvProgram).FullName; diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index ef9af1dcd..613d07d77 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -174,7 +174,6 @@ namespace Emby.Server.Implementations.Data /// The key. /// The user data. /// The cancellation token. - /// Task. public void PersistUserData(long internalUserId, string key, UserItemData userData, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -319,8 +318,8 @@ namespace Emby.Server.Implementations.Data /// /// Return all user-data associated with the given user. /// - /// - /// + /// The internal user id. + /// The list of user item data. public List GetAllUserData(long internalUserId) { if (internalUserId <= 0) @@ -349,7 +348,8 @@ namespace Emby.Server.Implementations.Data /// /// Read a row from the specified reader into the provided userData object. /// - /// + /// The list of result set values. + /// The user item data. private UserItemData ReadRow(IReadOnlyList reader) { var userData = new UserItemData(); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 7411239a1..7c2d02037 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -807,7 +807,7 @@ namespace Emby.Server.Implementations.Dto dto.MediaType = item.MediaType; - if (!(item is LiveTvProgram)) + if (item is not LiveTvProgram) { dto.LocationType = item.LocationType; } @@ -928,9 +928,9 @@ namespace Emby.Server.Implementations.Dto } // if (options.ContainsField(ItemFields.MediaSourceCount)) - //{ + // { // Songs always have one - //} + // } } if (item is IHasArtist hasArtist) @@ -938,10 +938,10 @@ namespace Emby.Server.Implementations.Dto dto.Artists = hasArtist.Artists; // var artistItems = _libraryManager.GetArtists(new InternalItemsQuery - //{ + // { // EnableTotalRecordCount = false, // ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) } - //}); + // }); // dto.ArtistItems = artistItems.Items // .Select(i => @@ -958,7 +958,7 @@ namespace Emby.Server.Implementations.Dto // Include artists that are not in the database yet, e.g., just added via metadata editor // var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); dto.ArtistItems = hasArtist.Artists - //.Except(foundArtists, new DistinctNameComparer()) + // .Except(foundArtists, new DistinctNameComparer()) .Select(i => { // This should not be necessary but we're seeing some cases of it @@ -990,10 +990,10 @@ namespace Emby.Server.Implementations.Dto dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); // var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery - //{ + // { // EnableTotalRecordCount = false, // ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) } - //}); + // }); // dto.AlbumArtists = artistItems.Items // .Select(i => @@ -1008,7 +1008,7 @@ namespace Emby.Server.Implementations.Dto // .ToList(); dto.AlbumArtists = hasAlbumArtist.AlbumArtists - //.Except(foundArtists, new DistinctNameComparer()) + // .Except(foundArtists, new DistinctNameComparer()) .Select(i => { // This should not be necessary but we're seeing some cases of it @@ -1035,8 +1035,7 @@ namespace Emby.Server.Implementations.Dto } // Add video info - var video = item as Video; - if (video != null) + if (item is Video video) { dto.VideoType = video.VideoType; dto.Video3DFormat = video.Video3DFormat; @@ -1075,9 +1074,7 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.MediaStreams)) { // Add VideoInfo - var iHasMediaSources = item as IHasMediaSources; - - if (iHasMediaSources != null) + if (item is IHasMediaSources) { MediaStream[] mediaStreams; @@ -1146,7 +1143,7 @@ namespace Emby.Server.Implementations.Dto // TODO maybe remove the if statement entirely // if (options.ContainsField(ItemFields.SeriesPrimaryImage)) { - episodeSeries = episodeSeries ?? episode.Series; + episodeSeries ??= episode.Series; if (episodeSeries != null) { dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, episodeSeries, ImageType.Primary); @@ -1159,7 +1156,7 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.SeriesStudio)) { - episodeSeries = episodeSeries ?? episode.Series; + episodeSeries ??= episode.Series; if (episodeSeries != null) { dto.SeriesStudio = episodeSeries.Studios.FirstOrDefault(); @@ -1172,7 +1169,7 @@ namespace Emby.Server.Implementations.Dto { dto.AirDays = series.AirDays; dto.AirTime = series.AirTime; - dto.Status = series.Status.HasValue ? series.Status.Value.ToString() : null; + dto.Status = series.Status?.ToString(); } // Add SeasonInfo @@ -1185,7 +1182,7 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.SeriesStudio)) { - series = series ?? season.Series; + series ??= season.Series; if (series != null) { dto.SeriesStudio = series.Studios.FirstOrDefault(); @@ -1196,7 +1193,7 @@ namespace Emby.Server.Implementations.Dto // TODO maybe remove the if statement entirely // if (options.ContainsField(ItemFields.SeriesPrimaryImage)) { - series = series ?? season.Series; + series ??= season.Series; if (series != null) { dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, series, ImageType.Primary); @@ -1283,7 +1280,7 @@ namespace Emby.Server.Implementations.Dto var parent = currentItem.DisplayParent ?? currentItem.GetOwner() ?? currentItem.GetParent(); - if (parent == null && !(originalItem is UserRootFolder) && !(originalItem is UserView) && !(originalItem is AggregateFolder) && !(originalItem is ICollectionFolder) && !(originalItem is Channel)) + if (parent == null && originalItem is not UserRootFolder && originalItem is not UserView && originalItem is not AggregateFolder && originalItem is not ICollectionFolder && originalItem is not Channel) { parent = _libraryManager.GetCollectionFolders(originalItem).FirstOrDefault(); } @@ -1317,7 +1314,7 @@ namespace Emby.Server.Implementations.Dto var imageTags = dto.ImageTags; while (((!(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && logoLimit > 0) || (!(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && artLimit > 0) || (!(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && thumbLimit > 0) || parent is Series) && - (parent = parent ?? (isFirst ? GetImageDisplayParent(item, item) ?? owner : parent)) != null) + (parent ??= (isFirst ? GetImageDisplayParent(item, item) ?? owner : parent)) != null) { if (parent == null) { @@ -1348,7 +1345,7 @@ namespace Emby.Server.Implementations.Dto } } - if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView)) + if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && parent is not ICollectionFolder && parent is not UserView) { var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb); diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 5bb4100ba..df48346e3 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -149,7 +149,7 @@ namespace Emby.Server.Implementations.EntryPoints private static bool EnableRefreshMessage(BaseItem item) { - if (!(item is Folder folder)) + if (item is not Folder folder) { return false; } @@ -403,7 +403,7 @@ namespace Emby.Server.Implementations.EntryPoints return false; } - if (item is IItemByName && !(item is MusicArtist)) + if (item is IItemByName && item is not MusicArtist) { return false; } diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 2e72b18f5..feaccf9fa 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -37,6 +37,9 @@ namespace Emby.Server.Implementations.EntryPoints /// /// Initializes a new instance of the class. /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. public UdpServerEntryPoint( ILogger logger, IServerApplicationHost appHost, diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index b2625a68c..badc6ce6c 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -74,6 +74,7 @@ namespace Emby.Server.Implementations.HttpServer.Security auth.TryGetValue("Token", out token); } +#pragma warning disable CA1508 // string.IsNullOrEmpty(token) is always false. if (string.IsNullOrEmpty(token)) { token = headers["X-Emby-Token"]; @@ -111,6 +112,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Request doesn't contain a token. return authInfo; } +#pragma warning restore CA1508 authInfo.HasToken = true; var result = _authRepo.Get(new AuthenticationInfoQuery diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 5d38ea0ca..7010a6fb0 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.HttpServer public event EventHandler? Closed; /// - /// Gets or sets the remote end point. + /// Gets the remote end point. /// public IPAddress? RemoteEndPoint { get; } @@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.HttpServer public DateTime LastKeepAliveDate { get; set; } /// - /// Gets or sets the query string. + /// Gets the query string. /// /// The query string. public IQueryCollection QueryString { get; } diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index a430b9e72..1d97882db 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -10,7 +10,7 @@ namespace Emby.Server.Implementations string? FFmpegPath { get; } /// - /// Gets the value of the --service command line option. + /// Gets a value value indicating whether to run as service by the --service command line option. /// bool IsService { get; } diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index ff5f26ce0..0229fbae7 100644 --- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -30,27 +30,27 @@ namespace Emby.Server.Implementations.Images string[] includeItemTypes; - if (string.Equals(viewType, CollectionType.Movies)) + if (string.Equals(viewType, CollectionType.Movies, StringComparison.Ordinal)) { includeItemTypes = new string[] { "Movie" }; } - else if (string.Equals(viewType, CollectionType.TvShows)) + else if (string.Equals(viewType, CollectionType.TvShows, StringComparison.Ordinal)) { includeItemTypes = new string[] { "Series" }; } - else if (string.Equals(viewType, CollectionType.Music)) + else if (string.Equals(viewType, CollectionType.Music, StringComparison.Ordinal)) { includeItemTypes = new string[] { "MusicAlbum" }; } - else if (string.Equals(viewType, CollectionType.Books)) + else if (string.Equals(viewType, CollectionType.Books, StringComparison.Ordinal)) { includeItemTypes = new string[] { "Book", "AudioBook" }; } - else if (string.Equals(viewType, CollectionType.BoxSets)) + else if (string.Equals(viewType, CollectionType.BoxSets, StringComparison.Ordinal)) { includeItemTypes = new string[] { "BoxSet" }; } - else if (string.Equals(viewType, CollectionType.HomeVideos) || string.Equals(viewType, CollectionType.Photos)) + else if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.Ordinal) || string.Equals(viewType, CollectionType.Photos, StringComparison.Ordinal)) { includeItemTypes = new string[] { "Video", "Photo" }; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 13fb8b2fd..6a2983d9b 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -287,14 +287,14 @@ namespace Emby.Server.Implementations.Library if (item is IItemByName) { - if (!(item is MusicArtist)) + if (item is not MusicArtist) { return; } } else if (!item.IsFolder) { - if (!(item is Video) && !(item is LiveTvChannel)) + if (item is not Video && item is not LiveTvChannel) { return; } @@ -866,7 +866,7 @@ namespace Emby.Server.Implementations.Library { var path = Person.GetPath(name); var id = GetItemByNameId(path); - if (!(GetItemById(id) is Person item)) + if (GetItemById(id) is not Person item) { item = new Person { @@ -2118,7 +2118,7 @@ namespace Emby.Server.Implementations.Library public LibraryOptions GetLibraryOptions(BaseItem item) { - if (!(item is CollectionFolder collectionFolder)) + if (item is not CollectionFolder collectionFolder) { // List.Find is more performant than FirstOrDefault due to enumerator allocation collectionFolder = GetCollectionFolders(item) diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index e893d6335..fd9747b4b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -21,11 +21,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// public class AudioResolver : ItemResolver, IMultiItemResolver { - private readonly ILibraryManager LibraryManager; + private readonly ILibraryManager _libraryManager; public AudioResolver(ILibraryManager libraryManager) { - LibraryManager = libraryManager; + _libraryManager = libraryManager; } /// @@ -88,13 +88,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio } var files = args.FileSystemChildren - .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .Where(i => !_libraryManager.IgnoreFile(i, args.Parent)) .ToList(); return FindAudio(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); } - if (LibraryManager.IsAudioFile(args.Path)) + if (_libraryManager.IsAudioFile(args.Path)) { var extension = Path.GetExtension(args.Path); @@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var isMixedCollectionType = string.IsNullOrEmpty(collectionType); // For conflicting extensions, give priority to videos - if (isMixedCollectionType && LibraryManager.IsVideoFile(args.Path)) + if (isMixedCollectionType && _libraryManager.IsVideoFile(args.Path)) { return null; } @@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio } } - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); + var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); var resolver = new AudioBookListResolver(namingOptions); var resolverResult = resolver.Resolve(files).ToList(); diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index cdb492022..e00332808 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// Resolves a Path into a Video or Video subclass. /// - /// + /// The type of item to resolve. public abstract class BaseVideoResolver : MediaBrowser.Controller.Resolvers.ItemResolver where T : Video, new() { @@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library.Resolvers break; } - if (IsBluRayDirectory(child.FullName, filename, args.DirectoryService)) + if (IsBluRayDirectory(filename)) { videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); @@ -279,25 +279,13 @@ namespace Emby.Server.Implementations.Library.Resolvers } /// - /// Determines whether [is blu ray directory] [the specified directory name]. + /// Determines whether [is bluray directory] [the specified directory name]. /// - protected bool IsBluRayDirectory(string fullPath, string directoryName, IDirectoryService directoryService) + /// The directory name. + /// Whether the directory is a bluray directory. + protected bool IsBluRayDirectory(string directoryName) { - if (!string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - return true; - // var blurayExtensions = new[] - //{ - // ".mts", - // ".m2ts", - // ".bdmv", - // ".mpls" - //}; - - // return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)); + return string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs new file mode 100644 index 000000000..9599faea4 --- /dev/null +++ b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs @@ -0,0 +1,18 @@ +#nullable disable + +#pragma warning disable CS1591 + +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; + +namespace Emby.Server.Implementations.Library.Resolvers +{ + public class GenericVideoResolver : BaseVideoResolver + where T : Video, new() + { + public GenericVideoResolver(ILibraryManager libraryManager) + : base(libraryManager) + { + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs index fa45ccf84..3f29ab191 100644 --- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs @@ -9,7 +9,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// Class ItemResolver. /// - /// + /// The type of BaseItem. public abstract class ItemResolver : IItemResolver where T : BaseItem, new() { diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 889e29a6b..8b55a7744 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -400,7 +400,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return movie; } - if (IsBluRayDirectory(child.FullName, filename, directoryService)) + if (IsBluRayDirectory(filename)) { var movie = new T { @@ -481,7 +481,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return true; } - if (subfolders.Any(s => IsBluRayDirectory(s.FullName, s.Name, directoryService))) + if (subfolders.Any(s => IsBluRayDirectory(s.Name))) { videoTypes.Add(VideoType.BluRay); return true; diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index ecd44be47..2c4ead719 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -18,7 +18,8 @@ namespace Emby.Server.Implementations.Library.Resolvers /// public class PlaylistResolver : FolderResolver { - private string[] _musicPlaylistCollectionTypes = new string[] { + private string[] _musicPlaylistCollectionTypes = + { string.Empty, CollectionType.Music }; diff --git a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs deleted file mode 100644 index 9599faea4..000000000 --- a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ /dev/null @@ -1,18 +0,0 @@ -#nullable disable - -#pragma warning disable CS1591 - -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; - -namespace Emby.Server.Implementations.Library.Resolvers -{ - public class GenericVideoResolver : BaseVideoResolver - where T : Video, new() - { - public GenericVideoResolver(ILibraryManager libraryManager) - : base(libraryManager) - { - } - } -} diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs index 9a8c5f39d..16bdf720c 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -87,12 +87,15 @@ namespace Emby.Server.Implementations.Library.Validators foreach (var item in deadEntities) { - _logger.LogInformation("Deleting dead {2} {0} {1}.", item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name, item.GetType().Name); + _logger.LogInformation("Deleting dead {ItemType} {ItemId} {ItemName}", item.Id.ToString("N", CultureInfo.InvariantCulture), item.Name, item.GetType().Name); - _libraryManager.DeleteItem(item, new DeleteOptions + _libraryManager.DeleteItem( + item, + new DeleteOptions { DeleteFileLocation = false - }, false); + }, + false); } progress.Report(100); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 797063120..a6be40745 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1458,7 +1458,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (item.GetType() == typeof(Folder) && string.Equals(item.Path, parentPath, StringComparison.OrdinalIgnoreCase)) { var parentItem = item.GetParent(); - if (parentItem != null && !(parentItem is AggregateFolder)) + if (parentItem != null && parentItem is not AggregateFolder) { item = parentItem; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs index 0ec52a959..20a8213a7 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs @@ -8,7 +8,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { internal class EpgChannelData { - private readonly Dictionary _channelsById; private readonly Dictionary _channelsByNumber; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index b7639a51c..bcfc4011c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -14,6 +14,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos; using MediaBrowser.Common; using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; @@ -96,12 +97,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings var dates = GetScheduleRequestDates(startDateUtc, endDateUtc); _logger.LogInformation("Channel Station ID is: {ChannelID}", channelId); - var requestList = new List() + var requestList = new List() { - new ScheduleDirect.RequestScheduleForChannel() + new RequestScheduleForChannelDto() { - stationID = channelId, - date = dates + StationId = channelId, + Date = dates } }; @@ -113,61 +114,61 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Headers.TryAddWithoutValidation("token", token); using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false); await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var dailySchedules = await JsonSerializer.DeserializeAsync>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var dailySchedules = await JsonSerializer.DeserializeAsync>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs"); programRequestOptions.Headers.TryAddWithoutValidation("token", token); - var programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct(); + var programsID = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct(); programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json); using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false); await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var programDetails = await JsonSerializer.DeserializeAsync>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); - var programDict = programDetails.ToDictionary(p => p.programID, y => y); + var programDetails = await JsonSerializer.DeserializeAsync>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var programDict = programDetails.ToDictionary(p => p.ProgramId, y => y); var programIdsWithImages = programDetails - .Where(p => p.hasImageArtwork).Select(p => p.programID) + .Where(p => p.HasImageArtwork).Select(p => p.ProgramId) .ToList(); var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken).ConfigureAwait(false); var programsInfo = new List(); - foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs)) + foreach (ProgramDto schedule in dailySchedules.SelectMany(d => d.Programs)) { // _logger.LogDebug("Proccesing Schedule for statio ID " + stationID + // " which corresponds to channel " + channelNumber + " and program id " + - // schedule.programID + " which says it has images? " + - // programDict[schedule.programID].hasImageArtwork); + // schedule.ProgramId + " which says it has images? " + + // programDict[schedule.ProgramId].hasImageArtwork); if (images != null) { - var imageIndex = images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10)); + var imageIndex = images.FindIndex(i => i.ProgramId == schedule.ProgramId[..10]); if (imageIndex > -1) { - var programEntry = programDict[schedule.programID]; + var programEntry = programDict[schedule.ProgramId]; - var allImages = images[imageIndex].data ?? new List(); - var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)); - var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase)); + var allImages = images[imageIndex].Data ?? new List(); + var imagesWithText = allImages.Where(i => string.Equals(i.Text, "yes", StringComparison.OrdinalIgnoreCase)); + var imagesWithoutText = allImages.Where(i => string.Equals(i.Text, "no", StringComparison.OrdinalIgnoreCase)); const double DesiredAspect = 2.0 / 3; - programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ?? + programEntry.PrimaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ?? GetProgramImage(ApiUrl, allImages, true, DesiredAspect); const double WideAspect = 16.0 / 9; - programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect); + programEntry.ThumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect); // Don't supply the same image twice - if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal)) + if (string.Equals(programEntry.PrimaryImage, programEntry.ThumbImage, StringComparison.Ordinal)) { - programEntry.thumbImage = null; + programEntry.ThumbImage = null; } - programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); + programEntry.BackdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); // programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? // GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? @@ -176,15 +177,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID])); + programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.ProgramId])); } return programsInfo; } - private static int GetSizeOrder(ScheduleDirect.ImageData image) + private static int GetSizeOrder(ImageDataDto image) { - if (int.TryParse(image.height, out int value)) + if (int.TryParse(image.Height, out int value)) { return value; } @@ -192,53 +193,53 @@ namespace Emby.Server.Implementations.LiveTv.Listings return 0; } - private static string GetChannelNumber(ScheduleDirect.Map map) + private static string GetChannelNumber(MapDto map) { - var channelNumber = map.logicalChannelNumber; + var channelNumber = map.LogicalChannelNumber; if (string.IsNullOrWhiteSpace(channelNumber)) { - channelNumber = map.channel; + channelNumber = map.Channel; } if (string.IsNullOrWhiteSpace(channelNumber)) { - channelNumber = map.atscMajor + "." + map.atscMinor; + channelNumber = map.AtscMajor + "." + map.AtscMinor; } return channelNumber.TrimStart('0'); } - private static bool IsMovie(ScheduleDirect.ProgramDetails programInfo) + private static bool IsMovie(ProgramDetailsDto programInfo) { - return string.Equals(programInfo.entityType, "movie", StringComparison.OrdinalIgnoreCase); + return string.Equals(programInfo.EntityType, "movie", StringComparison.OrdinalIgnoreCase); } - private ProgramInfo GetProgram(string channelId, ScheduleDirect.Program programInfo, ScheduleDirect.ProgramDetails details) + private ProgramInfo GetProgram(string channelId, ProgramDto programInfo, ProgramDetailsDto details) { - var startAt = GetDate(programInfo.airDateTime); - var endAt = startAt.AddSeconds(programInfo.duration); + var startAt = GetDate(programInfo.AirDateTime); + var endAt = startAt.AddSeconds(programInfo.Duration); var audioType = ProgramAudio.Stereo; - var programId = programInfo.programID ?? string.Empty; + var programId = programInfo.ProgramId ?? string.Empty; string newID = programId + "T" + startAt.Ticks + "C" + channelId; - if (programInfo.audioProperties != null) + if (programInfo.AudioProperties != null) { - if (programInfo.audioProperties.Exists(item => string.Equals(item, "atmos", StringComparison.OrdinalIgnoreCase))) + if (programInfo.AudioProperties.Exists(item => string.Equals(item, "atmos", StringComparison.OrdinalIgnoreCase))) { audioType = ProgramAudio.Atmos; } - else if (programInfo.audioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase))) + else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase))) { audioType = ProgramAudio.DolbyDigital; } - else if (programInfo.audioProperties.Exists(item => string.Equals(item, "dd", StringComparison.OrdinalIgnoreCase))) + else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "dd", StringComparison.OrdinalIgnoreCase))) { audioType = ProgramAudio.DolbyDigital; } - else if (programInfo.audioProperties.Exists(item => string.Equals(item, "stereo", StringComparison.OrdinalIgnoreCase))) + else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "stereo", StringComparison.OrdinalIgnoreCase))) { audioType = ProgramAudio.Stereo; } @@ -249,9 +250,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings } string episodeTitle = null; - if (details.episodeTitle150 != null) + if (details.EpisodeTitle150 != null) { - episodeTitle = details.episodeTitle150; + episodeTitle = details.EpisodeTitle150; } var info = new ProgramInfo @@ -260,22 +261,22 @@ namespace Emby.Server.Implementations.LiveTv.Listings Id = newID, StartDate = startAt, EndDate = endAt, - Name = details.titles[0].title120 ?? "Unknown", + Name = details.Titles[0].Title120 ?? "Unknown", OfficialRating = null, CommunityRating = null, EpisodeTitle = episodeTitle, Audio = audioType, // IsNew = programInfo.@new ?? false, - IsRepeat = programInfo.@new == null, - IsSeries = string.Equals(details.entityType, "episode", StringComparison.OrdinalIgnoreCase), - ImageUrl = details.primaryImage, - ThumbImageUrl = details.thumbImage, - IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase), - IsSports = string.Equals(details.entityType, "sports", StringComparison.OrdinalIgnoreCase), + IsRepeat = programInfo.New == null, + IsSeries = string.Equals(details.EntityType, "episode", StringComparison.OrdinalIgnoreCase), + ImageUrl = details.PrimaryImage, + ThumbImageUrl = details.ThumbImage, + IsKids = string.Equals(details.Audience, "children", StringComparison.OrdinalIgnoreCase), + IsSports = string.Equals(details.EntityType, "sports", StringComparison.OrdinalIgnoreCase), 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 + Etag = programInfo.Md5, + IsLive = string.Equals(programInfo.LiveTapeDelay, "live", StringComparison.OrdinalIgnoreCase), + IsPremiere = programInfo.Premiere || (programInfo.IsPremiereOrFinale ?? string.Empty).IndexOf("premiere", StringComparison.OrdinalIgnoreCase) != -1 }; var showId = programId; @@ -298,15 +299,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings info.ShowId = showId; - if (programInfo.videoProperties != null) + if (programInfo.VideoProperties != null) { - info.IsHD = programInfo.videoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase); - info.Is3D = programInfo.videoProperties.Contains("3d", StringComparer.OrdinalIgnoreCase); + info.IsHD = programInfo.VideoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase); + info.Is3D = programInfo.VideoProperties.Contains("3d", StringComparer.OrdinalIgnoreCase); } - if (details.contentRating != null && details.contentRating.Count > 0) + if (details.ContentRating != null && details.ContentRating.Count > 0) { - info.OfficialRating = details.contentRating[0].code.Replace("TV", "TV-", StringComparison.Ordinal) + info.OfficialRating = details.ContentRating[0].Code.Replace("TV", "TV-", StringComparison.Ordinal) .Replace("--", "-", StringComparison.Ordinal); var invalid = new[] { "N/A", "Approved", "Not Rated", "Passed" }; @@ -316,15 +317,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - if (details.descriptions != null) + if (details.Descriptions != null) { - if (details.descriptions.description1000 != null && details.descriptions.description1000.Count > 0) + if (details.Descriptions.Description1000 != null && details.Descriptions.Description1000.Count > 0) { - info.Overview = details.descriptions.description1000[0].description; + info.Overview = details.Descriptions.Description1000[0].Description; } - else if (details.descriptions.description100 != null && details.descriptions.description100.Count > 0) + else if (details.Descriptions.Description100 != null && details.Descriptions.Description100.Count > 0) { - info.Overview = details.descriptions.description100[0].description; + info.Overview = details.Descriptions.Description100[0].Description; } } @@ -334,18 +335,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings info.SeriesProviderIds[MetadataProvider.Zap2It.ToString()] = info.SeriesId; - if (details.metadata != null) + if (details.Metadata != null) { - foreach (var metadataProgram in details.metadata) + foreach (var metadataProgram in details.Metadata) { var gracenote = metadataProgram.Gracenote; if (gracenote != null) { - info.SeasonNumber = gracenote.season; + info.SeasonNumber = gracenote.Season; - if (gracenote.episode > 0) + if (gracenote.Episode > 0) { - info.EpisodeNumber = gracenote.episode; + info.EpisodeNumber = gracenote.Episode; } break; @@ -354,25 +355,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - if (!string.IsNullOrWhiteSpace(details.originalAirDate)) + if (!string.IsNullOrWhiteSpace(details.OriginalAirDate)) { - info.OriginalAirDate = DateTime.Parse(details.originalAirDate, CultureInfo.InvariantCulture); + info.OriginalAirDate = DateTime.Parse(details.OriginalAirDate, CultureInfo.InvariantCulture); info.ProductionYear = info.OriginalAirDate.Value.Year; } - if (details.movie != null) + if (details.Movie != null) { - if (!string.IsNullOrEmpty(details.movie.year) - && int.TryParse(details.movie.year, out int year)) + if (!string.IsNullOrEmpty(details.Movie.Year) + && int.TryParse(details.Movie.Year, out int year)) { info.ProductionYear = year; } } - if (details.genres != null) + if (details.Genres != null) { - info.Genres = details.genres.Where(g => !string.IsNullOrWhiteSpace(g)).ToList(); - info.IsNews = details.genres.Contains("news", StringComparer.OrdinalIgnoreCase); + info.Genres = details.Genres.Where(g => !string.IsNullOrWhiteSpace(g)).ToList(); + info.IsNews = details.Genres.Contains("news", StringComparer.OrdinalIgnoreCase); if (info.Genres.Contains("children", StringComparer.OrdinalIgnoreCase)) { @@ -395,11 +396,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings return date; } - private string GetProgramImage(string apiUrl, IEnumerable images, bool returnDefaultImage, double desiredAspect) + private string GetProgramImage(string apiUrl, IEnumerable images, bool returnDefaultImage, double desiredAspect) { var match = images .OrderBy(i => Math.Abs(desiredAspect - GetAspectRatio(i))) - .ThenByDescending(GetSizeOrder) + .ThenByDescending(i => GetSizeOrder(i)) .FirstOrDefault(); if (match == null) @@ -407,7 +408,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings return null; } - var uri = match.uri; + var uri = match.Uri; if (string.IsNullOrWhiteSpace(uri)) { @@ -423,19 +424,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - private static double GetAspectRatio(ScheduleDirect.ImageData i) + private static double GetAspectRatio(ImageDataDto i) { int width = 0; int height = 0; - if (!string.IsNullOrWhiteSpace(i.width)) + if (!string.IsNullOrWhiteSpace(i.Width)) { - int.TryParse(i.width, out width); + _ = int.TryParse(i.Width, out width); } - if (!string.IsNullOrWhiteSpace(i.height)) + if (!string.IsNullOrWhiteSpace(i.Height)) { - int.TryParse(i.height, out height); + _ = int.TryParse(i.Height, out height); } if (height == 0 || width == 0) @@ -448,14 +449,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings return result; } - private async Task> GetImageForPrograms( + private async Task> GetImageForPrograms( ListingsProviderInfo info, IReadOnlyList programIds, CancellationToken cancellationToken) { if (programIds.Count == 0) { - return new List(); + return new List(); } StringBuilder str = new StringBuilder("[", 1 + (programIds.Count * 13)); @@ -479,13 +480,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings { using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false); await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - return await JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); + return await JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "Error getting image info from schedules direct"); - return new List(); + return new List(); } } @@ -508,18 +509,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false); await using var response = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); + var root = await JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); if (root != null) { - foreach (ScheduleDirect.Headends headend in root) + foreach (HeadendsDto headend in root) { - foreach (ScheduleDirect.Lineup lineup in headend.lineups) + foreach (LineupDto lineup in headend.Lineups) { lineups.Add(new NameIdPair { - Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, - Id = lineup.uri.Substring(18) + Name = string.IsNullOrWhiteSpace(lineup.Name) ? lineup.Lineup : lineup.Name, + Id = lineup.Uri[18..] }); } } @@ -649,14 +650,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - if (string.Equals(root.message, "OK", StringComparison.Ordinal)) + var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + if (string.Equals(root.Message, "OK", StringComparison.Ordinal)) { - _logger.LogInformation("Authenticated with Schedules Direct token: " + root.token); - return root.token; + _logger.LogInformation("Authenticated with Schedules Direct token: {Token}", root.Token); + return root.Token; } - throw new Exception("Could not authenticate with Schedules Direct Error: " + root.message); + throw new Exception("Could not authenticate with Schedules Direct Error: " + root.Message); } private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -705,9 +706,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings httpResponse.EnsureSuccessStatusCode(); await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var response = httpResponse.Content; - var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase)); + return root.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase)); } catch (HttpRequestException ex) { @@ -777,35 +778,35 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false); await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count); + var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.Map.Count); _logger.LogInformation("Mapping Stations to Channel"); - var allStations = root.stations ?? new List(); + var allStations = root.Stations ?? new List(); - var map = root.map; + var map = root.Map; var list = new List(map.Count); foreach (var channel in map) { var channelNumber = GetChannelNumber(channel); - var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)) - ?? new ScheduleDirect.Station + var station = allStations.Find(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase)) + ?? new StationDto { - stationID = channel.stationID + StationId = channel.StationId }; var channelInfo = new ChannelInfo { - Id = station.stationID, - CallSign = station.callsign, + Id = station.StationId, + CallSign = station.Callsign, Number = channelNumber, - Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name + Name = string.IsNullOrWhiteSpace(station.Name) ? channelNumber : station.Name }; - if (station.logo != null) + if (station.Logo != null) { - channelInfo.ImageUrl = station.logo.URL; + channelInfo.ImageUrl = station.Logo.Url; } list.Add(channelInfo); @@ -818,402 +819,5 @@ namespace Emby.Server.Implementations.LiveTv.Listings { return value.Replace(" ", string.Empty, StringComparison.Ordinal).Replace("-", string.Empty, StringComparison.Ordinal); } - - public class ScheduleDirect - { - public class Token - { - public int code { get; set; } - - public string message { get; set; } - - public string serverID { get; set; } - - public string token { get; set; } - } - - public class Lineup - { - public string lineup { get; set; } - - public string name { get; set; } - - public string transport { get; set; } - - public string location { get; set; } - - public string uri { get; set; } - } - - public class Lineups - { - public int code { get; set; } - - public string serverID { get; set; } - - public string datetime { get; set; } - - public List lineups { get; set; } - } - - public class Headends - { - public string headend { get; set; } - - public string transport { get; set; } - - public string location { get; set; } - - public List lineups { get; set; } - } - - public class Map - { - public string stationID { get; set; } - - public string channel { get; set; } - - public string logicalChannelNumber { get; set; } - - public int uhfVhf { get; set; } - - public int atscMajor { get; set; } - - public int atscMinor { get; set; } - } - - public class Broadcaster - { - public string city { get; set; } - - public string state { get; set; } - - public string postalcode { get; set; } - - public string country { get; set; } - } - - public class Logo - { - public string URL { get; set; } - - public int height { get; set; } - - public int width { get; set; } - - public string md5 { get; set; } - } - - public class Station - { - public string stationID { get; set; } - - public string name { get; set; } - - public string callsign { get; set; } - - public List broadcastLanguage { get; set; } - - public List descriptionLanguage { get; set; } - - public Broadcaster broadcaster { get; set; } - - public string affiliate { get; set; } - - public Logo logo { get; set; } - - public bool? isCommercialFree { get; set; } - } - - public class Metadata - { - public string lineup { get; set; } - - public string modified { get; set; } - - public string transport { get; set; } - } - - public class Channel - { - public List map { get; set; } - - public List stations { get; set; } - - public Metadata metadata { get; set; } - } - - public class RequestScheduleForChannel - { - public string stationID { get; set; } - - public List date { get; set; } - } - - public class Rating - { - public string body { get; set; } - - public string code { get; set; } - } - - public class Multipart - { - public int partNumber { get; set; } - - public int totalParts { get; set; } - } - - public class Program - { - public string programID { get; set; } - - public string airDateTime { get; set; } - - public int duration { get; set; } - - public string md5 { get; set; } - - public List audioProperties { get; set; } - - public List videoProperties { get; set; } - - public List ratings { get; set; } - - public bool? @new { get; set; } - - public Multipart multipart { get; set; } - - public string liveTapeDelay { get; set; } - - public bool premiere { get; set; } - - public bool repeat { get; set; } - - public string isPremiereOrFinale { get; set; } - } - - public class MetadataSchedule - { - public string modified { get; set; } - - public string md5 { get; set; } - - public string startDate { get; set; } - - public string endDate { get; set; } - - public int days { get; set; } - } - - public class Day - { - public string stationID { get; set; } - - public List programs { get; set; } - - public MetadataSchedule metadata { get; set; } - - public Day() - { - programs = new List(); - } - } - - public class Title - { - public string title120 { get; set; } - } - - public class EventDetails - { - public string subType { get; set; } - } - - public class Description100 - { - public string descriptionLanguage { get; set; } - - public string description { get; set; } - } - - public class Description1000 - { - public string descriptionLanguage { get; set; } - - public string description { get; set; } - } - - public class DescriptionsProgram - { - public List description100 { get; set; } - - public List description1000 { get; set; } - } - - public class Gracenote - { - public int season { get; set; } - - public int episode { get; set; } - } - - public class MetadataPrograms - { - public Gracenote Gracenote { get; set; } - } - - public class ContentRating - { - public string body { get; set; } - - public string code { get; set; } - } - - public class Cast - { - public string billingOrder { get; set; } - - public string role { get; set; } - - public string nameId { get; set; } - - public string personId { get; set; } - - public string name { get; set; } - - public string characterName { get; set; } - } - - public class Crew - { - public string billingOrder { get; set; } - - public string role { get; set; } - - public string nameId { get; set; } - - public string personId { get; set; } - - public string name { get; set; } - } - - public class QualityRating - { - public string ratingsBody { get; set; } - - public string rating { get; set; } - - public string minRating { get; set; } - - public string maxRating { get; set; } - - public string increment { get; set; } - } - - public class Movie - { - public string year { get; set; } - - public int duration { get; set; } - - public List qualityRating { get; set; } - } - - public class Recommendation - { - public string programID { get; set; } - - public string title120 { get; set; } - } - - public class ProgramDetails - { - public string audience { get; set; } - - public string programID { get; set; } - - public List titles { get; set; } - - public EventDetails eventDetails { get; set; } - - public DescriptionsProgram descriptions { get; set; } - - public string originalAirDate { get; set; } - - public List<string> genres { get; set; } - - public string episodeTitle150 { get; set; } - - public List<MetadataPrograms> metadata { get; set; } - - public List<ContentRating> contentRating { get; set; } - - public List<Cast> cast { get; set; } - - public List<Crew> crew { get; set; } - - public string entityType { get; set; } - - public string showType { get; set; } - - public bool hasImageArtwork { get; set; } - - public string primaryImage { get; set; } - - public string thumbImage { get; set; } - - public string backdropImage { get; set; } - - public string bannerImage { get; set; } - - public string imageID { get; set; } - - public string md5 { get; set; } - - public List<string> contentAdvisory { get; set; } - - public Movie movie { get; set; } - - public List<Recommendation> recommendations { get; set; } - } - - public class Caption - { - public string content { get; set; } - - public string lang { get; set; } - } - - public class ImageData - { - public string width { get; set; } - - public string height { get; set; } - - public string uri { get; set; } - - public string size { get; set; } - - public string aspect { get; set; } - - public string category { get; set; } - - public string text { get; set; } - - public string primary { get; set; } - - public string tier { get; set; } - - public Caption caption { get; set; } - } - - public class ShowImages - { - public string programID { get; set; } - - public List<ImageData> data { get; set; } - } - } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs new file mode 100644 index 000000000..b881b307c --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs @@ -0,0 +1,36 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Broadcaster dto. + /// </summary> + public class BroadcasterDto + { + /// <summary> + /// Gets or sets the city. + /// </summary> + [JsonPropertyName("city")] + public string City { get; set; } + + /// <summary> + /// Gets or sets the state. + /// </summary> + [JsonPropertyName("state")] + public string State { get; set; } + + /// <summary> + /// Gets or sets the postal code. + /// </summary> + [JsonPropertyName("postalCode")] + public string Postalcode { get; set; } + + /// <summary> + /// Gets or sets the country. + /// </summary> + [JsonPropertyName("country")] + public string Country { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs new file mode 100644 index 000000000..96b67d1eb --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Caption dto. + /// </summary> + public class CaptionDto + { + /// <summary> + /// Gets or sets the content. + /// </summary> + [JsonPropertyName("content")] + public string Content { get; set; } + + /// <summary> + /// Gets or sets the lang. + /// </summary> + [JsonPropertyName("lang")] + public string Lang { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs new file mode 100644 index 000000000..dac6f5f3e --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs @@ -0,0 +1,48 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Cast dto. + /// </summary> + public class CastDto + { + /// <summary> + /// Gets or sets the billing order. + /// </summary> + [JsonPropertyName("billingOrder")] + public string BillingOrder { get; set; } + + /// <summary> + /// Gets or sets the role. + /// </summary> + [JsonPropertyName("role")] + public string Role { get; set; } + + /// <summary> + /// Gets or sets the name id. + /// </summary> + [JsonPropertyName("nameId")] + public string NameId { get; set; } + + /// <summary> + /// Gets or sets the person id. + /// </summary> + [JsonPropertyName("personId")] + public string PersonId { get; set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + [JsonPropertyName("name")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the character name. + /// </summary> + [JsonPropertyName("characterName")] + public string CharacterName { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs new file mode 100644 index 000000000..8c9c2c1fc --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs @@ -0,0 +1,31 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Channel dto. + /// </summary> + public class ChannelDto + { + /// <summary> + /// Gets or sets the list of maps. + /// </summary> + [JsonPropertyName("map")] + public List<MapDto> Map { get; set; } + + /// <summary> + /// Gets or sets the list of stations. + /// </summary> + [JsonPropertyName("stations")] + public List<StationDto> Stations { get; set; } + + /// <summary> + /// Gets or sets the metadata. + /// </summary> + [JsonPropertyName("metadata")] + public MetadataDto Metadata { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs new file mode 100644 index 000000000..135b5bb08 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Content rating dto. + /// </summary> + public class ContentRatingDto + { + /// <summary> + /// Gets or sets the body. + /// </summary> + [JsonPropertyName("body")] + public string Body { get; set; } + + /// <summary> + /// Gets or sets the code. + /// </summary> + [JsonPropertyName("code")] + public string Code { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs new file mode 100644 index 000000000..82d1001c8 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs @@ -0,0 +1,42 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Crew dto. + /// </summary> + public class CrewDto + { + /// <summary> + /// Gets or sets the billing order. + /// </summary> + [JsonPropertyName("billingOrder")] + public string BillingOrder { get; set; } + + /// <summary> + /// Gets or sets the role. + /// </summary> + [JsonPropertyName("role")] + public string Role { get; set; } + + /// <summary> + /// Gets or sets the name id. + /// </summary> + [JsonPropertyName("nameId")] + public string NameId { get; set; } + + /// <summary> + /// Gets or sets the person id. + /// </summary> + [JsonPropertyName("personId")] + public string PersonId { get; set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + [JsonPropertyName("name")] + public string Name { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs new file mode 100644 index 000000000..68876b068 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs @@ -0,0 +1,39 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Day dto. + /// </summary> + public class DayDto + { + /// <summary> + /// Initializes a new instance of the <see cref="DayDto"/> class. + /// </summary> + public DayDto() + { + Programs = new List<ProgramDto>(); + } + + /// <summary> + /// Gets or sets the station id. + /// </summary> + [JsonPropertyName("stationID")] + public string StationId { get; set; } + + /// <summary> + /// Gets or sets the list of programs. + /// </summary> + [JsonPropertyName("programs")] + public List<ProgramDto> Programs { get; set; } + + /// <summary> + /// Gets or sets the metadata schedule. + /// </summary> + [JsonPropertyName("metadata")] + public MetadataScheduleDto Metadata { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs new file mode 100644 index 000000000..d3e6ff393 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Description 1_000 dto. + /// </summary> + public class Description1000Dto + { + /// <summary> + /// Gets or sets the description language. + /// </summary> + [JsonPropertyName("descriptionLanguage")] + public string DescriptionLanguage { get; set; } + + /// <summary> + /// Gets or sets the description. + /// </summary> + [JsonPropertyName("description")] + public string Description { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs new file mode 100644 index 000000000..04360266c --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Description 100 dto. + /// </summary> + public class Description100Dto + { + /// <summary> + /// Gets or sets the description language. + /// </summary> + [JsonPropertyName("descriptionLanguage")] + public string DescriptionLanguage { get; set; } + + /// <summary> + /// Gets or sets the description. + /// </summary> + [JsonPropertyName("description")] + public string Description { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs new file mode 100644 index 000000000..3af36ae96 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs @@ -0,0 +1,25 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Descriptions program dto. + /// </summary> + public class DescriptionsProgramDto + { + /// <summary> + /// Gets or sets the list of description 100. + /// </summary> + [JsonPropertyName("description100")] + public List<Description100Dto> Description100 { get; set; } + + /// <summary> + /// Gets or sets the list of description1000. + /// </summary> + [JsonPropertyName("description1000")] + public List<Description1000Dto> Description1000 { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs new file mode 100644 index 000000000..c3b2bd9c1 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs @@ -0,0 +1,18 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Event details dto. + /// </summary> + public class EventDetailsDto + { + /// <summary> + /// Gets or sets the sub type. + /// </summary> + [JsonPropertyName("subType")] + public string SubType { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs new file mode 100644 index 000000000..3d8bea362 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Gracenote dto. + /// </summary> + public class GracenoteDto + { + /// <summary> + /// Gets or sets the season. + /// </summary> + [JsonPropertyName("season")] + public int Season { get; set; } + + /// <summary> + /// Gets or sets the episode. + /// </summary> + [JsonPropertyName("episode")] + public int Episode { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs new file mode 100644 index 000000000..1fb3decb2 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs @@ -0,0 +1,37 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Headends dto. + /// </summary> + public class HeadendsDto + { + /// <summary> + /// Gets or sets the headend. + /// </summary> + [JsonPropertyName("headend")] + public string Headend { get; set; } + + /// <summary> + /// Gets or sets the transport. + /// </summary> + [JsonPropertyName("transport")] + public string Transport { get; set; } + + /// <summary> + /// Gets or sets the location. + /// </summary> + [JsonPropertyName("location")] + public string Location { get; set; } + + /// <summary> + /// Gets or sets the list of lineups. + /// </summary> + [JsonPropertyName("lineups")] + public List<LineupDto> Lineups { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs new file mode 100644 index 000000000..b80ac624c --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs @@ -0,0 +1,69 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + public class ImageDataDto + { + /// <summary> + /// Gets or sets the width. + /// </summary> + [JsonPropertyName("width")] + public string Width { get; set; } + + /// <summary> + /// Gets or sets the height. + /// </summary> + [JsonPropertyName("height")] + public string Height { get; set; } + + /// <summary> + /// Gets or sets the uri. + /// </summary> + [JsonPropertyName("uri")] + public string Uri { get; set; } + + /// <summary> + /// Gets or sets the size. + /// </summary> + [JsonPropertyName("size")] + public string Size { get; set; } + + /// <summary> + /// Gets or sets the aspect. + /// </summary> + [JsonPropertyName("aspect")] + public string aspect { get; set; } + + /// <summary> + /// Gets or sets the category. + /// </summary> + [JsonPropertyName("category")] + public string Category { get; set; } + + /// <summary> + /// Gets or sets the text. + /// </summary> + [JsonPropertyName("text")] + public string Text { get; set; } + + /// <summary> + /// Gets or sets the primary. + /// </summary> + [JsonPropertyName("primary")] + public string Primary { get; set; } + + /// <summary> + /// Gets or sets the tier. + /// </summary> + [JsonPropertyName("tier")] + public string Tier { get; set; } + + /// <summary> + /// Gets or sets the caption. + /// </summary> + [JsonPropertyName("caption")] + public CaptionDto Caption { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs new file mode 100644 index 000000000..b8f27a8ac --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs @@ -0,0 +1,42 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// The lineup dto. + /// </summary> + public class LineupDto + { + /// <summary> + /// Gets or sets the linup. + /// </summary> + [JsonPropertyName("lineup")] + public string Lineup { get; set; } + + /// <summary> + /// Gets or sets the lineup name. + /// </summary> + [JsonPropertyName("name")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the transport. + /// </summary> + [JsonPropertyName("transport.")] + public string Transport { get; set; } + + /// <summary> + /// Gets or sets the location. + /// </summary> + [JsonPropertyName("location")] + public string Location { get; set; } + + /// <summary> + /// Gets or sets the uri. + /// </summary> + [JsonPropertyName("uri")] + public string Uri { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs new file mode 100644 index 000000000..15139ba3b --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs @@ -0,0 +1,37 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Lineups dto. + /// </summary> + public class LineupsDto + { + /// <summary> + /// Gets or sets the response code. + /// </summary> + [JsonPropertyName("code")] + public int Code { get; set; } + + /// <summary> + /// Gets or sets the server id. + /// </summary> + [JsonPropertyName("serverID")] + public string ServerId { get; set; } + + /// <summary> + /// Gets or sets the datetime. + /// </summary> + [JsonPropertyName("datetime")] + public string Datetime { get; set; } + + /// <summary> + /// Gets or sets the list of lineups. + /// </summary> + [JsonPropertyName("lineups")] + public List<LineupDto> Lineups { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs new file mode 100644 index 000000000..7b235ed7f --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs @@ -0,0 +1,36 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Logo dto. + /// </summary> + public class LogoDto + { + /// <summary> + /// Gets or sets the url. + /// </summary> + [JsonPropertyName("URL")] + public string Url { get; set; } + + /// <summary> + /// Gets or sets the height. + /// </summary> + [JsonPropertyName("height")] + public int Height { get; set; } + + /// <summary> + /// Gets or sets the width. + /// </summary> + [JsonPropertyName("width")] + public int Width { get; set; } + + /// <summary> + /// Gets or sets the md5. + /// </summary> + [JsonPropertyName("md5")] + public string Md5 { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs new file mode 100644 index 000000000..8d45e8fff --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs @@ -0,0 +1,48 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Map dto. + /// </summary> + public class MapDto + { + /// <summary> + /// Gets or sets the station id. + /// </summary> + [JsonPropertyName("stationID")] + public string StationId { get; set; } + + /// <summary> + /// Gets or sets the channel. + /// </summary> + [JsonPropertyName("channel")] + public string Channel { get; set; } + + /// <summary> + /// Gets or sets the logical channel number. + /// </summary> + [JsonPropertyName("logicalChannelNumber")] + public string LogicalChannelNumber { get; set; } + + /// <summary> + /// Gets or sets the uhfvhf. + /// </summary> + [JsonPropertyName("uhfVhf")] + public int UhfVhf { get; set; } + + /// <summary> + /// Gets or sets the astc major. + /// </summary> + [JsonPropertyName("astcMajor")] + public int AtscMajor { get; set; } + + /// <summary> + /// Gets or sets the astc minor. + /// </summary> + [JsonPropertyName("astcMinor")] + public int AtscMinor { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs new file mode 100644 index 000000000..5a3893a35 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs @@ -0,0 +1,30 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Metadata dto. + /// </summary> + public class MetadataDto + { + /// <summary> + /// Gets or sets the linup. + /// </summary> + [JsonPropertyName("lineup")] + public string Lineup { get; set; } + + /// <summary> + /// Gets or sets the modified timestamp. + /// </summary> + [JsonPropertyName("modified")] + public string Modified { get; set; } + + /// <summary> + /// Gets or sets the transport. + /// </summary> + [JsonPropertyName("transport")] + public string Transport { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs new file mode 100644 index 000000000..4057e9802 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs @@ -0,0 +1,18 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Metadata programs dto. + /// </summary> + public class MetadataProgramsDto + { + /// <summary> + /// Gets or sets the gracenote object. + /// </summary> + [JsonPropertyName("gracenote")] + public GracenoteDto Gracenote { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs new file mode 100644 index 000000000..4979296da --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs @@ -0,0 +1,42 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Metadata schedule dto. + /// </summary> + public class MetadataScheduleDto + { + /// <summary> + /// Gets or sets the modified timestamp. + /// </summary> + [JsonPropertyName("modified")] + public string Modified { get; set; } + + /// <summary> + /// Gets or sets the md5. + /// </summary> + [JsonPropertyName("md5")] + public string Md5 { get; set; } + + /// <summary> + /// Gets or sets the start date. + /// </summary> + [JsonPropertyName("startDate")] + public string StartDate { get; set; } + + /// <summary> + /// Gets or sets the end date. + /// </summary> + [JsonPropertyName("endDate")] + public string EndDate { get; set; } + + /// <summary> + /// Gets or sets the days count. + /// </summary> + [JsonPropertyName("days")] + public int Days { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs new file mode 100644 index 000000000..48d731d89 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs @@ -0,0 +1,31 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Movie dto. + /// </summary> + public class MovieDto + { + /// <summary> + /// Gets or sets the year. + /// </summary> + [JsonPropertyName("year")] + public string Year { get; set; } + + /// <summary> + /// Gets or sets the duration. + /// </summary> + [JsonPropertyName("duration")] + public int Duration { get; set; } + + /// <summary> + /// Gets or sets the list of quality rating. + /// </summary> + [JsonPropertyName("qualityRating")] + public List<QualityRatingDto> QualityRating { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs new file mode 100644 index 000000000..42eddfff2 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Multipart dto. + /// </summary> + public class MultipartDto + { + /// <summary> + /// Gets or sets the part number. + /// </summary> + [JsonPropertyName("partNumber")] + public int PartNumber { get; set; } + + /// <summary> + /// Gets or sets the total parts. + /// </summary> + [JsonPropertyName("totalParts")] + public int TotalParts { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs new file mode 100644 index 000000000..a84c47c12 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs @@ -0,0 +1,157 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Program details dto. + /// </summary> + public class ProgramDetailsDto + { + /// <summary> + /// Gets or sets the audience. + /// </summary> + [JsonPropertyName("audience")] + public string Audience { get; set; } + + /// <summary> + /// Gets or sets the program id. + /// </summary> + [JsonPropertyName("programID")] + public string ProgramId { get; set; } + + /// <summary> + /// Gets or sets the list of titles. + /// </summary> + [JsonPropertyName("titles")] + public List<TitleDto> Titles { get; set; } + + /// <summary> + /// Gets or sets the event details object. + /// </summary> + [JsonPropertyName("eventDetails")] + public EventDetailsDto EventDetails { get; set; } + + /// <summary> + /// Gets or sets the descriptions. + /// </summary> + [JsonPropertyName("descriptions")] + public DescriptionsProgramDto Descriptions { get; set; } + + /// <summary> + /// Gets or sets the original air date. + /// </summary> + [JsonPropertyName("originalAirDate")] + public string OriginalAirDate { get; set; } + + /// <summary> + /// Gets or sets the list of genres. + /// </summary> + [JsonPropertyName("genres")] + public List<string> Genres { get; set; } + + /// <summary> + /// Gets or sets the episode title. + /// </summary> + [JsonPropertyName("episodeTitle150")] + public string EpisodeTitle150 { get; set; } + + /// <summary> + /// Gets or sets the list of metadata. + /// </summary> + [JsonPropertyName("metadata")] + public List<MetadataProgramsDto> Metadata { get; set; } + + /// <summary> + /// Gets or sets the list of content raitings. + /// </summary> + [JsonPropertyName("contentRating")] + public List<ContentRatingDto> ContentRating { get; set; } + + /// <summary> + /// Gets or sets the list of cast. + /// </summary> + [JsonPropertyName("cast")] + public List<CastDto> Cast { get; set; } + + /// <summary> + /// Gets or sets the list of crew. + /// </summary> + [JsonPropertyName("crew")] + public List<CrewDto> Crew { get; set; } + + /// <summary> + /// Gets or sets the entity type. + /// </summary> + [JsonPropertyName("entityType")] + public string EntityType { get; set; } + + /// <summary> + /// Gets or sets the show type. + /// </summary> + [JsonPropertyName("showType")] + public string ShowType { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether there is image artwork. + /// </summary> + [JsonPropertyName("hasImageArtwork")] + public bool HasImageArtwork { get; set; } + + /// <summary> + /// Gets or sets the primary image. + /// </summary> + [JsonPropertyName("primaryImage")] + public string PrimaryImage { get; set; } + + /// <summary> + /// Gets or sets the thumb image. + /// </summary> + [JsonPropertyName("thumbImage")] + public string ThumbImage { get; set; } + + /// <summary> + /// Gets or sets the backdrop image. + /// </summary> + [JsonPropertyName("backdropImage")] + public string BackdropImage { get; set; } + + /// <summary> + /// Gets or sets the banner image. + /// </summary> + [JsonPropertyName("bannerImage")] + public string BannerImage { get; set; } + + /// <summary> + /// Gets or sets the image id. + /// </summary> + [JsonPropertyName("imageID")] + public string ImageId { get; set; } + + /// <summary> + /// Gets or sets the md5. + /// </summary> + [JsonPropertyName("md5")] + public string Md5 { get; set; } + + /// <summary> + /// Gets or sets the list of content advisory. + /// </summary> + [JsonPropertyName("contentAdvisory")] + public List<string> ContentAdvisory { get; set; } + + /// <summary> + /// Gets or sets the movie object. + /// </summary> + [JsonPropertyName("movie")] + public MovieDto Movie { get; set; } + + /// <summary> + /// Gets or sets the list of recommendations. + /// </summary> + [JsonPropertyName("recommendations")] + public List<RecommendationDto> Recommendations { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs new file mode 100644 index 000000000..ad5389100 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs @@ -0,0 +1,91 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Program dto. + /// </summary> + public class ProgramDto + { + /// <summary> + /// Gets or sets the program id. + /// </summary> + [JsonPropertyName("programID")] + public string ProgramId { get; set; } + + /// <summary> + /// Gets or sets the air date time. + /// </summary> + [JsonPropertyName("airDateTime")] + public string AirDateTime { get; set; } + + /// <summary> + /// Gets or sets the duration. + /// </summary> + [JsonPropertyName("duration")] + public int Duration { get; set; } + + /// <summary> + /// Gets or sets the md5. + /// </summary> + [JsonPropertyName("md5")] + public string Md5 { get; set; } + + /// <summary> + /// Gets or sets the list of audio properties. + /// </summary> + [JsonPropertyName("audioProperties")] + public List<string> AudioProperties { get; set; } + + /// <summary> + /// Gets or sets the list of video properties. + /// </summary> + [JsonPropertyName("videoProperties")] + public List<string> VideoProperties { get; set; } + + /// <summary> + /// Gets or sets the list of ratings. + /// </summary> + [JsonPropertyName("ratings")] + public List<RatingDto> Ratings { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this program is new. + /// </summary> + [JsonPropertyName("new")] + public bool? New { get; set; } + + /// <summary> + /// Gets or sets the multipart object. + /// </summary> + [JsonPropertyName("multipart")] + public MultipartDto Multipart { get; set; } + + /// <summary> + /// Gets or sets the live tape delay. + /// </summary> + [JsonPropertyName("liveTapeDelay")] + public string LiveTapeDelay { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this is the premiere. + /// </summary> + [JsonPropertyName("premiere")] + public bool Premiere { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this is a repeat. + /// </summary> + [JsonPropertyName("repeat")] + public bool Repeat { get; set; } + + /// <summary> + /// Gets or sets the premiere or finale. + /// </summary> + [JsonPropertyName("isPremiereOrFinale")] + public string IsPremiereOrFinale { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs new file mode 100644 index 000000000..5cd0a7459 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs @@ -0,0 +1,42 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Quality rating dto. + /// </summary> + public class QualityRatingDto + { + /// <summary> + /// Gets or sets the ratings body. + /// </summary> + [JsonPropertyName("ratingsBody")] + public string RatingsBody { get; set; } + + /// <summary> + /// Gets or sets the rating. + /// </summary> + [JsonPropertyName("rating")] + public string Rating { get; set; } + + /// <summary> + /// Gets or sets the min rating. + /// </summary> + [JsonPropertyName("minRating")] + public string MinRating { get; set; } + + /// <summary> + /// Gets or sets the max rating. + /// </summary> + [JsonPropertyName("maxRating")] + public string MaxRating { get; set; } + + /// <summary> + /// Gets or sets the increment. + /// </summary> + [JsonPropertyName("increment")] + public string Increment { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs new file mode 100644 index 000000000..948b83144 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Rating dto. + /// </summary> + public class RatingDto + { + /// <summary> + /// Gets or sets the body. + /// </summary> + [JsonPropertyName("body")] + public string Body { get; set; } + + /// <summary> + /// Gets or sets the code. + /// </summary> + [JsonPropertyName("code")] + public string Code { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs new file mode 100644 index 000000000..1308f45ce --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs @@ -0,0 +1,24 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Recommendation dto. + /// </summary> + public class RecommendationDto + { + /// <summary> + /// Gets or sets the program id. + /// </summary> + [JsonPropertyName("programID")] + public string ProgramId { get; set; } + + /// <summary> + /// Gets or sets the title. + /// </summary> + [JsonPropertyName("title120")] + public string Title120 { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs new file mode 100644 index 000000000..fb7a31ac8 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs @@ -0,0 +1,25 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Request schedule for channel dto. + /// </summary> + public class RequestScheduleForChannelDto + { + /// <summary> + /// Gets or sets the station id. + /// </summary> + [JsonPropertyName("stationID")] + public string StationId { get; set; } + + /// <summary> + /// Gets or sets the list of dates. + /// </summary> + [JsonPropertyName("date")] + public List<string> Date { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs new file mode 100644 index 000000000..332edf7c3 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs @@ -0,0 +1,22 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + public class ShowImagesDto + { + /// <summary> + /// Gets or sets the program id. + /// </summary> + [JsonPropertyName("programID")] + public string ProgramId { get; set; } + + /// <summary> + /// Gets or sets the list of data. + /// </summary> + [JsonPropertyName("data")] + public List<ImageDataDto> Data { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs new file mode 100644 index 000000000..12f3576c6 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs @@ -0,0 +1,67 @@ +#nullable disable + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Station dto. + /// </summary> + public class StationDto + { + /// <summary> + /// Gets or sets the station id. + /// </summary> + [JsonPropertyName("stationID")] + public string StationId { get; set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + [JsonPropertyName("name")] + public string Name { get; set; } + + /// <summary> + /// Gets or sets the callsign. + /// </summary> + [JsonPropertyName("callsign")] + public string Callsign { get; set; } + + /// <summary> + /// Gets or sets the broadcast language. + /// </summary> + [JsonPropertyName("broadcastLanguage")] + public List<string> BroadcastLanguage { get; set; } + + /// <summary> + /// Gets or sets the description language. + /// </summary> + [JsonPropertyName("descriptionLanguage")] + public List<string> DescriptionLanguage { get; set; } + + /// <summary> + /// Gets or sets the broadcaster. + /// </summary> + [JsonPropertyName("broadcaster")] + public BroadcasterDto Broadcaster { get; set; } + + /// <summary> + /// Gets or sets the affiliate. + /// </summary> + [JsonPropertyName("affiliate")] + public string Affiliate { get; set; } + + /// <summary> + /// Gets or sets the logo. + /// </summary> + [JsonPropertyName("logo")] + public LogoDto Logo { get; set; } + + /// <summary> + /// Gets or set a value indicating whether it is commercial free. + /// </summary> + [JsonPropertyName("isCommercialFree")] + public bool? IsCommercialFree { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs new file mode 100644 index 000000000..06c95524b --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs @@ -0,0 +1,18 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// Title dto. + /// </summary> + public class TitleDto + { + /// <summary> + /// Gets or sets the title. + /// </summary> + [JsonPropertyName("title120")] + public string Title120 { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs new file mode 100644 index 000000000..c3ec1c7d6 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs @@ -0,0 +1,36 @@ +#nullable disable + +using System.Text.Json.Serialization; + +namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos +{ + /// <summary> + /// The token dto. + /// </summary> + public class TokenDto + { + /// <summary> + /// Gets or sets the response code. + /// </summary> + [JsonPropertyName("code")] + public int Code { get; set; } + + /// <summary> + /// Gets or sets the response message. + /// </summary> + [JsonPropertyName("message")] + public string Message { get; set; } + + /// <summary> + /// Gets or sets the server id. + /// </summary> + [JsonPropertyName("serverID")] + public string ServerId { get; set; } + + /// <summary> + /// Gets or sets the token. + /// </summary> + [JsonPropertyName("token")] + public string Token { get; set; } + } +} diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index d964769b5..ce585d0fb 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -403,7 +403,7 @@ namespace Emby.Server.Implementations.LiveTv // Set the total bitrate if not already supplied mediaSource.InferTotalBitrate(); - if (!(service is EmbyTV.EmbyTV)) + if (service is not EmbyTV.EmbyTV) { // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says // mediaSource.SupportsDirectPlay = false; @@ -1724,7 +1724,7 @@ namespace Emby.Server.Implementations.LiveTv await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); - if (!(service is EmbyTV.EmbyTV)) + if (service is not EmbyTV.EmbyTV) { TimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>(new TimerEventInfo(id))); } @@ -2050,7 +2050,7 @@ namespace Emby.Server.Implementations.LiveTv _logger.LogInformation("New recording scheduled"); - if (!(service is EmbyTV.EmbyTV)) + if (service is not EmbyTV.EmbyTV) { TimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>( new TimerEventInfo(newTimerId) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 3016eeda2..b2e555c7d 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -27,6 +27,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { private string _channel; private string _program; + public LegacyHdHomerunChannelCommands(string url) { // parse url for channel and program diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 8cafde38e..b07798fa4 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -260,7 +260,7 @@ namespace Emby.Server.Implementations.Playlists public async Task RemoveFromPlaylistAsync(string playlistId, IEnumerable<string> entryIds) { - if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist)) + if (_libraryManager.GetItemById(playlistId) is not Playlist playlist) { throw new ArgumentException("No Playlist exists with the supplied Id"); } @@ -293,7 +293,7 @@ namespace Emby.Server.Implementations.Playlists public async Task MoveItemAsync(string playlistId, string entryId, int newIndex) { - if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist)) + if (_libraryManager.GetItemById(playlistId) is not Playlist playlist) { throw new ArgumentException("No Playlist exists with the supplied Id"); } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index b34325041..fb93c375d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -24,7 +24,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// </summary> public class ScheduledTaskWorker : IScheduledTaskWorker { - /// <summary> /// Gets or sets the application paths. /// </summary> @@ -267,7 +266,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// <summary> - /// Gets the triggers that define when the task will run. + /// Gets or sets the triggers that define when the task will run. /// </summary> /// <value>The triggers.</value> /// <exception cref="ArgumentNullException"><c>value</c> is <c>null</c>.</exception> diff --git a/Emby.Server.Implementations/Sorting/ArtistComparer.cs b/Emby.Server.Implementations/Sorting/ArtistComparer.cs index 98bee3fd9..7b7ba5753 100644 --- a/Emby.Server.Implementations/Sorting/ArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/ArtistComparer.cs @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.String.</returns> private static string? GetValue(BaseItem? x) { - if (!(x is Audio audio)) + if (x is not Audio audio) { return string.Empty; } diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index a9f4a5a58..64d7b2f3e 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -154,11 +154,11 @@ namespace Jellyfin.Api.Controllers }; if (!item.IsVirtualItem - && !(item is ICollectionFolder) - && !(item is UserView) - && !(item is AggregateFolder) - && !(item is LiveTvChannel) - && !(item is IItemByName) + && item is not ICollectionFolder + && item is not UserView + && item is not AggregateFolder + && item is not LiveTvChannel + && item is not IItemByName && item.SourceType == SourceType.Library) { var inheritedContentType = _libraryManager.GetInheritedContentType(item); diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 35c27dd0e..52eefc5c2 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -241,7 +241,7 @@ namespace Jellyfin.Api.Controllers var item = _libraryManager.GetParentItem(parentId, userId); QueryResult<BaseItem> result; - if (!(item is Folder folder)) + if (item is not Folder folder) { folder = _libraryManager.GetUserRootFolder(); } @@ -285,7 +285,7 @@ namespace Jellyfin.Api.Controllers return Unauthorized($"{user.Username} is not permitted to access Library {item.Name}."); } - if ((recursive.HasValue && recursive.Value) || ids.Length != 0 || !(item is UserRootFolder)) + if ((recursive.HasValue && recursive.Value) || ids.Length != 0 || item is not UserRootFolder) { var query = new InternalItemsQuery(user!) { diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 4ed15e1d5..8cc369a5c 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -700,7 +700,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.RootFolder) : _libraryManager.GetItemById(itemId); - if (item is Episode || (item is IItemByName && !(item is MusicArtist))) + if (item is Episode || (item is IItemByName && item is not MusicArtist)) { return new QueryResult<BaseItemDto>(); } diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index 51d40994e..7c5b8a43b 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -228,7 +228,7 @@ namespace Jellyfin.Api.Controllers if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. { var item = _libraryManager.GetItemById(seasonId.Value); - if (!(item is Season seasonItem)) + if (item is not Season seasonItem) { return NotFound("No season exists with Id " + seasonId); } @@ -237,7 +237,7 @@ namespace Jellyfin.Api.Controllers } else if (season.HasValue) // Season number was supplied. Get episodes by season number { - if (!(_libraryManager.GetItemById(seriesId) is Series series)) + if (_libraryManager.GetItemById(seriesId) is not Series series) { return NotFound("Series not found"); } @@ -252,7 +252,7 @@ namespace Jellyfin.Api.Controllers } else // No season number or season id was supplied. Returning all episodes. { - if (!(_libraryManager.GetItemById(seriesId) is Series series)) + if (_libraryManager.GetItemById(seriesId) is not Series series) { return NotFound("Series not found"); } @@ -336,7 +336,7 @@ namespace Jellyfin.Api.Controllers ? _userManager.GetUserById(userId.Value) : null; - if (!(_libraryManager.GetItemById(seriesId) is Series series)) + if (_libraryManager.GetItemById(seriesId) is not Series series) { return NotFound("Series not found"); } diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 8cffe9c4c..5b14b6468 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -222,11 +222,7 @@ namespace Jellyfin.Api.Helpers { var resolution = ResolutionNormalizer.Normalize( state.VideoStream?.BitRate, - state.VideoStream?.Width, - state.VideoStream?.Height, state.OutputVideoBitrate.Value, - state.VideoStream?.Codec, - state.OutputVideoCodec, state.VideoRequest.MaxWidth, state.VideoRequest.MaxHeight); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 067fecd87..3b182f7c9 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.Entities private string _name; - public static char SlugChar = '-'; + public const char SlugChar = '-'; protected BaseItem() { @@ -2050,7 +2050,7 @@ namespace MediaBrowser.Controller.Entities public virtual string GetClientTypeName() { - if (IsFolder && SourceType == SourceType.Channel && !(this is Channel)) + if (IsFolder && SourceType == SourceType.Channel && this is not Channel) { return "ChannelFolderItem"; } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index d45a02cf2..dd08c31ed 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -233,7 +233,7 @@ namespace MediaBrowser.Controller.Entities public override bool IsVisible(User user) { - if (this is ICollectionFolder && !(this is BasePluginFolder)) + if (this is ICollectionFolder && this is not BasePluginFolder) { var blockedMediaFolders = user.GetPreferenceValues<Guid>(PreferenceKind.BlockedMediaFolders); if (blockedMediaFolders.Length > 0) @@ -673,7 +673,7 @@ namespace MediaBrowser.Controller.Entities { if (LinkedChildren.Length > 0) { - if (!(this is ICollectionFolder)) + if (this is not ICollectionFolder) { return GetChildren(user, true).Count; } @@ -730,7 +730,7 @@ namespace MediaBrowser.Controller.Entities return PostFilterAndSort(items, query, true); } - if (!(this is UserRootFolder) && !(this is AggregateFolder) && query.ParentId == Guid.Empty) + if (this is not UserRootFolder && this is not AggregateFolder && query.ParentId == Guid.Empty) { query.Parent = this; } @@ -805,7 +805,7 @@ namespace MediaBrowser.Controller.Entities { if (LinkedChildren.Length > 0) { - if (!(this is ICollectionFolder)) + if (this is not ICollectionFolder) { Logger.LogDebug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name); return true; @@ -1545,7 +1545,7 @@ namespace MediaBrowser.Controller.Entities var childOwner = child.GetOwner() ?? child; - if (childOwner != null && !(child is IItemByName)) + if (child is not IItemByName) { var childProtocol = childOwner.PathProtocol; if (!childProtocol.HasValue || childProtocol.Value != Model.MediaInfo.MediaProtocol.File) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index beda504b9..e4933e968 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -296,7 +296,7 @@ namespace MediaBrowser.Controller.Entities.TV // Refresh seasons foreach (var item in items) { - if (!(item is Season)) + if (item is not Season) { continue; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 141bb91c5..3e577ebb7 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -504,7 +504,9 @@ namespace MediaBrowser.Controller.MediaEncoding var arg = new StringBuilder(); var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty; var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty; +#pragma warning disable CA1508 // Defaults to string.Empty var isSwDecoder = string.IsNullOrEmpty(videoDecoder); +#pragma warning restore CA1508 var isD3d11vaDecoder = videoDecoder.IndexOf("d3d11va", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; @@ -1759,7 +1761,7 @@ namespace MediaBrowser.Controller.MediaEncoding var request = state.BaseRequest; - var inputChannels = audioStream?.Channels; + var inputChannels = audioStream.Channels; if (inputChannels <= 0) { @@ -2027,8 +2029,8 @@ namespace MediaBrowser.Controller.MediaEncoding { // Adjust the size of graphical subtitles to fit the video stream. var videoStream = state.VideoStream; - var inputWidth = videoStream?.Width; - var inputHeight = videoStream?.Height; + var inputWidth = videoStream.Width; + var inputHeight = videoStream.Height; var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); if (width.HasValue && height.HasValue) @@ -3101,7 +3103,7 @@ namespace MediaBrowser.Controller.MediaEncoding inputModifier += " " + videoDecoder; if (!IsCopyCodec(state.OutputVideoCodec) - && (videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1) + && videoDecoder.IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1) { var videoStream = state.VideoStream; var inputWidth = videoStream?.Width; @@ -3110,7 +3112,7 @@ namespace MediaBrowser.Controller.MediaEncoding var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); - if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1 + if (videoDecoder.IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1 && width.HasValue && height.HasValue) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index fa9f40d60..b09b7dba6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -422,7 +422,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (EncodingHelper.IsCopyCodec(OutputVideoCodec)) { - return VideoStream?.Codec; + return VideoStream.Codec; } return OutputVideoCodec; @@ -440,7 +440,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (EncodingHelper.IsCopyCodec(OutputAudioCodec)) { - return AudioStream?.Codec; + return AudioStream.Codec; } return OutputAudioCodec; @@ -568,7 +568,7 @@ namespace MediaBrowser.Controller.MediaEncoding } } - return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced; + return forceDeinterlaceIfSourceIsInterlaced; } public string[] GetRequestedProfiles(string codec) diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index 31475e22f..b7398880e 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -283,7 +283,7 @@ namespace MediaBrowser.LocalMetadata.Images { imageFileNames = _seriesImageFileNames; } - else if (item is Video && !(item is Episode)) + else if (item is Video && item is not Episode) { imageFileNames = _videoImageFileNames; } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index dd824206f..6a3896eb6 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -223,7 +223,7 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteElementString("CustomRating", item.CustomRating); } - if (!string.IsNullOrEmpty(item.Name) && !(item is Episode)) + if (!string.IsNullOrEmpty(item.Name) && item is not Episode) { writer.WriteElementString("LocalTitle", item.Name); } @@ -240,7 +240,7 @@ namespace MediaBrowser.LocalMetadata.Savers { writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); } - else if (!(item is Episode)) + else if (item is not Episode) { writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); } @@ -252,7 +252,7 @@ namespace MediaBrowser.LocalMetadata.Savers { writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); } - else if (!(item is Episode)) + else if (item is not Episode) { writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); } @@ -292,7 +292,7 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(_usCulture)); } - if (item.ProductionYear.HasValue && !(item is Person)) + if (item.ProductionYear.HasValue && item is not Person) { writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture)); } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfile.cs b/MediaBrowser.Model/Dlna/MediaFormatProfile.cs index 20e05b8a9..06f6660f4 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfile.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfile.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591, CA1707 namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs index 65fccbdd4..806877ff0 100644 --- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs +++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs @@ -21,11 +21,7 @@ namespace MediaBrowser.Model.Dlna public static ResolutionOptions Normalize( int? inputBitrate, - int? unused1, - int? unused2, int outputBitrate, - string inputCodec, - string outputCodec, int? maxWidth, int? maxHeight) { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index f4c69fe8f..635420a76 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -694,7 +694,7 @@ namespace MediaBrowser.Model.Dlna if (isEligibleForDirectPlay || isEligibleForDirectStream) { // See if it can be direct played - var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); + var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectStream); var directPlay = directPlayInfo.Item1; if (directPlay != null) @@ -810,7 +810,7 @@ namespace MediaBrowser.Model.Dlna // Honor requested max channels playlistItem.GlobalMaxAudioChannels = options.MaxAudioChannels; - int audioBitrate = GetAudioBitrate(playlistItem.SubProtocol, options.GetMaxBitrate(false) ?? 0, playlistItem.TargetAudioCodec, audioStream, playlistItem); + int audioBitrate = GetAudioBitrate(options.GetMaxBitrate(false) ?? 0, playlistItem.TargetAudioCodec, audioStream, playlistItem); playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); isFirstAppliedCodecProfile = true; @@ -907,7 +907,7 @@ namespace MediaBrowser.Model.Dlna return 192000; } - private static int GetAudioBitrate(string subProtocol, long maxTotalBitrate, string[] targetAudioCodecs, MediaStream audioStream, StreamInfo item) + private static int GetAudioBitrate(long maxTotalBitrate, string[] targetAudioCodecs, MediaStream audioStream, StreamInfo item) { string targetAudioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; @@ -1005,7 +1005,6 @@ namespace MediaBrowser.Model.Dlna MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream, - bool isEligibleForDirectPlay, bool isEligibleForDirectStream) { if (options.ForceDirectPlay) @@ -1146,7 +1145,7 @@ namespace MediaBrowser.Model.Dlna { string audioCodec = audioStream.Codec; conditions = new List<ProfileCondition>(); - bool? isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream); + bool? isSecondaryAudio = mediaSource.IsSecondaryAudio(audioStream); foreach (var i in profile.CodecProfiles) { @@ -1262,7 +1261,7 @@ namespace MediaBrowser.Model.Dlna continue; } - if (playMethod == PlayMethod.Transcode && !IsSubtitleEmbedSupported(subtitleStream, profile, transcodingSubProtocol, outputContainer)) + if (playMethod == PlayMethod.Transcode && !IsSubtitleEmbedSupported(outputContainer)) { continue; } @@ -1291,7 +1290,7 @@ namespace MediaBrowser.Model.Dlna continue; } - if (playMethod == PlayMethod.Transcode && !IsSubtitleEmbedSupported(subtitleStream, profile, transcodingSubProtocol, outputContainer)) + if (playMethod == PlayMethod.Transcode && !IsSubtitleEmbedSupported(outputContainer)) { continue; } @@ -1313,7 +1312,7 @@ namespace MediaBrowser.Model.Dlna }; } - private static bool IsSubtitleEmbedSupported(MediaStream subtitleStream, SubtitleProfile subtitleProfile, string transcodingSubProtocol, string transcodingContainer) + private static bool IsSubtitleEmbedSupported(string transcodingContainer) { if (!string.IsNullOrEmpty(transcodingContainer)) { @@ -1728,18 +1727,14 @@ namespace MediaBrowser.Model.Dlna continue; } - if (!string.IsNullOrEmpty(value)) - { - // change from split by | to comma - - // strip spaces to avoid having to encode - var values = value - .Split('|', StringSplitOptions.RemoveEmptyEntries); + // change from split by | to comma + // strip spaces to avoid having to encode + var values = value + .Split('|', StringSplitOptions.RemoveEmptyEntries); - if (condition.Condition == ProfileConditionType.Equals || condition.Condition == ProfileConditionType.EqualsAny) - { - item.SetOption(qualifier, "profile", string.Join(',', values)); - } + if (condition.Condition == ProfileConditionType.Equals || condition.Condition == ProfileConditionType.EqualsAny) + { + item.SetOption(qualifier, "profile", string.Join(',', values)); } break; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 252872847..432c1c1d6 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -636,7 +636,7 @@ namespace MediaBrowser.Model.Dlna continue; } - var encodedValue = pair.Value.Replace(" ", "%20"); + var encodedValue = pair.Value.Replace(" ", "%20", StringComparison.Ordinal); list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 9653a8ece..de9fe6ff6 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -261,7 +261,7 @@ namespace MediaBrowser.Model.Entities foreach (var tag in attributes) { // Keep Tags that are not already in Title. - if (Title.IndexOf(tag, StringComparison.OrdinalIgnoreCase) == -1) + if (!Title.Contains(tag, StringComparison.OrdinalIgnoreCase)) { result.Append(" - ").Append(tag); } diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index be4f1e16b..0f77d6b5b 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -51,7 +51,7 @@ namespace MediaBrowser.Model.IO /// <returns>A <see cref="FileSystemMetadata" /> object.</returns> /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata" /> object's /// <see cref="FileSystemMetadata.IsDirectory" /> property and the <see cref="FileSystemMetadata.Exists" /> property will both be set to false.</para> - /// <para>For automatic handling of files <b>and</b> directories, use <see cref="M:IFileSystem.GetFileSystemInfo(System.String)" />.</para></remarks> + /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo(string)" />.</para></remarks> FileSystemMetadata GetFileInfo(string path); /// <summary> @@ -61,7 +61,7 @@ namespace MediaBrowser.Model.IO /// <returns>A <see cref="FileSystemMetadata" /> object.</returns> /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata" /> object's /// <see cref="FileSystemMetadata.IsDirectory" /> property will be set to true and the <see cref="FileSystemMetadata.Exists" /> property will be set to false.</para> - /// <para>For automatic handling of files <b>and</b> directories, use <see cref="M:IFileSystem.GetFileSystemInfo(System.String)" />.</para></remarks> + /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo(string)" />.</para></remarks> FileSystemMetadata GetDirectoryInfo(string path); /// <summary> diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index fb1d4f490..7d259a9d3 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Providers.Manager throw new ArgumentNullException(nameof(mimeType)); } - var saveLocally = item.SupportsLocalMetadata && item.IsSaveLocalMetadataEnabled() && !item.ExtraType.HasValue && !(item is Audio); + var saveLocally = item.SupportsLocalMetadata && item.IsSaveLocalMetadataEnabled() && !item.ExtraType.HasValue && item is not Audio; if (type != ImageType.Primary && item is Episode) { diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 607fd127b..cc4c75d7d 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Providers.Manager { var hasChanges = false; - if (!(item is Photo)) + if (item is not Photo) { var images = providers.OfType<ILocalImageProvider>() .SelectMany(i => i.GetImages(item, directoryService)) @@ -529,7 +529,7 @@ namespace MediaBrowser.Providers.Manager return true; } - if (item is IItemByName && !(item is MusicArtist)) + if (item is IItemByName && item is not MusicArtist) { var hasDualAccess = item as IHasDualAccess; if (hasDualAccess == null || hasDualAccess.IsAccessedByName) diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 3a42eb4c1..ab8d3a2a6 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -584,7 +584,7 @@ namespace MediaBrowser.Providers.Manager protected virtual IEnumerable<IImageProvider> GetNonLocalImageProviders(BaseItem item, IEnumerable<IImageProvider> allImageProviders, ImageRefreshOptions options) { // Get providers to refresh - var providers = allImageProviders.Where(i => !(i is ILocalImageProvider)); + var providers = allImageProviders.Where(i => i is not ILocalImageProvider); var dateLastImageRefresh = item.DateLastRefreshed; @@ -729,7 +729,7 @@ namespace MediaBrowser.Providers.Manager refreshResult.Failures += remoteResult.Failures; } - if (providers.Any(i => !(i is ICustomMetadataProvider))) + if (providers.Any(i => i is not ICustomMetadataProvider)) { if (refreshResult.UpdateType > ItemUpdateType.None) { @@ -748,7 +748,7 @@ namespace MediaBrowser.Providers.Manager // var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0; - foreach (var provider in customProviders.Where(i => !(i is IPreRefreshProvider))) + foreach (var provider in customProviders.Where(i => i is not IPreRefreshProvider)) { await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 2dfaa372c..7e60eced0 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -323,7 +323,7 @@ namespace MediaBrowser.Providers.Manager .OrderBy(i => { // See if there's a user-defined order - if (!(i is ILocalImageProvider)) + if (i is not ILocalImageProvider) { var fetcherOrder = typeFetcherOrder ?? currentOptions.ImageFetcherOrder; var index = Array.IndexOf(fetcherOrder, i.Name); @@ -390,7 +390,7 @@ namespace MediaBrowser.Providers.Manager if (!includeDisabled) { // If locked only allow local providers - if (item.IsLocked && !(provider is ILocalMetadataProvider) && !(provider is IForcedProvider)) + if (item.IsLocked && provider is not ILocalMetadataProvider && provider is not IForcedProvider) { return false; } @@ -431,7 +431,7 @@ namespace MediaBrowser.Providers.Manager if (!includeDisabled) { // If locked only allow local providers - if (item.IsLocked && !(provider is ILocalImageProvider)) + if (item.IsLocked && provider is not ILocalImageProvider) { if (refreshOptions.ImageRefreshMode != MetadataRefreshMode.FullRefresh) { @@ -466,7 +466,7 @@ namespace MediaBrowser.Providers.Manager /// <returns>System.Int32.</returns> private int GetOrder(IImageProvider provider) { - if (!(provider is IHasOrder hasOrder)) + if (provider is not IHasOrder hasOrder) { return 0; } @@ -745,7 +745,7 @@ namespace MediaBrowser.Providers.Manager { // Manual edit occurred // Even if save local is off, save locally anyway if the metadata file already exists - if (!(saver is IMetadataFileSaver fileSaver) || !File.Exists(fileSaver.GetSavePath(item))) + if (saver is not IMetadataFileSaver fileSaver || !File.Exists(fileSaver.GetSavePath(item))) { return false; } diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index aceba2215..6d088e6e7 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -135,7 +135,7 @@ namespace MediaBrowser.Providers.Manager { if (replaceData || !target.RunTimeTicks.HasValue) { - if (!(target is Audio) && !(target is Video)) + if (target is not Audio && target is not Video) { target.RunTimeTicks = source.RunTimeTicks; } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 3be35e2d9..38726a6f0 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -555,7 +555,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } // Series xml saver already saves this - if (!(item is Series)) + if (item is not Series) { var tvdb = item.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdb)) @@ -582,7 +582,7 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("countrycode", item.PreferredMetadataCountryCode); } - if (item.PremiereDate.HasValue && !(item is Episode)) + if (item.PremiereDate.HasValue && item is not Episode) { var formatString = options.ReleaseDateFormat; @@ -605,7 +605,7 @@ namespace MediaBrowser.XbmcMetadata.Savers if (item.EndDate.HasValue) { - if (!(item is Episode)) + if (item is not Episode) { var formatString = options.ReleaseDateFormat; diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs index 412e8031b..21e7e2335 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } // Check parent for null to avoid running this against things like video backdrops - if (item is Video video && !(item is Episode) && !video.ExtraType.HasValue) + if (item is Video video && item is not Episode && !video.ExtraType.HasValue) { return updateType >= MinimumUpdateType; } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs index b9d73ba82..e97550630 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs @@ -52,7 +52,7 @@ namespace MediaBrowser.XbmcMetadata.Savers return false; } - if (!(item is Season)) + if (item is not Season) { return false; } -- cgit v1.2.3 From 963ab2dab6a8c4dafadae61312b36ed5fbb1f323 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sun, 4 Apr 2021 23:02:28 +0200 Subject: Simplify the way we choose our ffmpeg * no longer search $PATH * no longer require a full path * don't fall back --- Emby.Server.Implementations/ApplicationHost.cs | 1 - .../MediaEncoding/IMediaEncoder.cs | 6 -- .../Encoder/EncoderValidator.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 107 ++++++--------------- MediaBrowser.Model/System/SystemInfo.cs | 1 + .../EncoderValidatorTests.cs | 8 +- 6 files changed, 38 insertions(+), 89 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bf7ddace2..0b5322f39 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1099,7 +1099,6 @@ namespace Emby.Server.Implementations ServerName = FriendlyName, LocalAddress = GetSmartApiUrl(source), SupportsLibraryMonitor = true, - EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, PackageName = _startupOptions.PackageName }; diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index ff2456070..63308fa09 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -10,7 +10,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.System; namespace MediaBrowser.Controller.MediaEncoding { @@ -19,11 +18,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// </summary> public interface IMediaEncoder : ITranscoderSupport { - /// <summary> - /// Gets location of the discovered FFmpeg tool. - /// </summary> - FFmpegLocation EncoderLocation { get; } - /// <summary> /// Gets the encoder path. /// </summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f782e65bd..ef831ab82 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -12,8 +12,6 @@ namespace MediaBrowser.MediaEncoding.Encoder { public class EncoderValidator { - private const string DefaultEncoderPath = "ffmpeg"; - private static readonly string[] _requiredDecoders = new[] { "h264", @@ -106,7 +104,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly string _encoderPath; - public EncoderValidator(ILogger logger, string encoderPath = DefaultEncoderPath) + public EncoderValidator(ILogger logger, string encoderPath) { _logger = logger; _encoderPath = encoderPath; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 412a95321..f8ba78e46 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -23,7 +23,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -69,7 +68,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private string _ffmpegPath = string.Empty; private string _ffprobePath; - private int threads; + private int _threads; public MediaEncoder( ILogger<MediaEncoder> logger, @@ -89,9 +88,6 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <inheritdoc /> public string EncoderPath => _ffmpegPath; - /// <inheritdoc /> - public FFmpegLocation EncoderLocation { get; private set; } - /// <summary> /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. @@ -100,20 +96,23 @@ namespace MediaBrowser.MediaEncoding.Encoder public void SetFFmpegPath() { // 1) Custom path stored in config/encoding xml file under tag <EncoderAppPath> takes precedence - if (!ValidatePath(_configurationManager.GetEncodingOptions().EncoderAppPath, FFmpegLocation.Custom)) + var ffmpegPath = _configurationManager.GetEncodingOptions().EncoderAppPath; + if (string.IsNullOrEmpty(ffmpegPath)) { // 2) Check if the --ffmpeg CLI switch has been given - if (!ValidatePath(_startupOptionFFmpegPath, FFmpegLocation.SetByArgument)) + ffmpegPath = _startupOptionFFmpegPath; + if (string.IsNullOrEmpty(ffmpegPath)) { - // 3) Search system $PATH environment variable for valid FFmpeg - if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) - { - EncoderLocation = FFmpegLocation.NotFound; - _ffmpegPath = null; - } + // 3) Check "ffmpeg" + ffmpegPath = "ffmpeg"; } } + if (!ValidatePath(ffmpegPath)) + { + _ffmpegPath = null; + } + // Write the FFmpeg path to the config/encoding.xml file as <EncoderAppPathDisplay> so it appears in UI var config = _configurationManager.GetEncodingOptions(); config.EncoderAppPathDisplay = _ffmpegPath ?? string.Empty; @@ -131,10 +130,10 @@ namespace MediaBrowser.MediaEncoding.Encoder SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); SetAvailableHwaccels(validator.GetHwaccels()); - threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null); + _threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null); } - _logger.LogInformation("FFmpeg: {EncoderLocation}: {FfmpegPath}", EncoderLocation, _ffmpegPath ?? string.Empty); + _logger.LogInformation("FFmpeg: {FfmpegPath}", _ffmpegPath ?? string.Empty); } /// <summary> @@ -153,15 +152,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { throw new ArgumentException("Unexpected pathType value"); } - else if (string.IsNullOrWhiteSpace(path)) + + if (string.IsNullOrWhiteSpace(path)) { // User had cleared the custom path in UI newPath = string.Empty; } - else if (File.Exists(path)) - { - newPath = path; - } else if (Directory.Exists(path)) { // Given path is directory, so resolve down to filename @@ -169,7 +165,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - throw new ResourceNotFoundException(); + newPath = path; } // Write the new ffmpeg path to the xml as <EncoderAppPath> @@ -184,37 +180,26 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Validates the supplied FQPN to ensure it is a ffmpeg utility. - /// If checks pass, global variable FFmpegPath and EncoderLocation are updated. + /// If checks pass, global variable FFmpegPath is updated. /// </summary> /// <param name="path">FQPN to test.</param> - /// <param name="location">Location (External, Custom, System) of tool.</param> /// <returns><c>true</c> if the version validation succeeded; otherwise, <c>false</c>.</returns> - private bool ValidatePath(string path, FFmpegLocation location) + private bool ValidatePath(string path) { - bool rc = false; - - if (!string.IsNullOrEmpty(path)) + if (string.IsNullOrEmpty(path)) { - if (File.Exists(path)) - { - rc = new EncoderValidator(_logger, path).ValidateVersion(); - - if (!rc) - { - _logger.LogWarning("FFmpeg: {Location}: Failed version check: {Path}", location, path); - } + return false; + } - _ffmpegPath = path; - EncoderLocation = location; - return true; - } - else - { - _logger.LogWarning("FFmpeg: {Location}: File not found: {Path}", location, path); - } + bool rc = new EncoderValidator(_logger, path).ValidateVersion(); + if (!rc) + { + _logger.LogWarning("FFmpeg: Failed version check: {Path}", path); + return false; } - return rc; + _ffmpegPath = path; + return true; } private string GetEncoderPathFromDirectory(string path, string filename, bool recursive = false) @@ -235,34 +220,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - /// <summary> - /// Search the system $PATH environment variable looking for given filename. - /// </summary> - /// <param name="fileName">The filename.</param> - /// <returns>The full path to the file.</returns> - private string ExistsOnSystemPath(string fileName) - { - var inJellyfinPath = GetEncoderPathFromDirectory(AppContext.BaseDirectory, fileName, recursive: true); - if (!string.IsNullOrEmpty(inJellyfinPath)) - { - return inJellyfinPath; - } - - var values = Environment.GetEnvironmentVariable("PATH"); - - foreach (var path in values.Split(Path.PathSeparator)) - { - var candidatePath = GetEncoderPathFromDirectory(path, fileName); - - if (!string.IsNullOrEmpty(candidatePath)) - { - return candidatePath; - } - } - - return null; - } - public void SetAvailableEncoders(IEnumerable<string> list) { _encoders = list.ToList(); @@ -394,7 +351,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = extractChapters ? "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_chapters -show_format" : "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_format"; - args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, threads).Trim(); + args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, _threads).Trim(); var process = new Process { @@ -615,7 +572,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, _threads); if (offset.HasValue) { @@ -728,7 +685,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, _threads); if (!string.IsNullOrWhiteSpace(container)) { diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index e45b2f33a..a82c1c8c0 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -133,6 +133,7 @@ namespace MediaBrowser.Model.System [Obsolete("This should be handled by the package manager")] public bool HasUpdateAvailable { get; set; } + [Obsolete("This isn't set correctly anymore")] public FFmpegLocation EncoderLocation { get; set; } public Architecture SystemArchitecture { get; set; } diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index 39fd8afda..cc429b442 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -9,12 +9,13 @@ namespace Jellyfin.MediaEncoding.Tests { public class EncoderValidatorTests { + private readonly EncoderValidator _encoderValidator = new EncoderValidator(new NullLogger<EncoderValidatorTests>(), "ffmpeg"); + [Theory] [ClassData(typeof(GetFFmpegVersionTestData))] public void GetFFmpegVersionTest(string versionOutput, Version? version) { - var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>()); - Assert.Equal(version, val.GetFFmpegVersion(versionOutput)); + Assert.Equal(version, _encoderValidator.GetFFmpegVersion(versionOutput)); } [Theory] @@ -28,8 +29,7 @@ namespace Jellyfin.MediaEncoding.Tests [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, false)] public void ValidateVersionInternalTest(string versionOutput, bool valid) { - var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>()); - Assert.Equal(valid, val.ValidateVersionInternal(versionOutput)); + Assert.Equal(valid, _encoderValidator.ValidateVersionInternal(versionOutput)); } private class GetFFmpegVersionTestData : IEnumerable<object?[]> -- cgit v1.2.3 From 637e86478f5cca7c8ac5e17cf541dc4c6adac14e Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Fri, 3 Sep 2021 18:46:34 +0200 Subject: Fix some warnings --- Emby.Server.Implementations/ApplicationHost.cs | 244 +++++++++------------ .../Collections/CollectionManager.cs | 4 +- .../Data/SqliteItemRepository.cs | 17 +- .../Data/SqliteUserDataRepository.cs | 47 ++-- Emby.Server.Implementations/Dto/DtoService.cs | 14 +- .../IO/ManagedFileSystem.cs | 6 +- .../Images/BaseDynamicImageProvider.cs | 2 +- .../Library/LibraryManager.cs | 22 +- .../Library/MusicManager.cs | 5 +- .../Library/Resolvers/BaseVideoResolver.cs | 4 +- .../Library/UserDataManager.cs | 4 +- .../LiveTv/EmbyTV/EmbyTV.cs | 26 +-- .../LiveTv/LiveTvManager.cs | 55 +++-- .../LiveTv/TunerHosts/BaseTunerHost.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 64 +++--- .../LiveTv/TunerHosts/M3UTunerHost.cs | 22 +- Emby.Server.Implementations/Net/SocketFactory.cs | 20 +- Emby.Server.Implementations/Net/UdpSocket.cs | 4 +- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 4 + .../Session/SessionManager.cs | 18 +- Emby.Server.Implementations/TV/TVSeriesManager.cs | 22 +- .../Entities/CollectionFolder.cs | 3 +- MediaBrowser.Controller/IServerApplicationHost.cs | 7 - MediaBrowser.Controller/Library/ILibraryManager.cs | 6 +- .../Library/IUserDataManager.cs | 6 +- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 +- MediaBrowser.Controller/LiveTv/ILiveTvService.cs | 4 +- .../Persistence/IItemRepository.cs | 8 +- MediaBrowser.Controller/Session/ISessionManager.cs | 2 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 85 +++---- jellyfin.ruleset | 6 + 31 files changed, 325 insertions(+), 410 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 39e59a073..3a504d2f4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -114,6 +114,11 @@ namespace Emby.Server.Implementations /// </summary> private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" }; + /// <summary> + /// The disposable parts. + /// </summary> + private readonly List<IDisposable> _disposableParts = new List<IDisposable>(); + private readonly IFileSystem _fileSystemManager; private readonly IConfiguration _startupConfig; private readonly IXmlSerializer _xmlSerializer; @@ -125,6 +130,62 @@ namespace Emby.Server.Implementations private ISessionManager _sessionManager; private string[] _urlPrefixes; + /// <summary> + /// Gets or sets all concrete types. + /// </summary> + /// <value>All concrete types.</value> + private Type[] _allConcreteTypes; + + private DeviceId _deviceId; + + private bool _disposed = false; + + /// <summary> + /// Initializes a new instance of the <see cref="ApplicationHost"/> class. + /// </summary> + /// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param> + /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> + /// <param name="options">Instance of the <see cref="IStartupOptions"/> interface.</param> + /// <param name="startupConfig">The <see cref="IConfiguration" /> interface.</param> + /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> + /// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param> + public ApplicationHost( + IServerApplicationPaths applicationPaths, + ILoggerFactory loggerFactory, + IStartupOptions options, + IConfiguration startupConfig, + IFileSystem fileSystem, + IServiceCollection serviceCollection) + { + ApplicationPaths = applicationPaths; + LoggerFactory = loggerFactory; + _startupOptions = options; + _startupConfig = startupConfig; + _fileSystemManager = fileSystem; + ServiceCollection = serviceCollection; + + Logger = LoggerFactory.CreateLogger<ApplicationHost>(); + fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); + + ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version; + ApplicationVersionString = ApplicationVersion.ToString(3); + ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString; + + _xmlSerializer = new MyXmlSerializer(); + ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); + _pluginManager = new PluginManager( + LoggerFactory.CreateLogger<PluginManager>(), + this, + ConfigurationManager.Configuration, + ApplicationPaths.PluginsPath, + ApplicationVersion); + } + + /// <summary> + /// Occurs when [has pending restart changed]. + /// </summary> + public event EventHandler HasPendingRestartChanged; + /// <summary> /// Gets a value indicating whether this instance can self restart. /// </summary> @@ -155,11 +216,6 @@ namespace Emby.Server.Implementations /// </summary> public INetworkManager NetManager { get; internal set; } - /// <summary> - /// Occurs when [has pending restart changed]. - /// </summary> - public event EventHandler HasPendingRestartChanged; - /// <summary> /// Gets a value indicating whether this instance has changes that require the entire application to restart. /// </summary> @@ -187,17 +243,6 @@ namespace Emby.Server.Implementations /// <value>The application paths.</value> protected IServerApplicationPaths ApplicationPaths { get; set; } - /// <summary> - /// Gets or sets all concrete types. - /// </summary> - /// <value>All concrete types.</value> - private Type[] _allConcreteTypes; - - /// <summary> - /// The disposable parts. - /// </summary> - private readonly List<IDisposable> _disposableParts = new List<IDisposable>(); - /// <summary> /// Gets or sets the configuration manager. /// </summary> @@ -224,47 +269,55 @@ namespace Emby.Server.Implementations /// </summary> public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig[UdpServer.AddressOverrideConfigKey]; + /// <inheritdoc /> + public Version ApplicationVersion { get; } + + /// <inheritdoc /> + public string ApplicationVersionString { get; } + /// <summary> - /// Initializes a new instance of the <see cref="ApplicationHost"/> class. + /// Gets the current application user agent. /// </summary> - /// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param> - /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> - /// <param name="options">Instance of the <see cref="IStartupOptions"/> interface.</param> - /// <param name="startupConfig">The <see cref="IConfiguration" /> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param> - public ApplicationHost( - IServerApplicationPaths applicationPaths, - ILoggerFactory loggerFactory, - IStartupOptions options, - IConfiguration startupConfig, - IFileSystem fileSystem, - IServiceCollection serviceCollection) - { - ApplicationPaths = applicationPaths; - LoggerFactory = loggerFactory; - _startupOptions = options; - _startupConfig = startupConfig; - _fileSystemManager = fileSystem; - ServiceCollection = serviceCollection; + /// <value>The application user agent.</value> + public string ApplicationUserAgent { get; } - Logger = LoggerFactory.CreateLogger<ApplicationHost>(); - fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); + /// <summary> + /// Gets the email address for use within a comment section of a user agent field. + /// Presently used to provide contact information to MusicBrainz service. + /// </summary> + public string ApplicationUserAgentAddress => "team@jellyfin.org"; - ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version; - ApplicationVersionString = ApplicationVersion.ToString(3); - ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString; + /// <summary> + /// Gets the current application name. + /// </summary> + /// <value>The application name.</value> + public string ApplicationProductName { get; } = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductName; - _xmlSerializer = new MyXmlSerializer(); - ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); - _pluginManager = new PluginManager( - LoggerFactory.CreateLogger<PluginManager>(), - this, - ConfigurationManager.Configuration, - ApplicationPaths.PluginsPath, - ApplicationVersion); + public string SystemId + { + get + { + _deviceId ??= new DeviceId(ApplicationPaths, LoggerFactory); + + return _deviceId.Value; + } } + /// <inheritdoc/> + public string Name => ApplicationProductName; + + private CertificateInfo CertificateInfo { get; set; } + + public X509Certificate2 Certificate { get; private set; } + + /// <inheritdoc/> + public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps; + + public string FriendlyName => + string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName) + ? Environment.MachineName + : ConfigurationManager.Configuration.ServerName; + /// <summary> /// Temporary function to migration network settings out of system.xml and into network.xml. /// TODO: remove at the point when a fixed migration path has been decided upon. @@ -297,45 +350,6 @@ namespace Emby.Server.Implementations .Replace(appPaths.InternalMetadataPath, appPaths.VirtualInternalMetadataPath, StringComparison.OrdinalIgnoreCase); } - /// <inheritdoc /> - public Version ApplicationVersion { get; } - - /// <inheritdoc /> - public string ApplicationVersionString { get; } - - /// <summary> - /// Gets the current application user agent. - /// </summary> - /// <value>The application user agent.</value> - public string ApplicationUserAgent { get; } - - /// <summary> - /// Gets the email address for use within a comment section of a user agent field. - /// Presently used to provide contact information to MusicBrainz service. - /// </summary> - public string ApplicationUserAgentAddress => "team@jellyfin.org"; - - /// <summary> - /// Gets the current application name. - /// </summary> - /// <value>The application name.</value> - public string ApplicationProductName { get; } = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductName; - - private DeviceId _deviceId; - - public string SystemId - { - get - { - _deviceId ??= new DeviceId(ApplicationPaths, LoggerFactory); - - return _deviceId.Value; - } - } - - /// <inheritdoc/> - public string Name => ApplicationProductName; - /// <summary> /// Creates an instance of type and resolves all constructor dependencies. /// </summary> @@ -857,10 +871,6 @@ namespace Emby.Server.Implementations } } - private CertificateInfo CertificateInfo { get; set; } - - public X509Certificate2 Certificate { get; private set; } - private IEnumerable<string> GetUrlPrefixes() { var hosts = new[] { "+" }; @@ -1114,9 +1124,6 @@ namespace Emby.Server.Implementations }; } - /// <inheritdoc/> - public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps; - /// <inheritdoc/> public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null) { @@ -1203,14 +1210,7 @@ namespace Emby.Server.Implementations }.ToString().TrimEnd('/'); } - public string FriendlyName => - string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName) - ? Environment.MachineName - : ConfigurationManager.Configuration.ServerName; - - /// <summary> - /// Shuts down. - /// </summary> + /// <inheritdoc /> public async Task Shutdown() { if (IsShuttingDown) @@ -1248,41 +1248,7 @@ namespace Emby.Server.Implementations } } - public virtual void LaunchUrl(string url) - { - if (!CanLaunchWebBrowser) - { - throw new NotSupportedException(); - } - - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = url, - UseShellExecute = true, - ErrorDialog = false - }, - EnableRaisingEvents = true - }; - process.Exited += (sender, args) => ((Process)sender).Dispose(); - - try - { - process.Start(); - } - catch (Exception ex) - { - Logger.LogError(ex, "Error launching url: {url}", url); - throw; - } - } - - private bool _disposed = false; - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> + /// <inheritdoc /> public void Dispose() { Dispose(true); diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index b00a51922..79ef70fff 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -196,8 +196,8 @@ namespace Emby.Server.Implementations.Collections } /// <inheritdoc /> - public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids) - => AddToCollectionAsync(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); + public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds) + => AddToCollectionAsync(collectionId, itemIds, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions) { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 0e6b7fb82..30f88c796 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1902,12 +1902,7 @@ namespace Emby.Server.Implementations.Data return result; } - /// <summary> - /// Gets chapters for an item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>IEnumerable{ChapterInfo}.</returns> - /// <exception cref="ArgumentNullException">id</exception> + /// <inheritdoc /> public List<ChapterInfo> GetChapters(BaseItem item) { CheckDisposed(); @@ -1930,13 +1925,7 @@ namespace Emby.Server.Implementations.Data } } - /// <summary> - /// Gets a single chapter for an item. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="index">The index.</param> - /// <returns>ChapterInfo.</returns> - /// <exception cref="ArgumentNullException">id</exception> + /// <inheritdoc /> public ChapterInfo GetChapter(BaseItem item, int index) { CheckDisposed(); @@ -2048,7 +2037,7 @@ namespace Emby.Server.Implementations.Data for (var i = startIndex; i < endIndex; i++) { - insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture)); + insertText.AppendFormat(CultureInfo.InvariantCulture, "(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture)); } insertText.Length -= 1; // Remove last , diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 613d07d77..829f1de2f 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -129,19 +129,17 @@ namespace Emby.Server.Implementations.Data return list; } - /// <summary> - /// Saves the user data. - /// </summary> - public void SaveUserData(long internalUserId, string key, UserItemData userData, CancellationToken cancellationToken) + /// <inheritdoc /> + public void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException(nameof(userData)); } - if (internalUserId <= 0) + if (userId <= 0) { - throw new ArgumentNullException(nameof(internalUserId)); + throw new ArgumentNullException(nameof(userId)); } if (string.IsNullOrEmpty(key)) @@ -149,22 +147,23 @@ namespace Emby.Server.Implementations.Data throw new ArgumentNullException(nameof(key)); } - PersistUserData(internalUserId, key, userData, cancellationToken); + PersistUserData(userId, key, userData, cancellationToken); } - public void SaveAllUserData(long internalUserId, UserItemData[] userData, CancellationToken cancellationToken) + /// <inheritdoc /> + public void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException(nameof(userData)); } - if (internalUserId <= 0) + if (userId <= 0) { - throw new ArgumentNullException(nameof(internalUserId)); + throw new ArgumentNullException(nameof(userId)); } - PersistAllUserData(internalUserId, userData, cancellationToken); + PersistAllUserData(userId, userData, cancellationToken); } /// <summary> @@ -263,19 +262,19 @@ namespace Emby.Server.Implementations.Data /// <summary> /// Gets the user data. /// </summary> - /// <param name="internalUserId">The user id.</param> + /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <returns>Task{UserItemData}.</returns> /// <exception cref="ArgumentNullException"> /// userId /// or - /// key + /// key. /// </exception> - public UserItemData GetUserData(long internalUserId, string key) + public UserItemData GetUserData(long userId, string key) { - if (internalUserId <= 0) + if (userId <= 0) { - throw new ArgumentNullException(nameof(internalUserId)); + throw new ArgumentNullException(nameof(userId)); } if (string.IsNullOrEmpty(key)) @@ -287,7 +286,7 @@ namespace Emby.Server.Implementations.Data { using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from UserDatas where key =@Key and userId=@UserId")) { - statement.TryBind("@UserId", internalUserId); + statement.TryBind("@UserId", userId); statement.TryBind("@Key", key); foreach (var row in statement.ExecuteQuery()) @@ -300,7 +299,7 @@ namespace Emby.Server.Implementations.Data } } - public UserItemData GetUserData(long internalUserId, List<string> keys) + public UserItemData GetUserData(long userId, List<string> keys) { if (keys == null) { @@ -312,19 +311,19 @@ namespace Emby.Server.Implementations.Data return null; } - return GetUserData(internalUserId, keys[0]); + return GetUserData(userId, keys[0]); } /// <summary> /// Return all user-data associated with the given user. /// </summary> - /// <param name="internalUserId">The internal user id.</param> + /// <param name="userId">The internal user id.</param> /// <returns>The list of user item data.</returns> - public List<UserItemData> GetAllUserData(long internalUserId) + public List<UserItemData> GetAllUserData(long userId) { - if (internalUserId <= 0) + if (userId <= 0) { - throw new ArgumentNullException(nameof(internalUserId)); + throw new ArgumentNullException(nameof(userId)); } var list = new List<UserItemData>(); @@ -333,7 +332,7 @@ namespace Emby.Server.Implementations.Data { using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from UserDatas where userId=@UserId")) { - statement.TryBind("@UserId", internalUserId); + statement.TryBind("@UserId", userId); foreach (var row in statement.ExecuteQuery()) { diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 7c2d02037..74400b512 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -51,8 +51,6 @@ namespace Emby.Server.Implementations.Dto private readonly IMediaSourceManager _mediaSourceManager; private readonly Lazy<ILiveTvManager> _livetvManagerFactory; - private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; - public DtoService( ILogger<DtoService> logger, ILibraryManager libraryManager, @@ -75,6 +73,8 @@ namespace Emby.Server.Implementations.Dto _livetvManagerFactory = livetvManagerFactory; } + private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; + /// <inheritdoc /> public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null) { @@ -507,7 +507,6 @@ namespace Emby.Server.Implementations.Dto /// </summary> /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> - /// <returns>Task.</returns> private void AttachPeople(BaseItemDto dto, BaseItem item) { // Ordering by person type to ensure actors and artists are at the front. @@ -616,7 +615,6 @@ namespace Emby.Server.Implementations.Dto /// </summary> /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> - /// <returns>Task.</returns> private void AttachStudios(BaseItemDto dto, BaseItem item) { dto.Studios = item.Studios @@ -1313,9 +1311,12 @@ namespace Emby.Server.Implementations.Dto var imageTags = dto.ImageTags; - while (((!(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && logoLimit > 0) || (!(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && artLimit > 0) || (!(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && thumbLimit > 0) || parent is Series) && - (parent ??= (isFirst ? GetImageDisplayParent(item, item) ?? owner : parent)) != null) + while ((!(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && logoLimit > 0) + || (!(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && artLimit > 0) + || (!(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && thumbLimit > 0) + || parent is Series) { + parent ??= isFirst ? GetImageDisplayParent(item, item) ?? owner : parent; if (parent == null) { break; @@ -1395,7 +1396,6 @@ namespace Emby.Server.Implementations.Dto /// </summary> /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> - /// <returns>Task.</returns> public void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item) { dto.PrimaryImageAspectRatio = GetPrimaryImageAspectRatio(item); diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 7c3c7da23..2c722ff25 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -423,7 +423,7 @@ namespace Emby.Server.Implementations.IO } } - public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly) + public virtual void SetAttributes(string path, bool isHidden, bool readOnly) { if (!OperatingSystem.IsWindows()) { @@ -437,14 +437,14 @@ namespace Emby.Server.Implementations.IO return; } - if (info.IsReadOnly == isReadOnly && info.IsHidden == isHidden) + if (info.IsReadOnly == readOnly && info.IsHidden == isHidden) { return; } var attributes = File.GetAttributes(path); - if (isReadOnly) + if (readOnly) { attributes = attributes | FileAttributes.ReadOnly; } diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index 833fb0b7a..4a026fd21 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Images public int Order => 0; - protected virtual bool Supports(BaseItem _) => true; + protected virtual bool Supports(BaseItem item) => true; public async Task<ItemUpdateType> FetchAsync(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index a0a6bb292..8054beae3 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1761,22 +1761,20 @@ namespace Emby.Server.Implementations.Library return orderedItems ?? items; } - public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ValueTuple<string, SortOrder>> orderByList) + public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ValueTuple<string, SortOrder>> orderBy) { var isFirst = true; IOrderedEnumerable<BaseItem> orderedItems = null; - foreach (var orderBy in orderByList) + foreach (var (name, sortOrder) in orderBy) { - var comparer = GetComparer(orderBy.Item1, user); + var comparer = GetComparer(name, user); if (comparer == null) { continue; } - var sortOrder = orderBy.Item2; - if (isFirst) { orderedItems = sortOrder == SortOrder.Descending ? items.OrderByDescending(i => i, comparer) : items.OrderBy(i => i, comparer); @@ -3076,9 +3074,9 @@ namespace Emby.Server.Implementations.Library }); } - public void AddMediaPath(string virtualFolderName, MediaPathInfo pathInfo) + public void AddMediaPath(string virtualFolderName, MediaPathInfo mediaPath) { - AddMediaPathInternal(virtualFolderName, pathInfo, true); + AddMediaPathInternal(virtualFolderName, mediaPath, true); } private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions) @@ -3131,11 +3129,11 @@ namespace Emby.Server.Implementations.Library } } - public void UpdateMediaPath(string virtualFolderName, MediaPathInfo pathInfo) + public void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath) { - if (pathInfo == null) + if (mediaPath == null) { - throw new ArgumentNullException(nameof(pathInfo)); + throw new ArgumentNullException(nameof(mediaPath)); } var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; @@ -3148,9 +3146,9 @@ namespace Emby.Server.Implementations.Library var list = libraryOptions.PathInfos.ToList(); foreach (var originalPathInfo in list) { - if (string.Equals(pathInfo.Path, originalPathInfo.Path, StringComparison.Ordinal)) + if (string.Equals(mediaPath.Path, originalPathInfo.Path, StringComparison.Ordinal)) { - originalPathInfo.NetworkPath = pathInfo.NetworkPath; + originalPathInfo.NetworkPath = mediaPath.NetworkPath; break; } } diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs index 06300adeb..e2f1fb0ad 100644 --- a/Emby.Server.Implementations/Library/MusicManager.cs +++ b/Emby.Server.Implementations/Library/MusicManager.cs @@ -36,9 +36,10 @@ namespace Emby.Server.Implementations.Library return list.Concat(GetInstantMixFromGenres(item.Genres, user, dtoOptions)).ToList(); } - public List<BaseItem> GetInstantMixFromArtist(MusicArtist item, User user, DtoOptions dtoOptions) + /// <inheritdoc /> + public List<BaseItem> GetInstantMixFromArtist(MusicArtist artist, User user, DtoOptions dtoOptions) { - return GetInstantMixFromGenres(item.Genres, user, dtoOptions); + return GetInstantMixFromGenres(artist.Genres, user, dtoOptions); } public List<BaseItem> GetInstantMixFromAlbum(MusicAlbum item, User user, DtoOptions dtoOptions) diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 01e89302e..b102b86cf 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -21,13 +21,13 @@ namespace Emby.Server.Implementations.Library.Resolvers public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T> where T : Video, new() { - protected readonly ILibraryManager LibraryManager; - protected BaseVideoResolver(ILibraryManager libraryManager) { LibraryManager = libraryManager; } + protected ILibraryManager LibraryManager { get; } + /// <summary> /// Resolves the specified args. /// </summary> diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 8aa605a90..c4e230f21 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -177,6 +177,7 @@ namespace Emby.Server.Implementations.Library return dto; } + /// <inheritdoc /> public UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions options) { var userData = GetUserData(user, item); @@ -191,7 +192,7 @@ namespace Emby.Server.Implementations.Library /// </summary> /// <param name="data">The data.</param> /// <returns>DtoUserItemData.</returns> - /// <exception cref="ArgumentNullException"></exception> + /// <exception cref="ArgumentNullException"><paramref name="data"/> is <c>null</c>.</exception> private UserItemDataDto GetUserItemDataDto(UserItemData data) { if (data == null) @@ -212,6 +213,7 @@ namespace Emby.Server.Implementations.Library }; } + /// <inheritdoc /> public bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPositionTicks) { var playedToCompletion = false; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index f2b9f3cb9..026b6bc0b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -610,11 +610,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV throw new NotImplementedException(); } - public Task<string> CreateTimer(TimerInfo timer, CancellationToken cancellationToken) + public Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken) { - var existingTimer = string.IsNullOrWhiteSpace(timer.ProgramId) ? + var existingTimer = string.IsNullOrWhiteSpace(info.ProgramId) ? null : - _timerProvider.GetTimerByProgramId(timer.ProgramId); + _timerProvider.GetTimerByProgramId(info.ProgramId); if (existingTimer != null) { @@ -632,32 +632,32 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - timer.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); + info.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); LiveTvProgram programInfo = null; - if (!string.IsNullOrWhiteSpace(timer.ProgramId)) + if (!string.IsNullOrWhiteSpace(info.ProgramId)) { - programInfo = GetProgramInfoFromCache(timer); + programInfo = GetProgramInfoFromCache(info); } if (programInfo == null) { - _logger.LogInformation("Unable to find program with Id {0}. Will search using start date", timer.ProgramId); - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.StartDate); + _logger.LogInformation("Unable to find program with Id {0}. Will search using start date", info.ProgramId); + programInfo = GetProgramInfoFromCache(info.ChannelId, info.StartDate); } if (programInfo != null) { - CopyProgramInfoToTimerInfo(programInfo, timer); + CopyProgramInfoToTimerInfo(programInfo, info); } - timer.IsManual = true; - _timerProvider.Add(timer); + info.IsManual = true; + _timerProvider.Add(info); - TimerCreated?.Invoke(this, new GenericEventArgs<TimerInfo>(timer)); + TimerCreated?.Invoke(this, new GenericEventArgs<TimerInfo>(info)); - return Task.FromResult(timer.Id); + return Task.FromResult(info.Id); } public async Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index ce585d0fb..ea1a28fe8 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -65,6 +65,8 @@ namespace Emby.Server.Implementations.LiveTv private ITunerHost[] _tunerHosts = Array.Empty<ITunerHost>(); private IListingsProvider[] _listingProviders = Array.Empty<IListingsProvider>(); + private bool _disposed = false; + public LiveTvManager( IServerConfigurationManager config, ILogger<LiveTvManager> logger, @@ -520,7 +522,7 @@ namespace Emby.Server.Implementations.LiveTv return item; } - private Tuple<LiveTvProgram, bool, bool> GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel, ChannelType channelType, string serviceName, CancellationToken cancellationToken) + private (LiveTvProgram item, bool isNew, bool isUpdated) GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel) { var id = _tvDtoService.GetInternalProgramId(info.Id); @@ -559,8 +561,6 @@ namespace Emby.Server.Implementations.LiveTv item.ParentId = channel.Id; - // item.ChannelType = channelType; - item.Audio = info.Audio; item.ChannelId = channel.Id; item.CommunityRating ??= info.CommunityRating; @@ -772,7 +772,7 @@ namespace Emby.Server.Implementations.LiveTv item.OnMetadataChanged(); } - return new Tuple<LiveTvProgram, bool, bool>(item, isNew, isUpdated); + return (item, isNew, isUpdated); } public async Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null) @@ -1187,14 +1187,14 @@ namespace Emby.Server.Implementations.LiveTv foreach (var program in channelPrograms) { - var programTuple = GetProgram(program, existingPrograms, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken); - var programItem = programTuple.Item1; + var programTuple = GetProgram(program, existingPrograms, currentChannel); + var programItem = programTuple.item; - if (programTuple.Item2) + if (programTuple.isNew) { newPrograms.Add(programItem); } - else if (programTuple.Item3) + else if (programTuple.isUpdated) { updatedPrograms.Add(programItem); } @@ -1385,10 +1385,10 @@ namespace Emby.Server.Implementations.LiveTv // var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray(); // return new QueryResult<BaseItem> - //{ + // { // Items = items, // TotalRecordCount = items.Length - //}; + // }; dtoOptions.Fields = dtoOptions.Fields.Concat(new[] { ItemFields.Tags }).Distinct().ToArray(); } @@ -1425,16 +1425,15 @@ namespace Emby.Server.Implementations.LiveTv return result; } - public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> tuples, IReadOnlyList<ItemFields> fields, User user = null) + public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null) { var programTuples = new List<Tuple<BaseItemDto, string, string>>(); var hasChannelImage = fields.Contains(ItemFields.ChannelImage); var hasChannelInfo = fields.Contains(ItemFields.ChannelInfo); - foreach (var tuple in tuples) + foreach (var (item, dto) in programs) { - var program = (LiveTvProgram)tuple.Item1; - var dto = tuple.Item2; + var program = (LiveTvProgram)item; dto.StartDate = program.StartDate; dto.EpisodeTitle = program.EpisodeTitle; @@ -1871,11 +1870,11 @@ namespace Emby.Server.Implementations.LiveTv return _libraryManager.GetItemById(internalChannelId); } - public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> tuples, DtoOptions options, User user) + public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> items, DtoOptions options, User user) { var now = DateTime.UtcNow; - var channelIds = tuples.Select(i => i.Item2.Id).Distinct().ToArray(); + var channelIds = items.Select(i => i.Item2.Id).Distinct().ToArray(); var programs = options.AddCurrentProgram ? _libraryManager.GetItemList(new InternalItemsQuery(user) { @@ -1896,7 +1895,7 @@ namespace Emby.Server.Implementations.LiveTv var addCurrentProgram = options.AddCurrentProgram; - foreach (var tuple in tuples) + foreach (var tuple in items) { var dto = tuple.Item1; var channel = tuple.Item2; @@ -2118,17 +2117,13 @@ namespace Emby.Server.Implementations.LiveTv }; } - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> + /// <inheritdoc /> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } - private bool _disposed = false; - /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> @@ -2324,20 +2319,20 @@ namespace Emby.Server.Implementations.LiveTv _taskManager.CancelIfRunningAndQueue<RefreshGuideScheduledTask>(); } - public async Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelId, string providerChannelId) + public async Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber) { var config = GetConfiguration(); var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(providerId, i.Id, StringComparison.OrdinalIgnoreCase)); - listingsProviderInfo.ChannelMappings = listingsProviderInfo.ChannelMappings.Where(i => !string.Equals(i.Name, tunerChannelId, StringComparison.OrdinalIgnoreCase)).ToArray(); + listingsProviderInfo.ChannelMappings = listingsProviderInfo.ChannelMappings.Where(i => !string.Equals(i.Name, tunerChannelNumber, StringComparison.OrdinalIgnoreCase)).ToArray(); - if (!string.Equals(tunerChannelId, providerChannelId, StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(tunerChannelNumber, providerChannelNumber, StringComparison.OrdinalIgnoreCase)) { var list = listingsProviderInfo.ChannelMappings.ToList(); list.Add(new NameValuePair { - Name = tunerChannelId, - Value = providerChannelId + Name = tunerChannelNumber, + Value = providerChannelNumber }); listingsProviderInfo.ChannelMappings = list.ToArray(); } @@ -2357,10 +2352,10 @@ namespace Emby.Server.Implementations.LiveTv _taskManager.CancelIfRunningAndQueue<RefreshGuideScheduledTask>(); - return tunerChannelMappings.First(i => string.Equals(i.Id, tunerChannelId, StringComparison.OrdinalIgnoreCase)); + return tunerChannelMappings.First(i => string.Equals(i.Id, tunerChannelNumber, StringComparison.OrdinalIgnoreCase)); } - public TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, NameValuePair[] mappings, List<ChannelInfo> epgChannels) + public TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, NameValuePair[] mappings, List<ChannelInfo> providerChannels) { var result = new TunerChannelMapping { @@ -2373,7 +2368,7 @@ namespace Emby.Server.Implementations.LiveTv result.Name = tunerChannel.Number + " " + result.Name; } - var providerChannel = EmbyTV.EmbyTV.Current.GetEpgChannelFromTunerChannel(mappings, tunerChannel, epgChannels); + var providerChannel = EmbyTV.EmbyTV.Current.GetEpgChannelFromTunerChannel(mappings, tunerChannel, providerChannels); if (providerChannel != null) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 5941613cf..9bff0861b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -158,7 +158,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return new List<MediaSourceInfo>(); } - protected abstract Task<ILiveStream> GetChannelStream(TunerHostInfo tuner, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken); + protected abstract Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken); public async Task<ILiveStream> GetChannelStream(string channelId, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 011748d1d..2bd12a9c8 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -95,17 +95,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public bool IsLegacyTuner { get; set; } } - protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) + protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) { - var lineup = await GetLineup(info, cancellationToken).ConfigureAwait(false); + var lineup = await GetLineup(tuner, cancellationToken).ConfigureAwait(false); return lineup.Select(i => new HdHomerunChannelInfo { Name = i.GuideName, Number = i.GuideNumber, - Id = GetChannelId(info, i), + Id = GetChannelId(tuner, i), IsFavorite = i.Favorite, - TunerHostId = info.Id, + TunerHostId = tuner.Id, IsHD = i.HD, AudioCodec = i.AudioCodec, VideoCodec = i.VideoCodec, @@ -496,57 +496,53 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return mediaSource; } - protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, ChannelInfo channelInfo, CancellationToken cancellationToken) + protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, ChannelInfo channel, CancellationToken cancellationToken) { var list = new List<MediaSourceInfo>(); - var channelId = channelInfo.Id; + var channelId = channel.Id; var hdhrId = GetHdHrIdFromChannelId(channelId); - var hdHomerunChannelInfo = channelInfo as HdHomerunChannelInfo; - - var isLegacyTuner = hdHomerunChannelInfo != null && hdHomerunChannelInfo.IsLegacyTuner; - - if (isLegacyTuner) + if (channel is HdHomerunChannelInfo hdHomerunChannelInfo && hdHomerunChannelInfo.IsLegacyTuner) { - list.Add(GetMediaSource(info, hdhrId, channelInfo, "native")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "native")); } else { - var modelInfo = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); + var modelInfo = await GetModelInfo(tuner, false, cancellationToken).ConfigureAwait(false); if (modelInfo != null && modelInfo.SupportsTranscoding) { - if (info.AllowHWTranscoding) + if (tuner.AllowHWTranscoding) { - list.Add(GetMediaSource(info, hdhrId, channelInfo, "heavy")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "heavy")); - list.Add(GetMediaSource(info, hdhrId, channelInfo, "internet540")); - list.Add(GetMediaSource(info, hdhrId, channelInfo, "internet480")); - list.Add(GetMediaSource(info, hdhrId, channelInfo, "internet360")); - list.Add(GetMediaSource(info, hdhrId, channelInfo, "internet240")); - list.Add(GetMediaSource(info, hdhrId, channelInfo, "mobile")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "internet540")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "internet480")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "internet360")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "internet240")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "mobile")); } - list.Add(GetMediaSource(info, hdhrId, channelInfo, "native")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "native")); } if (list.Count == 0) { - list.Add(GetMediaSource(info, hdhrId, channelInfo, "native")); + list.Add(GetMediaSource(tuner, hdhrId, channel, "native")); } } return list; } - protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, ChannelInfo channelInfo, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) + protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) { - var tunerCount = info.TunerCount; + var tunerCount = tunerHost.TunerCount; if (tunerCount > 0) { - var tunerHostId = info.Id; + var tunerHostId = tunerHost.Id; var liveStreams = currentLiveStreams.Where(i => string.Equals(i.TunerHostId, tunerHostId, StringComparison.OrdinalIgnoreCase)); if (liveStreams.Count() >= tunerCount) @@ -557,26 +553,26 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var profile = streamId.Split('_')[0]; - Logger.LogInformation("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channelInfo.Id, streamId, profile); + Logger.LogInformation("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channel.Id, streamId, profile); - var hdhrId = GetHdHrIdFromChannelId(channelInfo.Id); + var hdhrId = GetHdHrIdFromChannelId(channel.Id); - var hdhomerunChannel = channelInfo as HdHomerunChannelInfo; + var hdhomerunChannel = channel as HdHomerunChannelInfo; - var modelInfo = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); + var modelInfo = await GetModelInfo(tunerHost, false, cancellationToken).ConfigureAwait(false); if (!modelInfo.SupportsTranscoding) { profile = "native"; } - var mediaSource = GetMediaSource(info, hdhrId, channelInfo, profile); + var mediaSource = GetMediaSource(tunerHost, hdhrId, channel, profile); if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner) { return new HdHomerunUdpStream( mediaSource, - info, + tunerHost, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Path), modelInfo.TunerCount, @@ -592,7 +588,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { mediaSource.Protocol = MediaProtocol.Http; - var httpUrl = channelInfo.Path; + var httpUrl = channel.Path; // If raw was used, the tuner doesn't support params if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -604,7 +600,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return new SharedHttpStream( mediaSource, - info, + tunerHost, streamId, FileSystem, _httpClientFactory, @@ -616,7 +612,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return new HdHomerunUdpStream( mediaSource, - info, + tunerHost, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number, profile), modelInfo.TunerCount, diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 8fa6f5ad6..08b9260b9 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -71,12 +71,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return ChannelIdPrefix + info.Url.GetMD5().ToString("N", CultureInfo.InvariantCulture); } - protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) + protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) { - var channelIdPrefix = GetFullChannelIdPrefix(info); + var channelIdPrefix = GetFullChannelIdPrefix(tuner); return await new M3uParser(Logger, _httpClientFactory) - .Parse(info, channelIdPrefix, cancellationToken) + .Parse(tuner, channelIdPrefix, cancellationToken) .ConfigureAwait(false); } @@ -96,13 +96,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.FromResult(list); } - protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, ChannelInfo channelInfo, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) + protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo tunerHost, ChannelInfo channel, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) { - var tunerCount = info.TunerCount; + var tunerCount = tunerHost.TunerCount; if (tunerCount > 0) { - var tunerHostId = info.Id; + var tunerHostId = tunerHost.Id; var liveStreams = currentLiveStreams.Where(i => string.Equals(i.TunerHostId, tunerHostId, StringComparison.OrdinalIgnoreCase)); if (liveStreams.Count() >= tunerCount) @@ -111,7 +111,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } - var sources = await GetChannelStreamMediaSources(info, channelInfo, cancellationToken).ConfigureAwait(false); + var sources = await GetChannelStreamMediaSources(tunerHost, channel, cancellationToken).ConfigureAwait(false); var mediaSource = sources[0]; @@ -121,11 +121,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { - return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper); + return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper); } } - return new LiveStream(mediaSource, info, FileSystem, Logger, Config, _streamHelper); + return new LiveStream(mediaSource, tunerHost, FileSystem, Logger, Config, _streamHelper); } public async Task Validate(TunerHostInfo info) @@ -135,9 +135,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } - protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, ChannelInfo channelInfo, CancellationToken cancellationToken) + protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, ChannelInfo channel, CancellationToken cancellationToken) { - return Task.FromResult(new List<MediaSourceInfo> { CreateMediaSourceInfo(info, channelInfo) }); + return Task.FromResult(new List<MediaSourceInfo> { CreateMediaSourceInfo(tuner, channel) }); } protected virtual MediaSourceInfo CreateMediaSourceInfo(TunerHostInfo info, ChannelInfo channel) diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 137728616..6d0c8731e 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -11,6 +11,7 @@ namespace Emby.Server.Implementations.Net { public class SocketFactory : ISocketFactory { + /// <inheritdoc /> public ISocket CreateUdpBroadcastSocket(int localPort) { if (localPort < 0) @@ -35,11 +36,8 @@ namespace Emby.Server.Implementations.Net } } - /// <summary> - /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. - /// </summary> - /// <returns>An implementation of the <see cref="ISocket"/> interface used by RSSDP components to perform acceptSocket operations.</returns> - public ISocket CreateSsdpUdpSocket(IPAddress localIpAddress, int localPort) + /// <inheritdoc /> + public ISocket CreateSsdpUdpSocket(IPAddress localIp, int localPort) { if (localPort < 0) { @@ -53,8 +51,8 @@ namespace Emby.Server.Implementations.Net retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIpAddress)); - return new UdpSocket(retVal, localPort, localIpAddress); + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp)); + return new UdpSocket(retVal, localPort, localIp); } catch { @@ -64,13 +62,7 @@ namespace Emby.Server.Implementations.Net } } - /// <summary> - /// Creates a new UDP acceptSocket that is a member of the specified multicast IP address, and binds it to the specified local port. - /// </summary> - /// <param name="ipAddress">The multicast IP address to make the acceptSocket a member of.</param> - /// <param name="multicastTimeToLive">The multicast time to live value for the acceptSocket.</param> - /// <param name="localPort">The number of the local port to bind to.</param> - /// <returns></returns> + /// <inheritdoc /> public ISocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) { if (ipAddress == null) diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index a8b18d292..9b799e854 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Net return taskCompletion.Task; } - public Task SendToAsync(byte[] buffer, int offset, int size, IPEndPoint endPoint, CancellationToken cancellationToken) + public Task SendToAsync(byte[] buffer, int offset, int bytes, IPEndPoint endPoint, CancellationToken cancellationToken) { ThrowIfDisposed(); @@ -214,7 +214,7 @@ namespace Emby.Server.Implementations.Net } }; - var result = BeginSendTo(buffer, offset, size, endPoint, new AsyncCallback(callback), null); + var result = BeginSendTo(buffer, offset, bytes, endPoint, new AsyncCallback(callback), null); if (result.CompletedSynchronously) { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index 692d1667d..a575b260c 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -29,6 +29,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// <summary> /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class. /// </summary> + /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param> + /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> + /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> + /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> public DeleteCacheFileTask( IApplicationPaths appPaths, ILogger<DeleteCacheFileTask> logger, diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index ea710013e..4111590c8 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -235,12 +235,12 @@ namespace Emby.Server.Implementations.Session } /// <inheritdoc /> - public void UpdateDeviceName(string sessionId, string deviceName) + public void UpdateDeviceName(string sessionId, string reportedDeviceName) { var session = GetSession(sessionId); if (session != null) { - session.DeviceName = deviceName; + session.DeviceName = reportedDeviceName; } } @@ -316,14 +316,14 @@ namespace Emby.Server.Implementations.Session } /// <inheritdoc /> - public void OnSessionControllerConnected(SessionInfo info) + public void OnSessionControllerConnected(SessionInfo session) { EventHelper.QueueEventIfNotNull( SessionControllerConnected, this, new SessionEventArgs { - SessionInfo = info + SessionInfo = session }, _logger); } @@ -1581,16 +1581,16 @@ namespace Emby.Server.Implementations.Session } /// <inheritdoc /> - public async Task Logout(Device existing) + public async Task Logout(Device device) { CheckDisposed(); - _logger.LogInformation("Logging out access token {0}", existing.AccessToken); + _logger.LogInformation("Logging out access token {0}", device.AccessToken); - await _deviceManager.DeleteDevice(existing).ConfigureAwait(false); + await _deviceManager.DeleteDevice(device).ConfigureAwait(false); var sessions = Sessions - .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase)) + .Where(i => string.Equals(i.DeviceId, device.DeviceId, StringComparison.OrdinalIgnoreCase)) .ToList(); foreach (var session in sessions) @@ -1601,7 +1601,7 @@ namespace Emby.Server.Implementations.Session } catch (Exception ex) { - _logger.LogError("Error reporting session ended", ex); + _logger.LogError(ex, "Error reporting session ended"); } } } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index af453d148..4d990c871 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -33,9 +33,9 @@ namespace Emby.Server.Implementations.TV _configurationManager = configurationManager; } - public QueryResult<BaseItem> GetNextUp(NextUpQuery request, DtoOptions dtoOptions) + public QueryResult<BaseItem> GetNextUp(NextUpQuery query, DtoOptions options) { - var user = _userManager.GetUserById(request.UserId); + var user = _userManager.GetUserById(query.UserId); if (user == null) { @@ -43,9 +43,9 @@ namespace Emby.Server.Implementations.TV } string presentationUniqueKey = null; - if (!string.IsNullOrEmpty(request.SeriesId)) + if (!string.IsNullOrEmpty(query.SeriesId)) { - if (_libraryManager.GetItemById(request.SeriesId) is Series series) + if (_libraryManager.GetItemById(query.SeriesId) is Series series) { presentationUniqueKey = GetUniqueSeriesKey(series); } @@ -53,14 +53,14 @@ namespace Emby.Server.Implementations.TV if (!string.IsNullOrEmpty(presentationUniqueKey)) { - return GetResult(GetNextUpEpisodes(request, user, new[] { presentationUniqueKey }, dtoOptions), request); + return GetResult(GetNextUpEpisodes(query, user, new[] { presentationUniqueKey }, options), query); } BaseItem[] parents; - if (request.ParentId.HasValue) + if (query.ParentId.HasValue) { - var parent = _libraryManager.GetItemById(request.ParentId.Value); + var parent = _libraryManager.GetItemById(query.ParentId.Value); if (parent != null) { @@ -79,10 +79,10 @@ namespace Emby.Server.Implementations.TV .ToArray(); } - return GetNextUp(request, parents, dtoOptions); + return GetNextUp(query, parents, options); } - public QueryResult<BaseItem> GetNextUp(NextUpQuery request, BaseItem[] parentsFolders, DtoOptions dtoOptions) + public QueryResult<BaseItem> GetNextUp(NextUpQuery request, BaseItem[] parentsFolders, DtoOptions options) { var user = _userManager.GetUserById(request.UserId); @@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.TV if (!string.IsNullOrEmpty(presentationUniqueKey)) { - return GetResult(GetNextUpEpisodes(request, user, new[] { presentationUniqueKey }, dtoOptions), request); + return GetResult(GetNextUpEpisodes(request, user, new[] { presentationUniqueKey }, options), request); } if (limit.HasValue) @@ -128,7 +128,7 @@ namespace Emby.Server.Implementations.TV .Select(GetUniqueSeriesKey); // Avoid implicitly captured closure - var episodes = GetNextUpEpisodes(request, user, items, dtoOptions); + var episodes = GetNextUpEpisodes(request, user, items, options); return GetResult(episodes, request); } diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 0fb4771dd..7dc7f774d 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -97,8 +97,7 @@ namespace MediaBrowser.Controller.Entities { try { - var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions; - if (result == null) + if (XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) is not LibraryOptions result) { return new LibraryOptions(); } diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 753c18bc7..b0abca367 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -104,13 +104,6 @@ namespace MediaBrowser.Controller /// <returns>The API URL.</returns> string GetLocalApiUrl(string hostname, string scheme = null, int? port = null); - /// <summary> - /// Open a URL in an external browser window. - /// </summary> - /// <param name="url">The URL to open.</param> - /// <exception cref="NotSupportedException"><see cref="CanLaunchWebBrowser"/> is false.</exception> - void LaunchUrl(string url); - IEnumerable<WakeOnLanInfo> GetWakeOnLanInfo(); string ExpandVirtualPath(string path); diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 604960d8b..d40e56c7d 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -595,11 +595,11 @@ namespace MediaBrowser.Controller.Library Task RemoveVirtualFolder(string name, bool refreshLibrary); - void AddMediaPath(string virtualFolderName, MediaPathInfo path); + void AddMediaPath(string virtualFolderName, MediaPathInfo mediaPath); - void UpdateMediaPath(string virtualFolderName, MediaPathInfo path); + void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath); - void RemoveMediaPath(string virtualFolderName, string path); + void RemoveMediaPath(string virtualFolderName, string mediaPath); QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query); diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index cf35b48db..034c40591 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Library /// <returns>User data dto.</returns> UserItemDataDto GetUserDataDto(BaseItem item, User user); - UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions dto_options); + UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions options); /// <summary> /// Get all user data for the given user. @@ -69,8 +69,8 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="item">Item to update.</param> /// <param name="data">Data to update.</param> - /// <param name="positionTicks">New playstate.</param> + /// <param name="reportedPositionTicks">New playstate.</param> /// <returns>True if playstate was updated.</returns> - bool UpdatePlayState(BaseItem item, UserItemData data, long? positionTicks); + bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPositionTicks); } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index bd097c90a..dbd18165d 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -274,7 +274,7 @@ namespace MediaBrowser.Controller.LiveTv Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber); - TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, NameValuePair[] mappings, List<ChannelInfo> providerChannels); + TunerChannelMapping GetTunerChannelMapping(ChannelInfo tunerChannel, NameValuePair[] mappings, List<ChannelInfo> providerChannels); /// <summary> /// Gets the lineups. diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs index 897f263f3..ce34954e3 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs @@ -70,10 +70,10 @@ namespace MediaBrowser.Controller.LiveTv /// <summary> /// Updates the timer asynchronous. /// </summary> - /// <param name="info">The information.</param> + /// <param name="updatedTimer">The updated timer information.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken); + Task UpdateTimerAsync(TimerInfo updatedTimer, CancellationToken cancellationToken); /// <summary> /// Updates the series timer asynchronous. diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 0a9073e7f..a084f9196 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -49,17 +49,17 @@ namespace MediaBrowser.Controller.Persistence /// <summary> /// Gets chapters for an item. /// </summary> - /// <param name="id">The item.</param> + /// <param name="item">The item.</param> /// <returns>The list of chapter info.</returns> - List<ChapterInfo> GetChapters(BaseItem id); + List<ChapterInfo> GetChapters(BaseItem item); /// <summary> /// Gets a single chapter for an item. /// </summary> - /// <param name="id">The item.</param> + /// <param name="item">The item.</param> /// <param name="index">The chapter index.</param> /// <returns>The chapter info at the specified index.</returns> - ChapterInfo GetChapter(BaseItem id, int index); + ChapterInfo GetChapter(BaseItem item, int index); /// <summary> /// Saves the chapters. diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 23b36cc10..cc12cb102 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -344,7 +344,7 @@ namespace MediaBrowser.Controller.Session /// <returns>A <see cref="Task"/> representing the log out process.</returns> Task Logout(string accessToken); - Task Logout(Device accessToken); + Task Logout(Device device); /// <summary> /// Revokes the user tokens. diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 432c1c1d6..4414415a2 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Model.Dlna var stream = TargetAudioStream; return AudioSampleRate.HasValue && !IsDirectStream ? AudioSampleRate - : stream == null ? null : stream.SampleRate; + : stream?.SampleRate; } } @@ -146,7 +146,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; + return TargetAudioStream?.BitDepth; } var targetAudioCodecs = TargetAudioCodec; @@ -156,7 +156,7 @@ namespace MediaBrowser.Model.Dlna return GetTargetAudioBitDepth(audioCodec); } - return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; + return TargetAudioStream?.BitDepth; } } @@ -169,7 +169,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; + return TargetVideoStream?.BitDepth; } var targetVideoCodecs = TargetVideoCodec; @@ -179,7 +179,7 @@ namespace MediaBrowser.Model.Dlna return GetTargetVideoBitDepth(videoCodec); } - return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; + return TargetVideoStream?.BitDepth; } } @@ -193,7 +193,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + return TargetVideoStream?.RefFrames; } var targetVideoCodecs = TargetVideoCodec; @@ -203,7 +203,7 @@ namespace MediaBrowser.Model.Dlna return GetTargetRefFrames(videoCodec); } - return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + return TargetVideoStream?.RefFrames; } } @@ -230,7 +230,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + return TargetVideoStream?.Level; } var targetVideoCodecs = TargetVideoCodec; @@ -240,7 +240,7 @@ namespace MediaBrowser.Model.Dlna return GetTargetVideoLevel(videoCodec); } - return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + return TargetVideoStream?.Level; } } @@ -254,7 +254,7 @@ namespace MediaBrowser.Model.Dlna var stream = TargetVideoStream; return !IsDirectStream ? null - : stream == null ? null : stream.PacketLength; + : stream?.PacketLength; } } @@ -267,7 +267,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? null : TargetVideoStream.Profile; + return TargetVideoStream?.Profile; } var targetVideoCodecs = TargetVideoCodec; @@ -277,7 +277,7 @@ namespace MediaBrowser.Model.Dlna return GetOption(videoCodec, "profile"); } - return TargetVideoStream == null ? null : TargetVideoStream.Profile; + return TargetVideoStream?.Profile; } } @@ -292,7 +292,7 @@ namespace MediaBrowser.Model.Dlna var stream = TargetVideoStream; return !IsDirectStream ? null - : stream == null ? null : stream.CodecTag; + : stream?.CodecTag; } } @@ -306,7 +306,7 @@ namespace MediaBrowser.Model.Dlna var stream = TargetAudioStream; return AudioBitrate.HasValue && !IsDirectStream ? AudioBitrate - : stream == null ? null : stream.BitRate; + : stream?.BitRate; } } @@ -319,7 +319,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + return TargetAudioStream?.Channels; } var targetAudioCodecs = TargetAudioCodec; @@ -329,7 +329,7 @@ namespace MediaBrowser.Model.Dlna return GetTargetRefFrames(codec); } - return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + return TargetAudioStream?.Channels; } } @@ -425,7 +425,7 @@ namespace MediaBrowser.Model.Dlna return VideoBitrate.HasValue && !IsDirectStream ? VideoBitrate - : stream == null ? null : stream.BitRate; + : stream?.BitRate; } } @@ -451,7 +451,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic; + return TargetVideoStream?.IsAnamorphic; } return false; @@ -464,7 +464,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; + return TargetVideoStream?.IsInterlaced; } var targetVideoCodecs = TargetVideoCodec; @@ -477,7 +477,7 @@ namespace MediaBrowser.Model.Dlna } } - return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; + return TargetVideoStream?.IsInterlaced; } } @@ -487,7 +487,7 @@ namespace MediaBrowser.Model.Dlna { if (IsDirectStream) { - return TargetVideoStream == null ? null : TargetVideoStream.IsAVC; + return TargetVideoStream?.IsAVC; } return true; @@ -618,20 +618,20 @@ namespace MediaBrowser.Model.Dlna } // Try to keep the url clean by omitting defaults - if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) + && string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) { continue; } - if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) + && string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) { continue; } - if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "false", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) + && string.Equals(pair.Value, "false", StringComparison.OrdinalIgnoreCase)) { continue; } @@ -641,7 +641,7 @@ namespace MediaBrowser.Model.Dlna list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } - string queryString = string.Join("&", list.ToArray()); + string queryString = string.Join('&', list); return GetUrl(baseUrl, queryString); } @@ -681,11 +681,11 @@ namespace MediaBrowser.Model.Dlna string audioCodecs = item.AudioCodecs.Length == 0 ? string.Empty : - string.Join(",", item.AudioCodecs); + string.Join(',', item.AudioCodecs); string videoCodecs = item.VideoCodecs.Length == 0 ? string.Empty : - string.Join(",", item.VideoCodecs); + string.Join(',', item.VideoCodecs); list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); @@ -1024,30 +1024,5 @@ namespace MediaBrowser.Model.Dlna return count; } - - public List<MediaStream> GetSelectableAudioStreams() - { - return GetSelectableStreams(MediaStreamType.Audio); - } - - public List<MediaStream> GetSelectableSubtitleStreams() - { - return GetSelectableStreams(MediaStreamType.Subtitle); - } - - public List<MediaStream> GetSelectableStreams(MediaStreamType type) - { - var list = new List<MediaStream>(); - - foreach (var stream in MediaSource.MediaStreams) - { - if (type == stream.Type) - { - list.Add(stream); - } - } - - return list; - } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index a2fc7bc8d..68fb9064e 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -12,6 +12,8 @@ <Rule Id="SA1101" Action="None" /> <!-- disable warning SA1108: Block statements should not contain embedded comments --> <Rule Id="SA1108" Action="None" /> + <!-- disable warning SA1118: Parameter must not span multiple lines. --> + <Rule Id="SA1118" Action="None" /> <!-- disable warning SA1128:: Put constructor initializers on their own line --> <Rule Id="SA1128" Action="None" /> <!-- disable warning SA1130: Use lambda syntax --> @@ -39,6 +41,10 @@ </Rules> <Rules AnalyzerId="Microsoft.CodeAnalysis.NetAnalyzers" RuleNamespace="Microsoft.Design"> + <!-- error on CA1305: Specify IFormatProvider --> + <Rule Id="CA1305" Action="Error" /> + <!-- error on CA1725: Parameter names should match base declaration --> + <Rule Id="CA1725" Action="Error" /> <!-- error on CA2016: Forward the CancellationToken parameter to methods that take one or pass in 'CancellationToken.None' explicitly to indicate intentionally not propagating the token --> <Rule Id="CA2016" Action="Error" /> -- cgit v1.2.3 From 90174f68e2b477e613d756d78cbfd89c2a33f30a Mon Sep 17 00:00:00 2001 From: Fredrik Lindberg <fli@shapeshifter.se> Date: Tue, 31 Aug 2021 22:22:55 +0200 Subject: Dynamically populate LocalAddress based on HTTP request Support populating the LocalAddress field in the system info endpoint based on the x-forwarded-host and x-forwarded-proto header. The x-forwarded-host header must contain both the host and port for the url to be properly constructed. Behind network configuration option that is disabled by default. --- Emby.Server.Implementations/ApplicationHost.cs | 22 +++++++++++++++++----- Jellyfin.Api/Controllers/SystemController.cs | 4 ++-- .../Configuration/NetworkConfiguration.cs | 5 +++++ .../Extensions/ApiServiceCollectionExtensions.cs | 3 ++- MediaBrowser.Controller/IServerApplicationHost.cs | 6 +++--- 5 files changed, 29 insertions(+), 11 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bf7ddace2..64ec5833f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1073,9 +1073,9 @@ namespace Emby.Server.Implementations /// <summary> /// Gets the system status. /// </summary> - /// <param name="source">Where this request originated.</param> + /// <param name="request">Where this request originated.</param> /// <returns>SystemInfo.</returns> - public SystemInfo GetSystemInfo(IPAddress source) + public SystemInfo GetSystemInfo(HttpRequest request) { return new SystemInfo { @@ -1097,7 +1097,7 @@ namespace Emby.Server.Implementations CanLaunchWebBrowser = CanLaunchWebBrowser, TranscodingTempPath = ConfigurationManager.GetTranscodePath(), ServerName = FriendlyName, - LocalAddress = GetSmartApiUrl(source), + LocalAddress = GetSmartApiUrl(request), SupportsLibraryMonitor = true, EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, @@ -1110,7 +1110,7 @@ namespace Emby.Server.Implementations .Select(i => new WakeOnLanInfo(i)) .ToList(); - public PublicSystemInfo GetPublicSystemInfo(IPAddress address) + public PublicSystemInfo GetPublicSystemInfo(HttpRequest request) { return new PublicSystemInfo { @@ -1119,7 +1119,7 @@ namespace Emby.Server.Implementations Id = SystemId, OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(), ServerName = FriendlyName, - LocalAddress = GetSmartApiUrl(address), + LocalAddress = GetSmartApiUrl(request), StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted }; } @@ -1150,6 +1150,18 @@ namespace Emby.Server.Implementations /// <inheritdoc/> public string GetSmartApiUrl(HttpRequest request, int? port = null) { + // Return the host in the HTTP request as the API url + if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest) + { + int? requestPort = request.Host.Port; + if ((requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase)) || (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase))) + { + requestPort = -1; + } + + return GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort); + } + // Published server ends with a / if (!string.IsNullOrEmpty(PublishedServerUrl)) { diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index bbbe5fb8d..ff81cc53b 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -66,7 +66,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<SystemInfo> GetSystemInfo() { - return _appHost.GetSystemInfo(Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback); + return _appHost.GetSystemInfo(Request); } /// <summary> @@ -78,7 +78,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<PublicSystemInfo> GetPublicSystemInfo() { - return _appHost.GetPublicSystemInfo(Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback); + return _appHost.GetPublicSystemInfo(Request); } /// <summary> diff --git a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs index faf814c06..61db223d9 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs @@ -226,5 +226,10 @@ namespace Jellyfin.Networking.Configuration /// Gets or sets the known proxies. If the proxy is a network, it's added to the KnownNetworks. /// </summary> public string[] KnownProxies { get; set; } = Array.Empty<string>(); + + /// <summary> + /// Gets or sets a value indicating whether the published server uri is based on information in HTTP requests. + /// </summary> + public bool EnablePublishedServerUriByRequest { get; set; } = false; } } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index f19e87aba..266dfef69 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -188,7 +188,8 @@ namespace Jellyfin.Server.Extensions // https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/HttpOverrides/src/ForwardedHeadersMiddleware.cs // Enable debug logging on Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware to help investigate issues. - options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost; + if (config.KnownProxies.Length == 0) { options.KnownNetworks.Clear(); diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 753c18bc7..07aea6ad1 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -51,11 +51,11 @@ namespace MediaBrowser.Controller /// <summary> /// Gets the system info. /// </summary> - /// <param name="source">The originator of the request.</param> + /// <param name="request">The HTTP request.</param> /// <returns>SystemInfo.</returns> - SystemInfo GetSystemInfo(IPAddress source); + SystemInfo GetSystemInfo(HttpRequest request); - PublicSystemInfo GetPublicSystemInfo(IPAddress address); + PublicSystemInfo GetPublicSystemInfo(HttpRequest request); /// <summary> /// Gets a URL specific for the request. -- cgit v1.2.3 From 03f933aaa07113b0ae6971921249691c8455d5ba Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Wed, 6 Oct 2021 11:30:45 +0200 Subject: Fix the last few warnings Enables TreatWarningsAsErrors for all projects --- Emby.Server.Implementations/ApplicationHost.cs | 38 +++----- .../Data/BaseSqliteRepository.cs | 2 +- .../Emby.Server.Implementations.csproj | 5 -- .../Images/BaseDynamicImageProvider.cs | 4 +- .../Images/BaseFolderImageProvider.cs | 67 ++++++++++++++ .../Images/FolderImageProvider.cs | 69 -------------- .../Images/GenreImageProvider.cs | 41 --------- .../Images/MusicAlbumImageProvider.cs | 19 ++++ .../Images/MusicGenreImageProvider.cs | 59 ++++++++++++ .../Images/PhotoAlbumImageProvider.cs | 19 ++++ .../Library/Resolvers/FolderResolver.cs | 22 +---- .../Library/Resolvers/GenericFolderResolver.cs | 27 ++++++ .../Library/Resolvers/Movies/BoxSetResolver.cs | 2 +- .../Library/Resolvers/PhotoAlbumResolver.cs | 2 +- .../Library/Resolvers/PlaylistResolver.cs | 2 +- .../Library/Resolvers/SpecialFolderResolver.cs | 2 +- .../Library/Resolvers/TV/SeasonResolver.cs | 2 +- .../Library/Resolvers/TV/SeriesResolver.cs | 2 +- .../Listings/SchedulesDirectDtos/ImageDataDto.cs | 2 +- .../Listings/SchedulesDirectDtos/StationDto.cs | 100 ++++++++++----------- .../HdHomerun/HdHomerunChannelCommands.cs | 35 ++++++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 10 +-- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 66 -------------- .../HdHomerun/IHdHomerunChannelCommands.cs | 11 +++ .../HdHomerun/LegacyHdHomerunChannelCommands.cs | 38 ++++++++ .../MediaBrowser.Controller.csproj | 5 -- MediaBrowser.Model/MediaBrowser.Model.csproj | 5 -- 27 files changed, 353 insertions(+), 303 deletions(-) create mode 100644 Emby.Server.Implementations/Images/BaseFolderImageProvider.cs create mode 100644 Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs create mode 100644 Emby.Server.Implementations/Images/MusicGenreImageProvider.cs create mode 100644 Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3a504d2f4..1f11bdad7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -306,7 +306,7 @@ namespace Emby.Server.Implementations /// <inheritdoc/> public string Name => ApplicationProductName; - private CertificateInfo CertificateInfo { get; set; } + private string CertificatePath { get; set; } public X509Certificate2 Certificate { get; private set; } @@ -548,12 +548,8 @@ namespace Emby.Server.Implementations HttpsPort = NetworkConfiguration.DefaultHttpsPort; } - CertificateInfo = new CertificateInfo - { - Path = networkConfiguration.CertificatePath, - Password = networkConfiguration.CertificatePassword - }; - Certificate = GetCertificate(CertificateInfo); + CertificatePath = networkConfiguration.CertificatePath; + Certificate = GetCertificate(CertificatePath, networkConfiguration.CertificatePassword); RegisterServices(); @@ -729,30 +725,27 @@ namespace Emby.Server.Implementations logger.LogInformation("Application directory: {ApplicationPath}", appPaths.ProgramSystemPath); } - private X509Certificate2 GetCertificate(CertificateInfo info) + private X509Certificate2 GetCertificate(string path, string password) { - var certificateLocation = info?.Path; - - if (string.IsNullOrWhiteSpace(certificateLocation)) + if (string.IsNullOrWhiteSpace(path)) { return null; } try { - if (!File.Exists(certificateLocation)) + if (!File.Exists(path)) { return null; } // Don't use an empty string password - var password = string.IsNullOrWhiteSpace(info.Password) ? null : info.Password; + password = string.IsNullOrWhiteSpace(password) ? null : password; - var localCert = new X509Certificate2(certificateLocation, password, X509KeyStorageFlags.UserKeySet); - // localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA; + var localCert = new X509Certificate2(path, password, X509KeyStorageFlags.UserKeySet); if (!localCert.HasPrivateKey) { - Logger.LogError("No private key included in SSL cert {CertificateLocation}.", certificateLocation); + Logger.LogError("No private key included in SSL cert {CertificateLocation}.", path); return null; } @@ -760,7 +753,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError(ex, "Error loading cert from {CertificateLocation}", certificateLocation); + Logger.LogError(ex, "Error loading cert from {CertificateLocation}", path); return null; } } @@ -882,7 +875,7 @@ namespace Emby.Server.Implementations "http://" + i + ":" + HttpPort + "/" }; - if (CertificateInfo != null) + if (Certificate != null) { prefixes.Add("https://" + i + ":" + HttpsPort + "/"); } @@ -946,7 +939,7 @@ namespace Emby.Server.Implementations var newPath = networkConfig.CertificatePath; if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(CertificateInfo?.Path, newPath, StringComparison.Ordinal)) + && !string.Equals(CertificatePath, newPath, StringComparison.Ordinal)) { if (File.Exists(newPath)) { @@ -1293,11 +1286,4 @@ namespace Emby.Server.Implementations _disposed = true; } } - - internal class CertificateInfo - { - public string Path { get; set; } - - public string Password { get; set; } - } } diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 4f6c81102..73c31f49d 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -98,7 +98,7 @@ namespace Emby.Server.Implementations.Data /// <value>The write connection.</value> protected SQLiteDatabaseConnection WriteConnection { get; set; } - protected ManagedConnection GetConnection(bool _ = false) + protected ManagedConnection GetConnection(bool readOnly = false) { WriteLock.Wait(); if (WriteConnection != null) diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 428cad071..82e4c3d69 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -47,11 +47,6 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 --> <NoWarn>AD0001</NoWarn> - <TreatWarningsAsErrors>false</TreatWarningsAsErrors> - </PropertyGroup> - - <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <!-- Code Analyzers--> diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index 4a026fd21..758986945 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -65,13 +65,13 @@ namespace Emby.Server.Implementations.Images if (SupportedImages.Contains(ImageType.Primary)) { var primaryResult = await FetchAsync(item, ImageType.Primary, options, cancellationToken).ConfigureAwait(false); - updateType = updateType | primaryResult; + updateType |= primaryResult; } if (SupportedImages.Contains(ImageType.Thumb)) { var thumbResult = await FetchAsync(item, ImageType.Thumb, options, cancellationToken).ConfigureAwait(false); - updateType = updateType | thumbResult; + updateType |= thumbResult; } return updateType; diff --git a/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs new file mode 100644 index 000000000..1c69056d2 --- /dev/null +++ b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs @@ -0,0 +1,67 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System.Collections.Generic; +using Jellyfin.Data.Enums; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; + +namespace Emby.Server.Implementations.Images +{ + public abstract class BaseFolderImageProvider<T> : BaseDynamicImageProvider<T> + where T : Folder, new() + { + private readonly ILibraryManager _libraryManager; + + public BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + _libraryManager = libraryManager; + } + + protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item) + { + return _libraryManager.GetItemList(new InternalItemsQuery + { + Parent = item, + DtoOptions = new DtoOptions(true), + ImageTypes = new ImageType[] { ImageType.Primary }, + OrderBy = new (string, SortOrder)[] + { + (ItemSortBy.IsFolder, SortOrder.Ascending), + (ItemSortBy.SortName, SortOrder.Ascending) + }, + Limit = 1 + }); + } + + protected override string CreateImage(BaseItem item, IReadOnlyCollection<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) + { + return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); + } + + protected override bool Supports(BaseItem item) + { + return item is T; + } + + protected override bool HasChangedByDate(BaseItem item, ItemImageInfo image) + { + if (item is MusicAlbum) + { + return false; + } + + return base.HasChangedByDate(item, image); + } + } +} diff --git a/Emby.Server.Implementations/Images/FolderImageProvider.cs b/Emby.Server.Implementations/Images/FolderImageProvider.cs index 859017f86..4376bd356 100644 --- a/Emby.Server.Implementations/Images/FolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/FolderImageProvider.cs @@ -2,69 +2,16 @@ #pragma warning disable CS1591 -using System.Collections.Generic; -using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { - public abstract class BaseFolderImageProvider<T> : BaseDynamicImageProvider<T> - where T : Folder, new() - { - protected ILibraryManager _libraryManager; - - public BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _libraryManager = libraryManager; - } - - protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item) - { - return _libraryManager.GetItemList(new InternalItemsQuery - { - Parent = item, - DtoOptions = new DtoOptions(true), - ImageTypes = new ImageType[] { ImageType.Primary }, - OrderBy = new System.ValueTuple<string, SortOrder>[] - { - new System.ValueTuple<string, SortOrder>(ItemSortBy.IsFolder, SortOrder.Ascending), - new System.ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) - }, - Limit = 1 - }); - } - - protected override string CreateImage(BaseItem item, IReadOnlyCollection<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); - } - - protected override bool Supports(BaseItem item) - { - return item is T; - } - - protected override bool HasChangedByDate(BaseItem item, ItemImageInfo image) - { - if (item is MusicAlbum) - { - return false; - } - - return base.HasChangedByDate(item, image); - } - } - public class FolderImageProvider : BaseFolderImageProvider<Folder> { public FolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) @@ -87,20 +34,4 @@ namespace Emby.Server.Implementations.Images return true; } } - - public class MusicAlbumImageProvider : BaseFolderImageProvider<MusicAlbum> - { - public MusicAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) - { - } - } - - public class PhotoAlbumImageProvider : BaseFolderImageProvider<PhotoAlbum> - { - public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) - { - } - } } diff --git a/Emby.Server.Implementations/Images/GenreImageProvider.cs b/Emby.Server.Implementations/Images/GenreImageProvider.cs index 6da431c68..1f5090f7f 100644 --- a/Emby.Server.Implementations/Images/GenreImageProvider.cs +++ b/Emby.Server.Implementations/Images/GenreImageProvider.cs @@ -8,7 +8,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; @@ -19,46 +18,6 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { - /// <summary> - /// Class MusicGenreImageProvider. - /// </summary> - public class MusicGenreImageProvider : BaseDynamicImageProvider<MusicGenre> - { - /// <summary> - /// The library manager. - /// </summary> - private readonly ILibraryManager _libraryManager; - - public MusicGenreImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _libraryManager = libraryManager; - } - - /// <summary> - /// Get children objects used to create an music genre image. - /// </summary> - /// <param name="item">The music genre used to create the image.</param> - /// <returns>Any relevant children objects.</returns> - protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item) - { - return _libraryManager.GetItemList(new InternalItemsQuery - { - Genres = new[] { item.Name }, - IncludeItemTypes = new[] - { - nameof(MusicAlbum), - nameof(MusicVideo), - nameof(Audio) - }, - OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) }, - Limit = 4, - Recursive = true, - ImageTypes = new[] { ImageType.Primary }, - DtoOptions = new DtoOptions(false) - }); - } - } - /// <summary> /// Class GenreImageProvider. /// </summary> diff --git a/Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs b/Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs new file mode 100644 index 000000000..ce8367363 --- /dev/null +++ b/Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs @@ -0,0 +1,19 @@ +#pragma warning disable CS1591 + +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; + +namespace Emby.Server.Implementations.Images +{ + public class MusicAlbumImageProvider : BaseFolderImageProvider<MusicAlbum> + { + public MusicAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) + { + } + } +} diff --git a/Emby.Server.Implementations/Images/MusicGenreImageProvider.cs b/Emby.Server.Implementations/Images/MusicGenreImageProvider.cs new file mode 100644 index 000000000..baf1c9051 --- /dev/null +++ b/Emby.Server.Implementations/Images/MusicGenreImageProvider.cs @@ -0,0 +1,59 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System.Collections.Generic; +using Jellyfin.Data.Enums; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; + +namespace Emby.Server.Implementations.Images +{ + /// <summary> + /// Class MusicGenreImageProvider. + /// </summary> + public class MusicGenreImageProvider : BaseDynamicImageProvider<MusicGenre> + { + /// <summary> + /// The library manager. + /// </summary> + private readonly ILibraryManager _libraryManager; + + public MusicGenreImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + _libraryManager = libraryManager; + } + + /// <summary> + /// Get children objects used to create an music genre image. + /// </summary> + /// <param name="item">The music genre used to create the image.</param> + /// <returns>Any relevant children objects.</returns> + protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item) + { + return _libraryManager.GetItemList(new InternalItemsQuery + { + Genres = new[] { item.Name }, + IncludeItemTypes = new[] + { + nameof(MusicAlbum), + nameof(MusicVideo), + nameof(Audio) + }, + OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) }, + Limit = 4, + Recursive = true, + ImageTypes = new[] { ImageType.Primary }, + DtoOptions = new DtoOptions(false) + }); + } + } +} diff --git a/Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs b/Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs new file mode 100644 index 000000000..1ddb4c757 --- /dev/null +++ b/Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs @@ -0,0 +1,19 @@ +#pragma warning disable CS1591 + +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; + +namespace Emby.Server.Implementations.Images +{ + public class PhotoAlbumImageProvider : BaseFolderImageProvider<PhotoAlbum> + { + public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) + { + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs index 7aaee017d..db7703cd6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs @@ -9,7 +9,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// <summary> /// Class FolderResolver. /// </summary> - public class FolderResolver : FolderResolver<Folder> + public class FolderResolver : GenericFolderResolver<Folder> { /// <summary> /// Gets the priority. @@ -32,24 +32,4 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } } - - /// <summary> - /// Class FolderResolver. - /// </summary> - /// <typeparam name="TItemType">The type of the T item type.</typeparam> - public abstract class FolderResolver<TItemType> : ItemResolver<TItemType> - where TItemType : Folder, new() - { - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - item.IsRoot = args.Parent == null; - } - } } diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs new file mode 100644 index 000000000..f109a5e9a --- /dev/null +++ b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs @@ -0,0 +1,27 @@ +#nullable disable + +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; + +namespace Emby.Server.Implementations.Library.Resolvers +{ + /// <summary> + /// Class FolderResolver. + /// </summary> + /// <typeparam name="TItemType">The type of the T item type.</typeparam> + public abstract class GenericFolderResolver<TItemType> : ItemResolver<TItemType> + where TItemType : Folder, new() + { + /// <summary> + /// Sets the initial item values. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="args">The args.</param> + protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) + { + base.SetInitialItemValues(item, args); + + item.IsRoot = args.Parent == null; + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index 69d71d0d9..e7abe1e6d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// <summary> /// Class BoxSetResolver. /// </summary> - public class BoxSetResolver : FolderResolver<BoxSet> + public class BoxSetResolver : GenericFolderResolver<BoxSet> { /// <summary> /// Resolves the specified args. diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index 534bc80dd..1c560e8a6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// <summary> /// Class PhotoAlbumResolver. /// </summary> - public class PhotoAlbumResolver : FolderResolver<PhotoAlbum> + public class PhotoAlbumResolver : GenericFolderResolver<PhotoAlbum> { private readonly IImageProcessor _imageProcessor; private readonly ILibraryManager _libraryManager; diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index 2c4ead719..8ce59717d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// <summary> /// <see cref="IItemResolver"/> for <see cref="Playlist"/> library items. /// </summary> - public class PlaylistResolver : FolderResolver<Playlist> + public class PlaylistResolver : GenericFolderResolver<Playlist> { private string[] _musicPlaylistCollectionTypes = { diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index a42ac4144..6bb999641 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { - public class SpecialFolderResolver : FolderResolver<Folder> + public class SpecialFolderResolver : GenericFolderResolver<Folder> { private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 7d707df18..063f67543 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// <summary> /// Class SeasonResolver. /// </summary> - public class SeasonResolver : FolderResolver<Season> + public class SeasonResolver : GenericFolderResolver<Season> { private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 4d8a6494c..b7fbe01c5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// <summary> /// Class SeriesResolver. /// </summary> - public class SeriesResolver : FolderResolver<Series> + public class SeriesResolver : GenericFolderResolver<Series> { private readonly ILogger<SeriesResolver> _logger; private readonly ILibraryManager _libraryManager; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs index 912e680dd..4e9efc60f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs @@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the aspect. /// </summary> [JsonPropertyName("aspect")] - public string aspect { get; set; } + public string Aspect { get; set; } /// <summary> /// Gets or sets the category. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs index 12f3576c6..c37f19678 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs @@ -6,62 +6,62 @@ using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos { /// <summary> - /// Station dto. - /// </summary> - public class StationDto - { - /// <summary> - /// Gets or sets the station id. - /// </summary> - [JsonPropertyName("stationID")] - public string StationId { get; set; } + /// Station dto. + /// </summary> + public class StationDto + { + /// <summary> + /// Gets or sets the station id. + /// </summary> + [JsonPropertyName("stationID")] + public string StationId { get; set; } - /// <summary> - /// Gets or sets the name. - /// </summary> - [JsonPropertyName("name")] - public string Name { get; set; } + /// <summary> + /// Gets or sets the name. + /// </summary> + [JsonPropertyName("name")] + public string Name { get; set; } - /// <summary> - /// Gets or sets the callsign. - /// </summary> - [JsonPropertyName("callsign")] - public string Callsign { get; set; } + /// <summary> + /// Gets or sets the callsign. + /// </summary> + [JsonPropertyName("callsign")] + public string Callsign { get; set; } - /// <summary> - /// Gets or sets the broadcast language. - /// </summary> - [JsonPropertyName("broadcastLanguage")] - public List<string> BroadcastLanguage { get; set; } + /// <summary> + /// Gets or sets the broadcast language. + /// </summary> + [JsonPropertyName("broadcastLanguage")] + public List<string> BroadcastLanguage { get; set; } - /// <summary> - /// Gets or sets the description language. - /// </summary> - [JsonPropertyName("descriptionLanguage")] - public List<string> DescriptionLanguage { get; set; } + /// <summary> + /// Gets or sets the description language. + /// </summary> + [JsonPropertyName("descriptionLanguage")] + public List<string> DescriptionLanguage { get; set; } - /// <summary> - /// Gets or sets the broadcaster. - /// </summary> - [JsonPropertyName("broadcaster")] - public BroadcasterDto Broadcaster { get; set; } + /// <summary> + /// Gets or sets the broadcaster. + /// </summary> + [JsonPropertyName("broadcaster")] + public BroadcasterDto Broadcaster { get; set; } - /// <summary> - /// Gets or sets the affiliate. - /// </summary> - [JsonPropertyName("affiliate")] - public string Affiliate { get; set; } + /// <summary> + /// Gets or sets the affiliate. + /// </summary> + [JsonPropertyName("affiliate")] + public string Affiliate { get; set; } - /// <summary> - /// Gets or sets the logo. - /// </summary> - [JsonPropertyName("logo")] - public LogoDto Logo { get; set; } + /// <summary> + /// Gets or sets the logo. + /// </summary> + [JsonPropertyName("logo")] + public LogoDto Logo { get; set; } - /// <summary> - /// Gets or set a value indicating whether it is commercial free. - /// </summary> - [JsonPropertyName("isCommercialFree")] - public bool? IsCommercialFree { get; set; } - } + /// <summary> + /// Gets or sets a value indicating whether it is commercial free. + /// </summary> + [JsonPropertyName("isCommercialFree")] + public bool? IsCommercialFree { get; set; } + } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs new file mode 100644 index 000000000..069b4fab6 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs @@ -0,0 +1,35 @@ +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class HdHomerunChannelCommands : IHdHomerunChannelCommands + { + private string? _channel; + private string? _profile; + + public HdHomerunChannelCommands(string? channel, string? profile) + { + _channel = channel; + _profile = profile; + } + + public IEnumerable<(string, string)> GetCommands() + { + if (!string.IsNullOrEmpty(_channel)) + { + if (!string.IsNullOrEmpty(_profile) + && !string.Equals(_profile, "native", StringComparison.OrdinalIgnoreCase)) + { + yield return ("vchannel", $"{_channel} transcode={_profile}"); + } + else + { + yield return ("vchannel", _channel); + } + } + } + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 4d538c604..78ea7bd0f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -87,11 +87,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return lineup.Where(i => !i.DRM).ToList(); } - private class HdHomerunChannelInfo : ChannelInfo - { - public bool IsLegacyTuner { get; set; } - } - protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) { var lineup = await GetLineup(tuner, cancellationToken).ConfigureAwait(false); @@ -715,5 +710,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return hostInfo; } + + private class HdHomerunChannelInfo : ChannelInfo + { + public bool IsLegacyTuner { get; set; } + } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index b2e555c7d..f0f61297f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -5,12 +5,10 @@ using System; using System.Buffers; using System.Buffers.Binary; -using System.Collections.Generic; using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -18,70 +16,6 @@ using MediaBrowser.Controller.LiveTv; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { - public interface IHdHomerunChannelCommands - { - IEnumerable<(string, string)> GetCommands(); - } - - public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands - { - private string _channel; - private string _program; - - public LegacyHdHomerunChannelCommands(string url) - { - // parse url for channel and program - var regExp = new Regex(@"\/ch([0-9]+)-?([0-9]*)"); - var match = regExp.Match(url); - if (match.Success) - { - _channel = match.Groups[1].Value; - _program = match.Groups[2].Value; - } - } - - public IEnumerable<(string, string)> GetCommands() - { - if (!string.IsNullOrEmpty(_channel)) - { - yield return ("channel", _channel); - } - - if (!string.IsNullOrEmpty(_program)) - { - yield return ("program", _program); - } - } - } - - public class HdHomerunChannelCommands : IHdHomerunChannelCommands - { - private string _channel; - private string _profile; - - public HdHomerunChannelCommands(string channel, string profile) - { - _channel = channel; - _profile = profile; - } - - public IEnumerable<(string, string)> GetCommands() - { - if (!string.IsNullOrEmpty(_channel)) - { - if (!string.IsNullOrEmpty(_profile) - && !string.Equals(_profile, "native", StringComparison.OrdinalIgnoreCase)) - { - yield return ("vchannel", $"{_channel} transcode={_profile}"); - } - else - { - yield return ("vchannel", _channel); - } - } - } - } - public sealed class HdHomerunManager : IDisposable { public const int HdHomeRunPort = 65001; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs new file mode 100644 index 000000000..153354932 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs @@ -0,0 +1,11 @@ +#pragma warning disable CS1591 + +using System.Collections.Generic; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public interface IHdHomerunChannelCommands + { + IEnumerable<(string, string)> GetCommands(); + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs new file mode 100644 index 000000000..26627b8aa --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs @@ -0,0 +1,38 @@ +#pragma warning disable CS1591 + +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands + { + private string? _channel; + private string? _program; + + public LegacyHdHomerunChannelCommands(string url) + { + // parse url for channel and program + var regExp = new Regex(@"\/ch([0-9]+)-?([0-9]*)"); + var match = regExp.Match(url); + if (match.Success) + { + _channel = match.Groups[1].Value; + _program = match.Groups[2].Value; + } + } + + public IEnumerable<(string, string)> GetCommands() + { + if (!string.IsNullOrEmpty(_channel)) + { + yield return ("channel", _channel); + } + + if (!string.IsNullOrEmpty(_program)) + { + yield return ("program", _program); + } + } + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 47cec7d77..4b3a75b90 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -39,11 +39,6 @@ <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> <SymbolPackageFormat>snupkg</SymbolPackageFormat> - <TreatWarningsAsErrors>false</TreatWarningsAsErrors> - </PropertyGroup> - - <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b0a12a9c9..91803ade6 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -21,11 +21,6 @@ <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> <SymbolPackageFormat>snupkg</SymbolPackageFormat> - <TreatWarningsAsErrors>false</TreatWarningsAsErrors> - </PropertyGroup> - - <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> -- cgit v1.2.3