mirror of https://github.com/jellyfin/jellyfin.git
Fix all warnings in Emby.Dlna
This commit is contained in:
parent
ac58d07e0e
commit
170e434f92
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,
|
|
@ -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,
|
{
|
||||||
TotalRecordCount = folders.Length
|
Items = folders,
|
||||||
}, startIndex, limit);
|
TotalRecordCount = folders.Length
|
||||||
|
},
|
||||||
|
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,
|
{
|
||||||
Limit = 50,
|
UserId = user.Id,
|
||||||
IncludeItemTypes = new[] { nameof(Audio) },
|
Limit = 50,
|
||||||
ParentId = parent?.Id ?? Guid.Empty,
|
IncludeItemTypes = new[] { nameof(Audio) },
|
||||||
GroupItems = true
|
ParentId = parent?.Id ?? Guid.Empty,
|
||||||
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
|
GroupItems = true
|
||||||
|
},
|
||||||
|
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,
|
{
|
||||||
StartIndex = query.StartIndex,
|
Limit = query.Limit,
|
||||||
UserId = query.User.Id
|
StartIndex = query.StartIndex,
|
||||||
}, new[] { parent }, query.DtoOptions);
|
UserId = query.User.Id
|
||||||
|
},
|
||||||
|
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,
|
{
|
||||||
Limit = 50,
|
UserId = user.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
Limit = 50,
|
||||||
ParentId = parent == null ? Guid.Empty : parent.Id,
|
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||||
GroupItems = false
|
ParentId = parent == null ? Guid.Empty : parent.Id,
|
||||||
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
|
GroupItems = false
|
||||||
|
},
|
||||||
|
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
|
||||||
|
|
||||||
return ToResult(items);
|
return ToResult(items);
|
||||||
}
|
}
|
||||||
|
@ -1183,13 +1196,14 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
var items = _userViewManager.GetLatestItems(
|
var items = _userViewManager.GetLatestItems(
|
||||||
new LatestItemsQuery
|
new LatestItemsQuery
|
||||||
{
|
{
|
||||||
UserId = user.Id,
|
UserId = user.Id,
|
||||||
Limit = 50,
|
Limit = 50,
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
{
|
}
|
||||||
Url = url,
|
|
||||||
Width = width,
|
private class ImageDownloadInfo
|
||||||
Height = height
|
{
|
||||||
};
|
internal Guid ItemId { get; set; }
|
||||||
|
|
||||||
|
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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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-->
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,19 +108,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DlnaEntryPoint Current { get; private set; }
|
public static DlnaEntryPoint Current { get; private set; }
|
||||||
|
|
||||||
public IContentDirectory ContentDirectory { get; private set; }
|
public IContentDirectory ContentDirectory { get; private set; }
|
||||||
|
@ -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();
|
||||||
{
|
DisposePlayToManager();
|
||||||
DisposeDevicePublisher();
|
DisposeDeviceDiscovery();
|
||||||
DisposePlayToManager();
|
|
||||||
DisposeDeviceDiscovery();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_communicationsServer != null)
|
if (_communicationsServer != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,42 +503,44 @@ 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.TargetAudioCodec.FirstOrDefault(),
|
streamInfo.Container,
|
||||||
streamInfo.TargetAudioBitrate,
|
streamInfo.TargetAudioCodec.FirstOrDefault(),
|
||||||
streamInfo.TargetAudioSampleRate,
|
streamInfo.TargetAudioBitrate,
|
||||||
streamInfo.TargetAudioChannels,
|
streamInfo.TargetAudioSampleRate,
|
||||||
streamInfo.TargetAudioBitDepth,
|
streamInfo.TargetAudioChannels,
|
||||||
streamInfo.IsDirectStream,
|
streamInfo.TargetAudioBitDepth,
|
||||||
streamInfo.RunTimeTicks ?? 0,
|
streamInfo.IsDirectStream,
|
||||||
streamInfo.TranscodeSeekInfo);
|
streamInfo.RunTimeTicks ?? 0,
|
||||||
|
streamInfo.TranscodeSeekInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.TargetVideoCodec.FirstOrDefault(),
|
streamInfo.Container,
|
||||||
streamInfo.TargetAudioCodec.FirstOrDefault(),
|
streamInfo.TargetVideoCodec.FirstOrDefault(),
|
||||||
streamInfo.TargetWidth,
|
streamInfo.TargetAudioCodec.FirstOrDefault(),
|
||||||
streamInfo.TargetHeight,
|
streamInfo.TargetWidth,
|
||||||
streamInfo.TargetVideoBitDepth,
|
streamInfo.TargetHeight,
|
||||||
streamInfo.TargetVideoBitrate,
|
streamInfo.TargetVideoBitDepth,
|
||||||
streamInfo.TargetTimestamp,
|
streamInfo.TargetVideoBitrate,
|
||||||
streamInfo.IsDirectStream,
|
streamInfo.TargetTimestamp,
|
||||||
streamInfo.RunTimeTicks ?? 0,
|
streamInfo.IsDirectStream,
|
||||||
streamInfo.TargetVideoProfile,
|
streamInfo.RunTimeTicks ?? 0,
|
||||||
streamInfo.TargetVideoLevel,
|
streamInfo.TargetVideoProfile,
|
||||||
streamInfo.TargetFramerate ?? 0,
|
streamInfo.TargetVideoLevel,
|
||||||
streamInfo.TargetPacketLength,
|
streamInfo.TargetFramerate ?? 0,
|
||||||
streamInfo.TranscodeSeekInfo,
|
streamInfo.TargetPacketLength,
|
||||||
streamInfo.IsTargetAnamorphic,
|
streamInfo.TranscodeSeekInfo,
|
||||||
streamInfo.IsTargetInterlaced,
|
streamInfo.IsTargetAnamorphic,
|
||||||
streamInfo.TargetRefFrames,
|
streamInfo.IsTargetInterlaced,
|
||||||
streamInfo.TargetVideoStreamCount,
|
streamInfo.TargetRefFrames,
|
||||||
streamInfo.TargetAudioStreamCount,
|
streamInfo.TargetVideoStreamCount,
|
||||||
streamInfo.TargetVideoCodecTag,
|
streamInfo.TargetAudioStreamCount,
|
||||||
streamInfo.IsTargetAVC);
|
streamInfo.TargetVideoCodecTag,
|
||||||
|
streamInfo.IsTargetAVC);
|
||||||
|
|
||||||
return list.Count == 0 ? null : list[0];
|
return list.Count == 0 ? null : list[0];
|
||||||
}
|
}
|
||||||
|
@ -681,48 +684,41 @@ 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException("Unsupported SetAudioStreamIndex value supplied.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException("SetAudioStreamIndex argument cannot be null");
|
throw new ArgumentException("Unsupported SetAudioStreamIndex value supplied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException("Unsupported SetSubtitleStreamIndex value supplied.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException("SetSubtitleStreamIndex argument cannot be null");
|
throw new ArgumentException("Unsupported SetSubtitleStreamIndex value supplied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException("Unsupported volume value supplied.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException("Volume argument cannot be null");
|
throw new ArgumentException("Unsupported volume value supplied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable SA1602
|
||||||
|
|
||||||
namespace Emby.Dlna.PlayTo
|
namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue