From 9b998a068a2622f43ac813800654e357f94d0c21 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 28 Oct 2015 15:40:38 -0400 Subject: update image encoding --- .../Library/LibraryManager.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 92acd08d1..daa3d8ad4 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1280,6 +1280,11 @@ namespace MediaBrowser.Server.Implementations.Library return ItemRepository.GetItemIdsList(query); } + public IEnumerable GetItems(InternalItemsQuery query, User user) + { + return GetItemIds(query).Select(GetItemById).Where(i => i.IsVisibleStandalone(user)); + } + /// /// Gets the intros. /// @@ -1811,14 +1816,9 @@ namespace MediaBrowser.Server.Implementations.Library isNew = true; } - if (!item.UserId.HasValue) + if (!item.UserId.HasValue || !string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) { item.UserId = user.Id; - await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); - } - - if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) - { item.ViewType = viewType; await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); } -- cgit v1.2.3 From 0bd1f36ececc04c86bbf49b1ffd07dd30a5878b1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 29 Oct 2015 09:28:05 -0400 Subject: update db queries --- MediaBrowser.Api/PluginService.cs | 6 +- MediaBrowser.Api/TvShowsService.cs | 34 ++--- .../Security/PluginSecurityManager.cs | 17 ++- .../Entities/AggregateFolder.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 21 ++- MediaBrowser.Controller/Entities/Folder.cs | 45 ++++-- .../Entities/InternalItemsQuery.cs | 6 +- MediaBrowser.Controller/Entities/Person.cs | 9 ++ MediaBrowser.Controller/Entities/TV/Episode.cs | 14 ++ MediaBrowser.Controller/Entities/UserView.cs | 15 ++ MediaBrowser.Controller/Library/ILibraryManager.cs | 12 +- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 9 ++ .../Persistence/IItemRepository.cs | 7 + .../ContentDirectory/ControlHandler.cs | 24 ++-- .../Configuration/ServerConfiguration.cs | 9 +- .../Collections/CollectionManager.cs | 1 + .../Dto/DtoService.cs | 14 +- .../Intros/DefaultIntroProvider.cs | 8 +- .../Library/LibraryManager.cs | 58 +++++--- .../Library/MusicManager.cs | 8 +- .../Library/SearchEngine.cs | 27 +--- .../LiveTv/LiveTvManager.cs | 34 ++--- .../Persistence/CleanDatabaseScheduledTask.cs | 8 ++ .../Persistence/SqliteItemRepository.cs | 152 +++++++++++++++++++-- .../Playlists/PlaylistManager.cs | 1 + .../TV/TVSeriesManager.cs | 48 ++----- .../ApplicationHost.cs | 2 +- .../MediaBrowser.Server.Startup.Common.csproj | 2 +- .../Migrations/DbMigration.cs | 34 +++++ .../Migrations/Release5767.cs | 48 ------- 30 files changed, 431 insertions(+), 244 deletions(-) create mode 100644 MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs delete mode 100644 MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index a7fd14bf0..74b37df92 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -278,9 +278,11 @@ namespace MediaBrowser.Api /// /// /// - public async Task Post(RegisterAppstoreSale request) + public void Post(RegisterAppstoreSale request) { - await _securityManager.RegisterAppStoreSale(request.Parameters); + var task = _securityManager.RegisterAppStoreSale(request.Parameters); + + Task.WaitAll(task); } /// diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 19d12fe65..ead232888 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -275,38 +275,26 @@ namespace MediaBrowser.Api var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime(); - IEnumerable items; + var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId }; - if (string.IsNullOrWhiteSpace(request.ParentId)) + var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user) { - items = _libraryManager.GetItems(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { "PremiereDate", "SortName" }, - SortOrder = SortOrder.Ascending, - MinPremiereDate = minPremiereDate - - }, user); - } - else - { - items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate); - } - - var itemsList = _libraryManager - .Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending) - .Cast() - .ToList(); + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { "PremiereDate", "AirTime", "SortName" }, + SortOrder = SortOrder.Ascending, + MinPremiereDate = minPremiereDate, + StartIndex = request.StartIndex, + Limit = request.Limit - var pagedItems = ApplyPaging(itemsList, request.StartIndex, request.Limit); + }, user, parentIds); var options = GetDtoOptions(request); - var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray(); + var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray(); var result = new ItemsResult { - TotalRecordCount = itemsList.Count, + TotalRecordCount = itemsResult.TotalRecordCount, Items = returnItems }; diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index 7cc31ad7a..1176407ce 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -8,8 +8,10 @@ using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Net; namespace MediaBrowser.Common.Implementations.Security { @@ -219,10 +221,6 @@ namespace MediaBrowser.Common.Implementations.Security { SupporterKey = reg.key; } - else - { - throw new PaymentRequiredException(); - } } } @@ -231,10 +229,15 @@ namespace MediaBrowser.Common.Implementations.Security SaveAppStoreInfo(parameters); throw; } - catch (PaymentRequiredException) + catch (HttpException e) { - SaveAppStoreInfo(parameters); - throw; + _logger.ErrorException("Error registering appstore purchase {0}", e, parameters ?? "NO PARMS SENT"); + + if (e.StatusCode.HasValue && e.StatusCode.Value == HttpStatusCode.PaymentRequired) + { + throw new PaymentRequiredException(); + } + throw new ApplicationException("Error registering store sale"); } catch (Exception e) { diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 14f8c1617..10372eb49 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. protected override IEnumerable GetNonCachedChildren(IDirectoryService directoryService) { - return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren); + return base.GetNonCachedChildren(directoryService); } /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index fdf035e8d..f14e09616 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -639,7 +639,7 @@ namespace MediaBrowser.Controller.Entities /// /// The tags. public List Tags { get; set; } - + /// /// Gets or sets the home page URL. /// @@ -1898,5 +1898,24 @@ namespace MediaBrowser.Controller.Entities DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture) }; } + + public virtual IEnumerable GetAncestorIds() + { + return Parents.Select(i => i.Id).Concat(LibraryManager.GetCollectionFolders(this).Select(i => i.Id)); + } + + [IgnoreDataMember] + public virtual bool SupportsAncestors + { + get + { + return true; + } + } + + public virtual IEnumerable GetIdsForAncestorQuery() + { + return new[] { Id }; + } } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index fcbe54d05..e08eda1ac 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -149,7 +149,15 @@ namespace MediaBrowser.Controller.Entities await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + if (!EnableNewFolderQuerying()) + { + await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + } + } + + private static bool EnableNewFolderQuerying() + { + return ConfigurationManager.Configuration.MigrationVersion >= 1; } protected void AddChildrenInternal(IEnumerable children) @@ -222,7 +230,12 @@ namespace MediaBrowser.Controller.Entities item.SetParent(null); - return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken); + if (!EnableNewFolderQuerying()) + { + return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken); + } + + return Task.FromResult(true); } /// @@ -471,6 +484,7 @@ namespace MediaBrowser.Controller.Entities } else { + child.SetParent(this); newItems.Add(child); validChildren.Add(child); } @@ -478,6 +492,7 @@ namespace MediaBrowser.Controller.Entities else { // Brand new item - needs to be added + child.SetParent(this); newItems.Add(child); validChildren.Add(child); } @@ -506,7 +521,6 @@ namespace MediaBrowser.Controller.Entities } else { - await UpdateIsOffline(item, false).ConfigureAwait(false); actualRemovals.Add(item); } } @@ -517,6 +531,9 @@ namespace MediaBrowser.Controller.Entities foreach (var item in actualRemovals) { + item.SetParent(null); + item.IsOffline = false; + await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false); LibraryManager.ReportItemRemoved(item); } } @@ -525,7 +542,10 @@ namespace MediaBrowser.Controller.Entities AddChildrenInternal(newItems); - await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + if (!EnableNewFolderQuerying()) + { + await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); + } } } @@ -755,19 +775,16 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. protected IEnumerable GetCachedChildren() { - if (ConfigurationManager.Configuration.DisableStartupScan) + if (EnableNewFolderQuerying()) { - return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); - //return ItemRepository.GetItems(new InternalItemsQuery - //{ - // ParentId = Id + return ItemRepository.GetItemList(new InternalItemsQuery + { + ParentId = Id - //}).Items.Select(RetrieveChild).Where(i => i != null); - } - else - { - return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); + }).Select(RetrieveChild).Where(i => i != null); } + + return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); } private BaseItem RetrieveChild(BaseItem child) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 786c96d36..038a46316 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -102,7 +102,8 @@ namespace MediaBrowser.Controller.Entities public LocationType? LocationType { get; set; } public Guid? ParentId { get; set; } - + public string[] AncestorIds { get; set; } + public InternalItemsQuery() { Tags = new string[] { }; @@ -121,6 +122,7 @@ namespace MediaBrowser.Controller.Entities PersonIds = new string[] { }; ChannelIds = new string[] { }; ItemIds = new string[] { }; + AncestorIds = new string[] { }; } public InternalItemsQuery(User user) @@ -130,6 +132,8 @@ namespace MediaBrowser.Controller.Entities { var policy = user.Policy; MaxParentalRating = policy.MaxParentalRating; + + User = user; } } } diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 6c277da56..120a376d4 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -101,6 +101,15 @@ namespace MediaBrowser.Controller.Entities return false; } } + + [IgnoreDataMember] + public override bool SupportsAncestors + { + get + { + return false; + } + } } /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 92ca9e970..3d18b86df 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -265,6 +265,20 @@ namespace MediaBrowser.Controller.Entities.TV } } + public override IEnumerable GetAncestorIds() + { + var list = base.GetAncestorIds().ToList(); + + var seasonId = SeasonId; + + if (seasonId.HasValue && !list.Contains(seasonId.Value)) + { + list.Add(seasonId.Value); + } + + return list; + } + public override IEnumerable GetDeletePaths() { return new[] { Path }; diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 5ee49ae5a..76188ce58 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -24,6 +24,21 @@ namespace MediaBrowser.Controller.Entities { return true; } + + public override IEnumerable GetIdsForAncestorQuery() + { + var list = new List(); + + if (DisplayParentId != Guid.Empty) + { + list.Add(DisplayParentId); + } + else if (ParentId != Guid.Empty) + { + list.Add(ParentId); + } + return list; + } public override Task> GetItems(InternalItemsQuery query) { diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 96bb6e2b6..c24cf9bce 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -549,7 +549,17 @@ namespace MediaBrowser.Controller.Library /// /// The query. /// The user. + /// The parent ids. /// List<BaseItem>. - IEnumerable GetItems(InternalItemsQuery query, User user); + IEnumerable GetItems(InternalItemsQuery query, User user, IEnumerable parentIds); + + /// + /// Gets the items result. + /// + /// The query. + /// The user. + /// The parent ids. + /// QueryResult<BaseItem>. + QueryResult GetItemsResult(InternalItemsQuery query, User user, IEnumerable parentIds); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index aa1a3b9c2..55bc2269e 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -217,5 +217,14 @@ namespace MediaBrowser.Controller.LiveTv return base.SupportsPeople; } } + + [IgnoreDataMember] + public override bool SupportsAncestors + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 8fc0aedd3..0b1c9c3e0 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -176,6 +176,13 @@ namespace MediaBrowser.Controller.Persistence /// The query. /// QueryResult<Tuple<Guid, System.String>>. QueryResult> GetItemIdsWithPath(InternalItemsQuery query); + + /// + /// Gets the item list. + /// + /// The query. + /// List<BaseItem>. + IEnumerable GetItemList(InternalItemsQuery query); } } diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index a9ce5587d..ba50f2f32 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -481,23 +481,17 @@ namespace MediaBrowser.Dlna.ContentDirectory private QueryResult GetItemsFromPerson(Person person, User user, int? startIndex, int? limit) { - var itemsWithPerson = _libraryManager.GetItems(new InternalItemsQuery + var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user) { - Person = person.Name - - }).Items; - - var items = itemsWithPerson - .Where(i => i is Movie || i is Series || i is IChannelItem) - .Where(i => i.IsVisibleStandalone(user)) - .ToList(); + Person = person.Name, + IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(ChannelVideoItem).Name }, + SortBy = new[] { ItemSortBy.SortName }, + Limit = limit, + StartIndex = startIndex - items = _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) - .Skip(startIndex ?? 0) - .Take(limit ?? int.MaxValue) - .ToList(); + }, user, new string[] { }); - var serverItems = items.Select(i => new ServerItem + var serverItems = itemsResult.Items.Select(i => new ServerItem { Item = i, StubType = null @@ -506,7 +500,7 @@ namespace MediaBrowser.Dlna.ContentDirectory return new QueryResult { - TotalRecordCount = serverItems.Length, + TotalRecordCount = itemsResult.TotalRecordCount, Items = serverItems }; } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index e4c4e4762..ec024e87c 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Model.Configuration /// /// true if [enable high quality image scaling]; otherwise, false. public bool EnableHighQualityImageScaling { get; set; } - + /// /// Gets or sets the item by name path. /// @@ -234,12 +234,14 @@ namespace MediaBrowser.Model.Configuration public string[] Migrations { get; set; } + public int MigrationVersion { get; set; } + /// /// Initializes a new instance of the class. /// public ServerConfiguration() { - Migrations = new string[] {}; + Migrations = new string[] { }; ImageSavingConvention = ImageSavingConvention.Compatible; PublicPort = 8096; @@ -583,7 +585,8 @@ namespace MediaBrowser.Model.Configuration Limit = 0, Type = ImageType.Thumb } - } + }, + DisabledMetadataFetchers = new []{ "TheMovieDb" } } }; } diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs index 5c98e401f..4e742ca7a 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -40,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.Collections public Folder GetCollectionsFolder(string userId) { return _libraryManager.RootFolder.Children.OfType() + .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType() .FirstOrDefault(); } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index fcda802f4..8439f28f7 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -163,16 +163,11 @@ namespace MediaBrowser.Server.Implementations.Dto if (person != null) { - var items = _libraryManager.GetItems(new InternalItemsQuery + var items = _libraryManager.GetItems(new InternalItemsQuery(user) { Person = byName.Name - }).Items; - - if (user != null) - { - return items.Where(i => i.IsVisibleStandalone(user)).ToList(); - } + }, user, new string[] { }); return items.ToList(); } @@ -471,8 +466,7 @@ namespace MediaBrowser.Server.Implementations.Dto dto.ChildCount = GetChildCount(folder, user); // These are just far too slow. - // TODO: Disable for CollectionFolder - if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is IChannelItem)) + if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is IChannelItem) && !(folder is ICollectionFolder)) { SetSpecialCounts(folder, user, dto, fields, syncProgress); } @@ -1524,7 +1518,7 @@ namespace MediaBrowser.Server.Implementations.Dto } dto.ChannelId = item.ChannelId; - + var channelItem = item as IChannelItem; if (channelItem != null) { diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index ec94e16db..6310b61d1 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -83,13 +83,11 @@ namespace MediaBrowser.Server.Implementations.Intros if (config.EnableIntrosFromMoviesInLibrary) { - var inputItems = _libraryManager.GetItems(new InternalItemsQuery + var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user) { - IncludeItemTypes = new[] { typeof(Movie).Name }, + IncludeItemTypes = new[] { typeof(Movie).Name } - User = user - - }).Items; + }, user, new string[]{}); var itemsWithTrailers = inputItems .Where(i => diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index daa3d8ad4..522038b46 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -401,12 +401,12 @@ namespace MediaBrowser.Server.Implementations.Library { foreach (var path in item.GetDeletePaths().ToList()) { - if (_fileSystem.DirectoryExists(path)) + if (_fileSystem.DirectoryExists(path)) { _logger.Debug("Deleting path {0}", path); _fileSystem.DeleteDirectory(path, true); } - else if (_fileSystem.FileExists(path)) + else if (_fileSystem.FileExists(path)) { _logger.Debug("Deleting path {0}", path); _fileSystem.DeleteFile(path); @@ -697,7 +697,7 @@ namespace MediaBrowser.Server.Implementations.Library { var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath; - _fileSystem.CreateDirectory(rootFolderPath); + _fileSystem.CreateDirectory(rootFolderPath); var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)); @@ -727,6 +727,13 @@ namespace MediaBrowser.Server.Implementations.Library folder = dbItem; } + //if (folder.ParentId != rootFolder.Id) + //{ + // folder.ParentId = rootFolder.Id; + // var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); + // Task.WaitAll(task); + //} + rootFolder.AddVirtualChild(folder); RegisterItem(folder); @@ -748,7 +755,7 @@ namespace MediaBrowser.Server.Implementations.Library { var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - _fileSystem.CreateDirectory(userRootPath); + _fileSystem.CreateDirectory(userRootPath); var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; @@ -1000,9 +1007,9 @@ namespace MediaBrowser.Server.Implementations.Library private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable items) { - + } - + /// /// Validate and refresh the People sub-set of the IBN. /// The items are stored in the db but not loaded into memory until actually requested by an operation. @@ -1013,7 +1020,7 @@ namespace MediaBrowser.Server.Implementations.Library public Task ValidatePeople(CancellationToken cancellationToken, IProgress progress) { // Ensure the location is available. - _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); + _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress); } @@ -1280,9 +1287,29 @@ namespace MediaBrowser.Server.Implementations.Library return ItemRepository.GetItemIdsList(query); } - public IEnumerable GetItems(InternalItemsQuery query, User user) + public IEnumerable GetItems(InternalItemsQuery query, User user, IEnumerable parentIds) { - return GetItemIds(query).Select(GetItemById).Where(i => i.IsVisibleStandalone(user)); + var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList(); + + query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray(); + + var items = GetItemIds(query).Select(GetItemById); + + if (user != null) + { + items = items.Where(i => i.IsVisibleStandalone(user)); + } + + return items; + } + + public QueryResult GetItemsResult(InternalItemsQuery query, User user, IEnumerable parentIds) + { + var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList(); + + query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray(); + + return GetItems(query); } /// @@ -1700,7 +1727,7 @@ namespace MediaBrowser.Server.Implementations.Library if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase)) { - _fileSystem.CreateDirectory(path); + _fileSystem.CreateDirectory(path); item = new UserView { @@ -1719,8 +1746,7 @@ namespace MediaBrowser.Server.Implementations.Library if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) { - item.ViewType = viewType; - await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); + refresh = true; } if (!refresh) @@ -1793,7 +1819,7 @@ namespace MediaBrowser.Server.Implementations.Library if (item == null) { - _fileSystem.CreateDirectory(path); + _fileSystem.CreateDirectory(path); item = new UserView { @@ -1917,7 +1943,7 @@ namespace MediaBrowser.Server.Implementations.Library return item; } - + public async Task GetNamedView(string name, string parentId, string viewType, @@ -1946,7 +1972,7 @@ namespace MediaBrowser.Server.Implementations.Library if (item == null) { - _fileSystem.CreateDirectory(path); + _fileSystem.CreateDirectory(path); item = new UserView { @@ -2379,7 +2405,7 @@ namespace MediaBrowser.Server.Implementations.Library return ItemRepository.UpdatePeople(item.Id, people); } - private readonly SemaphoreSlim _dynamicImageResourcePool = new SemaphoreSlim(1,1); + private readonly SemaphoreSlim _dynamicImageResourcePool = new SemaphoreSlim(1, 1); public async Task ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex) { _logger.Debug("ConvertImageToLocal item {0}", item.Id); diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs index aee101ef4..3d2286e1f 100644 --- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs @@ -80,15 +80,13 @@ namespace MediaBrowser.Server.Implementations.Library { var genreList = genres.ToList(); - var inputItems = _libraryManager.GetItems(new InternalItemsQuery + var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Audio).Name }, - Genres = genreList.ToArray(), + Genres = genreList.ToArray() - User = user - - }).Items; + }, user, new string[] { }); var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 108a891e0..82e0f92e6 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -156,18 +156,18 @@ namespace MediaBrowser.Server.Implementations.Library } AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name); - + var mediaItems = _libraryManager.GetItems(new InternalItemsQuery(user) { NameContains = searchTerm, ExcludeItemTypes = excludeItemTypes.ToArray(), IncludeItemTypes = includeItemTypes.ToArray(), - Limit = (query.Limit.HasValue ? (int?)(query.Limit.Value * 3) : null), + Limit = (query.Limit.HasValue ? (int?)(query.Limit.Value * 2) : null), - }).Items; + }, user, new string[] { }); // Add search hints based on item name - hints.AddRange(mediaItems.Where(i => IncludeInSearch(i) && IsVisible(i, user)).Select(item => + hints.AddRange(mediaItems.Where(IncludeInSearch).Select(item => { var index = GetIndex(item.Name, searchTerm, terms); @@ -183,25 +183,6 @@ namespace MediaBrowser.Server.Implementations.Library return Task.FromResult(returnValue); } - private bool IsVisible(BaseItem item, User user) - { - if (user == null) - { - return true; - } - - if (item is IItemByName) - { - var dual = item as IHasDualAccess; - if (dual == null || dual.IsAccessedByName) - { - return true; - } - } - - return item.IsVisibleStandalone(user); - } - private bool IncludeInSearch(BaseItem item) { var episode = item as Episode; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index d7c9edae3..1b8966aa0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1357,7 +1357,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv await RefreshRecordings(cancellationToken).ConfigureAwait(false); - var internalQuery = new InternalItemsQuery + var internalQuery = new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name } }; @@ -1367,8 +1367,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv internalQuery.ChannelIds = new[] { query.ChannelId }; } - var queryResult = _libraryManager.GetItems(internalQuery); - IEnumerable recordings = queryResult.Items.Cast(); + var queryResult = _libraryManager.GetItems(internalQuery, user, new string[]{}); + IEnumerable recordings = queryResult.Cast(); if (!string.IsNullOrEmpty(query.Id)) { @@ -1405,12 +1405,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv .Where(i => _tvDtoService.GetInternalSeriesTimerId(i.ServiceName, i.SeriesTimerId) == guid); } - if (user != null) - { - var currentUser = user; - recordings = recordings.Where(i => i.IsParentalAllowed(currentUser)); - } - recordings = recordings.OrderByDescending(i => i.StartDate); var entityList = recordings.ToList(); @@ -1771,19 +1765,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv var now = DateTime.UtcNow; - var programs = _libraryManager.GetItems(new InternalItemsQuery + var programs = _libraryManager.GetItems(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, ChannelIds = new[] { id }, MaxStartDate = now, MinEndDate = now, - Limit = 1 + Limit = 1, + SortBy = new[] { "StartDate"} - }).Items.Cast(); + }, user, new string[]{}).Cast(); - var currentProgram = programs - .OrderBy(i => i.StartDate) - .FirstOrDefault(); + var currentProgram = programs.FirstOrDefault(); var dto = _tvDtoService.GetChannelInfoDto(channel, new DtoOptions(), currentProgram, user); @@ -1796,19 +1789,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv var now = DateTime.UtcNow; - var programs = _libraryManager.GetItems(new InternalItemsQuery + var programs = _libraryManager.GetItems(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, ChannelIds = new[] { channel.Id.ToString("N") }, MaxStartDate = now, MinEndDate = now, - Limit = 1 + Limit = 1, + SortBy = new[] { "StartDate" } - }).Items.Cast(); + }, user, new string []{}).Cast(); - var currentProgram = programs - .OrderBy(i => i.StartDate) - .FirstOrDefault(); + var currentProgram = programs.FirstOrDefault(); if (currentProgram != null) { diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 60b8c00bd..74688d9b1 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -24,6 +24,8 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; + public const int MigrationVersion = 1; + public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) { _libraryManager = libraryManager; @@ -121,6 +123,12 @@ namespace MediaBrowser.Server.Implementations.Persistence _config.SaveConfiguration(); } + if (_config.Configuration.MigrationVersion < MigrationVersion) + { + _config.Configuration.MigrationVersion = MigrationVersion; + _config.SaveConfiguration(); + } + progress.Report(100); } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 167c96185..20d890d02 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -77,7 +77,10 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteStreamsCommand; private IDbCommand _saveStreamCommand; - private const int LatestSchemaVersion = 17; + private IDbCommand _deleteAncestorsCommand; + private IDbCommand _saveAncestorCommand; + + private const int LatestSchemaVersion = 18; /// /// Initializes a new instance of the class. @@ -126,9 +129,13 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] queries = { - "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB)", + "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID)", "create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)", + "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", + "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, PRIMARY KEY (ItemId, AncestorId))", + "create index if not exists idx_AncestorIds on AncestorIds(ItemId,AncestorId)", + "create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))", "create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)", @@ -205,6 +212,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(_logger, "TypedBaseItems", "Studios", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "Audio", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text"); + _connection.AddColumn(_logger, "TypedBaseItems", "Tags", "Text"); PrepareStatements(); @@ -429,7 +437,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "LockedFields", "Studios", "Audio", - "ExternalServiceId" + "ExternalServiceId", + "Tags" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -472,6 +481,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType"); _savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder"); _savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder"); + + // Ancestors + _deleteAncestorsCommand = _connection.CreateCommand(); + _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; + _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id"); + + _saveAncestorCommand = _connection.CreateCommand(); + _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId) values (@ItemId, @AncestorId)"; + _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId"); + _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId"); // Chapters _deleteChaptersCommand = _connection.CreateCommand(); @@ -682,9 +701,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = null; } + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); + + if (item.SupportsAncestors) + { + UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction); + } } transaction.Commit(); @@ -765,22 +791,32 @@ namespace MediaBrowser.Server.Implementations.Persistence return null; } - BaseItem item; + BaseItem item = null; using (var stream = reader.GetMemoryStream(1)) { try { item = _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem; + } + catch (SerializationException ex) + { + _logger.ErrorException("Error deserializing item", ex); + } - if (item == null) + if (item == null) + { + try + { + item = Activator.CreateInstance(type) as BaseItem; + } + catch { - return null; } } - catch (SerializationException ex) + + if (item == null) { - _logger.ErrorException("Error deserializing item", ex); return null; } } @@ -1328,6 +1364,8 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId; + //_logger.Debug(cmd.CommandText); + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { while (reader.Read()) @@ -1373,6 +1411,50 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + public IEnumerable GetItemList(InternalItemsQuery query) + { + if (query == null) + { + throw new ArgumentNullException("query"); + } + + CheckDisposed(); + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems"; + + var whereClauses = GetWhereClauses(query, cmd, true); + + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + cmd.CommandText += whereText; + + cmd.CommandText += GetOrderByText(query); + + if (query.Limit.HasValue) + { + cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture); + } + + //_logger.Debug(cmd.CommandText); + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + var item = GetItem(reader); + if (item != null) + { + yield return item; + } + } + } + } + } + public QueryResult GetItems(InternalItemsQuery query) { if (query == null) @@ -1453,6 +1535,12 @@ namespace MediaBrowser.Server.Implementations.Persistence private string MapOrderByField(string name) { + if (string.Equals(name, "airtime", StringComparison.OrdinalIgnoreCase)) + { + // TODO + return "SortName"; + } + return name; } @@ -1813,6 +1901,17 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + if (query.AncestorIds.Length == 1) + { + whereClauses.Add("Guid in (select itemId from AncestorIds where AncestorId=@AncestorId)"); + cmd.Parameters.Add(cmd, "@AncestorId", DbType.Guid).Value = new Guid(query.AncestorIds[0]); + } + if (query.AncestorIds.Length > 1) + { + var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i + "'").ToArray()); + whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); + } + if (addPaging) { if (query.StartIndex.HasValue && query.StartIndex.Value > 0) @@ -1847,6 +1946,7 @@ namespace MediaBrowser.Server.Implementations.Persistence typeof(Movie), typeof(BoxSet), typeof(Episode), + typeof(ChannelVideoItem), typeof(Season), typeof(Series), typeof(Book), @@ -1933,6 +2033,11 @@ namespace MediaBrowser.Server.Implementations.Persistence _deleteStreamsCommand.GetParameter(0).Value = id; _deleteStreamsCommand.Transaction = transaction; _deleteStreamsCommand.ExecuteNonQuery(); + + // Delete ancestors + _deleteAncestorsCommand.GetParameter(0).Value = id; + _deleteAncestorsCommand.Transaction = transaction; + _deleteAncestorsCommand.ExecuteNonQuery(); // Delete the item _deleteItemCommand.GetParameter(0).Value = id; @@ -2167,6 +2272,37 @@ namespace MediaBrowser.Server.Implementations.Persistence return whereClauses; } + private void UpdateAncestors(Guid itemId, List ancestorIds, IDbTransaction transaction) + { + if (itemId == Guid.Empty) + { + throw new ArgumentNullException("itemId"); + } + + if (ancestorIds == null) + { + throw new ArgumentNullException("ancestorIds"); + } + + CheckDisposed(); + + // First delete + _deleteAncestorsCommand.GetParameter(0).Value = itemId; + _deleteAncestorsCommand.Transaction = transaction; + + _deleteAncestorsCommand.ExecuteNonQuery(); + + foreach (var ancestorId in ancestorIds) + { + _saveAncestorCommand.GetParameter(0).Value = itemId; + _saveAncestorCommand.GetParameter(1).Value = ancestorId; + + _saveAncestorCommand.Transaction = transaction; + + _saveAncestorCommand.ExecuteNonQuery(); + } + } + public async Task UpdatePeople(Guid itemId, List people) { if (itemId == Guid.Empty) diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs index d9b3ed755..048e2bf8d 100644 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs +++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs @@ -264,6 +264,7 @@ namespace MediaBrowser.Server.Implementations.Playlists public Folder GetPlaylistsFolder(string userId) { return _libraryManager.RootFolder.Children.OfType() + .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType() .FirstOrDefault(); } } diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index 93ebd0a1c..d913360f0 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -36,22 +36,12 @@ namespace MediaBrowser.Server.Implementations.TV ? new string[] { } : new[] { request.ParentId }; - IEnumerable items; - - if (parentIds.Length == 0) + var items = _libraryManager.GetItems(new InternalItemsQuery(user) { - items = _libraryManager.GetItems(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Series).Name }, - SortOrder = SortOrder.Ascending + IncludeItemTypes = new[] { typeof(Series).Name }, + SortOrder = SortOrder.Ascending - }, user).Cast(); - } - else - { - items = GetAllLibraryItems(user, parentIds, i => i is Series) - .Cast(); - } + }, user, parentIds).Cast(); // Avoid implicitly captured closure var episodes = GetNextUpEpisodes(request, user, items); @@ -68,9 +58,12 @@ namespace MediaBrowser.Server.Implementations.TV throw new ArgumentException("User not found"); } - var items = parentsFolders - .SelectMany(i => i.GetRecursiveChildren(user, s => s is Series)) - .Cast(); + var items = _libraryManager.GetItems(new InternalItemsQuery(user) + { + IncludeItemTypes = new[] { typeof(Series).Name }, + SortOrder = SortOrder.Ascending + + }, user, parentsFolders.Select(i => i.Id.ToString("N"))).Cast(); // Avoid implicitly captured closure var episodes = GetNextUpEpisodes(request, user, items); @@ -78,27 +71,6 @@ namespace MediaBrowser.Server.Implementations.TV return GetResult(episodes, null, request); } - private IEnumerable GetAllLibraryItems(User user, string[] parentIds, Func filter) - { - if (parentIds.Length > 0) - { - return parentIds.SelectMany(i => - { - var folder = (Folder)_libraryManager.GetItemById(new Guid(i)); - - return folder.GetRecursiveChildren(user, filter); - - }); - } - - if (user == null) - { - throw new ArgumentException("User not found"); - } - - return user.RootFolder.GetRecursiveChildren(user, filter); - } - public IEnumerable GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable series) { // Avoid implicitly captured closure diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 97a457a1b..694bd1b79 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -363,7 +363,7 @@ namespace MediaBrowser.Server.Startup.Common { var migrations = new List { - new Release5767(ServerConfigurationManager, TaskManager) + new DbMigration(ServerConfigurationManager, TaskManager) }; foreach (var task in migrations) diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index 13b782e40..b58646a2e 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -72,7 +72,7 @@ - + diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs new file mode 100644 index 000000000..de7cba68d --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.Server.Startup.Common.Migrations +{ + public class DbMigration : IVersionMigration + { + private readonly IServerConfigurationManager _config; + private readonly ITaskManager _taskManager; + + public DbMigration(IServerConfigurationManager config, ITaskManager taskManager) + { + _config = config; + _taskManager = taskManager; + } + + public void Run() + { + if (_config.Configuration.MigrationVersion < CleanDatabaseScheduledTask.MigrationVersion) + { + return; + } + + Task.Run(async () => + { + await Task.Delay(2000).ConfigureAwait(false); + + _taskManager.QueueScheduledTask(); + }); + } + } +} diff --git a/MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs b/MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs deleted file mode 100644 index 168230b87..000000000 --- a/MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Server.Implementations.LiveTv; -using MediaBrowser.Server.Implementations.Persistence; -using MediaBrowser.Server.Implementations.ScheduledTasks; - -namespace MediaBrowser.Server.Startup.Common.Migrations -{ - public class Release5767 : IVersionMigration - { - private readonly IServerConfigurationManager _config; - private readonly ITaskManager _taskManager; - - public Release5767(IServerConfigurationManager config, ITaskManager taskManager) - { - _config = config; - _taskManager = taskManager; - } - - public async void Run() - { - var name = "5767.1"; - - if (_config.Configuration.Migrations.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - return; - } - - Task.Run(async () => - { - await Task.Delay(3000).ConfigureAwait(false); - - _taskManager.QueueScheduledTask(); - }); - - // Wait a few minutes before marking this as done. Make sure the server doesn't get restarted. - await Task.Delay(300000).ConfigureAwait(false); - - var list = _config.Configuration.Migrations.ToList(); - list.Add(name); - _config.Configuration.Migrations = list.ToArray(); - _config.SaveConfiguration(); - } - } -} -- cgit v1.2.3 From 67dc2a0bf98cf02c1ff07608c0f10b4e0ead6f58 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 29 Oct 2015 15:01:04 -0400 Subject: update item queries --- MediaBrowser.Api/TvShowsService.cs | 2 +- .../Entities/InternalItemsQuery.cs | 5 +- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- .../LiveTv/LiveTvAudioRecording.cs | 5 ++ .../LiveTv/LiveTvVideoRecording.cs | 5 ++ .../ContentDirectory/ControlHandler.cs | 2 +- .../Library/LibraryManager.cs | 13 ++- .../Library/UserViewManager.cs | 93 ++++------------------ .../Persistence/CleanDatabaseScheduledTask.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 28 ++++++- 10 files changed, 70 insertions(+), 87 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index ead232888..2dad9533f 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -286,7 +286,7 @@ namespace MediaBrowser.Api StartIndex = request.StartIndex, Limit = request.Limit - }, user, parentIds); + }, parentIds); var options = GetDtoOptions(request); diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 038a46316..5c60e19f0 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -103,7 +103,9 @@ namespace MediaBrowser.Controller.Entities public Guid? ParentId { get; set; } public string[] AncestorIds { get; set; } - + + public LocationType[] ExcludeLocationTypes { get; set; } + public InternalItemsQuery() { Tags = new string[] { }; @@ -123,6 +125,7 @@ namespace MediaBrowser.Controller.Entities ChannelIds = new string[] { }; ItemIds = new string[] { }; AncestorIds = new string[] { }; + ExcludeLocationTypes = new LocationType[] { }; } public InternalItemsQuery(User user) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index c24cf9bce..9e434541a 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -560,6 +560,6 @@ namespace MediaBrowser.Controller.Library /// The user. /// The parent ids. /// QueryResult<BaseItem>. - QueryResult GetItemsResult(InternalItemsQuery query, User user, IEnumerable parentIds); + QueryResult GetItemsResult(InternalItemsQuery query, IEnumerable parentIds); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index dd6a53d45..f1634a8a5 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -139,5 +139,10 @@ namespace MediaBrowser.Controller.LiveTv return list; } + + public override bool IsVisibleStandalone(User user) + { + return IsVisible(user); + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index de8764e6d..96a465201 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -149,5 +149,10 @@ namespace MediaBrowser.Controller.LiveTv return list; } + + public override bool IsVisibleStandalone(User user) + { + return IsVisible(user); + } } } diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index ba50f2f32..c70014cb6 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -489,7 +489,7 @@ namespace MediaBrowser.Dlna.ContentDirectory Limit = limit, StartIndex = startIndex - }, user, new string[] { }); + }, new string[] { }); var serverItems = itemsResult.Items.Select(i => new ServerItem { diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 522038b46..f24edf086 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1297,21 +1297,32 @@ namespace MediaBrowser.Server.Implementations.Library if (user != null) { + AddUserToQuery(query, user); items = items.Where(i => i.IsVisibleStandalone(user)); } return items; } - public QueryResult GetItemsResult(InternalItemsQuery query, User user, IEnumerable parentIds) + public QueryResult GetItemsResult(InternalItemsQuery query, IEnumerable parentIds) { var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList(); query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray(); + if (query.User != null) + { + AddUserToQuery(query, query.User); + } + return GetItems(query); } + private void AddUserToQuery(InternalItemsQuery query, User user) + { + + } + /// /// Gets the intros. /// diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index c2938475c..177d82b22 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -245,16 +245,8 @@ namespace MediaBrowser.Server.Implementations.Library var currentUser = user; - Func filter = i => + var libraryItems = GetItemsForLatestItems(user, request.ParentId, includeTypes).Where(i => { - if (includeTypes.Length > 0) - { - if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase)) - { - return false; - } - } - if (request.IsPlayed.HasValue) { var val = request.IsPlayed.Value; @@ -264,29 +256,12 @@ namespace MediaBrowser.Server.Implementations.Library } } - return i.LocationType != LocationType.Virtual && !i.IsFolder; - }; - - // Avoid implicitly captured closure - var libraryItems = string.IsNullOrEmpty(request.ParentId) && user != null ? - GetItemsConfiguredForLatest(user, filter) : - GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, filter); - - libraryItems = libraryItems.OrderByDescending(i => i.DateCreated); - - if (request.IsPlayed.HasValue) - { - var takeLimit = (request.Limit ?? 20) * 20; - libraryItems = libraryItems.Take(takeLimit); - } - - // Avoid implicitly captured closure - var items = libraryItems - .ToList(); + return true; + }); var list = new List>>(); - foreach (var item in items) + foreach (var item in libraryItems) { // Only grab the index container for media var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer; @@ -318,59 +293,23 @@ namespace MediaBrowser.Server.Implementations.Library return list; } - protected IList GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func filter) + private IEnumerable GetItemsForLatestItems(User user, string parentId, string[] includeItemTypes) { - if (!string.IsNullOrEmpty(parentId)) - { - var folder = (Folder)libraryManager.GetItemById(new Guid(parentId)); - - if (!string.IsNullOrWhiteSpace(userId)) - { - var user = userManager.GetUserById(userId); + var parentIds = string.IsNullOrEmpty(parentId) + ? new string[] { } + : new[] { parentId }; - if (user == null) - { - throw new ArgumentException("User not found"); - } - - return folder - .GetRecursiveChildren(user, filter) - .ToList(); - } - - return folder - .GetRecursiveChildren(filter); - } - if (!string.IsNullOrWhiteSpace(userId)) + return _libraryManager.GetItems(new InternalItemsQuery(user) { - var user = userManager.GetUserById(userId); - - if (user == null) - { - throw new ArgumentException("User not found"); - } + IncludeItemTypes = includeItemTypes, + SortOrder = SortOrder.Descending, + SortBy = new[] { ItemSortBy.DateCreated }, + IsFolder = false, + ExcludeItemTypes = new[] { "ChannelItem", "Recording" }, + ExcludeLocationTypes = new[] { LocationType.Virtual } - return user - .RootFolder - .GetRecursiveChildren(user, filter) - .ToList(); - } - - return libraryManager - .RootFolder - .GetRecursiveChildren(filter); - } + }, user, parentIds); - private IEnumerable GetItemsConfiguredForLatest(User user, Func filter) - { - // Avoid implicitly captured closure - var currentUser = user; - - return user.RootFolder.GetChildren(user, true) - .OfType() - .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N"))) - .SelectMany(i => i.GetRecursiveChildren(currentUser, filter)) - .DistinctBy(i => i.Id); } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 74688d9b1..aef2157c3 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - public const int MigrationVersion = 1; + public const int MigrationVersion = 2; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 20d890d02..4d86330e5 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteAncestorsCommand; private IDbCommand _saveAncestorCommand; - private const int LatestSchemaVersion = 18; + private const int LatestSchemaVersion = 19; /// /// Initializes a new instance of the class. @@ -213,6 +213,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(_logger, "TypedBaseItems", "Audio", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "Tags", "Text"); + _connection.AddColumn(_logger, "TypedBaseItems", "IsFolder", "BIT"); PrepareStatements(); @@ -438,7 +439,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "Studios", "Audio", "ExternalServiceId", - "Tags" + "Tags", + "IsFolder" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -702,7 +704,8 @@ namespace MediaBrowser.Server.Implementations.Persistence } _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); - + _saveItemCommand.GetParameter(index++).Value = item.IsFolder; + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1576,7 +1579,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _logger.Debug(cmd.CommandText); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { while (reader.Read()) { @@ -1760,6 +1763,11 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add("IsSports=@IsSports"); cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports; } + if (query.IsFolder.HasValue) + { + whereClauses.Add("IsFolder=@IsFolder"); + cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder; + } var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); if (includeTypes.Length == 1) @@ -1911,6 +1919,17 @@ namespace MediaBrowser.Server.Implementations.Persistence var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i + "'").ToArray()); whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); } + if (query.ExcludeLocationTypes.Length == 1) + { + whereClauses.Add("LocationType<>@LocationType"); + cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.ExcludeLocationTypes[0].ToString(); + } + if (query.ExcludeLocationTypes.Length > 1) + { + var val = string.Join(",", query.ExcludeLocationTypes.Select(i => "'" + i + "'").ToArray()); + + whereClauses.Add("LocationType not in (" + val + ")"); + } if (addPaging) { @@ -1976,6 +1995,7 @@ namespace MediaBrowser.Server.Implementations.Persistence dict[t.Name] = new[] { t.FullName }; } + dict["ChannelItem"] = new[] { typeof(ChannelVideoItem).FullName, typeof(ChannelAudioItem).FullName, typeof(ChannelFolderItem).FullName }; dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName }; dict["Program"] = new[] { typeof(LiveTvProgram).FullName }; dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName }; -- cgit v1.2.3 From bed740668c4d9e7de1473925c7d6a1e33346bc22 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 30 Oct 2015 12:40:47 -0400 Subject: update special folders --- MediaBrowser.Controller/Entities/AggregateFolder.cs | 2 +- MediaBrowser.Controller/Entities/UserRootFolder.cs | 7 ++++++- .../Library/LibraryManager.cs | 12 ++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 10372eb49..14f8c1617 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. protected override IEnumerable GetNonCachedChildren(IDirectoryService directoryService) { - return base.GetNonCachedChildren(directoryService); + return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren); } /// diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index a78beb645..e6f322595 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -55,13 +55,18 @@ namespace MediaBrowser.Controller.Entities } } + protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user) + { + return base.GetEligibleChildrenForRecursiveChildren(user).Concat(LibraryManager.RootFolder.VirtualChildren); + } + /// /// Get the children of this folder from the actual file system /// /// IEnumerable{BaseItem}. protected override IEnumerable GetNonCachedChildren(IDirectoryService directoryService) { - return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren); + return base.GetNonCachedChildren(directoryService); } public override bool BeforeMetadataRefresh() diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index f24edf086..b5f1c2132 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -727,12 +727,12 @@ namespace MediaBrowser.Server.Implementations.Library folder = dbItem; } - //if (folder.ParentId != rootFolder.Id) - //{ - // folder.ParentId = rootFolder.Id; - // var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); - // Task.WaitAll(task); - //} + if (folder.ParentId != rootFolder.Id) + { + folder.ParentId = rootFolder.Id; + var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); + Task.WaitAll(task); + } rootFolder.AddVirtualChild(folder); -- cgit v1.2.3 From fbf8d27637a0b3804cf31665425be372420097a5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 2 Nov 2015 12:25:01 -0500 Subject: update channel db --- MediaBrowser.Api/UserLibrary/UserViewsService.cs | 5 +- MediaBrowser.Controller/Entities/BaseItem.cs | 17 +++ MediaBrowser.Controller/Entities/Folder.cs | 41 +++-- MediaBrowser.Controller/Entities/UserView.cs | 12 +- .../Entities/UserViewBuilder.cs | 8 +- .../Persistence/IItemRepository.cs | 7 + .../MediaBrowser.LocalMetadata.csproj | 3 - .../Parsers/GameXmlParser.cs | 20 --- .../Savers/EpisodeXmlSaver.cs | 166 --------------------- MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs | 14 -- MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs | 147 ------------------ .../Savers/SeriesXmlSaver.cs | 154 ------------------- .../Configuration/UserConfiguration.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 9 ++ MediaBrowser.Model/Dto/BaseItemDto.cs | 6 - MediaBrowser.Model/Dto/IItemDto.cs | 6 - MediaBrowser.Model/Dto/UserDto.cs | 6 - MediaBrowser.Model/Entities/MetadataProviders.cs | 2 - MediaBrowser.Model/LiveTv/ChannelInfoDto.cs | 6 - MediaBrowser.Model/Querying/ItemFields.cs | 5 - .../Channels/ChannelManager.cs | 17 ++- .../Dto/DtoService.cs | 21 +-- .../Library/LibraryManager.cs | 16 +- .../Library/MediaSourceManager.cs | 2 +- .../Library/SearchEngine.cs | 2 +- .../Library/UserViewManager.cs | 44 +++--- .../Persistence/CleanDatabaseScheduledTask.cs | 4 +- .../Persistence/SqliteItemRepository.cs | 93 ++++++++++-- .../Sync/SyncManager.cs | 1 - .../ApplicationHost.cs | 14 +- .../Migrations/DbMigration.cs | 14 +- SharedVersion.cs | 4 +- 32 files changed, 224 insertions(+), 644 deletions(-) delete mode 100644 MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs delete mode 100644 MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs delete mode 100644 MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index 9d7c38d6f..6ba30a35e 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -78,6 +78,7 @@ namespace MediaBrowser.Api.UserLibrary var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false); var dtoOptions = GetDtoOptions(request); + dtoOptions.Fields = new List(); var user = _userManager.GetUserById(request.UserId); @@ -141,9 +142,7 @@ namespace MediaBrowser.Api.UserLibrary private bool IsEligibleForSpecialView(ICollectionFolder view) { - var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos }; - - return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return UserView.IsEligibleForEnhancedView(view.CollectionType); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f14e09616..798f1b7bb 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1153,6 +1153,23 @@ namespace MediaBrowser.Controller.Entities } public int? GetParentalRatingValue() + { + var rating = CustomRating; + + if (string.IsNullOrWhiteSpace(rating)) + { + rating = OfficialRating; + } + + if (string.IsNullOrWhiteSpace(rating)) + { + return null; + } + + return LocalizationManager.GetRatingLevel(rating); + } + + public int? GetInheritedParentalRatingValue() { var rating = CustomRatingForComparison; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index e08eda1ac..4b30e845b 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -468,34 +468,25 @@ namespace MediaBrowser.Controller.Entities { BaseItem currentChild; - if (currentChildren.TryGetValue(child.Id, out currentChild)) + if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child)) { - if (IsValidFromResolver(currentChild, child)) + var currentChildLocationType = currentChild.LocationType; + if (currentChildLocationType != LocationType.Remote && + currentChildLocationType != LocationType.Virtual) { - var currentChildLocationType = currentChild.LocationType; - if (currentChildLocationType != LocationType.Remote && - currentChildLocationType != LocationType.Virtual) - { - currentChild.DateModified = child.DateModified; - } - - await UpdateIsOffline(currentChild, false).ConfigureAwait(false); - validChildren.Add(currentChild); - } - else - { - child.SetParent(this); - newItems.Add(child); - validChildren.Add(child); + currentChild.DateModified = child.DateModified; } + + await UpdateIsOffline(currentChild, false).ConfigureAwait(false); + validChildren.Add(currentChild); + + continue; } - else - { - // Brand new item - needs to be added - child.SetParent(this); - newItems.Add(child); - validChildren.Add(child); - } + + // Brand new item - needs to be added + child.SetParent(this); + newItems.Add(child); + validChildren.Add(child); } // If any items were added or removed.... @@ -531,6 +522,8 @@ namespace MediaBrowser.Controller.Entities foreach (var item in actualRemovals) { + Logger.Debug("Removed item: " + item.Path); + item.SetParent(null); item.IsOffline = false; await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 76188ce58..4e3b58778 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Threading.Tasks; +using System.Linq; namespace MediaBrowser.Controller.Entities { @@ -105,7 +106,9 @@ namespace MediaBrowser.Controller.Entities CollectionType.Photos, CollectionType.Playlists, CollectionType.BoxSets, - CollectionType.MusicVideos + CollectionType.MusicVideos, + CollectionType.Games, + CollectionType.Music }; var collectionFolder = folder as ICollectionFolder; @@ -136,6 +139,13 @@ namespace MediaBrowser.Controller.Entities return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty); } + public static bool IsEligibleForEnhancedView(string viewType) + { + var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music }; + + return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + } + [IgnoreDataMember] public override bool SupportsPeople { diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index f5800ce81..ed81e2d73 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -120,26 +120,22 @@ namespace MediaBrowser.Controller.Entities return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false); } + case CollectionType.Photos: case CollectionType.Books: case CollectionType.HomeVideos: + case CollectionType.Games: case CollectionType.MusicVideos: return GetResult(queryParent.GetChildren(user, true), queryParent, query); case CollectionType.Folders: return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); - case CollectionType.Games: - return await GetGameView(user, queryParent, query).ConfigureAwait(false); - case CollectionType.Playlists: return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false); case CollectionType.BoxSets: return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false); - case CollectionType.Photos: - return await GetPhotosView(queryParent, user, query).ConfigureAwait(false); - case CollectionType.TvShows: return await GetTvView(queryParent, user, query).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 0b1c9c3e0..533d66b95 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -183,6 +183,13 @@ namespace MediaBrowser.Controller.Persistence /// The query. /// List<BaseItem>. IEnumerable GetItemList(InternalItemsQuery query); + + /// + /// Updates the inherited values. + /// + /// The cancellation token. + /// Task. + Task UpdateInheritedValues(CancellationToken cancellationToken); } } diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index a74fe7e98..5ef8eaaa3 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -79,14 +79,11 @@ - - - diff --git a/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs index b5a68c61f..4bfcae44f 100644 --- a/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs @@ -62,26 +62,6 @@ namespace MediaBrowser.LocalMetadata.Parsers break; } - case "NesBox": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.SetProviderId(MetadataProviders.NesBox, val); - } - break; - } - - case "NesBoxRom": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.SetProviderId(MetadataProviders.NesBoxRom, val); - } - break; - } - case "Players": { var val = reader.ReadElementContentAsString(); diff --git a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs deleted file mode 100644 index dc8a16cd8..000000000 --- a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs +++ /dev/null @@ -1,166 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.LocalMetadata.Savers -{ - public class EpisodeXmlProvider : IMetadataFileSaver, IConfigurableProvider - { - private readonly IItemRepository _itemRepository; - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private IFileSystem _fileSystem; - - public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem) - { - _itemRepository = itemRepository; - _config = config; - _libraryManager = libraryManager; - _fileSystem = fileSystem; - } - - /// - /// Determines whether [is enabled for] [the specified item]. - /// - /// The item. - /// Type of the update. - /// true if [is enabled for] [the specified item]; otherwise, false. - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is Episode && updateType >= ItemUpdateType.MetadataDownload; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - public bool IsEnabled - { - get { return !_config.Configuration.DisableXmlSavers; } - } - - /// - /// Saves the specified item. - /// - /// The item. - /// The cancellation token. - /// Task. - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var episode = (Episode)item; - - var builder = new StringBuilder(); - - builder.Append(""); - - if (!string.IsNullOrEmpty(item.Name)) - { - builder.Append("" + SecurityElement.Escape(episode.Name) + ""); - } - - if (episode.IndexNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.IndexNumberEnd.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + ""); - } - - if (episode.AirsAfterSeasonNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + ""); - } - if (episode.AirsBeforeEpisodeNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + ""); - } - if (episode.AirsBeforeSeasonNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.ParentIndexNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.AbsoluteEpisodeNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.DvdEpisodeNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.DvdSeasonNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.PremiereDate.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + ""); - } - - XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder); - XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository); - - builder.Append(""); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List - { - "FirstAired", - "SeasonNumber", - "EpisodeNumber", - "EpisodeName", - "EpisodeNumberEnd", - "airsafter_season", - "airsbefore_episode", - "airsbefore_season", - "DVD_episodenumber", - "DVD_season", - "absolute_number" - - }, _config, _fileSystem); - } - - /// - /// Gets the save path. - /// - /// The item. - /// System.String. - public string GetSavePath(IHasMetadata item) - { - var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml"); - - return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename); - } - } -} diff --git a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs index 89c274e12..53efc7811 100644 --- a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs @@ -79,20 +79,6 @@ namespace MediaBrowser.LocalMetadata.Savers builder.Append("" + SecurityElement.Escape(game.GameSystem) + ""); } - var val = game.GetProviderId(MetadataProviders.NesBox); - - if (!string.IsNullOrEmpty(val)) - { - builder.Append("" + SecurityElement.Escape(val) + ""); - } - - val = game.GetProviderId(MetadataProviders.NesBoxRom); - - if (!string.IsNullOrEmpty(val)) - { - builder.Append("" + SecurityElement.Escape(val) + ""); - } - XmlSaverHelpers.AddCommonNodes(game, _libraryManager, builder); builder.Append(""); diff --git a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs deleted file mode 100644 index 2e3e7aaa1..000000000 --- a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs +++ /dev/null @@ -1,147 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using System.Collections.Generic; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.LocalMetadata.Savers -{ - /// - /// Saves movie.xml for movies, trailers and music videos - /// - public class MovieXmlProvider : IMetadataFileSaver, IConfigurableProvider - { - private readonly IItemRepository _itemRepository; - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private IFileSystem _fileSystem; - - public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem) - { - _itemRepository = itemRepository; - _config = config; - _libraryManager = libraryManager; - _fileSystem = fileSystem; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - public bool IsEnabled - { - get { return !_config.Configuration.DisableXmlSavers; } - } - - /// - /// Determines whether [is enabled for] [the specified item]. - /// - /// The item. - /// Type of the update. - /// true if [is enabled for] [the specified item]; otherwise, false. - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - var video = item as Video; - - // Check parent for null to avoid running this against things like video backdrops - if (video != null && !(item is Episode) && !video.IsOwnedItem) - { - return updateType >= ItemUpdateType.MetadataDownload; - } - - return false; - } - - /// - /// Saves the specified item. - /// - /// The item. - /// The cancellation token. - /// Task. - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var video = (Video)item; - - var builder = new StringBuilder(); - - builder.Append(""); - - XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder); - - var musicVideo = item as MusicVideo; - - if (musicVideo != null) - { - if (musicVideo.Artists.Count > 0) - { - builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>"); - } - if (!string.IsNullOrEmpty(musicVideo.Album)) - { - builder.Append("<Album>" + SecurityElement.Escape(musicVideo.Album) + "</Album>"); - } - } - - var movie = item as Movie; - - if (movie != null) - { - if (!string.IsNullOrEmpty(movie.TmdbCollectionName)) - { - builder.Append("<TmdbCollectionName>" + SecurityElement.Escape(movie.TmdbCollectionName) + "</TmdbCollectionName>"); - } - } - - XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository); - - builder.Append(""); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List - { - // Deprecated. No longer saving in this field. - "IMDBrating", - - // Deprecated. No longer saving in this field. - "Description", - - "Artist", - "Album", - "TmdbCollectionName" - }, _config, _fileSystem); - } - - public string GetSavePath(IHasMetadata item) - { - return GetMovieSavePath((Video)item); - } - - public static string GetMovieSavePath(Video item) - { - if (item.IsInMixedFolder) - { - return Path.ChangeExtension(item.Path, ".xml"); - } - - return Path.Combine(item.ContainingFolderPath, "movie.xml"); - } - } -} diff --git a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs deleted file mode 100644 index 9806c4216..000000000 --- a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs +++ /dev/null @@ -1,154 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.LocalMetadata.Savers -{ - public class SeriesXmlProvider : IMetadataFileSaver, IConfigurableProvider - { - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private IFileSystem _fileSystem; - - public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem) - { - _config = config; - _libraryManager = libraryManager; - _fileSystem = fileSystem; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - /// - /// Determines whether [is enabled for] [the specified item]. - /// - /// The item. - /// Type of the update. - /// true if [is enabled for] [the specified item]; otherwise, false. - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is Series && updateType >= ItemUpdateType.MetadataDownload; - } - - public bool IsEnabled - { - get { return !_config.Configuration.DisableXmlSavers; } - } - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - /// - /// Saves the specified item. - /// - /// The item. - /// The cancellation token. - /// Task. - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var series = (Series)item; - - var builder = new StringBuilder(); - - builder.Append(""); - - var tvdb = item.GetProviderId(MetadataProviders.Tvdb); - - if (!string.IsNullOrEmpty(tvdb)) - { - builder.Append("" + SecurityElement.Escape(tvdb) + ""); - } - - if (series.Status.HasValue) - { - builder.Append("" + SecurityElement.Escape(series.Status.Value.ToString()) + ""); - } - - if (series.Studios.Count > 0) - { - builder.Append("" + SecurityElement.Escape(series.Studios[0]) + ""); - } - - if (!string.IsNullOrEmpty(series.AirTime)) - { - builder.Append("" + SecurityElement.Escape(series.AirTime) + ""); - } - - if (series.AirDays != null) - { - if (series.AirDays.Count == 7) - { - builder.Append("" + SecurityElement.Escape("Daily") + ""); - } - else if (series.AirDays.Count > 0) - { - builder.Append("" + SecurityElement.Escape(series.AirDays[0].ToString()) + ""); - } - } - - if (series.PremiereDate.HasValue) - { - builder.Append("" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + ""); - } - - if (series.AnimeSeriesIndex.HasValue) - { - builder.Append("" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + ""); - } - - XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder); - - builder.Append(""); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List - { - "id", - "Status", - "Network", - "Airs_Time", - "Airs_DayOfWeek", - "FirstAired", - - // Don't preserve old series node - "Series", - - "SeriesName", - - // Deprecated. No longer saving in this field. - "AnimeSeriesIndex" - }, _config, _fileSystem); - } - - /// - /// Gets the save path. - /// - /// The item. - /// System.String. - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "series.xml"); - } - } -} diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 349780958..278d22cfb 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -63,9 +63,9 @@ namespace MediaBrowser.Model.Configuration LatestItemsExcludes = new string[] { }; OrderedViews = new string[] { }; DisplayChannelsWithinViews = new string[] { }; + DisplayChannelsInline = true; PlainFolderViews = new string[] { }; - DisplayCollectionsView = true; IncludeTrailersInSuggestions = true; EnableCinemaMode = true; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 1834e24fe..d451fe8a0 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -525,6 +525,15 @@ namespace MediaBrowser.Model.Dlna bool isEligibleForDirectPlay, bool isEligibleForDirectStream) { + if (videoStream == null) + { + _logger.Info("Profile: {0}, Cannot direct stream with no known video stream. Path: {1}", + profile.Name ?? "Unknown Profile", + mediaSource.Path ?? "Unknown path"); + + return null; + } + // See if it can be direct played DirectPlayProfile directPlay = null; foreach (DirectPlayProfile i in profile.DirectPlayProfiles) diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index ff67db1b6..91beba726 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -530,12 +530,6 @@ namespace MediaBrowser.Model.Dto /// The primary image aspect ratio. public double? PrimaryImageAspectRatio { get; set; } - /// - /// Gets or sets the primary image aspect ratio, before image enhancements. - /// - /// The original primary image aspect ratio. - public double? OriginalPrimaryImageAspectRatio { get; set; } - /// /// Gets or sets the artists. /// diff --git a/MediaBrowser.Model/Dto/IItemDto.cs b/MediaBrowser.Model/Dto/IItemDto.cs index af46d29b9..3e7d1c608 100644 --- a/MediaBrowser.Model/Dto/IItemDto.cs +++ b/MediaBrowser.Model/Dto/IItemDto.cs @@ -11,11 +11,5 @@ namespace MediaBrowser.Model.Dto /// /// The primary image aspect ratio. double? PrimaryImageAspectRatio { get; set; } - - /// - /// Gets or sets the original primary image aspect ratio. - /// - /// The original primary image aspect ratio. - double? OriginalPrimaryImageAspectRatio { get; set; } } } diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index fc5d2f134..f133f3343 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -122,12 +122,6 @@ namespace MediaBrowser.Model.Dto /// The primary image aspect ratio. public double? PrimaryImageAspectRatio { get; set; } - /// - /// Gets or sets the original primary image aspect ratio. - /// - /// The original primary image aspect ratio. - public double? OriginalPrimaryImageAspectRatio { get; set; } - /// /// Gets a value indicating whether this instance has primary image. /// diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs index 7644b150a..f5ab0c1d4 100644 --- a/MediaBrowser.Model/Entities/MetadataProviders.cs +++ b/MediaBrowser.Model/Entities/MetadataProviders.cs @@ -36,8 +36,6 @@ namespace MediaBrowser.Model.Entities MusicBrainzArtist = 10, MusicBrainzReleaseGroup = 11, Zap2It = 12, - NesBox = 13, - NesBoxRom = 14, TvRage = 15, AudioDbArtist = 16, AudioDbAlbum = 17, diff --git a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs index fd901f29e..91493def8 100644 --- a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs @@ -105,12 +105,6 @@ namespace MediaBrowser.Model.LiveTv /// The primary image aspect ratio. public double? PrimaryImageAspectRatio { get; set; } - /// - /// Gets or sets the primary image aspect ratio, before image enhancements. - /// - /// The original primary image aspect ratio. - public double? OriginalPrimaryImageAspectRatio { get; set; } - /// /// Gets a value indicating whether this instance has primary image. /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index eea561f72..e8b1414b7 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -165,11 +165,6 @@ /// PrimaryImageAspectRatio, - /// - /// The original primary image aspect ratio - /// - OriginalPrimaryImageAspectRatio, - /// /// The revenue /// diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index ba759dcb9..6af0fb691 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -408,6 +408,9 @@ namespace MediaBrowser.Server.Implementations.Channels private async Task GetChannel(IChannel channelInfo, CancellationToken cancellationToken) { + var parentFolder = await GetInternalChannelFolder(cancellationToken).ConfigureAwait(false); + var parentFolderId = parentFolder.Id; + var id = GetInternalChannelId(channelInfo.Name); var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id); @@ -450,6 +453,13 @@ namespace MediaBrowser.Server.Implementations.Channels { isNew = true; } + item.ChannelId = channelId; + + if (item.ParentId != parentFolderId) + { + isNew = true; + } + item.ParentId = parentFolderId; item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating); item.Overview = channelInfo.Description; @@ -1254,7 +1264,6 @@ namespace MediaBrowser.Server.Implementations.Channels item.ProductionYear = info.ProductionYear; item.ProviderIds = info.ProviderIds; item.OfficialRating = info.OfficialRating; - item.DateCreated = info.DateCreated ?? DateTime.UtcNow; } @@ -1262,6 +1271,12 @@ namespace MediaBrowser.Server.Implementations.Channels channelItem.ChannelId = internalChannelId.ToString("N"); + if (item.ParentId != internalChannelId) + { + isNew = true; + } + item.ParentId = internalChannelId; + if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase)) { isNew = true; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 8439f28f7..dfe02d7a1 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -463,12 +463,15 @@ namespace MediaBrowser.Server.Implementations.Dto var folder = (Folder)item; - dto.ChildCount = GetChildCount(folder, user); - - // These are just far too slow. - if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is IChannelItem) && !(folder is ICollectionFolder)) + if (!(folder is IChannelItem) && !(folder is Channel)) { - SetSpecialCounts(folder, user, dto, fields, syncProgress); + dto.ChildCount = GetChildCount(folder, user); + + // These are just far too slow. + if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is ICollectionFolder)) + { + SetSpecialCounts(folder, user, dto, fields, syncProgress); + } } dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100; @@ -1763,14 +1766,6 @@ namespace MediaBrowser.Server.Implementations.Dto return; } - if (fields.Contains(ItemFields.OriginalPrimaryImageAspectRatio)) - { - if (size.Width > 0 && size.Height > 0) - { - dto.OriginalPrimaryImageAspectRatio = size.Width / size.Height; - } - } - var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList(); foreach (var enhancer in supportedEnhancers) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index b5f1c2132..3920d6171 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1293,14 +1293,13 @@ namespace MediaBrowser.Server.Implementations.Library query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray(); - var items = GetItemIds(query).Select(GetItemById); - if (user != null) { AddUserToQuery(query, user); - items = items.Where(i => i.IsVisibleStandalone(user)); } + var items = GetItemIds(query).Select(GetItemById); + return items; } @@ -1320,7 +1319,16 @@ namespace MediaBrowser.Server.Implementations.Library private void AddUserToQuery(InternalItemsQuery query, User user) { - + if (query.AncestorIds.Length == 0) + { + // Need to filter on user folders + } + + query.MaxParentalRating = user.Policy.MaxParentalRating; + + // handle blocking by tags + + // handle unrated filter } /// diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 9694965c7..99eeb625c 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Server.Implementations.Library return 10000000; } - return 2000000; + return 4000000; } private IEnumerable GetMediaStreamsForItem(IEnumerable streams) diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 82e0f92e6..94d30f0cb 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -162,7 +162,7 @@ namespace MediaBrowser.Server.Implementations.Library NameContains = searchTerm, ExcludeItemTypes = excludeItemTypes.ToArray(), IncludeItemTypes = includeItemTypes.ToArray(), - Limit = (query.Limit.HasValue ? (int?)(query.Limit.Value * 2) : null), + Limit = query.Limit, }, user, new string[] { }); diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 177d82b22..03ebcbbdc 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities.Audio; namespace MediaBrowser.Server.Implementations.Library { @@ -74,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.Library { list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false)); } - else if (plainFolderIds.Contains(folder.Id)) + else if (plainFolderIds.Contains(folder.Id) && UserView.IsEligibleForEnhancedView(folderViewType)) { list.Add(await GetUserView(folder, folderViewType, false, string.Empty, cancellationToken).ConfigureAwait(false)); } @@ -100,7 +101,7 @@ namespace MediaBrowser.Server.Implementations.Library { list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false)); } - else if (plainFolderIds.Contains(folder.Id)) + else if (plainFolderIds.Contains(folder.Id) && UserView.IsEligibleForEnhancedView(folderViewType)) { list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, user, cancellationToken).ConfigureAwait(false)); } @@ -123,14 +124,6 @@ namespace MediaBrowser.Server.Implementations.Library list.Add(await GetUserView(parents, list, CollectionType.TvShows, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false)); } - parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Music, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.GetViewType(user))) - .ToList(); - - if (parents.Count > 0) - { - list.Add(await GetUserView(parents, list, CollectionType.Music, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false)); - } - parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Movies, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.GetViewType(user))) .ToList(); @@ -139,14 +132,6 @@ namespace MediaBrowser.Server.Implementations.Library list.Add(await GetUserView(parents, list, CollectionType.Movies, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false)); } - parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Games, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - if (parents.Count > 0) - { - list.Add(await GetUserView(parents, list, CollectionType.Games, string.Empty, user, enableUserViews, cancellationToken).ConfigureAwait(false)); - } - if (user.Configuration.DisplayFoldersView) { var name = _localizationManager.GetLocalizedString("ViewType" + CollectionType.Folders); @@ -245,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.Library var currentUser = user; - var libraryItems = GetItemsForLatestItems(user, request.ParentId, includeTypes).Where(i => + var libraryItems = GetItemsForLatestItems(user, request.ParentId, includeTypes, request.Limit ?? 10).Where(i => { if (request.IsPlayed.HasValue) { @@ -293,23 +278,34 @@ namespace MediaBrowser.Server.Implementations.Library return list; } - private IEnumerable GetItemsForLatestItems(User user, string parentId, string[] includeItemTypes) + private IEnumerable GetItemsForLatestItems(User user, string parentId, string[] includeItemTypes, int limit) { var parentIds = string.IsNullOrEmpty(parentId) ? new string[] { } : new[] { parentId }; + if (parentIds.Length == 0) + { + parentIds = user.RootFolder.GetChildren(user, true) + .OfType() + .Select(i => i.Id.ToString("N")) + .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i)) + .ToArray(); + } + + var excludeItemTypes = includeItemTypes.Length == 0 ? new[] { "ChannelItem", "LiveTvItem", typeof(Person).Name, typeof(Studio).Name, typeof(Year).Name, typeof(GameGenre).Name, typeof(MusicGenre).Name, typeof(Genre).Name } : new string[] { }; + return _libraryManager.GetItems(new InternalItemsQuery(user) { IncludeItemTypes = includeItemTypes, SortOrder = SortOrder.Descending, SortBy = new[] { ItemSortBy.DateCreated }, - IsFolder = false, - ExcludeItemTypes = new[] { "ChannelItem", "Recording" }, - ExcludeLocationTypes = new[] { LocationType.Virtual } + IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null, + ExcludeItemTypes = excludeItemTypes, + ExcludeLocationTypes = new[] { LocationType.Virtual }, + Limit = limit * 20 }, user, parentIds); - } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index aef2157c3..3234336e2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - public const int MigrationVersion = 2; + public const int MigrationVersion = 4; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) { @@ -66,6 +66,8 @@ namespace MediaBrowser.Server.Implementations.Persistence innerProgress.RegisterAction(p => progress.Report(45 + (.55 * p))); await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false); progress.Report(100); + + await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false); } private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress progress) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4d86330e5..a33bdc0c7 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteAncestorsCommand; private IDbCommand _saveAncestorCommand; - private const int LatestSchemaVersion = 19; + private const int LatestSchemaVersion = 25; /// /// Initializes a new instance of the class. @@ -133,13 +133,15 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)", "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", - "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, PRIMARY KEY (ItemId, AncestorId))", + "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds on AncestorIds(ItemId,AncestorId)", "create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))", "create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)", "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", + "create index if not exists idxPeopleItemId on People(ItemId)", + "create index if not exists idxPeopleName on People(Name)", "create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT, StartPositionTicks BIGINT, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", "create index if not exists idx_"+ChaptersTableName+" on "+ChaptersTableName+"(ItemId, ChapterIndex)", @@ -155,6 +157,8 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(queries, _logger); + _connection.AddColumn(_logger, "AncestorIds", "AncestorIdText", "Text"); + _connection.AddColumn(_logger, "TypedBaseItems", "Path", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "StartDate", "DATETIME"); _connection.AddColumn(_logger, "TypedBaseItems", "EndDate", "DATETIME"); @@ -214,6 +218,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "Tags", "Text"); _connection.AddColumn(_logger, "TypedBaseItems", "IsFolder", "BIT"); + _connection.AddColumn(_logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); PrepareStatements(); @@ -416,6 +421,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "ParentId", "Genres", "ParentalRatingValue", + "InheritedParentalRatingValue", "SchemaVersion", "SortName", "RunTimeTicks", @@ -483,16 +489,17 @@ namespace MediaBrowser.Server.Implementations.Persistence _savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType"); _savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder"); _savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder"); - + // Ancestors _deleteAncestorsCommand = _connection.CreateCommand(); _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id"); _saveAncestorCommand = _connection.CreateCommand(); - _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId) values (@ItemId, @AncestorId)"; + _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)"; _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId"); _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId"); + _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorIdText"); // Chapters _deleteChaptersCommand = _connection.CreateCommand(); @@ -648,7 +655,8 @@ namespace MediaBrowser.Server.Implementations.Persistence } _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); - _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue(); + _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0; + _saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; _saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; _saveItemCommand.GetParameter(index++).Value = item.SortName; @@ -705,7 +713,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); _saveItemCommand.GetParameter(index++).Value = item.IsFolder; - + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1368,7 +1376,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId; //_logger.Debug(cmd.CommandText); - + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { while (reader.Read()) @@ -1885,7 +1893,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (query.MaxParentalRating.HasValue) { - whereClauses.Add("(ParentalRatingValue is NULL OR ParentalRatingValue<=@MaxParentalRating)"); + whereClauses.Add("InheritedParentalRatingValue<=@MaxParentalRating"); cmd.Parameters.Add(cmd, "@MaxParentalRating", DbType.Int32).Value = query.MaxParentalRating.Value; } @@ -1893,11 +1901,11 @@ namespace MediaBrowser.Server.Implementations.Persistence { if (query.HasParentalRating.Value) { - whereClauses.Add("ParentalRatingValue NOT NULL"); + whereClauses.Add("InheritedParentalRatingValue > 0"); } else { - whereClauses.Add("ParentalRatingValue IS NULL"); + whereClauses.Add("InheritedParentalRatingValue = 0"); } } @@ -1916,8 +1924,8 @@ namespace MediaBrowser.Server.Implementations.Persistence } if (query.AncestorIds.Length > 1) { - var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); + var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + new Guid(i).ToString("N") + "'").ToArray()); + whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } if (query.ExcludeLocationTypes.Length == 1) { @@ -1986,6 +1994,59 @@ namespace MediaBrowser.Server.Implementations.Persistence typeof(Channel) }; + public async Task UpdateInheritedValues(CancellationToken cancellationToken) + { + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try + { + transaction = _connection.BeginTransaction(); + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "update TypedBaseItems set InheritedParentalRatingValue = (select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems as T where guid in (Select AncestorId from AncestorIds where ItemId=T.guid))))"; + + cmd.Transaction = transaction; + cmd.ExecuteNonQuery(); + + cmd.ExecuteNonQuery(); + } + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + _logger.ErrorException("Error running query:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + + _writeLock.Release(); + } + } + private static Dictionary GetTypeMapDictionary() { var dict = new Dictionary(); @@ -1996,6 +2057,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } dict["ChannelItem"] = new[] { typeof(ChannelVideoItem).FullName, typeof(ChannelAudioItem).FullName, typeof(ChannelFolderItem).FullName }; + dict["LiveTvItem"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName, typeof(LiveTvChannel).FullName, typeof(LiveTvProgram).FullName }; dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName }; dict["Program"] = new[] { typeof(LiveTvProgram).FullName }; dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName }; @@ -2053,7 +2115,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _deleteStreamsCommand.GetParameter(0).Value = id; _deleteStreamsCommand.Transaction = transaction; _deleteStreamsCommand.ExecuteNonQuery(); - + // Delete ancestors _deleteAncestorsCommand.GetParameter(0).Value = id; _deleteAncestorsCommand.Transaction = transaction; @@ -2063,7 +2125,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _deleteItemCommand.GetParameter(0).Value = id; _deleteItemCommand.Transaction = transaction; _deleteItemCommand.ExecuteNonQuery(); - + transaction.Commit(); } catch (OperationCanceledException) @@ -2316,6 +2378,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { _saveAncestorCommand.GetParameter(0).Value = itemId; _saveAncestorCommand.GetParameter(1).Value = ancestorId; + _saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N"); _saveAncestorCommand.Transaction = transaction; @@ -2550,7 +2613,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; - + _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index c715c3f50..db6a753b7 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -640,7 +640,6 @@ namespace MediaBrowser.Server.Implementations.Sync dtoOptions.Fields.Remove(ItemFields.MediaStreams); dtoOptions.Fields.Remove(ItemFields.IndexOptions); dtoOptions.Fields.Remove(ItemFields.MediaSourceCount); - dtoOptions.Fields.Remove(ItemFields.OriginalPrimaryImageAspectRatio); dtoOptions.Fields.Remove(ItemFields.Path); dtoOptions.Fields.Remove(ItemFields.SeriesGenres); dtoOptions.Fields.Remove(ItemFields.Settings); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 694bd1b79..6fc25f24c 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -640,11 +640,19 @@ namespace MediaBrowser.Server.Startup.Common /// Task{IUserRepository}. private async Task GetUserRepository() { - var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer); + try + { + var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize().ConfigureAwait(false); - return repo; + return repo; + } + catch (Exception ex) + { + Logger.ErrorException("Error opening user db", ex); + throw; + } } /// diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs index de7cba68d..cdb69025a 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs @@ -20,15 +20,13 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { if (_config.Configuration.MigrationVersion < CleanDatabaseScheduledTask.MigrationVersion) { - return; - } - - Task.Run(async () => - { - await Task.Delay(2000).ConfigureAwait(false); + Task.Run(async () => + { + await Task.Delay(2000).ConfigureAwait(false); - _taskManager.QueueScheduledTask(); - }); + _taskManager.QueueScheduledTask(); + }); + } } } } diff --git a/SharedVersion.cs b/SharedVersion.cs index 319a682ef..299f7d775 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -//[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5781.0")] +[assembly: AssemblyVersion("3.0.*")] +//[assembly: AssemblyVersion("3.0.5781.0")] -- cgit v1.2.3 From 6aa3313bc05fe5a26cee8944c00489c022612069 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 4 Nov 2015 18:49:06 -0500 Subject: make sure ._ osx files are properly ignored --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 1 - MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 8 ++- MediaBrowser.Api/UserLibrary/UserViewsService.cs | 1 + MediaBrowser.Controller/Library/ILibraryManager.cs | 9 +++- .../Resolvers/IResolverIgnoreRule.cs | 5 +- .../Configuration/EncodingOptions.cs | 2 +- .../Channels/ChannelManager.cs | 13 ++--- .../Library/CoreResolutionIgnoreRule.cs | 63 ++++++++++++---------- .../Library/LibraryManager.cs | 9 +++- .../Library/Resolvers/Movies/MovieResolver.cs | 20 ++++--- .../MediaBrowser.WebDashboard.csproj | 6 +-- 11 files changed, 85 insertions(+), 52 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 36207c8b4..426f1883e 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1662,7 +1662,6 @@ namespace MediaBrowser.Api.Playback state.InputContainer = mediaSource.Container; state.InputFileSize = mediaSource.Size; state.InputBitrate = mediaSource.Bitrate; - state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; state.RunTimeTicks = mediaSource.RunTimeTicks; state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 6ca2677e7..4d7a10f02 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -173,11 +173,14 @@ namespace MediaBrowser.Api.Playback.Hls } await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); + var released = false; try { if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); + ApiEntryPoint.Instance.TranscodingStartLock.Release(); + released = true; return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); } else @@ -238,7 +241,10 @@ namespace MediaBrowser.Api.Playback.Hls } finally { - ApiEntryPoint.Instance.TranscodingStartLock.Release(); + if (!released) + { + ApiEntryPoint.Instance.TranscodingStartLock.Release(); + } } //Logger.Info("waiting for {0}", segmentPath); diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index 6ba30a35e..6db195e3e 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -79,6 +79,7 @@ namespace MediaBrowser.Api.UserLibrary var dtoOptions = GetDtoOptions(request); dtoOptions.Fields = new List(); + dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio); var user = _userManager.GetUserById(request.UserId); diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 9e434541a..4a9ee312f 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -557,9 +557,16 @@ namespace MediaBrowser.Controller.Library /// Gets the items result. /// /// The query. - /// The user. /// The parent ids. /// QueryResult<BaseItem>. QueryResult GetItemsResult(InternalItemsQuery query, IEnumerable parentIds); + + /// + /// Ignores the file. + /// + /// The file. + /// The parent. + /// true if XXXX, false otherwise. + bool IgnoreFile(FileSystemMetadata file, BaseItem parent); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs index e85535548..2c82882c6 100644 --- a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs +++ b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Library; +using CommonIO; +using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Resolvers { @@ -7,6 +8,6 @@ namespace MediaBrowser.Controller.Resolvers /// public interface IResolverIgnoreRule { - bool ShouldIgnore(ItemResolveArgs args); + bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent); } } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 77b894eb8..4c3d1be37 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Configuration { DownMixAudioBoost = 2; EnableThrottling = true; - ThrottleThresholdInSeconds = 120; + ThrottleThresholdInSeconds = 100; EncodingThreadCount = -1; } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 645102230..34e7f33fc 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -1235,6 +1235,7 @@ namespace MediaBrowser.Server.Implementations.Channels { BaseItem item; bool isNew; + bool forceUpdate = false; if (info.Type == ChannelItemType.Folder) { @@ -1265,6 +1266,7 @@ namespace MediaBrowser.Server.Implementations.Channels item.ProviderIds = info.ProviderIds; item.OfficialRating = info.OfficialRating; item.DateCreated = info.DateCreated ?? DateTime.UtcNow; + item.Tags = info.Tags; } var channelItem = (IChannelItem)item; @@ -1273,7 +1275,7 @@ namespace MediaBrowser.Server.Implementations.Channels if (item.ParentId != internalChannelId) { - isNew = true; + forceUpdate = true; } item.ParentId = internalChannelId; @@ -1283,11 +1285,6 @@ namespace MediaBrowser.Server.Implementations.Channels } channelItem.ExternalId = info.Id; - if (isNew) - { - channelItem.Tags = info.Tags; - } - var channelMediaItem = item as IChannelMediaItem; if (channelMediaItem != null) @@ -1315,6 +1312,10 @@ namespace MediaBrowser.Server.Implementations.Channels await _libraryManager.UpdatePeople(item, info.People ?? new List()).ConfigureAwait(false); } } + else if (forceUpdate) + { + await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false); + } return item; } diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index 9035d6479..043996403 100644 --- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -47,11 +47,14 @@ namespace MediaBrowser.Server.Implementations.Library /// /// Shoulds the ignore. /// - /// The args. + /// The file information. + /// The parent. /// true if XXXX, false otherwise - public bool ShouldIgnore(ItemResolveArgs args) + public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent) { - var filename = args.FileInfo.Name; + var filename = fileInfo.Name; + var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; + var path = fileInfo.FullName; // Handle mac .DS_Store // https://github.com/MediaBrowser/MediaBrowser/issues/427 @@ -61,21 +64,24 @@ namespace MediaBrowser.Server.Implementations.Library } // Ignore hidden files and folders - if (args.IsHidden) + if (isHidden) { - var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path)); - - if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) + if (parent != null) { - return false; + var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path)); + + if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) + { + return false; + } } // Sometimes these are marked hidden - if (_fileSystem.IsRootPath(args.Path)) + if (_fileSystem.IsRootPath(path)) { return false; } @@ -83,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library return true; } - if (args.IsDirectory) + if (fileInfo.IsDirectory) { // Ignore any folders in our list if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase)) @@ -91,26 +97,29 @@ namespace MediaBrowser.Server.Implementations.Library return true; } - // Ignore trailer folders but allow it at the collection level - if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) && - !(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder)) + if (parent != null) { - return true; - } + // Ignore trailer folders but allow it at the collection level + if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) && + !(parent is AggregateFolder) && !(parent is UserRootFolder)) + { + return true; + } - if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - { - return true; - } + if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } - if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - { - return true; + if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } } } else { - if (args.Parent != null) + if (parent != null) { // Don't resolve these into audio files if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename)) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 3920d6171..70d28547c 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -580,7 +580,7 @@ namespace MediaBrowser.Server.Implementations.Library }; // Return null if ignore rules deem that we should do so - if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(args))) + if (IgnoreFile(args.FileInfo, args.Parent)) { return null; } @@ -616,6 +616,11 @@ namespace MediaBrowser.Server.Implementations.Library return ResolveItem(args); } + public bool IgnoreFile(FileSystemMetadata file, BaseItem parent) + { + return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent)); + } + public IEnumerable NormalizeRootPathList(IEnumerable paths) { var list = paths.Select(_fileSystem.NormalizePath) @@ -646,7 +651,7 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, Folder parent, string collectionType) { - var fileList = files.ToList(); + var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList(); if (parent != null) { diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 3252db505..e84fc242f 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies string collectionType, IDirectoryService directoryService) { - if (IsInvalid(parent, collectionType, files)) + if (IsInvalid(parent, collectionType)) { return null; } @@ -185,7 +185,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies { var collectionType = args.GetCollectionType(); - if (IsInvalid(args.Parent, collectionType, args.FileSystemChildren)) + if (IsInvalid(args.Parent, collectionType)) { return null; } @@ -193,14 +193,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies // Find movies with their own folders if (args.IsDirectory) { + var files = args.FileSystemChildren + .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .ToList(); + if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType); + return FindMovie(args.Path, args.Parent, files, args.DirectoryService, collectionType); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie