diff options
Diffstat (limited to 'MediaBrowser.Model')
45 files changed, 962 insertions, 383 deletions
diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs index c6580598b..5ec6b0dd4 100644 --- a/MediaBrowser.Model/Branding/BrandingOptions.cs +++ b/MediaBrowser.Model/Branding/BrandingOptions.cs @@ -1,5 +1,3 @@ -using System.Text.Json.Serialization; - namespace MediaBrowser.Model.Branding; /// <summary> @@ -27,10 +25,5 @@ public class BrandingOptions /// <summary> /// Gets or sets the splashscreen location on disk. /// </summary> - /// <remarks> - /// Not served via the API. - /// Only used to save the custom uploaded user splashscreen in the configuration file. - /// </remarks> - [JsonIgnore] public string? SplashscreenLocation { get; set; } } diff --git a/MediaBrowser.Model/Branding/BrandingOptionsDto.cs b/MediaBrowser.Model/Branding/BrandingOptionsDto.cs new file mode 100644 index 000000000..c0d8cb31c --- /dev/null +++ b/MediaBrowser.Model/Branding/BrandingOptionsDto.cs @@ -0,0 +1,25 @@ +namespace MediaBrowser.Model.Branding; + +/// <summary> +/// The branding options DTO for API use. +/// This DTO excludes SplashscreenLocation to prevent it from being updated via API. +/// </summary> +public class BrandingOptionsDto +{ + /// <summary> + /// Gets or sets the login disclaimer. + /// </summary> + /// <value>The login disclaimer.</value> + public string? LoginDisclaimer { get; set; } + + /// <summary> + /// Gets or sets the custom CSS. + /// </summary> + /// <value>The custom CSS.</value> + public string? CustomCss { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether to enable the splashscreen. + /// </summary> + public bool SplashscreenEnabled { get; set; } = false; +} diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index 09b966367..1b61bfe15 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -345,6 +345,15 @@ namespace MediaBrowser.Model.Dlna return !condition.IsRequired; } + // Special case: HDR10 also satisfies if the video is HDR10Plus + if (currentValue.Value == VideoRangeType.HDR10Plus) + { + if (IsConditionSatisfied(condition, VideoRangeType.HDR10)) + { + return true; + } + } + var conditionType = condition.Condition; if (conditionType == ProfileConditionType.EqualsAny) { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 806900e9a..61e04a813 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -665,15 +665,39 @@ namespace MediaBrowser.Model.Dlna // Collect candidate audio streams ICollection<MediaStream> candidateAudioStreams = audioStream is null ? [] : [audioStream]; - if (!options.AudioStreamIndex.HasValue || options.AudioStreamIndex < 0) + // When the index is explicitly required by client or the default is specified by user, don't do any stream reselection. + if (!item.DefaultAudioIndexSource.HasFlag(AudioIndexSource.User) && (options.AudioStreamIndex is null or < 0)) { - if (audioStream?.IsDefault == true) + // When user has no preferences allow stream selection on all streams. + if (item.DefaultAudioIndexSource == AudioIndexSource.None && audioStream is not null) { - candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.IsDefault).ToArray(); + candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio).ToArray(); + if (audioStream.IsDefault) + { + // If default is picked, only allow selection within default streams. + candidateAudioStreams = candidateAudioStreams.Where(stream => stream.IsDefault).ToArray(); + } } - else + + if (item.DefaultAudioIndexSource.HasFlag(AudioIndexSource.Language)) { + // If user has language preference, only allow stream selection within the same language. candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.Language == audioStream?.Language).ToArray(); + if (item.DefaultAudioIndexSource.HasFlag(AudioIndexSource.Default)) + { + var defaultStreamsInPreferredLanguage = candidateAudioStreams.Where(stream => stream.IsDefault).ToArray(); + + // If the user also prefers default streams, try limit selection within default tracks in the same language. + // If there is no default stream in the preferred language, allow selection on all default streams to match the "Play default audio track regardless of language" setting. + candidateAudioStreams = defaultStreamsInPreferredLanguage.Length > 0 + ? defaultStreamsInPreferredLanguage + : item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.IsDefault).ToArray(); + } + } + else if (item.DefaultAudioIndexSource.HasFlag(AudioIndexSource.Default)) + { + // If user prefers default streams, only allow stream selection on default streams. + candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.IsDefault).ToArray(); } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index f9aab2d67..13acd15a3 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Linq; using System.Text; @@ -956,12 +957,10 @@ public class StreamInfo sb.Append(AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture)); } - if (SubtitleStreamIndex.HasValue && SubtitleDeliveryMethod != SubtitleDeliveryMethod.External && SubtitleStreamIndex != -1) + if (SubtitleStreamIndex.HasValue && (AlwaysBurnInSubtitleWhenTranscoding || SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) && SubtitleStreamIndex != -1) { sb.Append("&SubtitleStreamIndex="); sb.Append(SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture)); - sb.Append("&SubtitleMethod="); - sb.Append(SubtitleDeliveryMethod.ToString()); } if (VideoBitrate.HasValue) @@ -1095,17 +1094,11 @@ public class StreamInfo sb.Append(CopyTimestamps.ToString(CultureInfo.InvariantCulture)); } - if (RequireAvc) - { - sb.Append("&RequireAvc="); - sb.Append(RequireAvc.ToString(CultureInfo.InvariantCulture)); - } + sb.Append("&RequireAvc="); + sb.Append(RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); - if (EnableAudioVbrEncoding) - { - sb.Append("EnableAudioVbrEncoding="); - sb.Append(EnableAudioVbrEncoding.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); - } + sb.Append("&EnableAudioVbrEncoding="); + sb.Append(EnableAudioVbrEncoding.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); } var etag = MediaSource?.ETag; @@ -1118,7 +1111,7 @@ public class StreamInfo if (SubtitleStreamIndex.HasValue && SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) { sb.Append("&SubtitleMethod="); - sb.AppendJoin(',', SubtitleDeliveryMethod); + sb.Append(SubtitleDeliveryMethod); } if (SubtitleStreamIndex.HasValue && SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed && SubtitleCodecs.Count != 0) diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 7bfd8ca29..937409111 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using Jellyfin.Data.Enums; using Jellyfin.Database.Implementations.Entities; using MediaBrowser.Model.Drawing; @@ -550,7 +551,7 @@ namespace MediaBrowser.Model.Dto /// Gets or sets the parent primary image item identifier. /// </summary> /// <value>The parent primary image item identifier.</value> - public string ParentPrimaryImageItemId { get; set; } + public Guid? ParentPrimaryImageItemId { get; set; } /// <summary> /// Gets or sets the parent primary image tag. @@ -586,6 +587,7 @@ namespace MediaBrowser.Model.Dto /// Gets or sets the type of the media. /// </summary> /// <value>The type of the media.</value> + [DefaultValue(MediaType.Unknown)] public MediaType MediaType { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Dto/BaseItemPerson.cs b/MediaBrowser.Model/Dto/BaseItemPerson.cs index d3bcf492d..80e2cfb08 100644 --- a/MediaBrowser.Model/Dto/BaseItemPerson.cs +++ b/MediaBrowser.Model/Dto/BaseItemPerson.cs @@ -1,6 +1,7 @@ #nullable disable using System; using System.Collections.Generic; +using System.ComponentModel; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; using MediaBrowser.Model.Entities; @@ -34,6 +35,7 @@ namespace MediaBrowser.Model.Dto /// Gets or sets the type. /// </summary> /// <value>The type.</value> + [DefaultValue(PersonKind.Unknown)] public PersonKind Type { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 66de18cfe..75ccdcf27 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -24,6 +24,7 @@ namespace MediaBrowser.Model.Dto SupportsDirectPlay = true; SupportsProbing = true; UseMostCompatibleTranscodingProfile = false; + DefaultAudioIndexSource = AudioIndexSource.None; } public MediaProtocol Protocol { get; set; } @@ -118,6 +119,9 @@ namespace MediaBrowser.Model.Dto [JsonIgnore] public TranscodeReason TranscodeReasons { get; set; } + [JsonIgnore] + public AudioIndexSource DefaultAudioIndexSource { get; set; } + public int? DefaultAudioStreamIndex { get; set; } public int? DefaultSubtitleStreamIndex { get; set; } diff --git a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs index a3035bf61..2f3a5d117 100644 --- a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs +++ b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs @@ -1,35 +1,55 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; using Jellyfin.Data.Enums; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Providers; -namespace MediaBrowser.Model.Dto +namespace MediaBrowser.Model.Dto; + +/// <summary> +/// A class representing metadata editor information. +/// </summary> +public class MetadataEditorInfo { - public class MetadataEditorInfo + /// <summary> + /// Initializes a new instance of the <see cref="MetadataEditorInfo"/> class. + /// </summary> + public MetadataEditorInfo() { - public MetadataEditorInfo() - { - ParentalRatingOptions = Array.Empty<ParentalRating>(); - Countries = Array.Empty<CountryInfo>(); - Cultures = Array.Empty<CultureDto>(); - ExternalIdInfos = Array.Empty<ExternalIdInfo>(); - ContentTypeOptions = Array.Empty<NameValuePair>(); - } - - public IReadOnlyList<ParentalRating> ParentalRatingOptions { get; set; } - - public IReadOnlyList<CountryInfo> Countries { get; set; } - - public IReadOnlyList<CultureDto> Cultures { get; set; } - - public IReadOnlyList<ExternalIdInfo> ExternalIdInfos { get; set; } - - public CollectionType? ContentType { get; set; } - - public IReadOnlyList<NameValuePair> ContentTypeOptions { get; set; } + ParentalRatingOptions = []; + Countries = []; + Cultures = []; + ExternalIdInfos = []; + ContentTypeOptions = []; } + + /// <summary> + /// Gets or sets the parental rating options. + /// </summary> + public IReadOnlyList<ParentalRating> ParentalRatingOptions { get; set; } + + /// <summary> + /// Gets or sets the countries. + /// </summary> + public IReadOnlyList<CountryInfo> Countries { get; set; } + + /// <summary> + /// Gets or sets the cultures. + /// </summary> + public IReadOnlyList<CultureDto> Cultures { get; set; } + + /// <summary> + /// Gets or sets the external id infos. + /// </summary> + public IReadOnlyList<ExternalIdInfo> ExternalIdInfos { get; set; } + + /// <summary> + /// Gets or sets the content type. + /// </summary> + public CollectionType? ContentType { get; set; } + + /// <summary> + /// Gets or sets the content type options. + /// </summary> + public IReadOnlyList<NameValuePair> ContentTypeOptions { get; set; } } diff --git a/MediaBrowser.Model/Entities/MediaAttachment.cs b/MediaBrowser.Model/Entities/MediaAttachment.cs index 34e3eabc9..f8f7ad0f9 100644 --- a/MediaBrowser.Model/Entities/MediaAttachment.cs +++ b/MediaBrowser.Model/Entities/MediaAttachment.cs @@ -1,51 +1,49 @@ -#nullable disable -namespace MediaBrowser.Model.Entities +namespace MediaBrowser.Model.Entities; + +/// <summary> +/// Class MediaAttachment. +/// </summary> +public class MediaAttachment { /// <summary> - /// Class MediaAttachment. + /// Gets or sets the codec. /// </summary> - public class MediaAttachment - { - /// <summary> - /// Gets or sets the codec. - /// </summary> - /// <value>The codec.</value> - public string Codec { get; set; } + /// <value>The codec.</value> + public string? Codec { get; set; } - /// <summary> - /// Gets or sets the codec tag. - /// </summary> - /// <value>The codec tag.</value> - public string CodecTag { get; set; } + /// <summary> + /// Gets or sets the codec tag. + /// </summary> + /// <value>The codec tag.</value> + public string? CodecTag { get; set; } - /// <summary> - /// Gets or sets the comment. - /// </summary> - /// <value>The comment.</value> - public string Comment { get; set; } + /// <summary> + /// Gets or sets the comment. + /// </summary> + /// <value>The comment.</value> + public string? Comment { get; set; } - /// <summary> - /// Gets or sets the index. - /// </summary> - /// <value>The index.</value> - public int Index { get; set; } + /// <summary> + /// Gets or sets the index. + /// </summary> + /// <value>The index.</value> + public int Index { get; set; } - /// <summary> - /// Gets or sets the filename. - /// </summary> - /// <value>The filename.</value> - public string FileName { get; set; } + /// <summary> + /// Gets or sets the filename. + /// </summary> + /// <value>The filename.</value> + public string? FileName { get; set; } - /// <summary> - /// Gets or sets the MIME type. - /// </summary> - /// <value>The MIME type.</value> - public string MimeType { get; set; } + /// <summary> + /// Gets or sets the MIME type. + /// </summary> + /// <value>The MIME type.</value> + public string? MimeType { get; set; } - /// <summary> - /// Gets or sets the delivery URL. - /// </summary> - /// <value>The delivery URL.</value> - public string DeliveryUrl { get; set; } - } + /// <summary> + /// Gets or sets the delivery URL. + /// </summary> + /// <value>The delivery URL.</value> + public string? DeliveryUrl { get; set; } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 400768ef3..5c8f37fcd 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -2,6 +2,7 @@ #pragma warning disable CS1591 using System; +using System.Collections.Frozen; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -153,10 +154,13 @@ namespace MediaBrowser.Model.Entities /// <value>The title.</value> public string Title { get; set; } + public bool? Hdr10PlusPresentFlag { get; set; } + /// <summary> /// Gets the video range. /// </summary> /// <value>The video range.</value> + [DefaultValue(VideoRange.Unknown)] public VideoRange VideoRange { get @@ -171,6 +175,7 @@ namespace MediaBrowser.Model.Entities /// Gets the video range type. /// </summary> /// <value>The video range type.</value> + [DefaultValue(VideoRangeType.Unknown)] public VideoRangeType VideoRangeType { get @@ -268,7 +273,7 @@ namespace MediaBrowser.Model.Entities // Do not display the language code in display titles if unset or set to a special code. Show it in all other cases (possibly expanded). if (!string.IsNullOrEmpty(Language) && !_specialCodes.Contains(Language, StringComparison.OrdinalIgnoreCase)) { - // Get full language string i.e. eng -> English. Will not work for some languages which use ISO 639-2/B instead of /T codes. + // Get full language string i.e. eng -> English. string fullLanguage = CultureInfo .GetCultures(CultureTypes.NeutralCultures) .FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase)) @@ -371,7 +376,7 @@ namespace MediaBrowser.Model.Entities if (!string.IsNullOrEmpty(Language)) { - // Get full language string i.e. eng -> English. Will not work for some languages which use ISO 639-2/B instead of /T codes. + // Get full language string i.e. eng -> English. string fullLanguage = CultureInfo .GetCultures(CultureTypes.NeutralCultures) .FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase)) @@ -778,8 +783,8 @@ namespace MediaBrowser.Model.Entities var blPresentFlag = BlPresentFlag == 1; var dvBlCompatId = DvBlSignalCompatibilityId; - var isDoViProfile = dvProfile == 5 || dvProfile == 7 || dvProfile == 8 || dvProfile == 10; - var isDoViFlag = rpuPresentFlag && blPresentFlag && (dvBlCompatId == 0 || dvBlCompatId == 1 || dvBlCompatId == 4 || dvBlCompatId == 2 || dvBlCompatId == 6); + var isDoViProfile = dvProfile is 5 or 7 or 8 or 10; + var isDoViFlag = rpuPresentFlag && blPresentFlag && dvBlCompatId is 0 or 1 or 4 or 2 or 6; if ((isDoViProfile && isDoViFlag) || string.Equals(codecTag, "dovi", StringComparison.OrdinalIgnoreCase) @@ -787,7 +792,7 @@ namespace MediaBrowser.Model.Entities || string.Equals(codecTag, "dvhe", StringComparison.OrdinalIgnoreCase) || string.Equals(codecTag, "dav1", StringComparison.OrdinalIgnoreCase)) { - return dvProfile switch + var dvRangeSet = dvProfile switch { 5 => (VideoRange.HDR, VideoRangeType.DOVI), 8 => dvBlCompatId switch @@ -795,32 +800,40 @@ namespace MediaBrowser.Model.Entities 1 => (VideoRange.HDR, VideoRangeType.DOVIWithHDR10), 4 => (VideoRange.HDR, VideoRangeType.DOVIWithHLG), 2 => (VideoRange.SDR, VideoRangeType.DOVIWithSDR), - // While not in Dolby Spec, Profile 8 CCid 6 media are possible to create, and since CCid 6 stems from Bluray (Profile 7 originally) an HDR10 base layer is guaranteed to exist. - 6 => (VideoRange.HDR, VideoRangeType.DOVIWithHDR10), - // There is no other case to handle here as per Dolby Spec. Default case included for completeness and linting purposes - _ => (VideoRange.SDR, VideoRangeType.SDR) + // Out of Dolby Spec files should be marked as invalid + _ => (VideoRange.HDR, VideoRangeType.DOVIInvalid) }, - 7 => (VideoRange.HDR, VideoRangeType.HDR10), + 7 => (VideoRange.HDR, VideoRangeType.DOVIWithEL), 10 => dvBlCompatId switch { 0 => (VideoRange.HDR, VideoRangeType.DOVI), 1 => (VideoRange.HDR, VideoRangeType.DOVIWithHDR10), 2 => (VideoRange.SDR, VideoRangeType.DOVIWithSDR), 4 => (VideoRange.HDR, VideoRangeType.DOVIWithHLG), - // While not in Dolby Spec, Profile 8 CCid 6 media are possible to create, and since CCid 6 stems from Bluray (Profile 7 originally) an HDR10 base layer is guaranteed to exist. - 6 => (VideoRange.HDR, VideoRangeType.DOVIWithHDR10), - // There is no other case to handle here as per Dolby Spec. Default case included for completeness and linting purposes - _ => (VideoRange.SDR, VideoRangeType.SDR) + // Out of Dolby Spec files should be marked as invalid + _ => (VideoRange.HDR, VideoRangeType.DOVIInvalid) }, _ => (VideoRange.SDR, VideoRangeType.SDR) }; + + if (Hdr10PlusPresentFlag == true) + { + return dvRangeSet.Item2 switch + { + VideoRangeType.DOVIWithHDR10 => (VideoRange.HDR, VideoRangeType.DOVIWithHDR10Plus), + VideoRangeType.DOVIWithEL => (VideoRange.HDR, VideoRangeType.DOVIWithELHDR10Plus), + _ => dvRangeSet + }; + } + + return dvRangeSet; } var colorTransfer = ColorTransfer; if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase)) { - return (VideoRange.HDR, VideoRangeType.HDR10); + return Hdr10PlusPresentFlag == true ? (VideoRange.HDR, VideoRangeType.HDR10Plus) : (VideoRange.HDR, VideoRangeType.HDR10); } else if (string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Entities/ParentalRating.cs b/MediaBrowser.Model/Entities/ParentalRating.cs index c92640818..4f1198902 100644 --- a/MediaBrowser.Model/Entities/ParentalRating.cs +++ b/MediaBrowser.Model/Entities/ParentalRating.cs @@ -1,33 +1,40 @@ -#nullable disable -#pragma warning disable CS1591 +namespace MediaBrowser.Model.Entities; -namespace MediaBrowser.Model.Entities +/// <summary> +/// Class ParentalRating. +/// </summary> +public class ParentalRating { /// <summary> - /// Class ParentalRating. + /// Initializes a new instance of the <see cref="ParentalRating"/> class. /// </summary> - public class ParentalRating + /// <param name="name">The name.</param> + /// <param name="score">The score.</param> + public ParentalRating(string name, ParentalRatingScore? score) { - public ParentalRating() - { - } + Name = name; + Value = score?.Score; + RatingScore = score; + } - public ParentalRating(string name, int? value) - { - Name = name; - Value = value; - } + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - public string Name { get; set; } + /// <summary> + /// Gets or sets the value. + /// </summary> + /// <value>The value.</value> + /// <remarks> + /// Deprecated. + /// </remarks> + public int? Value { get; set; } - /// <summary> - /// Gets or sets the value. - /// </summary> - /// <value>The value.</value> - public int? Value { get; set; } - } + /// <summary> + /// Gets or sets the rating score. + /// </summary> + /// <value>The rating score.</value> + public ParentalRatingScore? RatingScore { get; set; } } diff --git a/MediaBrowser.Model/Entities/ParentalRatingEntry.cs b/MediaBrowser.Model/Entities/ParentalRatingEntry.cs new file mode 100644 index 000000000..69be74ac0 --- /dev/null +++ b/MediaBrowser.Model/Entities/ParentalRatingEntry.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Model.Entities; + +/// <summary> +/// A class representing an parental rating entry. +/// </summary> +public class ParentalRatingEntry +{ + /// <summary> + /// Gets or sets the rating strings. + /// </summary> + [JsonPropertyName("ratingStrings")] + public required IReadOnlyList<string> RatingStrings { get; set; } + + /// <summary> + /// Gets or sets the score. + /// </summary> + [JsonPropertyName("ratingScore")] + public required ParentalRatingScore RatingScore { get; set; } +} diff --git a/MediaBrowser.Model/Entities/ParentalRatingScore.cs b/MediaBrowser.Model/Entities/ParentalRatingScore.cs new file mode 100644 index 000000000..b9bb99685 --- /dev/null +++ b/MediaBrowser.Model/Entities/ParentalRatingScore.cs @@ -0,0 +1,32 @@ +using System.Text.Json.Serialization; + +namespace MediaBrowser.Model.Entities; + +/// <summary> +/// A class representing an parental rating score. +/// </summary> +public class ParentalRatingScore +{ + /// <summary> + /// Initializes a new instance of the <see cref="ParentalRatingScore"/> class. + /// </summary> + /// <param name="score">The score.</param> + /// <param name="subScore">The sub score.</param> + public ParentalRatingScore(int score, int? subScore) + { + Score = score; + SubScore = subScore; + } + + /// <summary> + /// Gets or sets the score. + /// </summary> + [JsonPropertyName("score")] + public int Score { get; set; } + + /// <summary> + /// Gets or sets the sub score. + /// </summary> + [JsonPropertyName("subScore")] + public int? SubScore { get; set; } +} diff --git a/MediaBrowser.Model/Entities/ParentalRatingSystem.cs b/MediaBrowser.Model/Entities/ParentalRatingSystem.cs new file mode 100644 index 000000000..b452f2901 --- /dev/null +++ b/MediaBrowser.Model/Entities/ParentalRatingSystem.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Model.Entities; + +/// <summary> +/// A class representing a parental rating system. +/// </summary> +public class ParentalRatingSystem +{ + /// <summary> + /// Gets or sets the country code. + /// </summary> + [JsonPropertyName("countryCode")] + public required string CountryCode { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether sub scores are supported. + /// </summary> + [JsonPropertyName("supportsSubScores")] + public bool SupportsSubScores { get; set; } + + /// <summary> + /// Gets or sets the ratings. + /// </summary> + [JsonPropertyName("ratings")] + public IReadOnlyList<ParentalRatingEntry>? Ratings { get; set; } +} diff --git a/MediaBrowser.Model/Extensions/ContainerHelper.cs b/MediaBrowser.Model/Extensions/ContainerHelper.cs index 39e5358ba..848cc2f62 100644 --- a/MediaBrowser.Model/Extensions/ContainerHelper.cs +++ b/MediaBrowser.Model/Extensions/ContainerHelper.cs @@ -21,7 +21,7 @@ public static class ContainerHelper public static bool ContainsContainer(string? profileContainers, string? inputContainer) { var isNegativeList = false; - if (profileContainers != null && profileContainers.StartsWith('-')) + if (profileContainers is not null && profileContainers.StartsWith('-')) { isNegativeList = true; profileContainers = profileContainers[1..]; @@ -42,7 +42,7 @@ public static class ContainerHelper public static bool ContainsContainer(string? profileContainers, ReadOnlySpan<char> inputContainer) { var isNegativeList = false; - if (profileContainers != null && profileContainers.StartsWith('-')) + if (profileContainers is not null && profileContainers.StartsWith('-')) { isNegativeList = true; profileContainers = profileContainers[1..]; diff --git a/MediaBrowser.Model/Extensions/EnumerableExtensions.cs b/MediaBrowser.Model/Extensions/EnumerableExtensions.cs index 8963bdb73..94f425229 100644 --- a/MediaBrowser.Model/Extensions/EnumerableExtensions.cs +++ b/MediaBrowser.Model/Extensions/EnumerableExtensions.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Model.Extensions return 0; }) - .ThenByDescending(i => i.CommunityRating ?? 0) + .ThenByDescending(i => Math.Round(i.CommunityRating ?? 0, 1) ) .ThenByDescending(i => i.VoteCount ?? 0); } } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index 20deaa505..f6e65028e 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -1,65 +1,73 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using MediaBrowser.Model.Entities; -namespace MediaBrowser.Model.Globalization +namespace MediaBrowser.Model.Globalization; + +/// <summary> +/// Interface ILocalizationManager. +/// </summary> +public interface ILocalizationManager { /// <summary> - /// Interface ILocalizationManager. + /// Gets the cultures. /// </summary> - public interface ILocalizationManager - { - /// <summary> - /// Gets the cultures. - /// </summary> - /// <returns><see cref="IEnumerable{CultureDto}" />.</returns> - IEnumerable<CultureDto> GetCultures(); + /// <returns><see cref="IEnumerable{CultureDto}" />.</returns> + IEnumerable<CultureDto> GetCultures(); - /// <summary> - /// Gets the countries. - /// </summary> - /// <returns><see cref="IEnumerable{CountryInfo}" />.</returns> - IEnumerable<CountryInfo> GetCountries(); + /// <summary> + /// Gets the countries. + /// </summary> + /// <returns><see cref="IReadOnlyList{CountryInfo}" />.</returns> + IReadOnlyList<CountryInfo> GetCountries(); - /// <summary> - /// Gets the parental ratings. - /// </summary> - /// <returns><see cref="IEnumerable{ParentalRating}" />.</returns> - IEnumerable<ParentalRating> GetParentalRatings(); + /// <summary> + /// Gets the parental ratings. + /// </summary> + /// <returns><see cref="IReadOnlyList{ParentalRating}" />.</returns> + IReadOnlyList<ParentalRating> GetParentalRatings(); - /// <summary> - /// Gets the rating level. - /// </summary> - /// <param name="rating">The rating.</param> - /// <param name="countryCode">The optional two letter ISO language string.</param> - /// <returns><see cref="int" /> or <c>null</c>.</returns> - int? GetRatingLevel(string rating, string? countryCode = null); + /// <summary> + /// Gets the rating level. + /// </summary> + /// <param name="rating">The rating.</param> + /// <param name="countryCode">The optional two letter ISO language string.</param> + /// <returns><see cref="ParentalRatingScore" /> or <c>null</c>.</returns> + ParentalRatingScore? GetRatingScore(string rating, string? countryCode = null); + + /// <summary> + /// Gets the localized string. + /// </summary> + /// <param name="phrase">The phrase.</param> + /// <param name="culture">The culture.</param> + /// <returns><see cref="string" />.</returns> + string GetLocalizedString(string phrase, string culture); - /// <summary> - /// Gets the localized string. - /// </summary> - /// <param name="phrase">The phrase.</param> - /// <param name="culture">The culture.</param> - /// <returns><see cref="string" />.</returns> - string GetLocalizedString(string phrase, string culture); + /// <summary> + /// Gets the localized string. + /// </summary> + /// <param name="phrase">The phrase.</param> + /// <returns>System.String.</returns> + string GetLocalizedString(string phrase); - /// <summary> - /// Gets the localized string. - /// </summary> - /// <param name="phrase">The phrase.</param> - /// <returns>System.String.</returns> - string GetLocalizedString(string phrase); + /// <summary> + /// Gets the localization options. + /// </summary> + /// <returns><see cref="IEnumerable{LocalizationOption}" />.</returns> + IEnumerable<LocalizationOption> GetLocalizationOptions(); - /// <summary> - /// Gets the localization options. - /// </summary> - /// <returns><see cref="IEnumerable{LocalizationOption}" />.</returns> - IEnumerable<LocalizationOption> GetLocalizationOptions(); + /// <summary> + /// Returns the correct <see cref="CultureDto" /> for the given language. + /// </summary> + /// <param name="language">The language.</param> + /// <returns>The correct <see cref="CultureDto" /> for the given language.</returns> + CultureDto? FindLanguageInfo(string language); - /// <summary> - /// Returns the correct <see cref="CultureDto" /> for the given language. - /// </summary> - /// <param name="language">The language.</param> - /// <returns>The correct <see cref="CultureDto" /> for the given language.</returns> - CultureDto? FindLanguageInfo(string language); - } + /// <summary> + /// Returns the language in ISO 639-2/T when the input is ISO 639-2/B. + /// </summary> + /// <param name="isoB">The language in ISO 639-2/B.</param> + /// <param name="isoT">The language in ISO 639-2/T.</param> + /// <returns>Whether the language could be converted.</returns> + public bool TryGetISO6392TFromB(string isoB, [NotNullWhen(true)] out string? isoT); } diff --git a/MediaBrowser.Model/IO/AsyncFile.cs b/MediaBrowser.Model/IO/AsyncFile.cs index 3c8007d1c..a9db6b81c 100644 --- a/MediaBrowser.Model/IO/AsyncFile.cs +++ b/MediaBrowser.Model/IO/AsyncFile.cs @@ -27,6 +27,14 @@ namespace MediaBrowser.Model.IO }; /// <summary> + /// Creates, or truncates and overwrites, a file in the specified path. + /// </summary> + /// <param name="path">The path and name of the file to create.</param> + /// <returns>A <see cref="FileStream" /> that provides read/write access to the file specified in path.</returns> + public static FileStream Create(string path) + => new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + + /// <summary> /// Opens an existing file for reading. /// </summary> /// <param name="path">The file to be opened for reading.</param> diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs index b26f5f45f..1e8add943 100644 --- a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs @@ -83,7 +83,7 @@ namespace MediaBrowser.Model.LiveTv /// Gets or sets the parent primary image item identifier. /// </summary> /// <value>The parent primary image item identifier.</value> - public string ParentPrimaryImageItemId { get; set; } + public Guid? ParentPrimaryImageItemId { get; set; } /// <summary> /// Gets or sets the parent primary image tag. diff --git a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs index a355387b1..b70333bce 100644 --- a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs +++ b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs @@ -9,6 +9,7 @@ namespace MediaBrowser.Model.LiveTv { AllowHWTranscoding = true; IgnoreDts = true; + ReadAtNativeFramerate = false; AllowStreamSharing = true; AllowFmp4TranscodingContainer = false; FallbackMaxStreamingBitrate = 30000000; @@ -43,5 +44,7 @@ namespace MediaBrowser.Model.LiveTv public string UserAgent { get; set; } public bool IgnoreDts { get; set; } + + public bool ReadAtNativeFramerate { get; set; } } } diff --git a/MediaBrowser.Model/Lyrics/LyricLine.cs b/MediaBrowser.Model/Lyrics/LyricLine.cs index 64d1f64c2..788bace69 100644 --- a/MediaBrowser.Model/Lyrics/LyricLine.cs +++ b/MediaBrowser.Model/Lyrics/LyricLine.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace MediaBrowser.Model.Lyrics; /// <summary> @@ -10,10 +12,12 @@ public class LyricLine /// </summary> /// <param name="text">The lyric text.</param> /// <param name="start">The lyric start time in ticks.</param> - public LyricLine(string text, long? start = null) + /// <param name="cues">The time-aligned cues for the song's lyrics.</param> + public LyricLine(string text, long? start = null, IReadOnlyList<LyricLineCue>? cues = null) { Text = text; Start = start; + Cues = cues; } /// <summary> @@ -25,4 +29,9 @@ public class LyricLine /// Gets the start time in ticks. /// </summary> public long? Start { get; } + + /// <summary> + /// Gets the time-aligned cues for the song's lyrics. + /// </summary> + public IReadOnlyList<LyricLineCue>? Cues { get; } } diff --git a/MediaBrowser.Model/Lyrics/LyricLineCue.cs b/MediaBrowser.Model/Lyrics/LyricLineCue.cs new file mode 100644 index 000000000..1172a0231 --- /dev/null +++ b/MediaBrowser.Model/Lyrics/LyricLineCue.cs @@ -0,0 +1,35 @@ +namespace MediaBrowser.Model.Lyrics; + +/// <summary> +/// LyricLineCue model, holds information about the timing of words within a LyricLine. +/// </summary> +public class LyricLineCue +{ + /// <summary> + /// Initializes a new instance of the <see cref="LyricLineCue"/> class. + /// </summary> + /// <param name="position">The start of the character index of the lyric.</param> + /// <param name="start">The start of the timestamp the lyric is synced to in ticks.</param> + /// <param name="end">The end of the timestamp the lyric is synced to in ticks.</param> + public LyricLineCue(int position, long start, long? end) + { + Position = position; + Start = start; + End = end; + } + + /// <summary> + /// Gets the character index of the lyric. + /// </summary> + public int Position { get; } + + /// <summary> + /// Gets the timestamp the lyric is synced to in ticks. + /// </summary> + public long Start { get; } + + /// <summary> + /// Gets the end timestamp the lyric is synced to in ticks. + /// </summary> + public long? End { get; } +} diff --git a/MediaBrowser.Model/Lyrics/LyricSearchRequest.cs b/MediaBrowser.Model/Lyrics/LyricSearchRequest.cs index 48c442a55..67f3d7b42 100644 --- a/MediaBrowser.Model/Lyrics/LyricSearchRequest.cs +++ b/MediaBrowser.Model/Lyrics/LyricSearchRequest.cs @@ -15,7 +15,12 @@ public class LyricSearchRequest : IHasProviderIds public string? MediaPath { get; set; } /// <summary> - /// Gets or sets the artist name. + /// Gets or sets the album artist names. + /// </summary> + public IReadOnlyList<string>? AlbumArtistsNames { get; set; } + + /// <summary> + /// Gets or sets the artist names. /// </summary> public IReadOnlyList<string>? ArtistNames { get; set; } diff --git a/MediaBrowser.Model/MediaInfo/AudioIndexSource.cs b/MediaBrowser.Model/MediaInfo/AudioIndexSource.cs new file mode 100644 index 000000000..810087b92 --- /dev/null +++ b/MediaBrowser.Model/MediaInfo/AudioIndexSource.cs @@ -0,0 +1,30 @@ +using System; + +namespace MediaBrowser.Model.MediaInfo; + +/// <summary> +/// How is the audio index determined. +/// </summary> +[Flags] +public enum AudioIndexSource +{ + /// <summary> + /// The default index when no preference is specified. + /// </summary> + None = 0, + + /// <summary> + /// The index is calculated whether the track is marked as default or not. + /// </summary> + Default = 1 << 0, + + /// <summary> + /// The index is calculated whether the track is in preferred language or not. + /// </summary> + Language = 1 << 1, + + /// <summary> + /// The index is specified by the user. + /// </summary> + User = 1 << 2 +} diff --git a/MediaBrowser.Model/MediaSegments/MediaSegmentDto.cs b/MediaBrowser.Model/MediaSegments/MediaSegmentDto.cs index 6e5c7885c..d9129c395 100644 --- a/MediaBrowser.Model/MediaSegments/MediaSegmentDto.cs +++ b/MediaBrowser.Model/MediaSegments/MediaSegmentDto.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using Jellyfin.Database.Implementations.Enums; namespace MediaBrowser.Model.MediaSegments; @@ -21,6 +22,7 @@ public class MediaSegmentDto /// <summary> /// Gets or sets the type of content this segment defines. /// </summary> + [DefaultValue(MediaSegmentType.Unknown)] public MediaSegmentType Type { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 49d7c0bcb..ffecd392f 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -1,7 +1,3 @@ -#pragma warning disable CS1591 - -using System; - namespace MediaBrowser.Model.Querying { /// <summary> @@ -39,6 +35,9 @@ namespace MediaBrowser.Model.Querying /// </summary> Trickplay, + /// <summary> + /// The child count. + /// </summary> ChildCount, /// <summary> @@ -82,11 +81,6 @@ namespace MediaBrowser.Model.Querying Genres, /// <summary> - /// The home page URL. - /// </summary> - HomePageUrl, - - /// <summary> /// The item counts. /// </summary> ItemCounts, @@ -101,6 +95,9 @@ namespace MediaBrowser.Model.Querying /// </summary> MediaSources, + /// <summary> + /// The original title. + /// </summary> OriginalTitle, /// <summary> @@ -123,6 +120,9 @@ namespace MediaBrowser.Model.Querying /// </summary> People, + /// <summary> + /// Value indicating whether playback access is granted. + /// </summary> PlayAccess, /// <summary> @@ -140,6 +140,9 @@ namespace MediaBrowser.Model.Querying /// </summary> PrimaryImageAspectRatio, + /// <summary> + /// The recursive item count. + /// </summary> RecursiveItemCount, /// <summary> @@ -148,14 +151,6 @@ namespace MediaBrowser.Model.Querying Settings, /// <summary> - /// The screenshot image tags. - /// </summary> - [Obsolete("Screenshot image type is no longer used.")] - ScreenshotImageTags, - - SeriesPrimaryImage, - - /// <summary> /// The series studio. /// </summary> SeriesStudio, @@ -201,26 +196,58 @@ namespace MediaBrowser.Model.Querying SeasonUserData, /// <summary> - /// The service name. + /// The last time metadata was refreshed. /// </summary> - ServiceName, - ThemeSongIds, - ThemeVideoIds, - ExternalEtag, - PresentationUniqueKey, - InheritedParentalRatingValue, - ExternalSeriesId, - SeriesPresentationUniqueKey, DateLastRefreshed, + + /// <summary> + /// The last time metadata was saved. + /// </summary> DateLastSaved, + + /// <summary> + /// The refresh state. + /// </summary> RefreshState, + + /// <summary> + /// The channel image. + /// </summary> ChannelImage, + + /// <summary> + /// Value indicating whether media source display is enabled. + /// </summary> EnableMediaSourceDisplay, + + /// <summary> + /// The width. + /// </summary> Width, + + /// <summary> + /// The height. + /// </summary> Height, + + /// <summary> + /// The external Ids. + /// </summary> ExtraIds, + + /// <summary> + /// The local trailer count. + /// </summary> LocalTrailerCount, + + /// <summary> + /// Value indicating whether the item is HD. + /// </summary> IsHD, + + /// <summary> + /// The special feature count. + /// </summary> SpecialFeatureCount } } diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs index 2e2979fcf..a18a813cc 100644 --- a/MediaBrowser.Model/Search/SearchHint.cs +++ b/MediaBrowser.Model/Search/SearchHint.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using Jellyfin.Data.Enums; namespace MediaBrowser.Model.Search @@ -115,6 +116,7 @@ namespace MediaBrowser.Model.Search /// Gets or sets the type of the media. /// </summary> /// <value>The type of the media.</value> + [DefaultValue(MediaType.Unknown)] public MediaType MediaType { get; set; } /// <summary> diff --git a/MediaBrowser.Model/SyncPlay/GroupUpdate.cs b/MediaBrowser.Model/SyncPlay/GroupUpdate.cs index ec67d7ea8..794443499 100644 --- a/MediaBrowser.Model/SyncPlay/GroupUpdate.cs +++ b/MediaBrowser.Model/SyncPlay/GroupUpdate.cs @@ -5,15 +5,18 @@ namespace MediaBrowser.Model.SyncPlay; /// <summary> /// Group update without data. /// </summary> -public abstract class GroupUpdate +/// <typeparam name="T">The type of the update data.</typeparam> +public abstract class GroupUpdate<T> { /// <summary> - /// Initializes a new instance of the <see cref="GroupUpdate"/> class. + /// Initializes a new instance of the <see cref="GroupUpdate{T}"/> class. /// </summary> /// <param name="groupId">The group identifier.</param> - protected GroupUpdate(Guid groupId) + /// <param name="data">The update data.</param> + protected GroupUpdate(Guid groupId, T data) { GroupId = groupId; + Data = data; } /// <summary> @@ -23,8 +26,14 @@ public abstract class GroupUpdate public Guid GroupId { get; } /// <summary> + /// Gets the update data. + /// </summary> + /// <value>The update data.</value> + public T Data { get; } + + /// <summary> /// Gets the update type. /// </summary> /// <value>The update type.</value> - public GroupUpdateType Type { get; init; } + public abstract GroupUpdateType Type { get; } } diff --git a/MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs b/MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs deleted file mode 100644 index 25cd44461..000000000 --- a/MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs +++ /dev/null @@ -1,31 +0,0 @@ -#pragma warning disable SA1649 - -using System; - -namespace MediaBrowser.Model.SyncPlay; - -/// <summary> -/// Class GroupUpdate. -/// </summary> -/// <typeparam name="T">The type of the data of the message.</typeparam> -public class GroupUpdate<T> : GroupUpdate -{ - /// <summary> - /// Initializes a new instance of the <see cref="GroupUpdate{T}"/> class. - /// </summary> - /// <param name="groupId">The group identifier.</param> - /// <param name="type">The update type.</param> - /// <param name="data">The update data.</param> - public GroupUpdate(Guid groupId, GroupUpdateType type, T data) - : base(groupId) - { - Data = data; - Type = type; - } - - /// <summary> - /// Gets the update data. - /// </summary> - /// <value>The update data.</value> - public T Data { get; } -} diff --git a/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs b/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs index 907d1defe..e792229a4 100644 --- a/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs +++ b/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs @@ -46,16 +46,6 @@ namespace MediaBrowser.Model.SyncPlay GroupDoesNotExist, /// <summary> - /// The create-group-denied error. Sent when a user tries to create a group without required permissions. - /// </summary> - CreateGroupDenied, - - /// <summary> - /// The join-group-denied error. Sent when a user tries to join a group without required permissions. - /// </summary> - JoinGroupDenied, - - /// <summary> /// The library-access-denied error. Sent when a user tries to join a group without required access to the library. /// </summary> LibraryAccessDenied diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs new file mode 100644 index 000000000..7e2d10c8b --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayGroupDoesNotExistUpdate : GroupUpdate<string> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayGroupDoesNotExistUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayGroupDoesNotExistUpdate(Guid groupId, string data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.GroupDoesNotExist)] + public override GroupUpdateType Type => GroupUpdateType.GroupDoesNotExist; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs new file mode 100644 index 000000000..bfb49152a --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayGroupJoinedUpdate : GroupUpdate<GroupInfoDto> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayGroupJoinedUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayGroupJoinedUpdate(Guid groupId, GroupInfoDto data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.GroupJoined)] + public override GroupUpdateType Type => GroupUpdateType.GroupJoined; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs new file mode 100644 index 000000000..5ff60c5c2 --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayGroupLeftUpdate : GroupUpdate<string> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayGroupLeftUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayGroupLeftUpdate(Guid groupId, string data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.GroupLeft)] + public override GroupUpdateType Type => GroupUpdateType.GroupLeft; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs new file mode 100644 index 000000000..0d9a722f7 --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayLibraryAccessDeniedUpdate : GroupUpdate<string> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayLibraryAccessDeniedUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayLibraryAccessDeniedUpdate(Guid groupId, string data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.LibraryAccessDenied)] + public override GroupUpdateType Type => GroupUpdateType.LibraryAccessDenied; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs new file mode 100644 index 000000000..a3b610f61 --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayNotInGroupUpdate : GroupUpdate<string> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayNotInGroupUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayNotInGroupUpdate(Guid groupId, string data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.NotInGroup)] + public override GroupUpdateType Type => GroupUpdateType.NotInGroup; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs new file mode 100644 index 000000000..83d9bd40b --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayPlayQueueUpdate : GroupUpdate<PlayQueueUpdate> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayPlayQueueUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayPlayQueueUpdate(Guid groupId, PlayQueueUpdate data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.PlayQueue)] + public override GroupUpdateType Type => GroupUpdateType.PlayQueue; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs new file mode 100644 index 000000000..744ca46a0 --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayStateUpdate : GroupUpdate<GroupStateUpdate> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayStateUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayStateUpdate(Guid groupId, GroupStateUpdate data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.StateUpdate)] + public override GroupUpdateType Type => GroupUpdateType.StateUpdate; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs new file mode 100644 index 000000000..e8c6b4df4 --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayUserJoinedUpdate : GroupUpdate<string> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayUserJoinedUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayUserJoinedUpdate(Guid groupId, string data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.UserJoined)] + public override GroupUpdateType Type => GroupUpdateType.UserJoined; +} diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs new file mode 100644 index 000000000..97be8e63a --- /dev/null +++ b/MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel; + +namespace MediaBrowser.Model.SyncPlay; + +/// <inheritdoc /> +public class SyncPlayUserLeftUpdate : GroupUpdate<string> +{ + /// <summary> + /// Initializes a new instance of the <see cref="SyncPlayUserLeftUpdate"/> class. + /// </summary> + /// <param name="groupId">The groupId.</param> + /// <param name="data">The data.</param> + public SyncPlayUserLeftUpdate(Guid groupId, string data) : base(groupId, data) + { + } + + /// <inheritdoc /> + [DefaultValue(GroupUpdateType.UserLeft)] + public override GroupUpdateType Type => GroupUpdateType.UserLeft; +} diff --git a/MediaBrowser.Model/System/FolderStorageInfo.cs b/MediaBrowser.Model/System/FolderStorageInfo.cs new file mode 100644 index 000000000..7b10e4ea5 --- /dev/null +++ b/MediaBrowser.Model/System/FolderStorageInfo.cs @@ -0,0 +1,32 @@ +namespace MediaBrowser.Model.System; + +/// <summary> +/// Contains information about a specific folder. +/// </summary> +public record FolderStorageInfo +{ + /// <summary> + /// Gets the path of the folder in question. + /// </summary> + public required string Path { get; init; } + + /// <summary> + /// Gets the free space of the underlying storage device of the <see cref="Path"/>. + /// </summary> + public long FreeSpace { get; init; } + + /// <summary> + /// Gets the used space of the underlying storage device of the <see cref="Path"/>. + /// </summary> + public long UsedSpace { get; init; } + + /// <summary> + /// Gets the kind of storage device of the <see cref="Path"/>. + /// </summary> + public string? StorageType { get; init; } + + /// <summary> + /// Gets the Device Identifier. + /// </summary> + public string? DeviceId { get; init; } +} diff --git a/MediaBrowser.Model/System/LibraryStorageInfo.cs b/MediaBrowser.Model/System/LibraryStorageInfo.cs new file mode 100644 index 000000000..d4111b29c --- /dev/null +++ b/MediaBrowser.Model/System/LibraryStorageInfo.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Model.System; + +/// <summary> +/// Contains informations about a libraries storage informations. +/// </summary> +public class LibraryStorageInfo +{ + /// <summary> + /// Gets or sets the Library Id. + /// </summary> + public required Guid Id { get; set; } + + /// <summary> + /// Gets or sets the name of the library. + /// </summary> + public required string Name { get; set; } + + /// <summary> + /// Gets or sets the storage informations about the folders used in a library. + /// </summary> + public required IReadOnlyCollection<FolderStorageInfo> Folders { get; set; } +} diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index f37ac6a14..232a2a6bc 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -6,133 +6,139 @@ using System.Collections.Generic; using System.ComponentModel; using MediaBrowser.Model.Updates; -namespace MediaBrowser.Model.System +namespace MediaBrowser.Model.System; + +/// <summary> +/// Class SystemInfo. +/// </summary> +public class SystemInfo : PublicSystemInfo { /// <summary> - /// Class SystemInfo. + /// Initializes a new instance of the <see cref="SystemInfo" /> class. /// </summary> - public class SystemInfo : PublicSystemInfo + public SystemInfo() { - /// <summary> - /// Initializes a new instance of the <see cref="SystemInfo" /> class. - /// </summary> - public SystemInfo() - { - CompletedInstallations = Array.Empty<InstallationInfo>(); - } - - /// <summary> - /// Gets or sets the display name of the operating system. - /// </summary> - /// <value>The display name of the operating system.</value> - [Obsolete("This is no longer set")] - public string OperatingSystemDisplayName { get; set; } = string.Empty; - - /// <summary> - /// Gets or sets the package name. - /// </summary> - /// <value>The value of the '-package' command line argument.</value> - public string PackageName { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance has pending restart. - /// </summary> - /// <value><c>true</c> if this instance has pending restart; otherwise, <c>false</c>.</value> - public bool HasPendingRestart { get; set; } - - public bool IsShuttingDown { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether [supports library monitor]. - /// </summary> - /// <value><c>true</c> if [supports library monitor]; otherwise, <c>false</c>.</value> - public bool SupportsLibraryMonitor { get; set; } - - /// <summary> - /// Gets or sets the web socket port number. - /// </summary> - /// <value>The web socket port number.</value> - public int WebSocketPortNumber { get; set; } - - /// <summary> - /// Gets or sets the completed installations. - /// </summary> - /// <value>The completed installations.</value> - public InstallationInfo[] CompletedInstallations { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance can self restart. - /// </summary> - /// <value><c>true</c>.</value> - [Obsolete("This is always true")] - [DefaultValue(true)] - public bool CanSelfRestart { get; set; } = true; - - [Obsolete("This is always false")] - [DefaultValue(false)] - public bool CanLaunchWebBrowser { get; set; } = false; - - /// <summary> - /// Gets or sets the program data path. - /// </summary> - /// <value>The program data path.</value> - public string ProgramDataPath { get; set; } - - /// <summary> - /// Gets or sets the web UI resources path. - /// </summary> - /// <value>The web UI resources path.</value> - public string WebPath { get; set; } - - /// <summary> - /// Gets or sets the items by name path. - /// </summary> - /// <value>The items by name path.</value> - public string ItemsByNamePath { get; set; } - - /// <summary> - /// Gets or sets the cache path. - /// </summary> - /// <value>The cache path.</value> - public string CachePath { get; set; } - - /// <summary> - /// Gets or sets the log path. - /// </summary> - /// <value>The log path.</value> - public string LogPath { get; set; } - - /// <summary> - /// Gets or sets the internal metadata path. - /// </summary> - /// <value>The internal metadata path.</value> - public string InternalMetadataPath { get; set; } - - /// <summary> - /// Gets or sets the transcode path. - /// </summary> - /// <value>The transcode path.</value> - public string TranscodingTempPath { get; set; } - - /// <summary> - /// Gets or sets the list of cast receiver applications. - /// </summary> - public IReadOnlyList<CastReceiverApplication> CastReceiverApplications { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance has update available. - /// </summary> - /// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value> - [Obsolete("This should be handled by the package manager")] - [DefaultValue(false)] - public bool HasUpdateAvailable { get; set; } - - [Obsolete("This isn't set correctly anymore")] - [DefaultValue("System")] - public string EncoderLocation { get; set; } = "System"; - - [Obsolete("This is no longer set")] - [DefaultValue("X64")] - public string SystemArchitecture { get; set; } = "X64"; + CompletedInstallations = Array.Empty<InstallationInfo>(); } + + /// <summary> + /// Gets or sets the display name of the operating system. + /// </summary> + /// <value>The display name of the operating system.</value> + [Obsolete("This is no longer set")] + public string OperatingSystemDisplayName { get; set; } = string.Empty; + + /// <summary> + /// Gets or sets the package name. + /// </summary> + /// <value>The value of the '-package' command line argument.</value> + public string PackageName { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance has pending restart. + /// </summary> + /// <value><c>true</c> if this instance has pending restart; otherwise, <c>false</c>.</value> + public bool HasPendingRestart { get; set; } + + public bool IsShuttingDown { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether [supports library monitor]. + /// </summary> + /// <value><c>true</c> if [supports library monitor]; otherwise, <c>false</c>.</value> + public bool SupportsLibraryMonitor { get; set; } + + /// <summary> + /// Gets or sets the web socket port number. + /// </summary> + /// <value>The web socket port number.</value> + public int WebSocketPortNumber { get; set; } + + /// <summary> + /// Gets or sets the completed installations. + /// </summary> + /// <value>The completed installations.</value> + public InstallationInfo[] CompletedInstallations { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance can self restart. + /// </summary> + /// <value><c>true</c>.</value> + [Obsolete("This is always true")] + [DefaultValue(true)] + public bool CanSelfRestart { get; set; } = true; + + [Obsolete("This is always false")] + [DefaultValue(false)] + public bool CanLaunchWebBrowser { get; set; } = false; + + /// <summary> + /// Gets or sets the program data path. + /// </summary> + /// <value>The program data path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string ProgramDataPath { get; set; } + + /// <summary> + /// Gets or sets the web UI resources path. + /// </summary> + /// <value>The web UI resources path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string WebPath { get; set; } + + /// <summary> + /// Gets or sets the items by name path. + /// </summary> + /// <value>The items by name path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string ItemsByNamePath { get; set; } + + /// <summary> + /// Gets or sets the cache path. + /// </summary> + /// <value>The cache path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string CachePath { get; set; } + + /// <summary> + /// Gets or sets the log path. + /// </summary> + /// <value>The log path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string LogPath { get; set; } + + /// <summary> + /// Gets or sets the internal metadata path. + /// </summary> + /// <value>The internal metadata path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string InternalMetadataPath { get; set; } + + /// <summary> + /// Gets or sets the transcode path. + /// </summary> + /// <value>The transcode path.</value> + [Obsolete("Use the newer SystemStorageDto instead")] + public string TranscodingTempPath { get; set; } + + /// <summary> + /// Gets or sets the list of cast receiver applications. + /// </summary> + public IReadOnlyList<CastReceiverApplication> CastReceiverApplications { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance has update available. + /// </summary> + /// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value> + [Obsolete("This should be handled by the package manager")] + [DefaultValue(false)] + public bool HasUpdateAvailable { get; set; } + + [Obsolete("This isn't set correctly anymore")] + [DefaultValue("System")] + public string EncoderLocation { get; set; } = "System"; + + [Obsolete("This is no longer set")] + [DefaultValue("X64")] + public string SystemArchitecture { get; set; } = "X64"; } diff --git a/MediaBrowser.Model/System/SystemStorageInfo.cs b/MediaBrowser.Model/System/SystemStorageInfo.cs new file mode 100644 index 000000000..42e7a37e0 --- /dev/null +++ b/MediaBrowser.Model/System/SystemStorageInfo.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Model.System; + +/// <summary> +/// Contains informations about the systems storage. +/// </summary> +public class SystemStorageInfo +{ + /// <summary> + /// Gets or sets the program data path. + /// </summary> + /// <value>The program data path.</value> + public required FolderStorageInfo ProgramDataFolder { get; set; } + + /// <summary> + /// Gets or sets the web UI resources path. + /// </summary> + /// <value>The web UI resources path.</value> + public required FolderStorageInfo WebFolder { get; set; } + + /// <summary> + /// Gets or sets the items by name path. + /// </summary> + /// <value>The items by name path.</value> + public required FolderStorageInfo ImageCacheFolder { get; set; } + + /// <summary> + /// Gets or sets the cache path. + /// </summary> + /// <value>The cache path.</value> + public required FolderStorageInfo CacheFolder { get; set; } + + /// <summary> + /// Gets or sets the log path. + /// </summary> + /// <value>The log path.</value> + public required FolderStorageInfo LogFolder { get; set; } + + /// <summary> + /// Gets or sets the internal metadata path. + /// </summary> + /// <value>The internal metadata path.</value> + public required FolderStorageInfo InternalMetadataFolder { get; set; } + + /// <summary> + /// Gets or sets the transcode path. + /// </summary> + /// <value>The transcode path.</value> + public required FolderStorageInfo TranscodingTempFolder { get; set; } + + /// <summary> + /// Gets or sets the storage informations of all libraries. + /// </summary> + public required IReadOnlyCollection<LibraryStorageInfo> Libraries { get; set; } +} diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 3d430e101..2c393ca86 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -111,6 +111,8 @@ namespace MediaBrowser.Model.Users /// <value>The max parental rating.</value> public int? MaxParentalRating { get; set; } + public int? MaxParentalSubRating { get; set; } + public string[] BlockedTags { get; set; } public string[] AllowedTags { get; set; } |
