aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStéphane Senart <stephane.senart@gmail.com>2021-03-29 12:11:38 +0200
committerStéphane Senart <stephane.senart@gmail.com>2021-03-29 12:11:38 +0200
commita7c82b2681aa966e11958ee71d2d20fb20f8233f (patch)
tree12a9f8d2da803886eda79346421bf043ec8a24d6
parent8410a9a26601d754e3c8bed36641c990f1d0e22b (diff)
[5644] [DLNA] [Music] Next track command from any DLNA device does not do anything.
-rw-r--r--Emby.Dlna/PlayTo/Device.cs36
-rw-r--r--Emby.Dlna/PlayTo/PlayToController.cs40
2 files changed, 76 insertions, 0 deletions
diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs
index 7bf7047fb..9d45e89df 100644
--- a/Emby.Dlna/PlayTo/Device.cs
+++ b/Emby.Dlna/PlayTo/Device.cs
@@ -368,6 +368,42 @@ namespace Emby.Dlna.PlayTo
RestartTimer(true);
}
+ /*
+ * SetNextAvTransport is used to specify to the DLNA device what is the next track to play.
+ * Without that information, the next track command on the device does not work.
+ */
+ public async Task SetNextAvTransport(string url, string header, string metaData, CancellationToken cancellationToken = default)
+ {
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ url = url.Replace("&", "&amp;", StringComparison.Ordinal);
+
+ _logger.LogDebug("{0} - SetNextAvTransport Uri: {1} DlnaHeaders: {2}", Properties.Name, url, header);
+
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetNextAVTransportURI");
+ if (command == null)
+ {
+ return;
+ }
+
+ var dictionary = new Dictionary<string, string>
+ {
+ { "NextURI", url },
+ { "NextURIMetaData", CreateDidlMeta(metaData) }
+ };
+
+ var service = GetAvTransportService();
+
+ if (service == null)
+ {
+ throw new InvalidOperationException("Unable to find service");
+ }
+
+ var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
+ await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header, cancellationToken)
+ .ConfigureAwait(false);
+ }
+
private static string CreateDidlMeta(string value)
{
if (string.IsNullOrEmpty(value))
diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs
index 5abc1bc13..503c2eee2 100644
--- a/Emby.Dlna/PlayTo/PlayToController.cs
+++ b/Emby.Dlna/PlayTo/PlayToController.cs
@@ -102,6 +102,22 @@ namespace Emby.Dlna.PlayTo
_deviceDiscovery.DeviceLeft += OnDeviceDiscoveryDeviceLeft;
}
+ /*
+ * Send a message to the DLNA device to notify what is the next track in the playlist.
+ */
+ private async void SendNextTrackMessage(int currentPlayListItemIndex, CancellationToken cancellationToken)
+ {
+ if (currentPlayListItemIndex >= 0 && currentPlayListItemIndex < _playlist.Count - 1)
+ {
+ // The current playing item is indeed in the play list and we are not yet at the end of the playlist.
+ var nextItemIndex = currentPlayListItemIndex + 1;
+ var nextItem = _playlist[nextItemIndex];
+
+ // Send the SetNextAvTransport message.
+ await _device.SetNextAvTransport(nextItem.StreamUrl, GetDlnaHeaders(nextItem), nextItem.Didl, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
private void OnDeviceUnavailable()
{
try
@@ -153,6 +169,14 @@ namespace Emby.Dlna.PlayTo
return;
}
+ // Create the new play list item : mainly to have the normalized StreamUrl and find it in the playlist.
+ var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
+ var newItem = CreatePlaylistItem(streamInfo.Item, user, 0, streamInfo.MediaSourceId, streamInfo.AudioStreamIndex, streamInfo.SubtitleStreamIndex);
+
+ // Send a message to the DLNA device to notify what is the next track in the playlist.
+ var currentItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
+ SendNextTrackMessage(currentItemIndex, CancellationToken.None);
+
var newItemProgress = GetProgressInfo(streamInfo);
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
@@ -425,6 +449,11 @@ namespace Emby.Dlna.PlayTo
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, info.SubtitleStreamIndex);
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
+
+ // Send a message to the DLNA device to notify what is the next track in the play list.
+ var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
+ SendNextTrackMessage(newItemIndex, CancellationToken.None);
+
return;
}
@@ -623,6 +652,9 @@ namespace Emby.Dlna.PlayTo
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, cancellationToken).ConfigureAwait(false);
+ // Send a message to the DLNA device to notify what is the next track in the play list.
+ SendNextTrackMessage(index, CancellationToken.None);
+
var streamInfo = currentitem.StreamInfo;
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo))
{
@@ -736,6 +768,10 @@ namespace Emby.Dlna.PlayTo
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
+ // Send a message to the DLNA device to notify what is the next track in the play list.
+ var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
+ SendNextTrackMessage(newItemIndex, CancellationToken.None);
+
if (EnableClientSideSeek(newItem.StreamInfo))
{
await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false);
@@ -761,6 +797,10 @@ namespace Emby.Dlna.PlayTo
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
+ // Send a message to the DLNA device to notify what is the next track in the play list.
+ var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
+ SendNextTrackMessage(newItemIndex, CancellationToken.None);
+
if (EnableClientSideSeek(newItem.StreamInfo) && newPosition > 0)
{
await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false);