Fix all warnings in Emby.Dlna

This commit is contained in:
Bond_009 2020-08-20 21:04:57 +02:00
parent ac58d07e0e
commit 170e434f92
36 changed files with 528 additions and 503 deletions

View File

@ -13,7 +13,7 @@ namespace Emby.Dlna.Common
public string Name { get; set; } public string Name { get; set; }
public List<Argument> ArgumentList { get; set; } public List<Argument> ArgumentList { get; }
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()

View File

@ -1,6 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Collections.Generic;
namespace Emby.Dlna.Common namespace Emby.Dlna.Common
{ {
@ -17,7 +18,7 @@ namespace Emby.Dlna.Common
public bool SendsEvents { get; set; } public bool SendsEvents { get; set; }
public string[] AllowedValues { get; set; } public IReadOnlyList<string> AllowedValues { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()

View File

@ -1,7 +1,6 @@
#nullable enable #nullable enable
#pragma warning disable CS1591 #pragma warning disable CS1591
using System.Collections.Generic;
using Emby.Dlna.Configuration; using Emby.Dlna.Configuration;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
@ -14,19 +13,4 @@ namespace Emby.Dlna
return manager.GetConfiguration<DlnaOptions>("dlna"); return manager.GetConfiguration<DlnaOptions>("dlna");
} }
} }
public class DlnaConfigurationFactory : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new[]
{
new ConfigurationStore
{
Key = "dlna",
ConfigurationType = typeof(DlnaOptions)
}
};
}
}
} }

View File

@ -9,22 +9,20 @@ using Microsoft.Extensions.Logging;
namespace Emby.Dlna.ConnectionManager namespace Emby.Dlna.ConnectionManager
{ {
public class ConnectionManager : BaseService, IConnectionManager public class ConnectionManagerService : BaseService, IConnectionManager
{ {
private readonly IDlnaManager _dlna; private readonly IDlnaManager _dlna;
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
public ConnectionManager( public ConnectionManagerService(
IDlnaManager dlna, IDlnaManager dlna,
IServerConfigurationManager config, IServerConfigurationManager config,
ILogger<ConnectionManager> logger, ILogger<ConnectionManagerService> logger,
IHttpClient httpClient) IHttpClient httpClient)
: base(logger, httpClient) : base(logger, httpClient)
{ {
_dlna = dlna; _dlna = dlna;
_config = config; _config = config;
_logger = logger;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -39,7 +37,7 @@ namespace Emby.Dlna.ConnectionManager
var profile = _dlna.GetProfile(request.Headers) ?? var profile = _dlna.GetProfile(request.Headers) ??
_dlna.GetDefaultProfile(); _dlna.GetDefaultProfile();
return new ControlHandler(_config, _logger, profile).ProcessControlRequestAsync(request); return new ControlHandler(_config, Logger, profile).ProcessControlRequestAsync(request);
} }
} }
} }

View File

@ -19,7 +19,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Dlna.ContentDirectory namespace Emby.Dlna.ContentDirectory
{ {
public class ContentDirectory : BaseService, IContentDirectory public class ContentDirectoryService : BaseService, IContentDirectory
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IImageProcessor _imageProcessor; private readonly IImageProcessor _imageProcessor;
@ -33,14 +33,14 @@ namespace Emby.Dlna.ContentDirectory
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private readonly ITVSeriesManager _tvSeriesManager; private readonly ITVSeriesManager _tvSeriesManager;
public ContentDirectory( public ContentDirectoryService(
IDlnaManager dlna, IDlnaManager dlna,
IUserDataManager userDataManager, IUserDataManager userDataManager,
IImageProcessor imageProcessor, IImageProcessor imageProcessor,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IServerConfigurationManager config, IServerConfigurationManager config,
IUserManager userManager, IUserManager userManager,
ILogger<ContentDirectory> logger, ILogger<ContentDirectoryService> logger,
IHttpClient httpClient, IHttpClient httpClient,
ILocalizationManager localization, ILocalizationManager localization,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,

View File

@ -40,6 +40,11 @@ namespace Emby.Dlna.ContentDirectory
{ {
public class ControlHandler : BaseControlHandler public class ControlHandler : BaseControlHandler
{ {
private const string NsDc = "http://purl.org/dc/elements/1.1/";
private const string NsDidl = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/";
private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IUserDataManager _userDataManager; private readonly IUserDataManager _userDataManager;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
@ -47,11 +52,6 @@ namespace Emby.Dlna.ContentDirectory
private readonly IUserViewManager _userViewManager; private readonly IUserViewManager _userViewManager;
private readonly ITVSeriesManager _tvSeriesManager; private readonly ITVSeriesManager _tvSeriesManager;
private const string NS_DC = "http://purl.org/dc/elements/1.1/";
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
private const string NS_DLNA = "urn:schemas-dlna-org:metadata-1-0/";
private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
private readonly int _systemUpdateId; private readonly int _systemUpdateId;
private readonly DidlBuilder _didlBuilder; private readonly DidlBuilder _didlBuilder;
@ -181,7 +181,11 @@ namespace Emby.Dlna.ContentDirectory
userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks; userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
_userDataManager.SaveUserData(_user, item, userdata, UserDataSaveReason.TogglePlayed, _userDataManager.SaveUserData(
_user,
item,
userdata,
UserDataSaveReason.TogglePlayed,
CancellationToken.None); CancellationToken.None);
} }
@ -286,18 +290,17 @@ namespace Emby.Dlna.ContentDirectory
using (var writer = XmlWriter.Create(builder, settings)) using (var writer = XmlWriter.Create(builder, settings))
{ {
writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL); writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl);
writer.WriteAttributeString("xmlns", "dc", null, NS_DC); writer.WriteAttributeString("xmlns", "dc", null, NsDc);
writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA); writer.WriteAttributeString("xmlns", "dlna", null, NsDlna);
writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP); writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp);
DidlBuilder.WriteXmlRootAttributes(_profile, writer); DidlBuilder.WriteXmlRootAttributes(_profile, writer);
var serverItem = GetItemFromObjectId(id); var serverItem = GetItemFromObjectId(id);
var item = serverItem.Item; var item = serverItem.Item;
if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal)) if (string.Equals(flag, "BrowseMetadata", StringComparison.Ordinal))
{ {
totalCount = 1; totalCount = 1;
@ -397,11 +400,11 @@ namespace Emby.Dlna.ContentDirectory
using (var writer = XmlWriter.Create(builder, settings)) using (var writer = XmlWriter.Create(builder, settings))
{ {
writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL); writer.WriteStartElement(string.Empty, "DIDL-Lite", NsDidl);
writer.WriteAttributeString("xmlns", "dc", null, NS_DC); writer.WriteAttributeString("xmlns", "dc", null, NsDc);
writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA); writer.WriteAttributeString("xmlns", "dlna", null, NsDlna);
writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP); writer.WriteAttributeString("xmlns", "upnp", null, NsUpnp);
DidlBuilder.WriteXmlRootAttributes(_profile, writer); DidlBuilder.WriteXmlRootAttributes(_profile, writer);
@ -783,11 +786,14 @@ namespace Emby.Dlna.ContentDirectory
}) })
.ToArray(); .ToArray();
return ApplyPaging(new QueryResult<ServerItem> return ApplyPaging(
new QueryResult<ServerItem>
{ {
Items = folders, Items = folders,
TotalRecordCount = folders.Length TotalRecordCount = folders.Length
}, startIndex, limit); },
startIndex,
limit);
} }
private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit) private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
@ -1135,14 +1141,16 @@ namespace Emby.Dlna.ContentDirectory
{ {
query.OrderBy = Array.Empty<(string, SortOrder)>(); query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery var items = _userViewManager.GetLatestItems(
new LatestItemsQuery
{ {
UserId = user.Id, UserId = user.Id,
Limit = 50, Limit = 50,
IncludeItemTypes = new[] { nameof(Audio) }, IncludeItemTypes = new[] { nameof(Audio) },
ParentId = parent?.Id ?? Guid.Empty, ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true GroupItems = true
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); },
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
} }
@ -1151,12 +1159,15 @@ namespace Emby.Dlna.ContentDirectory
{ {
query.OrderBy = Array.Empty<(string, SortOrder)>(); query.OrderBy = Array.Empty<(string, SortOrder)>();
var result = _tvSeriesManager.GetNextUp(new NextUpQuery var result = _tvSeriesManager.GetNextUp(
new NextUpQuery
{ {
Limit = query.Limit, Limit = query.Limit,
StartIndex = query.StartIndex, StartIndex = query.StartIndex,
UserId = query.User.Id UserId = query.User.Id
}, new[] { parent }, query.DtoOptions); },
new[] { parent },
query.DtoOptions);
return ToResult(result); return ToResult(result);
} }
@ -1165,14 +1176,16 @@ namespace Emby.Dlna.ContentDirectory
{ {
query.OrderBy = Array.Empty<(string, SortOrder)>(); query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery var items = _userViewManager.GetLatestItems(
new LatestItemsQuery
{ {
UserId = user.Id, UserId = user.Id,
Limit = 50, Limit = 50,
IncludeItemTypes = new[] { typeof(Episode).Name }, IncludeItemTypes = new[] { typeof(Episode).Name },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent == null ? Guid.Empty : parent.Id,
GroupItems = false GroupItems = false
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); },
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
} }
@ -1189,7 +1202,8 @@ namespace Emby.Dlna.ContentDirectory
IncludeItemTypes = new[] { nameof(Movie) }, IncludeItemTypes = new[] { nameof(Movie) },
ParentId = parent?.Id ?? Guid.Empty, ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true GroupItems = true
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); },
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
} }
@ -1354,44 +1368,4 @@ namespace Emby.Dlna.ContentDirectory
return new ServerItem(_libraryManager.GetUserRootFolder()); return new ServerItem(_libraryManager.GetUserRootFolder());
} }
} }
internal class ServerItem
{
public BaseItem Item { get; set; }
public StubType? StubType { get; set; }
public ServerItem(BaseItem item)
{
Item = item;
if (item is IItemByName && !(item is Folder))
{
StubType = Dlna.ContentDirectory.StubType.Folder;
}
}
}
public enum StubType
{
Folder = 0,
Latest = 2,
Playlists = 3,
Albums = 4,
AlbumArtists = 5,
Artists = 6,
Songs = 7,
Genres = 8,
FavoriteSongs = 9,
FavoriteArtists = 10,
FavoriteAlbums = 11,
ContinueWatching = 12,
Movies = 13,
Collections = 14,
Favorites = 15,
NextUp = 16,
Series = 17,
FavoriteSeries = 18,
FavoriteEpisodes = 19
}
} }

View File

@ -0,0 +1,23 @@
#pragma warning disable CS1591
using MediaBrowser.Controller.Entities;
namespace Emby.Dlna.ContentDirectory
{
internal class ServerItem
{
public ServerItem(BaseItem item)
{
Item = item;
if (item is IItemByName && !(item is Folder))
{
StubType = Dlna.ContentDirectory.StubType.Folder;
}
}
public BaseItem Item { get; set; }
public StubType? StubType { get; set; }
}
}

View File

@ -0,0 +1,28 @@
#pragma warning disable CS1591
#pragma warning disable SA1602
namespace Emby.Dlna.ContentDirectory
{
public enum StubType
{
Folder = 0,
Latest = 2,
Playlists = 3,
Albums = 4,
AlbumArtists = 5,
Artists = 6,
Songs = 7,
Genres = 8,
FavoriteSongs = 9,
FavoriteArtists = 10,
FavoriteAlbums = 11,
ContinueWatching = 12,
Movies = 13,
Collections = 14,
Favorites = 15,
NextUp = 16,
Series = 17,
FavoriteSeries = 18,
FavoriteEpisodes = 19
}
}

View File

@ -7,12 +7,12 @@ namespace Emby.Dlna
{ {
public class ControlRequest public class ControlRequest
{ {
public ControlRequest() public ControlRequest(IHeaderDictionary headers)
{ {
Headers = new HeaderDictionary(); Headers = headers;
} }
public IHeaderDictionary Headers { get; set; } public IHeaderDictionary Headers { get; }
public Stream InputXml { get; set; } public Stream InputXml { get; set; }

View File

@ -11,7 +11,7 @@ namespace Emby.Dlna
Headers = new Dictionary<string, string>(); Headers = new Dictionary<string, string>();
} }
public IDictionary<string, string> Headers { get; set; } public IDictionary<string, string> Headers { get; }
public string Xml { get; set; } public string Xml { get; set; }

View File

@ -977,12 +977,12 @@ namespace Emby.Dlna.Didl
writer.WriteStartElement("upnp", "albumArtURI", NsUpnp); writer.WriteStartElement("upnp", "albumArtURI", NsUpnp);
writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn); writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
writer.WriteString(albumartUrlInfo.Url); writer.WriteString(albumartUrlInfo.url);
writer.WriteFullEndElement(); writer.WriteFullEndElement();
// TOOD: Remove these default values // TOOD: Remove these default values
var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg"); var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg");
writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.Url); writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.url);
if (!_profile.EnableAlbumArtInDidl) if (!_profile.EnableAlbumArtInDidl)
{ {
@ -1029,8 +1029,8 @@ namespace Emby.Dlna.Didl
// Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail // Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail
// rather than using a larger one when available // rather than using a larger one when available
var width = albumartUrlInfo.Width ?? maxWidth; var width = albumartUrlInfo.width ?? maxWidth;
var height = albumartUrlInfo.Height ?? maxHeight; var height = albumartUrlInfo.height ?? maxHeight;
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);
@ -1047,7 +1047,7 @@ namespace Emby.Dlna.Didl
"resolution", "resolution",
string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height)); string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
writer.WriteString(albumartUrlInfo.Url); writer.WriteString(albumartUrlInfo.url);
writer.WriteFullEndElement(); writer.WriteFullEndElement();
} }
@ -1143,7 +1143,6 @@ namespace Emby.Dlna.Didl
if (width == 0 || height == 0) if (width == 0 || height == 0)
{ {
// _imageProcessor.GetImageSize(item, imageInfo);
width = null; width = null;
height = null; height = null;
} }
@ -1153,18 +1152,6 @@ namespace Emby.Dlna.Didl
height = null; height = null;
} }
// try
// {
// var size = _imageProcessor.GetImageSize(imageInfo);
// width = size.Width;
// height = size.Height;
// }
// catch
// {
// }
var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty) var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
.TrimStart('.') .TrimStart('.')
.Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase); .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
@ -1181,30 +1168,6 @@ namespace Emby.Dlna.Didl
}; };
} }
private class ImageDownloadInfo
{
internal Guid ItemId;
internal string ImageTag;
internal ImageType Type;
internal int? Width;
internal int? Height;
internal bool IsDirectStream;
internal string Format;
internal ItemImageInfo ItemImageInfo;
}
private class ImageUrlInfo
{
internal string Url;
internal int? Width;
internal int? Height;
}
public static string GetClientId(BaseItem item, StubType? stubType) public static string GetClientId(BaseItem item, StubType? stubType)
{ {
return GetClientId(item.Id, stubType); return GetClientId(item.Id, stubType);
@ -1222,7 +1185,7 @@ namespace Emby.Dlna.Didl
return id; return id;
} }
private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format) private (string url, int? width, int? height) GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
{ {
var url = string.Format( var url = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -1260,12 +1223,26 @@ namespace Emby.Dlna.Didl
// just lie // just lie
info.IsDirectStream = true; info.IsDirectStream = true;
return new ImageUrlInfo return (url, width, height);
}
private class ImageDownloadInfo
{ {
Url = url, internal Guid ItemId { get; set; }
Width = width,
Height = height internal string ImageTag { get; set; }
};
internal ImageType Type { get; set; }
internal int? Width { get; set; }
internal int? Height { get; set; }
internal bool IsDirectStream { get; set; }
internal string Format { get; set; }
internal ItemImageInfo ItemImageInfo { get; set; }
} }
} }
} }

View File

@ -23,9 +23,7 @@ namespace Emby.Dlna.Didl
public bool Contains(string field) public bool Contains(string field)
{ {
// Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back. return _all || Array.Exists(_fields, x => x.Equals(field, StringComparison.OrdinalIgnoreCase));
return true;
// return _all || ListHelper.ContainsIgnoreCase(_fields, field);
} }
} }
} }

View File

@ -0,0 +1,24 @@
#nullable enable
#pragma warning disable CS1591
using System.Collections.Generic;
using Emby.Dlna.Configuration;
using MediaBrowser.Common.Configuration;
namespace Emby.Dlna
{
public class DlnaConfigurationFactory : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new[]
{
new ConfigurationStore
{
Key = "dlna",
ConfigurationType = typeof(DlnaOptions)
}
};
}
}
}

View File

@ -495,8 +495,8 @@ namespace Emby.Dlna
/// Recreates the object using serialization, to ensure it's not a subclass. /// Recreates the object using serialization, to ensure it's not a subclass.
/// If it's a subclass it may not serlialize properly to xml (different root element tag name). /// If it's a subclass it may not serlialize properly to xml (different root element tag name).
/// </summary> /// </summary>
/// <param name="profile"></param> /// <param name="profile">The device profile.</param>
/// <returns></returns> /// <returns>The reserialized device profile.</returns>
private DeviceProfile ReserializeProfile(DeviceProfile profile) private DeviceProfile ReserializeProfile(DeviceProfile profile)
{ {
if (profile.GetType() == typeof(DeviceProfile)) if (profile.GetType() == typeof(DeviceProfile))
@ -509,13 +509,6 @@ namespace Emby.Dlna
return _jsonSerializer.DeserializeFromString<DeviceProfile>(json); return _jsonSerializer.DeserializeFromString<DeviceProfile>(json);
} }
private class InternalProfileInfo
{
internal DeviceProfileInfo Info { get; set; }
internal string Path { get; set; }
}
public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress) public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress)
{ {
var profile = GetProfile(headers) ?? var profile = GetProfile(headers) ??
@ -540,6 +533,13 @@ namespace Emby.Dlna
Stream = _assembly.GetManifestResourceStream(resource) Stream = _assembly.GetManifestResourceStream(resource)
}; };
} }
private class InternalProfileInfo
{
internal DeviceProfileInfo Info { get; set; }
internal string Path { get; set; }
}
} }
/* /*

View File

@ -20,7 +20,7 @@
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'" >true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<!-- Code Analyzers--> <!-- Code Analyzers-->

View File

@ -15,6 +15,6 @@ namespace Emby.Dlna
public string ContentType { get; set; } public string ContentType { get; set; }
public Dictionary<string, string> Headers { get; set; } public Dictionary<string, string> Headers { get; }
} }
} }

View File

@ -8,16 +8,26 @@ namespace Emby.Dlna
/// Cancels the event subscription. /// Cancels the event subscription.
/// </summary> /// </summary>
/// <param name="subscriptionId">The subscription identifier.</param> /// <param name="subscriptionId">The subscription identifier.</param>
/// <returns>The response.</returns>
EventSubscriptionResponse CancelEventSubscription(string subscriptionId); EventSubscriptionResponse CancelEventSubscription(string subscriptionId);
/// <summary> /// <summary>
/// Renews the event subscription. /// Renews the event subscription.
/// </summary> /// </summary>
/// <param name="subscriptionId">The subscription identifier.</param>
/// <param name="notificationType">The notification type.</param>
/// <param name="requestedTimeoutString">The requested timeout as a sting.</param>
/// <param name="callbackUrl">The callback url.</param>
/// <returns>The response.</returns>
EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl); EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl);
/// <summary> /// <summary>
/// Creates the event subscription. /// Creates the event subscription.
/// </summary> /// </summary>
/// <param name="notificationType">The notification type.</param>
/// <param name="requestedTimeoutString">The requested timeout as a sting.</param>
/// <param name="callbackUrl">The callback url.</param>
/// <returns>The response.</returns>
EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl); EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl);
} }
} }

View File

@ -93,14 +93,14 @@ namespace Emby.Dlna.Main
_networkManager = networkManager; _networkManager = networkManager;
_logger = loggerFactory.CreateLogger<DlnaEntryPoint>(); _logger = loggerFactory.CreateLogger<DlnaEntryPoint>();
ContentDirectory = new ContentDirectory.ContentDirectory( ContentDirectory = new ContentDirectory.ContentDirectoryService(
dlnaManager, dlnaManager,
userDataManager, userDataManager,
imageProcessor, imageProcessor,
libraryManager, libraryManager,
config, config,
userManager, userManager,
loggerFactory.CreateLogger<ContentDirectory.ContentDirectory>(), loggerFactory.CreateLogger<ContentDirectory.ContentDirectoryService>(),
httpClient, httpClient,
localizationManager, localizationManager,
mediaSourceManager, mediaSourceManager,
@ -108,14 +108,14 @@ namespace Emby.Dlna.Main
mediaEncoder, mediaEncoder,
tvSeriesManager); tvSeriesManager);
ConnectionManager = new ConnectionManager.ConnectionManager( ConnectionManager = new ConnectionManager.ConnectionManagerService(
dlnaManager, dlnaManager,
config, config,
loggerFactory.CreateLogger<ConnectionManager.ConnectionManager>(), loggerFactory.CreateLogger<ConnectionManager.ConnectionManagerService>(),
httpClient); httpClient);
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar( MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService(
loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrar>(), loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrarService>(),
httpClient, httpClient,
config); config);
Current = this; Current = this;
@ -413,28 +413,15 @@ namespace Emby.Dlna.Main
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and optionally managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{ {
if (_disposed) if (_disposed)
{ {
return; return;
} }
if (disposing)
{
DisposeDevicePublisher(); DisposeDevicePublisher();
DisposePlayToManager(); DisposePlayToManager();
DisposeDeviceDiscovery(); DisposeDeviceDiscovery();
}
if (_communicationsServer != null) if (_communicationsServer != null)
{ {

View File

@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Dlna.MediaReceiverRegistrar namespace Emby.Dlna.MediaReceiverRegistrar
{ {
public class MediaReceiverRegistrar : BaseService, IMediaReceiverRegistrar public class MediaReceiverRegistrarService : BaseService, IMediaReceiverRegistrar
{ {
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
public MediaReceiverRegistrar( public MediaReceiverRegistrarService(
ILogger<MediaReceiverRegistrar> logger, ILogger<MediaReceiverRegistrarService> logger,
IHttpClient httpClient, IHttpClient httpClient,
IServerConfigurationManager config) IServerConfigurationManager config)
: base(logger, httpClient) : base(logger, httpClient)

View File

@ -21,15 +21,38 @@ namespace Emby.Dlna.PlayTo
{ {
private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
private readonly object _timerLock = new object();
private Timer _timer; private Timer _timer;
private int _muteVol;
private int _volume;
private DateTime _lastVolumeRefresh;
private bool _volumeRefreshActive;
private int _connectFailureCount;
private bool _disposed;
public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger)
{
Properties = deviceProperties;
_httpClient = httpClient;
_logger = logger;
}
public event EventHandler<PlaybackStartEventArgs> PlaybackStart;
public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
public event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
public event EventHandler<MediaChangedEventArgs> MediaChanged;
public DeviceInfo Properties { get; set; } public DeviceInfo Properties { get; set; }
private int _muteVol;
public bool IsMuted { get; set; } public bool IsMuted { get; set; }
private int _volume;
public int Volume public int Volume
{ {
get get
@ -53,18 +76,13 @@ namespace Emby.Dlna.PlayTo
public bool IsStopped => TransportState == TransportState.Stopped; public bool IsStopped => TransportState == TransportState.Stopped;
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
public Action OnDeviceUnavailable { get; set; } public Action OnDeviceUnavailable { get; set; }
public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger) private TransportCommands AvCommands { get; set; }
{
Properties = deviceProperties; private TransportCommands RendererCommands { get; set; }
_httpClient = httpClient;
_logger = logger; public UBaseObject CurrentMediaInfo { get; private set; }
}
public void Start() public void Start()
{ {
@ -72,8 +90,6 @@ namespace Emby.Dlna.PlayTo
_timer = new Timer(TimerCallback, null, 1000, Timeout.Infinite); _timer = new Timer(TimerCallback, null, 1000, Timeout.Infinite);
} }
private DateTime _lastVolumeRefresh;
private bool _volumeRefreshActive;
private Task RefreshVolumeIfNeeded() private Task RefreshVolumeIfNeeded()
{ {
if (_volumeRefreshActive if (_volumeRefreshActive
@ -104,7 +120,6 @@ namespace Emby.Dlna.PlayTo
} }
} }
private readonly object _timerLock = new object();
private void RestartTimer(bool immediate = false) private void RestartTimer(bool immediate = false)
{ {
lock (_timerLock) lock (_timerLock)
@ -232,6 +247,9 @@ namespace Emby.Dlna.PlayTo
/// <summary> /// <summary>
/// Sets volume on a scale of 0-100. /// Sets volume on a scale of 0-100.
/// </summary> /// </summary>
/// <param name="value">The volume on a scale of 0-100.</param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task SetVolume(int value, CancellationToken cancellationToken) public async Task SetVolume(int value, CancellationToken cancellationToken)
{ {
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false); var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
@ -405,8 +423,6 @@ namespace Emby.Dlna.PlayTo
RestartTimer(true); RestartTimer(true);
} }
private int _connectFailureCount;
private async void TimerCallback(object sender) private async void TimerCallback(object sender)
{ {
if (_disposed) if (_disposed)
@ -538,7 +554,7 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
var volume = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetVolumeResponse").Select(i => i.Element("CurrentVolume")).FirstOrDefault(i => i != null); var volume = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetVolumeResponse").Select(i => i.Element("CurrentVolume")).FirstOrDefault(i => i != null);
var volumeValue = volume?.Value; var volumeValue = volume?.Value;
if (string.IsNullOrWhiteSpace(volumeValue)) if (string.IsNullOrWhiteSpace(volumeValue))
@ -588,7 +604,7 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
var valueNode = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetMuteResponse") var valueNode = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetMuteResponse")
.Select(i => i.Element("CurrentMute")) .Select(i => i.Element("CurrentMute"))
.FirstOrDefault(i => i != null); .FirstOrDefault(i => i != null);
@ -622,7 +638,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?.Value; var transportStateValue = transportState?.Value;
@ -635,7 +651,7 @@ namespace Emby.Dlna.PlayTo
return null; return null;
} }
private async Task<uBaseObject> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken) private async Task<UBaseObject> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{ {
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo"); var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo");
if (command == null) if (command == null)
@ -670,7 +686,7 @@ namespace Emby.Dlna.PlayTo
return null; return null;
} }
var e = track.Element(uPnpNamespaces.items) ?? track; var e = track.Element(UPnpNamespaces.Items) ?? track;
var elementString = (string)e; var elementString = (string)e;
@ -686,13 +702,13 @@ namespace Emby.Dlna.PlayTo
return null; return null;
} }
e = track.Element(uPnpNamespaces.items) ?? track; e = track.Element(UPnpNamespaces.Items) ?? track;
elementString = (string)e; elementString = (string)e;
if (!string.IsNullOrWhiteSpace(elementString)) if (!string.IsNullOrWhiteSpace(elementString))
{ {
return new uBaseObject return new UBaseObject
{ {
Url = elementString Url = elementString
}; };
@ -701,7 +717,7 @@ namespace Emby.Dlna.PlayTo
return null; return null;
} }
private async Task<(bool, uBaseObject)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken) private async Task<(bool, UBaseObject)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{ {
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo"); var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
if (command == null) if (command == null)
@ -730,10 +746,10 @@ namespace Emby.Dlna.PlayTo
return (false, null); return (false, null);
} }
var trackUriElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null); var trackUriElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null);
var trackUri = trackUriElem?.Value; var trackUri = trackUriElem?.Value;
var durationElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null); var durationElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null);
var duration = durationElem?.Value; var duration = durationElem?.Value;
if (!string.IsNullOrWhiteSpace(duration) if (!string.IsNullOrWhiteSpace(duration)
@ -746,7 +762,7 @@ namespace Emby.Dlna.PlayTo
Duration = null; Duration = null;
} }
var positionElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null); var positionElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null);
var position = positionElem?.Value; var position = positionElem?.Value;
if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
@ -786,7 +802,7 @@ namespace Emby.Dlna.PlayTo
return (true, null); return (true, null);
} }
var e = uPnpResponse.Element(uPnpNamespaces.items); var e = uPnpResponse.Element(UPnpNamespaces.Items);
var uTrack = CreateUBaseObject(e, trackUri); var uTrack = CreateUBaseObject(e, trackUri);
@ -827,26 +843,26 @@ namespace Emby.Dlna.PlayTo
return null; return null;
} }
private static uBaseObject CreateUBaseObject(XElement container, string trackUri) private static UBaseObject CreateUBaseObject(XElement container, string trackUri)
{ {
if (container == null) if (container == null)
{ {
throw new ArgumentNullException(nameof(container)); throw new ArgumentNullException(nameof(container));
} }
var url = container.GetValue(uPnpNamespaces.Res); var url = container.GetValue(UPnpNamespaces.Res);
if (string.IsNullOrWhiteSpace(url)) if (string.IsNullOrWhiteSpace(url))
{ {
url = trackUri; url = trackUri;
} }
return new uBaseObject return new UBaseObject
{ {
Id = container.GetAttributeValue(uPnpNamespaces.Id), Id = container.GetAttributeValue(UPnpNamespaces.Id),
ParentId = container.GetAttributeValue(uPnpNamespaces.ParentId), ParentId = container.GetAttributeValue(UPnpNamespaces.ParentId),
Title = container.GetValue(uPnpNamespaces.title), Title = container.GetValue(UPnpNamespaces.Title),
IconUrl = container.GetValue(uPnpNamespaces.Artwork), IconUrl = container.GetValue(UPnpNamespaces.Artwork),
SecondText = string.Empty, SecondText = string.Empty,
Url = url, Url = url,
ProtocolInfo = GetProtocolInfo(container), ProtocolInfo = GetProtocolInfo(container),
@ -861,11 +877,11 @@ namespace Emby.Dlna.PlayTo
throw new ArgumentNullException(nameof(container)); throw new ArgumentNullException(nameof(container));
} }
var resElement = container.Element(uPnpNamespaces.Res); var resElement = container.Element(UPnpNamespaces.Res);
if (resElement != null) if (resElement != null)
{ {
var info = resElement.Attribute(uPnpNamespaces.ProtocolInfo); var info = resElement.Attribute(UPnpNamespaces.ProtocolInfo);
if (info != null && !string.IsNullOrWhiteSpace(info.Value)) if (info != null && !string.IsNullOrWhiteSpace(info.Value))
{ {
@ -953,11 +969,7 @@ namespace Emby.Dlna.PlayTo
return baseUrl + url; return baseUrl + url;
} }
private TransportCommands AvCommands { get; set; } public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
private TransportCommands RendererCommands { get; set; }
public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, CancellationToken cancellationToken)
{ {
var ssdpHttpClient = new SsdpHttpClient(httpClient); var ssdpHttpClient = new SsdpHttpClient(httpClient);
@ -965,13 +977,13 @@ namespace Emby.Dlna.PlayTo
var friendlyNames = new List<string>(); var friendlyNames = new List<string>();
var name = document.Descendants(uPnpNamespaces.ud.GetName("friendlyName")).FirstOrDefault(); var name = document.Descendants(UPnpNamespaces.Ud.GetName("friendlyName")).FirstOrDefault();
if (name != null && !string.IsNullOrWhiteSpace(name.Value)) if (name != null && !string.IsNullOrWhiteSpace(name.Value))
{ {
friendlyNames.Add(name.Value); friendlyNames.Add(name.Value);
} }
var room = document.Descendants(uPnpNamespaces.ud.GetName("roomName")).FirstOrDefault(); var room = document.Descendants(UPnpNamespaces.Ud.GetName("roomName")).FirstOrDefault();
if (room != null && !string.IsNullOrWhiteSpace(room.Value)) if (room != null && !string.IsNullOrWhiteSpace(room.Value))
{ {
friendlyNames.Add(room.Value); friendlyNames.Add(room.Value);
@ -983,74 +995,74 @@ namespace Emby.Dlna.PlayTo
BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port) BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port)
}; };
var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault(); var model = document.Descendants(UPnpNamespaces.Ud.GetName("modelName")).FirstOrDefault();
if (model != null) if (model != null)
{ {
deviceProperties.ModelName = model.Value; deviceProperties.ModelName = model.Value;
} }
var modelNumber = document.Descendants(uPnpNamespaces.ud.GetName("modelNumber")).FirstOrDefault(); var modelNumber = document.Descendants(UPnpNamespaces.Ud.GetName("modelNumber")).FirstOrDefault();
if (modelNumber != null) if (modelNumber != null)
{ {
deviceProperties.ModelNumber = modelNumber.Value; deviceProperties.ModelNumber = modelNumber.Value;
} }
var uuid = document.Descendants(uPnpNamespaces.ud.GetName("UDN")).FirstOrDefault(); var uuid = document.Descendants(UPnpNamespaces.Ud.GetName("UDN")).FirstOrDefault();
if (uuid != null) if (uuid != null)
{ {
deviceProperties.UUID = uuid.Value; deviceProperties.UUID = uuid.Value;
} }
var manufacturer = document.Descendants(uPnpNamespaces.ud.GetName("manufacturer")).FirstOrDefault(); var manufacturer = document.Descendants(UPnpNamespaces.Ud.GetName("manufacturer")).FirstOrDefault();
if (manufacturer != null) if (manufacturer != null)
{ {
deviceProperties.Manufacturer = manufacturer.Value; deviceProperties.Manufacturer = manufacturer.Value;
} }
var manufacturerUrl = document.Descendants(uPnpNamespaces.ud.GetName("manufacturerURL")).FirstOrDefault(); var manufacturerUrl = document.Descendants(UPnpNamespaces.Ud.GetName("manufacturerURL")).FirstOrDefault();
if (manufacturerUrl != null) if (manufacturerUrl != null)
{ {
deviceProperties.ManufacturerUrl = manufacturerUrl.Value; deviceProperties.ManufacturerUrl = manufacturerUrl.Value;
} }
var presentationUrl = document.Descendants(uPnpNamespaces.ud.GetName("presentationURL")).FirstOrDefault(); var presentationUrl = document.Descendants(UPnpNamespaces.Ud.GetName("presentationURL")).FirstOrDefault();
if (presentationUrl != null) if (presentationUrl != null)
{ {
deviceProperties.PresentationUrl = presentationUrl.Value; deviceProperties.PresentationUrl = presentationUrl.Value;
} }
var modelUrl = document.Descendants(uPnpNamespaces.ud.GetName("modelURL")).FirstOrDefault(); var modelUrl = document.Descendants(UPnpNamespaces.Ud.GetName("modelURL")).FirstOrDefault();
if (modelUrl != null) if (modelUrl != null)
{ {
deviceProperties.ModelUrl = modelUrl.Value; deviceProperties.ModelUrl = modelUrl.Value;
} }
var serialNumber = document.Descendants(uPnpNamespaces.ud.GetName("serialNumber")).FirstOrDefault(); var serialNumber = document.Descendants(UPnpNamespaces.Ud.GetName("serialNumber")).FirstOrDefault();
if (serialNumber != null) if (serialNumber != null)
{ {
deviceProperties.SerialNumber = serialNumber.Value; deviceProperties.SerialNumber = serialNumber.Value;
} }
var modelDescription = document.Descendants(uPnpNamespaces.ud.GetName("modelDescription")).FirstOrDefault(); var modelDescription = document.Descendants(UPnpNamespaces.Ud.GetName("modelDescription")).FirstOrDefault();
if (modelDescription != null) if (modelDescription != null)
{ {
deviceProperties.ModelDescription = modelDescription.Value; deviceProperties.ModelDescription = modelDescription.Value;
} }
var icon = document.Descendants(uPnpNamespaces.ud.GetName("icon")).FirstOrDefault(); var icon = document.Descendants(UPnpNamespaces.Ud.GetName("icon")).FirstOrDefault();
if (icon != null) if (icon != null)
{ {
deviceProperties.Icon = CreateIcon(icon); deviceProperties.Icon = CreateIcon(icon);
} }
foreach (var services in document.Descendants(uPnpNamespaces.ud.GetName("serviceList"))) foreach (var services in document.Descendants(UPnpNamespaces.Ud.GetName("serviceList")))
{ {
if (services == null) if (services == null)
{ {
continue; continue;
} }
var servicesList = services.Descendants(uPnpNamespaces.ud.GetName("service")); var servicesList = services.Descendants(UPnpNamespaces.Ud.GetName("service"));
if (servicesList == null) if (servicesList == null)
{ {
continue; continue;
@ -1077,11 +1089,11 @@ namespace Emby.Dlna.PlayTo
throw new ArgumentNullException(nameof(element)); throw new ArgumentNullException(nameof(element));
} }
var mimeType = element.GetDescendantValue(uPnpNamespaces.ud.GetName("mimetype")); var mimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype"));
var width = element.GetDescendantValue(uPnpNamespaces.ud.GetName("width")); var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
var height = element.GetDescendantValue(uPnpNamespaces.ud.GetName("height")); var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));
var depth = element.GetDescendantValue(uPnpNamespaces.ud.GetName("depth")); var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth"));
var url = element.GetDescendantValue(uPnpNamespaces.ud.GetName("url")); var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url"));
var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture); var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture);
var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture); var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
@ -1098,11 +1110,11 @@ namespace Emby.Dlna.PlayTo
private static DeviceService Create(XElement element) private static DeviceService Create(XElement element)
{ {
var type = element.GetDescendantValue(uPnpNamespaces.ud.GetName("serviceType")); var type = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType"));
var id = element.GetDescendantValue(uPnpNamespaces.ud.GetName("serviceId")); var id = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId"));
var scpdUrl = element.GetDescendantValue(uPnpNamespaces.ud.GetName("SCPDURL")); var scpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL"));
var controlURL = element.GetDescendantValue(uPnpNamespaces.ud.GetName("controlURL")); var controlURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL"));
var eventSubURL = element.GetDescendantValue(uPnpNamespaces.ud.GetName("eventSubURL")); var eventSubURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL"));
return new DeviceService return new DeviceService
{ {
@ -1114,14 +1126,7 @@ namespace Emby.Dlna.PlayTo
}; };
} }
public event EventHandler<PlaybackStartEventArgs> PlaybackStart; private void UpdateMediaInfo(UBaseObject mediaInfo, TransportState state)
public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
public event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
public event EventHandler<MediaChangedEventArgs> MediaChanged;
public uBaseObject CurrentMediaInfo { get; private set; }
private void UpdateMediaInfo(uBaseObject mediaInfo, TransportState state)
{ {
TransportState = state; TransportState = state;
@ -1149,7 +1154,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
private void OnPlaybackStart(uBaseObject mediaInfo) private void OnPlaybackStart(UBaseObject mediaInfo)
{ {
if (string.IsNullOrWhiteSpace(mediaInfo.Url)) if (string.IsNullOrWhiteSpace(mediaInfo.Url))
{ {
@ -1162,7 +1167,7 @@ namespace Emby.Dlna.PlayTo
}); });
} }
private void OnPlaybackProgress(uBaseObject mediaInfo) private void OnPlaybackProgress(UBaseObject mediaInfo)
{ {
if (string.IsNullOrWhiteSpace(mediaInfo.Url)) if (string.IsNullOrWhiteSpace(mediaInfo.Url))
{ {
@ -1175,7 +1180,7 @@ namespace Emby.Dlna.PlayTo
}); });
} }
private void OnPlaybackStop(uBaseObject mediaInfo) private void OnPlaybackStop(UBaseObject mediaInfo)
{ {
PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
{ {
@ -1183,7 +1188,7 @@ namespace Emby.Dlna.PlayTo
}); });
} }
private void OnMediaChanged(uBaseObject old, uBaseObject newMedia) private void OnMediaChanged(UBaseObject old, UBaseObject newMedia)
{ {
MediaChanged?.Invoke(this, new MediaChangedEventArgs MediaChanged?.Invoke(this, new MediaChangedEventArgs
{ {
@ -1192,8 +1197,7 @@ namespace Emby.Dlna.PlayTo
}); });
} }
bool _disposed; /// <inheritdoc />
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
@ -1222,6 +1226,7 @@ namespace Emby.Dlna.PlayTo
_disposed = true; _disposed = true;
} }
/// <inheritdoc />
public override string ToString() public override string ToString()
{ {
return string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Properties.Name, Properties.BaseUrl); return string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Properties.Name, Properties.BaseUrl);

View File

@ -6,8 +6,8 @@ namespace Emby.Dlna.PlayTo
{ {
public class MediaChangedEventArgs : EventArgs public class MediaChangedEventArgs : EventArgs
{ {
public uBaseObject OldMediaInfo { get; set; } public UBaseObject OldMediaInfo { get; set; }
public uBaseObject NewMediaInfo { get; set; } public UBaseObject NewMediaInfo { get; set; }
} }
} }

View File

@ -377,7 +377,8 @@ namespace Emby.Dlna.PlayTo
_session.ApplicationVersion, _session.ApplicationVersion,
_session.DeviceId, _session.DeviceId,
_session.DeviceName, _session.DeviceName,
_session.RemoteEndPoint, user); _session.RemoteEndPoint,
user);
} }
return PlayItems(playlist, cancellationToken); return PlayItems(playlist, cancellationToken);
@ -502,7 +503,8 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Audio) if (streamInfo.MediaType == DlnaProfileType.Audio)
{ {
return new ContentFeatureBuilder(profile) return new ContentFeatureBuilder(profile)
.BuildAudioHeader(streamInfo.Container, .BuildAudioHeader(
streamInfo.Container,
streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(),
streamInfo.TargetAudioBitrate, streamInfo.TargetAudioBitrate,
streamInfo.TargetAudioSampleRate, streamInfo.TargetAudioSampleRate,
@ -516,7 +518,8 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Video) if (streamInfo.MediaType == DlnaProfileType.Video)
{ {
var list = new ContentFeatureBuilder(profile) var list = new ContentFeatureBuilder(profile)
.BuildVideoHeader(streamInfo.Container, .BuildVideoHeader(
streamInfo.Container,
streamInfo.TargetVideoCodec.FirstOrDefault(), streamInfo.TargetVideoCodec.FirstOrDefault(),
streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(),
streamInfo.TargetWidth, streamInfo.TargetWidth,
@ -681,10 +684,9 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.ToggleMute: case GeneralCommandType.ToggleMute:
return _device.ToggleMute(cancellationToken); return _device.ToggleMute(cancellationToken);
case GeneralCommandType.SetAudioStreamIndex: case GeneralCommandType.SetAudioStreamIndex:
if (command.Arguments.TryGetValue("Index", out string index))
{ {
if (command.Arguments.TryGetValue("Index", out string arg)) if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
{
if (int.TryParse(arg, NumberStyles.Integer, _usCulture, out var val))
{ {
return SetAudioStreamIndex(val); return SetAudioStreamIndex(val);
} }
@ -693,12 +695,10 @@ namespace Emby.Dlna.PlayTo
} }
throw new ArgumentException("SetAudioStreamIndex argument cannot be null"); throw new ArgumentException("SetAudioStreamIndex argument cannot be null");
}
case GeneralCommandType.SetSubtitleStreamIndex: case GeneralCommandType.SetSubtitleStreamIndex:
if (command.Arguments.TryGetValue("Index", out index))
{ {
if (command.Arguments.TryGetValue("Index", out string arg)) if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
{
if (int.TryParse(arg, NumberStyles.Integer, _usCulture, out var val))
{ {
return SetSubtitleStreamIndex(val); return SetSubtitleStreamIndex(val);
} }
@ -707,12 +707,10 @@ namespace Emby.Dlna.PlayTo
} }
throw new ArgumentException("SetSubtitleStreamIndex argument cannot be null"); throw new ArgumentException("SetSubtitleStreamIndex argument cannot be null");
}
case GeneralCommandType.SetVolume: case GeneralCommandType.SetVolume:
if (command.Arguments.TryGetValue("Volume", out string vol))
{ {
if (command.Arguments.TryGetValue("Volume", out string arg)) if (int.TryParse(vol, NumberStyles.Integer, _usCulture, out var volume))
{
if (int.TryParse(arg, NumberStyles.Integer, _usCulture, out var volume))
{ {
return _device.SetVolume(volume, cancellationToken); return _device.SetVolume(volume, cancellationToken);
} }
@ -721,8 +719,6 @@ namespace Emby.Dlna.PlayTo
} }
throw new ArgumentException("Volume argument cannot be null"); throw new ArgumentException("Volume argument cannot be null");
}
default: default:
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -795,6 +791,62 @@ namespace Emby.Dlna.PlayTo
await _device.Seek(TimeSpan.FromTicks(positionTicks), cancellationToken).ConfigureAwait(false); await _device.Seek(TimeSpan.FromTicks(positionTicks), cancellationToken).ConfigureAwait(false);
} }
private static int? GetIntValue(IReadOnlyDictionary<string, string> values, string name)
{
var value = values.GetValueOrDefault(name);
if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
return result;
}
return null;
}
private static long GetLongValue(IReadOnlyDictionary<string, string> values, string name)
{
var value = values.GetValueOrDefault(name);
if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
return result;
}
return 0;
}
/// <inheritdoc />
public Task SendMessage<T>(string name, Guid messageId, T data, CancellationToken cancellationToken)
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
if (_device == null)
{
return Task.CompletedTask;
}
if (string.Equals(name, "Play", StringComparison.OrdinalIgnoreCase))
{
return SendPlayCommand(data as PlayRequest, cancellationToken);
}
if (string.Equals(name, "PlayState", StringComparison.OrdinalIgnoreCase))
{
return SendPlaystateCommand(data as PlaystateRequest, cancellationToken);
}
if (string.Equals(name, "GeneralCommand", StringComparison.OrdinalIgnoreCase))
{
return SendGeneralCommand(data as GeneralCommand, cancellationToken);
}
// Not supported or needed right now
return Task.CompletedTask;
}
private class StreamParams private class StreamParams
{ {
private MediaSourceInfo mediaSource; private MediaSourceInfo mediaSource;
@ -908,61 +960,5 @@ namespace Emby.Dlna.PlayTo
return request; return request;
} }
} }
private static int? GetIntValue(IReadOnlyDictionary<string, string> values, string name)
{
var value = values.GetValueOrDefault(name);
if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
return result;
}
return null;
}
private static long GetLongValue(IReadOnlyDictionary<string, string> values, string name)
{
var value = values.GetValueOrDefault(name);
if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
{
return result;
}
return 0;
}
/// <inheritdoc />
public Task SendMessage<T>(string name, Guid messageId, T data, CancellationToken cancellationToken)
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
if (_device == null)
{
return Task.CompletedTask;
}
if (string.Equals(name, "Play", StringComparison.OrdinalIgnoreCase))
{
return SendPlayCommand(data as PlayRequest, cancellationToken);
}
if (string.Equals(name, "PlayState", StringComparison.OrdinalIgnoreCase))
{
return SendPlaystateCommand(data as PlaystateRequest, cancellationToken);
}
if (string.Equals(name, "GeneralCommand", StringComparison.OrdinalIgnoreCase))
{
return SendGeneralCommand(data as GeneralCommand, cancellationToken);
}
// Not supported or needed right now
return Task.CompletedTask;
}
} }
} }

View File

@ -174,7 +174,7 @@ namespace Emby.Dlna.PlayTo
if (controller == null) if (controller == null)
{ {
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, cancellationToken).ConfigureAwait(false); var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _logger, cancellationToken).ConfigureAwait(false);
string deviceName = device.Properties.Name; string deviceName = device.Properties.Name;

View File

@ -6,6 +6,6 @@ namespace Emby.Dlna.PlayTo
{ {
public class PlaybackProgressEventArgs : EventArgs public class PlaybackProgressEventArgs : EventArgs
{ {
public uBaseObject MediaInfo { get; set; } public UBaseObject MediaInfo { get; set; }
} }
} }

View File

@ -6,6 +6,6 @@ namespace Emby.Dlna.PlayTo
{ {
public class PlaybackStartEventArgs : EventArgs public class PlaybackStartEventArgs : EventArgs
{ {
public uBaseObject MediaInfo { get; set; } public UBaseObject MediaInfo { get; set; }
} }
} }

View File

@ -6,6 +6,6 @@ namespace Emby.Dlna.PlayTo
{ {
public class PlaybackStoppedEventArgs : EventArgs public class PlaybackStoppedEventArgs : EventArgs
{ {
public uBaseObject MediaInfo { get; set; } public UBaseObject MediaInfo { get; set; }
} }
} }

View File

@ -16,34 +16,26 @@ namespace Emby.Dlna.PlayTo
private List<StateVariable> _stateVariables = new List<StateVariable>(); private List<StateVariable> _stateVariables = new List<StateVariable>();
private List<ServiceAction> _serviceActions = new List<ServiceAction>(); private List<ServiceAction> _serviceActions = new List<ServiceAction>();
public List<StateVariable> StateVariables public List<StateVariable> StateVariables => _stateVariables;
{
get => _stateVariables;
set => _stateVariables = value;
}
public List<ServiceAction> ServiceActions public List<ServiceAction> ServiceActions => _serviceActions;
{
get => _serviceActions;
set => _serviceActions = value;
}
public static TransportCommands Create(XDocument document) public static TransportCommands Create(XDocument document)
{ {
var command = new TransportCommands(); var command = new TransportCommands();
var actionList = document.Descendants(uPnpNamespaces.svc + "actionList"); var actionList = document.Descendants(UPnpNamespaces.Svc + "actionList");
foreach (var container in actionList.Descendants(uPnpNamespaces.svc + "action")) foreach (var container in actionList.Descendants(UPnpNamespaces.Svc + "action"))
{ {
command.ServiceActions.Add(ServiceActionFromXml(container)); command.ServiceActions.Add(ServiceActionFromXml(container));
} }
var stateValues = document.Descendants(uPnpNamespaces.ServiceStateTable).FirstOrDefault(); var stateValues = document.Descendants(UPnpNamespaces.ServiceStateTable).FirstOrDefault();
if (stateValues != null) if (stateValues != null)
{ {
foreach (var container in stateValues.Elements(uPnpNamespaces.svc + "stateVariable")) foreach (var container in stateValues.Elements(UPnpNamespaces.Svc + "stateVariable"))
{ {
command.StateVariables.Add(FromXml(container)); command.StateVariables.Add(FromXml(container));
} }
@ -54,19 +46,19 @@ namespace Emby.Dlna.PlayTo
private static ServiceAction ServiceActionFromXml(XElement container) private static ServiceAction ServiceActionFromXml(XElement container)
{ {
var argumentList = new List<Argument>(); var serviceAction = new ServiceAction
{
Name = container.GetValue(UPnpNamespaces.Svc + "name"),
};
foreach (var arg in container.Descendants(uPnpNamespaces.svc + "argument")) var argumentList = serviceAction.ArgumentList;
foreach (var arg in container.Descendants(UPnpNamespaces.Svc + "argument"))
{ {
argumentList.Add(ArgumentFromXml(arg)); argumentList.Add(ArgumentFromXml(arg));
} }
return new ServiceAction return serviceAction;
{
Name = container.GetValue(uPnpNamespaces.svc + "name"),
ArgumentList = argumentList
};
} }
private static Argument ArgumentFromXml(XElement container) private static Argument ArgumentFromXml(XElement container)
@ -78,29 +70,29 @@ namespace Emby.Dlna.PlayTo
return new Argument return new Argument
{ {
Name = container.GetValue(uPnpNamespaces.svc + "name"), Name = container.GetValue(UPnpNamespaces.Svc + "name"),
Direction = container.GetValue(uPnpNamespaces.svc + "direction"), Direction = container.GetValue(UPnpNamespaces.Svc + "direction"),
RelatedStateVariable = container.GetValue(uPnpNamespaces.svc + "relatedStateVariable") RelatedStateVariable = container.GetValue(UPnpNamespaces.Svc + "relatedStateVariable")
}; };
} }
private static StateVariable FromXml(XElement container) private static StateVariable FromXml(XElement container)
{ {
var allowedValues = new List<string>(); var allowedValues = new List<string>();
var element = container.Descendants(uPnpNamespaces.svc + "allowedValueList") var element = container.Descendants(UPnpNamespaces.Svc + "allowedValueList")
.FirstOrDefault(); .FirstOrDefault();
if (element != null) if (element != null)
{ {
var values = element.Descendants(uPnpNamespaces.svc + "allowedValue"); var values = element.Descendants(UPnpNamespaces.Svc + "allowedValue");
allowedValues.AddRange(values.Select(child => child.Value)); allowedValues.AddRange(values.Select(child => child.Value));
} }
return new StateVariable return new StateVariable
{ {
Name = container.GetValue(uPnpNamespaces.svc + "name"), Name = container.GetValue(UPnpNamespaces.Svc + "name"),
DataType = container.GetValue(uPnpNamespaces.svc + "dataType"), DataType = container.GetValue(UPnpNamespaces.Svc + "dataType"),
AllowedValues = allowedValues.ToArray() AllowedValues = allowedValues.ToArray()
}; };
} }
@ -183,8 +175,7 @@ namespace Emby.Dlna.PlayTo
if (state != null) if (state != null)
{ {
var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ?? var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
state.AllowedValues.FirstOrDefault() ?? (state.AllowedValues.Count > 0 ? state.AllowedValues[0] : value);
value;
return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue); return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
} }

View File

@ -1,4 +1,5 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
#pragma warning disable SA1602
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {

View File

@ -6,22 +6,22 @@ using Emby.Dlna.Ssdp;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
public class UpnpContainer : uBaseObject public class UpnpContainer : UBaseObject
{ {
public static uBaseObject Create(XElement container) public static UBaseObject Create(XElement container)
{ {
if (container == null) if (container == null)
{ {
throw new ArgumentNullException(nameof(container)); throw new ArgumentNullException(nameof(container));
} }
return new uBaseObject return new UBaseObject
{ {
Id = container.GetAttributeValue(uPnpNamespaces.Id), Id = container.GetAttributeValue(UPnpNamespaces.Id),
ParentId = container.GetAttributeValue(uPnpNamespaces.ParentId), ParentId = container.GetAttributeValue(UPnpNamespaces.ParentId),
Title = container.GetValue(uPnpNamespaces.title), Title = container.GetValue(UPnpNamespaces.Title),
IconUrl = container.GetValue(uPnpNamespaces.Artwork), IconUrl = container.GetValue(UPnpNamespaces.Artwork),
UpnpClass = container.GetValue(uPnpNamespaces.uClass) UpnpClass = container.GetValue(UPnpNamespaces.Class)
}; };
} }
} }

View File

@ -1,10 +1,11 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Collections.Generic;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
public class uBaseObject public class UBaseObject
{ {
public string Id { get; set; } public string Id { get; set; }
@ -20,7 +21,7 @@ namespace Emby.Dlna.PlayTo
public string Url { get; set; } public string Url { get; set; }
public string[] ProtocolInfo { get; set; } public IReadOnlyList<string> ProtocolInfo { get; set; }
public string UpnpClass { get; set; } public string UpnpClass { get; set; }
@ -49,7 +50,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
public bool Equals(uBaseObject obj) public bool Equals(UBaseObject obj)
{ {
if (obj == null) if (obj == null)
{ {

View File

@ -4,38 +4,64 @@ using System.Xml.Linq;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
public static class uPnpNamespaces public static class UPnpNamespaces
{ {
public static XNamespace dc = "http://purl.org/dc/elements/1.1/"; public static XNamespace Dc { get; } = "http://purl.org/dc/elements/1.1/";
public static XNamespace ns = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
public static XNamespace svc = "urn:schemas-upnp-org:service-1-0";
public static XNamespace ud = "urn:schemas-upnp-org:device-1-0";
public static XNamespace upnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
public static XNamespace RenderingControl = "urn:schemas-upnp-org:service:RenderingControl:1";
public static XNamespace AvTransport = "urn:schemas-upnp-org:service:AVTransport:1";
public static XNamespace ContentDirectory = "urn:schemas-upnp-org:service:ContentDirectory:1";
public static XName containers = ns + "container"; public static XNamespace Ns { get; } = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
public static XName items = ns + "item";
public static XName title = dc + "title";
public static XName creator = dc + "creator";
public static XName artist = upnp + "artist";
public static XName Id = "id";
public static XName ParentId = "parentID";
public static XName uClass = upnp + "class";
public static XName Artwork = upnp + "albumArtURI";
public static XName Description = dc + "description";
public static XName LongDescription = upnp + "longDescription";
public static XName Album = upnp + "album";
public static XName Author = upnp + "author";
public static XName Director = upnp + "director";
public static XName PlayCount = upnp + "playbackCount";
public static XName Tracknumber = upnp + "originalTrackNumber";
public static XName Res = ns + "res";
public static XName Duration = "duration";
public static XName ProtocolInfo = "protocolInfo";
public static XName ServiceStateTable = svc + "serviceStateTable"; public static XNamespace Svc { get; } = "urn:schemas-upnp-org:service-1-0";
public static XName StateVariable = svc + "stateVariable";
public static XNamespace Ud { get; } = "urn:schemas-upnp-org:device-1-0";
public static XNamespace UPnp { get; } = "urn:schemas-upnp-org:metadata-1-0/upnp/";
public static XNamespace RenderingControl { get; } = "urn:schemas-upnp-org:service:RenderingControl:1";
public static XNamespace AvTransport { get; } = "urn:schemas-upnp-org:service:AVTransport:1";
public static XNamespace ContentDirectory { get; } = "urn:schemas-upnp-org:service:ContentDirectory:1";
public static XName Containers { get; } = Ns + "container";
public static XName Items { get; } = Ns + "item";
public static XName Title { get; } = Dc + "title";
public static XName Creator { get; } = Dc + "creator";
public static XName Artist { get; } = UPnp + "artist";
public static XName Id { get; } = "id";
public static XName ParentId { get; } = "parentID";
public static XName Class { get; } = UPnp + "class";
public static XName Artwork { get; } = UPnp + "albumArtURI";
public static XName Description { get; } = Dc + "description";
public static XName LongDescription { get; } = UPnp + "longDescription";
public static XName Album { get; } = UPnp + "album";
public static XName Author { get; } = UPnp + "author";
public static XName Director { get; } = UPnp + "director";
public static XName PlayCount { get; } = UPnp + "playbackCount";
public static XName Tracknumber { get; } = UPnp + "originalTrackNumber";
public static XName Res { get; } = Ns + "res";
public static XName Duration { get; } = "duration";
public static XName ProtocolInfo { get; } = "protocolInfo";
public static XName ServiceStateTable { get; } = Svc + "serviceStateTable";
public static XName StateVariable { get; } = Svc + "stateVariable";
} }
} }

View File

@ -210,15 +210,6 @@ namespace Emby.Dlna.Service
} }
} }
private class ControlRequestInfo
{
public string LocalName { get; set; }
public string NamespaceURI { get; set; }
public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
protected abstract void WriteResult(string methodName, IDictionary<string, string> methodParams, XmlWriter xmlWriter); protected abstract void WriteResult(string methodName, IDictionary<string, string> methodParams, XmlWriter xmlWriter);
private void LogRequest(ControlRequest request) private void LogRequest(ControlRequest request)
@ -240,5 +231,14 @@ namespace Emby.Dlna.Service
Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml); Logger.LogDebug("Control response. Headers: {@Headers}\n{Xml}", response.Headers, response.Xml);
} }
private class ControlRequestInfo
{
public string LocalName { get; set; }
public string NamespaceURI { get; set; }
public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
} }
} }

View File

@ -8,31 +8,33 @@ namespace Emby.Dlna.Service
{ {
public class BaseService : IEventManager public class BaseService : IEventManager
{ {
protected IEventManager _eventManager;
protected IHttpClient _httpClient;
protected ILogger Logger;
protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient) protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
{ {
Logger = logger; Logger = logger;
_httpClient = httpClient; HttpClient = httpClient;
_eventManager = new EventManager(logger, _httpClient); EventManager = new EventManager(logger, HttpClient);
} }
protected IEventManager EventManager { get; }
protected IHttpClient HttpClient { get; }
protected ILogger Logger { get; }
public EventSubscriptionResponse CancelEventSubscription(string subscriptionId) public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)
{ {
return _eventManager.CancelEventSubscription(subscriptionId); return EventManager.CancelEventSubscription(subscriptionId);
} }
public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl) public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl)
{ {
return _eventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl); return EventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl);
} }
public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl) public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl)
{ {
return _eventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl); return EventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl);
} }
} }
} }

View File

@ -87,7 +87,7 @@ namespace Emby.Dlna.Service
.Append(SecurityElement.Escape(item.DataType ?? string.Empty)) .Append(SecurityElement.Escape(item.DataType ?? string.Empty))
.Append("</dataType>"); .Append("</dataType>");
if (item.AllowedValues.Length > 0) if (item.AllowedValues.Count > 0)
{ {
builder.Append("<allowedValueList>"); builder.Append("<allowedValueList>");
foreach (var allowedValue in item.AllowedValues) foreach (var allowedValue in item.AllowedValues)

View File

@ -5,7 +5,7 @@ using System.Xml.Linq;
namespace Emby.Dlna.Ssdp namespace Emby.Dlna.Ssdp
{ {
public static class Extensions public static class SsdpExtensions
{ {
public static string GetValue(this XElement container, XName name) public static string GetValue(this XElement container, XName name)
{ {

View File

@ -221,9 +221,8 @@ namespace Jellyfin.Api.Controllers
private Task<ControlResponse> ProcessControlRequestInternalAsync(string id, Stream requestStream, IUpnpService service) private Task<ControlResponse> ProcessControlRequestInternalAsync(string id, Stream requestStream, IUpnpService service)
{ {
return service.ProcessControlRequestAsync(new ControlRequest return service.ProcessControlRequestAsync(new ControlRequest(Request.Headers)
{ {
Headers = Request.Headers,
InputXml = requestStream, InputXml = requestStream,
TargetServerUuId = id, TargetServerUuId = id,
RequestedUrl = GetAbsoluteUri() RequestedUrl = GetAbsoluteUri()