From 141efafd3dbbef3dc64824a89fd3fdc77da0b25e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 20 Feb 2021 23:13:04 +0100 Subject: [PATCH] Enable TreatWarningsAsErrors for MediaBrowser.Model --- Emby.Dlna/ContentDirectory/StubType.cs | 2 +- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Dlna/PlayTo/TransportState.cs | 2 +- .../Data/SqliteItemRepository.cs | 6 +- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 2 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 6 +- .../Channels/ChannelFeatures.cs | 18 +- MediaBrowser.Model/Channels/ChannelQuery.cs | 6 +- .../Configuration/EncodingOptions.cs | 74 +- .../Configuration/ImageOption.cs | 10 +- .../Configuration/LibraryOptions.cs | 403 +----- .../Configuration/MediaPathInfo.cs | 12 + .../Configuration/MetadataConfiguration.cs | 4 +- .../Configuration/MetadataOptions.cs | 20 +- .../Configuration/MetadataPluginSummary.cs | 12 +- .../Configuration/TypeOptions.cs | 365 +++++ .../Configuration/UserConfiguration.cs | 36 +- .../Configuration/XbmcMetadataOptions.cs | 16 +- MediaBrowser.Model/Dlna/AudioOptions.cs | 9 +- MediaBrowser.Model/Dlna/CodecProfile.cs | 12 +- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 2 +- MediaBrowser.Model/Dlna/ContainerProfile.cs | 10 +- .../Dlna/ContentFeatureBuilder.cs | 36 +- MediaBrowser.Model/Dlna/IDeviceDiscovery.cs | 1 + .../Dlna/MediaFormatProfileResolver.cs | 4 +- .../Dlna/ResolutionConfiguration.cs | 8 +- MediaBrowser.Model/Dlna/ResponseProfile.cs | 10 +- MediaBrowser.Model/Dlna/SearchCriteria.cs | 54 +- MediaBrowser.Model/Dlna/SortCriteria.cs | 4 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 14 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 1190 +++++++++-------- MediaBrowser.Model/Dto/BaseItemDto.cs | 10 +- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 67 +- MediaBrowser.Model/Dto/MetadataEditorInfo.cs | 18 +- MediaBrowser.Model/Dto/NameGuidPair.cs | 14 + MediaBrowser.Model/Dto/NameIdPair.cs | 7 - MediaBrowser.Model/Dto/UserDto.cs | 18 +- MediaBrowser.Model/Entities/CollectionType.cs | 32 - MediaBrowser.Model/Entities/MediaStream.cs | 197 ++- .../Entities/PackageReviewInfo.cs | 40 - MediaBrowser.Model/Entities/SpecialFolder.cs | 36 + .../Entities/VirtualFolderInfo.cs | 16 +- .../Globalization/CultureDto.cs | 12 +- MediaBrowser.Model/IO/IFileSystem.cs | 7 +- MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs | 16 +- .../LiveTv/ListingsProviderInfo.cs | 58 + .../LiveTv/LiveTvChannelQuery.cs | 26 +- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 97 +- .../LiveTv/LiveTvServiceInfo.cs | 10 +- MediaBrowser.Model/LiveTv/RecordingQuery.cs | 16 +- .../LiveTv/SeriesTimerInfoDto.cs | 16 +- MediaBrowser.Model/LiveTv/TunerHostInfo.cs | 38 + MediaBrowser.Model/MediaBrowser.Model.csproj | 4 +- MediaBrowser.Model/MediaInfo/MediaInfo.cs | 22 +- .../MediaInfo/PlaybackInfoRequest.cs | 22 +- .../MediaInfo/PlaybackInfoResponse.cs | 16 +- .../MediaInfo/SubtitleTrackInfo.cs | 4 +- MediaBrowser.Model/Net/ISocket.cs | 6 + MediaBrowser.Model/Net/ISocketFactory.cs | 3 + MediaBrowser.Model/Net/MimeTypes.cs | 21 +- MediaBrowser.Model/Net/NetworkShare.cs | 33 - MediaBrowser.Model/Net/SocketReceiveResult.cs | 4 +- MediaBrowser.Model/Net/WebSocketMessage.cs | 2 +- .../Notifications/NotificationOptions.cs | 10 +- .../Notifications/NotificationRequest.cs | 14 +- .../Providers/ExternalIdInfo.cs | 4 +- .../Providers/RemoteImageInfo.cs | 2 +- .../Providers/SubtitleOptions.cs | 16 +- MediaBrowser.Model/Querying/EpisodeQuery.cs | 10 +- .../Querying/LatestItemsQuery.cs | 9 +- .../Querying/MovieRecommendationQuery.cs | 14 +- MediaBrowser.Model/Querying/NextUpQuery.cs | 20 +- MediaBrowser.Model/Querying/QueryFilters.cs | 25 +- .../Querying/QueryFiltersLegacy.cs | 26 + MediaBrowser.Model/Querying/QueryResult.cs | 26 +- .../Querying/UpcomingEpisodesQuery.cs | 16 +- MediaBrowser.Model/Search/SearchQuery.cs | 32 +- MediaBrowser.Model/Session/BrowseRequest.cs | 1 + .../Session/ClientCapabilities.cs | 14 +- MediaBrowser.Model/Session/GeneralCommand.cs | 13 +- .../Session/PlaybackProgressInfo.cs | 14 - .../Session/PlaystateCommand.cs | 6 +- MediaBrowser.Model/Session/QueueItem.cs | 14 + MediaBrowser.Model/Session/RepeatMode.cs | 11 + MediaBrowser.Model/Session/TranscodeReason.cs | 31 + MediaBrowser.Model/Session/TranscodingInfo.cs | 37 +- MediaBrowser.Model/Sync/SyncJob.cs | 10 +- MediaBrowser.Model/System/SystemInfo.cs | 18 +- MediaBrowser.Model/System/WakeOnLanInfo.cs | 2 +- .../Tasks/IScheduledTaskWorker.cs | 5 +- MediaBrowser.Model/Tasks/ITaskManager.cs | 20 +- MediaBrowser.Model/Tasks/ITaskTrigger.cs | 4 + MediaBrowser.Model/Tasks/TaskInfo.cs | 16 +- MediaBrowser.Model/Tasks/TaskTriggerInfo.cs | 12 +- MediaBrowser.Model/Users/UserPolicy.cs | 100 +- jellyfin.ruleset | 2 + .../ModelBinders/TestType.cs | 6 - 98 files changed, 1908 insertions(+), 1892 deletions(-) create mode 100644 MediaBrowser.Model/Configuration/MediaPathInfo.cs create mode 100644 MediaBrowser.Model/Configuration/TypeOptions.cs create mode 100644 MediaBrowser.Model/Dto/NameGuidPair.cs delete mode 100644 MediaBrowser.Model/Entities/PackageReviewInfo.cs create mode 100644 MediaBrowser.Model/Entities/SpecialFolder.cs create mode 100644 MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs create mode 100644 MediaBrowser.Model/LiveTv/TunerHostInfo.cs delete mode 100644 MediaBrowser.Model/Net/NetworkShare.cs create mode 100644 MediaBrowser.Model/Querying/QueryFiltersLegacy.cs create mode 100644 MediaBrowser.Model/Session/QueueItem.cs create mode 100644 MediaBrowser.Model/Session/RepeatMode.cs create mode 100644 MediaBrowser.Model/Session/TranscodeReason.cs diff --git a/Emby.Dlna/ContentDirectory/StubType.cs b/Emby.Dlna/ContentDirectory/StubType.cs index 982ae5d68e..a5116055d1 100644 --- a/Emby.Dlna/ContentDirectory/StubType.cs +++ b/Emby.Dlna/ContentDirectory/StubType.cs @@ -1,5 +1,5 @@ #pragma warning disable CS1591 -#pragma warning disable SA1602 + namespace Emby.Dlna.ContentDirectory { diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 21ba1c7552..9ab3240388 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -553,7 +553,7 @@ namespace Emby.Dlna private void DumpProfiles() { - DeviceProfile[] list = new [] + DeviceProfile[] list = new[] { new SamsungSmartTvProfile(), new XboxOneProfile(), diff --git a/Emby.Dlna/PlayTo/TransportState.cs b/Emby.Dlna/PlayTo/TransportState.cs index 7068a5d24d..1ca71283a8 100644 --- a/Emby.Dlna/PlayTo/TransportState.cs +++ b/Emby.Dlna/PlayTo/TransportState.cs @@ -1,5 +1,5 @@ #pragma warning disable CS1591 -#pragma warning disable SA1602 + namespace Emby.Dlna.PlayTo { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index dad8bec7b0..d78b93bd78 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -6207,9 +6207,9 @@ AND Type = @InternalPersonType)"); if (item.Type == MediaStreamType.Subtitle) { - item.localizedUndefined = _localization.GetLocalizedString("Undefined"); - item.localizedDefault = _localization.GetLocalizedString("Default"); - item.localizedForced = _localization.GetLocalizedString("Forced"); + item.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); + item.LocalizedDefault = _localization.GetLocalizedString("Default"); + item.LocalizedForced = _localization.GetLocalizedString("Forced"); } return item; diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 0d8315dee1..ce6740fc99 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -523,7 +523,7 @@ namespace Jellyfin.Api.Helpers /// Dlna profile type. public void NormalizeMediaSourceContainer(MediaSourceInfo mediaSource, DeviceProfile profile, DlnaProfileType type) { - mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, mediaSource.Path, profile, type); + mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, profile, type); } private void SetDeviceSpecificSubtitleInfo(StreamInfo info, MediaSourceInfo mediaSource, string accessToken) diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 4957ee8b8d..8df1f5c272 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -183,7 +183,7 @@ namespace Jellyfin.Api.Helpers if (string.IsNullOrEmpty(containerInternal)) { containerInternal = streamingRequest.Static ? - StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, state.MediaPath, null, DlnaProfileType.Audio) + StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, null, DlnaProfileType.Audio) : GetOutputFileExtension(state); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index b5291b5609..b9cb49cf2f 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -681,9 +681,9 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.Type = MediaStreamType.Subtitle; stream.Codec = NormalizeSubtitleCodec(stream.Codec); - stream.localizedUndefined = _localization.GetLocalizedString("Undefined"); - stream.localizedDefault = _localization.GetLocalizedString("Default"); - stream.localizedForced = _localization.GetLocalizedString("Forced"); + stream.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); + stream.LocalizedDefault = _localization.GetLocalizedString("Default"); + stream.LocalizedForced = _localization.GetLocalizedString("Forced"); } else if (string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Channels/ChannelFeatures.cs b/MediaBrowser.Model/Channels/ChannelFeatures.cs index a55754eddc..d925b78b6d 100644 --- a/MediaBrowser.Model/Channels/ChannelFeatures.cs +++ b/MediaBrowser.Model/Channels/ChannelFeatures.cs @@ -7,6 +7,13 @@ namespace MediaBrowser.Model.Channels { public class ChannelFeatures { + public ChannelFeatures() + { + MediaTypes = Array.Empty(); + ContentTypes = Array.Empty(); + DefaultSortFields = Array.Empty(); + } + /// /// Gets or sets the name. /// @@ -38,7 +45,7 @@ namespace MediaBrowser.Model.Channels public ChannelMediaContentType[] ContentTypes { get; set; } /// - /// Represents the maximum number of records the channel allows retrieving at a time. + /// Gets or sets the maximum number of records the channel allows retrieving at a time. /// public int? MaxPageSize { get; set; } @@ -55,7 +62,7 @@ namespace MediaBrowser.Model.Channels public ChannelItemSortField[] DefaultSortFields { get; set; } /// - /// Indicates if a sort ascending/descending toggle is supported or not. + /// Gets or sets a value indicating whether a sort ascending/descending toggle is supported. /// public bool SupportsSortOrderToggle { get; set; } @@ -76,12 +83,5 @@ namespace MediaBrowser.Model.Channels /// /// true if [supports content downloading]; otherwise, false. public bool SupportsContentDownloading { get; set; } - - public ChannelFeatures() - { - MediaTypes = Array.Empty(); - ContentTypes = Array.Empty(); - DefaultSortFields = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Channels/ChannelQuery.cs b/MediaBrowser.Model/Channels/ChannelQuery.cs index fd90e7f062..59966127fb 100644 --- a/MediaBrowser.Model/Channels/ChannelQuery.cs +++ b/MediaBrowser.Model/Channels/ChannelQuery.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Model.Channels public class ChannelQuery { /// - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } @@ -28,13 +28,13 @@ namespace MediaBrowser.Model.Channels public Guid UserId { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index da467e133f..a9b2803017 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -5,6 +5,41 @@ namespace MediaBrowser.Model.Configuration { public class EncodingOptions { + public EncodingOptions() + { + EnableFallbackFont = false; + DownMixAudioBoost = 2; + MaxMuxingQueueSize = 2048; + EnableThrottling = false; + ThrottleDelaySeconds = 180; + EncodingThreadCount = -1; + // This is a DRM device that is almost guaranteed to be there on every intel platform, + // plus it's the default one in ffmpeg if you don't specify anything + VaapiDevice = "/dev/dri/renderD128"; + // This is the OpenCL device that is used for tonemapping. + // The left side of the dot is the platform number, and the right side is the device number on the platform. + OpenclDevice = "0.0"; + EnableTonemapping = false; + EnableVppTonemapping = false; + TonemappingAlgorithm = "hable"; + TonemappingRange = "auto"; + TonemappingDesat = 0; + TonemappingThreshold = 0.8; + TonemappingPeak = 100; + TonemappingParam = 0; + H264Crf = 23; + H265Crf = 28; + DeinterlaceDoubleRate = false; + DeinterlaceMethod = "yadif"; + EnableDecodingColorDepth10Hevc = true; + EnableDecodingColorDepth10Vp9 = true; + EnableEnhancedNvdecDecoder = true; + EnableHardwareEncoding = true; + AllowHevcEncoding = true; + EnableSubtitleExtraction = true; + HardwareDecodingCodecs = new string[] { "h264", "vc1" }; + } + public int EncodingThreadCount { get; set; } public string TranscodingTempPath { get; set; } @@ -24,12 +59,12 @@ namespace MediaBrowser.Model.Configuration public string HardwareAccelerationType { get; set; } /// - /// FFmpeg path as set by the user via the UI. + /// Gets or sets the FFmpeg path as set by the user via the UI. /// public string EncoderAppPath { get; set; } /// - /// The current FFmpeg path being used by the system and displayed on the transcode page. + /// Gets or sets the current FFmpeg path being used by the system and displayed on the transcode page. /// public string EncoderAppPathDisplay { get; set; } @@ -76,40 +111,5 @@ namespace MediaBrowser.Model.Configuration public bool EnableSubtitleExtraction { get; set; } public string[] HardwareDecodingCodecs { get; set; } - - public EncodingOptions() - { - EnableFallbackFont = false; - DownMixAudioBoost = 2; - MaxMuxingQueueSize = 2048; - EnableThrottling = false; - ThrottleDelaySeconds = 180; - EncodingThreadCount = -1; - // This is a DRM device that is almost guaranteed to be there on every intel platform, - // plus it's the default one in ffmpeg if you don't specify anything - VaapiDevice = "/dev/dri/renderD128"; - // This is the OpenCL device that is used for tonemapping. - // The left side of the dot is the platform number, and the right side is the device number on the platform. - OpenclDevice = "0.0"; - EnableTonemapping = false; - EnableVppTonemapping = false; - TonemappingAlgorithm = "hable"; - TonemappingRange = "auto"; - TonemappingDesat = 0; - TonemappingThreshold = 0.8; - TonemappingPeak = 100; - TonemappingParam = 0; - H264Crf = 23; - H265Crf = 28; - DeinterlaceDoubleRate = false; - DeinterlaceMethod = "yadif"; - EnableDecodingColorDepth10Hevc = true; - EnableDecodingColorDepth10Vp9 = true; - EnableEnhancedNvdecDecoder = true; - EnableHardwareEncoding = true; - AllowHevcEncoding = true; - EnableSubtitleExtraction = true; - HardwareDecodingCodecs = new string[] { "h264", "vc1" }; - } } } diff --git a/MediaBrowser.Model/Configuration/ImageOption.cs b/MediaBrowser.Model/Configuration/ImageOption.cs index 2b1268c743..0af7b7e146 100644 --- a/MediaBrowser.Model/Configuration/ImageOption.cs +++ b/MediaBrowser.Model/Configuration/ImageOption.cs @@ -6,6 +6,11 @@ namespace MediaBrowser.Model.Configuration { public class ImageOption { + public ImageOption() + { + Limit = 1; + } + /// /// Gets or sets the type. /// @@ -23,10 +28,5 @@ namespace MediaBrowser.Model.Configuration /// /// The minimum width. public int MinWidth { get; set; } - - public ImageOption() - { - Limit = 1; - } } } diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 77ac11d69f..24698360ec 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -2,13 +2,30 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Model.Configuration { public class LibraryOptions { + public LibraryOptions() + { + TypeOptions = Array.Empty(); + DisabledSubtitleFetchers = Array.Empty(); + SubtitleFetcherOrder = Array.Empty(); + DisabledLocalMetadataReaders = Array.Empty(); + + SkipSubtitlesIfAudioTrackMatches = true; + RequirePerfectSubtitleMatch = true; + + EnablePhotos = true; + SaveSubtitlesWithMedia = true; + EnableRealtimeMonitor = true; + PathInfos = Array.Empty(); + EnableInternetProviders = true; + EnableAutomaticSeriesGrouping = true; + SeasonZeroDisplayName = "Specials"; + } + public bool EnablePhotos { get; set; } public bool EnableRealtimeMonitor { get; set; } @@ -79,387 +96,5 @@ namespace MediaBrowser.Model.Configuration return null; } - - public LibraryOptions() - { - TypeOptions = Array.Empty(); - DisabledSubtitleFetchers = Array.Empty(); - SubtitleFetcherOrder = Array.Empty(); - DisabledLocalMetadataReaders = Array.Empty(); - - SkipSubtitlesIfAudioTrackMatches = true; - RequirePerfectSubtitleMatch = true; - - EnablePhotos = true; - SaveSubtitlesWithMedia = true; - EnableRealtimeMonitor = true; - PathInfos = Array.Empty(); - EnableInternetProviders = true; - EnableAutomaticSeriesGrouping = true; - SeasonZeroDisplayName = "Specials"; - } - } - - public class MediaPathInfo - { - public string Path { get; set; } - - public string NetworkPath { get; set; } - } - - public class TypeOptions - { - public string Type { get; set; } - - public string[] MetadataFetchers { get; set; } - - public string[] MetadataFetcherOrder { get; set; } - - public string[] ImageFetchers { get; set; } - - public string[] ImageFetcherOrder { get; set; } - - public ImageOption[] ImageOptions { get; set; } - - public ImageOption GetImageOptions(ImageType type) - { - foreach (var i in ImageOptions) - { - if (i.Type == type) - { - return i; - } - } - - if (DefaultImageOptions.TryGetValue(Type, out ImageOption[] options)) - { - foreach (var i in options) - { - if (i.Type == type) - { - return i; - } - } - } - - return DefaultInstance; - } - - public int GetLimit(ImageType type) - { - return GetImageOptions(type).Limit; - } - - public int GetMinWidth(ImageType type) - { - return GetImageOptions(type).MinWidth; - } - - public bool IsEnabled(ImageType type) - { - return GetLimit(type) > 0; - } - - public TypeOptions() - { - MetadataFetchers = Array.Empty(); - MetadataFetcherOrder = Array.Empty(); - ImageFetchers = Array.Empty(); - ImageFetcherOrder = Array.Empty(); - ImageOptions = Array.Empty(); - } - - public static Dictionary DefaultImageOptions = new Dictionary - { - { - "Movie", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "MusicVideo", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "Series", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "MusicAlbum", new [] - { - new ImageOption - { - Limit = 0, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - } - } - }, - { - "MusicArtist", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default - // They do look great, but most artists won't have them, which means a banner view isn't really possible - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - // Don't download this by default - // Generally not used - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "BoxSet", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - } - } - }, - { - "Season", new [] - { - new ImageOption - { - Limit = 0, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Thumb - } - } - }, - { - "Episode", new [] - { - new ImageOption - { - Limit = 0, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - } - } - } - }; - - public static ImageOption DefaultInstance = new ImageOption(); } } diff --git a/MediaBrowser.Model/Configuration/MediaPathInfo.cs b/MediaBrowser.Model/Configuration/MediaPathInfo.cs new file mode 100644 index 0000000000..4f311c58f0 --- /dev/null +++ b/MediaBrowser.Model/Configuration/MediaPathInfo.cs @@ -0,0 +1,12 @@ +#nullable disable +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Configuration +{ + public class MediaPathInfo + { + public string Path { get; set; } + + public string NetworkPath { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/MetadataConfiguration.cs b/MediaBrowser.Model/Configuration/MetadataConfiguration.cs index 706831bddc..be044243dd 100644 --- a/MediaBrowser.Model/Configuration/MetadataConfiguration.cs +++ b/MediaBrowser.Model/Configuration/MetadataConfiguration.cs @@ -4,11 +4,11 @@ namespace MediaBrowser.Model.Configuration { public class MetadataConfiguration { - public bool UseFileCreationTimeForDateAdded { get; set; } - public MetadataConfiguration() { UseFileCreationTimeForDateAdded = true; } + + public bool UseFileCreationTimeForDateAdded { get; set; } } } diff --git a/MediaBrowser.Model/Configuration/MetadataOptions.cs b/MediaBrowser.Model/Configuration/MetadataOptions.cs index e7dc3da3cb..76b72bd08e 100644 --- a/MediaBrowser.Model/Configuration/MetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/MetadataOptions.cs @@ -10,6 +10,16 @@ namespace MediaBrowser.Model.Configuration /// public class MetadataOptions { + public MetadataOptions() + { + DisabledMetadataSavers = Array.Empty(); + LocalMetadataReaderOrder = Array.Empty(); + DisabledMetadataFetchers = Array.Empty(); + MetadataFetcherOrder = Array.Empty(); + DisabledImageFetchers = Array.Empty(); + ImageFetcherOrder = Array.Empty(); + } + public string ItemType { get; set; } public string[] DisabledMetadataSavers { get; set; } @@ -23,15 +33,5 @@ namespace MediaBrowser.Model.Configuration public string[] DisabledImageFetchers { get; set; } public string[] ImageFetcherOrder { get; set; } - - public MetadataOptions() - { - DisabledMetadataSavers = Array.Empty(); - LocalMetadataReaderOrder = Array.Empty(); - DisabledMetadataFetchers = Array.Empty(); - MetadataFetcherOrder = Array.Empty(); - DisabledImageFetchers = Array.Empty(); - ImageFetcherOrder = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs b/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs index 0c197ee021..aa07d66237 100644 --- a/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs +++ b/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs @@ -8,6 +8,12 @@ namespace MediaBrowser.Model.Configuration { public class MetadataPluginSummary { + public MetadataPluginSummary() + { + SupportedImageTypes = Array.Empty(); + Plugins = Array.Empty(); + } + /// /// Gets or sets the type of the item. /// @@ -25,11 +31,5 @@ namespace MediaBrowser.Model.Configuration /// /// The supported image types. public ImageType[] SupportedImageTypes { get; set; } - - public MetadataPluginSummary() - { - SupportedImageTypes = Array.Empty(); - Plugins = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Configuration/TypeOptions.cs b/MediaBrowser.Model/Configuration/TypeOptions.cs new file mode 100644 index 0000000000..d0179e5aab --- /dev/null +++ b/MediaBrowser.Model/Configuration/TypeOptions.cs @@ -0,0 +1,365 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Model.Configuration +{ + public class TypeOptions + { + public static readonly ImageOption DefaultInstance = new ImageOption(); + + public static readonly Dictionary DefaultImageOptions = new Dictionary + { + { + "Movie", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "MusicVideo", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "Series", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "MusicAlbum", new[] + { + new ImageOption + { + Limit = 0, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + } + } + }, + { + "MusicArtist", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default + // They do look great, but most artists won't have them, which means a banner view isn't really possible + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + // Don't download this by default + // Generally not used + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "BoxSet", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + } + } + }, + { + "Season", new[] + { + new ImageOption + { + Limit = 0, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Thumb + } + } + }, + { + "Episode", new[] + { + new ImageOption + { + Limit = 0, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + } + } + } + }; + + public TypeOptions() + { + MetadataFetchers = Array.Empty(); + MetadataFetcherOrder = Array.Empty(); + ImageFetchers = Array.Empty(); + ImageFetcherOrder = Array.Empty(); + ImageOptions = Array.Empty(); + } + + public string Type { get; set; } + + public string[] MetadataFetchers { get; set; } + + public string[] MetadataFetcherOrder { get; set; } + + public string[] ImageFetchers { get; set; } + + public string[] ImageFetcherOrder { get; set; } + + public ImageOption[] ImageOptions { get; set; } + + public ImageOption GetImageOptions(ImageType type) + { + foreach (var i in ImageOptions) + { + if (i.Type == type) + { + return i; + } + } + + if (DefaultImageOptions.TryGetValue(Type, out ImageOption[] options)) + { + foreach (var i in options) + { + if (i.Type == type) + { + return i; + } + } + } + + return DefaultInstance; + } + + public int GetLimit(ImageType type) + { + return GetImageOptions(type).Limit; + } + + public int GetMinWidth(ImageType type) + { + return GetImageOptions(type).MinWidth; + } + + public bool IsEnabled(ImageType type) + { + return GetLimit(type) > 0; + } + } +} diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index cc0e0c4681..935e6cbe10 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -11,6 +11,24 @@ namespace MediaBrowser.Model.Configuration /// public class UserConfiguration { + /// + /// Initializes a new instance of the class. + /// + public UserConfiguration() + { + EnableNextEpisodeAutoPlay = true; + RememberAudioSelections = true; + RememberSubtitleSelections = true; + + HidePlayedInLatest = true; + PlayDefaultAudioTrack = true; + + LatestItemsExcludes = Array.Empty(); + OrderedViews = Array.Empty(); + MyMediaExcludes = Array.Empty(); + GroupedFolders = Array.Empty(); + } + /// /// Gets or sets the audio language preference. /// @@ -52,23 +70,5 @@ namespace MediaBrowser.Model.Configuration public bool RememberSubtitleSelections { get; set; } public bool EnableNextEpisodeAutoPlay { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public UserConfiguration() - { - EnableNextEpisodeAutoPlay = true; - RememberAudioSelections = true; - RememberSubtitleSelections = true; - - HidePlayedInLatest = true; - PlayDefaultAudioTrack = true; - - LatestItemsExcludes = Array.Empty(); - OrderedViews = Array.Empty(); - MyMediaExcludes = Array.Empty(); - GroupedFolders = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs index 4d5f996f84..8ad070dcbf 100644 --- a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs @@ -5,6 +5,14 @@ namespace MediaBrowser.Model.Configuration { public class XbmcMetadataOptions { + public XbmcMetadataOptions() + { + ReleaseDateFormat = "yyyy-MM-dd"; + + SaveImagePathsInNfo = true; + EnablePathSubstitution = true; + } + public string UserId { get; set; } public string ReleaseDateFormat { get; set; } @@ -14,13 +22,5 @@ namespace MediaBrowser.Model.Configuration public bool EnablePathSubstitution { get; set; } public bool EnableExtraThumbsDuplication { get; set; } - - public XbmcMetadataOptions() - { - ReleaseDateFormat = "yyyy-MM-dd"; - - SaveImagePathsInNfo = true; - EnablePathSubstitution = true; - } } } diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index bbb8bf4263..4d4d8d78cb 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -34,20 +34,20 @@ namespace MediaBrowser.Model.Dlna public DeviceProfile Profile { get; set; } /// - /// Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested. + /// Gets or sets a media source id. Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested. /// public string MediaSourceId { get; set; } public string DeviceId { get; set; } /// - /// Allows an override of supported number of audio channels - /// Example: DeviceProfile supports five channel, but user only has stereo speakers + /// Gets or sets an override of supported number of audio channels + /// Example: DeviceProfile supports five channel, but user only has stereo speakers. /// public int? MaxAudioChannels { get; set; } /// - /// The application's configured quality setting. + /// Gets or sets the application's configured quality setting. /// public int? MaxBitrate { get; set; } @@ -66,6 +66,7 @@ namespace MediaBrowser.Model.Dlna /// /// Gets the maximum bitrate. /// + /// Whether or not this is audio. /// System.Nullable<System.Int32>. public int? GetMaxBitrate(bool isAudio) { diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index d4fd3e6730..8343cf028b 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -9,6 +9,12 @@ namespace MediaBrowser.Model.Dlna { public class CodecProfile { + public CodecProfile() + { + Conditions = Array.Empty(); + ApplyConditions = Array.Empty(); + } + [XmlAttribute("type")] public CodecType Type { get; set; } @@ -22,12 +28,6 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("container")] public string Container { get; set; } - public CodecProfile() - { - Conditions = Array.Empty(); - ApplyConditions = Array.Empty(); - } - public string[] GetCodecs() { return ContainerProfile.SplitValue(Codec); diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index faf1ee41be..55c4dd0742 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -1,8 +1,8 @@ #pragma warning disable CS1591 using System; -using System.Linq; using System.Globalization; +using System.Linq; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index 56c89d854f..d83c8f2f3c 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -9,6 +9,11 @@ namespace MediaBrowser.Model.Dlna { public class ContainerProfile { + public ContainerProfile() + { + Conditions = Array.Empty(); + } + [XmlAttribute("type")] public DlnaProfileType Type { get; set; } @@ -17,11 +22,6 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("container")] public string Container { get; set; } - public ContainerProfile() - { - Conditions = Array.Empty(); - } - public string[] GetContainers() { return SplitValue(Container); diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 50e3374f77..ec106f1054 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -81,13 +81,13 @@ namespace MediaBrowser.Model.Dlna DlnaFlags.DlnaV15; // if (isDirectStream) - //{ - // flagValue = flagValue | DlnaFlags.ByteBasedSeek; - //} - // else if (runtimeTicks.HasValue) - //{ - // flagValue = flagValue | DlnaFlags.TimeBasedSeek; - //} + // { + // flagValue = flagValue | DlnaFlags.ByteBasedSeek; + // } + // else if (runtimeTicks.HasValue) + // { + // flagValue = flagValue | DlnaFlags.TimeBasedSeek; + // } string dlnaflags = string.Format( CultureInfo.InvariantCulture, @@ -150,16 +150,18 @@ namespace MediaBrowser.Model.Dlna DlnaFlags.DlnaV15; // if (isDirectStream) - //{ - // flagValue = flagValue | DlnaFlags.ByteBasedSeek; - //} - // else if (runtimeTicks.HasValue) - //{ - // flagValue = flagValue | DlnaFlags.TimeBasedSeek; - //} - - string dlnaflags = string.Format(CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}", - DlnaMaps.FlagsToString(flagValue)); + // { + // flagValue = flagValue | DlnaFlags.ByteBasedSeek; + // } + // else if (runtimeTicks.HasValue) + // { + // flagValue = flagValue | DlnaFlags.TimeBasedSeek; + // } + + string dlnaflags = string.Format( + CultureInfo.InvariantCulture, + ";DLNA.ORG_FLAGS={0}", + DlnaMaps.FlagsToString(flagValue)); ResponseProfile mediaProfile = _profile.GetVideoMediaProfile( container, diff --git a/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs b/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs index 05209e53d0..086088deae 100644 --- a/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs +++ b/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Model.Dlna public interface IDeviceDiscovery { event EventHandler> DeviceDiscovered; + event EventHandler> DeviceLeft; } } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index 3c955989a1..f61b8d59e8 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -57,7 +57,6 @@ namespace MediaBrowser.Model.Dlna string.Equals(container, "mpegts", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "m2ts", StringComparison.OrdinalIgnoreCase)) { - return ResolveVideoMPEG2TSFormat(videoCodec, audioCodec, width, height, timestampType); } @@ -323,7 +322,6 @@ namespace MediaBrowser.Model.Dlna if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase) && (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "wmapro", StringComparison.OrdinalIgnoreCase))) { - if (width.HasValue && height.HasValue) { if ((width.Value <= 720) && (height.Value <= 576)) @@ -479,7 +477,9 @@ namespace MediaBrowser.Model.Dlna { if (string.Equals(container, "jpeg", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "jpg", StringComparison.OrdinalIgnoreCase)) + { return ResolveImageJPGFormat(width, height); + } if (string.Equals(container, "png", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs b/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs index 30c44fbe0e..f8f76c69d8 100644 --- a/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs +++ b/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs @@ -4,14 +4,14 @@ namespace MediaBrowser.Model.Dlna { public class ResolutionConfiguration { - public int MaxWidth { get; set; } - - public int MaxBitrate { get; set; } - public ResolutionConfiguration(int maxWidth, int maxBitrate) { MaxWidth = maxWidth; MaxBitrate = maxBitrate; } + + public int MaxWidth { get; set; } + + public int MaxBitrate { get; set; } } } diff --git a/MediaBrowser.Model/Dlna/ResponseProfile.cs b/MediaBrowser.Model/Dlna/ResponseProfile.cs index 48f53f06c2..bf9661f7f3 100644 --- a/MediaBrowser.Model/Dlna/ResponseProfile.cs +++ b/MediaBrowser.Model/Dlna/ResponseProfile.cs @@ -8,6 +8,11 @@ namespace MediaBrowser.Model.Dlna { public class ResponseProfile { + public ResponseProfile() + { + Conditions = Array.Empty(); + } + [XmlAttribute("container")] public string Container { get; set; } @@ -28,11 +33,6 @@ namespace MediaBrowser.Model.Dlna public ProfileCondition[] Conditions { get; set; } - public ResponseProfile() - { - Conditions = Array.Empty(); - } - public string[] GetContainers() { return ContainerProfile.SplitValue(Container); diff --git a/MediaBrowser.Model/Dlna/SearchCriteria.cs b/MediaBrowser.Model/Dlna/SearchCriteria.cs index 94f5bd3dbe..b1fc48c087 100644 --- a/MediaBrowser.Model/Dlna/SearchCriteria.cs +++ b/MediaBrowser.Model/Dlna/SearchCriteria.cs @@ -7,31 +7,6 @@ namespace MediaBrowser.Model.Dlna { public class SearchCriteria { - public SearchType SearchType { get; set; } - - /// - /// Splits the specified string. - /// - /// The string. - /// The term. - /// The limit. - /// System.String[]. - private static string[] RegexSplit(string str, string term, int limit) - { - return new Regex(term).Split(str, limit); - } - - /// - /// Splits the specified string. - /// - /// The string. - /// The term. - /// System.String[]. - private static string[] RegexSplit(string str, string term) - { - return Regex.Split(str, term, RegexOptions.IgnoreCase); - } - public SearchCriteria(string search) { if (search.Length == 0) @@ -48,8 +23,8 @@ namespace MediaBrowser.Model.Dlna if (subFactors.Length == 3) { - if (string.Equals("upnp:class", subFactors[0], StringComparison.OrdinalIgnoreCase) && - (string.Equals("=", subFactors[1], StringComparison.Ordinal) || string.Equals("derivedfrom", subFactors[1], StringComparison.OrdinalIgnoreCase))) + if (string.Equals("upnp:class", subFactors[0], StringComparison.OrdinalIgnoreCase) + && (string.Equals("=", subFactors[1], StringComparison.Ordinal) || string.Equals("derivedfrom", subFactors[1], StringComparison.OrdinalIgnoreCase))) { if (string.Equals("\"object.item.imageItem\"", subFactors[2], StringComparison.Ordinal) || string.Equals("\"object.item.imageItem.photo\"", subFactors[2], StringComparison.OrdinalIgnoreCase)) { @@ -71,5 +46,30 @@ namespace MediaBrowser.Model.Dlna } } } + + public SearchType SearchType { get; set; } + + /// + /// Splits the specified string. + /// + /// The string. + /// The term. + /// The limit. + /// System.String[]. + private static string[] RegexSplit(string str, string term, int limit) + { + return new Regex(term).Split(str, limit); + } + + /// + /// Splits the specified string. + /// + /// The string. + /// The term. + /// System.String[]. + private static string[] RegexSplit(string str, string term) + { + return Regex.Split(str, term, RegexOptions.IgnoreCase); + } } } diff --git a/MediaBrowser.Model/Dlna/SortCriteria.cs b/MediaBrowser.Model/Dlna/SortCriteria.cs index 53e4540cbb..7769d0bd3e 100644 --- a/MediaBrowser.Model/Dlna/SortCriteria.cs +++ b/MediaBrowser.Model/Dlna/SortCriteria.cs @@ -6,10 +6,10 @@ namespace MediaBrowser.Model.Dlna { public class SortCriteria { - public SortOrder SortOrder => SortOrder.Ascending; - public SortCriteria(string value) { } + + public SortOrder SortOrder => SortOrder.Ascending; } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a3983afe5f..bf33691c77 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -227,7 +227,7 @@ namespace MediaBrowser.Model.Dlna } } - public static string NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, string _, DeviceProfile profile, DlnaProfileType type) + public static string NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, DeviceProfile profile, DlnaProfileType type) { if (string.IsNullOrEmpty(inputContainer)) { @@ -274,14 +274,14 @@ namespace MediaBrowser.Model.Dlna if (options.ForceDirectPlay) { playlistItem.PlayMethod = PlayMethod.DirectPlay; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Audio); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } if (options.ForceDirectStream) { playlistItem.PlayMethod = PlayMethod.DirectStream; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Audio); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } @@ -349,7 +349,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.PlayMethod = PlayMethod.DirectStream; } - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Audio); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } @@ -698,7 +698,7 @@ namespace MediaBrowser.Model.Dlna if (directPlay != null) { playlistItem.PlayMethod = directPlay.Value; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Video); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Video); if (subtitleStream != null) { @@ -1404,7 +1404,9 @@ namespace MediaBrowser.Model.Dlna { _logger.LogInformation( "Bitrate exceeds {PlayBackMethod} limit: media bitrate: {MediaBitrate}, max bitrate: {MaxBitrate}", - playMethod, itemBitrate, requestedMaxBitrate); + playMethod, + itemBitrate, + requestedMaxBitrate); return false; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 4765052d59..f7010dcd0f 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -27,45 +27,6 @@ namespace MediaBrowser.Model.Dlna StreamOptions = new Dictionary(StringComparer.OrdinalIgnoreCase); } - public void SetOption(string qualifier, string name, string value) - { - if (string.IsNullOrEmpty(qualifier)) - { - SetOption(name, value); - } - else - { - SetOption(qualifier + "-" + name, value); - } - } - - public void SetOption(string name, string value) - { - StreamOptions[name] = value; - } - - public string GetOption(string qualifier, string name) - { - var value = GetOption(qualifier + "-" + name); - - if (string.IsNullOrEmpty(value)) - { - value = GetOption(name); - } - - return value; - } - - public string GetOption(string name) - { - if (StreamOptions.TryGetValue(name, out var value)) - { - return value; - } - - return null; - } - public Guid ItemId { get; set; } public PlayMethod PlayMethod { get; set; } @@ -152,887 +113,928 @@ namespace MediaBrowser.Model.Dlna PlayMethod == PlayMethod.DirectStream || PlayMethod == PlayMethod.DirectPlay; - public string ToUrl(string baseUrl, string accessToken) + /// + /// Gets the audio stream that will be used. + /// + public MediaStream TargetAudioStream { - if (PlayMethod == PlayMethod.DirectPlay) + get { - return MediaSource.Path; + if (MediaSource != null) + { + return MediaSource.GetDefaultAudioStream(AudioStreamIndex); + } + + return null; } + } - if (string.IsNullOrEmpty(baseUrl)) + /// + /// Gets the video stream that will be used. + /// + public MediaStream TargetVideoStream + { + get { - throw new ArgumentNullException(nameof(baseUrl)); + if (MediaSource != null) + { + return MediaSource.VideoStream; + } + + return null; } + } - var list = new List(); - foreach (NameValuePair pair in BuildParams(this, accessToken)) + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public int? TargetAudioSampleRate + { + get { - if (string.IsNullOrEmpty(pair.Value)) + var stream = TargetAudioStream; + return AudioSampleRate.HasValue && !IsDirectStream + ? AudioSampleRate + : stream == null ? null : stream.SampleRate; + } + } + + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public int? TargetAudioBitDepth + { + get + { + if (IsDirectStream) { - continue; + return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; } - // Try to keep the url clean by omitting defaults - if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) + var targetAudioCodecs = TargetAudioCodec; + var audioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; + if (!string.IsNullOrEmpty(audioCodec)) { - continue; + return GetTargetAudioBitDepth(audioCodec); } - if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) + return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; + } + } + + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public int? TargetVideoBitDepth + { + get + { + if (IsDirectStream) { - continue; + return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; } - // Be careful, IsDirectStream==true by default (Static != false or not in query). - // See initialization of StreamingRequestDto in AudioController.GetAudioStream() method : Static = @static ?? true. - if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "true", StringComparison.OrdinalIgnoreCase)) + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) { - continue; + return GetTargetVideoBitDepth(videoCodec); } - var encodedValue = pair.Value.Replace(" ", "%20", StringComparison.Ordinal); - - list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); + return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; } - - string queryString = string.Join('&', list); - - return GetUrl(baseUrl, queryString); } - private string GetUrl(string baseUrl, string queryString) + /// + /// Gets the target reference frames. + /// + /// The target reference frames. + public int? TargetRefFrames { - if (string.IsNullOrEmpty(baseUrl)) + get { - throw new ArgumentNullException(nameof(baseUrl)); - } - - string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container; - - baseUrl = baseUrl.TrimEnd('/'); + if (IsDirectStream) + { + return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + } - if (MediaType == DlnaProfileType.Audio) - { - if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) { - return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + return GetTargetRefFrames(videoCodec); } - return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; } + } - if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public float? TargetFramerate + { + get { - return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + var stream = TargetVideoStream; + return MaxFramerate.HasValue && !IsDirectStream + ? MaxFramerate + : stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate; } - - return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } - private static List BuildParams(StreamInfo item, string accessToken) + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public double? TargetVideoLevel { - var list = new List(); - - string audioCodecs = item.AudioCodecs.Length == 0 ? - string.Empty : - string.Join(',', item.AudioCodecs); - - string videoCodecs = item.VideoCodecs.Length == 0 ? - string.Empty : - string.Join(',', item.VideoCodecs); - - list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); - list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); - list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty)); - list.Add(new NameValuePair("Static", item.IsDirectStream.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - list.Add(new NameValuePair("VideoCodec", videoCodecs)); - list.Add(new NameValuePair("AudioCodec", audioCodecs)); - list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - long startPositionTicks = item.StartPositionTicks; + get + { + if (IsDirectStream) + { + return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + } - var isHls = string.Equals(item.SubProtocol, "hls", StringComparison.OrdinalIgnoreCase); + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) + { + return GetTargetVideoLevel(videoCodec); + } - if (isHls) - { - list.Add(new NameValuePair("StartTimeTicks", string.Empty)); + return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; } - else + } + + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public int? TargetPacketLength + { + get { - list.Add(new NameValuePair("StartTimeTicks", startPositionTicks.ToString(CultureInfo.InvariantCulture))); + var stream = TargetVideoStream; + return !IsDirectStream + ? null + : stream == null ? null : stream.PacketLength; } + } - list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); - list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); - - string liveStreamId = item.MediaSource?.LiveStreamId; - list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); - - list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); - - if (!item.IsDirectStream) + /// + /// Gets the audio sample rate that will be in the output stream. + /// + public string TargetVideoProfile + { + get { - if (item.RequireNonAnamorphic) + if (IsDirectStream) { - list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + return TargetVideoStream == null ? null : TargetVideoStream.Profile; } - list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? item.TranscodingMaxAudioChannels.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - if (item.EnableSubtitlesInManifest) + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) { - list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - if (item.EnableMpegtsM2TsMode) - { - list.Add(new NameValuePair("EnableMpegtsM2TsMode", item.EnableMpegtsM2TsMode.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - if (item.EstimateContentLength) - { - list.Add(new NameValuePair("EstimateContentLength", item.EstimateContentLength.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - if (item.TranscodeSeekInfo != TranscodeSeekInfo.Auto) - { - list.Add(new NameValuePair("TranscodeSeekInfo", item.TranscodeSeekInfo.ToString().ToLowerInvariant())); - } - - if (item.CopyTimestamps) - { - list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); - - string subtitleCodecs = item.SubtitleCodecs.Length == 0 ? - string.Empty : - string.Join(',', item.SubtitleCodecs); - - list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); - - if (isHls) - { - list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty)); - - if (item.SegmentLength.HasValue) - { - list.Add(new NameValuePair("SegmentLength", item.SegmentLength.Value.ToString(CultureInfo.InvariantCulture))); - } - - if (item.MinSegments.HasValue) - { - list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture))); - } - - list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCulture))); - } - - foreach (var pair in item.StreamOptions) - { - if (string.IsNullOrEmpty(pair.Value)) - { - continue; + return GetOption(videoCodec, "profile"); } - // strip spaces to avoid having to encode h264 profile names - list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty, StringComparison.Ordinal))); + return TargetVideoStream == null ? null : TargetVideoStream.Profile; } + } - if (!item.IsDirectStream) + /// + /// Gets the target video codec tag. + /// + /// The target video codec tag. + public string TargetVideoCodecTag + { + get { - list.Add(new NameValuePair("TranscodeReasons", string.Join(',', item.TranscodeReasons.Distinct().Select(i => i.ToString())))); + var stream = TargetVideoStream; + return !IsDirectStream + ? null + : stream == null ? null : stream.CodecTag; } - - return list; } - public List GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) + /// + /// Gets the audio bitrate that will be in the output stream. + /// + public int? TargetAudioBitrate { - return GetExternalSubtitles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + get + { + var stream = TargetAudioStream; + return AudioBitrate.HasValue && !IsDirectStream + ? AudioBitrate + : stream == null ? null : stream.BitRate; + } } - public List GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + /// + /// Gets the audio channels that will be in the output stream. + /// + public int? TargetAudioChannels { - var list = GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); - var newList = new List(); - - // First add the selected track - foreach (SubtitleStreamInfo stream in list) + get { - if (stream.DeliveryMethod == SubtitleDeliveryMethod.External) + if (IsDirectStream) { - newList.Add(stream); + return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; } - } - return newList; - } + var targetAudioCodecs = TargetAudioCodec; + var codec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; + if (!string.IsNullOrEmpty(codec)) + { + return GetTargetRefFrames(codec); + } - public List GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) - { - return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + } } - public List GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + /// + /// Gets the audio codec that will be in the output stream. + /// + public string[] TargetAudioCodec { - var list = new List(); + get + { + var stream = TargetAudioStream; - // HLS will preserve timestamps so we can just grab the full subtitle stream - long startPositionTicks = string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase) - ? 0 - : (PlayMethod == PlayMethod.Transcode && !CopyTimestamps ? StartPositionTicks : 0); + string inputCodec = stream?.Codec; - // First add the selected track - if (SubtitleStreamIndex.HasValue) - { - foreach (var stream in MediaSource.MediaStreams) + if (IsDirectStream) { - if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) - { - AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); - } + return string.IsNullOrEmpty(inputCodec) ? Array.Empty() : new[] { inputCodec }; } - } - if (!includeSelectedTrackOnly) - { - foreach (var stream in MediaSource.MediaStreams) + foreach (string codec in AudioCodecs) { - if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) + if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) { - AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); + return string.IsNullOrEmpty(codec) ? Array.Empty() : new[] { codec }; } } - } - - return list; - } - - private void AddSubtitleProfiles(List list, MediaStream stream, ITranscoderSupport transcoderSupport, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) - { - if (enableAllProfiles) - { - foreach (var profile in DeviceProfile.SubtitleProfiles) - { - var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, transcoderSupport); - - list.Add(info); - } - } - else - { - var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport); - list.Add(info); + return AudioCodecs; } } - private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport) + public string[] TargetVideoCodec { - var subtitleProfile = StreamBuilder.GetSubtitleProfile(MediaSource, stream, subtitleProfiles, PlayMethod, transcoderSupport, Container, SubProtocol); - var info = new SubtitleStreamInfo + get { - IsForced = stream.IsForced, - Language = stream.Language, - Name = stream.Language ?? "Unknown", - Format = subtitleProfile.Format, - Index = stream.Index, - DeliveryMethod = subtitleProfile.Method, - DisplayTitle = stream.DisplayTitle - }; + var stream = TargetVideoStream; - if (info.DeliveryMethod == SubtitleDeliveryMethod.External) - { - if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, StringComparison.OrdinalIgnoreCase) || !stream.IsExternal) + string inputCodec = stream?.Codec; + + if (IsDirectStream) { - info.Url = string.Format(CultureInfo.InvariantCulture, "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", - baseUrl, - ItemId, - MediaSourceId, - stream.Index.ToString(CultureInfo.InvariantCulture), - startPositionTicks.ToString(CultureInfo.InvariantCulture), - subtitleProfile.Format); + return string.IsNullOrEmpty(inputCodec) ? Array.Empty() : new[] { inputCodec }; + } - if (!string.IsNullOrEmpty(accessToken)) + foreach (string codec in VideoCodecs) + { + if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) { - info.Url += "?api_key=" + accessToken; + return string.IsNullOrEmpty(codec) ? Array.Empty() : new[] { codec }; } - - info.IsExternalUrl = false; } - else - { - info.Url = stream.Path; - info.IsExternalUrl = true; - } - } - return info; + return VideoCodecs; + } } /// - /// Returns the audio stream that will be used. + /// Gets the audio channels that will be in the output stream. /// - public MediaStream TargetAudioStream + public long? TargetSize { get { - if (MediaSource != null) + if (IsDirectStream) { - return MediaSource.GetDefaultAudioStream(AudioStreamIndex); + return MediaSource.Size; + } + + if (RunTimeTicks.HasValue) + { + int? totalBitrate = TargetTotalBitrate; + + double totalSeconds = RunTimeTicks.Value; + // Convert to ms + totalSeconds /= 10000; + // Convert to seconds + totalSeconds /= 1000; + + return totalBitrate.HasValue ? + Convert.ToInt64(totalBitrate.Value * totalSeconds) : + (long?)null; } return null; } } - /// - /// Returns the video stream that will be used. - /// - public MediaStream TargetVideoStream + public int? TargetVideoBitrate { get { - if (MediaSource != null) - { - return MediaSource.VideoStream; - } + var stream = TargetVideoStream; - return null; + return VideoBitrate.HasValue && !IsDirectStream + ? VideoBitrate + : stream == null ? null : stream.BitRate; } } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public int? TargetAudioSampleRate + public TransportStreamTimestamp TargetTimestamp { get { - var stream = TargetAudioStream; - return AudioSampleRate.HasValue && !IsDirectStream - ? AudioSampleRate - : stream == null ? null : stream.SampleRate; + var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase) + ? TransportStreamTimestamp.Valid + : TransportStreamTimestamp.None; + + return !IsDirectStream + ? defaultValue + : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None; } } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public int? TargetAudioBitDepth + public int? TargetTotalBitrate => (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0); + + public bool? IsTargetAnamorphic { get { if (IsDirectStream) { - return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; - } - - var targetAudioCodecs = TargetAudioCodec; - var audioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; - if (!string.IsNullOrEmpty(audioCodec)) - { - return GetTargetAudioBitDepth(audioCodec); + return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic; } - return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; + return false; } } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public int? TargetVideoBitDepth + public bool? IsTargetInterlaced { get { if (IsDirectStream) { - return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; + return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } var targetVideoCodecs = TargetVideoCodec; var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; if (!string.IsNullOrEmpty(videoCodec)) { - return GetTargetVideoBitDepth(videoCodec); + if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) + { + return false; + } } - return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; + return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } } - /// - /// Gets the target reference frames. - /// - /// The target reference frames. - public int? TargetRefFrames + public bool? IsTargetAVC { get { if (IsDirectStream) { - return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; - } - - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) - { - return GetTargetRefFrames(videoCodec); + return TargetVideoStream == null ? null : TargetVideoStream.IsAVC; } - return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + return true; } } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public float? TargetFramerate + public int? TargetWidth { get { - var stream = TargetVideoStream; - return MaxFramerate.HasValue && !IsDirectStream - ? MaxFramerate - : stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate; + var videoStream = TargetVideoStream; + + if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) + { + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + + return size.Width; + } + + return MaxWidth; } } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public double? TargetVideoLevel + public int? TargetHeight { get { - if (IsDirectStream) - { - return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; - } + var videoStream = TargetVideoStream; - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) + if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) { - return GetTargetVideoLevel(videoCodec); + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + + return size.Height; } - return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + return MaxHeight; } } - public int? GetTargetVideoBitDepth(string codec) + public int? TargetVideoStreamCount { - var value = GetOption(codec, "videobitdepth"); - if (string.IsNullOrEmpty(value)) + get { - return null; - } + if (IsDirectStream) + { + return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue); + } - if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) - { - return result; + return GetMediaStreamCount(MediaStreamType.Video, 1); } - - return null; } - public int? GetTargetAudioBitDepth(string codec) + public int? TargetAudioStreamCount { - var value = GetOption(codec, "audiobitdepth"); - if (string.IsNullOrEmpty(value)) - { - return null; - } - - if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + get { - return result; - } + if (IsDirectStream) + { + return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue); + } - return null; + return GetMediaStreamCount(MediaStreamType.Audio, 1); + } } - public double? GetTargetVideoLevel(string codec) + public void SetOption(string qualifier, string name, string value) { - var value = GetOption(codec, "level"); - if (string.IsNullOrEmpty(value)) + if (string.IsNullOrEmpty(qualifier)) { - return null; + SetOption(name, value); } - - if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + else { - return result; + SetOption(qualifier + "-" + name, value); } + } - return null; + public void SetOption(string name, string value) + { + StreamOptions[name] = value; } - public int? GetTargetRefFrames(string codec) + public string GetOption(string qualifier, string name) { - var value = GetOption(codec, "maxrefframes"); + var value = GetOption(qualifier + "-" + name); + if (string.IsNullOrEmpty(value)) { - return null; + value = GetOption(name); } - if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + return value; + } + + public string GetOption(string name) + { + if (StreamOptions.TryGetValue(name, out var value)) { - return result; + return value; } return null; } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public int? TargetPacketLength + public string ToUrl(string baseUrl, string accessToken) { - get + if (PlayMethod == PlayMethod.DirectPlay) { - var stream = TargetVideoStream; - return !IsDirectStream - ? null - : stream == null ? null : stream.PacketLength; + return MediaSource.Path; } - } - /// - /// Predicts the audio sample rate that will be in the output stream. - /// - public string TargetVideoProfile - { - get + if (string.IsNullOrEmpty(baseUrl)) { - if (IsDirectStream) + throw new ArgumentNullException(nameof(baseUrl)); + } + + var list = new List(); + foreach (NameValuePair pair in BuildParams(this, accessToken)) + { + if (string.IsNullOrEmpty(pair.Value)) { - return TargetVideoStream == null ? null : TargetVideoStream.Profile; + continue; } - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) + // Try to keep the url clean by omitting defaults + if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) && + string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) { - return GetOption(videoCodec, "profile"); + continue; } - return TargetVideoStream == null ? null : TargetVideoStream.Profile; - } - } + if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) && + string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) + { + continue; + } - /// - /// Gets the target video codec tag. - /// - /// The target video codec tag. - public string TargetVideoCodecTag - { - get - { - var stream = TargetVideoStream; - return !IsDirectStream - ? null - : stream == null ? null : stream.CodecTag; + // Be careful, IsDirectStream==true by default (Static != false or not in query). + // See initialization of StreamingRequestDto in AudioController.GetAudioStream() method : Static = @static ?? true. + if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && + string.Equals(pair.Value, "true", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var encodedValue = pair.Value.Replace(" ", "%20"); + + list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } + + string queryString = string.Join("&", list.ToArray()); + + return GetUrl(baseUrl, queryString); } - /// - /// Predicts the audio bitrate that will be in the output stream. - /// - public int? TargetAudioBitrate + private string GetUrl(string baseUrl, string queryString) { - get + if (string.IsNullOrEmpty(baseUrl)) { - var stream = TargetAudioStream; - return AudioBitrate.HasValue && !IsDirectStream - ? AudioBitrate - : stream == null ? null : stream.BitRate; + throw new ArgumentNullException(nameof(baseUrl)); } - } - /// - /// Predicts the audio channels that will be in the output stream. - /// - public int? TargetAudioChannels - { - get + string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container; + + baseUrl = baseUrl.TrimEnd('/'); + + if (MediaType == DlnaProfileType.Audio) { - if (IsDirectStream) + if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - var targetAudioCodecs = TargetAudioCodec; - var codec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; - if (!string.IsNullOrEmpty(codec)) - { - return GetTargetRefFrames(codec); - } + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + } - return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) + { + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } + + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } - public int? GetTargetAudioChannels(string codec) + private static List BuildParams(StreamInfo item, string accessToken) { - var defaultValue = GlobalMaxAudioChannels ?? TranscodingMaxAudioChannels; + var list = new List(); - var value = GetOption(codec, "audiochannels"); - if (string.IsNullOrEmpty(value)) + string audioCodecs = item.AudioCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.AudioCodecs); + + string videoCodecs = item.VideoCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.VideoCodecs); + + list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); + list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); + list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty)); + list.Add(new NameValuePair("Static", item.IsDirectStream.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + list.Add(new NameValuePair("VideoCodec", videoCodecs)); + list.Add(new NameValuePair("AudioCodec", audioCodecs)); + list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + + list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + + long startPositionTicks = item.StartPositionTicks; + + var isHls = string.Equals(item.SubProtocol, "hls", StringComparison.OrdinalIgnoreCase); + + if (isHls) { - return defaultValue; + list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } - - if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + else { - return Math.Min(result, defaultValue ?? result); + list.Add(new NameValuePair("StartTimeTicks", startPositionTicks.ToString(CultureInfo.InvariantCulture))); } - return defaultValue; - } + list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); + list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); - /// - /// Predicts the audio codec that will be in the output stream. - /// - public string[] TargetAudioCodec - { - get - { - var stream = TargetAudioStream; + string liveStreamId = item.MediaSource?.LiveStreamId; + list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); - string inputCodec = stream?.Codec; + list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); - if (IsDirectStream) + if (!item.IsDirectStream) + { + if (item.RequireNonAnamorphic) { - return string.IsNullOrEmpty(inputCodec) ? Array.Empty() : new[] { inputCodec }; + list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - foreach (string codec in AudioCodecs) + list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? item.TranscodingMaxAudioChannels.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + + if (item.EnableSubtitlesInManifest) { - if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) - { - return string.IsNullOrEmpty(codec) ? Array.Empty() : new[] { codec }; - } + list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - return AudioCodecs; - } - } - - public string[] TargetVideoCodec - { - get - { - var stream = TargetVideoStream; + if (item.EnableMpegtsM2TsMode) + { + list.Add(new NameValuePair("EnableMpegtsM2TsMode", item.EnableMpegtsM2TsMode.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + } - string inputCodec = stream?.Codec; + if (item.EstimateContentLength) + { + list.Add(new NameValuePair("EstimateContentLength", item.EstimateContentLength.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + } - if (IsDirectStream) + if (item.TranscodeSeekInfo != TranscodeSeekInfo.Auto) { - return string.IsNullOrEmpty(inputCodec) ? Array.Empty() : new[] { inputCodec }; + list.Add(new NameValuePair("TranscodeSeekInfo", item.TranscodeSeekInfo.ToString().ToLowerInvariant())); } - foreach (string codec in VideoCodecs) + if (item.CopyTimestamps) { - if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) - { - return string.IsNullOrEmpty(codec) ? Array.Empty() : new[] { codec }; - } + list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - return VideoCodecs; + list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - } - /// - /// Predicts the audio channels that will be in the output stream. - /// - public long? TargetSize - { - get + list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); + + string subtitleCodecs = item.SubtitleCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.SubtitleCodecs); + + list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); + + if (isHls) { - if (IsDirectStream) + list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty)); + + if (item.SegmentLength.HasValue) { - return MediaSource.Size; + list.Add(new NameValuePair("SegmentLength", item.SegmentLength.Value.ToString(CultureInfo.InvariantCulture))); } - if (RunTimeTicks.HasValue) + if (item.MinSegments.HasValue) { - int? totalBitrate = TargetTotalBitrate; - - double totalSeconds = RunTimeTicks.Value; - // Convert to ms - totalSeconds /= 10000; - // Convert to seconds - totalSeconds /= 1000; - - return totalBitrate.HasValue ? - Convert.ToInt64(totalBitrate.Value * totalSeconds) : - (long?)null; + list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture))); } - return null; + list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCulture))); } - } - public int? TargetVideoBitrate - { - get + foreach (var pair in item.StreamOptions) { - var stream = TargetVideoStream; + if (string.IsNullOrEmpty(pair.Value)) + { + continue; + } - return VideoBitrate.HasValue && !IsDirectStream - ? VideoBitrate - : stream == null ? null : stream.BitRate; + // strip spaces to avoid having to encode h264 profile names + list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty))); } - } - public TransportStreamTimestamp TargetTimestamp - { - get + if (!item.IsDirectStream) { - var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase) - ? TransportStreamTimestamp.Valid - : TransportStreamTimestamp.None; - - return !IsDirectStream - ? defaultValue - : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None; + list.Add(new NameValuePair("TranscodeReasons", string.Join(',', item.TranscodeReasons.Distinct()))); } + + return list; } - public int? TargetTotalBitrate => (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0); + public List GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) + { + return GetExternalSubtitles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + } - public bool? IsTargetAnamorphic + public List GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) { - get + var list = GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); + var newList = new List(); + + // First add the selected track + foreach (SubtitleStreamInfo stream in list) { - if (IsDirectStream) + if (stream.DeliveryMethod == SubtitleDeliveryMethod.External) { - return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic; + newList.Add(stream); } - - return false; } + + return newList; } - public bool? IsTargetInterlaced + public List GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) { - get + return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + } + + public List GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + { + var list = new List(); + + // HLS will preserve timestamps so we can just grab the full subtitle stream + long startPositionTicks = string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase) + ? 0 + : (PlayMethod == PlayMethod.Transcode && !CopyTimestamps ? StartPositionTicks : 0); + + // First add the selected track + if (SubtitleStreamIndex.HasValue) { - if (IsDirectStream) + foreach (var stream in MediaSource.MediaStreams) { - return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; + if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) + { + AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); + } } + } - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) + if (!includeSelectedTrackOnly) + { + foreach (var stream in MediaSource.MediaStreams) { - if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) + if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) { - return false; + AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); } } - - return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } + + return list; } - public bool? IsTargetAVC + private void AddSubtitleProfiles(List list, MediaStream stream, ITranscoderSupport transcoderSupport, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) { - get + if (enableAllProfiles) { - if (IsDirectStream) + foreach (var profile in DeviceProfile.SubtitleProfiles) { - return TargetVideoStream == null ? null : TargetVideoStream.IsAVC; + var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, transcoderSupport); + + list.Add(info); } + } + else + { + var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport); - return true; + list.Add(info); } } - public int? TargetWidth + private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport) { - get + var subtitleProfile = StreamBuilder.GetSubtitleProfile(MediaSource, stream, subtitleProfiles, PlayMethod, transcoderSupport, Container, SubProtocol); + var info = new SubtitleStreamInfo { - var videoStream = TargetVideoStream; + IsForced = stream.IsForced, + Language = stream.Language, + Name = stream.Language ?? "Unknown", + Format = subtitleProfile.Format, + Index = stream.Index, + DeliveryMethod = subtitleProfile.Method, + DisplayTitle = stream.DisplayTitle + }; - if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) + if (info.DeliveryMethod == SubtitleDeliveryMethod.External) + { + if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, StringComparison.OrdinalIgnoreCase) || !stream.IsExternal) { - ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + info.Url = string.Format( + CultureInfo.InvariantCulture, + "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", + baseUrl, + ItemId, + MediaSourceId, + stream.Index.ToString(CultureInfo.InvariantCulture), + startPositionTicks.ToString(CultureInfo.InvariantCulture), + subtitleProfile.Format); - size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + if (!string.IsNullOrEmpty(accessToken)) + { + info.Url += "?api_key=" + accessToken; + } - return size.Width; + info.IsExternalUrl = false; + } + else + { + info.Url = stream.Path; + info.IsExternalUrl = true; } + } - return MaxWidth; + return info; + } + + public int? GetTargetVideoBitDepth(string codec) + { + var value = GetOption(codec, "videobitdepth"); + if (string.IsNullOrEmpty(value)) + { + return null; + } + + if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + return result; } + + return null; } - public int? TargetHeight + public int? GetTargetAudioBitDepth(string codec) { - get + var value = GetOption(codec, "audiobitdepth"); + if (string.IsNullOrEmpty(value)) { - var videoStream = TargetVideoStream; + return null; + } - if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) - { - ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + return result; + } - size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + return null; + } - return size.Height; - } + public double? GetTargetVideoLevel(string codec) + { + var value = GetOption(codec, "level"); + if (string.IsNullOrEmpty(value)) + { + return null; + } - return MaxHeight; + if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; } + + return null; } - public int? TargetVideoStreamCount + public int? GetTargetRefFrames(string codec) { - get + var value = GetOption(codec, "maxrefframes"); + if (string.IsNullOrEmpty(value)) { - if (IsDirectStream) - { - return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue); - } + return null; + } - return GetMediaStreamCount(MediaStreamType.Video, 1); + if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; } + + return null; } - public int? TargetAudioStreamCount + public int? GetTargetAudioChannels(string codec) { - get + var defaultValue = GlobalMaxAudioChannels ?? TranscodingMaxAudioChannels; + + var value = GetOption(codec, "audiochannels"); + if (string.IsNullOrEmpty(value)) { - if (IsDirectStream) - { - return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue); - } + return defaultValue; + } - return GetMediaStreamCount(MediaStreamType.Audio, 1); + if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + return Math.Min(result, defaultValue ?? result); } + + return defaultValue; } private int? GetMediaStreamCount(MediaStreamType type, int limit) diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 2f9f9d3cdb..a784025e3d 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -294,13 +294,13 @@ namespace MediaBrowser.Model.Dto public NameGuidPair[] GenreItems { get; set; } /// - /// If the item does not have a logo, this will hold the Id of the Parent that has one. + /// Gets or sets wether the item has a logo, this will hold the Id of the Parent that has one. /// /// The parent logo item id. public string ParentLogoItemId { get; set; } /// - /// If the item does not have any backdrops, this will hold the Id of the Parent that has one. + /// Gets or sets wether the item has any backdrops, this will hold the Id of the Parent that has one. /// /// The parent backdrop item id. public string ParentBackdropItemId { get; set; } @@ -318,7 +318,7 @@ namespace MediaBrowser.Model.Dto public int? LocalTrailerCount { get; set; } /// - /// User data for this item based on the user it's being requested for. + /// Gets or sets the user data for this item based on the user it's being requested for. /// /// The user data. public UserItemDataDto UserData { get; set; } @@ -506,7 +506,7 @@ namespace MediaBrowser.Model.Dto public string ParentLogoImageTag { get; set; } /// - /// If the item does not have a art, this will hold the Id of the Parent that has one. + /// Gets or sets wether the item has fan art, this will hold the Id of the Parent that has one. /// /// The parent art item id. public string ParentArtItemId { get; set; } @@ -695,7 +695,7 @@ namespace MediaBrowser.Model.Dto public string ChannelPrimaryImageTag { get; set; } /// - /// The start date of the recording, in UTC. + /// Gets or sets the start date of the recording, in UTC. /// public DateTime? StartDate { get; set; } diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index be682be23c..ec3b37efa3 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -12,6 +12,18 @@ namespace MediaBrowser.Model.Dto { public class MediaSourceInfo { + public MediaSourceInfo() + { + Formats = Array.Empty(); + MediaStreams = new List(); + MediaAttachments = Array.Empty(); + RequiredHttpHeaders = new Dictionary(); + SupportsTranscoding = true; + SupportsDirectStream = true; + SupportsDirectPlay = true; + SupportsProbing = true; + } + public MediaProtocol Protocol { get; set; } public string Id { get; set; } @@ -31,6 +43,7 @@ namespace MediaBrowser.Model.Dto public string Name { get; set; } /// + /// Gets or sets a value indicating whether the media is remote. /// Differentiate internet url vs local network. /// public bool IsRemote { get; set; } @@ -95,16 +108,28 @@ namespace MediaBrowser.Model.Dto public int? AnalyzeDurationMs { get; set; } - public MediaSourceInfo() + [JsonIgnore] + public TranscodeReason[] TranscodeReasons { get; set; } + + public int? DefaultAudioStreamIndex { get; set; } + + public int? DefaultSubtitleStreamIndex { get; set; } + + [JsonIgnore] + public MediaStream VideoStream { - Formats = Array.Empty(); - MediaStreams = new List(); - MediaAttachments = Array.Empty(); - RequiredHttpHeaders = new Dictionary(); - SupportsTranscoding = true; - SupportsDirectStream = true; - SupportsDirectPlay = true; - SupportsProbing = true; + get + { + foreach (var i in MediaStreams) + { + if (i.Type == MediaStreamType.Video) + { + return i; + } + } + + return null; + } } public void InferTotalBitrate(bool force = false) @@ -134,13 +159,6 @@ namespace MediaBrowser.Model.Dto } } - [JsonIgnore] - public TranscodeReason[] TranscodeReasons { get; set; } - - public int? DefaultAudioStreamIndex { get; set; } - - public int? DefaultSubtitleStreamIndex { get; set; } - public MediaStream GetDefaultAudioStream(int? defaultIndex) { if (defaultIndex.HasValue) @@ -175,23 +193,6 @@ namespace MediaBrowser.Model.Dto return null; } - [JsonIgnore] - public MediaStream VideoStream - { - get - { - foreach (var i in MediaStreams) - { - if (i.Type == MediaStreamType.Video) - { - return i; - } - } - - return null; - } - } - public MediaStream GetMediaStream(MediaStreamType type, int index) { foreach (var i in MediaStreams) diff --git a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs index e4f38d6af3..e0e889f7d0 100644 --- a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs +++ b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs @@ -10,6 +10,15 @@ namespace MediaBrowser.Model.Dto { public class MetadataEditorInfo { + public MetadataEditorInfo() + { + ParentalRatingOptions = Array.Empty(); + Countries = Array.Empty(); + Cultures = Array.Empty(); + ExternalIdInfos = Array.Empty(); + ContentTypeOptions = Array.Empty(); + } + public ParentalRating[] ParentalRatingOptions { get; set; } public CountryInfo[] Countries { get; set; } @@ -21,14 +30,5 @@ namespace MediaBrowser.Model.Dto public string ContentType { get; set; } public NameValuePair[] ContentTypeOptions { get; set; } - - public MetadataEditorInfo() - { - ParentalRatingOptions = Array.Empty(); - Countries = Array.Empty(); - Cultures = Array.Empty(); - ExternalIdInfos = Array.Empty(); - ContentTypeOptions = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Dto/NameGuidPair.cs b/MediaBrowser.Model/Dto/NameGuidPair.cs new file mode 100644 index 0000000000..71166df979 --- /dev/null +++ b/MediaBrowser.Model/Dto/NameGuidPair.cs @@ -0,0 +1,14 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Model.Dto +{ + public class NameGuidPair + { + public string Name { get; set; } + + public Guid Id { get; set; } + } +} diff --git a/MediaBrowser.Model/Dto/NameIdPair.cs b/MediaBrowser.Model/Dto/NameIdPair.cs index 45c2fb35db..7f18b45028 100644 --- a/MediaBrowser.Model/Dto/NameIdPair.cs +++ b/MediaBrowser.Model/Dto/NameIdPair.cs @@ -19,11 +19,4 @@ namespace MediaBrowser.Model.Dto /// The identifier. public string Id { get; set; } } - - public class NameGuidPair - { - public string Name { get; set; } - - public Guid Id { get; set; } - } } diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index 40222c9dca..256d7b10f1 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -10,6 +10,15 @@ namespace MediaBrowser.Model.Dto /// public class UserDto : IItemDto, IHasServerId { + /// + /// Initializes a new instance of the class. + /// + public UserDto() + { + Configuration = new UserConfiguration(); + Policy = new UserPolicy(); + } + /// /// Gets or sets the name. /// @@ -94,15 +103,6 @@ namespace MediaBrowser.Model.Dto /// The primary image aspect ratio. public double? PrimaryImageAspectRatio { get; set; } - /// - /// Initializes a new instance of the class. - /// - public UserDto() - { - Configuration = new UserConfiguration(); - Policy = new UserPolicy(); - } - /// public override string ToString() { diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs index 3540387129..60b69d4b01 100644 --- a/MediaBrowser.Model/Entities/CollectionType.cs +++ b/MediaBrowser.Model/Entities/CollectionType.cs @@ -24,36 +24,4 @@ namespace MediaBrowser.Model.Entities public const string Playlists = "playlists"; public const string Folders = "folders"; } - - public static class SpecialFolder - { - public const string TvShowSeries = "TvShowSeries"; - public const string TvGenres = "TvGenres"; - public const string TvGenre = "TvGenre"; - public const string TvLatest = "TvLatest"; - public const string TvNextUp = "TvNextUp"; - public const string TvResume = "TvResume"; - public const string TvFavoriteSeries = "TvFavoriteSeries"; - public const string TvFavoriteEpisodes = "TvFavoriteEpisodes"; - - public const string MovieLatest = "MovieLatest"; - public const string MovieResume = "MovieResume"; - public const string MovieMovies = "MovieMovies"; - public const string MovieCollections = "MovieCollections"; - public const string MovieFavorites = "MovieFavorites"; - public const string MovieGenres = "MovieGenres"; - public const string MovieGenre = "MovieGenre"; - - public const string MusicArtists = "MusicArtists"; - public const string MusicAlbumArtists = "MusicAlbumArtists"; - public const string MusicAlbums = "MusicAlbums"; - public const string MusicGenres = "MusicGenres"; - public const string MusicLatest = "MusicLatest"; - public const string MusicPlaylists = "MusicPlaylists"; - public const string MusicSongs = "MusicSongs"; - public const string MusicFavorites = "MusicFavorites"; - public const string MusicFavoriteArtists = "MusicFavoriteArtists"; - public const string MusicFavoriteAlbums = "MusicFavoriteAlbums"; - public const string MusicFavoriteSongs = "MusicFavoriteSongs"; - } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index d85a8cde95..ade9d7e8dd 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Model.Entities public string Title { get; set; } /// - /// Gets or sets the video range. + /// Gets the video range. /// /// The video range. public string VideoRange @@ -108,11 +108,11 @@ namespace MediaBrowser.Model.Entities } } - public string localizedUndefined { get; set; } + public string LocalizedUndefined { get; set; } - public string localizedDefault { get; set; } + public string LocalizedDefault { get; set; } - public string localizedForced { get; set; } + public string LocalizedForced { get; set; } public string DisplayTitle { @@ -154,7 +154,7 @@ namespace MediaBrowser.Model.Entities if (IsDefault) { - attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault); + attributes.Add(string.IsNullOrEmpty(LocalizedDefault) ? "Default" : LocalizedDefault); } if (!string.IsNullOrEmpty(Title)) @@ -229,17 +229,17 @@ namespace MediaBrowser.Model.Entities } else { - attributes.Add(string.IsNullOrEmpty(localizedUndefined) ? "Und" : localizedUndefined); + attributes.Add(string.IsNullOrEmpty(LocalizedUndefined) ? "Und" : LocalizedUndefined); } if (IsDefault) { - attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault); + attributes.Add(string.IsNullOrEmpty(LocalizedDefault) ? "Default" : LocalizedDefault); } if (IsForced) { - attributes.Add(string.IsNullOrEmpty(localizedForced) ? "Forced" : localizedForced); + attributes.Add(string.IsNullOrEmpty(LocalizedForced) ? "Forced" : LocalizedForced); } if (!string.IsNullOrEmpty(Title)) @@ -266,67 +266,6 @@ namespace MediaBrowser.Model.Entities } } - private string GetResolutionText() - { - var i = this; - - if (i.Width.HasValue && i.Height.HasValue) - { - var width = i.Width.Value; - var height = i.Height.Value; - - if (width >= 3800 || height >= 2000) - { - return "4K"; - } - - if (width >= 2500) - { - if (i.IsInterlaced) - { - return "1440i"; - } - - return "1440p"; - } - - if (width >= 1900 || height >= 1000) - { - if (i.IsInterlaced) - { - return "1080i"; - } - - return "1080p"; - } - - if (width >= 1260 || height >= 700) - { - if (i.IsInterlaced) - { - return "720i"; - } - - return "720p"; - } - - if (width >= 700 || height >= 440) - { - - if (i.IsInterlaced) - { - return "480i"; - } - - return "480p"; - } - - return "SD"; - } - - return null; - } - public string NalLengthSize { get; set; } /// @@ -487,6 +426,96 @@ namespace MediaBrowser.Model.Entities } } + /// + /// Gets or sets a value indicating whether [supports external stream]. + /// + /// true if [supports external stream]; otherwise, false. + public bool SupportsExternalStream { get; set; } + + /// + /// Gets or sets the filename. + /// + /// The filename. + public string Path { get; set; } + + /// + /// Gets or sets the pixel format. + /// + /// The pixel format. + public string PixelFormat { get; set; } + + /// + /// Gets or sets the level. + /// + /// The level. + public double? Level { get; set; } + + /// + /// Gets or sets whether this instance is anamorphic. + /// + /// true if this instance is anamorphic; otherwise, false. + public bool? IsAnamorphic { get; set; } + + private string GetResolutionText() + { + var i = this; + + if (i.Width.HasValue && i.Height.HasValue) + { + var width = i.Width.Value; + var height = i.Height.Value; + + if (width >= 3800 || height >= 2000) + { + return "4K"; + } + + if (width >= 2500) + { + if (i.IsInterlaced) + { + return "1440i"; + } + + return "1440p"; + } + + if (width >= 1900 || height >= 1000) + { + if (i.IsInterlaced) + { + return "1080i"; + } + + return "1080p"; + } + + if (width >= 1260 || height >= 700) + { + if (i.IsInterlaced) + { + return "720i"; + } + + return "720p"; + } + + if (width >= 700 || height >= 440) + { + if (i.IsInterlaced) + { + return "480i"; + } + + return "480p"; + } + + return "SD"; + } + + return null; + } + public static bool IsTextFormat(string format) { string codec = format ?? string.Empty; @@ -533,35 +562,5 @@ namespace MediaBrowser.Model.Entities return true; } - - /// - /// Gets or sets a value indicating whether [supports external stream]. - /// - /// true if [supports external stream]; otherwise, false. - public bool SupportsExternalStream { get; set; } - - /// - /// Gets or sets the filename. - /// - /// The filename. - public string Path { get; set; } - - /// - /// Gets or sets the pixel format. - /// - /// The pixel format. - public string PixelFormat { get; set; } - - /// - /// Gets or sets the level. - /// - /// The level. - public double? Level { get; set; } - - /// - /// Gets a value indicating whether this instance is anamorphic. - /// - /// true if this instance is anamorphic; otherwise, false. - public bool? IsAnamorphic { get; set; } } } diff --git a/MediaBrowser.Model/Entities/PackageReviewInfo.cs b/MediaBrowser.Model/Entities/PackageReviewInfo.cs deleted file mode 100644 index 5b22b34ace..0000000000 --- a/MediaBrowser.Model/Entities/PackageReviewInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -#nullable disable -#pragma warning disable CS1591 - -using System; - -namespace MediaBrowser.Model.Entities -{ - public class PackageReviewInfo - { - /// - /// Gets or sets the package id (database key) for this review. - /// - public int id { get; set; } - - /// - /// Gets or sets the rating value. - /// - public int rating { get; set; } - - /// - /// Gets or sets whether or not this review recommends this item. - /// - public bool recommend { get; set; } - - /// - /// Gets or sets a short description of the review. - /// - public string title { get; set; } - - /// - /// Gets or sets the full review. - /// - public string review { get; set; } - - /// - /// Gets or sets the time of review. - /// - public DateTime timestamp { get; set; } - } -} diff --git a/MediaBrowser.Model/Entities/SpecialFolder.cs b/MediaBrowser.Model/Entities/SpecialFolder.cs new file mode 100644 index 0000000000..2250c5dffb --- /dev/null +++ b/MediaBrowser.Model/Entities/SpecialFolder.cs @@ -0,0 +1,36 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Entities +{ + public static class SpecialFolder + { + public const string TvShowSeries = "TvShowSeries"; + public const string TvGenres = "TvGenres"; + public const string TvGenre = "TvGenre"; + public const string TvLatest = "TvLatest"; + public const string TvNextUp = "TvNextUp"; + public const string TvResume = "TvResume"; + public const string TvFavoriteSeries = "TvFavoriteSeries"; + public const string TvFavoriteEpisodes = "TvFavoriteEpisodes"; + + public const string MovieLatest = "MovieLatest"; + public const string MovieResume = "MovieResume"; + public const string MovieMovies = "MovieMovies"; + public const string MovieCollections = "MovieCollections"; + public const string MovieFavorites = "MovieFavorites"; + public const string MovieGenres = "MovieGenres"; + public const string MovieGenre = "MovieGenre"; + + public const string MusicArtists = "MusicArtists"; + public const string MusicAlbumArtists = "MusicAlbumArtists"; + public const string MusicAlbums = "MusicAlbums"; + public const string MusicGenres = "MusicGenres"; + public const string MusicLatest = "MusicLatest"; + public const string MusicPlaylists = "MusicPlaylists"; + public const string MusicSongs = "MusicSongs"; + public const string MusicFavorites = "MusicFavorites"; + public const string MusicFavoriteArtists = "MusicFavoriteArtists"; + public const string MusicFavoriteAlbums = "MusicFavoriteAlbums"; + public const string MusicFavoriteSongs = "MusicFavoriteSongs"; + } +} diff --git a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs index f2bc6f25e0..1b0e592401 100644 --- a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs +++ b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs @@ -11,6 +11,14 @@ namespace MediaBrowser.Model.Entities /// public class VirtualFolderInfo { + /// + /// Initializes a new instance of the class. + /// + public VirtualFolderInfo() + { + Locations = Array.Empty(); + } + /// /// Gets or sets the name. /// @@ -31,14 +39,6 @@ namespace MediaBrowser.Model.Entities public LibraryOptions LibraryOptions { get; set; } - /// - /// Initializes a new instance of the class. - /// - public VirtualFolderInfo() - { - Locations = Array.Empty(); - } - /// /// Gets or sets the item identifier. /// diff --git a/MediaBrowser.Model/Globalization/CultureDto.cs b/MediaBrowser.Model/Globalization/CultureDto.cs index 6af4a872ce..5246f87d92 100644 --- a/MediaBrowser.Model/Globalization/CultureDto.cs +++ b/MediaBrowser.Model/Globalization/CultureDto.cs @@ -10,6 +10,11 @@ namespace MediaBrowser.Model.Globalization /// public class CultureDto { + public CultureDto() + { + ThreeLetterISOLanguageNames = Array.Empty(); + } + /// /// Gets or sets the name. /// @@ -29,7 +34,7 @@ namespace MediaBrowser.Model.Globalization public string TwoLetterISOLanguageName { get; set; } /// - /// Gets or sets the name of the three letter ISO language. + /// Gets the name of the three letter ISO language. /// /// The name of the three letter ISO language. public string ThreeLetterISOLanguageName @@ -47,10 +52,5 @@ namespace MediaBrowser.Model.Globalization } public string[] ThreeLetterISOLanguageNames { get; set; } - - public CultureDto() - { - ThreeLetterISOLanguageNames = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index dc65497876..ef08ecec66 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -155,13 +155,16 @@ namespace MediaBrowser.Model.IO /// Gets the directories. /// /// The path. - /// if set to true [recursive]. - /// IEnumerable<DirectoryInfo>. + /// If set to true also searches in subdirectiories. + /// All found directories. IEnumerable GetDirectories(string path, bool recursive = false); /// /// Gets the files. /// + /// The path in which to search. + /// If set to true also searches in subdirectiories. + /// All found files. IEnumerable GetFiles(string path, bool recursive = false); IEnumerable GetFiles(string path, IReadOnlyList extensions, bool enableCaseSensitiveExtensions, bool recursive); diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs index 07e76d9600..c6de4c1ab8 100644 --- a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.LiveTv public class BaseTimerInfoDto : IHasServerId { /// - /// Id of the recording. + /// Gets or sets the Id of the recording. /// public string Id { get; set; } @@ -28,7 +28,7 @@ namespace MediaBrowser.Model.LiveTv public string ExternalId { get; set; } /// - /// ChannelId of the recording. + /// Gets or sets the channel id of the recording. /// public Guid ChannelId { get; set; } @@ -39,7 +39,7 @@ namespace MediaBrowser.Model.LiveTv public string ExternalChannelId { get; set; } /// - /// ChannelName of the recording. + /// Gets or sets the channel name of the recording. /// public string ChannelName { get; set; } @@ -58,22 +58,22 @@ namespace MediaBrowser.Model.LiveTv public string ExternalProgramId { get; set; } /// - /// Name of the recording. + /// Gets or sets the name of the recording. /// public string Name { get; set; } /// - /// Description of the recording. + /// Gets or sets the description of the recording. /// public string Overview { get; set; } /// - /// The start date of the recording, in UTC. + /// Gets or sets the start date of the recording, in UTC. /// public DateTime StartDate { get; set; } /// - /// The end date of the recording, in UTC. + /// Gets or sets the end date of the recording, in UTC. /// public DateTime EndDate { get; set; } @@ -108,7 +108,7 @@ namespace MediaBrowser.Model.LiveTv public bool IsPrePaddingRequired { get; set; } /// - /// If the item does not have any backdrops, this will hold the Id of the Parent that has one. + /// Gets or sets the Id of the Parent that has a backdrop if the item does not have one. /// /// The parent backdrop item id. public string ParentBackdropItemId { get; set; } diff --git a/MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs b/MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs new file mode 100644 index 0000000000..082daeb51b --- /dev/null +++ b/MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs @@ -0,0 +1,58 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Model.LiveTv +{ + public class ListingsProviderInfo + { + public ListingsProviderInfo() + { + NewsCategories = new[] { "news", "journalism", "documentary", "current affairs" }; + SportsCategories = new[] { "sports", "basketball", "baseball", "football" }; + KidsCategories = new[] { "kids", "family", "children", "childrens", "disney" }; + MovieCategories = new[] { "movie" }; + EnabledTuners = Array.Empty(); + EnableAllTuners = true; + ChannelMappings = Array.Empty(); + } + + public string Id { get; set; } + + public string Type { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + + public string ListingsId { get; set; } + + public string ZipCode { get; set; } + + public string Country { get; set; } + + public string Path { get; set; } + + public string[] EnabledTuners { get; set; } + + public bool EnableAllTuners { get; set; } + + public string[] NewsCategories { get; set; } + + public string[] SportsCategories { get; set; } + + public string[] KidsCategories { get; set; } + + public string[] MovieCategories { get; set; } + + public NameValuePair[] ChannelMappings { get; set; } + + public string MoviePrefix { get; set; } + + public string PreferredLanguage { get; set; } + + public string UserAgent { get; set; } + } +} diff --git a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs index bcba344cc5..ca8defd8ba 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs @@ -11,6 +11,12 @@ namespace MediaBrowser.Model.LiveTv /// public class LiveTvChannelQuery { + public LiveTvChannelQuery() + { + EnableUserData = true; + SortBy = Array.Empty(); + } + /// /// Gets or sets the type of the channel. /// @@ -48,13 +54,13 @@ namespace MediaBrowser.Model.LiveTv public Guid UserId { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// gets or sets the start index. Used for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } @@ -68,15 +74,15 @@ namespace MediaBrowser.Model.LiveTv public bool EnableUserData { get; set; } /// - /// Used to specific whether to return news or not. + /// Gets or sets a value whether to return news or not. /// - /// If set to null, all programs will be returned + /// If set to null, all programs will be returned. public bool? IsNews { get; set; } /// - /// Used to specific whether to return movies or not. + /// Gets or sets a value whether to return movies or not. /// - /// If set to null, all programs will be returned + /// If set to null, all programs will be returned. public bool? IsMovie { get; set; } /// @@ -96,15 +102,9 @@ namespace MediaBrowser.Model.LiveTv public string[] SortBy { get; set; } /// - /// The sort order to return results with. + /// Gets or sets the sort order to return results with. /// /// The sort order. public SortOrder? SortOrder { get; set; } - - public LiveTvChannelQuery() - { - EnableUserData = true; - SortBy = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 789de3198a..4cece941cf 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -2,12 +2,19 @@ #pragma warning disable CS1591 using System; -using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.LiveTv { public class LiveTvOptions { + public LiveTvOptions() + { + TunerHosts = Array.Empty(); + ListingProviders = Array.Empty(); + MediaLocationsCreated = Array.Empty(); + RecordingPostProcessorArguments = "\"{path}\""; + } + public int? GuideDays { get; set; } public string RecordingPath { get; set; } @@ -33,93 +40,5 @@ namespace MediaBrowser.Model.LiveTv public string RecordingPostProcessor { get; set; } public string RecordingPostProcessorArguments { get; set; } - - public LiveTvOptions() - { - TunerHosts = Array.Empty(); - ListingProviders = Array.Empty(); - MediaLocationsCreated = Array.Empty(); - RecordingPostProcessorArguments = "\"{path}\""; - } - } - - public class TunerHostInfo - { - public string Id { get; set; } - - public string Url { get; set; } - - public string Type { get; set; } - - public string DeviceId { get; set; } - - public string FriendlyName { get; set; } - - public bool ImportFavoritesOnly { get; set; } - - public bool AllowHWTranscoding { get; set; } - - public bool EnableStreamLooping { get; set; } - - public string Source { get; set; } - - public int TunerCount { get; set; } - - public string UserAgent { get; set; } - - public TunerHostInfo() - { - AllowHWTranscoding = true; - } - } - - public class ListingsProviderInfo - { - public string Id { get; set; } - - public string Type { get; set; } - - public string Username { get; set; } - - public string Password { get; set; } - - public string ListingsId { get; set; } - - public string ZipCode { get; set; } - - public string Country { get; set; } - - public string Path { get; set; } - - public string[] EnabledTuners { get; set; } - - public bool EnableAllTuners { get; set; } - - public string[] NewsCategories { get; set; } - - public string[] SportsCategories { get; set; } - - public string[] KidsCategories { get; set; } - - public string[] MovieCategories { get; set; } - - public NameValuePair[] ChannelMappings { get; set; } - - public string MoviePrefix { get; set; } - - public string PreferredLanguage { get; set; } - - public string UserAgent { get; set; } - - public ListingsProviderInfo() - { - NewsCategories = new[] { "news", "journalism", "documentary", "current affairs" }; - SportsCategories = new[] { "sports", "basketball", "baseball", "football" }; - KidsCategories = new[] { "kids", "family", "children", "childrens", "disney" }; - MovieCategories = new[] { "movie" }; - EnabledTuners = Array.Empty(); - EnableAllTuners = true; - ChannelMappings = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs index 856f638c5c..ef5c5d2f31 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs @@ -10,6 +10,11 @@ namespace MediaBrowser.Model.LiveTv /// public class LiveTvServiceInfo { + public LiveTvServiceInfo() + { + Tuners = Array.Empty(); + } + /// /// Gets or sets the name. /// @@ -53,10 +58,5 @@ namespace MediaBrowser.Model.LiveTv public bool IsVisible { get; set; } public string[] Tuners { get; set; } - - public LiveTvServiceInfo() - { - Tuners = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index 69e7db4708..99bb1603c3 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -12,6 +12,11 @@ namespace MediaBrowser.Model.LiveTv /// public class RecordingQuery { + public RecordingQuery() + { + EnableTotalRecordCount = true; + } + /// /// Gets or sets the channel identifier. /// @@ -31,13 +36,13 @@ namespace MediaBrowser.Model.LiveTv public string Id { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } @@ -61,7 +66,7 @@ namespace MediaBrowser.Model.LiveTv public string SeriesTimerId { get; set; } /// - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } @@ -85,10 +90,5 @@ namespace MediaBrowser.Model.LiveTv public ImageType[] EnableImageTypes { get; set; } public bool EnableTotalRecordCount { get; set; } - - public RecordingQuery() - { - EnableTotalRecordCount = true; - } } } diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs index 90422d19c3..b26f5f45fe 100644 --- a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs @@ -7,6 +7,14 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Model.LiveTv { + public enum KeepUntil + { + UntilDeleted, + UntilSpaceNeeded, + UntilWatched, + UntilDate + } + /// /// Class SeriesTimerInfoDto. /// @@ -83,12 +91,4 @@ namespace MediaBrowser.Model.LiveTv /// The parent primary image tag. public string ParentPrimaryImageTag { get; set; } } - - public enum KeepUntil - { - UntilDeleted, - UntilSpaceNeeded, - UntilWatched, - UntilDate - } } diff --git a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs new file mode 100644 index 0000000000..7d4bbb2d07 --- /dev/null +++ b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs @@ -0,0 +1,38 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Model.LiveTv +{ + public class TunerHostInfo + { + public TunerHostInfo() + { + AllowHWTranscoding = true; + } + + public string Id { get; set; } + + public string Url { get; set; } + + public string Type { get; set; } + + public string DeviceId { get; set; } + + public string FriendlyName { get; set; } + + public bool ImportFavoritesOnly { get; set; } + + public bool AllowHWTranscoding { get; set; } + + public bool EnableStreamLooping { get; set; } + + public string Source { get; set; } + + public int TunerCount { get; set; } + + public string UserAgent { get; set; } + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c534286510..b6d9169139 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -17,7 +17,7 @@ net5.0 false true - true + true enable latest true @@ -44,7 +44,7 @@ - + diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs index 472055c22c..a268a4fa66 100644 --- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs +++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs @@ -10,6 +10,17 @@ namespace MediaBrowser.Model.MediaInfo { public class MediaInfo : MediaSourceInfo, IHasProviderIds { + public MediaInfo() + { + Chapters = Array.Empty(); + Artists = Array.Empty(); + AlbumArtists = Array.Empty(); + Studios = Array.Empty(); + Genres = Array.Empty(); + People = Array.Empty(); + ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + public ChapterInfo[] Chapters { get; set; } /// @@ -69,16 +80,5 @@ namespace MediaBrowser.Model.MediaInfo /// /// The overview. public string Overview { get; set; } - - public MediaInfo() - { - Chapters = Array.Empty(); - Artists = Array.Empty(); - AlbumArtists = Array.Empty(); - Studios = Array.Empty(); - Genres = Array.Empty(); - People = Array.Empty(); - ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } } } diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs index 3216856777..ecd9b8834e 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs @@ -8,6 +8,17 @@ namespace MediaBrowser.Model.MediaInfo { public class PlaybackInfoRequest { + public PlaybackInfoRequest() + { + EnableDirectPlay = true; + EnableDirectStream = true; + EnableTranscoding = true; + AllowVideoStreamCopy = true; + AllowAudioStreamCopy = true; + IsPlayback = true; + DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; + } + public Guid Id { get; set; } public Guid UserId { get; set; } @@ -43,16 +54,5 @@ namespace MediaBrowser.Model.MediaInfo public bool AutoOpenLiveStream { get; set; } public MediaProtocol[] DirectPlayProtocols { get; set; } - - public PlaybackInfoRequest() - { - EnableDirectPlay = true; - EnableDirectStream = true; - EnableTranscoding = true; - AllowVideoStreamCopy = true; - AllowAudioStreamCopy = true; - IsPlayback = true; - DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; - } } } diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs index 2733501822..32971b108f 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs @@ -10,6 +10,14 @@ namespace MediaBrowser.Model.MediaInfo /// public class PlaybackInfoResponse { + /// + /// Initializes a new instance of the class. + /// + public PlaybackInfoResponse() + { + MediaSources = Array.Empty(); + } + /// /// Gets or sets the media sources. /// @@ -27,13 +35,5 @@ namespace MediaBrowser.Model.MediaInfo /// /// The error code. public PlaybackErrorCode? ErrorCode { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public PlaybackInfoResponse() - { - MediaSources = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs index 37f5c55da6..d5c3a6aec5 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs @@ -7,11 +7,11 @@ namespace MediaBrowser.Model.MediaInfo { public class SubtitleTrackInfo { - public IReadOnlyList TrackEvents { get; set; } - public SubtitleTrackInfo() { TrackEvents = Array.Empty(); } + + public IReadOnlyList TrackEvents { get; set; } } } diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs index 5b6ed92df1..3de41d565a 100644 --- a/MediaBrowser.Model/Net/ISocket.cs +++ b/MediaBrowser.Model/Net/ISocket.cs @@ -23,6 +23,12 @@ namespace MediaBrowser.Model.Net /// /// Sends a UDP message to a particular end point (uni or multicast). /// + /// An array of type that contains the data to send. + /// The zero-based position in buffer at which to begin sending data. + /// The number of bytes to send. + /// An that represents the remote device. + /// The cancellation token to cancel operation. + /// The task object representing the asynchronous operation. Task SendToAsync(byte[] buffer, int offset, int bytes, IPEndPoint endPoint, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index 363abefc19..1527ef595c 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -14,6 +14,9 @@ namespace MediaBrowser.Model.Net /// /// Creates a new unicast socket using the specified local port number. /// + /// The local IP address to bind to. + /// The local port to bind to. + /// A new unicast socket using the specified local port number. ISocket CreateSsdpUdpSocket(IPAddress localIp, int localPort); /// diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 902db1e9e5..96f5ab51ae 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -91,9 +91,9 @@ namespace MediaBrowser.Model.Net { ".webp", "image/webp" }, // Type font - { ".ttf" , "font/ttf" }, - { ".woff" , "font/woff" }, - { ".woff2" , "font/woff2" }, + { ".ttf", "font/ttf" }, + { ".woff", "font/woff" }, + { ".woff2", "font/woff2" }, // Type text { ".ass", "text/x-ssa" }, @@ -168,14 +168,17 @@ namespace MediaBrowser.Model.Net /// /// Gets the type of the MIME. /// - public static string? GetMimeType(string path, bool enableStreamDefault) + /// The filename to find the MIME type of. + /// Whether of not to return a default value if no fitting MIME type is found. + /// The worrect MIME type for the given filename, or `null` if it wasn't found and is false. + public static string? GetMimeType(string filename, bool enableStreamDefault) { - if (path.Length == 0) + if (filename.Length == 0) { - throw new ArgumentException("String can't be empty.", nameof(path)); + throw new ArgumentException("String can't be empty.", nameof(filename)); } - var ext = Path.GetExtension(path); + var ext = Path.GetExtension(filename); if (_mimeTypeLookup.TryGetValue(ext, out string? result)) { @@ -210,9 +213,9 @@ namespace MediaBrowser.Model.Net return enableStreamDefault ? "application/octet-stream" : null; } - public static string? ToExtension(string? mimeType) + public static string? ToExtension(string mimeType) { - if (string.IsNullOrEmpty(mimeType)) + if (mimeType.Length == 0) { throw new ArgumentException("String can't be empty.", nameof(mimeType)); } diff --git a/MediaBrowser.Model/Net/NetworkShare.cs b/MediaBrowser.Model/Net/NetworkShare.cs deleted file mode 100644 index 6344cbe21e..0000000000 --- a/MediaBrowser.Model/Net/NetworkShare.cs +++ /dev/null @@ -1,33 +0,0 @@ -#nullable disable -#pragma warning disable CS1591 - -namespace MediaBrowser.Model.Net -{ - public class NetworkShare - { - /// - /// The name of the computer that this share belongs to. - /// - public string Server { get; set; } - - /// - /// Share name. - /// - public string Name { get; set; } - - /// - /// Local path. - /// - public string Path { get; set; } - - /// - /// Share type. - /// - public NetworkShareType ShareType { get; set; } - - /// - /// Comment. - /// - public string Remark { get; set; } - } -} diff --git a/MediaBrowser.Model/Net/SocketReceiveResult.cs b/MediaBrowser.Model/Net/SocketReceiveResult.cs index 54139fe9c5..1524786ea7 100644 --- a/MediaBrowser.Model/Net/SocketReceiveResult.cs +++ b/MediaBrowser.Model/Net/SocketReceiveResult.cs @@ -20,12 +20,12 @@ namespace MediaBrowser.Model.Net public int ReceivedBytes { get; set; } /// - /// The the data was received from. + /// Gets or sets the the data was received from. /// public IPEndPoint RemoteEndPoint { get; set; } /// - /// The local . + /// Gets or sets the local . /// public IPAddress LocalIPAddress { get; set; } } diff --git a/MediaBrowser.Model/Net/WebSocketMessage.cs b/MediaBrowser.Model/Net/WebSocketMessage.cs index bffbbe612d..b00158cb33 100644 --- a/MediaBrowser.Model/Net/WebSocketMessage.cs +++ b/MediaBrowser.Model/Net/WebSocketMessage.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Net /// /// Class WebSocketMessage. /// - /// + /// The type of the data. public class WebSocketMessage { /// diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs index 239a3777e1..94bb5d6e35 100644 --- a/MediaBrowser.Model/Notifications/NotificationOptions.cs +++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs @@ -2,18 +2,16 @@ #pragma warning disable CS1591 using System; -using Jellyfin.Data.Enums; -using MediaBrowser.Model.Extensions; using System.Linq; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Notifications { public class NotificationOptions { - public NotificationOption[] Options { get; set; } - public NotificationOptions() { Options = new[] @@ -71,6 +69,8 @@ namespace MediaBrowser.Model.Notifications }; } + public NotificationOption[] Options { get; set; } + public NotificationOption GetOptions(string type) { foreach (NotificationOption i in Options) @@ -104,7 +104,7 @@ namespace MediaBrowser.Model.Notifications NotificationOption opt = GetOptions(type); return opt != null && opt.Enabled && - !opt.DisabledMonitorUsers.Contains(userId.ToString(""), StringComparer.OrdinalIgnoreCase); + !opt.DisabledMonitorUsers.Contains(userId.ToString(string.Empty), StringComparer.OrdinalIgnoreCase); } public bool IsEnabledToSendToUser(string type, string userId, User user) diff --git a/MediaBrowser.Model/Notifications/NotificationRequest.cs b/MediaBrowser.Model/Notifications/NotificationRequest.cs index febc2bc099..622c50cd88 100644 --- a/MediaBrowser.Model/Notifications/NotificationRequest.cs +++ b/MediaBrowser.Model/Notifications/NotificationRequest.cs @@ -7,6 +7,12 @@ namespace MediaBrowser.Model.Notifications { public class NotificationRequest { + public NotificationRequest() + { + UserIds = Array.Empty(); + Date = DateTime.UtcNow; + } + public string Name { get; set; } public string Description { get; set; } @@ -20,16 +26,10 @@ namespace MediaBrowser.Model.Notifications public DateTime Date { get; set; } /// - /// The corresponding type name used in configuration. Not for display. + /// Gets or sets the corresponding type name used in configuration. Not for display. /// public string NotificationType { get; set; } public SendToUserType? SendToUserMode { get; set; } - - public NotificationRequest() - { - UserIds = Array.Empty(); - Date = DateTime.UtcNow; - } } } diff --git a/MediaBrowser.Model/Providers/ExternalIdInfo.cs b/MediaBrowser.Model/Providers/ExternalIdInfo.cs index afe95e6eee..0ea3e96cae 100644 --- a/MediaBrowser.Model/Providers/ExternalIdInfo.cs +++ b/MediaBrowser.Model/Providers/ExternalIdInfo.cs @@ -6,11 +6,11 @@ namespace MediaBrowser.Model.Providers public class ExternalIdInfo { /// - /// Represents the external id information for serialization to the client. + /// Initializes a new instance of the class. /// /// Name of the external id provider (IE: IMDB, MusicBrainz, etc). /// Key for this id. This key should be unique across all providers. - /// Specific media type for this id + /// Specific media type for this id. /// URL format string. public ExternalIdInfo(string name, string key, ExternalIdMediaType? type, string urlFormatString) { diff --git a/MediaBrowser.Model/Providers/RemoteImageInfo.cs b/MediaBrowser.Model/Providers/RemoteImageInfo.cs index fb25999e0a..48207d2d41 100644 --- a/MediaBrowser.Model/Providers/RemoteImageInfo.cs +++ b/MediaBrowser.Model/Providers/RemoteImageInfo.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Model.Providers public string Url { get; set; } /// - /// Gets a url used for previewing a smaller version. + /// Gets or sets a url used for previewing a smaller version. /// public string ThumbnailUrl { get; set; } diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs index 5702c460b0..6ea1e14862 100644 --- a/MediaBrowser.Model/Providers/SubtitleOptions.cs +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -7,6 +7,14 @@ namespace MediaBrowser.Model.Providers { public class SubtitleOptions { + public SubtitleOptions() + { + DownloadLanguages = Array.Empty(); + + SkipIfAudioTrackMatches = true; + RequirePerfectMatch = true; + } + public bool SkipIfEmbeddedSubtitlesPresent { get; set; } public bool SkipIfAudioTrackMatches { get; set; } @@ -24,13 +32,5 @@ namespace MediaBrowser.Model.Providers public bool IsOpenSubtitleVipAccount { get; set; } public bool RequirePerfectMatch { get; set; } - - public SubtitleOptions() - { - DownloadLanguages = Array.Empty(); - - SkipIfAudioTrackMatches = true; - RequirePerfectMatch = true; - } } } diff --git a/MediaBrowser.Model/Querying/EpisodeQuery.cs b/MediaBrowser.Model/Querying/EpisodeQuery.cs index 13b1a0dcbf..56a7f33201 100644 --- a/MediaBrowser.Model/Querying/EpisodeQuery.cs +++ b/MediaBrowser.Model/Querying/EpisodeQuery.cs @@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Querying { public class EpisodeQuery { + public EpisodeQuery() + { + Fields = Array.Empty(); + } + /// /// Gets or sets the user identifier. /// @@ -66,10 +71,5 @@ namespace MediaBrowser.Model.Querying /// /// The start item identifier. public string StartItemId { get; set; } - - public EpisodeQuery() - { - Fields = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Querying/LatestItemsQuery.cs b/MediaBrowser.Model/Querying/LatestItemsQuery.cs index 7954ef4b43..f555ffb36d 100644 --- a/MediaBrowser.Model/Querying/LatestItemsQuery.cs +++ b/MediaBrowser.Model/Querying/LatestItemsQuery.cs @@ -14,31 +14,32 @@ namespace MediaBrowser.Model.Querying } /// - /// The user to localize search results for. + /// Gets or sets the user to localize search results for. /// /// The user id. public Guid UserId { get; set; } /// + /// Gets or sets the parent id. /// Specify this to localize the search to a specific item or folder. Omit to use the root. /// /// The parent id. public Guid ParentId { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Used for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } diff --git a/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs b/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs index 1c8875890a..b800f5de5f 100644 --- a/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs +++ b/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs @@ -7,6 +7,13 @@ namespace MediaBrowser.Model.Querying { public class MovieRecommendationQuery { + public MovieRecommendationQuery() + { + ItemLimit = 10; + CategoryLimit = 6; + Fields = Array.Empty(); + } + /// /// Gets or sets the user identifier. /// @@ -36,12 +43,5 @@ namespace MediaBrowser.Model.Querying /// /// The fields. public ItemFields[] Fields { get; set; } - - public MovieRecommendationQuery() - { - ItemLimit = 10; - CategoryLimit = 6; - Fields = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Querying/NextUpQuery.cs b/MediaBrowser.Model/Querying/NextUpQuery.cs index 001d0623cc..0555afc00d 100644 --- a/MediaBrowser.Model/Querying/NextUpQuery.cs +++ b/MediaBrowser.Model/Querying/NextUpQuery.cs @@ -8,6 +8,13 @@ namespace MediaBrowser.Model.Querying { public class NextUpQuery { + public NextUpQuery() + { + EnableImageTypes = Array.Empty(); + EnableTotalRecordCount = true; + DisableFirstEpisode = false; + } + /// /// Gets or sets the user id. /// @@ -27,19 +34,19 @@ namespace MediaBrowser.Model.Querying public string SeriesId { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information. + /// gets or sets the fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } @@ -68,12 +75,5 @@ namespace MediaBrowser.Model.Querying /// Gets or sets a value indicating whether do disable sending first episode as next up. /// public bool DisableFirstEpisode { get; set; } - - public NextUpQuery() - { - EnableImageTypes = Array.Empty(); - EnableTotalRecordCount = true; - DisableFirstEpisode = false; - } } } diff --git a/MediaBrowser.Model/Querying/QueryFilters.cs b/MediaBrowser.Model/Querying/QueryFilters.cs index 6e4d251818..73b27a7b06 100644 --- a/MediaBrowser.Model/Querying/QueryFilters.cs +++ b/MediaBrowser.Model/Querying/QueryFilters.cs @@ -6,35 +6,16 @@ using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.Querying { - public class QueryFiltersLegacy + public class QueryFilters { - public string[] Genres { get; set; } - - public string[] Tags { get; set; } - - public string[] OfficialRatings { get; set; } - - public int[] Years { get; set; } - - public QueryFiltersLegacy() + public QueryFilters() { - Genres = Array.Empty(); Tags = Array.Empty(); - OfficialRatings = Array.Empty(); - Years = Array.Empty(); + Genres = Array.Empty(); } - } - public class QueryFilters - { public NameGuidPair[] Genres { get; set; } public string[] Tags { get; set; } - - public QueryFilters() - { - Tags = Array.Empty(); - Genres = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Querying/QueryFiltersLegacy.cs b/MediaBrowser.Model/Querying/QueryFiltersLegacy.cs new file mode 100644 index 0000000000..fcb450ed30 --- /dev/null +++ b/MediaBrowser.Model/Querying/QueryFiltersLegacy.cs @@ -0,0 +1,26 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Model.Querying +{ + public class QueryFiltersLegacy + { + public QueryFiltersLegacy() + { + Genres = Array.Empty(); + Tags = Array.Empty(); + OfficialRatings = Array.Empty(); + Years = Array.Empty(); + } + + public string[] Genres { get; set; } + + public string[] Tags { get; set; } + + public string[] OfficialRatings { get; set; } + + public int[] Years { get; set; } + } +} diff --git a/MediaBrowser.Model/Querying/QueryResult.cs b/MediaBrowser.Model/Querying/QueryResult.cs index 490f48b84b..8ce794800b 100644 --- a/MediaBrowser.Model/Querying/QueryResult.cs +++ b/MediaBrowser.Model/Querying/QueryResult.cs @@ -8,6 +8,17 @@ namespace MediaBrowser.Model.Querying { public class QueryResult { + public QueryResult() + { + Items = Array.Empty(); + } + + public QueryResult(IReadOnlyList items) + { + Items = items; + TotalRecordCount = items.Count; + } + /// /// Gets or sets the items. /// @@ -15,26 +26,15 @@ namespace MediaBrowser.Model.Querying public IReadOnlyList Items { get; set; } /// - /// The total number of records available. + /// Gets or sets the total number of records available. /// /// The total record count. public int TotalRecordCount { get; set; } /// - /// The index of the first record in Items. + /// Gets or sets the index of the first record in Items. /// /// First record index. public int StartIndex { get; set; } - - public QueryResult() - { - Items = Array.Empty(); - } - - public QueryResult(IReadOnlyList items) - { - Items = items; - TotalRecordCount = items.Count; - } } } diff --git a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs index eb62394605..2cf0f0d5f8 100644 --- a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs +++ b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs @@ -8,6 +8,11 @@ namespace MediaBrowser.Model.Querying { public class UpcomingEpisodesQuery { + public UpcomingEpisodesQuery() + { + EnableImageTypes = Array.Empty(); + } + /// /// Gets or sets the user id. /// @@ -21,19 +26,19 @@ namespace MediaBrowser.Model.Querying public string ParentId { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } @@ -55,10 +60,5 @@ namespace MediaBrowser.Model.Querying /// /// The enable image types. public ImageType[] EnableImageTypes { get; set; } - - public UpcomingEpisodesQuery() - { - EnableImageTypes = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Search/SearchQuery.cs b/MediaBrowser.Model/Search/SearchQuery.cs index ce60062cd3..aedfa4d363 100644 --- a/MediaBrowser.Model/Search/SearchQuery.cs +++ b/MediaBrowser.Model/Search/SearchQuery.cs @@ -7,8 +7,21 @@ namespace MediaBrowser.Model.Search { public class SearchQuery { + public SearchQuery() + { + IncludeArtists = true; + IncludeGenres = true; + IncludeMedia = true; + IncludePeople = true; + IncludeStudios = true; + + MediaTypes = Array.Empty(); + IncludeItemTypes = Array.Empty(); + ExcludeItemTypes = Array.Empty(); + } + /// - /// The user to localize search results for. + /// Gets or sets the user to localize search results for. /// /// The user id. public Guid UserId { get; set; } @@ -20,13 +33,13 @@ namespace MediaBrowser.Model.Search public string SearchTerm { get; set; } /// - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Used for paging. /// /// The start index. public int? StartIndex { get; set; } /// - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// /// The limit. public int? Limit { get; set; } @@ -58,18 +71,5 @@ namespace MediaBrowser.Model.Search public bool? IsKids { get; set; } public bool? IsSports { get; set; } - - public SearchQuery() - { - IncludeArtists = true; - IncludeGenres = true; - IncludeMedia = true; - IncludePeople = true; - IncludeStudios = true; - - MediaTypes = Array.Empty(); - IncludeItemTypes = Array.Empty(); - ExcludeItemTypes = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Session/BrowseRequest.cs b/MediaBrowser.Model/Session/BrowseRequest.cs index 1c997d5846..65afe5cf34 100644 --- a/MediaBrowser.Model/Session/BrowseRequest.cs +++ b/MediaBrowser.Model/Session/BrowseRequest.cs @@ -7,6 +7,7 @@ namespace MediaBrowser.Model.Session public class BrowseRequest { /// + /// Gets or sets the item type. /// Artist, Genre, Studio, Person, or any kind of BaseItem. /// /// The type of the item. diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs index 5852f4e37a..d692906c64 100644 --- a/MediaBrowser.Model/Session/ClientCapabilities.cs +++ b/MediaBrowser.Model/Session/ClientCapabilities.cs @@ -9,6 +9,13 @@ namespace MediaBrowser.Model.Session { public class ClientCapabilities { + public ClientCapabilities() + { + PlayableMediaTypes = Array.Empty(); + SupportedCommands = Array.Empty(); + SupportsPersistentIdentifier = true; + } + public IReadOnlyList PlayableMediaTypes { get; set; } public IReadOnlyList SupportedCommands { get; set; } @@ -28,12 +35,5 @@ namespace MediaBrowser.Model.Session public string AppStoreUrl { get; set; } public string IconUrl { get; set; } - - public ClientCapabilities() - { - PlayableMediaTypes = Array.Empty(); - SupportedCommands = Array.Empty(); - SupportsPersistentIdentifier = true; - } } } diff --git a/MediaBrowser.Model/Session/GeneralCommand.cs b/MediaBrowser.Model/Session/GeneralCommand.cs index 77bb6bcf77..29528c1106 100644 --- a/MediaBrowser.Model/Session/GeneralCommand.cs +++ b/MediaBrowser.Model/Session/GeneralCommand.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -8,15 +7,15 @@ namespace MediaBrowser.Model.Session { public class GeneralCommand { - public GeneralCommandType Name { get; set; } - - public Guid ControllingUserId { get; set; } - - public Dictionary Arguments { get; set; } - public GeneralCommand() { Arguments = new Dictionary(); } + + public GeneralCommandType Name { get; set; } + + public Guid ControllingUserId { get; set; } + + public Dictionary Arguments { get; } } } diff --git a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs index 73dbe6a2da..a6e7efcb0c 100644 --- a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs @@ -111,18 +111,4 @@ namespace MediaBrowser.Model.Session public string PlaylistItemId { get; set; } } - - public enum RepeatMode - { - RepeatNone = 0, - RepeatAll = 1, - RepeatOne = 2 - } - - public class QueueItem - { - public Guid Id { get; set; } - - public string PlaylistItemId { get; set; } - } } diff --git a/MediaBrowser.Model/Session/PlaystateCommand.cs b/MediaBrowser.Model/Session/PlaystateCommand.cs index 3aa091f791..df47f3b73d 100644 --- a/MediaBrowser.Model/Session/PlaystateCommand.cs +++ b/MediaBrowser.Model/Session/PlaystateCommand.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - namespace MediaBrowser.Model.Session { /// @@ -46,6 +44,10 @@ namespace MediaBrowser.Model.Session /// The fast forward. /// FastForward, + + /// + /// The play pause. + /// PlayPause } } diff --git a/MediaBrowser.Model/Session/QueueItem.cs b/MediaBrowser.Model/Session/QueueItem.cs new file mode 100644 index 0000000000..32b19101b2 --- /dev/null +++ b/MediaBrowser.Model/Session/QueueItem.cs @@ -0,0 +1,14 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Model.Session +{ + public class QueueItem + { + public Guid Id { get; set; } + + public string PlaylistItemId { get; set; } + } +} diff --git a/MediaBrowser.Model/Session/RepeatMode.cs b/MediaBrowser.Model/Session/RepeatMode.cs new file mode 100644 index 0000000000..c6e173d6b8 --- /dev/null +++ b/MediaBrowser.Model/Session/RepeatMode.cs @@ -0,0 +1,11 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Session +{ + public enum RepeatMode + { + RepeatNone = 0, + RepeatAll = 1, + RepeatOne = 2 + } +} diff --git a/MediaBrowser.Model/Session/TranscodeReason.cs b/MediaBrowser.Model/Session/TranscodeReason.cs new file mode 100644 index 0000000000..e93b5d2882 --- /dev/null +++ b/MediaBrowser.Model/Session/TranscodeReason.cs @@ -0,0 +1,31 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Session +{ + public enum TranscodeReason + { + ContainerNotSupported = 0, + VideoCodecNotSupported = 1, + AudioCodecNotSupported = 2, + ContainerBitrateExceedsLimit = 3, + AudioBitrateNotSupported = 4, + AudioChannelsNotSupported = 5, + VideoResolutionNotSupported = 6, + UnknownVideoStreamInfo = 7, + UnknownAudioStreamInfo = 8, + AudioProfileNotSupported = 9, + AudioSampleRateNotSupported = 10, + AnamorphicVideoNotSupported = 11, + InterlacedVideoNotSupported = 12, + SecondaryAudioNotSupported = 13, + RefFramesNotSupported = 14, + VideoBitDepthNotSupported = 15, + VideoBitrateNotSupported = 16, + VideoFramerateNotSupported = 17, + VideoLevelNotSupported = 18, + VideoProfileNotSupported = 19, + AudioBitDepthNotSupported = 20, + SubtitleCodecNotSupported = 21, + DirectPlayError = 22 + } +} diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index e832c2f6fa..064a087d5d 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Session { public class TranscodingInfo { + public TranscodingInfo() + { + TranscodeReasons = Array.Empty(); + } + public string AudioCodec { get; set; } public string VideoCodec { get; set; } @@ -30,37 +35,5 @@ namespace MediaBrowser.Model.Session public int? AudioChannels { get; set; } public TranscodeReason[] TranscodeReasons { get; set; } - - public TranscodingInfo() - { - TranscodeReasons = Array.Empty(); - } - } - - public enum TranscodeReason - { - ContainerNotSupported = 0, - VideoCodecNotSupported = 1, - AudioCodecNotSupported = 2, - ContainerBitrateExceedsLimit = 3, - AudioBitrateNotSupported = 4, - AudioChannelsNotSupported = 5, - VideoResolutionNotSupported = 6, - UnknownVideoStreamInfo = 7, - UnknownAudioStreamInfo = 8, - AudioProfileNotSupported = 9, - AudioSampleRateNotSupported = 10, - AnamorphicVideoNotSupported = 11, - InterlacedVideoNotSupported = 12, - SecondaryAudioNotSupported = 13, - RefFramesNotSupported = 14, - VideoBitDepthNotSupported = 15, - VideoBitrateNotSupported = 16, - VideoFramerateNotSupported = 17, - VideoLevelNotSupported = 18, - VideoProfileNotSupported = 19, - AudioBitDepthNotSupported = 20, - SubtitleCodecNotSupported = 21, - DirectPlayError = 22 } } diff --git a/MediaBrowser.Model/Sync/SyncJob.cs b/MediaBrowser.Model/Sync/SyncJob.cs index b9290b6e83..3e396e5d13 100644 --- a/MediaBrowser.Model/Sync/SyncJob.cs +++ b/MediaBrowser.Model/Sync/SyncJob.cs @@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Sync { public class SyncJob { + public SyncJob() + { + RequestedItemIds = Array.Empty(); + } + /// /// Gets or sets the identifier. /// @@ -126,10 +131,5 @@ namespace MediaBrowser.Model.Sync public string PrimaryImageItemId { get; set; } public string PrimaryImageTag { get; set; } - - public SyncJob() - { - RequestedItemIds = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 4b83fb7e61..d75ae91c02 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -30,6 +30,14 @@ namespace MediaBrowser.Model.System /// public class SystemInfo : PublicSystemInfo { + /// + /// Initializes a new instance of the class. + /// + public SystemInfo() + { + CompletedInstallations = Array.Empty(); + } + /// /// Gets or sets the display name of the operating system. /// @@ -37,7 +45,7 @@ namespace MediaBrowser.Model.System public string OperatingSystemDisplayName { get; set; } /// - /// Get or sets the package name. + /// Gets or sets the package name. /// /// The value of the '-package' command line argument. public string PackageName { get; set; } @@ -127,13 +135,5 @@ namespace MediaBrowser.Model.System public FFmpegLocation EncoderLocation { get; set; } public Architecture SystemArchitecture { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public SystemInfo() - { - CompletedInstallations = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/System/WakeOnLanInfo.cs b/MediaBrowser.Model/System/WakeOnLanInfo.cs index b2cbe737d1..aba19a6baf 100644 --- a/MediaBrowser.Model/System/WakeOnLanInfo.cs +++ b/MediaBrowser.Model/System/WakeOnLanInfo.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Model.System /// Gets the MAC address of the device. /// /// The MAC address. - public string? MacAddress { get; set; } + public string? MacAddress { get; } /// /// Gets or sets the wake-on-LAN port. diff --git a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs index 2f05e08c51..ca769e26b3 100644 --- a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs +++ b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Tasks event EventHandler> TaskProgress; /// - /// Gets or sets the scheduled task. + /// Gets the scheduled task. /// /// The scheduled task. IScheduledTask ScheduledTask { get; } @@ -57,10 +57,9 @@ namespace MediaBrowser.Model.Tasks double? CurrentProgress { get; } /// - /// Gets the triggers that define when the task will run. + /// Gets or sets the triggers that define when the task will run. /// /// The triggers. - /// value TaskTriggerInfo[] Triggers { get; set; } /// diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index 02b29074e3..a86bf2a1c8 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -9,6 +9,10 @@ namespace MediaBrowser.Model.Tasks { public interface ITaskManager : IDisposable { + event EventHandler> TaskExecuting; + + event EventHandler TaskCompleted; + /// /// Gets the list of Scheduled Tasks. /// @@ -18,7 +22,7 @@ namespace MediaBrowser.Model.Tasks /// /// Cancels if running and queue. /// - /// + /// An implementatin of . /// Task options. void CancelIfRunningAndQueue(TaskOptions options) where T : IScheduledTask; @@ -26,21 +30,21 @@ namespace MediaBrowser.Model.Tasks /// /// Cancels if running and queue. /// - /// + /// An implementatin of . void CancelIfRunningAndQueue() where T : IScheduledTask; /// /// Cancels if running. /// - /// + /// An implementatin of . void CancelIfRunning() where T : IScheduledTask; /// /// Queues the scheduled task. /// - /// + /// An implementatin of . /// Task options. void QueueScheduledTask(TaskOptions options) where T : IScheduledTask; @@ -48,7 +52,7 @@ namespace MediaBrowser.Model.Tasks /// /// Queues the scheduled task. /// - /// + /// An implementatin of . void QueueScheduledTask() where T : IScheduledTask; @@ -58,6 +62,8 @@ namespace MediaBrowser.Model.Tasks /// /// Queues the scheduled task. /// + /// The to queue. + /// The to use. void QueueScheduledTask(IScheduledTask task, TaskOptions options); /// @@ -67,12 +73,10 @@ namespace MediaBrowser.Model.Tasks void AddTasks(IEnumerable tasks); void Cancel(IScheduledTaskWorker task); + Task Execute(IScheduledTaskWorker task, TaskOptions options); void Execute() where T : IScheduledTask; - - event EventHandler> TaskExecuting; - event EventHandler TaskCompleted; } } diff --git a/MediaBrowser.Model/Tasks/ITaskTrigger.cs b/MediaBrowser.Model/Tasks/ITaskTrigger.cs index 5c30d6c220..cbd60cca18 100644 --- a/MediaBrowser.Model/Tasks/ITaskTrigger.cs +++ b/MediaBrowser.Model/Tasks/ITaskTrigger.cs @@ -21,6 +21,10 @@ namespace MediaBrowser.Model.Tasks /// /// Stars waiting for the trigger action. /// + /// Result of the last run triggerd task. + /// The . + /// The name of the task. + /// Wheter or not this is is fired during startup. void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup); /// diff --git a/MediaBrowser.Model/Tasks/TaskInfo.cs b/MediaBrowser.Model/Tasks/TaskInfo.cs index 77100dfe76..16de0b1210 100644 --- a/MediaBrowser.Model/Tasks/TaskInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskInfo.cs @@ -8,6 +8,14 @@ namespace MediaBrowser.Model.Tasks /// public class TaskInfo { + /// + /// Initializes a new instance of the class. + /// + public TaskInfo() + { + Triggers = Array.Empty(); + } + /// /// Gets or sets the name. /// @@ -67,13 +75,5 @@ namespace MediaBrowser.Model.Tasks /// /// The key. public string Key { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public TaskInfo() - { - Triggers = Array.Empty(); - } } } diff --git a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs index 5aeaffc2b3..f8a8c727ef 100644 --- a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs @@ -10,6 +10,12 @@ namespace MediaBrowser.Model.Tasks /// public class TaskTriggerInfo { + public const string TriggerDaily = "DailyTrigger"; + public const string TriggerWeekly = "WeeklyTrigger"; + public const string TriggerInterval = "IntervalTrigger"; + public const string TriggerSystemEvent = "SystemEventTrigger"; + public const string TriggerStartup = "StartupTrigger"; + /// /// Gets or sets the type. /// @@ -39,11 +45,5 @@ namespace MediaBrowser.Model.Tasks /// /// The maximum runtime ticks. public long? MaxRuntimeTicks { get; set; } - - public const string TriggerDaily = "DailyTrigger"; - public const string TriggerWeekly = "WeeklyTrigger"; - public const string TriggerInterval = "IntervalTrigger"; - public const string TriggerSystemEvent = "SystemEventTrigger"; - public const string TriggerStartup = "StartupTrigger"; } } diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 37da04adf7..111070d813 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -10,6 +10,56 @@ namespace MediaBrowser.Model.Users { public class UserPolicy { + public UserPolicy() + { + IsHidden = true; + + EnableContentDeletion = false; + EnableContentDeletionFromFolders = Array.Empty(); + + EnableSyncTranscoding = true; + EnableMediaConversion = true; + + EnableMediaPlayback = true; + EnableAudioPlaybackTranscoding = true; + EnableVideoPlaybackTranscoding = true; + EnablePlaybackRemuxing = true; + ForceRemoteSourceTranscoding = false; + EnableLiveTvManagement = true; + EnableLiveTvAccess = true; + + // Without this on by default, admins won't be able to do this + // Improve in the future + EnableLiveTvManagement = true; + + EnableSharedDeviceControl = true; + + BlockedTags = Array.Empty(); + BlockUnratedItems = Array.Empty(); + + EnableUserPreferenceAccess = true; + + AccessSchedules = Array.Empty(); + + LoginAttemptsBeforeLockout = -1; + + MaxActiveSessions = 0; + + EnableAllChannels = true; + EnabledChannels = Array.Empty(); + + EnableAllFolders = true; + EnabledFolders = Array.Empty(); + + EnabledDevices = Array.Empty(); + EnableAllDevices = true; + + EnableContentDownloading = true; + EnablePublicSharing = true; + EnableRemoteAccess = true; + SyncPlayAccess = SyncPlayUserAccessType.CreateAndJoinGroups; + } + /// /// Gets or sets a value indicating whether this instance is administrator. /// @@ -112,55 +162,5 @@ namespace MediaBrowser.Model.Users /// /// Access level to SyncPlay features. public SyncPlayUserAccessType SyncPlayAccess { get; set; } - - public UserPolicy() - { - IsHidden = true; - - EnableContentDeletion = false; - EnableContentDeletionFromFolders = Array.Empty(); - - EnableSyncTranscoding = true; - EnableMediaConversion = true; - - EnableMediaPlayback = true; - EnableAudioPlaybackTranscoding = true; - EnableVideoPlaybackTranscoding = true; - EnablePlaybackRemuxing = true; - ForceRemoteSourceTranscoding = false; - EnableLiveTvManagement = true; - EnableLiveTvAccess = true; - - // Without this on by default, admins won't be able to do this - // Improve in the future - EnableLiveTvManagement = true; - - EnableSharedDeviceControl = true; - - BlockedTags = Array.Empty(); - BlockUnratedItems = Array.Empty(); - - EnableUserPreferenceAccess = true; - - AccessSchedules = Array.Empty(); - - LoginAttemptsBeforeLockout = -1; - - MaxActiveSessions = 0; - - EnableAllChannels = true; - EnabledChannels = Array.Empty(); - - EnableAllFolders = true; - EnabledFolders = Array.Empty(); - - EnabledDevices = Array.Empty(); - EnableAllDevices = true; - - EnableContentDownloading = true; - EnablePublicSharing = true; - EnableRemoteAccess = true; - SyncPlayAccess = SyncPlayUserAccessType.CreateAndJoinGroups; - } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index fa09bfb66a..81337390cc 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -32,6 +32,8 @@ + + diff --git a/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs b/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs index 544a74637a..92c534eaea 100644 --- a/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs +++ b/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace Jellyfin.Api.Tests.ModelBinders { public enum TestType { -#pragma warning disable SA1602 // Enumeration items should be documented How, Much, Is, The, Fish -#pragma warning restore SA1602 // Enumeration items should be documented } }