aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Model
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Model')
-rw-r--r--MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs26
-rw-r--r--MediaBrowser.Model/Configuration/EncodingOptions.cs3
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs12
-rw-r--r--MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs87
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs5
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs14
-rw-r--r--MediaBrowser.Model/Entities/MediaStream.cs224
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj2
-rw-r--r--MediaBrowser.Model/Notifications/NotificationOption.cs13
-rw-r--r--MediaBrowser.Model/Plugins/PluginInfo.cs6
-rw-r--r--MediaBrowser.Model/Providers/ExternalIdInfo.cs32
-rw-r--r--MediaBrowser.Model/Providers/ExternalIdMediaType.cs71
-rw-r--r--MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs3
-rw-r--r--MediaBrowser.Model/Services/QueryParamCollection.cs4
-rw-r--r--MediaBrowser.Model/Services/RouteAttribute.cs18
-rw-r--r--MediaBrowser.Model/SyncPlay/JoinGroupRequest.cs6
-rw-r--r--MediaBrowser.Model/SyncPlay/PlaybackRequestType.cs6
-rw-r--r--MediaBrowser.Model/Updates/RepositoryInfo.cs20
18 files changed, 406 insertions, 146 deletions
diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs
index 54f4fb293c..66f3e1a94b 100644
--- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs
@@ -12,7 +12,15 @@ namespace MediaBrowser.Model.Configuration
public class BaseApplicationConfiguration
{
/// <summary>
- /// The number of days we should retain log files.
+ /// Initializes a new instance of the <see cref="BaseApplicationConfiguration" /> class.
+ /// </summary>
+ public BaseApplicationConfiguration()
+ {
+ LogFileRetentionDays = 3;
+ }
+
+ /// <summary>
+ /// Gets or sets the number of days we should retain log files.
/// </summary>
/// <value>The log file retention days.</value>
public int LogFileRetentionDays { get; set; }
@@ -30,29 +38,21 @@ namespace MediaBrowser.Model.Configuration
public string CachePath { get; set; }
/// <summary>
- /// Last known version that was ran using the configuration.
+ /// Gets or sets the last known version that was ran using the configuration.
/// </summary>
/// <value>The version from previous run.</value>
[XmlIgnore]
public Version PreviousVersion { get; set; }
/// <summary>
- /// Stringified PreviousVersion to be stored/loaded,
- /// because System.Version itself isn't xml-serializable
+ /// Gets or sets the stringified PreviousVersion to be stored/loaded,
+ /// because System.Version itself isn't xml-serializable.
/// </summary>
- /// <value>String value of PreviousVersion</value>
+ /// <value>String value of PreviousVersion.</value>
public string PreviousVersionStr
{
get => PreviousVersion?.ToString();
set => PreviousVersion = Version.Parse(value);
}
-
- /// <summary>
- /// Initializes a new instance of the <see cref="BaseApplicationConfiguration" /> class.
- /// </summary>
- public BaseApplicationConfiguration()
- {
- LogFileRetentionDays = 3;
- }
}
}
diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs
index a790ec42af..9a30f7e9f0 100644
--- a/MediaBrowser.Model/Configuration/EncodingOptions.cs
+++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs
@@ -36,8 +36,11 @@ namespace MediaBrowser.Model.Configuration
public string EncoderPreset { get; set; }
public string DeinterlaceMethod { get; set; }
+
public bool EnableDecodingColorDepth10Hevc { get; set; }
+
public bool EnableDecodingColorDepth10Vp9 { get; set; }
+
public bool EnableHardwareEncoding { get; set; }
public bool EnableSubtitleExtraction { get; set; }
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 4a7cf78012..82aefbd85e 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -2,7 +2,9 @@
#pragma warning disable CS1591
using System;
+using System.Collections.Generic;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Updates;
namespace MediaBrowser.Model.Configuration
{
@@ -85,8 +87,6 @@ namespace MediaBrowser.Model.Configuration
public bool EnableRemoteAccess { get; set; }
- public bool CollectionsUpgraded { get; set; }
-
/// <summary>
/// Gets or sets a value indicating whether [enable case sensitive item ids].
/// </summary>
@@ -234,6 +234,8 @@ namespace MediaBrowser.Model.Configuration
public string[] CodecsUsed { get; set; }
+ public List<RepositoryInfo> PluginRepositories { get; set; }
+
public bool IgnoreVirtualInterfaces { get; set; }
public bool EnableExternalContentInSuggestions { get; set; }
@@ -270,6 +272,9 @@ namespace MediaBrowser.Model.Configuration
PathSubstitutions = Array.Empty<PathSubstitution>();
IgnoreVirtualInterfaces = false;
EnableSimpleArtistDetection = false;
+ SkipDeserializationForBasicTypes = true;
+
+ PluginRepositories = new List<RepositoryInfo>();
DisplaySpecialsWithinSeasons = true;
EnableExternalContentInSuggestions = true;
@@ -283,6 +288,9 @@ namespace MediaBrowser.Model.Configuration
EnableHttps = false;
EnableDashboardResponseCaching = true;
EnableCaseSensitiveItemIds = true;
+ EnableNormalizedItemByNameIds = true;
+ DisableLiveTvChannelUserDataName = true;
+ EnableNewOmdbSupport = true;
AutoRunWebApp = true;
EnableRemoteAccess = true;
diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
index 47cc892107..bdc5f8bb78 100644
--- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
+++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
@@ -32,18 +32,25 @@ namespace MediaBrowser.Model.Dlna
}
if (string.Equals(container, "avi", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.AVI };
+ }
if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.MATROSKA };
+ }
if (string.Equals(container, "mpeg2ps", StringComparison.OrdinalIgnoreCase) ||
string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase))
-
+ {
return new MediaFormatProfile[] { MediaFormatProfile.MPEG_PS_NTSC, MediaFormatProfile.MPEG_PS_PAL };
+ }
if (string.Equals(container, "mpeg1video", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.MPEG1 };
+ }
if (string.Equals(container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) ||
string.Equals(container, "mpegts", StringComparison.OrdinalIgnoreCase) ||
@@ -54,10 +61,14 @@ namespace MediaBrowser.Model.Dlna
}
if (string.Equals(container, "flv", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.FLV };
+ }
if (string.Equals(container, "wtv", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.WTV };
+ }
if (string.Equals(container, "3gp", StringComparison.OrdinalIgnoreCase))
{
@@ -66,7 +77,9 @@ namespace MediaBrowser.Model.Dlna
}
if (string.Equals(container, "ogv", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.OGV };
+ }
return Array.Empty<MediaFormatProfile>();
}
@@ -111,7 +124,9 @@ namespace MediaBrowser.Model.Dlna
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(audioCodec, "lpcm", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { MediaFormatProfile.AVC_TS_HD_50_LPCM_T };
+ }
if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase))
{
@@ -134,14 +149,20 @@ namespace MediaBrowser.Model.Dlna
}
if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AAC_MULT5{1}", resolution, suffix)) };
+ }
if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_MPEG1_L3{1}", resolution, suffix)) };
+ }
if (string.IsNullOrEmpty(audioCodec) ||
string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AC3{1}", resolution, suffix)) };
+ }
}
else if (string.Equals(videoCodec, "vc1", StringComparison.OrdinalIgnoreCase))
{
@@ -165,16 +186,27 @@ namespace MediaBrowser.Model.Dlna
else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AAC{0}", suffix)) };
+ }
+
if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) };
+ }
+
if (string.Equals(audioCodec, "mp2", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) };
+ }
+
if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase))
+ {
return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AC3{0}", suffix)) };
+ }
}
- return new MediaFormatProfile[] { };
+ return Array.Empty<MediaFormatProfile>();
}
private MediaFormatProfile ValueOf(string value)
@@ -187,7 +219,10 @@ namespace MediaBrowser.Model.Dlna
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(audioCodec, "lpcm", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.AVC_MP4_LPCM;
+ }
+
if (string.IsNullOrEmpty(audioCodec) ||
string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase))
{
@@ -204,12 +239,16 @@ namespace MediaBrowser.Model.Dlna
if ((width.Value <= 720) && (height.Value <= 576))
{
if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.AVC_MP4_MP_SD_AAC_MULT5;
+ }
}
else if ((width.Value <= 1280) && (height.Value <= 720))
{
if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.AVC_MP4_MP_HD_720p_AAC;
+ }
}
else if ((width.Value <= 1920) && (height.Value <= 1080))
{
@@ -226,7 +265,10 @@ namespace MediaBrowser.Model.Dlna
if (width.HasValue && height.HasValue && width.Value <= 720 && height.Value <= 576)
{
if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.MPEG4_P2_MP4_ASP_AAC;
+ }
+
if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase) || string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase))
{
return MediaFormatProfile.MPEG4_P2_MP4_NDSD;
@@ -250,15 +292,22 @@ namespace MediaBrowser.Model.Dlna
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.AVC_3GPP_BL_QCIF15_AAC;
+ }
}
else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) ||
string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.MPEG4_P2_3GPP_SP_L0B_AAC;
+ }
+
if (string.Equals(audioCodec, "amrnb", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.MPEG4_P2_3GPP_SP_L0B_AMR;
+ }
}
else if (string.Equals(videoCodec, "h263", StringComparison.OrdinalIgnoreCase) && string.Equals(audioCodec, "amrnb", StringComparison.OrdinalIgnoreCase))
{
@@ -300,11 +349,19 @@ namespace MediaBrowser.Model.Dlna
if (width.HasValue && height.HasValue)
{
if ((width.Value <= 720) && (height.Value <= 576))
+ {
return MediaFormatProfile.VC1_ASF_AP_L1_WMA;
+ }
+
if ((width.Value <= 1280) && (height.Value <= 720))
+ {
return MediaFormatProfile.VC1_ASF_AP_L2_WMA;
+ }
+
if ((width.Value <= 1920) && (height.Value <= 1080))
+ {
return MediaFormatProfile.VC1_ASF_AP_L3_WMA;
+ }
}
}
else if (string.Equals(videoCodec, "mpeg2video", StringComparison.OrdinalIgnoreCase))
@@ -318,27 +375,41 @@ namespace MediaBrowser.Model.Dlna
public MediaFormatProfile? ResolveAudioFormat(string container, int? bitrate, int? frequency, int? channels)
{
if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
+ {
return ResolveAudioASFFormat(bitrate);
+ }
if (string.Equals(container, "mp3", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.MP3;
+ }
if (string.Equals(container, "lpcm", StringComparison.OrdinalIgnoreCase))
+ {
return ResolveAudioLPCMFormat(frequency, channels);
+ }
if (string.Equals(container, "mp4", StringComparison.OrdinalIgnoreCase) ||
string.Equals(container, "aac", StringComparison.OrdinalIgnoreCase))
+ {
return ResolveAudioMP4Format(bitrate);
+ }
if (string.Equals(container, "adts", StringComparison.OrdinalIgnoreCase))
+ {
return ResolveAudioADTSFormat(bitrate);
+ }
if (string.Equals(container, "flac", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.FLAC;
+ }
if (string.Equals(container, "oga", StringComparison.OrdinalIgnoreCase) ||
string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.OGG;
+ }
return null;
}
@@ -410,13 +481,19 @@ namespace MediaBrowser.Model.Dlna
return ResolveImageJPGFormat(width, height);
if (string.Equals(container, "png", StringComparison.OrdinalIgnoreCase))
+ {
return ResolveImagePNGFormat(width, height);
+ }
if (string.Equals(container, "gif", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.GIF_LRG;
+ }
if (string.Equals(container, "raw", StringComparison.OrdinalIgnoreCase))
+ {
return MediaFormatProfile.RAW;
+ }
return null;
}
@@ -426,10 +503,14 @@ namespace MediaBrowser.Model.Dlna
if (width.HasValue && height.HasValue)
{
if ((width.Value <= 160) && (height.Value <= 160))
+ {
return MediaFormatProfile.JPEG_TN;
+ }
if ((width.Value <= 640) && (height.Value <= 480))
+ {
return MediaFormatProfile.JPEG_SM;
+ }
if ((width.Value <= 1024) && (height.Value <= 768))
{
@@ -447,7 +528,9 @@ namespace MediaBrowser.Model.Dlna
if (width.HasValue && height.HasValue)
{
if ((width.Value <= 160) && (height.Value <= 160))
+ {
return MediaFormatProfile.PNG_TN;
+ }
}
return MediaFormatProfile.PNG_LRG;
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 06bd244763..cfe862f5a9 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -384,7 +384,10 @@ namespace MediaBrowser.Model.Dlna
audioCodecProfiles.Add(i);
}
- if (audioCodecProfiles.Count >= 1) break;
+ if (audioCodecProfiles.Count >= 1)
+ {
+ break;
+ }
}
var audioTranscodingConditions = new List<ProfileCondition>();
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index b89e9ce90a..204340c466 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -144,7 +144,7 @@ namespace MediaBrowser.Model.Dlna
public Dictionary<string, string> StreamOptions { get; private set; }
- public string MediaSourceId => MediaSource == null ? null : MediaSource.Id;
+ public string MediaSourceId => MediaSource?.Id;
public bool IsDirectStream =>
PlayMethod == PlayMethod.DirectStream ||
@@ -813,18 +813,18 @@ namespace MediaBrowser.Model.Dlna
{
var stream = TargetAudioStream;
- string inputCodec = stream == null ? null : stream.Codec;
+ string inputCodec = stream?.Codec;
if (IsDirectStream)
{
- return string.IsNullOrEmpty(inputCodec) ? new string[] { } : new[] { inputCodec };
+ return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec };
}
foreach (string codec in AudioCodecs)
{
if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase))
{
- return string.IsNullOrEmpty(codec) ? new string[] { } : new[] { codec };
+ return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec };
}
}
@@ -838,18 +838,18 @@ namespace MediaBrowser.Model.Dlna
{
var stream = TargetVideoStream;
- string inputCodec = stream == null ? null : stream.Codec;
+ string inputCodec = stream?.Codec;
if (IsDirectStream)
{
- return string.IsNullOrEmpty(inputCodec) ? new string[] { } : new[] { inputCodec };
+ return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec };
}
foreach (string codec in VideoCodecs)
{
if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase))
{
- return string.IsNullOrEmpty(codec) ? new string[] { } : new[] { codec };
+ return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec };
}
}
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index d8ee79d0d0..1b37cfc939 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -112,107 +112,146 @@ namespace MediaBrowser.Model.Entities
{
get
{
- if (Type == MediaStreamType.Audio)
+ switch (Type)
{
- // if (!string.IsNullOrEmpty(Title))
- //{
- // return AddLanguageIfNeeded(Title);
- //}
-
- var attributes = new List<string>();
-
- if (!string.IsNullOrEmpty(Language))
- {
- attributes.Add(StringHelper.FirstToUpper(Language));
- }
-
- if (!string.IsNullOrEmpty(Codec) && !string.Equals(Codec, "dca", StringComparison.OrdinalIgnoreCase))
- {
- attributes.Add(AudioCodec.GetFriendlyName(Codec));
- }
- else if (!string.IsNullOrEmpty(Profile) && !string.Equals(Profile, "lc", StringComparison.OrdinalIgnoreCase))
- {
- attributes.Add(Profile);
- }
-
- if (!string.IsNullOrEmpty(ChannelLayout))
- {
- attributes.Add(ChannelLayout);
- }
- else if (Channels.HasValue)
- {
- attributes.Add(Channels.Value.ToString(CultureInfo.InvariantCulture) + " ch");
- }
-
- if (IsDefault)
- {
- attributes.Add("Default");
- }
-
- return string.Join(" ", attributes);
- }
-
- if (Type == MediaStreamType.Video)
- {
- var attributes = new List<string>();
-
- var resolutionText = GetResolutionText();
-
- if (!string.IsNullOrEmpty(resolutionText))
+ case MediaStreamType.Audio:
{
- attributes.Add(resolutionText);
+ var attributes = new List<string>();
+
+ 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.
+ string fullLanguage = CultureInfo
+ .GetCultures(CultureTypes.NeutralCultures)
+ .FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase))
+ ?.DisplayName;
+ attributes.Add(StringHelper.FirstToUpper(fullLanguage ?? Language));
+ }
+
+ if (!string.IsNullOrEmpty(Codec) && !string.Equals(Codec, "dca", StringComparison.OrdinalIgnoreCase))
+ {
+ attributes.Add(AudioCodec.GetFriendlyName(Codec));
+ }
+ else if (!string.IsNullOrEmpty(Profile) && !string.Equals(Profile, "lc", StringComparison.OrdinalIgnoreCase))
+ {
+ attributes.Add(Profile);
+ }
+
+ if (!string.IsNullOrEmpty(ChannelLayout))
+ {
+ attributes.Add(StringHelper.FirstToUpper(ChannelLayout));
+ }
+ else if (Channels.HasValue)
+ {
+ attributes.Add(Channels.Value.ToString(CultureInfo.InvariantCulture) + " ch");
+ }
+
+ if (IsDefault)
+ {
+ attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault);
+ }
+
+ if (!string.IsNullOrEmpty(Title))
+ {
+ var result = new StringBuilder(Title);
+ foreach (var tag in attributes)
+ {
+ // Keep Tags that are not already in Title.
+ if (Title.IndexOf(tag, StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ result.Append(" - ").Append(tag);
+ }
+ }
+
+ return result.ToString();
+ }
+
+ return string.Join(" - ", attributes);
}
- if (!string.IsNullOrEmpty(Codec))
+ case MediaStreamType.Video:
{
- attributes.Add(Codec.ToUpperInvariant());
+ var attributes = new List<string>();
+
+ var resolutionText = GetResolutionText();
+
+ if (!string.IsNullOrEmpty(resolutionText))
+ {
+ attributes.Add(resolutionText);
+ }
+
+ if (!string.IsNullOrEmpty(Codec))
+ {
+ attributes.Add(Codec.ToUpperInvariant());
+ }
+
+ if (!string.IsNullOrEmpty(Title))
+ {
+ var result = new StringBuilder(Title);
+ foreach (var tag in attributes)
+ {
+ // Keep Tags that are not already in Title.
+ if (Title.IndexOf(tag, StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ result.Append(" - ").Append(tag);
+ }
+ }
+
+ return result.ToString();
+ }
+
+ return string.Join(" ", attributes);
}
- return string.Join(" ", attributes);
- }
-
- if (Type == MediaStreamType.Subtitle)
- {
-
- var attributes = new List<string>();
-
- if (!string.IsNullOrEmpty(Language))
- {
- attributes.Add(StringHelper.FirstToUpper(Language));
- }
- else
- {
- attributes.Add(string.IsNullOrEmpty(localizedUndefined) ? "Und" : localizedUndefined);
- }
-
- if (IsDefault)
+ case MediaStreamType.Subtitle:
{
- attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault);
+ var attributes = new List<string>();
+
+ 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.
+ string fullLanguage = CultureInfo
+ .GetCultures(CultureTypes.NeutralCultures)
+ .FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase))
+ ?.DisplayName;
+ attributes.Add(StringHelper.FirstToUpper(fullLanguage ?? Language));
+ }
+ else
+ {
+ attributes.Add(string.IsNullOrEmpty(localizedUndefined) ? "Und" : localizedUndefined);
+ }
+
+ if (IsDefault)
+ {
+ attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault);
+ }
+
+ if (IsForced)
+ {
+ attributes.Add(string.IsNullOrEmpty(localizedForced) ? "Forced" : localizedForced);
+ }
+
+ if (!string.IsNullOrEmpty(Title))
+ {
+ var result = new StringBuilder(Title);
+ foreach (var tag in attributes)
+ {
+ // Keep Tags that are not already in Title.
+ if (Title.IndexOf(tag, StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ result.Append(" - ").Append(tag);
+ }
+ }
+
+ return result.ToString();
+ }
+
+ return string.Join(" - ", attributes.ToArray());
}
- if (IsForced)
- {
- attributes.Add(string.IsNullOrEmpty(localizedForced) ? "Forced" : localizedForced);
- }
-
- if (!string.IsNullOrEmpty(Title))
- {
- return attributes.AsEnumerable()
- // keep Tags that are not already in Title
- .Where(tag => Title.IndexOf(tag, StringComparison.OrdinalIgnoreCase) == -1)
- // attributes concatenation, starting with Title
- .Aggregate(new StringBuilder(Title), (builder, attr) => builder.Append(" - ").Append(attr))
- .ToString();
- }
-
- return string.Join(" - ", attributes.ToArray());
+ default:
+ return null;
}
-
- if (Type == MediaStreamType.Video)
- {
- }
-
- return null;
}
}
@@ -421,7 +460,10 @@ namespace MediaBrowser.Model.Entities
{
get
{
- if (Type != MediaStreamType.Subtitle) return false;
+ if (Type != MediaStreamType.Subtitle)
+ {
+ return false;
+ }
if (string.IsNullOrEmpty(Codec) && !IsExternal)
{
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 83bd0c07e6..902e29b20b 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -23,7 +23,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
- <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.5" />
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.6" />
<PackageReference Include="System.Globalization" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
</ItemGroup>
diff --git a/MediaBrowser.Model/Notifications/NotificationOption.cs b/MediaBrowser.Model/Notifications/NotificationOption.cs
index ea363d9b17..58aecb3d35 100644
--- a/MediaBrowser.Model/Notifications/NotificationOption.cs
+++ b/MediaBrowser.Model/Notifications/NotificationOption.cs
@@ -1,3 +1,4 @@
+#pragma warning disable CA1819 // Properties should not return arrays
#pragma warning disable CS1591
using System;
@@ -9,21 +10,27 @@ namespace MediaBrowser.Model.Notifications
public NotificationOption(string type)
{
Type = type;
+ DisabledServices = Array.Empty<string>();
+ DisabledMonitorUsers = Array.Empty<string>();
+ SendToUsers = Array.Empty<string>();
+ }
+ public NotificationOption()
+ {
DisabledServices = Array.Empty<string>();
DisabledMonitorUsers = Array.Empty<string>();
SendToUsers = Array.Empty<string>();
}
- public string Type { get; set; }
+ public string? Type { get; set; }
/// <summary>
- /// User Ids to not monitor (it's opt out).
+ /// Gets or sets user Ids to not monitor (it's opt out).
/// </summary>
public string[] DisabledMonitorUsers { get; set; }
/// <summary>
- /// User Ids to send to (if SendToUserMode == Custom)
+ /// Gets or sets user Ids to send to (if SendToUserMode == Custom).
/// </summary>
public string[] SendToUsers { get; set; }
diff --git a/MediaBrowser.Model/Plugins/PluginInfo.cs b/MediaBrowser.Model/Plugins/PluginInfo.cs
index c13f1a89f1..dd215192f9 100644
--- a/MediaBrowser.Model/Plugins/PluginInfo.cs
+++ b/MediaBrowser.Model/Plugins/PluginInfo.cs
@@ -35,6 +35,12 @@ namespace MediaBrowser.Model.Plugins
/// </summary>
/// <value>The unique id.</value>
public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the plugin can be uninstalled.
+ /// </summary>
+ public bool CanUninstall { get; set; }
+
/// <summary>
/// Gets or sets the image URL.
/// </summary>
diff --git a/MediaBrowser.Model/Providers/ExternalIdInfo.cs b/MediaBrowser.Model/Providers/ExternalIdInfo.cs
index f2e6d8ef32..01784554f9 100644
--- a/MediaBrowser.Model/Providers/ExternalIdInfo.cs
+++ b/MediaBrowser.Model/Providers/ExternalIdInfo.cs
@@ -1,26 +1,36 @@
-#nullable disable
-#pragma warning disable CS1591
-
namespace MediaBrowser.Model.Providers
{
+ /// <summary>
+ /// Represents the external id information for serialization to the client.
+ /// </summary>
public class ExternalIdInfo
{
/// <summary>
- /// Gets or sets the name.
+ /// Gets or sets the display name of the external id provider (IE: IMDB, MusicBrainz, etc).
+ /// </summary>
+ // TODO: This should be renamed to ProviderName
+ public string? Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the unique key for this id. This key should be unique across all providers.
/// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
+ // TODO: This property is not actually unique across the concrete types at the moment. It should be updated to be unique.
+ public string? Key { get; set; }
/// <summary>
- /// Gets or sets the key.
+ /// Gets or sets the specific media type for this id. This is used to distinguish between the different
+ /// external id types for providers with multiple ids.
+ /// A null value indicates there is no specific media type associated with the external id, or this is the
+ /// default id for the external provider so there is no need to specify a type.
/// </summary>
- /// <value>The key.</value>
- public string Key { get; set; }
+ /// <remarks>
+ /// This can be used along with the <see cref="Name"/> to localize the external id on the client.
+ /// </remarks>
+ public ExternalIdMediaType? Type { get; set; }
/// <summary>
/// Gets or sets the URL format string.
/// </summary>
- /// <value>The URL format string.</value>
- public string UrlFormatString { get; set; }
+ public string? UrlFormatString { get; set; }
}
}
diff --git a/MediaBrowser.Model/Providers/ExternalIdMediaType.cs b/MediaBrowser.Model/Providers/ExternalIdMediaType.cs
new file mode 100644
index 0000000000..5303c8f58b
--- /dev/null
+++ b/MediaBrowser.Model/Providers/ExternalIdMediaType.cs
@@ -0,0 +1,71 @@
+namespace MediaBrowser.Model.Providers
+{
+ /// <summary>
+ /// The specific media type of an <see cref="ExternalIdInfo"/>.
+ /// </summary>
+ /// <remarks>
+ /// Client applications may use this as a translation key.
+ /// </remarks>
+ public enum ExternalIdMediaType
+ {
+ /// <summary>
+ /// A music album.
+ /// </summary>
+ Album = 1,
+
+ /// <summary>
+ /// The artist of a music album.
+ /// </summary>
+ AlbumArtist = 2,
+
+ /// <summary>
+ /// The artist of a media item.
+ /// </summary>
+ Artist = 3,
+
+ /// <summary>
+ /// A boxed set of media.
+ /// </summary>
+ BoxSet = 4,
+
+ /// <summary>
+ /// A series episode.
+ /// </summary>
+ Episode = 5,
+
+ /// <summary>
+ /// A movie.
+ /// </summary>
+ Movie = 6,
+
+ /// <summary>
+ /// An alternative artist apart from the main artist.
+ /// </summary>
+ OtherArtist = 7,
+
+ /// <summary>
+ /// A person.
+ /// </summary>
+ Person = 8,
+
+ /// <summary>
+ /// A release group.
+ /// </summary>
+ ReleaseGroup = 9,
+
+ /// <summary>
+ /// A single season of a series.
+ /// </summary>
+ Season = 10,
+
+ /// <summary>
+ /// A series.
+ /// </summary>
+ Series = 11,
+
+ /// <summary>
+ /// A music track.
+ /// </summary>
+ Track = 12
+ }
+}
diff --git a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs
index 12d537492a..2ef6f7c60b 100644
--- a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs
+++ b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs
@@ -1,6 +1,7 @@
#nullable disable
#pragma warning disable CS1591
+using System;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Querying
@@ -54,7 +55,7 @@ namespace MediaBrowser.Model.Querying
public UpcomingEpisodesQuery()
{
- EnableImageTypes = new ImageType[] { };
+ EnableImageTypes = Array.Empty<ImageType>();
}
}
}
diff --git a/MediaBrowser.Model/Services/QueryParamCollection.cs b/MediaBrowser.Model/Services/QueryParamCollection.cs
index d07ff15482..bdb0cabdf2 100644
--- a/MediaBrowser.Model/Services/QueryParamCollection.cs
+++ b/MediaBrowser.Model/Services/QueryParamCollection.cs
@@ -124,8 +124,8 @@ namespace MediaBrowser.Model.Services
/// Gets or sets a query parameter value by name. A query may contain multiple values of the same name
/// (i.e. "x=1&amp;x=2"), in which case the value is an array, which works for both getting and setting.
/// </summary>
- /// <param name="name">The query parameter name</param>
- /// <returns>The query parameter value or array of values</returns>
+ /// <param name="name">The query parameter name.</param>
+ /// <returns>The query parameter value or array of values.</returns>
public string this[string name]
{
get => Get(name);
diff --git a/MediaBrowser.Model/Services/RouteAttribute.cs b/MediaBrowser.Model/Services/RouteAttribute.cs
index 162576aa7e..f8bf511124 100644
--- a/MediaBrowser.Model/Services/RouteAttribute.cs
+++ b/MediaBrowser.Model/Services/RouteAttribute.cs
@@ -128,9 +128,21 @@ namespace MediaBrowser.Model.Services
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != this.GetType()) return false;
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != this.GetType())
+ {
+ return false;
+ }
+
return Equals((RouteAttribute)obj);
}
diff --git a/MediaBrowser.Model/SyncPlay/JoinGroupRequest.cs b/MediaBrowser.Model/SyncPlay/JoinGroupRequest.cs
index d67b6bd555..0c77a61322 100644
--- a/MediaBrowser.Model/SyncPlay/JoinGroupRequest.cs
+++ b/MediaBrowser.Model/SyncPlay/JoinGroupRequest.cs
@@ -12,11 +12,5 @@ namespace MediaBrowser.Model.SyncPlay
/// </summary>
/// <value>The Group id to join.</value>
public Guid GroupId { get; set; }
-
- /// <summary>
- /// Gets or sets the playing item id.
- /// </summary>
- /// <value>The client's currently playing item id.</value>
- public Guid PlayingItemId { get; set; }
}
}
diff --git a/MediaBrowser.Model/SyncPlay/PlaybackRequestType.cs b/MediaBrowser.Model/SyncPlay/PlaybackRequestType.cs
index 671f4e01ff..e89efeed8a 100644
--- a/MediaBrowser.Model/SyncPlay/PlaybackRequestType.cs
+++ b/MediaBrowser.Model/SyncPlay/PlaybackRequestType.cs
@@ -23,16 +23,16 @@ namespace MediaBrowser.Model.SyncPlay
/// <summary>
/// A user is signaling that playback is buffering.
/// </summary>
- Buffering = 3,
+ Buffer = 3,
/// <summary>
/// A user is signaling that playback resumed.
/// </summary>
- BufferingDone = 4,
+ Ready = 4,
/// <summary>
/// A user is reporting its ping.
/// </summary>
- UpdatePing = 5
+ Ping = 5
}
}
diff --git a/MediaBrowser.Model/Updates/RepositoryInfo.cs b/MediaBrowser.Model/Updates/RepositoryInfo.cs
new file mode 100644
index 0000000000..bd42e77f0f
--- /dev/null
+++ b/MediaBrowser.Model/Updates/RepositoryInfo.cs
@@ -0,0 +1,20 @@
+namespace MediaBrowser.Model.Updates
+{
+ /// <summary>
+ /// Class RepositoryInfo.
+ /// </summary>
+ public class RepositoryInfo
+ {
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string? Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the URL.
+ /// </summary>
+ /// <value>The URL.</value>
+ public string? Url { get; set; }
+ }
+}