mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-08 23:00:51 +02:00
commit
d5cc10d7e1
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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] != '\"')
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue