diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 34e5b8a36..657850ac0 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -25,6 +25,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Querying; @@ -50,7 +51,6 @@ namespace Emby.Dlna.ContentDirectory private readonly ILibraryManager _libraryManager; private readonly IUserDataManager _userDataManager; - private readonly IServerConfigurationManager _config; private readonly User _user; private readonly IUserViewManager _userViewManager; private readonly ITVSeriesManager _tvSeriesManager; @@ -104,7 +104,6 @@ namespace Emby.Dlna.ContentDirectory _userViewManager = userViewManager; _tvSeriesManager = tvSeriesManager; _profile = profile; - _config = config; _didlBuilder = new DidlBuilder( profile, @@ -330,75 +329,72 @@ namespace Emby.Dlna.ContentDirectory int totalCount; - using (StringWriter builder = new StringWriterWithEncoding(Encoding.UTF8)) + var settings = new XmlWriterSettings { - var settings = new XmlWriterSettings() + Encoding = Encoding.UTF8, + CloseOutput = false, + OmitXmlDeclaration = true, + ConformanceLevel = ConformanceLevel.Fragment + }; + + using (StringWriter builder = new StringWriterWithEncoding(Encoding.UTF8)) + using (var writer = XmlWriter.Create(builder, settings)) + { + writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl); + + writer.WriteAttributeString("xmlns", "dc", null, NsDc); + writer.WriteAttributeString("xmlns", "dlna", null, NsDlna); + writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp); + + DidlBuilder.WriteXmlRootAttributes(_profile, writer); + + var serverItem = GetItemFromObjectId(id); + var item = serverItem.Item; + + if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal)) { - Encoding = Encoding.UTF8, - CloseOutput = false, - OmitXmlDeclaration = true, - ConformanceLevel = ConformanceLevel.Fragment - }; + totalCount = 1; - using (var writer = XmlWriter.Create(builder, settings)) - { - writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl); - - writer.WriteAttributeString("xmlns", "dc", null, NsDc); - writer.WriteAttributeString("xmlns", "dlna", null, NsDlna); - writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp); - - DidlBuilder.WriteXmlRootAttributes(_profile, writer); - - var serverItem = GetItemFromObjectId(id); - var item = serverItem.Item; - - if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal)) + if (item.IsDisplayedAsFolder || serverItem.StubType.HasValue) { - totalCount = 1; + var childrenResult = GetUserItems(item, serverItem.StubType, _user, sortCriteria, start, requestedCount); - if (item.IsDisplayedAsFolder || serverItem.StubType.HasValue) - { - var childrenResult = GetUserItems(item, serverItem.StubType, _user, sortCriteria, start, requestedCount); - - _didlBuilder.WriteFolderElement(writer, item, serverItem.StubType, null, childrenResult.TotalRecordCount, filter, id); - } - else - { - _didlBuilder.WriteItemElement(writer, item, _user, null, null, deviceId, filter); - } - - provided++; + _didlBuilder.WriteFolderElement(writer, item, serverItem.StubType, null, childrenResult.TotalRecordCount, filter, id); } else { - var childrenResult = GetUserItems(item, serverItem.StubType, _user, sortCriteria, start, requestedCount); - totalCount = childrenResult.TotalRecordCount; - - provided = childrenResult.Items.Count; - - foreach (var i in childrenResult.Items) - { - var childItem = i.Item; - var displayStubType = i.StubType; - - if (childItem.IsDisplayedAsFolder || displayStubType.HasValue) - { - var childCount = GetUserItems(childItem, displayStubType, _user, sortCriteria, null, 0) - .TotalRecordCount; - - _didlBuilder.WriteFolderElement(writer, childItem, displayStubType, item, childCount, filter); - } - else - { - _didlBuilder.WriteItemElement(writer, childItem, _user, item, serverItem.StubType, deviceId, filter); - } - } + _didlBuilder.WriteItemElement(writer, item, _user, null, null, deviceId, filter); } - writer.WriteFullEndElement(); + provided++; + } + else + { + var childrenResult = GetUserItems(item, serverItem.StubType, _user, sortCriteria, start, requestedCount); + totalCount = childrenResult.TotalRecordCount; + + provided = childrenResult.Items.Count; + + foreach (var i in childrenResult.Items) + { + var childItem = i.Item; + var displayStubType = i.StubType; + + if (childItem.IsDisplayedAsFolder || displayStubType.HasValue) + { + var childCount = GetUserItems(childItem, displayStubType, _user, sortCriteria, null, 0) + .TotalRecordCount; + + _didlBuilder.WriteFolderElement(writer, childItem, displayStubType, item, childCount, filter); + } + else + { + _didlBuilder.WriteItemElement(writer, childItem, _user, item, serverItem.StubType, deviceId, filter); + } + } } + writer.WriteFullEndElement(); xmlWriter.WriteElementString("Result", builder.ToString()); } @@ -449,53 +445,45 @@ namespace Emby.Dlna.ContentDirectory } QueryResult childrenResult; + var settings = new XmlWriterSettings + { + Encoding = Encoding.UTF8, + CloseOutput = false, + OmitXmlDeclaration = true, + ConformanceLevel = ConformanceLevel.Fragment + }; using (StringWriter builder = new StringWriterWithEncoding(Encoding.UTF8)) + using (var writer = XmlWriter.Create(builder, settings)) { - var settings = new XmlWriterSettings() + writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl); + writer.WriteAttributeString("xmlns", "dc", null, NsDc); + writer.WriteAttributeString("xmlns", "dlna", null, NsDlna); + writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp); + + DidlBuilder.WriteXmlRootAttributes(_profile, writer); + + var serverItem = GetItemFromObjectId(sparams["ContainerID"]); + + var item = serverItem.Item; + + childrenResult = GetChildrenSorted(item, _user, searchCriteria, sortCriteria, start, requestedCount); + foreach (var i in childrenResult.Items) { - Encoding = Encoding.UTF8, - CloseOutput = false, - OmitXmlDeclaration = true, - ConformanceLevel = ConformanceLevel.Fragment - }; - - using (var writer = XmlWriter.Create(builder, settings)) - { - writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl); - - writer.WriteAttributeString("xmlns", "dc", null, NsDc); - writer.WriteAttributeString("xmlns", "dlna", null, NsDlna); - writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp); - - DidlBuilder.WriteXmlRootAttributes(_profile, writer); - - var serverItem = GetItemFromObjectId(sparams["ContainerID"]); - - var item = serverItem.Item; - - childrenResult = GetChildrenSorted(item, _user, searchCriteria, sortCriteria, start, requestedCount); - - var dlnaOptions = _config.GetDlnaConfiguration(); - - foreach (var i in childrenResult.Items) + if (i.IsDisplayedAsFolder) { - if (i.IsDisplayedAsFolder) - { - var childCount = GetChildrenSorted(i, _user, searchCriteria, sortCriteria, null, 0) - .TotalRecordCount; + var childCount = GetChildrenSorted(i, _user, searchCriteria, sortCriteria, null, 0) + .TotalRecordCount; - _didlBuilder.WriteFolderElement(writer, i, null, item, childCount, filter); - } - else - { - _didlBuilder.WriteItemElement(writer, i, _user, item, serverItem.StubType, deviceId, filter); - } + _didlBuilder.WriteFolderElement(writer, i, null, item, childCount, filter); + } + else + { + _didlBuilder.WriteItemElement(writer, i, _user, item, serverItem.StubType, deviceId, filter); } - - writer.WriteFullEndElement(); } + writer.WriteFullEndElement(); xmlWriter.WriteElementString("Result", builder.ToString()); } @@ -518,44 +506,34 @@ namespace Emby.Dlna.ContentDirectory { var folder = (Folder)item; - var sortOrders = folder.IsPreSorted - ? Array.Empty<(string, SortOrder)>() - : new[] { (ItemSortBy.SortName, sort.SortOrder) }; - string[] mediaTypes = Array.Empty(); bool? isFolder = null; - if (search.SearchType == SearchType.Audio) + switch (search.SearchType) { - mediaTypes = new[] { MediaType.Audio }; - isFolder = false; - } - else if (search.SearchType == SearchType.Video) - { - mediaTypes = new[] { MediaType.Video }; - isFolder = false; - } - else if (search.SearchType == SearchType.Image) - { - mediaTypes = new[] { MediaType.Photo }; - isFolder = false; - } - else if (search.SearchType == SearchType.Playlist) - { - // items = items.OfType(); - isFolder = true; - } - else if (search.SearchType == SearchType.MusicAlbum) - { - // items = items.OfType(); - isFolder = true; + case SearchType.Audio: + mediaTypes = new[] { MediaType.Audio }; + isFolder = false; + break; + case SearchType.Video: + mediaTypes = new[] { MediaType.Video }; + isFolder = false; + break; + case SearchType.Image: + mediaTypes = new[] { MediaType.Photo }; + isFolder = false; + break; + case SearchType.Playlist: + case SearchType.MusicAlbum: + isFolder = true; + break; } return folder.GetItems(new InternalItemsQuery { Limit = limit, StartIndex = startIndex, - OrderBy = sortOrders, + OrderBy = GetOrderBy(sort, folder.IsPreSorted), User = user, Recursive = true, IsMissing = false, @@ -587,52 +565,49 @@ namespace Emby.Dlna.ContentDirectory /// The . private QueryResult GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit) { - if (item is MusicGenre) + switch (item) { - return GetMusicGenreItems(item, Guid.Empty, user, sort, startIndex, limit); + case MusicGenre: + return GetMusicGenreItems(item, user, sort, startIndex, limit); + case MusicArtist: + return GetMusicArtistItems(item, user, sort, startIndex, limit); + case Genre: + return GetGenreItems(item, user, sort, startIndex, limit); } - if (item is MusicArtist) + if (stubType != StubType.Folder && item is IHasCollectionType collectionFolder) { - return GetMusicArtistItems(item, Guid.Empty, user, sort, startIndex, limit); - } - - if (item is Genre) - { - return GetGenreItems(item, Guid.Empty, user, sort, startIndex, limit); - } - - if ((!stubType.HasValue || stubType.Value != StubType.Folder) - && item is IHasCollectionType collectionFolder) - { - if (string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + var collectionType = collectionFolder.CollectionType; + if (string.Equals(CollectionType.Music, collectionType, StringComparison.OrdinalIgnoreCase)) { return GetMusicFolders(item, user, stubType, sort, startIndex, limit); } - else if (string.Equals(CollectionType.Movies, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(CollectionType.Movies, collectionType, StringComparison.OrdinalIgnoreCase)) { return GetMovieFolders(item, user, stubType, sort, startIndex, limit); } - else if (string.Equals(CollectionType.TvShows, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(CollectionType.TvShows, collectionType, StringComparison.OrdinalIgnoreCase)) { return GetTvFolders(item, user, stubType, sort, startIndex, limit); } - else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(CollectionType.Folders, collectionType, StringComparison.OrdinalIgnoreCase)) { return GetFolders(user, startIndex, limit); } - else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + + if (string.Equals(CollectionType.LiveTv, collectionType, StringComparison.OrdinalIgnoreCase)) { return GetLiveTvChannels(user, sort, startIndex, limit); } } - if (stubType.HasValue) + if (stubType.HasValue && stubType.Value != StubType.Folder) { - if (stubType.Value != StubType.Folder) - { - return ApplyPaging(new QueryResult(), startIndex, limit); - } + // TODO should this be doing something? + return new QueryResult(); } var folder = (Folder)item; @@ -644,11 +619,10 @@ namespace Emby.Dlna.ContentDirectory IsVirtualItem = false, ExcludeItemTypes = new[] { nameof(Book) }, IsPlaceHolder = false, - DtoOptions = GetDtoOptions() + DtoOptions = GetDtoOptions(), + OrderBy = GetOrderBy(sort, folder.IsPreSorted) }; - SetSorting(query, sort, folder.IsPreSorted); - var queryResult = folder.GetItems(query); return ToResult(queryResult); @@ -668,10 +642,9 @@ namespace Emby.Dlna.ContentDirectory { StartIndex = startIndex, Limit = limit, + IncludeItemTypes = new[] { nameof(LiveTvChannel) }, + OrderBy = GetOrderBy(sort, false) }; - query.IncludeItemTypes = new[] { nameof(LiveTvChannel) }; - - SetSorting(query, sort, false); var result = _libraryManager.GetItemsResult(query); @@ -693,122 +666,57 @@ namespace Emby.Dlna.ContentDirectory var query = new InternalItemsQuery(user) { StartIndex = startIndex, - Limit = limit - }; - SetSorting(query, sort, false); - - if (stubType.HasValue && stubType.Value == StubType.Latest) - { - return GetMusicLatest(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Playlists) - { - return GetMusicPlaylists(user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Albums) - { - return GetMusicAlbums(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Artists) - { - return GetMusicArtists(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.AlbumArtists) - { - return GetMusicAlbumArtists(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.FavoriteAlbums) - { - return GetFavoriteAlbums(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.FavoriteArtists) - { - return GetFavoriteArtists(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.FavoriteSongs) - { - return GetFavoriteSongs(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Songs) - { - return GetMusicSongs(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Genres) - { - return GetMusicGenres(item, user, query); - } - - var list = new List - { - new ServerItem(item) - { - StubType = StubType.Latest - }, - - new ServerItem(item) - { - StubType = StubType.Playlists - }, - - new ServerItem(item) - { - StubType = StubType.Albums - }, - - new ServerItem(item) - { - StubType = StubType.AlbumArtists - }, - - new ServerItem(item) - { - StubType = StubType.Artists - }, - - new ServerItem(item) - { - StubType = StubType.Songs - }, - - new ServerItem(item) - { - StubType = StubType.Genres - }, - - new ServerItem(item) - { - StubType = StubType.FavoriteArtists - }, - - new ServerItem(item) - { - StubType = StubType.FavoriteAlbums - }, - - new ServerItem(item) - { - StubType = StubType.FavoriteSongs - } + Limit = limit, + OrderBy = GetOrderBy(sort, false) }; - if (limit.HasValue) + switch (stubType) { - list = list.Take(limit.Value).ToList(); + case StubType.Latest: + return GetLatest(item, query, nameof(Audio)); + case StubType.Playlists: + return GetMusicPlaylists(query); + case StubType.Albums: + return GetChildrenOfItem(item, query, nameof(MusicAlbum)); + case StubType.Artists: + return GetMusicArtists(item, query); + case StubType.AlbumArtists: + return GetMusicAlbumArtists(item, query); + case StubType.FavoriteAlbums: + return GetChildrenOfItem(item, query, nameof(MusicAlbum), true); + case StubType.FavoriteArtists: + return GetFavoriteArtists(item, query); + case StubType.FavoriteSongs: + return GetChildrenOfItem(item, query, nameof(Audio), true); + case StubType.Songs: + return GetChildrenOfItem(item, query, nameof(Audio)); + case StubType.Genres: + return GetMusicGenres(item, query); + } + + var serverItems = new ServerItem[] + { + new (item, StubType.Latest), + new (item, StubType.Playlists), + new (item, StubType.Albums), + new (item, StubType.AlbumArtists), + new (item, StubType.Artists), + new (item, StubType.Songs), + new (item, StubType.Genres), + new (item, StubType.FavoriteArtists), + new (item, StubType.FavoriteAlbums), + new (item, StubType.FavoriteSongs) + }; + + if (limit < serverItems.Length) + { + serverItems = serverItems[..limit.Value]; } return new QueryResult { - Items = list, - TotalRecordCount = list.Count + Items = serverItems, + TotalRecordCount = serverItems.Length }; } @@ -827,71 +735,39 @@ namespace Emby.Dlna.ContentDirectory var query = new InternalItemsQuery(user) { StartIndex = startIndex, - Limit = limit - }; - SetSorting(query, sort, false); - - if (stubType.HasValue && stubType.Value == StubType.ContinueWatching) - { - return GetMovieContinueWatching(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Latest) - { - return GetMovieLatest(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Movies) - { - return GetMovieMovies(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Collections) - { - return GetMovieCollections(user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Favorites) - { - return GetMovieFavorites(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Genres) - { - return GetGenres(item, user, query); - } - - var array = new[] - { - new ServerItem(item) - { - StubType = StubType.ContinueWatching - }, - new ServerItem(item) - { - StubType = StubType.Latest - }, - new ServerItem(item) - { - StubType = StubType.Movies - }, - new ServerItem(item) - { - StubType = StubType.Collections - }, - new ServerItem(item) - { - StubType = StubType.Favorites - }, - new ServerItem(item) - { - StubType = StubType.Genres - } + Limit = limit, + OrderBy = GetOrderBy(sort, false) }; - if (limit.HasValue) + switch (stubType) { - array = array.Take(limit.Value).ToArray(); + case StubType.ContinueWatching: + return GetMovieContinueWatching(item, query); + case StubType.Latest: + return GetLatest(item, query, nameof(Movie)); + case StubType.Movies: + return GetChildrenOfItem(item, query, nameof(Movie)); + case StubType.Collections: + return GetMovieCollections(query); + case StubType.Favorites: + return GetChildrenOfItem(item, query, nameof(Movie), true); + case StubType.Genres: + return GetGenres(item, query); + } + + var array = new ServerItem[] + { + new (item, StubType.ContinueWatching), + new (item, StubType.Latest), + new (item, StubType.Movies), + new (item, StubType.Collections), + new (item, StubType.Favorites), + new (item, StubType.Genres) + }; + + if (limit < array.Length) + { + array = array[..limit.Value]; } return new QueryResult @@ -910,22 +786,21 @@ namespace Emby.Dlna.ContentDirectory /// The . private QueryResult GetFolders(User user, int? startIndex, int? limit) { - var folders = _libraryManager.GetUserRootFolder().GetChildren(user, true) + var folders = _libraryManager.GetUserRootFolder().GetChildren(user, true); + var totalRecordCount = folders.Count; + // Handle paging + var items = folders .OrderBy(i => i.SortName) - .Select(i => new ServerItem(i) - { - StubType = StubType.Folder - }) + .Skip(startIndex ?? 0) + .Take(limit ?? int.MaxValue) + .Select(i => new ServerItem(i, StubType.Folder)) .ToArray(); - return ApplyPaging( - new QueryResult - { - Items = folders, - TotalRecordCount = folders.Length - }, - startIndex, - limit); + return new QueryResult + { + Items = items, + TotalRecordCount = totalRecordCount + }; } /// @@ -943,92 +818,48 @@ namespace Emby.Dlna.ContentDirectory var query = new InternalItemsQuery(user) { StartIndex = startIndex, - Limit = limit - }; - SetSorting(query, sort, false); - - if (stubType.HasValue && stubType.Value == StubType.ContinueWatching) - { - return GetMovieContinueWatching(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.NextUp) - { - return GetNextUp(item, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Latest) - { - return GetTvLatest(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Series) - { - return GetSeries(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.FavoriteSeries) - { - return GetFavoriteSeries(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.FavoriteEpisodes) - { - return GetFavoriteEpisodes(item, user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Genres) - { - return GetGenres(item, user, query); - } - - var list = new List - { - new ServerItem(item) - { - StubType = StubType.ContinueWatching - }, - - new ServerItem(item) - { - StubType = StubType.NextUp - }, - - new ServerItem(item) - { - StubType = StubType.Latest - }, - - new ServerItem(item) - { - StubType = StubType.Series - }, - - new ServerItem(item) - { - StubType = StubType.FavoriteSeries - }, - - new ServerItem(item) - { - StubType = StubType.FavoriteEpisodes - }, - - new ServerItem(item) - { - StubType = StubType.Genres - } + Limit = limit, + OrderBy = GetOrderBy(sort, false) }; - if (limit.HasValue) + switch (stubType) { - list = list.Take(limit.Value).ToList(); + case StubType.ContinueWatching: + return GetMovieContinueWatching(item, query); + case StubType.NextUp: + return GetNextUp(item, query); + case StubType.Latest: + return GetLatest(item, query, nameof(Episode)); + case StubType.Series: + return GetChildrenOfItem(item, query, nameof(Series)); + case StubType.FavoriteSeries: + return GetChildrenOfItem(item, query, nameof(Series), true); + case StubType.FavoriteEpisodes: + return GetChildrenOfItem(item, query, nameof(Episode), true); + case StubType.Genres: + return GetGenres(item, query); + } + + var serverItems = new ServerItem[] + { + new (item, StubType.ContinueWatching), + new (item, StubType.NextUp), + new (item, StubType.Latest), + new (item, StubType.Series), + new (item, StubType.FavoriteSeries), + new (item, StubType.FavoriteEpisodes), + new (item, StubType.Genres) + }; + + if (limit < serverItems.Length) + { + serverItems = serverItems[..limit.Value]; } return new QueryResult { - Items = list, - TotalRecordCount = list.Count + Items = serverItems, + TotalRecordCount = serverItems.Length }; } @@ -1036,14 +867,12 @@ namespace Emby.Dlna.ContentDirectory /// Returns the Movies that are part watched that meet the criteria. /// /// The . - /// The . /// The . /// The . - private QueryResult GetMovieContinueWatching(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetMovieContinueWatching(BaseItem parent, InternalItemsQuery query) { query.Recursive = true; query.Parent = parent; - query.SetUser(user); query.OrderBy = new[] { @@ -1052,47 +881,7 @@ namespace Emby.Dlna.ContentDirectory }; query.IsResumable = true; - query.Limit = query.Limit ?? 10; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the series meeting the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetSeries(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { nameof(Series) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the Movie folders meeting the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetMovieMovies(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { nameof(Movie) }; + query.Limit ??= 10; var result = _libraryManager.GetItemsResult(query); @@ -1102,15 +891,11 @@ namespace Emby.Dlna.ContentDirectory /// /// Returns the Movie collections meeting the criteria. /// - /// The see cref="User"/>. /// The see cref="InternalItemsQuery"/>. /// The . - private QueryResult GetMovieCollections(User user, InternalItemsQuery query) + private QueryResult GetMovieCollections(InternalItemsQuery query) { query.Recursive = true; - // query.Parent = parent; - query.SetUser(user); - query.IncludeItemTypes = new[] { nameof(BoxSet) }; var result = _libraryManager.GetItemsResult(query); @@ -1119,139 +904,19 @@ namespace Emby.Dlna.ContentDirectory } /// - /// Returns the Music albums meeting the criteria. + /// Returns the children that meet the criteria. /// /// The . - /// The . /// The . + /// The item type. + /// A value indicating whether to only fetch favorite items. /// The . - private QueryResult GetMusicAlbums(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetChildrenOfItem(BaseItem parent, InternalItemsQuery query, string itemType, bool isFavorite = false) { query.Recursive = true; query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { nameof(MusicAlbum) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the Music songs meeting the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetMusicSongs(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { nameof(Audio) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the songs tagged as favourite that meet the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetFavoriteSongs(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { nameof(Audio) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the series tagged as favourite that meet the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetFavoriteSeries(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { nameof(Series) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the episodes tagged as favourite that meet the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetFavoriteEpisodes(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { nameof(Episode) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// Returns the movies tagged as favourite that meet the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetMovieFavorites(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { nameof(Movie) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// - /// /// Returns the albums tagged as favourite that meet the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetFavoriteAlbums(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { nameof(MusicAlbum) }; + query.IsFavorite = isFavorite; + query.IncludeItemTypes = new[] { itemType }; var result = _libraryManager.GetItemsResult(query); @@ -1263,139 +928,90 @@ namespace Emby.Dlna.ContentDirectory /// The GetGenres. /// /// The . - /// The . /// The . /// The . - private QueryResult GetGenres(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetGenres(BaseItem parent, InternalItemsQuery query) { - var genresResult = _libraryManager.GetGenres(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var genresResult = _libraryManager.GetGenres(query); - var result = new QueryResult - { - TotalRecordCount = genresResult.TotalRecordCount, - Items = genresResult.Items.Select(i => i.Item1).ToArray() - }; - - return ToResult(result); + return ToResult(genresResult); } /// /// Returns the music genres meeting the criteria. /// /// The . - /// The . /// The . /// The . - private QueryResult GetMusicGenres(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetMusicGenres(BaseItem parent, InternalItemsQuery query) { - var genresResult = _libraryManager.GetMusicGenres(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var genresResult = _libraryManager.GetMusicGenres(query); - var result = new QueryResult - { - TotalRecordCount = genresResult.TotalRecordCount, - Items = genresResult.Items.Select(i => i.Item1).ToArray() - }; - - return ToResult(result); + return ToResult(genresResult); } /// /// Returns the music albums by artist that meet the criteria. /// /// The . - /// The . /// The . /// The . - private QueryResult GetMusicAlbumArtists(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetMusicAlbumArtists(BaseItem parent, InternalItemsQuery query) { - var artists = _libraryManager.GetAlbumArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var artists = _libraryManager.GetAlbumArtists(query); - var result = new QueryResult - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; - - return ToResult(result); + return ToResult(artists); } /// /// Returns the music artists meeting the criteria. /// /// The . - /// The . /// The . /// The . - private QueryResult GetMusicArtists(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetMusicArtists(BaseItem parent, InternalItemsQuery query) { - var artists = _libraryManager.GetArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - var result = new QueryResult - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; - - return ToResult(result); + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var artists = _libraryManager.GetArtists(query); + return ToResult(artists); } /// /// Returns the artists tagged as favourite that meet the criteria. /// /// The . - /// The . /// The . /// The . - private QueryResult GetFavoriteArtists(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetFavoriteArtists(BaseItem parent, InternalItemsQuery query) { - var artists = _libraryManager.GetArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit, - IsFavorite = true - }); - - var result = new QueryResult - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; - - return ToResult(result); + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + query.IsFavorite = true; + var artists = _libraryManager.GetArtists(query); + return ToResult(artists); } /// /// Returns the music playlists meeting the criteria. /// - /// The user. /// The query. /// The . - private QueryResult GetMusicPlaylists(User user, InternalItemsQuery query) + private QueryResult GetMusicPlaylists(InternalItemsQuery query) { query.Parent = null; query.IncludeItemTypes = new[] { nameof(Playlist) }; - query.SetUser(user); query.Recursive = true; var result = _libraryManager.GetItemsResult(query); @@ -1403,31 +1019,6 @@ namespace Emby.Dlna.ContentDirectory return ToResult(result); } - /// - /// Returns the latest music meeting the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetMusicLatest(BaseItem parent, User user, InternalItemsQuery query) - { - query.OrderBy = Array.Empty<(string, SortOrder)>(); - - var items = _userViewManager.GetLatestItems( - new LatestItemsQuery - { - UserId = user.Id, - Limit = 50, - IncludeItemTypes = new[] { nameof(Audio) }, - ParentId = parent?.Id ?? Guid.Empty, - GroupItems = true - }, - query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); - - return ToResult(items); - } - /// /// Returns the next up item meeting the criteria. /// @@ -1443,7 +1034,8 @@ namespace Emby.Dlna.ContentDirectory { Limit = query.Limit, StartIndex = query.StartIndex, - UserId = query.User.Id + // User cannot be null here as the caller has set it + UserId = query.User!.Id }, new[] { parent }, query.DtoOptions); @@ -1452,47 +1044,23 @@ namespace Emby.Dlna.ContentDirectory } /// - /// Returns the latest tv meeting the criteria. + /// Returns the latest items of [itemType] meeting the criteria. /// /// The . - /// The . /// The . + /// The item type. /// The . - private QueryResult GetTvLatest(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult GetLatest(BaseItem parent, InternalItemsQuery query, string itemType) { query.OrderBy = Array.Empty<(string, SortOrder)>(); var items = _userViewManager.GetLatestItems( new LatestItemsQuery { - UserId = user.Id, + // User cannot be null here as the caller has set it + UserId = query.User!.Id, Limit = query.Limit ?? 50, - IncludeItemTypes = new[] { nameof(Episode) }, - ParentId = parent == null ? Guid.Empty : parent.Id, - GroupItems = false - }, - query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); - - return ToResult(items); - } - - /// - /// Returns the latest movies meeting the criteria. - /// - /// The . - /// The . - /// The . - /// The . - private QueryResult GetMovieLatest(BaseItem parent, User user, InternalItemsQuery query) - { - query.OrderBy = Array.Empty<(string, SortOrder)>(); - - var items = _userViewManager.GetLatestItems( - new LatestItemsQuery - { - UserId = user.Id, - Limit = query.Limit ?? 50, - IncludeItemTypes = new[] { nameof(Movie) }, + IncludeItemTypes = new[] { itemType }, ParentId = parent?.Id ?? Guid.Empty, GroupItems = true }, @@ -1505,27 +1073,24 @@ namespace Emby.Dlna.ContentDirectory /// Returns music artist items that meet the criteria. /// /// The . - /// The . /// The . /// The . /// The start index. /// The maximum number to return. /// The . - private QueryResult GetMusicArtistItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit) + private QueryResult GetMusicArtistItems(BaseItem item, User user, SortCriteria sort, int? startIndex, int? limit) { var query = new InternalItemsQuery(user) { Recursive = true, - ParentId = parentId, ArtistIds = new[] { item.Id }, IncludeItemTypes = new[] { nameof(MusicAlbum) }, Limit = limit, StartIndex = startIndex, - DtoOptions = GetDtoOptions() + DtoOptions = GetDtoOptions(), + OrderBy = GetOrderBy(sort, false) }; - SetSorting(query, sort, false); - var result = _libraryManager.GetItemsResult(query); return ToResult(result); @@ -1535,18 +1100,16 @@ namespace Emby.Dlna.ContentDirectory /// Returns the genre items meeting the criteria. /// /// The . - /// The . /// The . /// The . /// The start index. /// The maximum number to return. /// The . - private QueryResult GetGenreItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit) + private QueryResult GetGenreItems(BaseItem item, User user, SortCriteria sort, int? startIndex, int? limit) { var query = new InternalItemsQuery(user) { Recursive = true, - ParentId = parentId, GenreIds = new[] { item.Id }, IncludeItemTypes = new[] { @@ -1555,11 +1118,10 @@ namespace Emby.Dlna.ContentDirectory }, Limit = limit, StartIndex = startIndex, - DtoOptions = GetDtoOptions() + DtoOptions = GetDtoOptions(), + OrderBy = GetOrderBy(sort, false) }; - SetSorting(query, sort, false); - var result = _libraryManager.GetItemsResult(query); return ToResult(result); @@ -1569,46 +1131,43 @@ namespace Emby.Dlna.ContentDirectory /// Returns the music genre items meeting the criteria. /// /// The . - /// The . /// The . /// The . /// The start index. /// The maximum number to return. /// The . - private QueryResult GetMusicGenreItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit) + private QueryResult GetMusicGenreItems(BaseItem item, User user, SortCriteria sort, int? startIndex, int? limit) { var query = new InternalItemsQuery(user) { Recursive = true, - ParentId = parentId, GenreIds = new[] { item.Id }, IncludeItemTypes = new[] { nameof(MusicAlbum) }, Limit = limit, StartIndex = startIndex, - DtoOptions = GetDtoOptions() + DtoOptions = GetDtoOptions(), + OrderBy = GetOrderBy(sort, false) }; - SetSorting(query, sort, false); - var result = _libraryManager.GetItemsResult(query); return ToResult(result); } /// - /// Converts a array into a . + /// Converts into a . /// /// An array of . /// A . - private static QueryResult ToResult(BaseItem[] result) + private static QueryResult ToResult(IReadOnlyCollection result) { var serverItems = result - .Select(i => new ServerItem(i)) + .Select(i => new ServerItem(i, null)) .ToArray(); return new QueryResult { - TotalRecordCount = result.Length, + TotalRecordCount = result.Count, Items = serverItems }; } @@ -1620,10 +1179,12 @@ namespace Emby.Dlna.ContentDirectory /// The . private static QueryResult ToResult(QueryResult result) { - var serverItems = result - .Items - .Select(i => new ServerItem(i)) - .ToArray(); + var length = result.Items.Count; + var serverItems = new ServerItem[length]; + for (var i = 0; i < length; i++) + { + serverItems[i] = new ServerItem(result.Items[i], null); + } return new QueryResult { @@ -1633,35 +1194,34 @@ namespace Emby.Dlna.ContentDirectory } /// - /// Sets the sorting method on a query. + /// Converts a query result to a . /// - /// The . - /// The . - /// True if pre-sorted. - private static void SetSorting(InternalItemsQuery query, SortCriteria sort, bool isPreSorted) + /// A . + /// The . + private static QueryResult ToResult(QueryResult<(BaseItem, ItemCounts)> result) { - if (isPreSorted) + var length = result.Items.Count; + var serverItems = new ServerItem[length]; + for (var i = 0; i < length; i++) { - query.OrderBy = Array.Empty<(string, SortOrder)>(); + serverItems[i] = new ServerItem(result.Items[i].Item1, null); } - else + + return new QueryResult { - query.OrderBy = new[] { (ItemSortBy.SortName, sort.SortOrder) }; - } + TotalRecordCount = result.TotalRecordCount, + Items = serverItems + }; } /// - /// Apply paging to a query. + /// Gets the sorting method on a query. /// - /// The . - /// The start index. - /// The maximum number to return. - /// A . - private static QueryResult ApplyPaging(QueryResult result, int? startIndex, int? limit) + /// The . + /// True if pre-sorted. + private static (string, SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted) { - result.Items = result.Items.Skip(startIndex ?? 0).Take(limit ?? int.MaxValue).ToArray(); - - return result; + return isPreSorted ? Array.Empty<(string, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) }; } /// @@ -1672,7 +1232,7 @@ namespace Emby.Dlna.ContentDirectory private ServerItem GetItemFromObjectId(string id) { return DidlBuilder.IsIdRoot(id) - ? new ServerItem(_libraryManager.GetUserRootFolder()) + ? new ServerItem(_libraryManager.GetUserRootFolder(), null) : ParseItemId(id); } @@ -1690,37 +1250,29 @@ namespace Emby.Dlna.ContentDirectory var paramsIndex = id.IndexOf(ParamsSrch, StringComparison.OrdinalIgnoreCase); if (paramsIndex != -1) { - id = id.Substring(paramsIndex + ParamsSrch.Length); + id = id[(paramsIndex + ParamsSrch.Length)..]; var parts = id.Split(';'); id = parts[23]; } - var enumNames = Enum.GetNames(typeof(StubType)); - foreach (var name in enumNames) + var dividerIndex = id.IndexOf('_', StringComparison.Ordinal); + if (dividerIndex != -1 && Enum.TryParse(id.AsSpan(0, dividerIndex), true, out var parsedStubType)) { - if (id.StartsWith(name + "_", StringComparison.OrdinalIgnoreCase)) - { - stubType = Enum.Parse(name, true); - id = id.Split('_', 2)[1]; - - break; - } + id = id[(dividerIndex + 1)..]; + stubType = parsedStubType; } if (Guid.TryParse(id, out var itemId)) { var item = _libraryManager.GetItemById(itemId); - return new ServerItem(item) - { - StubType = stubType - }; + return new ServerItem(item, stubType); } Logger.LogError("Error parsing item Id: {Id}. Returning user root folder.", id); - return new ServerItem(_libraryManager.GetUserRootFolder()); + return new ServerItem(_libraryManager.GetUserRootFolder(), null); } } } diff --git a/Emby.Dlna/ContentDirectory/ServerItem.cs b/Emby.Dlna/ContentDirectory/ServerItem.cs index ff30e6e4a..df05fa966 100644 --- a/Emby.Dlna/ContentDirectory/ServerItem.cs +++ b/Emby.Dlna/ContentDirectory/ServerItem.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - using MediaBrowser.Controller.Entities; namespace Emby.Dlna.ContentDirectory @@ -13,24 +11,29 @@ namespace Emby.Dlna.ContentDirectory /// Initializes a new instance of the class. /// /// The . - public ServerItem(BaseItem item) + /// The stub type. + public ServerItem(BaseItem item, StubType? stubType) { Item = item; - if (item is IItemByName && item is not Folder) + if (stubType.HasValue) + { + StubType = stubType; + } + else if (item is IItemByName and not Folder) { StubType = Dlna.ContentDirectory.StubType.Folder; } } /// - /// Gets or sets the underlying base item. + /// Gets the underlying base item. /// - public BaseItem Item { get; set; } + public BaseItem Item { get; } /// - /// Gets or sets the DLNA item type. + /// Gets the DLNA item type. /// - public StubType? StubType { get; set; } + public StubType? StubType { get; } } } diff --git a/MediaBrowser.Model/Dlna/SortCriteria.cs b/MediaBrowser.Model/Dlna/SortCriteria.cs index 7769d0bd3..7fef16e53 100644 --- a/MediaBrowser.Model/Dlna/SortCriteria.cs +++ b/MediaBrowser.Model/Dlna/SortCriteria.cs @@ -1,15 +1,24 @@ #pragma warning disable CS1591 +using System; using Jellyfin.Data.Enums; namespace MediaBrowser.Model.Dlna { public class SortCriteria { - public SortCriteria(string value) + public SortCriteria(string sortOrder) { + if (!string.IsNullOrEmpty(sortOrder) && Enum.TryParse(sortOrder, true, out var sortOrderValue)) + { + SortOrder = sortOrderValue; + } + else + { + SortOrder = SortOrder.Ascending; + } } - public SortOrder SortOrder => SortOrder.Ascending; + public SortOrder SortOrder { get; } } }