Merge pull request #2741 from Bond-009/dlnawarnings2

Fix some warnings
This commit is contained in:
Vasily 2020-04-04 01:38:09 +03:00 committed by GitHub
commit d5cc10d7e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 316 additions and 228 deletions

View file

@ -1,6 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -151,6 +152,7 @@ namespace Emby.Dlna.Api
return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, XMLContentType, () => Task.FromResult<Stream>(new MemoryStream(bytes))); return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, XMLContentType, () => Task.FromResult<Stream>(new MemoryStream(bytes)));
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetContentDirectory request) public object Get(GetContentDirectory request)
{ {
var xml = ContentDirectory.GetServiceXml(); var xml = ContentDirectory.GetServiceXml();
@ -158,6 +160,7 @@ namespace Emby.Dlna.Api
return _resultFactory.GetResult(Request, xml, XMLContentType); return _resultFactory.GetResult(Request, xml, XMLContentType);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetMediaReceiverRegistrar request) public object Get(GetMediaReceiverRegistrar request)
{ {
var xml = MediaReceiverRegistrar.GetServiceXml(); var xml = MediaReceiverRegistrar.GetServiceXml();
@ -165,6 +168,7 @@ namespace Emby.Dlna.Api
return _resultFactory.GetResult(Request, xml, XMLContentType); return _resultFactory.GetResult(Request, xml, XMLContentType);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetConnnectionManager request) public object Get(GetConnnectionManager request)
{ {
var xml = ConnectionManager.GetServiceXml(); var xml = ConnectionManager.GetServiceXml();
@ -313,31 +317,37 @@ namespace Emby.Dlna.Api
return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, contentType, () => Task.FromResult(_dlnaManager.GetIcon(request.Filename).Stream)); return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, contentType, () => Task.FromResult(_dlnaManager.GetIcon(request.Filename).Stream));
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Subscribe(ProcessContentDirectoryEventRequest request) public object Subscribe(ProcessContentDirectoryEventRequest request)
{ {
return ProcessEventRequest(ContentDirectory); return ProcessEventRequest(ContentDirectory);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Subscribe(ProcessConnectionManagerEventRequest request) public object Subscribe(ProcessConnectionManagerEventRequest request)
{ {
return ProcessEventRequest(ConnectionManager); return ProcessEventRequest(ConnectionManager);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Subscribe(ProcessMediaReceiverRegistrarEventRequest request) public object Subscribe(ProcessMediaReceiverRegistrarEventRequest request)
{ {
return ProcessEventRequest(MediaReceiverRegistrar); return ProcessEventRequest(MediaReceiverRegistrar);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Unsubscribe(ProcessContentDirectoryEventRequest request) public object Unsubscribe(ProcessContentDirectoryEventRequest request)
{ {
return ProcessEventRequest(ContentDirectory); return ProcessEventRequest(ContentDirectory);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Unsubscribe(ProcessConnectionManagerEventRequest request) public object Unsubscribe(ProcessConnectionManagerEventRequest request)
{ {
return ProcessEventRequest(ConnectionManager); return ProcessEventRequest(ConnectionManager);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Unsubscribe(ProcessMediaReceiverRegistrarEventRequest request) public object Unsubscribe(ProcessMediaReceiverRegistrarEventRequest request)
{ {
return ProcessEventRequest(MediaReceiverRegistrar); return ProcessEventRequest(MediaReceiverRegistrar);

View file

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
@ -52,6 +53,7 @@ namespace Emby.Dlna.Api
_dlnaManager = dlnaManager; _dlnaManager = dlnaManager;
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetProfileInfos request) public object Get(GetProfileInfos request)
{ {
return _dlnaManager.GetProfileInfos().ToArray(); return _dlnaManager.GetProfileInfos().ToArray();
@ -62,6 +64,7 @@ namespace Emby.Dlna.Api
return _dlnaManager.GetProfile(request.Id); return _dlnaManager.GetProfile(request.Id);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetDefaultProfile request) public object Get(GetDefaultProfile request)
{ {
return _dlnaManager.GetDefaultProfile(); return _dlnaManager.GetDefaultProfile();

View file

@ -78,7 +78,18 @@ namespace Emby.Dlna.ContentDirectory
_profile = profile; _profile = profile;
_config = config; _config = config;
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, mediaEncoder); _didlBuilder = new DidlBuilder(
profile,
user,
imageProcessor,
serverAddress,
accessToken,
userDataManager,
localization,
mediaSourceManager,
Logger,
mediaEncoder,
libraryManager);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -153,7 +164,7 @@ namespace Emby.Dlna.ContentDirectory
{ {
var id = sparams["ObjectID"]; var id = sparams["ObjectID"];
var serverItem = GetItemFromObjectId(id, _user); var serverItem = GetItemFromObjectId(id);
var item = serverItem.Item; var item = serverItem.Item;
@ -276,7 +287,7 @@ namespace Emby.Dlna.ContentDirectory
DidlBuilder.WriteXmlRootAttributes(_profile, writer); DidlBuilder.WriteXmlRootAttributes(_profile, writer);
var serverItem = GetItemFromObjectId(id, _user); var serverItem = GetItemFromObjectId(id);
var item = serverItem.Item; var item = serverItem.Item;
@ -293,7 +304,7 @@ namespace Emby.Dlna.ContentDirectory
else else
{ {
var dlnaOptions = _config.GetDlnaConfiguration(); var dlnaOptions = _config.GetDlnaConfiguration();
_didlBuilder.WriteItemElement(dlnaOptions, writer, item, _user, null, null, deviceId, filter); _didlBuilder.WriteItemElement(writer, item, _user, null, null, deviceId, filter);
} }
provided++; provided++;
@ -320,7 +331,7 @@ namespace Emby.Dlna.ContentDirectory
} }
else else
{ {
_didlBuilder.WriteItemElement(dlnaOptions, writer, childItem, _user, item, serverItem.StubType, deviceId, filter); _didlBuilder.WriteItemElement(writer, childItem, _user, item, serverItem.StubType, deviceId, filter);
} }
} }
} }
@ -387,7 +398,7 @@ namespace Emby.Dlna.ContentDirectory
DidlBuilder.WriteXmlRootAttributes(_profile, writer); DidlBuilder.WriteXmlRootAttributes(_profile, writer);
var serverItem = GetItemFromObjectId(sparams["ContainerID"], _user); var serverItem = GetItemFromObjectId(sparams["ContainerID"]);
var item = serverItem.Item; var item = serverItem.Item;
@ -406,7 +417,7 @@ namespace Emby.Dlna.ContentDirectory
} }
else else
{ {
_didlBuilder.WriteItemElement(dlnaOptions, writer, i, _user, item, serverItem.StubType, deviceId, filter); _didlBuilder.WriteItemElement(writer, i, _user, item, serverItem.StubType, deviceId, filter);
} }
} }
@ -512,11 +523,11 @@ namespace Emby.Dlna.ContentDirectory
} }
else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
{ {
return GetFolders(item, user, stubType, sort, startIndex, limit); return GetFolders(user, startIndex, limit);
} }
else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
{ {
return GetLiveTvChannels(item, user, stubType, sort, startIndex, limit); return GetLiveTvChannels(user, sort, startIndex, limit);
} }
} }
@ -547,7 +558,7 @@ namespace Emby.Dlna.ContentDirectory
return ToResult(queryResult); return ToResult(queryResult);
} }
private QueryResult<ServerItem> GetLiveTvChannels(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit) private QueryResult<ServerItem> GetLiveTvChannels(User user, SortCriteria sort, int? startIndex, int? limit)
{ {
var query = new InternalItemsQuery(user) var query = new InternalItemsQuery(user)
{ {
@ -579,7 +590,7 @@ namespace Emby.Dlna.ContentDirectory
if (stubType.HasValue && stubType.Value == StubType.Playlists) if (stubType.HasValue && stubType.Value == StubType.Playlists)
{ {
return GetMusicPlaylists(item, user, query); return GetMusicPlaylists(user, query);
} }
if (stubType.HasValue && stubType.Value == StubType.Albums) if (stubType.HasValue && stubType.Value == StubType.Albums)
@ -707,7 +718,7 @@ namespace Emby.Dlna.ContentDirectory
if (stubType.HasValue && stubType.Value == StubType.Collections) if (stubType.HasValue && stubType.Value == StubType.Collections)
{ {
return GetMovieCollections(item, user, query); return GetMovieCollections(user, query);
} }
if (stubType.HasValue && stubType.Value == StubType.Favorites) if (stubType.HasValue && stubType.Value == StubType.Favorites)
@ -720,46 +731,42 @@ namespace Emby.Dlna.ContentDirectory
return GetGenres(item, user, query); return GetGenres(item, user, query);
} }
var list = new List<ServerItem>(); var array = new ServerItem[]
list.Add(new ServerItem(item)
{ {
StubType = StubType.ContinueWatching new ServerItem(item)
}); {
StubType = StubType.ContinueWatching
list.Add(new ServerItem(item) },
{ new ServerItem(item)
StubType = StubType.Latest {
}); StubType = StubType.Latest
},
list.Add(new ServerItem(item) new ServerItem(item)
{ {
StubType = StubType.Movies StubType = StubType.Movies
}); },
new ServerItem(item)
list.Add(new ServerItem(item) {
{ StubType = StubType.Collections
StubType = StubType.Collections },
}); new ServerItem(item)
{
list.Add(new ServerItem(item) StubType = StubType.Favorites
{ },
StubType = StubType.Favorites new ServerItem(item)
}); {
StubType = StubType.Genres
list.Add(new ServerItem(item) }
{ };
StubType = StubType.Genres
});
return new QueryResult<ServerItem> return new QueryResult<ServerItem>
{ {
Items = list, Items = array,
TotalRecordCount = list.Count TotalRecordCount = array.Length
}; };
} }
private QueryResult<ServerItem> GetFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit) private QueryResult<ServerItem> GetFolders(User user, int? startIndex, int? limit)
{ {
var folders = _libraryManager.GetUserRootFolder().GetChildren(user, true) var folders = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.OrderBy(i => i.SortName) .OrderBy(i => i.SortName)
@ -792,7 +799,7 @@ namespace Emby.Dlna.ContentDirectory
if (stubType.HasValue && stubType.Value == StubType.NextUp) if (stubType.HasValue && stubType.Value == StubType.NextUp)
{ {
return GetNextUp(item, user, query); return GetNextUp(item, query);
} }
if (stubType.HasValue && stubType.Value == StubType.Latest) if (stubType.HasValue && stubType.Value == StubType.Latest)
@ -910,7 +917,7 @@ namespace Emby.Dlna.ContentDirectory
return ToResult(result); return ToResult(result);
} }
private QueryResult<ServerItem> GetMovieCollections(BaseItem parent, User user, InternalItemsQuery query) private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query)
{ {
query.Recursive = true; query.Recursive = true;
//query.Parent = parent; //query.Parent = parent;
@ -1105,7 +1112,7 @@ namespace Emby.Dlna.ContentDirectory
return ToResult(result); return ToResult(result);
} }
private QueryResult<ServerItem> GetMusicPlaylists(BaseItem parent, User user, InternalItemsQuery query) private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query)
{ {
query.Parent = null; query.Parent = null;
query.IncludeItemTypes = new[] { typeof(Playlist).Name }; query.IncludeItemTypes = new[] { typeof(Playlist).Name };
@ -1134,7 +1141,7 @@ namespace Emby.Dlna.ContentDirectory
return ToResult(items); return ToResult(items);
} }
private QueryResult<ServerItem> GetNextUp(BaseItem parent, User user, InternalItemsQuery query) private QueryResult<ServerItem> GetNextUp(BaseItem parent, InternalItemsQuery query)
{ {
query.OrderBy = Array.Empty<(string, SortOrder)>(); query.OrderBy = Array.Empty<(string, SortOrder)>();
@ -1289,15 +1296,15 @@ namespace Emby.Dlna.ContentDirectory
return result; return result;
} }
private ServerItem GetItemFromObjectId(string id, User user) private ServerItem GetItemFromObjectId(string id)
{ {
return DidlBuilder.IsIdRoot(id) return DidlBuilder.IsIdRoot(id)
? new ServerItem(_libraryManager.GetUserRootFolder()) ? new ServerItem(_libraryManager.GetUserRootFolder())
: ParseItemId(id, user); : ParseItemId(id);
} }
private ServerItem ParseItemId(string id, User user) private ServerItem ParseItemId(string id)
{ {
StubType? stubType = null; StubType? stubType = null;

View file

@ -45,6 +45,7 @@ namespace Emby.Dlna.Didl
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private readonly ILibraryManager _libraryManager;
public DidlBuilder( public DidlBuilder(
DeviceProfile profile, DeviceProfile profile,
@ -56,7 +57,8 @@ namespace Emby.Dlna.Didl
ILocalizationManager localization, ILocalizationManager localization,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
ILogger logger, ILogger logger,
IMediaEncoder mediaEncoder) IMediaEncoder mediaEncoder,
ILibraryManager libraryManager)
{ {
_profile = profile; _profile = profile;
_user = user; _user = user;
@ -68,6 +70,7 @@ namespace Emby.Dlna.Didl
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_logger = logger; _logger = logger;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
_libraryManager = libraryManager;
} }
public static string NormalizeDlnaMediaUrl(string url) public static string NormalizeDlnaMediaUrl(string url)
@ -75,7 +78,7 @@ namespace Emby.Dlna.Didl
return url + "&dlnaheaders=true"; return url + "&dlnaheaders=true";
} }
public string GetItemDidl(DlnaOptions options, BaseItem item, User user, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo) public string GetItemDidl(BaseItem item, User user, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo)
{ {
var settings = new XmlWriterSettings var settings = new XmlWriterSettings
{ {
@ -100,7 +103,7 @@ namespace Emby.Dlna.Didl
WriteXmlRootAttributes(_profile, writer); WriteXmlRootAttributes(_profile, writer);
WriteItemElement(options, writer, item, user, context, null, deviceId, filter, streamInfo); WriteItemElement(writer, item, user, context, null, deviceId, filter, streamInfo);
writer.WriteFullEndElement(); writer.WriteFullEndElement();
//writer.WriteEndDocument(); //writer.WriteEndDocument();
@ -127,7 +130,6 @@ namespace Emby.Dlna.Didl
} }
public void WriteItemElement( public void WriteItemElement(
DlnaOptions options,
XmlWriter writer, XmlWriter writer,
BaseItem item, BaseItem item,
User user, User user,
@ -164,25 +166,23 @@ namespace Emby.Dlna.Didl
// refID? // refID?
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false); // storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
var hasMediaSources = item as IHasMediaSources; if (item is IHasMediaSources)
if (hasMediaSources != null)
{ {
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{ {
AddAudioResource(options, writer, item, deviceId, filter, streamInfo); AddAudioResource(writer, item, deviceId, filter, streamInfo);
} }
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
{ {
AddVideoResource(options, writer, item, deviceId, filter, streamInfo); AddVideoResource(writer, item, deviceId, filter, streamInfo);
} }
} }
AddCover(item, context, null, writer); AddCover(item, null, writer);
writer.WriteFullEndElement(); writer.WriteFullEndElement();
} }
private void AddVideoResource(DlnaOptions options, XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo streamInfo = null) private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo streamInfo = null)
{ {
if (streamInfo == null) if (streamInfo == null)
{ {
@ -226,7 +226,7 @@ namespace Emby.Dlna.Didl
foreach (var contentFeature in contentFeatureList) foreach (var contentFeature in contentFeatureList)
{ {
AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo); AddVideoResource(writer, filter, contentFeature, streamInfo);
} }
var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken); var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken);
@ -283,7 +283,10 @@ namespace Emby.Dlna.Didl
else else
{ {
writer.WriteStartElement(string.Empty, "res", NS_DIDL); writer.WriteStartElement(string.Empty, "res", NS_DIDL);
var protocolInfo = string.Format("http-get:*:text/{0}:*", info.Format.ToLowerInvariant()); var protocolInfo = string.Format(
CultureInfo.InvariantCulture,
"http-get:*:text/{0}:*",
info.Format.ToLowerInvariant());
writer.WriteAttributeString("protocolInfo", protocolInfo); writer.WriteAttributeString("protocolInfo", protocolInfo);
writer.WriteString(info.Url); writer.WriteString(info.Url);
@ -293,7 +296,7 @@ namespace Emby.Dlna.Didl
return true; return true;
} }
private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo) private void AddVideoResource(XmlWriter writer, Filter filter, string contentFeatures, StreamInfo streamInfo)
{ {
writer.WriteStartElement(string.Empty, "res", NS_DIDL); writer.WriteStartElement(string.Empty, "res", NS_DIDL);
@ -335,7 +338,13 @@ namespace Emby.Dlna.Didl
{ {
if (targetWidth.HasValue && targetHeight.HasValue) if (targetWidth.HasValue && targetHeight.HasValue)
{ {
writer.WriteAttributeString("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value)); writer.WriteAttributeString(
"resolution",
string.Format(
CultureInfo.InvariantCulture,
"{0}x{1}",
targetWidth.Value,
targetHeight.Value));
} }
} }
@ -369,17 +378,19 @@ namespace Emby.Dlna.Didl
streamInfo.TargetVideoCodecTag, streamInfo.TargetVideoCodecTag,
streamInfo.IsTargetAVC); streamInfo.IsTargetAVC);
var filename = url.Substring(0, url.IndexOf('?')); var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal));
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
? MimeTypes.GetMimeType(filename) ? MimeTypes.GetMimeType(filename)
: mediaProfile.MimeType; : mediaProfile.MimeType;
writer.WriteAttributeString("protocolInfo", string.Format( writer.WriteAttributeString(
"http-get:*:{0}:{1}", "protocolInfo",
mimeType, string.Format(
contentFeatures CultureInfo.InvariantCulture,
)); "http-get:*:{0}:{1}",
mimeType,
contentFeatures));
writer.WriteString(url); writer.WriteString(url);
@ -420,7 +431,10 @@ namespace Emby.Dlna.Didl
if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value == 0 if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value == 0
&& season.IndexNumber.HasValue && season.IndexNumber.Value != 0) && season.IndexNumber.HasValue && season.IndexNumber.Value != 0)
{ {
return string.Format(_localization.GetLocalizedString("ValueSpecialEpisodeName"), item.Name); return string.Format(
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("ValueSpecialEpisodeName"),
item.Name);
} }
if (item.IndexNumber.HasValue) if (item.IndexNumber.HasValue)
@ -462,7 +476,7 @@ namespace Emby.Dlna.Didl
return item.Name; return item.Name;
} }
private void AddAudioResource(DlnaOptions options, XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null) private void AddAudioResource(XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
{ {
writer.WriteStartElement(string.Empty, "res", NS_DIDL); writer.WriteStartElement(string.Empty, "res", NS_DIDL);
@ -528,7 +542,7 @@ namespace Emby.Dlna.Didl
targetSampleRate, targetSampleRate,
targetAudioBitDepth); targetAudioBitDepth);
var filename = url.Substring(0, url.IndexOf('?')); var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal));
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType) var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
? MimeTypes.GetMimeType(filename) ? MimeTypes.GetMimeType(filename)
@ -544,11 +558,13 @@ namespace Emby.Dlna.Didl
streamInfo.RunTimeTicks ?? 0, streamInfo.RunTimeTicks ?? 0,
streamInfo.TranscodeSeekInfo); streamInfo.TranscodeSeekInfo);
writer.WriteAttributeString("protocolInfo", string.Format( writer.WriteAttributeString(
"http-get:*:{0}:{1}", "protocolInfo",
mimeType, string.Format(
contentFeatures CultureInfo.InvariantCulture,
)); "http-get:*:{0}:{1}",
mimeType,
contentFeatures));
writer.WriteString(url); writer.WriteString(url);
@ -571,7 +587,7 @@ namespace Emby.Dlna.Didl
var clientId = GetClientId(folder, stubType); var clientId = GetClientId(folder, stubType);
if (string.Equals(requestedId, "0")) if (string.Equals(requestedId, "0", StringComparison.Ordinal))
{ {
writer.WriteAttributeString("id", "0"); writer.WriteAttributeString("id", "0");
writer.WriteAttributeString("parentID", "-1"); writer.WriteAttributeString("parentID", "-1");
@ -600,7 +616,7 @@ namespace Emby.Dlna.Didl
AddGeneralProperties(folder, stubType, context, writer, filter); AddGeneralProperties(folder, stubType, context, writer, filter);
AddCover(folder, context, stubType, writer); AddCover(folder, stubType, writer);
writer.WriteFullEndElement(); writer.WriteFullEndElement();
} }
@ -633,7 +649,10 @@ namespace Emby.Dlna.Didl
if (playbackPositionTicks > 0) if (playbackPositionTicks > 0)
{ {
var elementValue = string.Format("BM={0}", Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds).ToString(_usCulture)); var elementValue = string.Format(
CultureInfo.InvariantCulture,
"BM={0}",
Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds));
AddValue(writer, "sec", "dcmInfo", elementValue, secAttribute.Value); AddValue(writer, "sec", "dcmInfo", elementValue, secAttribute.Value);
} }
} }
@ -786,37 +805,36 @@ namespace Emby.Dlna.Didl
private void AddPeople(BaseItem item, XmlWriter writer) private void AddPeople(BaseItem item, XmlWriter writer)
{ {
//var types = new[] if (!item.SupportsPeople)
//{ {
// PersonType.Director, return;
// PersonType.Writer, }
// PersonType.Producer,
// PersonType.Composer,
// "Creator"
//};
//var people = _libraryManager.GetPeople(item); var types = new[]
{
PersonType.Director,
PersonType.Writer,
PersonType.Producer,
PersonType.Composer,
"creator"
};
//var index = 0; // Seeing some LG models locking up due content with large lists of people
// The actual issue might just be due to processing a more metadata than it can handle
var people = _libraryManager.GetPeople(
new InternalPeopleQuery
{
ItemId = item.Id,
Limit = 6
});
//// Seeing some LG models locking up due content with large lists of people foreach (var actor in people)
//// The actual issue might just be due to processing a more metadata than it can handle {
//var limit = 6; var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
?? PersonType.Actor;
//foreach (var actor in people) AddValue(writer, "upnp", type.ToLowerInvariant(), actor.Name, NS_UPNP);
//{ }
// var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
// ?? PersonType.Actor;
// AddValue(writer, "upnp", type.ToLowerInvariant(), actor.Name, NS_UPNP);
// index++;
// if (index >= limit)
// {
// break;
// }
//}
} }
private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter) private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter)
@ -893,7 +911,7 @@ namespace Emby.Dlna.Didl
} }
} }
private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer) private void AddCover(BaseItem item, StubType? stubType, XmlWriter writer)
{ {
ImageDownloadInfo imageInfo = GetImageInfo(item); ImageDownloadInfo imageInfo = GetImageInfo(item);
@ -938,17 +956,8 @@ namespace Emby.Dlna.Didl
} }
private void AddEmbeddedImageAsCover(string name, XmlWriter writer) private void AddImageResElement(
{ BaseItem item,
writer.WriteStartElement("upnp", "albumArtURI", NS_UPNP);
writer.WriteAttributeString("dlna", "profileID", NS_DLNA, _profile.AlbumArtPn);
writer.WriteString(_serverAddress + "/Dlna/icons/people480.jpg");
writer.WriteFullEndElement();
writer.WriteElementString("upnp", "icon", NS_UPNP, _serverAddress + "/Dlna/icons/people48.jpg");
}
private void AddImageResElement(BaseItem item,
XmlWriter writer, XmlWriter writer,
int maxWidth, int maxWidth,
int maxHeight, int maxHeight,
@ -974,13 +983,17 @@ namespace Emby.Dlna.Didl
var contentFeatures = new ContentFeatureBuilder(_profile) var contentFeatures = new ContentFeatureBuilder(_profile)
.BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn); .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
writer.WriteAttributeString("protocolInfo", string.Format( writer.WriteAttributeString(
"http-get:*:{0}:{1}", "protocolInfo",
MimeTypes.GetMimeType("file." + format), string.Format(
contentFeatures CultureInfo.InvariantCulture,
)); "http-get:*:{0}:{1}",
MimeTypes.GetMimeType("file." + format),
contentFeatures));
writer.WriteAttributeString("resolution", string.Format("{0}x{1}", width, height)); writer.WriteAttributeString(
"resolution",
string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
writer.WriteString(albumartUrlInfo.Url); writer.WriteString(albumartUrlInfo.Url);
@ -1119,7 +1132,9 @@ namespace Emby.Dlna.Didl
private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format) private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
{ {
var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0", var url = string.Format(
CultureInfo.InvariantCulture,
"{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0",
_serverAddress, _serverAddress,
info.ItemId.ToString("N", CultureInfo.InvariantCulture), info.ItemId.ToString("N", CultureInfo.InvariantCulture),
info.Type, info.Type,

View file

@ -53,6 +53,6 @@ namespace Emby.Dlna.Didl
_encoding = encoding; _encoding = encoding;
} }
public override Encoding Encoding => (null == _encoding) ? base.Encoding : _encoding; public override Encoding Encoding => _encoding ?? base.Encoding;
} }
} }

View file

@ -346,7 +346,12 @@ namespace Emby.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service"); throw new InvalidOperationException("Unable to find service");
} }
return new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1)); return new SsdpHttpClient(_httpClient).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
avCommands.BuildPost(command, service.ServiceType, 1),
cancellationToken: cancellationToken);
} }
public async Task SetPlay(CancellationToken cancellationToken) public async Task SetPlay(CancellationToken cancellationToken)
@ -515,8 +520,12 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), true) var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
.ConfigureAwait(false); Properties.BaseUrl,
service,
command.Name,
rendererCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
if (result == null || result.Document == null) if (result == null || result.Document == null)
{ {
@ -561,8 +570,12 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), true) var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
.ConfigureAwait(false); Properties.BaseUrl,
service,
command.Name,
rendererCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
if (result == null || result.Document == null) if (result == null || result.Document == null)
return; return;
@ -588,8 +601,12 @@ namespace Emby.Dlna.PlayTo
return null; return null;
} }
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType), false) var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
.ConfigureAwait(false); Properties.BaseUrl,
service,
command.Name,
avCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
if (result == null || result.Document == null) if (result == null || result.Document == null)
{ {
@ -599,7 +616,7 @@ namespace Emby.Dlna.PlayTo
var transportState = var transportState =
result.Document.Descendants(uPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null); result.Document.Descendants(uPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null);
var transportStateValue = transportState == null ? null : transportState.Value; var transportStateValue = transportState?.Value;
if (transportStateValue != null if (transportStateValue != null
&& Enum.TryParse(transportStateValue, true, out TRANSPORTSTATE state)) && Enum.TryParse(transportStateValue, true, out TRANSPORTSTATE state))
@ -626,8 +643,12 @@ namespace Emby.Dlna.PlayTo
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false); var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), false) var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
.ConfigureAwait(false); Properties.BaseUrl,
service,
command.Name,
rendererCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
if (result == null || result.Document == null) if (result == null || result.Document == null)
{ {
@ -689,8 +710,12 @@ namespace Emby.Dlna.PlayTo
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false); var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), false) var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
.ConfigureAwait(false); Properties.BaseUrl,
service,
command.Name,
rendererCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
if (result == null || result.Document == null) if (result == null || result.Document == null)
{ {

View file

@ -27,6 +27,8 @@ namespace Emby.Dlna.PlayTo
{ {
public class PlayToController : ISessionController, IDisposable public class PlayToController : ISessionController, IDisposable
{ {
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
private Device _device; private Device _device;
private readonly SessionInfo _session; private readonly SessionInfo _session;
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
@ -45,9 +47,10 @@ namespace Emby.Dlna.PlayTo
private readonly string _serverAddress; private readonly string _serverAddress;
private readonly string _accessToken; private readonly string _accessToken;
public bool IsSessionActive => !_disposed && _device != null; private readonly List<PlaylistItem> _playlist = new List<PlaylistItem>();
private int _currentPlaylistIndex;
public bool SupportsMediaControl => IsSessionActive; private bool _disposed;
public PlayToController( public PlayToController(
SessionInfo session, SessionInfo session,
@ -83,18 +86,22 @@ namespace Emby.Dlna.PlayTo
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
} }
public bool IsSessionActive => !_disposed && _device != null;
public bool SupportsMediaControl => IsSessionActive;
public void Init(Device device) public void Init(Device device)
{ {
_device = device; _device = device;
_device.OnDeviceUnavailable = OnDeviceUnavailable; _device.OnDeviceUnavailable = OnDeviceUnavailable;
_device.PlaybackStart += _device_PlaybackStart; _device.PlaybackStart += OnDevicePlaybackStart;
_device.PlaybackProgress += _device_PlaybackProgress; _device.PlaybackProgress += OnDevicePlaybackProgress;
_device.PlaybackStopped += _device_PlaybackStopped; _device.PlaybackStopped += OnDevicePlaybackStopped;
_device.MediaChanged += _device_MediaChanged; _device.MediaChanged += OnDeviceMediaChanged;
_device.Start(); _device.Start();
_deviceDiscovery.DeviceLeft += _deviceDiscovery_DeviceLeft; _deviceDiscovery.DeviceLeft += OnDeviceDiscoveryDeviceLeft;
} }
private void OnDeviceUnavailable() private void OnDeviceUnavailable()
@ -110,7 +117,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
void _deviceDiscovery_DeviceLeft(object sender, GenericEventArgs<UpnpDeviceInfo> e) private void OnDeviceDiscoveryDeviceLeft(object sender, GenericEventArgs<UpnpDeviceInfo> e)
{ {
var info = e.Argument; var info = e.Argument;
@ -125,7 +132,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
async void _device_MediaChanged(object sender, MediaChangedEventArgs e) private async void OnDeviceMediaChanged(object sender, MediaChangedEventArgs e)
{ {
if (_disposed) if (_disposed)
{ {
@ -137,15 +144,15 @@ namespace Emby.Dlna.PlayTo
var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager); var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager);
if (streamInfo.Item != null) if (streamInfo.Item != null)
{ {
var positionTicks = GetProgressPositionTicks(e.OldMediaInfo, streamInfo); var positionTicks = GetProgressPositionTicks(streamInfo);
ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks); ReportPlaybackStopped(streamInfo, positionTicks);
} }
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager); streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager);
if (streamInfo.Item == null) return; if (streamInfo.Item == null) return;
var newItemProgress = GetProgressInfo(e.NewMediaInfo, streamInfo); var newItemProgress = GetProgressInfo(streamInfo);
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
} }
@ -155,7 +162,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e) private async void OnDevicePlaybackStopped(object sender, PlaybackStoppedEventArgs e)
{ {
if (_disposed) if (_disposed)
{ {
@ -168,9 +175,9 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.Item == null) return; if (streamInfo.Item == null) return;
var positionTicks = GetProgressPositionTicks(e.MediaInfo, streamInfo); var positionTicks = GetProgressPositionTicks(streamInfo);
ReportPlaybackStopped(e.MediaInfo, streamInfo, positionTicks); ReportPlaybackStopped(streamInfo, positionTicks);
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false); var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
@ -194,7 +201,7 @@ namespace Emby.Dlna.PlayTo
} }
else else
{ {
Playlist.Clear(); _playlist.Clear();
} }
} }
catch (Exception ex) catch (Exception ex)
@ -203,7 +210,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
private async void ReportPlaybackStopped(uBaseObject mediaInfo, StreamParams streamInfo, long? positionTicks) private async void ReportPlaybackStopped(StreamParams streamInfo, long? positionTicks)
{ {
try try
{ {
@ -222,7 +229,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e) private async void OnDevicePlaybackStart(object sender, PlaybackStartEventArgs e)
{ {
if (_disposed) if (_disposed)
{ {
@ -235,7 +242,7 @@ namespace Emby.Dlna.PlayTo
if (info.Item != null) if (info.Item != null)
{ {
var progress = GetProgressInfo(e.MediaInfo, info); var progress = GetProgressInfo(info);
await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
} }
@ -246,7 +253,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e) private async void OnDevicePlaybackProgress(object sender, PlaybackProgressEventArgs e)
{ {
if (_disposed) if (_disposed)
{ {
@ -266,7 +273,7 @@ namespace Emby.Dlna.PlayTo
if (info.Item != null) if (info.Item != null)
{ {
var progress = GetProgressInfo(e.MediaInfo, info); var progress = GetProgressInfo(info);
await _sessionManager.OnPlaybackProgress(progress).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(progress).ConfigureAwait(false);
} }
@ -277,7 +284,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
private long? GetProgressPositionTicks(uBaseObject mediaInfo, StreamParams info) private long? GetProgressPositionTicks(StreamParams info)
{ {
var ticks = _device.Position.Ticks; var ticks = _device.Position.Ticks;
@ -289,13 +296,13 @@ namespace Emby.Dlna.PlayTo
return ticks; return ticks;
} }
private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo, StreamParams info) private PlaybackStartInfo GetProgressInfo(StreamParams info)
{ {
return new PlaybackStartInfo return new PlaybackStartInfo
{ {
ItemId = info.ItemId, ItemId = info.ItemId,
SessionId = _session.Id, SessionId = _session.Id,
PositionTicks = GetProgressPositionTicks(mediaInfo, info), PositionTicks = GetProgressPositionTicks(info),
IsMuted = _device.IsMuted, IsMuted = _device.IsMuted,
IsPaused = _device.IsPaused, IsPaused = _device.IsPaused,
MediaSourceId = info.MediaSourceId, MediaSourceId = info.MediaSourceId,
@ -310,9 +317,7 @@ namespace Emby.Dlna.PlayTo
}; };
} }
#region SendCommands public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
public async Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
{ {
_logger.LogDebug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand); _logger.LogDebug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand);
@ -350,11 +355,12 @@ namespace Emby.Dlna.PlayTo
if (command.PlayCommand == PlayCommand.PlayLast) if (command.PlayCommand == PlayCommand.PlayLast)
{ {
Playlist.AddRange(playlist); _playlist.AddRange(playlist);
} }
if (command.PlayCommand == PlayCommand.PlayNext) if (command.PlayCommand == PlayCommand.PlayNext)
{ {
Playlist.AddRange(playlist); _playlist.AddRange(playlist);
} }
if (!command.ControllingUserId.Equals(Guid.Empty)) if (!command.ControllingUserId.Equals(Guid.Empty))
@ -363,7 +369,7 @@ namespace Emby.Dlna.PlayTo
_session.DeviceName, _session.RemoteEndPoint, user); _session.DeviceName, _session.RemoteEndPoint, user);
} }
await PlayItems(playlist).ConfigureAwait(false); return PlayItems(playlist, cancellationToken);
} }
private Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken) private Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
@ -371,7 +377,7 @@ namespace Emby.Dlna.PlayTo
switch (command.Command) switch (command.Command)
{ {
case PlaystateCommand.Stop: case PlaystateCommand.Stop:
Playlist.Clear(); _playlist.Clear();
return _device.SetStop(CancellationToken.None); return _device.SetStop(CancellationToken.None);
case PlaystateCommand.Pause: case PlaystateCommand.Pause:
@ -387,10 +393,10 @@ namespace Emby.Dlna.PlayTo
return Seek(command.SeekPositionTicks ?? 0); return Seek(command.SeekPositionTicks ?? 0);
case PlaystateCommand.NextTrack: case PlaystateCommand.NextTrack:
return SetPlaylistIndex(_currentPlaylistIndex + 1); return SetPlaylistIndex(_currentPlaylistIndex + 1, cancellationToken);
case PlaystateCommand.PreviousTrack: case PlaystateCommand.PreviousTrack:
return SetPlaylistIndex(_currentPlaylistIndex - 1); return SetPlaylistIndex(_currentPlaylistIndex - 1, cancellationToken);
} }
return Task.CompletedTask; return Task.CompletedTask;
@ -426,14 +432,6 @@ namespace Emby.Dlna.PlayTo
return info.IsDirectStream; return info.IsDirectStream;
} }
#endregion
#region Playlist
private int _currentPlaylistIndex;
private readonly List<PlaylistItem> _playlist = new List<PlaylistItem>();
private List<PlaylistItem> Playlist => _playlist;
private void AddItemFromId(Guid id, List<BaseItem> list) private void AddItemFromId(Guid id, List<BaseItem> list)
{ {
var item = _libraryManager.GetItemById(id); var item = _libraryManager.GetItemById(id);
@ -451,7 +449,7 @@ namespace Emby.Dlna.PlayTo
_dlnaManager.GetDefaultProfile(); _dlnaManager.GetDefaultProfile();
var mediaSources = item is IHasMediaSources var mediaSources = item is IHasMediaSources
? (_mediaSourceManager.GetStaticMediaSources(item, true, user)) ? _mediaSourceManager.GetStaticMediaSources(item, true, user)
: new List<MediaSourceInfo>(); : new List<MediaSourceInfo>();
var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex); var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
@ -459,8 +457,19 @@ namespace Emby.Dlna.PlayTo
playlistItem.StreamUrl = DidlBuilder.NormalizeDlnaMediaUrl(playlistItem.StreamInfo.ToUrl(_serverAddress, _accessToken)); playlistItem.StreamUrl = DidlBuilder.NormalizeDlnaMediaUrl(playlistItem.StreamInfo.ToUrl(_serverAddress, _accessToken));
var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _mediaEncoder) var itemXml = new DidlBuilder(
.GetItemDidl(_config.GetDlnaConfiguration(), item, user, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo); profile,
user,
_imageProcessor,
_serverAddress,
_accessToken,
_userDataManager,
_localization,
_mediaSourceManager,
_logger,
_mediaEncoder,
_libraryManager)
.GetItemDidl(item, user, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
playlistItem.Didl = itemXml; playlistItem.Didl = itemXml;
@ -570,30 +579,31 @@ namespace Emby.Dlna.PlayTo
/// Plays the items. /// Plays the items.
/// </summary> /// </summary>
/// <param name="items">The items.</param> /// <param name="items">The items.</param>
/// <returns></returns> /// <param name="cancellationToken">The cancellation token.</param>
private async Task<bool> PlayItems(IEnumerable<PlaylistItem> items) /// <returns><c>true</c> on success.</returns>
private async Task<bool> PlayItems(IEnumerable<PlaylistItem> items, CancellationToken cancellationToken = default)
{ {
Playlist.Clear(); _playlist.Clear();
Playlist.AddRange(items); _playlist.AddRange(items);
_logger.LogDebug("{0} - Playing {1} items", _session.DeviceName, Playlist.Count); _logger.LogDebug("{0} - Playing {1} items", _session.DeviceName, _playlist.Count);
await SetPlaylistIndex(0).ConfigureAwait(false); await SetPlaylistIndex(0, cancellationToken).ConfigureAwait(false);
return true; return true;
} }
private async Task SetPlaylistIndex(int index) private async Task SetPlaylistIndex(int index, CancellationToken cancellationToken = default)
{ {
if (index < 0 || index >= Playlist.Count) if (index < 0 || index >= _playlist.Count)
{ {
Playlist.Clear(); _playlist.Clear();
await _device.SetStop(CancellationToken.None); await _device.SetStop(cancellationToken).ConfigureAwait(false);
return; return;
} }
_currentPlaylistIndex = index; _currentPlaylistIndex = index;
var currentitem = Playlist[index]; var currentitem = _playlist[index];
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, CancellationToken.None); await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, cancellationToken).ConfigureAwait(false);
var streamInfo = currentitem.StreamInfo; var streamInfo = currentitem.StreamInfo;
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo)) if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo))
@ -602,10 +612,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
#endregion /// <inheritdoc />
private bool _disposed;
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
@ -624,19 +631,17 @@ namespace Emby.Dlna.PlayTo
_device.Dispose(); _device.Dispose();
} }
_device.PlaybackStart -= _device_PlaybackStart; _device.PlaybackStart -= OnDevicePlaybackStart;
_device.PlaybackProgress -= _device_PlaybackProgress; _device.PlaybackProgress -= OnDevicePlaybackProgress;
_device.PlaybackStopped -= _device_PlaybackStopped; _device.PlaybackStopped -= OnDevicePlaybackStopped;
_device.MediaChanged -= _device_MediaChanged; _device.MediaChanged -= OnDeviceMediaChanged;
_deviceDiscovery.DeviceLeft -= _deviceDiscovery_DeviceLeft; _deviceDiscovery.DeviceLeft -= OnDeviceDiscoveryDeviceLeft;
_device.OnDeviceUnavailable = null; _device.OnDeviceUnavailable = null;
_device = null; _device = null;
_disposed = true; _disposed = true;
} }
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
private Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) private Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
{ {
if (Enum.TryParse(command.Name, true, out GeneralCommandType commandType)) if (Enum.TryParse(command.Name, true, out GeneralCommandType commandType))
@ -713,7 +718,7 @@ namespace Emby.Dlna.PlayTo
if (info.Item != null) if (info.Item != null)
{ {
var newPosition = GetProgressPositionTicks(media, info) ?? 0; var newPosition = GetProgressPositionTicks(info) ?? 0;
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null; var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, newIndex, info.SubtitleStreamIndex); var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, newIndex, info.SubtitleStreamIndex);
@ -738,7 +743,7 @@ namespace Emby.Dlna.PlayTo
if (info.Item != null) if (info.Item != null)
{ {
var newPosition = GetProgressPositionTicks(media, info) ?? 0; var newPosition = GetProgressPositionTicks(info) ?? 0;
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null; var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, newIndex); var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, newIndex);
@ -852,8 +857,11 @@ namespace Emby.Dlna.PlayTo
return request; return request;
} }
var index = url.IndexOf('?'); var index = url.IndexOf('?', StringComparison.Ordinal);
if (index == -1) return request; if (index == -1)
{
return request;
}
var query = url.Substring(index + 1); var query = url.Substring(index + 1);
Dictionary<string, string> values = QueryHelpers.ParseQuery(query).ToDictionary(kv => kv.Key, kv => kv.Value.ToString()); Dictionary<string, string> values = QueryHelpers.ParseQuery(query).ToDictionary(kv => kv.Key, kv => kv.Value.ToString());

View file

@ -23,7 +23,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
public class PlayToManager : IDisposable public sealed class PlayToManager : IDisposable
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
@ -231,6 +231,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
/// <inheritdoc />
public void Dispose() public void Dispose()
{ {
_deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered; _deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered;
@ -244,6 +245,9 @@ namespace Emby.Dlna.PlayTo
} }
_sessionLock.Dispose();
_disposeCancellationTokenSource.Dispose();
_disposed = true; _disposed = true;
} }
} }

View file

@ -32,18 +32,15 @@ namespace Emby.Dlna.PlayTo
DeviceService service, DeviceService service,
string command, string command,
string postData, string postData,
bool logRequest = true, string header = null,
string header = null) CancellationToken cancellationToken = default)
{ {
var cancellationToken = CancellationToken.None;
var url = NormalizeServiceUrl(baseUrl, service.ControlUrl); var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
using (var response = await PostSoapDataAsync( using (var response = await PostSoapDataAsync(
url, url,
$"\"{service.ServiceType}#{command}\"", $"\"{service.ServiceType}#{command}\"",
postData, postData,
header, header,
logRequest,
cancellationToken) cancellationToken)
.ConfigureAwait(false)) .ConfigureAwait(false))
using (var stream = response.Content) using (var stream = response.Content)
@ -63,7 +60,7 @@ namespace Emby.Dlna.PlayTo
return serviceUrl; return serviceUrl;
} }
if (!serviceUrl.StartsWith("/")) if (!serviceUrl.StartsWith("/", StringComparison.Ordinal))
{ {
serviceUrl = "/" + serviceUrl; serviceUrl = "/" + serviceUrl;
} }
@ -127,7 +124,6 @@ namespace Emby.Dlna.PlayTo
string soapAction, string soapAction,
string postData, string postData,
string header, string header,
bool logRequest,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (soapAction[0] != '\"') if (soapAction[0] != '\"')

View file

@ -134,19 +134,19 @@ namespace Emby.Notifications.Api
_userManager = userManager; _userManager = userManager;
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetNotificationTypes request) public object Get(GetNotificationTypes request)
{ {
return _notificationManager.GetNotificationTypes(); return _notificationManager.GetNotificationTypes();
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetNotificationServices request) public object Get(GetNotificationServices request)
{ {
return _notificationManager.GetNotificationServices().ToList(); return _notificationManager.GetNotificationServices().ToList();
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetNotificationsSummary request) public object Get(GetNotificationsSummary request)
{ {
return new NotificationsSummary return new NotificationsSummary
@ -170,17 +170,17 @@ namespace Emby.Notifications.Api
return _notificationManager.SendNotification(notification, CancellationToken.None); return _notificationManager.SendNotification(notification, CancellationToken.None);
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public void Post(MarkRead request) public void Post(MarkRead request)
{ {
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public void Post(MarkUnread request) public void Post(MarkUnread request)
{ {
} }
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetNotifications request) public object Get(GetNotifications request)
{ {
return new NotificationResult(); return new NotificationResult();

View file

@ -5011,6 +5011,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
commandText += " order by ListOrder"; commandText += " order by ListOrder";
if (query.Limit > 0)
{
commandText += " LIMIT " + query.Limit;
}
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
{ {
var list = new List<string>(); var list = new List<string>();
@ -5049,6 +5054,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
commandText += " order by ListOrder"; commandText += " order by ListOrder";
if (query.Limit > 0)
{
commandText += " LIMIT " + query.Limit;
}
using (var connection = GetConnection(true)) using (var connection = GetConnection(true))
{ {
var list = new List<PersonInfo>(); var list = new List<PersonInfo>();

View file

@ -4,11 +4,21 @@ namespace MediaBrowser.Controller.Entities
{ {
public class InternalPeopleQuery public class InternalPeopleQuery
{ {
/// <summary>
/// Gets or sets the maximum number of items the query should return.
/// <summary>
public int Limit { get; set; }
public Guid ItemId { get; set; } public Guid ItemId { get; set; }
public string[] PersonTypes { get; set; } public string[] PersonTypes { get; set; }
public string[] ExcludePersonTypes { get; set; } public string[] ExcludePersonTypes { get; set; }
public int? MaxListOrder { get; set; } public int? MaxListOrder { get; set; }
public Guid AppearsInItemId { get; set; } public Guid AppearsInItemId { get; set; }
public string NameContains { get; set; } public string NameContains { get; set; }
public InternalPeopleQuery() public InternalPeopleQuery()