Bläddra i källkod

updated nuget

Luke Pulverenti 10 år sedan
förälder
incheckning
56f6b0335c
52 ändrade filer med 476 tillägg och 724 borttagningar
  1. 0 13
      MediaBrowser.Api/ItemLookupService.cs
  2. 1 1
      MediaBrowser.Api/Movies/TrailersService.cs
  3. 3 2
      MediaBrowser.Api/PackageService.cs
  4. 16 2
      MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
  5. 52 1
      MediaBrowser.Controller/Entities/BaseItem.cs
  6. 1 41
      MediaBrowser.Controller/Entities/Folder.cs
  7. 1 0
      MediaBrowser.Controller/Entities/Trailer.cs
  8. 1 2
      MediaBrowser.Controller/Entities/UserView.cs
  9. 71 183
      MediaBrowser.Controller/Entities/Video.cs
  10. 1 12
      MediaBrowser.Controller/Library/ILibraryManager.cs
  11. 0 1
      MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
  12. 0 37
      MediaBrowser.LocalMetadata/Providers/TrailerXmlProvider.cs
  13. 2 1
      MediaBrowser.Model/ApiClient/ConnectionMode.cs
  14. 1 1
      MediaBrowser.Model/ApiClient/IApiClient.cs
  15. 7 3
      MediaBrowser.Model/ApiClient/ServerCredentials.cs
  16. 5 0
      MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs
  17. 18 3
      MediaBrowser.Model/ApiClient/ServerInfo.cs
  18. 0 5
      MediaBrowser.Model/Dto/BaseItemDto.cs
  19. 0 5
      MediaBrowser.Model/Querying/ItemFields.cs
  20. 12 11
      MediaBrowser.Model/Querying/ItemQuery.cs
  21. 3 2
      MediaBrowser.Model/Querying/ItemsByNameQuery.cs
  22. 8 1
      MediaBrowser.Model/Querying/LatestItemsQuery.cs
  23. 7 2
      MediaBrowser.Model/Querying/NextUpQuery.cs
  24. 9 2
      MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs
  25. 0 1
      MediaBrowser.Providers/Manager/ProviderManager.cs
  26. 0 1
      MediaBrowser.Providers/MediaBrowser.Providers.csproj
  27. 0 6
      MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
  28. 0 7
      MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
  29. 0 7
      MediaBrowser.Providers/Movies/MovieDbImageProvider.cs
  30. 1 6
      MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
  31. 3 3
      MediaBrowser.Providers/Movies/MovieExternalIds.cs
  32. 1 1
      MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
  33. 0 34
      MediaBrowser.Providers/Movies/TrailerMetadataService.cs
  34. 1 1
      MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
  35. 1 13
      MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
  36. 2 3
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  37. 1 10
      MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
  38. 65 85
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  39. 126 34
      MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
  40. 0 61
      MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs
  41. 35 66
      MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
  42. 5 29
      MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
  43. 6 0
      MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs
  44. 1 2
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  45. 1 1
      MediaBrowser.Server.Implementations/Sync/SyncManager.cs
  46. 1 1
      MediaBrowser.Server.Implementations/packages.config
  47. 1 6
      MediaBrowser.Server.Startup.Common/ApplicationHost.cs
  48. 0 9
      MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs
  49. 2 2
      Nuget/MediaBrowser.Common.Internal.nuspec
  50. 1 1
      Nuget/MediaBrowser.Common.nuspec
  51. 1 1
      Nuget/MediaBrowser.Model.Signed.nuspec
  52. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec

+ 0 - 13
MediaBrowser.Api/ItemLookupService.cs

@@ -37,12 +37,6 @@ namespace MediaBrowser.Api
     {
     }
 
-    [Route("/Items/RemoteSearch/Trailer", "POST")]
-    [Authenticated]
-    public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
-    {
-    }
-
     [Route("/Items/RemoteSearch/AdultVideo", "POST")]
     [Authenticated]
     public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
@@ -162,13 +156,6 @@ namespace MediaBrowser.Api
             return ToOptimizedResult(result);
         }
 
-        public object Post(GetTrailerRemoteSearchResults request)
-        {
-            var result = _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).Result;
-
-            return ToOptimizedResult(result);
-        }
-
         public object Post(GetMusicAlbumRemoteSearchResults request)
         {
             var result = _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).Result;

+ 1 - 1
MediaBrowser.Api/Movies/TrailersService.cs

@@ -92,7 +92,7 @@ namespace MediaBrowser.Api.Movies
                 Logger,
 
                 // Strip out secondary versions
-                request, item => (item is Movie || item is Trailer) && !((Video)item).PrimaryVersionId.HasValue,
+                request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
 
                 SimilarItemsHelper.GetSimiliarityScore);
 

+ 3 - 2
MediaBrowser.Api/PackageService.cs

@@ -173,9 +173,10 @@ namespace MediaBrowser.Api
         public object Get(GetPackage request)
         {
             var packages = _installationManager.GetAvailablePackages(CancellationToken.None, applicationVersion: _appHost.ApplicationVersion).Result;
+            var list = packages.ToList();
 
-            var result = packages.FirstOrDefault(p => string.Equals(p.guid, request.AssemblyGuid ?? "none", StringComparison.OrdinalIgnoreCase))
-                         ?? packages.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
+            var result = list.FirstOrDefault(p => string.Equals(p.guid, request.AssemblyGuid ?? "none", StringComparison.OrdinalIgnoreCase))
+                         ?? list.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
 
             return ToOptimizedResult(result);
         }

+ 16 - 2
MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs

@@ -24,14 +24,28 @@ namespace MediaBrowser.Common.Implementations.Networking
         /// <returns>IPAddress.</returns>
         public IEnumerable<string> GetLocalIpAddresses()
         {
-            var list = GetIPsDefault().Where(i => !IPAddress.IsLoopback(i)).Select(i => i.ToString()).ToList();
+            var list = GetIPsDefault()
+                .Where(i => !IPAddress.IsLoopback(i))
+                .Select(i => i.ToString())
+                .Where(FilterIpAddress)
+                .ToList();
 
             if (list.Count > 0)
             {
                 return list;
             }
 
-            return GetLocalIpAddressesFallback();
+            return GetLocalIpAddressesFallback().Where(FilterIpAddress);
+        }
+
+        private bool FilterIpAddress(string address)
+        {
+            if (address.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
+            {
+                return false;
+            }
+
+            return true;
         }
 
         private bool IsInPrivateAddressSpace(string endpoint)

+ 52 - 1
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -893,6 +893,28 @@ namespace MediaBrowser.Controller.Entities
             return Id.ToString();
         }
 
+        internal virtual bool IsValidFromResolver(BaseItem newItem)
+        {
+            var current = this;
+
+            var currentAsPlaceHolder = current as ISupportsPlaceHolders;
+
+            if (currentAsPlaceHolder != null)
+            {
+                var newHasPlaceHolder = newItem as ISupportsPlaceHolders;
+
+                if (newHasPlaceHolder != null)
+                {
+                    if (currentAsPlaceHolder.IsPlaceHolder != newHasPlaceHolder.IsPlaceHolder)
+                    {
+                        return false;
+                    }
+                }
+            }
+
+            return current.IsInMixedFolder == newItem.IsInMixedFolder;
+        }
+
         /// <summary>
         /// Gets the preferred metadata language.
         /// </summary>
@@ -1288,7 +1310,7 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="resetPosition">if set to <c>true</c> [reset position].</param>
         /// <returns>Task.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public virtual async Task MarkPlayed(User user, 
+        public virtual async Task MarkPlayed(User user,
             DateTime? datePlayed,
             bool resetPosition)
         {
@@ -1726,5 +1748,34 @@ namespace MediaBrowser.Controller.Entities
                 }
             }
         }
+
+        protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken)
+        {
+            var newOptions = new MetadataRefreshOptions(options.DirectoryService)
+            {
+                ImageRefreshMode = options.ImageRefreshMode,
+                MetadataRefreshMode = options.MetadataRefreshMode,
+                ReplaceAllMetadata = options.ReplaceAllMetadata
+            };
+
+            var id = LibraryManager.GetNewItemId(path, typeof(Video));
+
+            // Try to retrieve it from the db. If we don't find it, use the resolved version
+            var video = LibraryManager.GetItemById(id) as Video;
+
+            if (video == null)
+            {
+                video = LibraryManager.ResolvePath(new FileInfo(path)) as Video;
+
+                newOptions.ForceSave = true;
+            }
+
+            if (video == null)
+            {
+                return Task.FromResult(true);
+            }
+
+            return video.RefreshMetadata(newOptions, cancellationToken);
+        }
     }
 }

+ 1 - 41
MediaBrowser.Controller/Entities/Folder.cs

@@ -363,47 +363,7 @@ namespace MediaBrowser.Controller.Entities
 
         private bool IsValidFromResolver(BaseItem current, BaseItem newItem)
         {
-            var currentAsVideo = current as Video;
-
-            if (currentAsVideo != null)
-            {
-                var newAsVideo = newItem as Video;
-
-                if (newAsVideo != null)
-                {
-                    if (currentAsVideo.IsPlaceHolder != newAsVideo.IsPlaceHolder)
-                    {
-                        return false;
-                    }
-                    if (currentAsVideo.IsMultiPart != newAsVideo.IsMultiPart)
-                    {
-                        return false;
-                    }
-                    if (currentAsVideo.HasLocalAlternateVersions != newAsVideo.HasLocalAlternateVersions)
-                    {
-                        return false;
-                    }
-                }
-            }
-            else
-            {
-                var currentAsPlaceHolder = current as ISupportsPlaceHolders;
-
-                if (currentAsPlaceHolder != null)
-                {
-                    var newHasPlaceHolder = newItem as ISupportsPlaceHolders;
-
-                    if (newHasPlaceHolder != null)
-                    {
-                        if (currentAsPlaceHolder.IsPlaceHolder != newHasPlaceHolder.IsPlaceHolder)
-                        {
-                            return false;
-                        }
-                    }
-                }
-            }
-
-            return current.IsInMixedFolder == newItem.IsInMixedFolder;
+            return current.IsValidFromResolver(newItem);
         }
 
         /// <summary>

+ 1 - 0
MediaBrowser.Controller/Entities/Trailer.cs

@@ -12,6 +12,7 @@ namespace MediaBrowser.Controller.Entities
     /// <summary>
     /// Class Trailer
     /// </summary>
+    [Obsolete]
     public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
     {
         public List<Guid> SoundtrackIds { get; set; }

+ 1 - 2
MediaBrowser.Controller/Entities/UserView.cs

@@ -63,8 +63,7 @@ namespace MediaBrowser.Controller.Entities
             {
                 CollectionType.Books,
                 CollectionType.HomeVideos,
-                CollectionType.Photos,
-                CollectionType.Trailers
+                CollectionType.Photos
             };
 
             var collectionFolder = folder as ICollectionFolder;

+ 71 - 183
MediaBrowser.Controller/Entities/Video.cs

@@ -1,7 +1,6 @@
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Providers;
-using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.MediaInfo;
@@ -19,24 +18,23 @@ namespace MediaBrowser.Controller.Entities
     /// <summary>
     /// Class Video
     /// </summary>
-    public class Video : BaseItem, 
-        IHasAspectRatio, 
-        IHasTags, 
+    public class Video : BaseItem,
+        IHasAspectRatio,
+        IHasTags,
         ISupportsPlaceHolders,
         IHasMediaSources,
         IHasShortOverview,
         IHasPreferredMetadataLanguage,
         IThemeMedia
     {
-        public bool IsMultiPart { get; set; }
-        public bool HasLocalAlternateVersions { get; set; }
         public Guid? PrimaryVersionId { get; set; }
 
-        public List<Guid> AdditionalPartIds { get; set; }
-        public List<Guid> LocalAlternateVersionIds { get; set; }
+        public List<string> AdditionalParts { get; set; }
+        public List<string> LocalAlternateVersions { get; set; }
+        public List<LinkedChild> LinkedAlternateVersions { get; set; }
 
         public bool IsThemeMedia { get; set; }
-        
+
         public string FormatName { get; set; }
         public long? Size { get; set; }
         public string Container { get; set; }
@@ -56,12 +54,12 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         /// <value>The timestamp.</value>
         public TransportStreamTimestamp? Timestamp { get; set; }
-        
+
         public Video()
         {
             PlayableStreamFileNames = new List<string>();
-            AdditionalPartIds = new List<Guid>();
-            LocalAlternateVersionIds = new List<Guid>();
+            AdditionalParts = new List<string>();
+            LocalAlternateVersions = new List<string>();
             Tags = new List<string>();
             SubtitleFiles = new List<string>();
             LinkedAlternateVersions = new List<LinkedChild>();
@@ -78,11 +76,31 @@ namespace MediaBrowser.Controller.Entities
         {
             get
             {
-                return LinkedAlternateVersions.Count + LocalAlternateVersionIds.Count + 1;
+                return LinkedAlternateVersions.Count + LocalAlternateVersions.Count + 1;
             }
         }
 
-        public List<LinkedChild> LinkedAlternateVersions { get; set; }
+        [IgnoreDataMember]
+        public bool IsStacked
+        {
+            get { return AdditionalParts.Count > 0; }
+        }
+
+        [IgnoreDataMember]
+        public bool HasLocalAlternateVersions
+        {
+            get { return LocalAlternateVersions.Count > 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)));
+        }
 
         /// <summary>
         /// Gets the linked children.
@@ -90,7 +108,7 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         public IEnumerable<Video> GetAlternateVersions()
         {
-            var filesWithinSameDirectory = LocalAlternateVersionIds
+            var filesWithinSameDirectory = GetLocalAlternateVersionIds()
                 .Select(i => LibraryManager.GetItemById(i))
                 .Where(i => i != null)
                 .OfType<Video>();
@@ -116,7 +134,7 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{Video}.</returns>
         public IEnumerable<Video> GetAdditionalParts()
         {
-            return AdditionalPartIds
+            return GetAdditionalPartIds()
                 .Select(i => LibraryManager.GetItemById(i))
                 .Where(i => i != null)
                 .OfType<Video>()
@@ -200,7 +218,7 @@ namespace MediaBrowser.Controller.Entities
         {
             get
             {
-                if (IsMultiPart)
+                if (IsStacked)
                 {
                     return System.IO.Path.GetDirectoryName(Path);
                 }
@@ -218,6 +236,27 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
+        internal override bool IsValidFromResolver(BaseItem newItem)
+        {
+            var current = this;
+
+            var newAsVideo = newItem as Video;
+
+            if (newAsVideo != null)
+            {
+                if (!current.AdditionalParts.SequenceEqual(newAsVideo.AdditionalParts, StringComparer.OrdinalIgnoreCase))
+                {
+                    return false;
+                }
+                if (!current.LocalAlternateVersions.SequenceEqual(newAsVideo.LocalAlternateVersions, StringComparer.OrdinalIgnoreCase))
+                {
+                    return false;
+                }
+            }
+
+            return base.IsValidFromResolver(newItem);
+        }
+
         public string MainFeaturePlaylistName { get; set; }
 
         /// <summary>
@@ -263,37 +302,34 @@ namespace MediaBrowser.Controller.Entities
         {
             var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
 
+            if (IsStacked)
+            {
+                var tasks = AdditionalParts
+                    .Select(i => RefreshMetadataForOwnedVideo(options, i, cancellationToken));
+
+                await Task.WhenAll(tasks).ConfigureAwait(false);
+            }
+
             // Must have a parent to have additional parts or alternate versions
             // In other words, it must be part of the Parent/Child tree
             // The additional parts won't have additional parts themselves
             if (LocationType == LocationType.FileSystem && Parent != null)
             {
-                if (IsMultiPart)
-                {
-                    var additionalPartsChanged = await RefreshAdditionalParts(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
-
-                    if (additionalPartsChanged)
-                    {
-                        hasChanges = true;
-                    }
-                }
-                else
+                if (!IsStacked)
                 {
                     RefreshLinkedAlternateVersions();
 
-                    var additionalPartsChanged = await RefreshAlternateVersionsWithinSameDirectory(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
+                    var tasks = LocalAlternateVersions
+                        .Select(i => RefreshMetadataForOwnedVideo(options, i, cancellationToken));
 
-                    if (additionalPartsChanged)
-                    {
-                        hasChanges = true;
-                    }
+                    await Task.WhenAll(tasks).ConfigureAwait(false);
                 }
             }
 
             return hasChanges;
         }
 
-        private bool RefreshLinkedAlternateVersions()
+        private void RefreshLinkedAlternateVersions()
         {
             foreach (var child in LinkedAlternateVersions)
             {
@@ -303,111 +339,13 @@ namespace MediaBrowser.Controller.Entities
                     child.ItemId = null;
                 }
             }
-
-            return false;
-        }
-
-        /// <summary>
-        /// Refreshes the additional parts.
-        /// </summary>
-        /// <param name="options">The options.</param>
-        /// <param name="fileSystemChildren">The file system children.</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task{System.Boolean}.</returns>
-        private async Task<bool> RefreshAdditionalParts(MetadataRefreshOptions options, IEnumerable<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
-        {
-            var newItems = LoadAdditionalParts(fileSystemChildren, options.DirectoryService).ToList();
-
-            var newItemIds = newItems.Select(i => i.Id).ToList();
-
-            var itemsChanged = !AdditionalPartIds.SequenceEqual(newItemIds);
-
-            var tasks = newItems.Select(i => i.RefreshMetadata(options, cancellationToken));
-
-            await Task.WhenAll(tasks).ConfigureAwait(false);
-
-            AdditionalPartIds = newItemIds;
-
-            return itemsChanged;
-        }
-
-        /// <summary>
-        /// Loads the additional parts.
-        /// </summary>
-        /// <returns>IEnumerable{Video}.</returns>
-        private IEnumerable<Video> LoadAdditionalParts(IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
-        {
-            var files = LibraryManager.GetAdditionalParts(Path, VideoType, fileSystemChildren);
-
-            return LibraryManager.ResolvePaths<Video>(files, directoryService, null).Select(video =>
-            {
-                // Try to retrieve it from the db. If we don't find it, use the resolved version
-                var dbItem = LibraryManager.GetItemById(video.Id) as Video;
-
-                if (dbItem != null)
-                {
-                    video = dbItem;
-                }
-
-                return video;
-
-                // Sort them so that the list can be easily compared for changes
-            }).OrderBy(i => i.Path).ToList();
-        }
-
-        private async Task<bool> RefreshAlternateVersionsWithinSameDirectory(MetadataRefreshOptions options, IEnumerable<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
-        {
-            var newItems = HasLocalAlternateVersions ?
-                LoadAlternateVersionsWithinSameDirectory(fileSystemChildren, options.DirectoryService).ToList() :
-                new List<Video>();
-
-            var newItemIds = newItems.Select(i => i.Id).ToList();
-
-            var itemsChanged = !LocalAlternateVersionIds.SequenceEqual(newItemIds);
-
-            var tasks = newItems.Select(i => RefreshAlternateVersion(options, i, cancellationToken));
-
-            await Task.WhenAll(tasks).ConfigureAwait(false);
-
-            LocalAlternateVersionIds = newItemIds;
-
-            return itemsChanged;
-        }
-
-        private Task RefreshAlternateVersion(MetadataRefreshOptions options, Video video, CancellationToken cancellationToken)
-        {
-            var currentImagePath = video.GetImagePath(ImageType.Primary);
-            var ownerImagePath = this.GetImagePath(ImageType.Primary);
-
-            var newOptions = new MetadataRefreshOptions(options.DirectoryService)
-            {
-                ImageRefreshMode = options.ImageRefreshMode,
-                MetadataRefreshMode = options.MetadataRefreshMode,
-                ReplaceAllMetadata = options.ReplaceAllMetadata
-            };
-
-            if (!string.Equals(currentImagePath, ownerImagePath, StringComparison.OrdinalIgnoreCase))
-            {
-                newOptions.ForceSave = true;
-
-                if (string.IsNullOrWhiteSpace(ownerImagePath))
-                {
-                    video.ImageInfos.Clear();
-                }
-                else
-                {
-                    video.SetImagePath(ImageType.Primary, ownerImagePath);
-                }
-            }
-
-            return video.RefreshMetadata(newOptions, cancellationToken);
         }
 
         public override async Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
         {
             await base.UpdateToRepository(updateReason, cancellationToken).ConfigureAwait(false);
 
-            foreach (var item in LocalAlternateVersionIds.Select(i => LibraryManager.GetItemById(i)))
+            foreach (var item in GetLocalAlternateVersionIds().Select(i => LibraryManager.GetItemById(i)))
             {
                 item.ImageInfos = ImageInfos;
                 item.Overview = Overview;
@@ -422,56 +360,6 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        /// <summary>
-        /// Loads the additional parts.
-        /// </summary>
-        /// <returns>IEnumerable{Video}.</returns>
-        private IEnumerable<Video> LoadAlternateVersionsWithinSameDirectory(IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
-        {
-            IEnumerable<FileSystemInfo> files;
-
-            // Only support this for video files. For folder rips, they'll have to use the linking feature
-            if (VideoType == VideoType.VideoFile || VideoType == VideoType.Iso)
-            {
-                var path = Path;
-
-                var filenamePrefix = System.IO.Path.GetFileName(System.IO.Path.GetDirectoryName(path));
-
-                files = fileSystemChildren.Where(i =>
-                {
-                    if ((i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
-                    {
-                        return false;
-                    }
-
-                    return !string.Equals(i.FullName, path, StringComparison.OrdinalIgnoreCase) &&
-                           LibraryManager.IsVideoFile(i.FullName) &&
-                           i.Name.StartsWith(filenamePrefix + " - ", StringComparison.OrdinalIgnoreCase);
-                });
-            }
-            else
-            {
-                files = new List<FileSystemInfo>();
-            }
-
-            return LibraryManager.ResolvePaths<Video>(files, directoryService, null).Select(video =>
-            {
-                // Try to retrieve it from the db. If we don't find it, use the resolved version
-                var dbItem = LibraryManager.GetItemById(video.Id) as Video;
-
-                if (dbItem != null)
-                {
-                    video = dbItem;
-                }
-
-                video.PrimaryVersionId = Id;
-
-                return video;
-
-                // Sort them so that the list can be easily compared for changes
-            }).OrderBy(i => i.Path).ToList();
-        }
-
         public override IEnumerable<string> GetDeletePaths()
         {
             if (!IsInMixedFolder)
@@ -539,7 +427,7 @@ namespace MediaBrowser.Controller.Entities
             var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList();
 
             var locationType = i.LocationType;
-            
+
             var info = new MediaSourceInfo
             {
                 Id = i.Id.ToString("N"),

+ 1 - 12
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -364,17 +364,6 @@ namespace MediaBrowser.Controller.Library
         /// <returns>ItemInfo.</returns>
         ItemLookupInfo ParseName(string name);
 
-        /// <summary>
-        /// Gets the additional parts.
-        /// </summary>
-        /// <param name="file">The file.</param>
-        /// <param name="type">The type.</param>
-        /// <param name="files">The files.</param>
-        /// <returns>IEnumerable&lt;System.String&gt;.</returns>
-        IEnumerable<FileSystemInfo> GetAdditionalParts(string file,
-            VideoType type,
-            IEnumerable<FileSystemInfo> files);
-
         /// <summary>
         /// Gets the new item identifier.
         /// </summary>
@@ -390,7 +379,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="fileSystemChildren">The file system children.</param>
         /// <param name="directoryService">The directory service.</param>
         /// <returns>IEnumerable&lt;Trailer&gt;.</returns>
-        IEnumerable<Trailer> FindTrailers(BaseItem owner, List<FileSystemInfo> fileSystemChildren,
+        IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemInfo> fileSystemChildren,
             IDirectoryService directoryService);
 
         /// <summary>

+ 0 - 1
MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj

@@ -72,7 +72,6 @@
     <Compile Include="Providers\PlaylistXmlProvider.cs" />
     <Compile Include="Providers\SeasonXmlProvider.cs" />
     <Compile Include="Providers\SeriesXmlProvider.cs" />
-    <Compile Include="Providers\TrailerXmlProvider.cs" />
     <Compile Include="Providers\VideoXmlProvider.cs" />
     <Compile Include="Savers\BoxSetXmlSaver.cs" />
     <Compile Include="Savers\ChannelXmlSaver.cs" />

+ 0 - 37
MediaBrowser.LocalMetadata/Providers/TrailerXmlProvider.cs

@@ -1,37 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.LocalMetadata.Parsers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-
-namespace MediaBrowser.LocalMetadata.Providers
-{
-    public class TrailerXmlProvider : BaseXmlProvider<Trailer>
-    {
-        private readonly ILogger _logger;
-
-        public TrailerXmlProvider(IFileSystem fileSystem, ILogger logger)
-            : base(fileSystem)
-        {
-            _logger = logger;
-        }
-
-        protected override void Fetch(LocalMetadataResult<Trailer> result, string path, CancellationToken cancellationToken)
-        {
-            var chapters = new List<ChapterInfo>();
-
-            new MovieXmlParser(_logger).Fetch(result.Item, chapters, path, cancellationToken);
-
-            result.Chapters = chapters;
-        }
-
-        protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
-        {
-            return MovieXmlProvider.GetXmlFileInfo(info, FileSystem);
-        }
-    }
-}

+ 2 - 1
MediaBrowser.Model/ApiClient/ConnectionMode.cs

@@ -3,6 +3,7 @@ namespace MediaBrowser.Model.ApiClient
     public enum ConnectionMode
     {
         Local = 1,
-        Remote = 2
+        Remote = 2,
+        Manual = 3
     }
 }

+ 1 - 1
MediaBrowser.Model/ApiClient/IApiClient.cs

@@ -413,7 +413,7 @@ namespace MediaBrowser.Model.ApiClient
         /// </summary>
         /// <param name="query">The query.</param>
         /// <returns>Task{ItemsResult}.</returns>
-        Task<ItemsResult> GetUpcomingEpisodesAsync(NextUpQuery query);
+        Task<ItemsResult> GetUpcomingEpisodesAsync(UpcomingEpisodesQuery query);
 
         /// <summary>
         /// Gets a genre

+ 7 - 3
MediaBrowser.Model/ApiClient/ServerCredentials.cs

@@ -50,10 +50,14 @@ namespace MediaBrowser.Model.ApiClient
                 {
                     existing.RemoteAddress = server.RemoteAddress;
                 }
-                if (!existing.IsLocalAddressFixed && !string.IsNullOrEmpty(server.LocalAddress))
+                if (!string.IsNullOrEmpty(server.LocalAddress))
                 {
                     existing.LocalAddress = server.LocalAddress;
                 }
+                if (!string.IsNullOrEmpty(server.ManualAddress))
+                {
+                    existing.LocalAddress = server.ManualAddress;
+                }
                 if (!string.IsNullOrEmpty(server.Name))
                 {
                     existing.Name = server.Name;
@@ -62,9 +66,9 @@ namespace MediaBrowser.Model.ApiClient
                 {
                     existing.WakeOnLanInfos = server.WakeOnLanInfos.ToList();
                 }
-                if (server.IsLocalAddressFixed)
+                if (server.LastConnectionMode.HasValue)
                 {
-                    existing.IsLocalAddressFixed = true;
+                    existing.LastConnectionMode = server.LastConnectionMode;
                 }
             }
             else

+ 5 - 0
MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs

@@ -18,5 +18,10 @@ namespace MediaBrowser.Model.ApiClient
         /// </summary>
         /// <value>The name.</value>
         public string Name { get; set; }
+        /// <summary>
+        /// Gets or sets the endpoint address.
+        /// </summary>
+        /// <value>The endpoint address.</value>
+        public string EndpointAddress { get; set; }
     }
 }

+ 18 - 3
MediaBrowser.Model/ApiClient/ServerInfo.cs

@@ -11,14 +11,14 @@ namespace MediaBrowser.Model.ApiClient
         public String Id { get; set; }
         public String LocalAddress { get; set; }
         public String RemoteAddress { get; set; }
+        public String ManualAddress { get; set; }
         public String UserId { get; set; }
         public String AccessToken { get; set; }
         public List<WakeOnLanInfo> WakeOnLanInfos { get; set; }
         public DateTime DateLastAccessed { get; set; }
         public String ExchangeToken { get; set; }
         public UserLinkType? UserLinkType { get; set; }
-
-        public bool IsLocalAddressFixed { get; set; }
+        public ConnectionMode? LastConnectionMode { get; set; }
 
         public ServerInfo()
         {
@@ -30,7 +30,7 @@ namespace MediaBrowser.Model.ApiClient
             Name = systemInfo.ServerName;
             Id = systemInfo.Id;
 
-            if (!IsLocalAddressFixed && !string.IsNullOrEmpty(systemInfo.LocalAddress))
+            if (!string.IsNullOrEmpty(systemInfo.LocalAddress))
             {
                 LocalAddress = systemInfo.LocalAddress;
             }
@@ -55,5 +55,20 @@ namespace MediaBrowser.Model.ApiClient
                 }
             }
         }
+
+        public string GetAddress(ConnectionMode mode)
+        {
+            switch (mode)
+            {
+                case ConnectionMode.Local:
+                    return LocalAddress;
+                case ConnectionMode.Manual:
+                    return ManualAddress;
+                case ConnectionMode.Remote:
+                    return RemoteAddress;
+                default:
+                    throw new ArgumentException("Unexpected ConnectionMode");
+            }
+        }
     }
 }

+ 0 - 5
MediaBrowser.Model/Dto/BaseItemDto.cs

@@ -708,11 +708,6 @@ namespace MediaBrowser.Model.Dto
         /// <value>The game count.</value>
         public int? GameCount { get; set; }
         /// <summary>
-        /// Gets or sets the trailer count.
-        /// </summary>
-        /// <value>The trailer count.</value>
-        public int? TrailerCount { get; set; }
-        /// <summary>
         /// Gets or sets the song count.
         /// </summary>
         /// <value>The song count.</value>

+ 0 - 5
MediaBrowser.Model/Querying/ItemFields.cs

@@ -116,11 +116,6 @@ namespace MediaBrowser.Model.Querying
         /// </summary>
         ParentId,
 
-        /// <summary>
-        /// The part count
-        /// </summary>
-        PartCount,
-
         /// <summary>
         /// The physical path of the item
         /// </summary>

+ 12 - 11
MediaBrowser.Model/Querying/ItemQuery.cs

@@ -97,7 +97,7 @@ namespace MediaBrowser.Model.Querying
         /// </summary>
         /// <value>The genres.</value>
         public string[] AllGenres { get; set; }
-        
+
         /// <summary>
         /// Limit results to items containing specific studios
         /// </summary>
@@ -211,7 +211,7 @@ namespace MediaBrowser.Model.Querying
         /// </summary>
         /// <value>The max players.</value>
         public int? MaxPlayers { get; set; }
-        
+
         /// <summary>
         /// Gets or sets the name starts with or greater.
         /// </summary>
@@ -223,7 +223,7 @@ namespace MediaBrowser.Model.Querying
         /// </summary>
         /// <value>The name starts with or greater.</value>
         public string NameStartsWith { get; set; }
-        
+
         /// <summary>
         /// Gets or sets the name starts with.
         /// </summary>
@@ -267,7 +267,7 @@ namespace MediaBrowser.Model.Querying
         public bool? CollapseBoxSetItems { get; set; }
 
         public bool? IsPlayed { get; set; }
-        
+
         /// <summary>
         /// Gets or sets the exclude location types.
         /// </summary>
@@ -285,8 +285,8 @@ namespace MediaBrowser.Model.Querying
 
         public bool? EnableImages { get; set; }
         public int? ImageTypeLimit { get; set; }
-        public string EnableImageTypes { get; set; }
-        
+        public ImageType[] EnableImageTypes { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="ItemQuery" /> class.
         /// </summary>
@@ -294,16 +294,16 @@ namespace MediaBrowser.Model.Querying
         {
             LocationTypes = new LocationType[] { };
             ExcludeLocationTypes = new LocationType[] { };
-            
+
             SortBy = new string[] { };
 
-            Filters = new ItemFilter[] {};
+            Filters = new ItemFilter[] { };
 
-            Fields = new ItemFields[] {};
+            Fields = new ItemFields[] { };
 
-            MediaTypes = new string[] {};
+            MediaTypes = new string[] { };
 
-            VideoTypes = new VideoType[] {};
+            VideoTypes = new VideoType[] { };
 
             Genres = new string[] { };
             Studios = new string[] { };
@@ -317,6 +317,7 @@ namespace MediaBrowser.Model.Querying
             ImageTypes = new ImageType[] { };
             AirDays = new DayOfWeek[] { };
             SeriesStatuses = new SeriesStatus[] { };
+            EnableImageTypes = new ImageType[] { };
         }
     }
 }

+ 3 - 2
MediaBrowser.Model/Querying/ItemsByNameQuery.cs

@@ -115,8 +115,8 @@ namespace MediaBrowser.Model.Querying
         /// Gets or sets the enable image types.
         /// </summary>
         /// <value>The enable image types.</value>
-        public string EnableImageTypes { get; set; }
-        
+        public ImageType[] EnableImageTypes { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="ItemsByNameQuery" /> class.
         /// </summary>
@@ -130,6 +130,7 @@ namespace MediaBrowser.Model.Querying
             SortBy = new string[] { };
             ExcludeItemTypes = new string[] { };
             IncludeItemTypes = new string[] { };
+            EnableImageTypes = new ImageType[] { };
         }
     }
 }

+ 8 - 1
MediaBrowser.Model/Querying/LatestItemsQuery.cs

@@ -1,4 +1,6 @@
 
+using MediaBrowser.Model.Entities;
+
 namespace MediaBrowser.Model.Querying
 {
     public class LatestItemsQuery
@@ -64,6 +66,11 @@ namespace MediaBrowser.Model.Querying
         /// Gets or sets the enable image types.
         /// </summary>
         /// <value>The enable image types.</value>
-        public string EnableImageTypes { get; set; }
+        public ImageType[] EnableImageTypes { get; set; }
+
+        public LatestItemsQuery()
+        {
+            EnableImageTypes = new ImageType[] {};
+        }
     }
 }

+ 7 - 2
MediaBrowser.Model/Querying/NextUpQuery.cs

@@ -1,4 +1,5 @@
-
+using MediaBrowser.Model.Entities;
+
 namespace MediaBrowser.Model.Querying
 {
     public class NextUpQuery
@@ -52,7 +53,11 @@ namespace MediaBrowser.Model.Querying
         /// Gets or sets the enable image types.
         /// </summary>
         /// <value>The enable image types.</value>
-        public string EnableImageTypes { get; set; }
+        public ImageType[] EnableImageTypes { get; set; }
 
+        public NextUpQuery()
+        {
+            EnableImageTypes = new ImageType[] {};
+        }
     }
 }

+ 9 - 2
MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs

@@ -1,4 +1,6 @@
-namespace MediaBrowser.Model.Querying
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Querying
 {
     public class UpcomingEpisodesQuery
     {
@@ -45,6 +47,11 @@
         /// Gets or sets the enable image types.
         /// </summary>
         /// <value>The enable image types.</value>
-        public string EnableImageTypes { get; set; }
+        public ImageType[] EnableImageTypes { get; set; }
+
+        public UpcomingEpisodesQuery()
+        {
+            EnableImageTypes = new ImageType[] {};
+        }
     }
 }

+ 0 - 1
MediaBrowser.Providers/Manager/ProviderManager.cs

@@ -437,7 +437,6 @@ namespace MediaBrowser.Providers.Manager
                 GetPluginSummary<Game>(),
                 GetPluginSummary<GameSystem>(),
                 GetPluginSummary<Movie>(),
-                GetPluginSummary<Trailer>(),
                 GetPluginSummary<BoxSet>(),
                 GetPluginSummary<Book>(),
                 GetPluginSummary<Series>(),

+ 0 - 1
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -110,7 +110,6 @@
     <Compile Include="MediaInfo\SubtitleScheduledTask.cs" />
     <Compile Include="Movies\MovieDbTrailerProvider.cs" />
     <Compile Include="Movies\MovieExternalIds.cs" />
-    <Compile Include="Movies\TrailerMetadataService.cs" />
     <Compile Include="Movies\GenericMovieDbInfo.cs" />
     <Compile Include="Movies\MovieDbSearch.cs" />
     <Compile Include="Movies\MovieMetadataService.cs" />

+ 0 - 6
MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs

@@ -31,7 +31,6 @@ namespace MediaBrowser.Providers.MediaInfo
         ICustomMetadataProvider<Movie>,
         ICustomMetadataProvider<LiveTvVideoRecording>,
         ICustomMetadataProvider<LiveTvAudioRecording>,
-        ICustomMetadataProvider<Trailer>,
         ICustomMetadataProvider<Video>,
         ICustomMetadataProvider<Audio>,
         IHasItemChangeMonitor,
@@ -77,11 +76,6 @@ namespace MediaBrowser.Providers.MediaInfo
             return FetchVideoInfo(item, options, cancellationToken);
         }
 
-        public Task<ItemUpdateType> FetchAsync(Trailer item, MetadataRefreshOptions options, CancellationToken cancellationToken)
-        {
-            return FetchVideoInfo(item, options, cancellationToken);
-        }
-
         public Task<ItemUpdateType> FetchAsync(Video item, MetadataRefreshOptions options, CancellationToken cancellationToken)
         {
             return FetchVideoInfo(item, options, cancellationToken);

+ 0 - 7
MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs

@@ -57,13 +57,6 @@ namespace MediaBrowser.Providers.Movies
 
         public bool Supports(IHasImages item)
         {
-            var trailer = item as Trailer;
-
-            if (trailer != null)
-            {
-                return !trailer.IsLocalTrailer;
-            }
-
             return item is Movie || item is BoxSet || item is MusicVideo;
         }
 

+ 0 - 7
MediaBrowser.Providers/Movies/MovieDbImageProvider.cs

@@ -40,13 +40,6 @@ namespace MediaBrowser.Providers.Movies
 
         public bool Supports(IHasImages item)
         {
-            var trailer = item as Trailer;
-
-            if (trailer != null)
-            {
-                return !trailer.IsLocalTrailer;
-            }
-
             var channelItem = item as ChannelVideoItem;
 
             if (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra && channelItem.ExtraType == ExtraType.Trailer)

+ 1 - 6
MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs

@@ -12,7 +12,7 @@ using System.Threading.Tasks;
 
 namespace MediaBrowser.Providers.Movies
 {
-    public class MovieDbTrailerProvider : IRemoteMetadataProvider<Trailer, TrailerInfo>, IHasOrder, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>
+    public class MovieDbTrailerProvider : IHasOrder, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>
     {
         private readonly IHttpClient _httpClient;
 
@@ -21,11 +21,6 @@ namespace MediaBrowser.Providers.Movies
             _httpClient = httpClient;
         }
 
-        public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
-        {
-            return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
-        }
-
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
         {
             return MovieDbProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken);

+ 3 - 3
MediaBrowser.Providers/Movies/MovieExternalIds.cs

@@ -34,7 +34,7 @@ namespace MediaBrowser.Providers.Movies
                 return true;
             }
 
-            return item is Movie || item is Trailer || item is MusicVideo;
+            return item is Movie || item is MusicVideo;
         }
     }
 
@@ -80,7 +80,7 @@ namespace MediaBrowser.Providers.Movies
 
         public bool Supports(IHasProviderIds item)
         {
-            return item is Movie || item is Trailer || item is MusicVideo;
+            return item is Movie || item is MusicVideo;
         }
     }
 
@@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.Movies
                 return true;
             }
 
-            return item is Movie || item is Trailer || item is MusicVideo || item is Series || item is Episode;
+            return item is Movie || item is MusicVideo || item is Series || item is Episode;
         }
     }
 

+ 1 - 1
MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs

@@ -178,7 +178,7 @@ namespace MediaBrowser.Providers.Movies
 
             // Gather all movies into a lookup by tmdb id
             var allMovies = _libraryManager.RootFolder.RecursiveChildren
-                .Where(i => i is Movie || i is Trailer)
+                .Where(i => i is Movie)
                 .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tmdb)))
                 .ToLookup(i => i.GetProviderId(MetadataProviders.Tmdb));
 

+ 0 - 34
MediaBrowser.Providers/Movies/TrailerMetadataService.cs

@@ -1,34 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Providers.Manager;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Movies
-{
-    public class TrailerMetadataService : MetadataService<Trailer, TrailerInfo>
-    {
-        public TrailerMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager)
-        {
-        }
-
-        /// <summary>
-        /// Merges the specified source.
-        /// </summary>
-        /// <param name="source">The source.</param>
-        /// <param name="target">The target.</param>
-        /// <param name="lockedFields">The locked fields.</param>
-        /// <param name="replaceData">if set to <c>true</c> [replace data].</param>
-        /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param>
-        protected override void MergeData(Trailer source, Trailer target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
-        {
-            ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
-        }
-    }
-}

+ 1 - 1
MediaBrowser.Providers/Omdb/OmdbImageProvider.cs

@@ -108,7 +108,7 @@ namespace MediaBrowser.Providers.Omdb
                 }
             }
 
-            return item is Movie || item is Trailer;
+            return item is Movie;
         }
 
         public int Order

+ 1 - 13
MediaBrowser.Providers/Omdb/OmdbItemProvider.cs

@@ -20,7 +20,7 @@ using System.Threading.Tasks;
 namespace MediaBrowser.Providers.Omdb
 {
     public class OmdbItemProvider : IRemoteMetadataProvider<Series, SeriesInfo>,
-        IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<Trailer, TrailerInfo>, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>
+        IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>
     {
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IHttpClient _httpClient;
@@ -114,18 +114,6 @@ namespace MediaBrowser.Providers.Omdb
             return GetMovieResult<Movie>(info, cancellationToken);
         }
 
-        public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
-        {
-            var result = new MetadataResult<Trailer>();
-
-            if (info.IsLocalTrailer)
-            {
-                return Task.FromResult(result);
-            }
-
-            return GetMovieResult<Trailer>(info, cancellationToken);
-        }
-
         private async Task<MetadataResult<T>> GetMovieResult<T>(ItemLookupInfo info, CancellationToken cancellationToken)
             where T : Video, new()
         {

+ 2 - 3
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -233,7 +233,6 @@ namespace MediaBrowser.Server.Implementations.Dto
                 dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo);
                 dto.SeriesCount = taggedItems.Count(i => i is Series);
                 dto.SongCount = taggedItems.Count(i => i is Audio);
-                dto.TrailerCount = taggedItems.Count(i => i is Trailer);
             }
 
             dto.ChildCount = taggedItems.Count;
@@ -1053,9 +1052,9 @@ namespace MediaBrowser.Server.Implementations.Dto
                 dto.IsoType = video.IsoType;
                 dto.IsHD = video.IsHD;
 
-                if (fields.Contains(ItemFields.Chapters))
+                if (video.AdditionalParts.Count != 0)
                 {
-                    dto.PartCount = video.AdditionalPartIds.Count + 1;
+                    dto.PartCount = video.AdditionalParts.Count + 1;
                 }
 
                 if (fields.Contains(ItemFields.MediaSourceCount))

+ 1 - 10
MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs

@@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.Intros
             }
 
             var ratingLevel = string.IsNullOrWhiteSpace(item.OfficialRating)
-                ? (int?)null
+                ? null
                 : _localization.GetRatingLevel(item.OfficialRating);
 
             var libaryItems = user.RootFolder.GetRecursiveChildren(user, false)
@@ -134,15 +134,6 @@ namespace MediaBrowser.Server.Implementations.Intros
                     WatchingItem = item,
                     Random = random
                 }));
-
-                candidates.AddRange(libaryItems.Where(i => i is Trailer).Select(i => new ItemWithTrailer
-                {
-                    Item = i,
-                    Type = ItemWithTrailerType.LibraryTrailer,
-                    User = user,
-                    WatchingItem = item,
-                    Random = random
-                }));
             }
 
             var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ?

+ 65 - 85
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -17,6 +17,7 @@ using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Naming.Audio;
 using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.IO;
 using MediaBrowser.Naming.Video;
 using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
 using MediaBrowser.Server.Implementations.Library.Validators;
@@ -1700,82 +1701,40 @@ namespace MediaBrowser.Server.Implementations.Library
             };
         }
 
-        public IEnumerable<FileSystemInfo> GetAdditionalParts(string file,
-            VideoType type,
-            IEnumerable<FileSystemInfo> files)
-        {
-            var resolver = new StackResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
-
-            StackResult result;
-            List<FileSystemInfo> filteredFiles;
-
-            if (type == VideoType.BluRay || type == VideoType.Dvd)
-            {
-                filteredFiles = files.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
-                    .ToList();
-
-                result = resolver.ResolveDirectories(filteredFiles.Select(i => i.FullName));
-            }
-            else
-            {
-                filteredFiles = files.Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
-                    .ToList();
-
-                result = resolver.ResolveFiles(filteredFiles.Select(i => i.FullName));
-            }
-
-            var stack = result.Stacks
-                .FirstOrDefault(i => i.Files.Contains(file, StringComparer.OrdinalIgnoreCase));
-
-            if (stack != null)
-            {
-                return stack.Files.Where(i => !string.Equals(i, file, StringComparison.OrdinalIgnoreCase))
-                    .Select(i => filteredFiles.FirstOrDefault(f => string.Equals(i, f.FullName, StringComparison.OrdinalIgnoreCase)))
-                    .Where(i => i != null);
-            }
-
-            return new List<FileSystemInfo>();
-        }
-
-        public IEnumerable<Trailer> FindTrailers(BaseItem owner, List<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
+        public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
         {
             var files = fileSystemChildren.OfType<DirectoryInfo>()
                 .Where(i => string.Equals(i.Name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase))
                 .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
                 .ToList();
 
-            var extraTypes = new List<ExtraType> { ExtraType.Trailer };
-            var suffixes = BaseItem.ExtraSuffixes.Where(i => extraTypes.Contains(i.Value))
-                .Select(i => i.Key)
-                .ToList();
+            var videoListResolver = new VideoListResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
 
-            files.AddRange(fileSystemChildren.OfType<FileInfo>()
-                .Where(i =>
-                {
-                    var nameEithoutExtension = _fileSystem.GetFileNameWithoutExtension(i);
+            var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo
+            {
+                FullName = i.FullName,
+                Type = GetFileType(i)
 
-                    if (!suffixes.Any(s => nameEithoutExtension.EndsWith(s, StringComparison.OrdinalIgnoreCase)))
-                    {
-                        return false;
-                    }
+            }).ToList());
 
-                    return !string.Equals(owner.Path, i.FullName, StringComparison.OrdinalIgnoreCase);
-                }));
+            var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase));
 
-            return ResolvePaths<Trailer>(files, directoryService, null).Select(video =>
+            if (currentVideo != null)
+            {
+                files.AddRange(currentVideo.Extras.Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => new FileInfo(i.Path)));
+            }
+
+            return ResolvePaths<Video>(files, directoryService, null).Select(video =>
             {
                 // Try to retrieve it from the db. If we don't find it, use the resolved version
-                var dbItem = GetItemById(video.Id) as Trailer;
+                var dbItem = GetItemById(video.Id) as Video;
 
                 if (dbItem != null)
                 {
                     video = dbItem;
                 }
 
-                if (video != null)
-                {
-                    video.ExtraType = ExtraType.Trailer;
-                }
+                video.ExtraType = ExtraType.Trailer;
 
                 return video;
 
@@ -1783,6 +1742,16 @@ namespace MediaBrowser.Server.Implementations.Library
             }).OrderBy(i => i.Path).ToList();
         }
 
+        private FileInfoType GetFileType(FileSystemInfo info)
+        {
+            if ((info.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
+            {
+                return FileInfoType.Directory;
+            }
+
+            return FileInfoType.File;
+        }
+
         public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
         {
             var files = fileSystemChildren.OfType<DirectoryInfo>()
@@ -1790,23 +1759,21 @@ namespace MediaBrowser.Server.Implementations.Library
                 .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
                 .ToList();
 
-            var extraTypes = new List<ExtraType> { ExtraType.BehindTheScenes, ExtraType.DeletedScene, ExtraType.Interview, ExtraType.Sample, ExtraType.Scene, ExtraType.Clip };
-            var suffixes = BaseItem.ExtraSuffixes.Where(i => extraTypes.Contains(i.Value))
-                .Select(i => i.Key)
-                .ToList();
+            var videoListResolver = new VideoListResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
 
-            files.AddRange(fileSystemChildren.OfType<FileInfo>()
-                .Where(i =>
-                {
-                    var nameEithoutExtension = _fileSystem.GetFileNameWithoutExtension(i);
+            var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo
+            {
+                FullName = i.FullName,
+                Type = GetFileType(i)
 
-                    if (!suffixes.Any(s => nameEithoutExtension.EndsWith(s, StringComparison.OrdinalIgnoreCase)))
-                    {
-                        return false;
-                    }
+            }).ToList());
 
-                    return !string.Equals(owner.Path, i.FullName, StringComparison.OrdinalIgnoreCase);
-                }));
+            var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase));
+
+            if (currentVideo != null)
+            {
+                files.AddRange(currentVideo.Extras.Where(i => !string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => new FileInfo(i.Path)));
+            }
 
             return ResolvePaths<Video>(files, directoryService, null).Select(video =>
             {
@@ -1818,10 +1785,7 @@ namespace MediaBrowser.Server.Implementations.Library
                     video = dbItem;
                 }
 
-                if (video != null)
-                {
-                    SetExtraTypeFromFilename(video);
-                }
+                SetExtraTypeFromFilename(video);
 
                 return video;
 
@@ -1831,18 +1795,34 @@ namespace MediaBrowser.Server.Implementations.Library
 
         private void SetExtraTypeFromFilename(Video item)
         {
-            var name = System.IO.Path.GetFileNameWithoutExtension(item.Path) ?? string.Empty;
+            var resolver = new ExtraResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
 
-            foreach (var suffix in BaseItem.ExtraSuffixes)
+            var result = resolver.GetExtraInfo(item.Path);
+
+            if (string.Equals(result.ExtraType, "deletedscene", StringComparison.OrdinalIgnoreCase))
             {
-                if (name.EndsWith(suffix.Key, StringComparison.OrdinalIgnoreCase))
-                {
-                    item.ExtraType = suffix.Value;
-                    return;
-                }
+                item.ExtraType = ExtraType.DeletedScene;
+            }
+            else if (string.Equals(result.ExtraType, "behindthescenes", StringComparison.OrdinalIgnoreCase))
+            {
+                item.ExtraType = ExtraType.BehindTheScenes;
+            }
+            else if (string.Equals(result.ExtraType, "interview", StringComparison.OrdinalIgnoreCase))
+            {
+                item.ExtraType = ExtraType.Interview;
+            }
+            else if (string.Equals(result.ExtraType, "scene", StringComparison.OrdinalIgnoreCase))
+            {
+                item.ExtraType = ExtraType.Scene;
+            }
+            else if (string.Equals(result.ExtraType, "sample", StringComparison.OrdinalIgnoreCase))
+            {
+                item.ExtraType = ExtraType.Sample;
+            }
+            else
+            {
+                item.ExtraType = ExtraType.Clip;
             }
-
-            item.ExtraType = ExtraType.Clip;
         }
     }
 }

+ 126 - 34
MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.Video;
 using System;
 using System.IO;
 
@@ -42,9 +43,75 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
               where TVideoType : Video, new()
         {
             // If the path is a file check for a matching extensions
-            if (!args.IsDirectory)
+            var parser = new Naming.Video.VideoResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
+
+            if (args.IsDirectory)
+            {
+                TVideoType video = null;
+                VideoFileInfo videoInfo = null;
+
+                // Loop through each child file/folder and see if we find a video
+                foreach (var child in args.FileSystemChildren)
+                {
+                    var filename = child.Name;
+
+                    if ((child.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
+                    {
+                        if (IsDvdDirectory(filename))
+                        {
+                            videoInfo = parser.ResolveDirectory(args.Path);
+
+                            if (videoInfo == null)
+                            {
+                                return null;
+                            }
+
+                            video = new TVideoType
+                            {
+                                Path = args.Path,
+                                VideoType = VideoType.Dvd,
+                                ProductionYear = videoInfo.Year
+                            };
+                            break;
+                        }
+                        if (IsBluRayDirectory(filename))
+                        {
+                            videoInfo = parser.ResolveDirectory(args.Path);
+
+                            if (videoInfo == null)
+                            {
+                                return null;
+                            }
+
+                            video = new TVideoType
+                            {
+                                Path = args.Path,
+                                VideoType = VideoType.BluRay,
+                                ProductionYear = videoInfo.Year
+                            };
+                            break;
+                        }
+                    }
+                }
+
+                if (video != null)
+                {
+                    if (parseName)
+                    {
+                        video.Name = videoInfo.Name;
+                    }
+                    else
+                    {
+                        video.Name = Path.GetFileName(args.Path);
+                    }
+
+                    Set3DFormat(video, videoInfo);
+                }
+
+                return video;
+            }
+            else
             {
-                var parser = new Naming.Video.VideoResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
                 var videoInfo = parser.ResolveFile(args.Path);
 
                 if (videoInfo == null)
@@ -57,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
                 if (LibraryManager.IsVideoFile(args.Path) || videoInfo.IsStub || isShortcut)
                 {
                     var type = string.Equals(videoInfo.Container, "iso", StringComparison.OrdinalIgnoreCase) || string.Equals(videoInfo.Container, "img", StringComparison.OrdinalIgnoreCase) ?
-                        VideoType.Iso : 
+                        VideoType.Iso :
                         VideoType.VideoFile;
 
                     var path = args.Path;
@@ -97,37 +164,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
                         }
                     }
 
-                    if (videoInfo.Is3D)
-                    {
-                        if (string.Equals(videoInfo.Format3D, "fsbs", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.FullSideBySide;
-                        }
-                        else if (string.Equals(videoInfo.Format3D, "ftab", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.FullTopAndBottom;
-                        }
-                        else if (string.Equals(videoInfo.Format3D, "hsbs", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.HalfSideBySide;
-                        }
-                        else if (string.Equals(videoInfo.Format3D, "htab", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.HalfTopAndBottom;
-                        }
-                        else if (string.Equals(videoInfo.Format3D, "sbs", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.HalfSideBySide;
-                        }
-                        else if (string.Equals(videoInfo.Format3D, "sbs3d", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.HalfSideBySide;
-                        }
-                        else if (string.Equals(videoInfo.Format3D, "tab", StringComparison.OrdinalIgnoreCase))
-                        {
-                            video.Video3DFormat = Video3DFormat.HalfTopAndBottom;
-                        }
-                    }
+                    Set3DFormat(video, videoInfo);
 
                     return video;
                 }
@@ -135,5 +172,60 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
 
             return null;
         }
+
+        private void Set3DFormat(Video video, VideoFileInfo videoInfo)
+        {
+            if (videoInfo.Is3D)
+            {
+                if (string.Equals(videoInfo.Format3D, "fsbs", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.FullSideBySide;
+                }
+                else if (string.Equals(videoInfo.Format3D, "ftab", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.FullTopAndBottom;
+                }
+                else if (string.Equals(videoInfo.Format3D, "hsbs", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.HalfSideBySide;
+                }
+                else if (string.Equals(videoInfo.Format3D, "htab", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.HalfTopAndBottom;
+                }
+                else if (string.Equals(videoInfo.Format3D, "sbs", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.HalfSideBySide;
+                }
+                else if (string.Equals(videoInfo.Format3D, "sbs3d", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.HalfSideBySide;
+                }
+                else if (string.Equals(videoInfo.Format3D, "tab", StringComparison.OrdinalIgnoreCase))
+                {
+                    video.Video3DFormat = Video3DFormat.HalfTopAndBottom;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Determines whether [is DVD directory] [the specified directory name].
+        /// </summary>
+        /// <param name="directoryName">Name of the directory.</param>
+        /// <returns><c>true</c> if [is DVD directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
+        protected bool IsDvdDirectory(string directoryName)
+        {
+            return string.Equals(directoryName, "video_ts", StringComparison.OrdinalIgnoreCase);
+        }
+
+        /// <summary>
+        /// Determines whether [is blu ray directory] [the specified directory name].
+        /// </summary>
+        /// <param name="directoryName">Name of the directory.</param>
+        /// <returns><c>true</c> if [is blu ray directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
+        protected bool IsBluRayDirectory(string directoryName)
+        {
+            return string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase);
+        }
     }
 }

+ 0 - 61
MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs

@@ -1,61 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Resolvers;
-using MediaBrowser.Model.Entities;
-using System;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Server.Implementations.Library.Resolvers
-{
-    /// <summary>
-    /// Class LocalTrailerResolver
-    /// </summary>
-    public class LocalTrailerResolver : BaseVideoResolver<Trailer>
-    {
-        private readonly IFileSystem _fileSystem;
-
-        public LocalTrailerResolver(ILibraryManager libraryManager, IFileSystem fileSystem) : base(libraryManager)
-        {
-            _fileSystem = fileSystem;
-        }
-
-        /// <summary>
-        /// Resolves the specified args.
-        /// </summary>
-        /// <param name="args">The args.</param>
-        /// <returns>Trailer.</returns>
-        protected override Trailer Resolve(ItemResolveArgs args)
-        {
-            // Trailers are not Children, therefore this can never happen
-            if (args.Parent != null)
-            {
-                return null;
-            }
-
-            // If the file is within a trailers folder, see if the VideoResolver returns something
-            if (!args.IsDirectory)
-            {
-                if (string.Equals(Path.GetFileName(Path.GetDirectoryName(args.Path)), BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase))
-                {
-                    return base.Resolve(args);
-                }
-
-                // Support xbmc local trailer convention, but only when looking for local trailers (hence the parent == null check)
-                if (args.Parent == null)
-                {
-                    var nameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(args.Path);
-                    var suffix = BaseItem.ExtraSuffixes.First(i => i.Value == ExtraType.Trailer);
-
-                    if (nameWithoutExtension.EndsWith(suffix.Key, StringComparison.OrdinalIgnoreCase))
-                    {
-                        return base.Resolve(args);
-                    }
-                }
-            }
-
-            return null;
-        }
-    }
-}

+ 35 - 66
MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
@@ -64,44 +63,44 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                 }
             }
 
-            var isDirectory = args.IsDirectory;
-
-            if (isDirectory)
-            {
-                // Since the looping is expensive, this is an optimization to help us avoid it
-                if (args.ContainsMetaFileByName("series.xml"))
-                {
-                    return null;
-                }
-            }
-
             var collectionType = args.GetCollectionType();
 
             // Find movies with their own folders
-            if (isDirectory)
+            if (args.IsDirectory)
             {
-                if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase))
-                {
-                    return FindMovie<Trailer>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, false, collectionType);
-                }
-
                 if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
                 {
-                    return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, false, collectionType);
+                    return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, collectionType);
                 }
 
                 if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
                 {
-                    return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, false, collectionType);
+                    return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, collectionType);
                 }
 
-                if (string.IsNullOrEmpty(collectionType) ||
-                    string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
-                    string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
+                if (string.IsNullOrEmpty(collectionType))
                 {
-                    return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, true, collectionType);
+                    // Owned items should just use the plain video type
+                    if (args.Parent == null)
+                    {
+                        return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, collectionType);
+                    }
+
+                    // Since the looping is expensive, this is an optimization to help us avoid it
+                    if (args.ContainsMetaFileByName("series.xml"))
+                    {
+                        return null;
+                    }
+                    
+                    return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, collectionType);
                 }
 
+                if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
+                  string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
+                {
+                    return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, collectionType);
+                }
+                
                 return null;
             }
 
@@ -112,12 +111,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                 return null;
             }
 
-            // Find movies that are mixed in the same folder
-            if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase))
-            {
-                return ResolveVideo<Trailer>(args, true);
-            }
-
             Video item = null;
 
             if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
@@ -126,13 +119,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
             }
 
             // To find a movie file, the collection type must be movies or boxsets
-            // Otherwise we'll consider it a plain video and let the video resolver handle it
-            if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
+            else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
                 string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
             {
                 item = ResolveVideo<Movie>(args, true);
             }
-
+            
             if (item != null)
             {
                 item.IsInMixedFolder = true;
@@ -178,11 +170,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
         /// <param name="parent">The parent.</param>
         /// <param name="fileSystemEntries">The file system entries.</param>
         /// <param name="directoryService">The directory service.</param>
-        /// <param name="supportMultiFileItems">if set to <c>true</c> [support multi file items].</param>
         /// <param name="supportsMultipleSources">if set to <c>true</c> [supports multiple sources].</param>
         /// <param name="collectionType">Type of the collection.</param>
         /// <returns>Movie.</returns>
-        private T FindMovie<T>(string path, Folder parent, IEnumerable<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, bool supportMultiFileItems, bool supportsMultipleSources, string collectionType)
+        private T FindMovie<T>(string path, Folder parent, IEnumerable<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, bool supportsMultipleSources, string collectionType)
             where T : Video, new()
         {
             var movies = new List<T>();
@@ -243,15 +234,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
 
             if (movies.Count > 1)
             {
-                if (supportMultiFileItems)
-                {
-                    var result = GetMultiFileMovie(movies);
+                var multiFileResult = GetMultiFileMovie(movies);
 
-                    if (result != null)
-                    {
-                        return result;
-                    }
+                if (multiFileResult != null)
+                {
+                    return multiFileResult;
                 }
+
                 if (supportsMultipleSources)
                 {
                     var result = GetMovieWithMultipleSources(movies);
@@ -334,7 +323,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
             {
                 Path = folderPaths[0],
 
-                IsMultiPart = true,
+                AdditionalParts = folderPaths.Skip(1).ToList(),
 
                 VideoType = videoTypes[0],
 
@@ -366,7 +355,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                 return null;
             }
 
-            firstMovie.IsMultiPart = true;
+            firstMovie.AdditionalParts = result.Stacks[0].Files.Skip(1).ToList();
             firstMovie.Name = result.Stacks[0].Name;
 
             // They must all be part of the sequence if we're going to consider it a multi-part movie
@@ -392,7 +381,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
             {
                 if (sortedMovies.All(i => _fileSystem.GetFileNameWithoutExtension(i.Path).StartsWith(filenamePrefix + " - ", StringComparison.OrdinalIgnoreCase)))
                 {
-                    firstMovie.HasLocalAlternateVersions = true;
+                    firstMovie.LocalAlternateVersions = sortedMovies.Skip(1).Select(i => i.Path).ToList();
 
                     _logger.Debug("Multi-version video found: " + firstMovie.Path);
 
@@ -402,25 +391,5 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
 
             return null;
         }
-
-        /// <summary>
-        /// Determines whether [is DVD directory] [the specified directory name].
-        /// </summary>
-        /// <param name="directoryName">Name of the directory.</param>
-        /// <returns><c>true</c> if [is DVD directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
-        private bool IsDvdDirectory(string directoryName)
-        {
-            return string.Equals(directoryName, "video_ts", StringComparison.OrdinalIgnoreCase);
-        }
-
-        /// <summary>
-        /// Determines whether [is blu ray directory] [the specified directory name].
-        /// </summary>
-        /// <param name="directoryName">Name of the directory.</param>
-        /// <returns><c>true</c> if [is blu ray directory] [the specified directory name]; otherwise, <c>false</c>.</returns>
-        private bool IsBluRayDirectory(string directoryName)
-        {
-            return string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase);
-        }
     }
 }

+ 5 - 29
MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities.TV;
+using System;
+using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Entities;
@@ -41,39 +42,14 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
             // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
             if (season != null || parent is Series || parent.Parents.OfType<Series>().Any())
             {
-                Episode episode = null;
-
-                if (args.IsDirectory)
+                if (args.IsDirectory && args.Path.IndexOf("dead like me", StringComparison.OrdinalIgnoreCase) != -1)
                 {
-                    if (args.ContainsFileSystemEntryByName("video_ts"))
-                    {
-                        episode = new Episode
-                        {
-                            Path = args.Path,
-                            VideoType = VideoType.Dvd
-                        };
-                    }
-                    if (args.ContainsFileSystemEntryByName("bdmv"))
-                    {
-                        episode = new Episode
-                        {
-                            Path = args.Path,
-                            VideoType = VideoType.BluRay
-                        };
-                    }
-                }
-
-                if (episode == null)
-                {
-                    episode = base.Resolve(args);
+                    var b = true;
                 }
+                var episode = ResolveVideo<Episode>(args, false);
 
                 if (episode != null)
                 {
-                    // The base video resolver is going to fill these in, so null them out
-                    episode.ProductionYear = null;
-                    episode.Name = null;
-
                     if (season != null)
                     {
                         episode.ParentIndexNumber = season.IndexNumber;

+ 6 - 0
MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs

@@ -21,6 +21,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
         {
             if (args.Parent != null)
             {
+                // The movie resolver will handle this
+                if (args.IsDirectory)
+                {
+                    return null;
+                }
+
                 var collectionType = args.GetCollectionType() ?? string.Empty;
                 var accepted = new[]
                 {

+ 1 - 2
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -51,7 +51,7 @@
     </Reference>
     <Reference Include="MediaBrowser.Naming, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\MediaBrowser.Naming.1.0.0.12\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Naming.1.0.0.13\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
     </Reference>
     <Reference Include="Mono.Nat, Version=1.2.21.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -194,7 +194,6 @@
     <Compile Include="Library\Resolvers\Audio\MusicArtistResolver.cs" />
     <Compile Include="Library\Resolvers\ItemResolver.cs" />
     <Compile Include="Library\Resolvers\FolderResolver.cs" />
-    <Compile Include="Library\Resolvers\LocalTrailerResolver.cs" />
     <Compile Include="Library\Resolvers\Movies\BoxSetResolver.cs" />
     <Compile Include="Library\Resolvers\Movies\MovieResolver.cs" />
     <Compile Include="Library\Resolvers\TV\EpisodeResolver.cs" />

+ 1 - 1
MediaBrowser.Server.Implementations/Sync/SyncManager.cs

@@ -189,7 +189,7 @@ namespace MediaBrowser.Server.Implementations.Sync
                             return false;
                         }
 
-                        if (video.IsMultiPart)
+                        if (video.IsStacked)
                         {
                             return false;
                         }

+ 1 - 1
MediaBrowser.Server.Implementations/packages.config

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Naming" version="1.0.0.12" targetFramework="net45" />
+  <package id="MediaBrowser.Naming" version="1.0.0.13" targetFramework="net45" />
   <package id="Mono.Nat" version="1.2.21.0" targetFramework="net45" />
   <package id="morelinq" version="1.1.0" targetFramework="net45" />
 </packages>

+ 1 - 6
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -950,11 +950,6 @@ namespace MediaBrowser.Server.Startup.Common
                 var localAddresses = NetworkManager.GetLocalIpAddresses()
                     .ToList();
 
-                if (localAddresses.Count < 2)
-                {
-                    return localAddresses;
-                }
-
                 var httpServerAddresses = HttpServer.LocalEndPoints
                     .Select(i => i.Split(':').FirstOrDefault())
                     .Where(i => !string.IsNullOrEmpty(i))
@@ -967,7 +962,7 @@ namespace MediaBrowser.Server.Startup.Common
 
                 if (matchedAddresses.Count == 0)
                 {
-                    return localAddresses.Take(1);
+                    return localAddresses;
                 }
 
                 return matchedAddresses;

+ 0 - 9
MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs

@@ -26,13 +26,4 @@ namespace MediaBrowser.XbmcMetadata.Providers
         {
         }
     }
-
-    public class TrailerNfoProvider : BaseVideoNfoProvider<Trailer>
-    {
-        public TrailerNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
-            : base(fileSystem, logger, config)
-        {
-        }
-    }
-
 }

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.511</version>
+        <version>3.0.517</version>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.511" />
+            <dependency id="MediaBrowser.Common" version="3.0.517" />
             <dependency id="NLog" version="3.1.0.0" />
             <dependency id="SimpleInjector" version="2.6.1" />
             <dependency id="sharpcompress" version="0.10.2" />

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.511</version>
+        <version>3.0.517</version>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 1 - 1
Nuget/MediaBrowser.Model.Signed.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Model.Signed</id>
-        <version>3.0.511</version>
+        <version>3.0.517</version>
         <title>MediaBrowser.Model - Signed Edition</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.511</version>
+        <version>3.0.517</version>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.511" />
+            <dependency id="MediaBrowser.Common" version="3.0.517" />
         </dependencies>
     </metadata>
     <files>