Merge remote-tracking branch 'origin/master' into master-cmake

Conflicts:
	README.md
	components/config/config.c
	components/driver_bt/bt_app_sink.c
	components/raop/raop.c
	components/services/audio_controls.c
	main/platform_esp32.h
This commit is contained in:
Sebastien
2020-05-18 10:13:32 -04:00
60 changed files with 1944 additions and 860 deletions

View File

@@ -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;
@@ -88,41 +87,49 @@ static EXT_RAM_ATTR struct {
bool updated;
} s_metadata;
static void bt_volume_up(void) {
static void bt_volume_up(bool pressed) {
if (!pressed) return;
// volume UP/DOWN buttons are not supported by iPhone/Android
volume_set_by_local_host(s_volume < 127-3 ? s_volume + 3 : 127);
(*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume);
ESP_LOGI(BT_AV_TAG, "BT volume up %u", s_volume);
}
static void bt_volume_down(void) {
static void bt_volume_down(bool pressed) {
if (!pressed) return;
// volume UP/DOWN buttons are not supported by iPhone/Android
volume_set_by_local_host(s_volume > 3 ? s_volume - 3 : 0);
(*bt_app_a2d_cmd_cb)(BT_SINK_VOLUME, s_volume);
}
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);
static void bt_toggle(bool pressed) {
if (!pressed) return;
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);
}
static void bt_play(void) {
static void bt_play(bool pressed) {
if (!pressed) return;
esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_PLAY, ESP_AVRC_PT_CMD_STATE_PRESSED);
}
static void bt_pause(void) {
static void bt_pause(bool pressed) {
if (!pressed) return;
esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_PAUSE, ESP_AVRC_PT_CMD_STATE_PRESSED);
}
static void bt_stop(void) {
static void bt_stop(bool pressed) {
if (!pressed) return;
esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED);
}
static void bt_prev(void) {
static void bt_prev(bool pressed) {
if (!pressed) return;
esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_BACKWARD, ESP_AVRC_PT_CMD_STATE_PRESSED);
}
static void bt_next(void) {
static void bt_next(bool pressed) {
if (!pressed) return;
esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_FORWARD, ESP_AVRC_PT_CMD_STATE_PRESSED);
}
@@ -139,14 +146,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 +297,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)
actrls_set(controls, false, NULL, actrls_ir_action);
} 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 +388,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;