diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index ea90afc3ba..6517d738b9 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -83,6 +83,13 @@ namespace MediaBrowser.Api { info.ContentTypeOptions = GetContentTypeOptions(true); info.ContentType = configuredContentType; + + if (string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + { + info.ContentTypeOptions = info.ContentTypeOptions + .Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + .ToList(); + } } } } diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index 094f056bdc..3f57ca2a04 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -145,12 +145,14 @@ namespace MediaBrowser.Api.Sync private readonly ISyncManager _syncManager; private readonly IDtoService _dtoService; private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; - public SyncService(ISyncManager syncManager, IDtoService dtoService, ILibraryManager libraryManager) + public SyncService(ISyncManager syncManager, IDtoService dtoService, ILibraryManager libraryManager, IUserManager userManager) { _syncManager = syncManager; _dtoService = dtoService; _libraryManager = libraryManager; + _userManager = userManager; } public object Get(GetSyncTargets request) @@ -238,11 +240,15 @@ namespace MediaBrowser.Api.Sync } }; + var auth = AuthorizationContext.GetAuthorizationInfo(Request); + + var authenticatedUser = _userManager.GetUserById(auth.UserId); + var items = request.ItemIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(_libraryManager.GetItemById) .Where(i => i != null); - var dtos = _dtoService.GetBaseItemDtos(items, dtoOptions) + var dtos = _dtoService.GetBaseItemDtos(items, dtoOptions, authenticatedUser) .ToList(); result.Options = SyncHelper.GetSyncOptions(dtos); @@ -266,9 +272,11 @@ namespace MediaBrowser.Api.Sync } } - public object Get(GetReadySyncItems request) + public async Task Get(GetReadySyncItems request) { - return ToOptimizedResult(_syncManager.GetReadySyncItems(request.TargetId)); + var result = await _syncManager.GetReadySyncItems(request.TargetId).ConfigureAwait(false); + + return ToOptimizedResult(result); } public async Task Post(SyncData request) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 13ec1db3cf..9c9feead50 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -157,6 +157,9 @@ namespace MediaBrowser.Api [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string AdjacentTo { get; set; } + [ApiMember(Name = "StartItemId", Description = "Optional. Skip through the list until a given item is found.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string StartItemId { get; set; } + /// /// Skips over a given number of items within the results. Use for paging. /// @@ -475,6 +478,11 @@ namespace MediaBrowser.Api episodes = episodes.Where(i => i.IsVirtualUnaired == val); } + if (!string.IsNullOrWhiteSpace(request.StartItemId)) + { + episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N"), request.StartItemId, StringComparison.OrdinalIgnoreCase)); + } + IEnumerable returnItems = episodes; // This must be the last filter @@ -483,9 +491,10 @@ namespace MediaBrowser.Api returnItems = UserViewBuilder.FilterForAdjacency(returnItems, request.AdjacentTo); } - returnItems = _libraryManager.ReplaceVideosWithPrimaryVersions(returnItems); + var returnList = _libraryManager.ReplaceVideosWithPrimaryVersions(returnItems) + .ToList(); - var pagedItems = ApplyPaging(returnItems, request.StartIndex, request.Limit); + var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit); var dtoOptions = GetDtoOptions(request); @@ -494,7 +503,7 @@ namespace MediaBrowser.Api return new ItemsResult { - TotalRecordCount = dtos.Length, + TotalRecordCount = returnList.Count, Items = dtos }; } diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index c34924f3cc..c17f333481 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -365,9 +365,7 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } - var auth = AuthorizationContext.GetAuthorizationInfo(Request); - - var result = _userManager.GetOfflineUserDto(user, auth.DeviceId); + var result = _userManager.GetOfflineUserDto(user); return ToOptimizedResult(result); } diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index 6deda12932..1762ed5754 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -169,24 +169,27 @@ namespace MediaBrowser.Common.Implementations.Networking IPAddress address; if (resolveHost && !IPAddress.TryParse(endpoint, out address)) { - var host = new Uri(endpoint).DnsSafeHost; - - Logger.Debug("Resolving host {0}", host); - - try + Uri uri; + if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri)) { - address = GetIpAddresses(host).FirstOrDefault(); + var host = uri.DnsSafeHost; + Logger.Debug("Resolving host {0}", host); - if (address != null) + try { - Logger.Debug("{0} resolved to {1}", host, address); + address = GetIpAddresses(host).FirstOrDefault(); - return IsInLocalNetworkInternal(address.ToString(), false); + if (address != null) + { + Logger.Debug("{0} resolved to {1}", host, address); + + return IsInLocalNetworkInternal(address.ToString(), false); + } + } + catch (Exception ex) + { + Logger.ErrorException("Error resovling hostname {0}", ex, host); } - } - catch (Exception ex) - { - Logger.ErrorException("Error resovling hostname {0}", ex, host); } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index e65d3c0e78..2b81450414 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -52,6 +52,16 @@ namespace MediaBrowser.Controller.Entities.Audio } } + public override bool IsSaveLocalMetadataEnabled() + { + if (IsAccessedByName) + { + return true; + } + + return base.IsSaveLocalMetadataEnabled(); + } + private readonly Task _cachedTask = Task.FromResult(true); protected override Task ValidateChildrenInternal(IProgress progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index ed09560732..971c092361 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -44,6 +44,11 @@ namespace MediaBrowser.Controller.Entities.Audio return false; } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 3ab02ea21a..50a6dda305 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -976,14 +976,21 @@ namespace MediaBrowser.Controller.Entities lang = hasLang.PreferredMetadataLanguage; } - if (string.IsNullOrEmpty(lang)) + if (string.IsNullOrWhiteSpace(lang)) { lang = Parents.OfType() .Select(i => i.PreferredMetadataLanguage) - .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } - if (string.IsNullOrEmpty(lang)) + if (string.IsNullOrWhiteSpace(lang)) + { + lang = LibraryManager.GetCollectionFolders(this) + .Select(i => i.PreferredMetadataLanguage) + .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); + } + + if (string.IsNullOrWhiteSpace(lang)) { lang = ConfigurationManager.Configuration.PreferredMetadataLanguage; } @@ -1006,14 +1013,21 @@ namespace MediaBrowser.Controller.Entities lang = hasLang.PreferredMetadataCountryCode; } - if (string.IsNullOrEmpty(lang)) + if (string.IsNullOrWhiteSpace(lang)) { lang = Parents.OfType() .Select(i => i.PreferredMetadataCountryCode) - .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } - if (string.IsNullOrEmpty(lang)) + if (string.IsNullOrWhiteSpace(lang)) + { + lang = LibraryManager.GetCollectionFolders(this) + .Select(i => i.PreferredMetadataCountryCode) + .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); + } + + if (string.IsNullOrWhiteSpace(lang)) { lang = ConfigurationManager.Configuration.MetadataCountryCode; } diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index b246b9388f..c91acbe3f1 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -43,6 +43,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + public override bool CanDelete() { return false; diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index e17a5c1d8b..cb68e5dae9 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + public override bool CanDelete() { return false; diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index d874046efd..0778643da5 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -79,6 +79,11 @@ namespace MediaBrowser.Controller.Entities.Movies return true; } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + /// /// Gets the trailer ids. /// diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index d8cb69ca17..ef24d43470 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -1,8 +1,8 @@ -using System.Runtime.Serialization; -using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Providers; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities { @@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.Entities return false; } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 31bbaf422e..b8d359369b 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities return false; } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + /// /// Gets a value indicating whether this instance is owned item. /// @@ -63,7 +68,6 @@ namespace MediaBrowser.Controller.Entities return inputItems.Where(GetItemFilter()); } - public Func GetItemFilter() { return i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 619617e9fa..4c34460d7c 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -1,7 +1,4 @@ -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; @@ -10,6 +7,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Controller.Entities.TV { diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index b5ca053ecd..85c10c272a 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -1632,7 +1632,7 @@ namespace MediaBrowser.Controller.Entities var ok = new[] { item }.Any(i => i.People != null && i.People.Any(p => - p.Name.Equals(query.Person, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role, StringComparer.OrdinalIgnoreCase)))); + string.Equals(p.Name, query.Person, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type ?? string.Empty, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role ?? string.Empty, StringComparer.OrdinalIgnoreCase)))); if (!ok) { diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index cf3ad3b6ab..a1a1523873 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -52,6 +52,11 @@ namespace MediaBrowser.Controller.Entities } } + public override bool IsSaveLocalMetadataEnabled() + { + return true; + } + public IEnumerable GetTaggedItems(IEnumerable inputItems) { int year; diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 9871ef3c5f..9c8ed45a53 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -393,5 +393,12 @@ namespace MediaBrowser.Controller.Library /// IEnumerable<Video>. IEnumerable