diff --git a/components/driver_bt/bt_app_sink.c b/components/driver_bt/bt_app_sink.c index 7159e6ff..e0d4d34d 100644 --- a/components/driver_bt/bt_app_sink.c +++ b/components/driver_bt/bt_app_sink.c @@ -71,8 +71,7 @@ static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; static _lock_t s_volume_lock; static uint8_t s_volume = 0; static bool s_volume_notify; -static bool s_playing = false; -static enum { AUDIO_IDLE, AUDIO_CONNECTED, AUDIO_ACTIVATED } s_audio = AUDIO_IDLE; +static enum { AUDIO_IDLE, AUDIO_CONNECTED, AUDIO_PLAYING } s_audio = AUDIO_IDLE; static int s_sample_rate; static int tl; @@ -102,7 +101,7 @@ static void bt_volume_down(void) { } static void bt_toggle(void) { - if (s_playing) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + if (s_audio == AUDIO_PLAYING) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); else esp_avrc_ct_send_passthrough_cmd(tl++, ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STATE_PRESSED); } @@ -139,14 +138,14 @@ const static actrls_t controls = { /* disconnection */ void bt_disconnect(void) { displayer_control(DISPLAYER_SHUTDOWN); - if (s_playing) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + if (s_audio == AUDIO_PLAYING) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); actrls_unset(); - ESP_LOGI(BT_AV_TAG, "forced disconnection"); + ESP_LOGI(BT_AV_TAG, "forced disconnection %d", s_audio); } /* update metadata if any */ void update_metadata(bool force) { - if ((s_metadata.updated || force) && s_audio == AUDIO_ACTIVATED) { + if ((s_metadata.updated || force) && s_audio == AUDIO_PLAYING) { (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, -1, s_metadata.duration); (*bt_app_a2d_cmd_cb)(BT_SINK_METADATA, s_metadata.artist, s_metadata.album, s_metadata.title); s_metadata.updated = false; @@ -290,18 +289,17 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) // verify that we can take control if ((*bt_app_a2d_cmd_cb)(BT_SINK_AUDIO_STARTED, s_sample_rate)) { - // resynchronize events as¨PLAY might be sent before STARTED ... - s_audio = AUDIO_ACTIVATED; - // send PLAY there, in case it was sent before AUDIO_STATE - if (s_playing) (*bt_app_a2d_cmd_cb)(BT_SINK_PLAY); + // if PLAY is sent before AUDIO_STARTED, generate the event here + s_audio = AUDIO_PLAYING; + (*bt_app_a2d_cmd_cb)(BT_SINK_PLAY); // force metadata update update_metadata(true); actrls_set(controls, NULL); - } else if (s_playing) { - // if decoder is busy but BT is playing, stop it (would be better to not ACK this command, but don't know how) + } else { + // if decoder is busy, stop it (would be better to not ACK this command, but don't know how) esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); } } else if (ESP_A2D_AUDIO_STATE_STOPPED == a2d->audio_stat.state || @@ -382,19 +380,33 @@ void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_param break; case ESP_AVRC_RN_PLAY_STATUS_CHANGE: ESP_LOGI(BT_AV_TAG, "Playback status changed: 0x%x", event_parameter->playback); - // re-synchronize events - s_playing = (event_parameter->playback == ESP_AVRC_PLAYBACK_PLAYING); - if (event_parameter->playback == ESP_AVRC_PLAYBACK_PLAYING && s_audio != AUDIO_IDLE) { - // if decoder is busy then stop (would be better to not ACK this command, but don't know how) - if (s_audio == AUDIO_CONNECTED || !(*bt_app_a2d_cmd_cb)(BT_SINK_PLAY)) { - esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); - } else { - update_metadata(false); + if (s_audio != AUDIO_IDLE) { + switch (event_parameter->playback) { + case ESP_AVRC_PLAYBACK_PLAYING: + // if decoder is busy then stop (would be better to not ACK this command, but don't know how) + if (s_audio != AUDIO_PLAYING && !(*bt_app_a2d_cmd_cb)(BT_SINK_PLAY)) { + ESP_LOGW(BT_AV_TAG, "Player busy with another controller"); + esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED); + } else { + s_audio = AUDIO_PLAYING; + update_metadata(false); + } + break; + case ESP_AVRC_PLAYBACK_PAUSED: + s_audio = AUDIO_CONNECTED; + (*bt_app_a2d_cmd_cb)(BT_SINK_PAUSE); + break; + case ESP_AVRC_PLAYBACK_STOPPED: + s_audio = AUDIO_CONNECTED; + (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, 0, -1); + (*bt_app_a2d_cmd_cb)(BT_SINK_STOP); + break; + default: + ESP_LOGI(BT_AV_TAG, "Un-handled event"); + break; } - } else if (event_parameter->playback == ESP_AVRC_PLAYBACK_PAUSED) (*bt_app_a2d_cmd_cb)(BT_SINK_PAUSE); - else if (event_parameter->playback == ESP_AVRC_PLAYBACK_STOPPED) { - (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, 0, -1); - (*bt_app_a2d_cmd_cb)(BT_SINK_STOP); + } else { + ESP_LOGW(BT_AV_TAG, "Not yet in BT connected mode: 0x%x", event_parameter->playback); } bt_av_playback_changed(); break; diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index 2d3c3a65..46e26fe7 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -127,12 +127,13 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) output.frames_played = 0; _buf_flush(outputbuf); if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR; - LOG_INFO("BT sink started"); + LOG_INFO("BT audio sink started"); break; case BT_SINK_AUDIO_STOPPED: if (output.external == DECODE_BT) { if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; - LOG_INFO("BT sink stopped"); + output.stop_time = gettime_ms(); + LOG_INFO("BT audio sink stopped"); } break; case BT_SINK_PLAY: @@ -146,6 +147,7 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) LOG_INFO("BT sink stopped"); break; case BT_SINK_PAUSE: + output.stop_time = gettime_ms(); LOG_INFO("BT sink paused, just silence"); break; case BT_SINK_RATE: