[5644] [DLNA] [Music] Next track command from any DLNA device does not do anything.

This commit is contained in:
Stéphane Senart 2021-03-29 12:11:38 +02:00
parent 8410a9a266
commit a7c82b2681
2 changed files with 76 additions and 0 deletions

View File

@ -368,6 +368,42 @@ namespace Emby.Dlna.PlayTo
RestartTimer(true); 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("&", "&", 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) private static string CreateDidlMeta(string value)
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))

View File

@ -102,6 +102,22 @@ namespace Emby.Dlna.PlayTo
_deviceDiscovery.DeviceLeft += OnDeviceDiscoveryDeviceLeft; _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() private void OnDeviceUnavailable()
{ {
try try
@ -153,6 +169,14 @@ namespace Emby.Dlna.PlayTo
return; 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); var newItemProgress = GetProgressInfo(streamInfo);
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false); 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); 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); 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; return;
} }
@ -623,6 +652,9 @@ namespace Emby.Dlna.PlayTo
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, cancellationToken).ConfigureAwait(false); 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; var streamInfo = currentitem.StreamInfo;
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(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); 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)) if (EnableClientSideSeek(newItem.StreamInfo))
{ {
await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false); 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); 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) if (EnableClientSideSeek(newItem.StreamInfo) && newPosition > 0)
{ {
await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false); await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false);