public async Task <bool> JoinPlaylist( string query, string token, Station station, string stationToken, CancellationToken cancellationToken) { // is the station playing? // default the position to what was returned by get info var info = await GetUserNowPlaying(stationToken); if ( info == null || !info.IsPlaying || info.Context == null || SpotifyUriHelper.NormalizeUri(info.Context.Uri) != SpotifyUriHelper.NormalizeUri(station.SpotifyUri)) { _logger.LogInformation($"JoinPlaylist: No longer playing station {station}"); _logger.LogDebug($"JoinPlaylist: station.SpotifyUri = {station.SpotifyUri}"); _logger.LogDebug($"JoinPlaylist: info = {JsonConvert.SerializeObject(info)}"); return(false); } (string itemId, (long positionMs, DateTime atUtc)position)itemPosition = (info.Item?.Id, (info.ProgressMs ?? 0, DateTime.UtcNow)); if (!SupportedSpotifyItemTypes.Contains(station.SpotifyContextType)) { throw new NotSupportedException($"\"{station.SpotifyContextType}\" is not a supported Spotify context type"); } var offset = await GetOffset(stationToken); if (offset.success) { // reset position to Station position itemPosition.itemId = offset.itemId; itemPosition.position = offset.position; } await TurnOffShuffleRepeat(token, info); try { // mute joining player await Volume(token, 0, info.Device.Id); // play from offset switch (station.SpotifyContextType) { case "album": await RetryHelper.RetryAsync( () => _player.PlayAlbumOffset( info.Context.Uri, info.Item.Id, accessToken: token, positionMs: PositionMsNow(itemPosition.position).positionMs), logger : _logger, cancellationToken : cancellationToken); break; case "playlist": await RetryHelper.RetryAsync( () => _player.PlayPlaylistOffset( info.Context.Uri, info.Item.Id, accessToken: token, positionMs: PositionMsNow(itemPosition.position).positionMs), logger : _logger, cancellationToken : cancellationToken); break; } if (offset.success) { await SyncJoiningPlayer(stationToken : stationToken, joiningToken : token); } } finally { // unmute joining player await Volume(token, (int)info.Device.VolumePercent, info.Device.Id); } return(true); }