2
0
Эх сурвалжийг харах

Merge pull request #6423 from richlander/mediabrowser-controller

Fix warnings in MediaBrowser.Controller
Bond-009 3 жил өмнө
parent
commit
db0d5b048a

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 523 - 381
MediaBrowser.Controller/Entities/BaseItem.cs


+ 5 - 0
MediaBrowser.Controller/Entities/BaseItemExtensions.cs

@@ -64,6 +64,8 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         /// <param name="source">The source object.</param>
         /// <param name="dest">The destination object.</param>
+        /// <typeparam name="T">Source type.</typeparam>
+        /// <typeparam name="TU">Destination type.</typeparam>
         public static void DeepCopy<T, TU>(this T source, TU dest)
             where T : BaseItem
             where TU : BaseItem
@@ -109,6 +111,9 @@ namespace MediaBrowser.Controller.Entities
         /// Copies all properties on newly created object. Skips properties that do not exist.
         /// </summary>
         /// <param name="source">The source object.</param>
+        /// <typeparam name="T">Source type.</typeparam>
+        /// <typeparam name="TU">Destination type.</typeparam>
+        /// <returns>Destination object.</returns>
         public static TU DeepCopy<T, TU>(this T source)
             where T : BaseItem
             where TU : BaseItem, new()

+ 6 - 6
MediaBrowser.Controller/Entities/BasePluginFolder.cs

@@ -15,6 +15,12 @@ namespace MediaBrowser.Controller.Entities
         [JsonIgnore]
         public virtual string CollectionType => null;
 
+        [JsonIgnore]
+        public override bool SupportsInheritedParentImages => false;
+
+        [JsonIgnore]
+        public override bool SupportsPeople => false;
+
         public override bool CanDelete()
         {
             return false;
@@ -24,11 +30,5 @@ namespace MediaBrowser.Controller.Entities
         {
             return true;
         }
-
-        [JsonIgnore]
-        public override bool SupportsInheritedParentImages => false;
-
-        [JsonIgnore]
-        public override bool SupportsPeople => false;
     }
 }

+ 20 - 20
MediaBrowser.Controller/Entities/CollectionFolder.cs

@@ -41,6 +41,23 @@ namespace MediaBrowser.Controller.Entities
             PhysicalFolderIds = Array.Empty<Guid>();
         }
 
+        /// <summary>
+        /// Gets the display preferences id.
+        /// </summary>
+        /// <remarks>
+        /// Allow different display preferences for each collection folder.
+        /// </remarks>
+        /// <value>The display prefs id.</value>
+        [JsonIgnore]
+        public override Guid DisplayPreferencesId => Id;
+
+        [JsonIgnore]
+        public override string[] PhysicalLocations => PhysicalLocationsList;
+
+        public string[] PhysicalLocationsList { get; set; }
+
+        public Guid[] PhysicalFolderIds { get; set; }
+
         public static IXmlSerializer XmlSerializer { get; set; }
 
         public static IServerApplicationHost ApplicationHost { get; set; }
@@ -63,6 +80,9 @@ namespace MediaBrowser.Controller.Entities
         [JsonIgnore]
         public override IEnumerable<BaseItem> Children => GetActualChildren();
 
+        [JsonIgnore]
+        public override bool SupportsPeople => false;
+
         public override bool CanDelete()
         {
             return false;
@@ -160,23 +180,6 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        /// <summary>
-        /// Gets the display preferences id.
-        /// </summary>
-        /// <remarks>
-        /// Allow different display preferences for each collection folder.
-        /// </remarks>
-        /// <value>The display prefs id.</value>
-        [JsonIgnore]
-        public override Guid DisplayPreferencesId => Id;
-
-        [JsonIgnore]
-        public override string[] PhysicalLocations => PhysicalLocationsList;
-
-        public string[] PhysicalLocationsList { get; set; }
-
-        public Guid[] PhysicalFolderIds { get; set; }
-
         public override bool IsSaveLocalMetadataEnabled()
         {
             return true;
@@ -373,8 +376,5 @@ namespace MediaBrowser.Controller.Entities
 
             return result;
         }
-
-        [JsonIgnore]
-        public override bool SupportsPeople => false;
     }
 }

+ 2 - 0
MediaBrowser.Controller/Entities/Extensions.cs

@@ -15,6 +15,8 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Adds the trailer URL.
         /// </summary>
+        /// <param name="item">Media item.</param>
+        /// <param name="url">Trailer URL.</param>
         public static void AddTrailerUrl(this BaseItem item, string url)
         {
             if (string.IsNullOrEmpty(url))

+ 0 - 2
MediaBrowser.Controller/Entities/Folder.cs

@@ -1669,7 +1669,6 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="user">The user.</param>
         /// <param name="datePlayed">The date played.</param>
         /// <param name="resetPosition">if set to <c>true</c> [reset position].</param>
-        /// <returns>Task.</returns>
         public override void MarkPlayed(
             User user,
             DateTime? datePlayed,
@@ -1711,7 +1710,6 @@ namespace MediaBrowser.Controller.Entities
         /// Marks the unplayed.
         /// </summary>
         /// <param name="user">The user.</param>
-        /// <returns>Task.</returns>
         public override void MarkUnplayed(User user)
         {
             var itemsResult = GetItemList(new InternalItemsQuery

+ 2 - 0
MediaBrowser.Controller/Entities/IHasMediaSources.cs

@@ -20,6 +20,8 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Gets the media sources.
         /// </summary>
+        /// <param name="enablePathSubstitution"><c>true</c> to enable path substitution, <c>false</c> to not.</param>
+        /// <returns>A list of media sources.</returns>
         List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
 
         List<MediaStream> GetMediaStreams();

+ 3 - 0
MediaBrowser.Controller/Entities/IHasTrailers.cs

@@ -39,6 +39,7 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Gets the trailer count.
         /// </summary>
+        /// <param name="item">Media item.</param>
         /// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
         public static int GetTrailerCount(this IHasTrailers item)
             => item.LocalTrailerIds.Count + item.RemoteTrailerIds.Count;
@@ -46,6 +47,7 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Gets the trailer ids.
         /// </summary>
+        /// <param name="item">Media item.</param>
         /// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
         public static IReadOnlyList<Guid> GetTrailerIds(this IHasTrailers item)
         {
@@ -70,6 +72,7 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Gets the trailers.
         /// </summary>
+        /// <param name="item">Media item.</param>
         /// <returns><see cref="IReadOnlyList{BaseItem}" />.</returns>
         public static IReadOnlyList<BaseItem> GetTrailers(this IHasTrailers item)
         {

+ 2 - 0
MediaBrowser.Controller/Entities/Person.cs

@@ -129,6 +129,8 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// This is called before any metadata refresh and returns true or false indicating if changes were made.
         /// </summary>
+        /// <param name="replaceAllMetadata"><c>true</c> to replace all metadata, <c>false</c> to not.</param>
+        /// <returns><c>true</c> if changes were made, <c>false</c> if not.</returns>
         public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
         {
             var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);

+ 2 - 0
MediaBrowser.Controller/Entities/Studio.cs

@@ -105,6 +105,8 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// This is called before any metadata refresh and returns true or false indicating if changes were made.
         /// </summary>
+        /// <param name="replaceAllMetadata"><c>true</c> to replace all metadata, <c>false</c> to not.</param>
+        /// <returns><c>true</c> if changes were made, <c>false</c> if not.</returns>
         public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
         {
             var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);

+ 68 - 68
MediaBrowser.Controller/Entities/TV/Episode.cs

@@ -49,12 +49,6 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <value>The index number.</value>
         public int? IndexNumberEnd { get; set; }
 
-        public string FindSeriesSortName()
-        {
-            var series = Series;
-            return series == null ? SeriesName : series.SortName;
-        }
-
         [JsonIgnore]
         protected override bool SupportsOwnedItems => IsStacked || MediaSourceCount > 1;
 
@@ -76,45 +70,6 @@ namespace MediaBrowser.Controller.Entities.TV
         [JsonIgnore]
         protected override bool EnableDefaultVideoUserDataKeys => false;
 
-        public override double GetDefaultPrimaryImageAspectRatio()
-        {
-            // hack for tv plugins
-            if (SourceType == SourceType.Channel)
-            {
-                return 0;
-            }
-
-            return 16.0 / 9;
-        }
-
-        public override List<string> GetUserDataKeys()
-        {
-            var list = base.GetUserDataKeys();
-
-            var series = Series;
-            if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
-            {
-                var seriesUserDataKeys = series.GetUserDataKeys();
-                var take = seriesUserDataKeys.Count;
-                if (seriesUserDataKeys.Count > 1)
-                {
-                    take--;
-                }
-
-                var newList = seriesUserDataKeys.GetRange(0, take);
-                var suffix = ParentIndexNumber.Value.ToString("000", CultureInfo.InvariantCulture) + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
-                for (int i = 0; i < take; i++)
-                {
-                    newList[i] = newList[i] + suffix;
-                }
-
-                newList.AddRange(list);
-                list = newList;
-            }
-
-            return list;
-        }
-
         /// <summary>
         /// Gets the Episode's Series Instance.
         /// </summary>
@@ -161,6 +116,74 @@ namespace MediaBrowser.Controller.Entities.TV
         [JsonIgnore]
         public string SeasonName { get; set; }
 
+        [JsonIgnore]
+        public override bool SupportsRemoteImageDownloading
+        {
+            get
+            {
+                if (IsMissingEpisode)
+                {
+                    return false;
+                }
+
+                return true;
+            }
+        }
+
+        [JsonIgnore]
+        public bool IsMissingEpisode => LocationType == LocationType.Virtual;
+
+        [JsonIgnore]
+        public Guid SeasonId { get; set; }
+
+        [JsonIgnore]
+        public Guid SeriesId { get; set; }
+
+        public string FindSeriesSortName()
+        {
+            var series = Series;
+            return series == null ? SeriesName : series.SortName;
+        }
+
+        public override double GetDefaultPrimaryImageAspectRatio()
+        {
+            // hack for tv plugins
+            if (SourceType == SourceType.Channel)
+            {
+                return 0;
+            }
+
+            return 16.0 / 9;
+        }
+
+        public override List<string> GetUserDataKeys()
+        {
+            var list = base.GetUserDataKeys();
+
+            var series = Series;
+            if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
+            {
+                var seriesUserDataKeys = series.GetUserDataKeys();
+                var take = seriesUserDataKeys.Count;
+                if (seriesUserDataKeys.Count > 1)
+                {
+                    take--;
+                }
+
+                var newList = seriesUserDataKeys.GetRange(0, take);
+                var suffix = ParentIndexNumber.Value.ToString("000", CultureInfo.InvariantCulture) + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
+                for (int i = 0; i < take; i++)
+                {
+                    newList[i] = newList[i] + suffix;
+                }
+
+                newList.AddRange(list);
+                list = newList;
+            }
+
+            return list;
+        }
+
         public string FindSeriesPresentationUniqueKey()
         {
             var series = Series;
@@ -242,29 +265,6 @@ namespace MediaBrowser.Controller.Entities.TV
             return false;
         }
 
-        [JsonIgnore]
-        public override bool SupportsRemoteImageDownloading
-        {
-            get
-            {
-                if (IsMissingEpisode)
-                {
-                    return false;
-                }
-
-                return true;
-            }
-        }
-
-        [JsonIgnore]
-        public bool IsMissingEpisode => LocationType == LocationType.Virtual;
-
-        [JsonIgnore]
-        public Guid SeasonId { get; set; }
-
-        [JsonIgnore]
-        public Guid SeriesId { get; set; }
-
         public Guid FindSeriesId()
         {
             var series = FindParent<Series>();

+ 48 - 44
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -38,6 +38,50 @@ namespace MediaBrowser.Controller.Entities.TV
         [JsonIgnore]
         public override Guid DisplayParentId => SeriesId;
 
+        /// <summary>
+        /// Gets this Episode's Series Instance.
+        /// </summary>
+        /// <value>The series.</value>
+        [JsonIgnore]
+        public Series Series
+        {
+            get
+            {
+                var seriesId = SeriesId;
+                if (seriesId == Guid.Empty)
+                {
+                    seriesId = FindSeriesId();
+                }
+
+                return seriesId == Guid.Empty ? null : (LibraryManager.GetItemById(seriesId) as Series);
+            }
+        }
+
+        [JsonIgnore]
+        public string SeriesPath
+        {
+            get
+            {
+                var series = Series;
+
+                if (series != null)
+                {
+                    return series.Path;
+                }
+
+                return System.IO.Path.GetDirectoryName(Path);
+            }
+        }
+
+        [JsonIgnore]
+        public string SeriesPresentationUniqueKey { get; set; }
+
+        [JsonIgnore]
+        public string SeriesName { get; set; }
+
+        [JsonIgnore]
+        public Guid SeriesId { get; set; }
+
         public override double GetDefaultPrimaryImageAspectRatio()
         {
             double value = 2;
@@ -80,41 +124,6 @@ namespace MediaBrowser.Controller.Entities.TV
             return result;
         }
 
-        /// <summary>
-        /// Gets this Episode's Series Instance.
-        /// </summary>
-        /// <value>The series.</value>
-        [JsonIgnore]
-        public Series Series
-        {
-            get
-            {
-                var seriesId = SeriesId;
-                if (seriesId == Guid.Empty)
-                {
-                    seriesId = FindSeriesId();
-                }
-
-                return seriesId == Guid.Empty ? null : (LibraryManager.GetItemById(seriesId) as Series);
-            }
-        }
-
-        [JsonIgnore]
-        public string SeriesPath
-        {
-            get
-            {
-                var series = Series;
-
-                if (series != null)
-                {
-                    return series.Path;
-                }
-
-                return System.IO.Path.GetDirectoryName(Path);
-            }
-        }
-
         public override string CreatePresentationUniqueKey()
         {
             if (IndexNumber.HasValue)
@@ -157,6 +166,9 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <summary>
         /// Gets the episodes.
         /// </summary>
+        /// <param name="user">The user.</param>
+        /// <param name="options">The options to use.</param>
+        /// <returns>Set of episodes.</returns>
         public List<BaseItem> GetEpisodes(User user, DtoOptions options)
         {
             return GetEpisodes(Series, user, options);
@@ -193,15 +205,6 @@ namespace MediaBrowser.Controller.Entities.TV
             return UnratedItem.Series;
         }
 
-        [JsonIgnore]
-        public string SeriesPresentationUniqueKey { get; set; }
-
-        [JsonIgnore]
-        public string SeriesName { get; set; }
-
-        [JsonIgnore]
-        public Guid SeriesId { get; set; }
-
         public string FindSeriesPresentationUniqueKey()
         {
             var series = Series;
@@ -241,6 +244,7 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <summary>
         /// This is called before any metadata refresh and returns true or false indicating if changes were made.
         /// </summary>
+        /// <param name="replaceAllMetadata"><c>true</c> to replace metdata, <c>false</c> to not.</param>
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
         public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
         {

+ 11 - 3
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -72,6 +72,9 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <value>The status.</value>
         public SeriesStatus? Status { get; set; }
 
+        [JsonIgnore]
+        public override bool StopRefreshIfLocalMetadataFound => false;
+
         public override double GetDefaultPrimaryImageAspectRatio()
         {
             double value = 2;
@@ -394,6 +397,10 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <summary>
         /// Filters the episodes by season.
         /// </summary>
+        /// <param name="episodes">The episodes.</param>
+        /// <param name="parentSeason">The season.</param>
+        /// <param name="includeSpecials"><c>true</c> to include special, <c>false</c> to not.</param>
+        /// <returns>The set of episodes.</returns>
         public static IEnumerable<BaseItem> FilterEpisodesBySeason(IEnumerable<BaseItem> episodes, Season parentSeason, bool includeSpecials)
         {
             var seasonNumber = parentSeason.IndexNumber;
@@ -424,6 +431,10 @@ namespace MediaBrowser.Controller.Entities.TV
         /// <summary>
         /// Filters the episodes by season.
         /// </summary>
+        /// <param name="episodes">The episodes.</param>
+        /// <param name="seasonNumber">The season.</param>
+        /// <param name="includeSpecials"><c>true</c> to include special, <c>false</c> to not.</param>
+        /// <returns>The set of episodes.</returns>
         public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
         {
             if (!includeSpecials || seasonNumber < 1)
@@ -499,8 +510,5 @@ namespace MediaBrowser.Controller.Entities.TV
 
             return list;
         }
-
-        [JsonIgnore]
-        public override bool StopRefreshIfLocalMetadataFound => false;
     }
 }

+ 7 - 7
MediaBrowser.Controller/Entities/UserItemData.cs

@@ -12,6 +12,13 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public class UserItemData
     {
+        public const double MinLikeValue = 6.5;
+
+        /// <summary>
+        /// The _rating.
+        /// </summary>
+        private double? _rating;
+
         /// <summary>
         /// Gets or sets the user id.
         /// </summary>
@@ -24,11 +31,6 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The key.</value>
         public string Key { get; set; }
 
-        /// <summary>
-        /// The _rating.
-        /// </summary>
-        private double? _rating;
-
         /// <summary>
         /// Gets or sets the users 0-10 rating.
         /// </summary>
@@ -93,8 +95,6 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The index of the subtitle stream.</value>
         public int? SubtitleStreamIndex { get; set; }
 
-        public const double MinLikeValue = 6.5;
-
         /// <summary>
         /// Gets or sets a value indicating whether the item is liked or not.
         /// This should never be serialized.

+ 21 - 21
MediaBrowser.Controller/Entities/UserRootFolder.cs

@@ -21,8 +21,28 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public class UserRootFolder : Folder
     {
-        private List<Guid> _childrenIds = null;
         private readonly object _childIdsLock = new object();
+        private List<Guid> _childrenIds = null;
+
+        [JsonIgnore]
+        public override bool SupportsInheritedParentImages => false;
+
+        [JsonIgnore]
+        public override bool SupportsPlayedStatus => false;
+
+        [JsonIgnore]
+        protected override bool SupportsShortcutChildren => true;
+
+        [JsonIgnore]
+        public override bool IsPreSorted => true;
+
+        private void ClearCache()
+        {
+            lock (_childIdsLock)
+            {
+                _childrenIds = null;
+            }
+        }
 
         protected override List<BaseItem> LoadChildren()
         {
@@ -39,20 +59,6 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        [JsonIgnore]
-        public override bool SupportsInheritedParentImages => false;
-
-        [JsonIgnore]
-        public override bool SupportsPlayedStatus => false;
-
-        private void ClearCache()
-        {
-            lock (_childIdsLock)
-            {
-                _childrenIds = null;
-            }
-        }
-
         protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
         {
             if (query.Recursive)
@@ -74,12 +80,6 @@ namespace MediaBrowser.Controller.Entities
             return GetChildren(user, true).Count;
         }
 
-        [JsonIgnore]
-        protected override bool SupportsShortcutChildren => true;
-
-        [JsonIgnore]
-        public override bool IsPreSorted => true;
-
         protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
         {
             var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList();

+ 119 - 119
MediaBrowser.Controller/Entities/Video.cs

@@ -28,6 +28,14 @@ namespace MediaBrowser.Controller.Entities
         ISupportsPlaceHolders,
         IHasMediaSources
     {
+        public Video()
+        {
+            AdditionalParts = Array.Empty<string>();
+            LocalAlternateVersions = Array.Empty<string>();
+            SubtitleFiles = Array.Empty<string>();
+            LinkedAlternateVersions = Array.Empty<LinkedChild>();
+        }
+
         [JsonIgnore]
         public string PrimaryVersionId { get; set; }
 
@@ -74,30 +82,6 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        public void SetPrimaryVersionId(string id)
-        {
-            if (string.IsNullOrEmpty(id))
-            {
-                PrimaryVersionId = null;
-            }
-            else
-            {
-                PrimaryVersionId = id;
-            }
-
-            PresentationUniqueKey = CreatePresentationUniqueKey();
-        }
-
-        public override string CreatePresentationUniqueKey()
-        {
-            if (!string.IsNullOrEmpty(PrimaryVersionId))
-            {
-                return PrimaryVersionId;
-            }
-
-            return base.CreatePresentationUniqueKey();
-        }
-
         [JsonIgnore]
         public override bool SupportsThemeMedia => true;
 
@@ -151,24 +135,6 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The aspect ratio.</value>
         public string AspectRatio { get; set; }
 
-        public Video()
-        {
-            AdditionalParts = Array.Empty<string>();
-            LocalAlternateVersions = Array.Empty<string>();
-            SubtitleFiles = Array.Empty<string>();
-            LinkedAlternateVersions = Array.Empty<LinkedChild>();
-        }
-
-        public override bool CanDownload()
-        {
-            if (VideoType == VideoType.Dvd || VideoType == VideoType.BluRay)
-            {
-                return false;
-            }
-
-            return IsFileProtocol;
-        }
-
         [JsonIgnore]
         public override bool SupportsAddingToPlaylist => true;
 
@@ -196,16 +162,6 @@ namespace MediaBrowser.Controller.Entities
         [JsonIgnore]
         public override bool HasLocalAlternateVersions => LocalAlternateVersions.Length > 0;
 
-        public IEnumerable<Guid> GetAdditionalPartIds()
-        {
-            return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
-        }
-
-        public IEnumerable<Guid> GetLocalAlternateVersionIds()
-        {
-            return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
-        }
-
         public static ILiveTvManager LiveTvManager { get; set; }
 
         [JsonIgnore]
@@ -222,37 +178,77 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        protected override bool IsActiveRecording()
+        [JsonIgnore]
+        public bool IsCompleteMedia
         {
-            return LiveTvManager.GetActiveRecordingInfo(Path) != null;
+            get
+            {
+                if (SourceType == SourceType.Channel)
+                {
+                    return !Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase);
+                }
+
+                return !IsActiveRecording();
+            }
         }
 
-        public override bool CanDelete()
+        [JsonIgnore]
+        protected virtual bool EnableDefaultVideoUserDataKeys => true;
+
+        [JsonIgnore]
+        public override string ContainingFolderPath
         {
-            if (IsActiveRecording())
+            get
             {
-                return false;
-            }
+                if (IsStacked)
+                {
+                    return System.IO.Path.GetDirectoryName(Path);
+                }
 
-            return base.CanDelete();
+                if (!IsPlaceHolder)
+                {
+                    if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd)
+                    {
+                        return Path;
+                    }
+                }
+
+                return base.ContainingFolderPath;
+            }
         }
 
         [JsonIgnore]
-        public bool IsCompleteMedia
+        public override string FileNameWithoutExtension
         {
             get
             {
-                if (SourceType == SourceType.Channel)
+                if (IsFileProtocol)
                 {
-                    return !Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase);
+                    if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd)
+                    {
+                        return System.IO.Path.GetFileName(Path);
+                    }
+
+                    return System.IO.Path.GetFileNameWithoutExtension(Path);
                 }
 
-                return !IsActiveRecording();
+                return null;
             }
         }
 
+        /// <summary>
+        /// Gets a value indicating whether [is3 D].
+        /// </summary>
+        /// <value><c>true</c> if [is3 D]; otherwise, <c>false</c>.</value>
         [JsonIgnore]
-        protected virtual bool EnableDefaultVideoUserDataKeys => true;
+        public bool Is3D => Video3DFormat.HasValue;
+
+        /// <summary>
+        /// Gets the type of the media.
+        /// </summary>
+        /// <value>The type of the media.</value>
+        [JsonIgnore]
+        public override string MediaType => Model.Entities.MediaType.Video;
 
         public override List<string> GetUserDataKeys()
         {
@@ -293,6 +289,65 @@ namespace MediaBrowser.Controller.Entities
             return list;
         }
 
+        public void SetPrimaryVersionId(string id)
+        {
+            if (string.IsNullOrEmpty(id))
+            {
+                PrimaryVersionId = null;
+            }
+            else
+            {
+                PrimaryVersionId = id;
+            }
+
+            PresentationUniqueKey = CreatePresentationUniqueKey();
+        }
+
+        public override string CreatePresentationUniqueKey()
+        {
+            if (!string.IsNullOrEmpty(PrimaryVersionId))
+            {
+                return PrimaryVersionId;
+            }
+
+            return base.CreatePresentationUniqueKey();
+        }
+
+        public override bool CanDownload()
+        {
+            if (VideoType == VideoType.Dvd || VideoType == VideoType.BluRay)
+            {
+                return false;
+            }
+
+            return IsFileProtocol;
+        }
+
+        protected override bool IsActiveRecording()
+        {
+            return LiveTvManager.GetActiveRecordingInfo(Path) != null;
+        }
+
+        public override bool CanDelete()
+        {
+            if (IsActiveRecording())
+            {
+                return false;
+            }
+
+            return base.CanDelete();
+        }
+
+        public IEnumerable<Guid> GetAdditionalPartIds()
+        {
+            return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
+        }
+
+        public IEnumerable<Guid> GetLocalAlternateVersionIds()
+        {
+            return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
+        }
+
         private string GetUserDataKey(string providerId)
         {
             var key = providerId + "-" + ExtraType.ToString().ToLowerInvariant();
@@ -328,47 +383,6 @@ namespace MediaBrowser.Controller.Entities
                 .OrderBy(i => i.SortName);
         }
 
-        [JsonIgnore]
-        public override string ContainingFolderPath
-        {
-            get
-            {
-                if (IsStacked)
-                {
-                    return System.IO.Path.GetDirectoryName(Path);
-                }
-
-                if (!IsPlaceHolder)
-                {
-                    if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd)
-                    {
-                        return Path;
-                    }
-                }
-
-                return base.ContainingFolderPath;
-            }
-        }
-
-        [JsonIgnore]
-        public override string FileNameWithoutExtension
-        {
-            get
-            {
-                if (IsFileProtocol)
-                {
-                    if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd)
-                    {
-                        return System.IO.Path.GetFileName(Path);
-                    }
-
-                    return System.IO.Path.GetFileNameWithoutExtension(Path);
-                }
-
-                return null;
-            }
-        }
-
         internal override ItemUpdateType UpdateFromResolvedItem(BaseItem newItem)
         {
             var updateType = base.UpdateFromResolvedItem(newItem);
@@ -397,20 +411,6 @@ namespace MediaBrowser.Controller.Entities
             return updateType;
         }
 
-        /// <summary>
-        /// Gets a value indicating whether [is3 D].
-        /// </summary>
-        /// <value><c>true</c> if [is3 D]; otherwise, <c>false</c>.</value>
-        [JsonIgnore]
-        public bool Is3D => Video3DFormat.HasValue;
-
-        /// <summary>
-        /// Gets the type of the media.
-        /// </summary>
-        /// <value>The type of the media.</value>
-        [JsonIgnore]
-        public override string MediaType => Model.Entities.MediaType.Video;
-
         protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
         {
             var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);

+ 16 - 16
MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs

@@ -1,6 +1,6 @@
 #nullable disable
 
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1306, SA1401
 
 using System;
 using System.Collections.Generic;
@@ -30,6 +30,21 @@ namespace MediaBrowser.Controller.Net
         private readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, TStateType>> _activeConnections =
             new List<Tuple<IWebSocketConnection, CancellationTokenSource, TStateType>>();
 
+        /// <summary>
+        /// The logger.
+        /// </summary>
+        protected ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> Logger;
+
+        protected BasePeriodicWebSocketListener(ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> logger)
+        {
+            if (logger == null)
+            {
+                throw new ArgumentNullException(nameof(logger));
+            }
+
+            Logger = logger;
+        }
+
         /// <summary>
         /// Gets the type used for the messages sent to the client.
         /// </summary>
@@ -54,21 +69,6 @@ namespace MediaBrowser.Controller.Net
         /// <returns>Task{`1}.</returns>
         protected abstract Task<TReturnDataType> GetDataToSend();
 
-        /// <summary>
-        /// The logger.
-        /// </summary>
-        protected ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> Logger;
-
-        protected BasePeriodicWebSocketListener(ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> logger)
-        {
-            if (logger == null)
-            {
-                throw new ArgumentNullException(nameof(logger));
-            }
-
-            Logger = logger;
-        }
-
         /// <summary>
         /// Processes the message.
         /// </summary>

+ 0 - 1
MediaBrowser.Controller/Persistence/IUserDataRepository.cs

@@ -18,7 +18,6 @@ namespace MediaBrowser.Controller.Persistence
         /// <param name="key">The key.</param>
         /// <param name="userData">The user data.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task.</returns>
         void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken);
 
         /// <summary>

+ 39 - 39
MediaBrowser.Controller/Playlists/Playlist.cs

@@ -31,24 +31,18 @@ namespace MediaBrowser.Controller.Playlists
             ".zpl"
         };
 
-        public Guid OwnerUserId { get; set; }
-
-        public Share[] Shares { get; set; }
-
         public Playlist()
         {
             Shares = Array.Empty<Share>();
         }
 
+        public Guid OwnerUserId { get; set; }
+
+        public Share[] Shares { get; set; }
+
         [JsonIgnore]
         public bool IsFile => IsPlaylistFile(Path);
 
-        public static bool IsPlaylistFile(string path)
-        {
-            // The path will sometimes be a directory and "Path.HasExtension" returns true if the name contains a '.' (dot).
-            return System.IO.Path.HasExtension(path) && !Directory.Exists(path);
-        }
-
         [JsonIgnore]
         public override string ContainingFolderPath
         {
@@ -80,6 +74,41 @@ namespace MediaBrowser.Controller.Playlists
         [JsonIgnore]
         public override bool SupportsCumulativeRunTimeTicks => true;
 
+        [JsonIgnore]
+        public override bool IsPreSorted => true;
+
+        public string PlaylistMediaType { get; set; }
+
+        [JsonIgnore]
+        public override string MediaType => PlaylistMediaType;
+
+        [JsonIgnore]
+        private bool IsSharedItem
+        {
+            get
+            {
+                var path = Path;
+
+                if (string.IsNullOrEmpty(path))
+                {
+                    return false;
+                }
+
+                return FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, path);
+            }
+        }
+
+        public static bool IsPlaylistFile(string path)
+        {
+            // The path will sometimes be a directory and "Path.HasExtension" returns true if the name contains a '.' (dot).
+            return System.IO.Path.HasExtension(path) && !Directory.Exists(path);
+        }
+
+        public void SetMediaType(string value)
+        {
+            PlaylistMediaType = value;
+        }
+
         public override double GetDefaultPrimaryImageAspectRatio()
         {
             return 1;
@@ -197,35 +226,6 @@ namespace MediaBrowser.Controller.Playlists
             return new[] { item };
         }
 
-        [JsonIgnore]
-        public override bool IsPreSorted => true;
-
-        public string PlaylistMediaType { get; set; }
-
-        [JsonIgnore]
-        public override string MediaType => PlaylistMediaType;
-
-        public void SetMediaType(string value)
-        {
-            PlaylistMediaType = value;
-        }
-
-        [JsonIgnore]
-        private bool IsSharedItem
-        {
-            get
-            {
-                var path = Path;
-
-                if (string.IsNullOrEmpty(path))
-                {
-                    return false;
-                }
-
-                return FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, path);
-            }
-        }
-
         public override bool IsVisible(User user)
         {
             if (!IsSharedItem)

+ 10 - 10
MediaBrowser.Controller/Resolvers/IItemResolver.cs

@@ -13,18 +13,18 @@ namespace MediaBrowser.Controller.Resolvers
     /// </summary>
     public interface IItemResolver
     {
+        /// <summary>
+        /// Gets the priority.
+        /// </summary>
+        /// <value>The priority.</value>
+        ResolverPriority Priority { get; }
+
         /// <summary>
         /// Resolves the path.
         /// </summary>
         /// <param name="args">The args.</param>
         /// <returns>BaseItem.</returns>
         BaseItem ResolvePath(ItemResolveArgs args);
-
-        /// <summary>
-        /// Gets the priority.
-        /// </summary>
-        /// <value>The priority.</value>
-        ResolverPriority Priority { get; }
     }
 
     public interface IMultiItemResolver
@@ -38,14 +38,14 @@ namespace MediaBrowser.Controller.Resolvers
 
     public class MultiItemResolverResult
     {
-        public List<BaseItem> Items { get; set; }
-
-        public List<FileSystemMetadata> ExtraFiles { get; set; }
-
         public MultiItemResolverResult()
         {
             Items = new List<BaseItem>();
             ExtraFiles = new List<FileSystemMetadata>();
         }
+
+        public List<BaseItem> Items { get; set; }
+
+        public List<FileSystemMetadata> ExtraFiles { get; set; }
     }
 }

+ 19 - 0
MediaBrowser.Controller/Subtitles/ISubtitleManager.cs

@@ -28,6 +28,11 @@ namespace MediaBrowser.Controller.Subtitles
         /// <summary>
         /// Searches the subtitles.
         /// </summary>
+        /// <param name="video">The video.</param>
+        /// <param name="language">Subtitle language.</param>
+        /// <param name="isPerfectMatch">Require perfect match.</param>
+        /// <param name="cancellationToken">CancellationToken to use for the operation.</param>
+        /// <returns>Subtitles, wrapped in task.</returns>
         Task<RemoteSubtitleInfo[]> SearchSubtitles(
             Video video,
             string language,
@@ -47,11 +52,20 @@ namespace MediaBrowser.Controller.Subtitles
         /// <summary>
         /// Downloads the subtitles.
         /// </summary>
+        /// <param name="video">The video.</param>
+        /// <param name="subtitleId">Subtitle ID.</param>
+        /// <param name="cancellationToken">CancellationToken to use for the operation.</param>
+        /// <returns>A task.</returns>
         Task DownloadSubtitles(Video video, string subtitleId, CancellationToken cancellationToken);
 
         /// <summary>
         /// Downloads the subtitles.
         /// </summary>
+        /// <param name="video">The video.</param>
+        /// <param name="libraryOptions">Library options to use.</param>
+        /// <param name="subtitleId">Subtitle ID.</param>
+        /// <param name="cancellationToken">CancellationToken to use for the operation.</param>
+        /// <returns>A task.</returns>
         Task DownloadSubtitles(Video video, LibraryOptions libraryOptions, string subtitleId, CancellationToken cancellationToken);
 
         /// <summary>
@@ -73,11 +87,16 @@ namespace MediaBrowser.Controller.Subtitles
         /// <summary>
         /// Deletes the subtitles.
         /// </summary>
+        /// <param name="item">Media item.</param>
+        /// <param name="index">Subtitle index.</param>
+        /// <returns>A task.</returns>
         Task DeleteSubtitles(BaseItem item, int index);
 
         /// <summary>
         /// Gets the providers.
         /// </summary>
+        /// <param name="item">The media item.</param>
+        /// <returns>Subtitles providers.</returns>
         SubtitleProviderInfo[] GetSupportedProviders(BaseItem item);
     }
 }

+ 9 - 9
MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs

@@ -11,6 +11,15 @@ namespace MediaBrowser.Controller.Subtitles
 {
     public class SubtitleSearchRequest : IHasProviderIds
     {
+        public SubtitleSearchRequest()
+        {
+            SearchAllProviders = true;
+            ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
+            DisabledSubtitleFetchers = Array.Empty<string>();
+            SubtitleFetcherOrder = Array.Empty<string>();
+        }
+
         public string Language { get; set; }
 
         public string TwoLetterISOLanguageName { get; set; }
@@ -42,14 +51,5 @@ namespace MediaBrowser.Controller.Subtitles
         public string[] DisabledSubtitleFetchers { get; set; }
 
         public string[] SubtitleFetcherOrder { get; set; }
-
-        public SubtitleSearchRequest()
-        {
-            SearchAllProviders = true;
-            ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
-            DisabledSubtitleFetchers = Array.Empty<string>();
-            SubtitleFetcherOrder = Array.Empty<string>();
-        }
     }
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно