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

Conflicts:
	components/driver_bt/bt_app_sink.c
This commit is contained in:
Sebastien
2020-03-15 08:37:23 -04:00
7 changed files with 50 additions and 34 deletions

View File

@@ -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_PLAYING } s_audio = AUDIO_IDLE;
static enum { AUDIO_IDLE, AUDIO_CONNECTED, AUDIO_ACTIVATED } 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 PLAY is sent before AUDIO_STARTED, generate the event here
if (s_playing) (*bt_app_a2d_cmd_cb)(BT_SINK_PLAY); 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) { } else {
// if decoder is busy but BT is playing, stop it (would be better to not ACK this command, but don't know how) // 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 if (s_audio != AUDIO_IDLE) {
s_playing = (event_parameter->playback == ESP_AVRC_PLAYBACK_PLAYING); switch (event_parameter->playback) {
if (event_parameter->playback == ESP_AVRC_PLAYBACK_PLAYING && s_audio != AUDIO_IDLE) { 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 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)) { 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); esp_avrc_ct_send_passthrough_cmd(tl++ & 0x0f, ESP_AVRC_PT_CMD_STOP, ESP_AVRC_PT_CMD_STATE_PRESSED);
} else { } else {
s_audio = AUDIO_PLAYING;
update_metadata(false); update_metadata(false);
} }
} else if (event_parameter->playback == ESP_AVRC_PLAYBACK_PAUSED) (*bt_app_a2d_cmd_cb)(BT_SINK_PAUSE); break;
else if (event_parameter->playback == ESP_AVRC_PLAYBACK_STOPPED) { 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_PROGRESS, 0, -1);
(*bt_app_a2d_cmd_cb)(BT_SINK_STOP); (*bt_app_a2d_cmd_cb)(BT_SINK_STOP);
break;
default:
ESP_LOGI(BT_AV_TAG, "Un-handled event");
break;
}
} 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;

View File

@@ -10,7 +10,8 @@
#define __BT_APP_SINK_H__ #define __BT_APP_SINK_H__
#include <stdint.h> #include <stdint.h>
#include <platform_bt_core.h>
#include "platform_bt_core.h"
typedef enum { BT_SINK_CONNECTED, BT_SINK_DISCONNECTED, BT_SINK_AUDIO_STARTED, BT_SINK_AUDIO_STOPPED, BT_SINK_PLAY, BT_SINK_STOP, BT_SINK_PAUSE, typedef enum { BT_SINK_CONNECTED, BT_SINK_DISCONNECTED, BT_SINK_AUDIO_STARTED, BT_SINK_AUDIO_STOPPED, BT_SINK_PLAY, BT_SINK_STOP, BT_SINK_PAUSE,
BT_SINK_RATE, BT_SINK_VOLUME, BT_SINK_METADATA, BT_SINK_PROGRESS } bt_sink_cmd_t; BT_SINK_RATE, BT_SINK_VOLUME, BT_SINK_METADATA, BT_SINK_PROGRESS } bt_sink_cmd_t;

View File

@@ -3,6 +3,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include "platform_bt_core.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_bt.h" #include "esp_bt.h"
#include "esp_bt_device.h" #include "esp_bt_device.h"
@@ -15,7 +16,6 @@
#include "esp_wifi.h" #include "esp_wifi.h"
#include "freertos/timers.h" #include "freertos/timers.h"
#include "argtable3/argtable3.h" #include "argtable3/argtable3.h"
#include "platform_bt_core.h"
#include "platform_config.h" #include "platform_config.h"
#include "trace.h" #include "trace.h"

View File

@@ -362,6 +362,7 @@ void displayer_control(enum displayer_cmd_e cmd, ...) {
break; break;
case DISPLAYER_TIMER_RUN: case DISPLAYER_TIMER_RUN:
if (!displayer.timer) { if (!displayer.timer) {
display_bus(&displayer, DISPLAY_BUS_TAKE);
displayer.timer = true; displayer.timer = true;
displayer.tick = xTaskGetTickCount(); displayer.tick = xTaskGetTickCount();
} }

View File

@@ -23,7 +23,8 @@
#include "squeezelite.h" #include "squeezelite.h"
#include "raop_sink.h" #include "raop_sink.h"
#include <math.h> #include <math.h>
#include <platform_bt_sink.h>
#include "bt_app_sink.h"
#define LOCK_O mutex_lock(outputbuf->mutex) #define LOCK_O mutex_lock(outputbuf->mutex)
#define UNLOCK_O mutex_unlock(outputbuf->mutex) #define UNLOCK_O mutex_unlock(outputbuf->mutex)
@@ -132,21 +133,23 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args)
case BT_SINK_AUDIO_STOPPED: case BT_SINK_AUDIO_STOPPED:
if (output.external == DECODE_BT) { if (output.external == DECODE_BT) {
if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED;
output.stop_time = gettime_ms();
LOG_INFO("BT sink stopped"); LOG_INFO("BT sink stopped");
} }
break; break;
case BT_SINK_PLAY: case BT_SINK_PLAY:
output.state = OUTPUT_RUNNING; output.state = OUTPUT_RUNNING;
LOG_INFO("BT sink playing"); LOG_INFO("BT playing");
break; break;
case BT_SINK_STOP: case BT_SINK_STOP:
_buf_flush(outputbuf); _buf_flush(outputbuf);
output.state = OUTPUT_STOPPED; output.state = OUTPUT_STOPPED;
output.stop_time = gettime_ms(); output.stop_time = gettime_ms();
LOG_INFO("BT sink stopped"); LOG_INFO("BT stopped");
break; break;
case BT_SINK_PAUSE: case BT_SINK_PAUSE:
LOG_INFO("BT sink paused, just silence"); output.stop_time = gettime_ms();
LOG_INFO("BT paused, just silence");
break; break;
case BT_SINK_RATE: case BT_SINK_RATE:
output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t); output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t);