diff options
Diffstat (limited to 'Emby.Dlna')
| -rw-r--r-- | Emby.Dlna/ContentDirectory/ControlHandler.cs | 1089 | ||||
| -rw-r--r-- | Emby.Dlna/ContentDirectory/ServerItem.cs | 19 | ||||
| -rw-r--r-- | Emby.Dlna/Didl/DidlBuilder.cs | 2 | ||||
| -rw-r--r-- | Emby.Dlna/DlnaManager.cs | 25 | ||||
| -rw-r--r-- | Emby.Dlna/Emby.Dlna.csproj | 2 | ||||
| -rw-r--r-- | Emby.Dlna/Main/DlnaEntryPoint.cs | 24 | ||||
| -rw-r--r-- | Emby.Dlna/PlayTo/PlayToManager.cs | 5 | ||||
| -rw-r--r-- | Emby.Dlna/Service/BaseControlHandler.cs | 2 |
8 files changed, 353 insertions, 815 deletions
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index ac336e5dcc..26a816107a 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, @@ -291,9 +290,9 @@ namespace Emby.Dlna.ContentDirectory return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<Features xmlns=\"urn:schemas-upnp-org:av:avs\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:schemas-upnp-org:av:avs http://www.upnp.org/schemas/av/avs.xsd\">" + "<Feature name=\"samsung.com_BASICVIEW\" version=\"1\">" - + "<container id=\"I\" type=\"object.item.imageItem\"/>" - + "<container id=\"A\" type=\"object.item.audioItem\"/>" - + "<container id=\"V\" type=\"object.item.videoItem\"/>" + + "<container id=\"0\" type=\"object.item.imageItem\"/>" + + "<container id=\"0\" type=\"object.item.audioItem\"/>" + + "<container id=\"0\" type=\"object.item.videoItem\"/>" + "</Feature>" + "</Features>"; } @@ -330,75 +329,73 @@ namespace Emby.Dlna.ContentDirectory int totalCount; + 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() - { - Encoding = Encoding.UTF8, - CloseOutput = false, - OmitXmlDeclaration = true, - ConformanceLevel = ConformanceLevel.Fragment - }; + writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl); - 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); - writer.WriteAttributeString("xmlns", "dc", null, NsDc); - writer.WriteAttributeString("xmlns", "dlna", null, NsDlna); - writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp); + DidlBuilder.WriteXmlRootAttributes(_profile, writer); - DidlBuilder.WriteXmlRootAttributes(_profile, writer); + var serverItem = GetItemFromObjectId(id); + var item = serverItem.Item; - var serverItem = GetItemFromObjectId(id); - var item = serverItem.Item; + if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal)) + { + totalCount = 1; - if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal)) + if (item.IsDisplayedAsFolder || serverItem.StubType.HasValue) { - totalCount = 1; - - 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); - } + var childrenResult = GetUserItems(item, serverItem.StubType, _user, sortCriteria, start, requestedCount); - 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; + _didlBuilder.WriteItemElement(writer, item, _user, null, null, deviceId, filter); + } + + 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; - provided = childrenResult.Items.Count; + if (childItem.IsDisplayedAsFolder || displayStubType.HasValue) + { + var childCount = GetUserItems(childItem, displayStubType, _user, sortCriteria, null, 0) + .TotalRecordCount; - foreach (var i in childrenResult.Items) + _didlBuilder.WriteFolderElement(writer, childItem, displayStubType, item, childCount, filter); + } + else { - 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, childItem, _user, item, serverItem.StubType, deviceId, filter); } } - - writer.WriteFullEndElement(); } + writer.WriteFullEndElement(); + writer.Flush(); xmlWriter.WriteElementString("Result", builder.ToString()); } @@ -449,53 +446,46 @@ namespace Emby.Dlna.ContentDirectory } QueryResult<BaseItem> 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() - { - 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"]); + 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); - var item = serverItem.Item; + DidlBuilder.WriteXmlRootAttributes(_profile, writer); - childrenResult = GetChildrenSorted(item, _user, searchCriteria, sortCriteria, start, requestedCount); + var serverItem = GetItemFromObjectId(sparams["ContainerID"]); - var dlnaOptions = _config.GetDlnaConfiguration(); + var item = serverItem.Item; - foreach (var i in childrenResult.Items) + childrenResult = GetChildrenSorted(item, _user, searchCriteria, sortCriteria, start, requestedCount); + 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(); + writer.Flush(); xmlWriter.WriteElementString("Result", builder.ToString()); } @@ -518,44 +508,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<string>(); bool? isFolder = null; - if (search.SearchType == SearchType.Audio) - { - 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<Playlist>(); - isFolder = true; - } - else if (search.SearchType == SearchType.MusicAlbum) + switch (search.SearchType) { - // items = items.OfType<MusicAlbum>(); - 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 +567,49 @@ namespace Emby.Dlna.ContentDirectory /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> private QueryResult<ServerItem> GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit) { - if (item is MusicGenre) - { - return GetMusicGenreItems(item, Guid.Empty, user, sort, startIndex, limit); - } - - if (item is MusicArtist) - { - return GetMusicArtistItems(item, Guid.Empty, user, sort, startIndex, limit); + switch (item) + { + 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 Genre) + if (stubType != StubType.Folder && item is IHasCollectionType collectionFolder) { - 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<ServerItem>(), startIndex, limit); - } + // TODO should this be doing something? + return new QueryResult<ServerItem>(); } var folder = (Folder)item; @@ -644,11 +621,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 +644,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,117 +668,57 @@ namespace Emby.Dlna.ContentDirectory var query = new InternalItemsQuery(user) { StartIndex = startIndex, - Limit = limit + Limit = limit, + OrderBy = GetOrderBy(sort, false) }; - 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); + switch (stubType) + { + 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); } - 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); - } + 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 (stubType.HasValue && stubType.Value == StubType.Genres) + if (limit < serverItems.Length) { - return GetMusicGenres(item, user, query); + serverItems = serverItems[..limit.Value]; } - var list = new List<ServerItem> - { - 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 - } - }; - return new QueryResult<ServerItem> { - Items = list, - TotalRecordCount = list.Count + Items = serverItems, + TotalRecordCount = serverItems.Length }; } @@ -822,68 +737,41 @@ namespace Emby.Dlna.ContentDirectory var query = new InternalItemsQuery(user) { StartIndex = startIndex, - Limit = limit + Limit = limit, + OrderBy = GetOrderBy(sort, false) }; - 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); + switch (stubType) + { + 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); } - if (stubType.HasValue && stubType.Value == StubType.Collections) + var array = new ServerItem[] { - return GetMovieCollections(user, query); - } - - if (stubType.HasValue && stubType.Value == StubType.Favorites) - { - return GetMovieFavorites(item, user, query); - } + 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 (stubType.HasValue && stubType.Value == StubType.Genres) + if (limit < array.Length) { - return GetGenres(item, user, query); + array = array[..limit.Value]; } - 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 - } - }; - return new QueryResult<ServerItem> { Items = array, @@ -900,22 +788,21 @@ namespace Emby.Dlna.ContentDirectory /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> private QueryResult<ServerItem> 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<ServerItem> - { - Items = folders, - TotalRecordCount = folders.Length - }, - startIndex, - limit); + return new QueryResult<ServerItem> + { + Items = items, + TotalRecordCount = totalRecordCount + }; } /// <summary> @@ -933,87 +820,48 @@ namespace Emby.Dlna.ContentDirectory var query = new InternalItemsQuery(user) { StartIndex = startIndex, - Limit = limit + Limit = limit, + OrderBy = GetOrderBy(sort, false) }; - SetSorting(query, sort, false); - if (stubType.HasValue && stubType.Value == StubType.ContinueWatching) - { - return GetMovieContinueWatching(item, user, query); + switch (stubType) + { + 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); } - if (stubType.HasValue && stubType.Value == StubType.NextUp) + var serverItems = new ServerItem[] { - 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); - } + 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 (stubType.HasValue && stubType.Value == StubType.Genres) + if (limit < serverItems.Length) { - return GetGenres(item, user, query); + serverItems = serverItems[..limit.Value]; } - var list = new List<ServerItem> - { - 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 - } - }; - return new QueryResult<ServerItem> { - Items = list, - TotalRecordCount = list.Count + Items = serverItems, + TotalRecordCount = serverItems.Length }; } @@ -1021,14 +869,12 @@ namespace Emby.Dlna.ContentDirectory /// Returns the Movies that are part watched that meet the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMovieContinueWatching(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetMovieContinueWatching(BaseItem parent, InternalItemsQuery query) { query.Recursive = true; query.Parent = parent; - query.SetUser(user); query.OrderBy = new[] { @@ -1037,47 +883,7 @@ namespace Emby.Dlna.ContentDirectory }; query.IsResumable = true; - query.Limit = 10; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// <summary> - /// Returns the series meeting the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); - } - - /// <summary> - /// Returns the Movie folders meeting the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); @@ -1087,15 +893,11 @@ namespace Emby.Dlna.ContentDirectory /// <summary> /// Returns the Movie collections meeting the criteria. /// </summary> - /// <param name="user">The see cref="User"/>.</param> /// <param name="query">The see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetMovieCollections(InternalItemsQuery query) { query.Recursive = true; - // query.Parent = parent; - query.SetUser(user); - query.IncludeItemTypes = new[] { nameof(BoxSet) }; var result = _libraryManager.GetItemsResult(query); @@ -1104,139 +906,19 @@ namespace Emby.Dlna.ContentDirectory } /// <summary> - /// Returns the Music albums meeting the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicAlbums(BaseItem parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { nameof(MusicAlbum) }; - - var result = _libraryManager.GetItemsResult(query); - - return ToResult(result); - } - - /// <summary> - /// Returns the Music songs meeting the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); - } - - /// <summary> - /// Returns the songs tagged as favourite that meet the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); - } - - /// <summary> - /// Returns the series tagged as favourite that meet the criteria. + /// Returns the children that meet the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> + /// <param name="itemType">The item type.</param> + /// <param name="isFavorite">A value indicating whether to only fetch favorite items.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetFavoriteSeries(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetChildrenOfItem(BaseItem parent, InternalItemsQuery query, string itemType, bool isFavorite = false) { 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); - } - - /// <summary> - /// Returns the episodes tagged as favourite that meet the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); - } - - /// <summary> - /// Returns the movies tagged as favourite that meet the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); - } - - /// <summary> - /// /// Returns the albums tagged as favourite that meet the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); @@ -1248,139 +930,90 @@ namespace Emby.Dlna.ContentDirectory /// The GetGenres. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetGenres(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetGenres(BaseItem parent, InternalItemsQuery query) { - var genresResult = _libraryManager.GetGenres(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - var result = new QueryResult<BaseItem> - { - TotalRecordCount = genresResult.TotalRecordCount, - Items = genresResult.Items.Select(i => i.Item1).ToArray() - }; + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var genresResult = _libraryManager.GetGenres(query); - return ToResult(result); + return ToResult(genresResult); } /// <summary> /// Returns the music genres meeting the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicGenres(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetMusicGenres(BaseItem parent, InternalItemsQuery query) { - var genresResult = _libraryManager.GetMusicGenres(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - var result = new QueryResult<BaseItem> - { - TotalRecordCount = genresResult.TotalRecordCount, - Items = genresResult.Items.Select(i => i.Item1).ToArray() - }; + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var genresResult = _libraryManager.GetMusicGenres(query); - return ToResult(result); + return ToResult(genresResult); } /// <summary> /// Returns the music albums by artist that meet the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicAlbumArtists(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetMusicAlbumArtists(BaseItem parent, InternalItemsQuery query) { - var artists = _libraryManager.GetAlbumArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - var result = new QueryResult<BaseItem> - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; + // Don't sort + query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.AncestorIds = new[] { parent.Id }; + var artists = _libraryManager.GetAlbumArtists(query); - return ToResult(result); + return ToResult(artists); } /// <summary> /// Returns the music artists meeting the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicArtists(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> 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<BaseItem> - { - 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); } /// <summary> /// Returns the artists tagged as favourite that meet the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetFavoriteArtists(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> 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<BaseItem> - { - 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); } /// <summary> /// Returns the music playlists meeting the criteria. /// </summary> - /// <param name="user">The user<see cref="User"/>.</param> /// <param name="query">The query<see cref="InternalItemsQuery"/>.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetMusicPlaylists(InternalItemsQuery query) { query.Parent = null; query.IncludeItemTypes = new[] { nameof(Playlist) }; - query.SetUser(user); query.Recursive = true; var result = _libraryManager.GetItemsResult(query); @@ -1389,31 +1022,6 @@ namespace Emby.Dlna.ContentDirectory } /// <summary> - /// Returns the latest music meeting the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> 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); - } - - /// <summary> /// Returns the next up item meeting the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> @@ -1428,7 +1036,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); @@ -1437,47 +1046,23 @@ namespace Emby.Dlna.ContentDirectory } /// <summary> - /// Returns the latest tv meeting the criteria. - /// </summary> - /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetTvLatest(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(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); - } - - /// <summary> - /// Returns the latest movies meeting the criteria. + /// Returns the latest items of [itemType] meeting the criteria. /// </summary> /// <param name="parent">The <see cref="BaseItem"/>.</param> - /// <param name="user">The <see cref="User"/>.</param> /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> + /// <param name="itemType">The item type.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMovieLatest(BaseItem parent, User user, InternalItemsQuery query) + private QueryResult<ServerItem> GetLatest(BaseItem parent, InternalItemsQuery query, string itemType) { query.OrderBy = Array.Empty<(string, SortOrder)>(); var items = _userViewManager.GetLatestItems( new LatestItemsQuery { - UserId = user.Id, - Limit = 50, - IncludeItemTypes = new[] { nameof(Movie) }, + // User cannot be null here as the caller has set it + UserId = query.User!.Id, + Limit = query.Limit ?? 50, + IncludeItemTypes = new[] { itemType }, ParentId = parent?.Id ?? Guid.Empty, GroupItems = true }, @@ -1490,27 +1075,24 @@ namespace Emby.Dlna.ContentDirectory /// Returns music artist items that meet the criteria. /// </summary> /// <param name="item">The <see cref="BaseItem"/>.</param> - /// <param name="parentId">The <see cref="Guid"/>.</param> /// <param name="user">The <see cref="User"/>.</param> /// <param name="sort">The <see cref="SortCriteria"/>.</param> /// <param name="startIndex">The start index.</param> /// <param name="limit">The maximum number to return.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicArtistItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit) + private QueryResult<ServerItem> 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); @@ -1520,18 +1102,16 @@ namespace Emby.Dlna.ContentDirectory /// Returns the genre items meeting the criteria. /// </summary> /// <param name="item">The <see cref="BaseItem"/>.</param> - /// <param name="parentId">The <see cref="Guid"/>.</param> /// <param name="user">The <see cref="User"/>.</param> /// <param name="sort">The <see cref="SortCriteria"/>.</param> /// <param name="startIndex">The start index.</param> /// <param name="limit">The maximum number to return.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit) + private QueryResult<ServerItem> 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[] { @@ -1540,11 +1120,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); @@ -1554,46 +1133,43 @@ namespace Emby.Dlna.ContentDirectory /// Returns the music genre items meeting the criteria. /// </summary> /// <param name="item">The <see cref="BaseItem"/>.</param> - /// <param name="parentId">The <see cref="Guid"/>.</param> /// <param name="user">The <see cref="User"/>.</param> /// <param name="sort">The <see cref="SortCriteria"/>.</param> /// <param name="startIndex">The start index.</param> /// <param name="limit">The maximum number to return.</param> /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> - private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit) + private QueryResult<ServerItem> 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); } /// <summary> - /// Converts a <see cref="BaseItem"/> array into a <see cref="QueryResult{ServerItem}"/>. + /// Converts <see cref="IReadOnlyCollection{BaseItem}"/> into a <see cref="QueryResult{ServerItem}"/>. /// </summary> /// <param name="result">An array of <see cref="BaseItem"/>.</param> /// <returns>A <see cref="QueryResult{ServerItem}"/>.</returns> - private static QueryResult<ServerItem> ToResult(BaseItem[] result) + private static QueryResult<ServerItem> ToResult(IReadOnlyCollection<BaseItem> result) { var serverItems = result - .Select(i => new ServerItem(i)) + .Select(i => new ServerItem(i, null)) .ToArray(); return new QueryResult<ServerItem> { - TotalRecordCount = result.Length, + TotalRecordCount = result.Count, Items = serverItems }; } @@ -1605,10 +1181,12 @@ namespace Emby.Dlna.ContentDirectory /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> private static QueryResult<ServerItem> ToResult(QueryResult<BaseItem> 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<ServerItem> { @@ -1618,35 +1196,34 @@ namespace Emby.Dlna.ContentDirectory } /// <summary> - /// Sets the sorting method on a query. + /// Converts a query result to a <see cref="QueryResult{ServerItem}"/>. /// </summary> - /// <param name="query">The <see cref="InternalItemsQuery"/>.</param> - /// <param name="sort">The <see cref="SortCriteria"/>.</param> - /// <param name="isPreSorted">True if pre-sorted.</param> - private static void SetSorting(InternalItemsQuery query, SortCriteria sort, bool isPreSorted) + /// <param name="result">A <see cref="QueryResult{BaseItem}"/>.</param> + /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> + private static QueryResult<ServerItem> 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<ServerItem> { - query.OrderBy = new[] { (ItemSortBy.SortName, sort.SortOrder) }; - } + TotalRecordCount = result.TotalRecordCount, + Items = serverItems + }; } /// <summary> - /// Apply paging to a query. + /// Gets the sorting method on a query. /// </summary> - /// <param name="result">The <see cref="QueryResult{ServerItem}"/>.</param> - /// <param name="startIndex">The start index.</param> - /// <param name="limit">The maximum number to return.</param> - /// <returns>A <see cref="QueryResult{ServerItem}"/>.</returns> - private static QueryResult<ServerItem> ApplyPaging(QueryResult<ServerItem> result, int? startIndex, int? limit) + /// <param name="sort">The <see cref="SortCriteria"/>.</param> + /// <param name="isPreSorted">True if pre-sorted.</param> + 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) }; } /// <summary> @@ -1657,7 +1234,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); } @@ -1675,37 +1252,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<StubType>(id.AsSpan(0, dividerIndex), true, out var parsedStubType)) { - if (id.StartsWith(name + "_", StringComparison.OrdinalIgnoreCase)) - { - stubType = Enum.Parse<StubType>(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 ff30e6e4af..df05fa9666 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 <see cref="ServerItem"/> class. /// </summary> /// <param name="item">The <see cref="BaseItem"/>.</param> - public ServerItem(BaseItem item) + /// <param name="stubType">The stub type.</param> + 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; } } /// <summary> - /// Gets or sets the underlying base item. + /// Gets the underlying base item. /// </summary> - public BaseItem Item { get; set; } + public BaseItem Item { get; } /// <summary> - /// Gets or sets the DLNA item type. + /// Gets the DLNA item type. /// </summary> - public StubType? StubType { get; set; } + public StubType? StubType { get; } } } diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 0a84f30c4c..b00e1c98af 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -729,7 +729,7 @@ namespace Emby.Dlna.Didl { if (item.PremiereDate.HasValue) { - AddValue(writer, "dc", "date", item.PremiereDate.Value.ToString("o", CultureInfo.InvariantCulture), NsDc); + AddValue(writer, "dc", "date", item.PremiereDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), NsDc); } } diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 73e8a0008e..93efa4b38d 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -112,7 +112,7 @@ namespace Emby.Dlna if (profile == null) { - LogUnmatchedProfile(deviceInfo); + _logger.LogInformation("No matching device profile found. The default will need to be used. \n{@Profile}", deviceInfo); } else { @@ -122,23 +122,6 @@ namespace Emby.Dlna return profile; } - private void LogUnmatchedProfile(DeviceIdentification profile) - { - var builder = new StringBuilder(); - - builder.AppendLine("No matching device profile found. The default will need to be used."); - builder.Append("FriendlyName: ").AppendLine(profile.FriendlyName); - builder.Append("Manufacturer: ").AppendLine(profile.Manufacturer); - builder.Append("ManufacturerUrl: ").AppendLine(profile.ManufacturerUrl); - builder.Append("ModelDescription: ").AppendLine(profile.ModelDescription); - builder.Append("ModelName: ").AppendLine(profile.ModelName); - builder.Append("ModelNumber: ").AppendLine(profile.ModelNumber); - builder.Append("ModelUrl: ").AppendLine(profile.ModelUrl); - builder.Append("SerialNumber: ").AppendLine(profile.SerialNumber); - - _logger.LogInformation(builder.ToString()); - } - /// <summary> /// Attempts to match a device with a profile. /// Rules: @@ -367,7 +350,7 @@ namespace Emby.Dlna Directory.CreateDirectory(systemProfilesPath); var fileOptions = AsyncFile.WriteOptions; - fileOptions.Mode = FileMode.CreateNew; + fileOptions.Mode = FileMode.Create; fileOptions.PreallocationSize = length; using (var fileStream = new FileStream(path, fileOptions)) { @@ -416,7 +399,7 @@ namespace Emby.Dlna } /// <inheritdoc /> - public void UpdateProfile(DeviceProfile profile) + public void UpdateProfile(string profileId, DeviceProfile profile) { profile = ReserializeProfile(profile); @@ -430,7 +413,7 @@ namespace Emby.Dlna throw new ArgumentException("Profile is missing Name"); } - var current = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, profile.Id, StringComparison.OrdinalIgnoreCase)); + var current = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, profileId, StringComparison.OrdinalIgnoreCase)); var newFilename = _fileSystem.GetValidFilename(profile.Name) + ".xml"; var path = Path.Combine(UserProfilesPath, newFilename); diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index c8332e44e4..7fdbd44f00 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -72,7 +72,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> </ItemGroup> </Project> diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 5d252d8dc4..f35d90f21c 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -52,7 +52,6 @@ namespace Emby.Dlna.Main private readonly ISocketFactory _socketFactory; private readonly INetworkManager _networkManager; private readonly object _syncLock = new object(); - private readonly NetworkConfiguration _netConfig; private readonly bool _disabled; private PlayToManager _manager; @@ -125,8 +124,8 @@ namespace Emby.Dlna.Main config); Current = this; - _netConfig = config.GetConfiguration<NetworkConfiguration>("network"); - _disabled = appHost.ListenWithHttps && _netConfig.RequireHttps; + var netConfig = config.GetConfiguration<NetworkConfiguration>("network"); + _disabled = appHost.ListenWithHttps && netConfig.RequireHttps; if (_disabled && _config.GetDlnaConfiguration().EnableServer) { @@ -219,11 +218,6 @@ namespace Emby.Dlna.Main } } - private void LogMessage(string msg) - { - _logger.LogDebug(msg); - } - private void StartDeviceDiscovery(ISsdpCommunicationsServer communicationsServer) { try @@ -268,12 +262,11 @@ namespace Emby.Dlna.Main { _publisher = new SsdpDevicePublisher( _communicationsServer, - _networkManager, MediaBrowser.Common.System.OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost) { - LogFunction = LogMessage, + LogFunction = (msg) => _logger.LogDebug("{Msg}", msg), SupportPnpRootDevice = false }; @@ -318,15 +311,9 @@ namespace Emby.Dlna.Main var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; - _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address); + _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address); - var uri = new UriBuilder(_appHost.GetSmartApiUrl(address.Address) + descriptorUri); - if (!string.IsNullOrEmpty(_appHost.PublishedServerUrl)) - { - // DLNA will only work over http, so we must reset to http:// : {port}. - uri.Scheme = "http"; - uri.Port = _netConfig.HttpServerPortNumber; - } + var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(false) + descriptorUri); var device = new SsdpRootDevice { @@ -412,7 +399,6 @@ namespace Emby.Dlna.Main _imageProcessor, _deviceDiscovery, _httpClientFactory, - _config, _userDataManager, _localization, _mediaSourceManager, diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 7927f5f8f9..294bda5b6a 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; @@ -35,7 +34,6 @@ namespace Emby.Dlna.PlayTo private readonly IServerApplicationHost _appHost; private readonly IImageProcessor _imageProcessor; private readonly IHttpClientFactory _httpClientFactory; - private readonly IServerConfigurationManager _config; private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; @@ -47,7 +45,7 @@ namespace Emby.Dlna.PlayTo private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1); private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); - public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder) + public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder) { _logger = logger; _sessionManager = sessionManager; @@ -58,7 +56,6 @@ namespace Emby.Dlna.PlayTo _imageProcessor = imageProcessor; _deviceDiscovery = deviceDiscovery; _httpClientFactory = httpClientFactory; - _config = config; _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index 581e4a2861..780aad9c18 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -64,7 +64,7 @@ namespace Emby.Dlna.Service requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false); } - Logger.LogDebug("Received control request {0}", requestInfo.LocalName); + Logger.LogDebug("Received control request {LocalName}, params: {@Headers}", requestInfo.LocalName, requestInfo.Headers); var settings = new XmlWriterSettings { |
