aboutsummaryrefslogtreecommitdiff
path: root/Emby.Dlna
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Dlna')
-rw-r--r--Emby.Dlna/ContentDirectory/ControlHandler.cs1113
-rw-r--r--Emby.Dlna/ContentDirectory/ServerItem.cs19
-rw-r--r--Emby.Dlna/Didl/DidlBuilder.cs42
-rw-r--r--Emby.Dlna/Didl/Filter.cs3
-rw-r--r--Emby.Dlna/DlnaManager.cs49
-rw-r--r--Emby.Dlna/Emby.Dlna.csproj9
-rw-r--r--Emby.Dlna/Eventing/DlnaEventManager.cs8
-rw-r--r--Emby.Dlna/Main/DlnaEntryPoint.cs24
-rw-r--r--Emby.Dlna/PlayTo/Device.cs67
-rw-r--r--Emby.Dlna/PlayTo/PlayToController.cs14
-rw-r--r--Emby.Dlna/PlayTo/PlayToManager.cs5
-rw-r--r--Emby.Dlna/PlayTo/SsdpHttpClient.cs8
-rw-r--r--Emby.Dlna/PlayTo/TransportCommands.cs2
-rw-r--r--Emby.Dlna/Profiles/DefaultProfile.cs3
-rw-r--r--Emby.Dlna/Server/DescriptionXmlBuilder.cs13
-rw-r--r--Emby.Dlna/Service/BaseControlHandler.cs2
-rw-r--r--Emby.Dlna/Service/ServiceXmlBuilder.cs12
17 files changed, 450 insertions, 943 deletions
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index ac336e5dcc..010f90c624 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -18,23 +18,16 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
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;
using Microsoft.Extensions.Logging;
-using Book = MediaBrowser.Controller.Entities.Book;
-using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
-using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
-using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
-using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Dlna.ContentDirectory
{
@@ -50,7 +43,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 +96,6 @@ namespace Emby.Dlna.ContentDirectory
_userViewManager = userViewManager;
_tvSeriesManager = tvSeriesManager;
_profile = profile;
- _config = config;
_didlBuilder = new DidlBuilder(
profile,
@@ -291,9 +282,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 +321,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 +438,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,48 +500,38 @@ 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,
- ExcludeItemTypes = new[] { nameof(Book) },
+ ExcludeItemTypes = new[] { BaseItemKind.Book },
IsFolder = isFolder,
MediaTypes = mediaTypes,
DtoOptions = GetDtoOptions()
@@ -587,52 +559,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;
@@ -642,13 +611,12 @@ namespace Emby.Dlna.ContentDirectory
Limit = limit,
StartIndex = startIndex,
IsVirtualItem = false,
- ExcludeItemTypes = new[] { nameof(Book) },
+ ExcludeItemTypes = new[] { BaseItemKind.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 +636,9 @@ namespace Emby.Dlna.ContentDirectory
{
StartIndex = startIndex,
Limit = limit,
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvChannel },
+ OrderBy = GetOrderBy(sort, false)
};
- query.IncludeItemTypes = new[] { nameof(LiveTvChannel) };
-
- SetSorting(query, sort, false);
var result = _libraryManager.GetItemsResult(query);
@@ -693,117 +660,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, BaseItemKind.Audio);
+ case StubType.Playlists:
+ return GetMusicPlaylists(query);
+ case StubType.Albums:
+ return GetChildrenOfItem(item, query, BaseItemKind.MusicAlbum);
+ case StubType.Artists:
+ return GetMusicArtists(item, query);
+ case StubType.AlbumArtists:
+ return GetMusicAlbumArtists(item, query);
+ case StubType.FavoriteAlbums:
+ return GetChildrenOfItem(item, query, BaseItemKind.MusicAlbum, true);
+ case StubType.FavoriteArtists:
+ return GetFavoriteArtists(item, query);
+ case StubType.FavoriteSongs:
+ return GetChildrenOfItem(item, query, BaseItemKind.Audio, true);
+ case StubType.Songs:
+ return GetChildrenOfItem(item, query, BaseItemKind.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 +729,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, BaseItemKind.Movie);
+ case StubType.Movies:
+ return GetChildrenOfItem(item, query, BaseItemKind.Movie);
+ case StubType.Collections:
+ return GetMovieCollections(query);
+ case StubType.Favorites:
+ return GetChildrenOfItem(item, query, BaseItemKind.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 +780,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 +812,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, BaseItemKind.Episode);
+ case StubType.Series:
+ return GetChildrenOfItem(item, query, BaseItemKind.Series);
+ case StubType.FavoriteSeries:
+ return GetChildrenOfItem(item, query, BaseItemKind.Series, true);
+ case StubType.FavoriteEpisodes:
+ return GetChildrenOfItem(item, query, BaseItemKind.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 +861,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 +875,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,76 +885,12 @@ 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)
- {
- query.Recursive = true;
- // query.Parent = parent;
- query.SetUser(user);
-
- query.IncludeItemTypes = new[] { nameof(BoxSet) };
-
- var result = _libraryManager.GetItemsResult(query);
-
- return ToResult(result);
- }
-
- /// <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)
+ private QueryResult<ServerItem> GetMovieCollections(InternalItemsQuery query)
{
query.Recursive = true;
- query.Parent = parent;
- query.SetUser(user);
- query.IsFavorite = true;
- query.IncludeItemTypes = new[] { nameof(Audio) };
+ query.IncludeItemTypes = new[] { BaseItemKind.BoxSet };
var result = _libraryManager.GetItemsResult(query);
@@ -1164,79 +898,19 @@ namespace Emby.Dlna.ContentDirectory
}
/// <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, BaseItemKind 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 +922,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.IncludeItemTypes = new[] { BaseItemKind.Playlist };
query.Recursive = true;
var result = _libraryManager.GetItemsResult(query);
@@ -1389,31 +1014,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 +1028,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 +1038,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, BaseItemKind 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 +1067,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) },
+ IncludeItemTypes = new[] { BaseItemKind.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,31 +1094,28 @@ 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[]
{
- nameof(Movie),
- nameof(Series)
+ BaseItemKind.Movie,
+ BaseItemKind.Series
},
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 +1125,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) },
+ IncludeItemTypes = new[] { BaseItemKind.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 +1173,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 +1188,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 +1226,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 +1244,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 c000784997..6803b3b875 100644
--- a/Emby.Dlna/Didl/DidlBuilder.cs
+++ b/Emby.Dlna/Didl/DidlBuilder.cs
@@ -41,8 +41,6 @@ namespace Emby.Dlna.Didl
private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/";
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
private readonly DeviceProfile _profile;
private readonly IImageProcessor _imageProcessor;
private readonly string _serverAddress;
@@ -317,7 +315,7 @@ namespace Emby.Dlna.Didl
if (mediaSource.RunTimeTicks.HasValue)
{
- writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
+ writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture));
}
if (filter.Contains("res@size"))
@@ -328,7 +326,7 @@ namespace Emby.Dlna.Didl
if (size.HasValue)
{
- writer.WriteAttributeString("size", size.Value.ToString(_usCulture));
+ writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture));
}
}
}
@@ -342,7 +340,7 @@ namespace Emby.Dlna.Didl
if (targetChannels.HasValue)
{
- writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
+ writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture));
}
if (filter.Contains("res@resolution"))
@@ -361,12 +359,12 @@ namespace Emby.Dlna.Didl
if (targetSampleRate.HasValue)
{
- writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
+ writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture));
}
if (totalBitrate.HasValue)
{
- writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(_usCulture));
+ writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(CultureInfo.InvariantCulture));
}
var mediaProfile = _profile.GetVideoMediaProfile(
@@ -552,7 +550,7 @@ namespace Emby.Dlna.Didl
if (mediaSource.RunTimeTicks.HasValue)
{
- writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
+ writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture));
}
if (filter.Contains("res@size"))
@@ -563,7 +561,7 @@ namespace Emby.Dlna.Didl
if (size.HasValue)
{
- writer.WriteAttributeString("size", size.Value.ToString(_usCulture));
+ writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture));
}
}
}
@@ -575,17 +573,17 @@ namespace Emby.Dlna.Didl
if (targetChannels.HasValue)
{
- writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
+ writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture));
}
if (targetSampleRate.HasValue)
{
- writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
+ writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture));
}
if (targetAudioBitrate.HasValue)
{
- writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(_usCulture));
+ writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(CultureInfo.InvariantCulture));
}
var mediaProfile = _profile.GetAudioMediaProfile(
@@ -639,7 +637,7 @@ namespace Emby.Dlna.Didl
writer.WriteAttributeString("restricted", "1");
writer.WriteAttributeString("searchable", "1");
- writer.WriteAttributeString("childCount", childCount.ToString(_usCulture));
+ writer.WriteAttributeString("childCount", childCount.ToString(CultureInfo.InvariantCulture));
var clientId = GetClientId(folder, stubType);
@@ -731,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);
}
}
@@ -931,11 +929,11 @@ namespace Emby.Dlna.Didl
if (item.IndexNumber.HasValue)
{
- AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp);
+ AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp);
if (item is Episode)
{
- AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp);
+ AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp);
}
}
}
@@ -991,7 +989,7 @@ namespace Emby.Dlna.Didl
writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
}
- writer.WriteString(albumArtUrlInfo.url);
+ writer.WriteString(albumArtUrlInfo.Url);
writer.WriteFullEndElement();
// TODO: Remove these default values
@@ -1000,7 +998,7 @@ namespace Emby.Dlna.Didl
_profile.MaxIconWidth ?? 48,
_profile.MaxIconHeight ?? 48,
"jpg");
- writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.url);
+ writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.Url);
if (!_profile.EnableAlbumArtInDidl)
{
@@ -1047,8 +1045,8 @@ namespace Emby.Dlna.Didl
// Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail
// rather than using a larger one when available
- var width = albumartUrlInfo.width ?? maxWidth;
- var height = albumartUrlInfo.height ?? maxHeight;
+ var width = albumartUrlInfo.Width ?? maxWidth;
+ var height = albumartUrlInfo.Height ?? maxHeight;
var contentFeatures = ContentFeatureBuilder.BuildImageHeader(_profile, format, width, height, imageInfo.IsDirectStream, org_Pn);
@@ -1064,7 +1062,7 @@ namespace Emby.Dlna.Didl
"resolution",
string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
- writer.WriteString(albumartUrlInfo.url);
+ writer.WriteString(albumartUrlInfo.Url);
writer.WriteFullEndElement();
}
@@ -1202,7 +1200,7 @@ namespace Emby.Dlna.Didl
return id;
}
- private (string url, int? width, int? height) GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
+ private (string Url, int? Width, int? Height) GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
{
var url = string.Format(
CultureInfo.InvariantCulture,
diff --git a/Emby.Dlna/Didl/Filter.cs b/Emby.Dlna/Didl/Filter.cs
index d703f043eb..6db6f3ae30 100644
--- a/Emby.Dlna/Didl/Filter.cs
+++ b/Emby.Dlna/Didl/Filter.cs
@@ -17,8 +17,7 @@ namespace Emby.Dlna.Didl
public Filter(string filter)
{
_all = string.Equals(filter, "*", StringComparison.OrdinalIgnoreCase);
-
- _fields = (filter ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries);
+ _fields = filter.Split(',', StringSplitOptions.RemoveEmptyEntries);
}
public bool Contains(string field)
diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs
index 8fe9d484e7..f2a0548c2d 100644
--- a/Emby.Dlna/DlnaManager.cs
+++ b/Emby.Dlna/DlnaManager.cs
@@ -5,7 +5,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
-using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -84,8 +83,7 @@ namespace Emby.Dlna
{
lock (_profiles)
{
- var list = _profiles.Values.ToList();
- return list
+ return _profiles.Values
.OrderBy(i => i.Item1.Info.Type == DeviceProfileType.User ? 0 : 1)
.ThenBy(i => i.Item1.Info.Name)
.Select(i => i.Item2)
@@ -112,7 +110,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 +120,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:
@@ -244,11 +225,8 @@ namespace Emby.Dlna
{
try
{
- var xmlFies = _fileSystem.GetFilePaths(path)
+ return _fileSystem.GetFilePaths(path)
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
- .ToList();
-
- return xmlFies
.Select(i => ParseProfileFile(i, type))
.Where(i => i != null)
.ToList()!; // We just filtered out all the nulls
@@ -270,11 +248,8 @@ namespace Emby.Dlna
try
{
- DeviceProfile profile;
-
var tempProfile = (DeviceProfile)_xmlSerializer.DeserializeFromFile(typeof(DeviceProfile), path);
-
- profile = ReserializeProfile(tempProfile);
+ var profile = ReserializeProfile(tempProfile);
profile.Id = path.ToLowerInvariant().GetMD5().ToString("N", CultureInfo.InvariantCulture);
@@ -313,8 +288,7 @@ namespace Emby.Dlna
{
lock (_profiles)
{
- var list = _profiles.Values.ToList();
- return list
+ return _profiles.Values
.Select(i => i.Item1)
.OrderBy(i => i.Info.Type == DeviceProfileType.User ? 0 : 1)
.ThenBy(i => i.Info.Name);
@@ -359,14 +333,17 @@ namespace Emby.Dlna
// The stream should exist as we just got its name from GetManifestResourceNames
using (var stream = _assembly.GetManifestResourceStream(name)!)
{
+ var length = stream.Length;
var fileInfo = _fileSystem.GetFileInfo(path);
- if (!fileInfo.Exists || fileInfo.Length != stream.Length)
+ if (!fileInfo.Exists || fileInfo.Length != length)
{
Directory.CreateDirectory(systemProfilesPath);
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ var fileOptions = AsyncFile.WriteOptions;
+ fileOptions.Mode = FileMode.Create;
+ fileOptions.PreallocationSize = length;
+ using (var fileStream = new FileStream(path, fileOptions))
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
}
@@ -413,7 +390,7 @@ namespace Emby.Dlna
}
/// <inheritdoc />
- public void UpdateProfile(DeviceProfile profile)
+ public void UpdateProfile(string profileId, DeviceProfile profile)
{
profile = ReserializeProfile(profile);
@@ -427,7 +404,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 1d4e3b047d..fd95041fe7 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -20,13 +20,16 @@
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
- <AnalysisMode>AllDisabledByDefault</AnalysisMode>
+ </PropertyGroup>
+
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
@@ -73,7 +76,7 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
+ <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
</ItemGroup>
</Project>
diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs
index b39bd5ce9b..d17e238715 100644
--- a/Emby.Dlna/Eventing/DlnaEventManager.cs
+++ b/Emby.Dlna/Eventing/DlnaEventManager.cs
@@ -26,8 +26,6 @@ namespace Emby.Dlna.Eventing
private readonly ILogger _logger;
private readonly IHttpClientFactory _httpClientFactory;
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
@@ -83,7 +81,7 @@ namespace Emby.Dlna.Eventing
if (!string.IsNullOrEmpty(header))
{
// Starts with SECOND-
- if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, _usCulture, out var val))
+ if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return val;
}
@@ -106,7 +104,7 @@ namespace Emby.Dlna.Eventing
var response = new EventSubscriptionResponse(string.Empty, "text/plain");
response.Headers["SID"] = subscriptionId;
- response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString;
+ response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(CultureInfo.InvariantCulture)) : requestedTimeoutString;
return response;
}
@@ -163,7 +161,7 @@ namespace Emby.Dlna.Eventing
options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType);
options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange");
options.Headers.TryAddWithoutValidation("SID", subscription.Id);
- options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture));
+ options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(CultureInfo.InvariantCulture));
try
{
diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs
index 5d252d8dc4..08f639d932 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>(NetworkConfigurationStore.StoreKey);
+ _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/Device.cs b/Emby.Dlna/PlayTo/Device.cs
index 11fcd81cff..34fb8fddd6 100644
--- a/Emby.Dlna/PlayTo/Device.cs
+++ b/Emby.Dlna/PlayTo/Device.cs
@@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo
{
public class Device : IDisposable
{
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger _logger;
@@ -640,7 +638,7 @@ namespace Emby.Dlna.PlayTo
return;
}
- Volume = int.Parse(volumeValue, UsCulture);
+ Volume = int.Parse(volumeValue, CultureInfo.InvariantCulture);
if (Volume > 0)
{
@@ -842,7 +840,7 @@ namespace Emby.Dlna.PlayTo
if (!string.IsNullOrWhiteSpace(duration)
&& !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
- Duration = TimeSpan.Parse(duration, UsCulture);
+ Duration = TimeSpan.Parse(duration, CultureInfo.InvariantCulture);
}
else
{
@@ -854,7 +852,7 @@ namespace Emby.Dlna.PlayTo
if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
- Position = TimeSpan.Parse(position, UsCulture);
+ Position = TimeSpan.Parse(position, CultureInfo.InvariantCulture);
}
var track = result.Document.Descendants("TrackMetaData").FirstOrDefault();
@@ -1181,6 +1179,7 @@ namespace Emby.Dlna.PlayTo
return new Device(deviceProperties, httpClientFactory, logger);
}
+#nullable enable
private static DeviceIcon CreateIcon(XElement element)
{
if (element == null)
@@ -1188,68 +1187,60 @@ namespace Emby.Dlna.PlayTo
throw new ArgumentNullException(nameof(element));
}
- var mimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype"));
var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));
- var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth"));
- var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url"));
- var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture);
- var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
+ _ = int.TryParse(width, NumberStyles.Integer, CultureInfo.InvariantCulture, out var widthValue);
+ _ = int.TryParse(height, NumberStyles.Integer, CultureInfo.InvariantCulture, out var heightValue);
return new DeviceIcon
{
- Depth = depth,
+ Depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth")) ?? string.Empty,
Height = heightValue,
- MimeType = mimeType,
- Url = url,
+ MimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype")) ?? string.Empty,
+ Url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url")) ?? string.Empty,
Width = widthValue
};
}
private static DeviceService Create(XElement element)
- {
- var type = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType"));
- var id = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId"));
- var scpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL"));
- var controlURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL"));
- var eventSubURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL"));
-
- return new DeviceService
- {
- ControlUrl = controlURL,
- EventSubUrl = eventSubURL,
- ScpdUrl = scpdUrl,
- ServiceId = id,
- ServiceType = type
+ => new DeviceService()
+ {
+ ControlUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL")) ?? string.Empty,
+ EventSubUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL")) ?? string.Empty,
+ ScpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL")) ?? string.Empty,
+ ServiceId = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId")) ?? string.Empty,
+ ServiceType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType")) ?? string.Empty
};
- }
- private void UpdateMediaInfo(UBaseObject mediaInfo, TransportState state)
+ private void UpdateMediaInfo(UBaseObject? mediaInfo, TransportState state)
{
TransportState = state;
var previousMediaInfo = CurrentMediaInfo;
CurrentMediaInfo = mediaInfo;
- if (previousMediaInfo == null && mediaInfo != null)
+ if (mediaInfo == null)
{
- if (state != TransportState.Stopped)
+ if (previousMediaInfo != null)
{
- OnPlaybackStart(mediaInfo);
+ OnPlaybackStop(previousMediaInfo);
}
}
- else if (mediaInfo != null && previousMediaInfo != null && !mediaInfo.Equals(previousMediaInfo))
+ else if (previousMediaInfo == null)
{
- OnMediaChanged(previousMediaInfo, mediaInfo);
+ if (state != TransportState.Stopped)
+ {
+ OnPlaybackStart(mediaInfo);
+ }
}
- else if (mediaInfo == null && previousMediaInfo != null)
+ else if (mediaInfo.Equals(previousMediaInfo))
{
- OnPlaybackStop(previousMediaInfo);
+ OnPlaybackProgress(mediaInfo);
}
- else if (mediaInfo != null && mediaInfo.Equals(previousMediaInfo))
+ else
{
- OnPlaybackProgress(mediaInfo);
+ OnMediaChanged(previousMediaInfo, mediaInfo);
}
}
diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs
index 0e49fd2c02..d0c9df68e3 100644
--- a/Emby.Dlna/PlayTo/PlayToController.cs
+++ b/Emby.Dlna/PlayTo/PlayToController.cs
@@ -30,8 +30,6 @@ namespace Emby.Dlna.PlayTo
{
public class PlayToController : ISessionController, IDisposable
{
- private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
-
private readonly SessionInfo _session;
private readonly ISessionManager _sessionManager;
private readonly ILibraryManager _libraryManager;
@@ -212,9 +210,9 @@ namespace Emby.Dlna.PlayTo
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
- var duration = mediaSource == null ?
- (_device.Duration == null ? (long?)null : _device.Duration.Value.Ticks) :
- mediaSource.RunTimeTicks;
+ var duration = mediaSource == null
+ ? _device.Duration?.Ticks
+ : mediaSource.RunTimeTicks;
var playedToCompletion = positionTicks.HasValue && positionTicks.Value == 0;
@@ -716,7 +714,7 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.SetAudioStreamIndex:
if (command.Arguments.TryGetValue("Index", out string index))
{
- if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
+ if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return SetAudioStreamIndex(val);
}
@@ -728,7 +726,7 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.SetSubtitleStreamIndex:
if (command.Arguments.TryGetValue("Index", out index))
{
- if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
+ if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return SetSubtitleStreamIndex(val);
}
@@ -740,7 +738,7 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.SetVolume:
if (command.Arguments.TryGetValue("Volume", out string vol))
{
- if (int.TryParse(vol, NumberStyles.Integer, _usCulture, out var volume))
+ if (int.TryParse(vol, NumberStyles.Integer, CultureInfo.InvariantCulture, out var volume))
{
return _device.SetVolume(volume, cancellationToken);
}
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/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs
index 4b92fbff43..cade7b4c2c 100644
--- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs
+++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs
@@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo
private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
private const string FriendlyName = "Jellyfin";
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
private readonly IHttpClientFactory _httpClientFactory;
public SsdpHttpClient(IHttpClientFactory httpClientFactory)
@@ -80,10 +78,10 @@ namespace Emby.Dlna.PlayTo
{
using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url);
options.Headers.UserAgent.ParseAdd(USERAGENT);
- options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture));
- options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">");
+ options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(CultureInfo.InvariantCulture));
+ options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(CultureInfo.InvariantCulture) + ">");
options.Headers.TryAddWithoutValidation("NT", "upnp:event");
- options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture));
+ options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(CultureInfo.InvariantCulture));
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(options, HttpCompletionOption.ResponseHeadersRead)
diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs
index b58669355d..d373b57f55 100644
--- a/Emby.Dlna/PlayTo/TransportCommands.cs
+++ b/Emby.Dlna/PlayTo/TransportCommands.cs
@@ -175,7 +175,7 @@ namespace Emby.Dlna.PlayTo
var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
(state.AllowedValues.Count > 0 ? state.AllowedValues[0] : value);
- return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
+ return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType, sendValue);
}
return string.Format(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", argument.Name, value);
diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs
index 8eaf12ba9a..8f4f2bd384 100644
--- a/Emby.Dlna/Profiles/DefaultProfile.cs
+++ b/Emby.Dlna/Profiles/DefaultProfile.cs
@@ -167,8 +167,7 @@ namespace Emby.Dlna.Profiles
public void AddXmlRootAttribute(string name, string value)
{
- var atts = XmlRootAttributes ?? System.Array.Empty<XmlAttribute>();
- var list = atts.ToList();
+ var list = XmlRootAttributes.ToList();
list.Add(new XmlAttribute
{
diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs
index 09525aae4e..8adaaea77e 100644
--- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs
+++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs
@@ -15,7 +15,6 @@ namespace Emby.Dlna.Server
{
private readonly DeviceProfile _profile;
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly string _serverUdn;
private readonly string _serverAddress;
private readonly string _serverName;
@@ -190,16 +189,16 @@ namespace Emby.Dlna.Server
builder.Append("<icon>");
builder.Append("<mimetype>")
- .Append(SecurityElement.Escape(icon.MimeType ?? string.Empty))
+ .Append(SecurityElement.Escape(icon.MimeType))
.Append("</mimetype>");
builder.Append("<width>")
- .Append(SecurityElement.Escape(icon.Width.ToString(_usCulture)))
+ .Append(SecurityElement.Escape(icon.Width.ToString(CultureInfo.InvariantCulture)))
.Append("</width>");
builder.Append("<height>")
- .Append(SecurityElement.Escape(icon.Height.ToString(_usCulture)))
+ .Append(SecurityElement.Escape(icon.Height.ToString(CultureInfo.InvariantCulture)))
.Append("</height>");
builder.Append("<depth>")
- .Append(SecurityElement.Escape(icon.Depth ?? string.Empty))
+ .Append(SecurityElement.Escape(icon.Depth))
.Append("</depth>");
builder.Append("<url>")
.Append(BuildUrl(icon.Url))
@@ -220,10 +219,10 @@ namespace Emby.Dlna.Server
builder.Append("<service>");
builder.Append("<serviceType>")
- .Append(SecurityElement.Escape(service.ServiceType ?? string.Empty))
+ .Append(SecurityElement.Escape(service.ServiceType))
.Append("</serviceType>");
builder.Append("<serviceId>")
- .Append(SecurityElement.Escape(service.ServiceId ?? string.Empty))
+ .Append(SecurityElement.Escape(service.ServiceId))
.Append("</serviceId>");
builder.Append("<SCPDURL>")
.Append(BuildUrl(service.ScpdUrl))
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
{
diff --git a/Emby.Dlna/Service/ServiceXmlBuilder.cs b/Emby.Dlna/Service/ServiceXmlBuilder.cs
index 1e56d09b29..6e0bc6ad8b 100644
--- a/Emby.Dlna/Service/ServiceXmlBuilder.cs
+++ b/Emby.Dlna/Service/ServiceXmlBuilder.cs
@@ -38,7 +38,7 @@ namespace Emby.Dlna.Service
builder.Append("<action>");
builder.Append("<name>")
- .Append(SecurityElement.Escape(item.Name ?? string.Empty))
+ .Append(SecurityElement.Escape(item.Name))
.Append("</name>");
builder.Append("<argumentList>");
@@ -48,13 +48,13 @@ namespace Emby.Dlna.Service
builder.Append("<argument>");
builder.Append("<name>")
- .Append(SecurityElement.Escape(argument.Name ?? string.Empty))
+ .Append(SecurityElement.Escape(argument.Name))
.Append("</name>");
builder.Append("<direction>")
- .Append(SecurityElement.Escape(argument.Direction ?? string.Empty))
+ .Append(SecurityElement.Escape(argument.Direction))
.Append("</direction>");
builder.Append("<relatedStateVariable>")
- .Append(SecurityElement.Escape(argument.RelatedStateVariable ?? string.Empty))
+ .Append(SecurityElement.Escape(argument.RelatedStateVariable))
.Append("</relatedStateVariable>");
builder.Append("</argument>");
@@ -81,10 +81,10 @@ namespace Emby.Dlna.Service
.Append("\">");
builder.Append("<name>")
- .Append(SecurityElement.Escape(item.Name ?? string.Empty))
+ .Append(SecurityElement.Escape(item.Name))
.Append("</name>");
builder.Append("<dataType>")
- .Append(SecurityElement.Escape(item.DataType ?? string.Empty))
+ .Append(SecurityElement.Escape(item.DataType))
.Append("</dataType>");
if (item.AllowedValues.Count > 0)