|
@@ -37,6 +37,8 @@ static EXT_RAM_ATTR struct {
|
|
|
} raop_sync;
|
|
|
#endif
|
|
|
|
|
|
+static bool abort_sink ;
|
|
|
+
|
|
|
#define LOCK_O mutex_lock(outputbuf->mutex)
|
|
|
#define UNLOCK_O mutex_unlock(outputbuf->mutex)
|
|
|
#define LOCK_D mutex_lock(decode.mutex);
|
|
@@ -63,11 +65,12 @@ static void sink_data_handler(const uint8_t *data, uint32_t len)
|
|
|
LOG_SDEBUG("Cannot use external sink while LMS is controlling player");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- // there will always be room at some point
|
|
|
- while (len) {
|
|
|
- LOCK_O;
|
|
|
|
|
|
+ LOCK_O;
|
|
|
+ abort_sink = false;
|
|
|
+
|
|
|
+ // there will always be room at some point
|
|
|
+ while (len && wait && !abort_sink) {
|
|
|
bytes = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / (BYTES_PER_FRAME / 4);
|
|
|
bytes = min(len, bytes);
|
|
|
#if BYTES_PER_FRAME == 4
|
|
@@ -86,11 +89,16 @@ static void sink_data_handler(const uint8_t *data, uint32_t len)
|
|
|
len -= bytes;
|
|
|
data += bytes;
|
|
|
|
|
|
- UNLOCK_O;
|
|
|
-
|
|
|
// allow i2s to empty the buffer if needed
|
|
|
- if (len && !space && wait--) usleep(20000);
|
|
|
+ if (len && !space) {
|
|
|
+ wait--;
|
|
|
+ UNLOCK_O;
|
|
|
+ usleep(50000);
|
|
|
+ LOCK_O;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ UNLOCK_O;
|
|
|
|
|
|
if (!wait) {
|
|
|
LOG_WARN("Waited too long, dropping frames");
|
|
@@ -105,7 +113,7 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args)
|
|
|
{
|
|
|
// don't LOCK_O as there is always a chance that LMS takes control later anyway
|
|
|
if (output.external != DECODE_BT && output.state > OUTPUT_STOPPED) {
|
|
|
- LOG_WARN("Cannot use BT sink while LMS/AirPlay is controlling player");
|
|
|
+ LOG_WARN("Cannot use BT sink while LMS/AirPlay are controlling player");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -115,11 +123,11 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args)
|
|
|
|
|
|
switch(cmd) {
|
|
|
case BT_SINK_AUDIO_STARTED:
|
|
|
+ _buf_flush(outputbuf);
|
|
|
output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t);
|
|
|
output.external = DECODE_BT;
|
|
|
output.state = OUTPUT_STOPPED;
|
|
|
output.frames_played = 0;
|
|
|
- _buf_flush(outputbuf);
|
|
|
if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR;
|
|
|
LOG_INFO("BT sink started");
|
|
|
break;
|
|
@@ -132,17 +140,18 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args)
|
|
|
break;
|
|
|
case BT_SINK_PLAY:
|
|
|
output.state = OUTPUT_RUNNING;
|
|
|
- LOG_INFO("BT playing");
|
|
|
+ LOG_INFO("BT play");
|
|
|
break;
|
|
|
case BT_SINK_STOP:
|
|
|
_buf_flush(outputbuf);
|
|
|
output.state = OUTPUT_STOPPED;
|
|
|
output.stop_time = gettime_ms();
|
|
|
- LOG_INFO("BT stopped");
|
|
|
+ abort_sink = true;
|
|
|
+ LOG_INFO("BT stop");
|
|
|
break;
|
|
|
case BT_SINK_PAUSE:
|
|
|
output.stop_time = gettime_ms();
|
|
|
- LOG_INFO("BT paused, just silence");
|
|
|
+ LOG_INFO("BT pause, just silence");
|
|
|
break;
|
|
|
case BT_SINK_RATE:
|
|
|
output.next_sample_rate = output.current_sample_rate = va_arg(args, u32_t);
|
|
@@ -184,7 +193,7 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args)
|
|
|
{
|
|
|
// don't LOCK_O as there is always a chance that LMS takes control later anyway
|
|
|
if (output.external != DECODE_RAOP && output.state > OUTPUT_STOPPED) {
|
|
|
- LOG_WARN("Cannot use Airplay sink while LMS/BT is controlling player");
|
|
|
+ LOG_WARN("Cannot use Airplay sink while LMS/BT are controlling player");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -269,6 +278,7 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args)
|
|
|
raop_state = event;
|
|
|
_buf_flush(outputbuf);
|
|
|
if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED;
|
|
|
+ abort_sink = true;
|
|
|
output.frames_played = 0;
|
|
|
output.stop_time = gettime_ms();
|
|
|
break;
|