|
@@ -7,13 +7,14 @@
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
*/
|
|
|
|
|
|
-#include <platform_bt_sink.h>
|
|
|
|
#include <stdint.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <string.h>
|
|
#include "esp_log.h"
|
|
#include "esp_log.h"
|
|
|
|
|
|
|
|
+#include "bt_app_core.h"
|
|
|
|
+#include "bt_app_sink.h"
|
|
#include "esp_bt.h"
|
|
#include "esp_bt.h"
|
|
#include "esp_bt_main.h"
|
|
#include "esp_bt_main.h"
|
|
#include "esp_bt_device.h"
|
|
#include "esp_bt_device.h"
|
|
@@ -21,14 +22,13 @@
|
|
#include "esp_a2dp_api.h"
|
|
#include "esp_a2dp_api.h"
|
|
#include "esp_avrc_api.h"
|
|
#include "esp_avrc_api.h"
|
|
#include "nvs.h"
|
|
#include "nvs.h"
|
|
-#include "platform_config.h"
|
|
|
|
|
|
+#include "config.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/task.h"
|
|
#include "trace.h"
|
|
#include "trace.h"
|
|
#include "audio_controls.h"
|
|
#include "audio_controls.h"
|
|
#include "sys/lock.h"
|
|
#include "sys/lock.h"
|
|
#include "display.h"
|
|
#include "display.h"
|
|
-#include "platform_bt_core.h"
|
|
|
|
|
|
|
|
// AVRCP used transaction label
|
|
// AVRCP used transaction label
|
|
#define APP_RC_CT_TL_GET_CAPS (0)
|
|
#define APP_RC_CT_TL_GET_CAPS (0)
|
|
@@ -71,8 +71,7 @@ static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
|
|
static _lock_t s_volume_lock;
|
|
static _lock_t s_volume_lock;
|
|
static uint8_t s_volume = 0;
|
|
static uint8_t s_volume = 0;
|
|
static bool s_volume_notify;
|
|
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 s_sample_rate;
|
|
static int tl;
|
|
static int tl;
|
|
@@ -102,7 +101,7 @@ static void bt_volume_down(void) {
|
|
}
|
|
}
|
|
|
|
|
|
static void bt_toggle(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);
|
|
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 */
|
|
/* disconnection */
|
|
void bt_disconnect(void) {
|
|
void bt_disconnect(void) {
|
|
displayer_control(DISPLAYER_SHUTDOWN);
|
|
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();
|
|
actrls_unset();
|
|
- ESP_LOGI(BT_AV_TAG, "forced disconnection");
|
|
|
|
|
|
+ ESP_LOGI(BT_AV_TAG, "forced disconnection %d", s_audio);
|
|
}
|
|
}
|
|
|
|
|
|
/* update metadata if any */
|
|
/* update metadata if any */
|
|
void update_metadata(bool force) {
|
|
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_PROGRESS, -1, s_metadata.duration);
|
|
(*bt_app_a2d_cmd_cb)(BT_SINK_METADATA, s_metadata.artist, s_metadata.album, s_metadata.title);
|
|
(*bt_app_a2d_cmd_cb)(BT_SINK_METADATA, s_metadata.artist, s_metadata.album, s_metadata.title);
|
|
s_metadata.updated = false;
|
|
s_metadata.updated = false;
|
|
@@ -231,7 +230,6 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param
|
|
switch (event) {
|
|
switch (event) {
|
|
case ESP_AVRC_CT_METADATA_RSP_EVT:
|
|
case ESP_AVRC_CT_METADATA_RSP_EVT:
|
|
bt_app_alloc_meta_buffer(param);
|
|
bt_app_alloc_meta_buffer(param);
|
|
- /* no break */
|
|
|
|
/* fall through */
|
|
/* fall through */
|
|
case ESP_AVRC_CT_CONNECTION_STATE_EVT:
|
|
case ESP_AVRC_CT_CONNECTION_STATE_EVT:
|
|
case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT:
|
|
case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT:
|
|
@@ -291,18 +289,17 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param)
|
|
|
|
|
|
// verify that we can take control
|
|
// verify that we can take control
|
|
if ((*bt_app_a2d_cmd_cb)(BT_SINK_AUDIO_STARTED, s_sample_rate)) {
|
|
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
|
|
// force metadata update
|
|
update_metadata(true);
|
|
update_metadata(true);
|
|
|
|
|
|
actrls_set(controls, NULL);
|
|
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);
|
|
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 ||
|
|
} else if (ESP_A2D_AUDIO_STATE_STOPPED == a2d->audio_stat.state ||
|
|
@@ -383,19 +380,33 @@ void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_param
|
|
break;
|
|
break;
|
|
case ESP_AVRC_RN_PLAY_STATUS_CHANGE:
|
|
case ESP_AVRC_RN_PLAY_STATUS_CHANGE:
|
|
ESP_LOGI(BT_AV_TAG, "Playback status changed: 0x%x", event_parameter->playback);
|
|
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();
|
|
bt_av_playback_changed();
|
|
break;
|
|
break;
|