diff --git a/components/spotify/Shim.cpp b/components/spotify/Shim.cpp index 577143e3..07d05e8d 100644 --- a/components/spotify/Shim.cpp +++ b/components/spotify/Shim.cpp @@ -126,9 +126,12 @@ static void cspotTask(void *pvParameters) { case CSpotEventType::PLAY_PAUSE: { bool isPaused = std::get(event.data); if (isPaused) cspot.cHandler(CSPOT_PAUSE); - else cspot.cHandler(CSPOT_PLAY); + else cspot.cHandler(CSPOT_PLAY, false); break; } + case CSpotEventType::PLAYBACK_START: + cspot.cHandler(CSPOT_PLAY, (int) std::get(event.data)); + break; case CSpotEventType::LOAD: cspot.cHandler(CSPOT_LOAD, std::get(event.data), -1); break; @@ -347,7 +350,7 @@ void ShimHTTPServer::registerHandler(bell::RequestType requestType, const std::s .user_ctx = NULL, }; - // find athe first free spot and register handler + // find the first free spot and register handler for (int i = 0; i < sizeof(uriHandlers)/sizeof(bell::httpHandler); i++) { if (!uriHandlers[i]) { uriHandlers[i] = handler; diff --git a/components/spotify/cspot/include/Player.h b/components/spotify/cspot/include/Player.h index 2ad8a439..4cce75c4 100644 --- a/components/spotify/cspot/include/Player.h +++ b/components/spotify/cspot/include/Player.h @@ -32,19 +32,19 @@ public: std::function endOfFileCallback; int volume = 255; uint32_t logVolume; + bool needFlush = false; std::atomic isRunning = false; trackChangedCallback trackChanged; std::mutex runningMutex; void setVolume(uint32_t volume); - void handleLoad(std::shared_ptr track, std::function &trackLoadedCallback, uint32_t position_ms, bool isPaused); + void handleLoad(std::shared_ptr track, std::function &trackLoadedCallback, uint32_t position_ms, bool isPaused); void pause(); void cancelCurrentTrack(); void seekMs(size_t positionMs); void feedPCM(uint8_t *data, size_t len); void play(); void stop(); - }; #endif diff --git a/components/spotify/cspot/src/ChunkedAudioStream.cpp b/components/spotify/cspot/src/ChunkedAudioStream.cpp index 6185153f..9b83efa7 100644 --- a/components/spotify/cspot/src/ChunkedAudioStream.cpp +++ b/components/spotify/cspot/src/ChunkedAudioStream.cpp @@ -5,8 +5,13 @@ static size_t vorbisReadCb(void *ptr, size_t size, size_t nmemb, ChunkedAudioStream *self) { size_t readSize = 0; - while (readSize < nmemb * size && self->byteStream->position() < self->byteStream->size()) { - readSize += self->byteStream->read((uint8_t *) ptr + readSize, (size * nmemb) - readSize); + while (readSize < nmemb * size && self->byteStream->position() < self->byteStream->size() && self->isRunning) { + size_t bytes = self->byteStream->read((uint8_t *) ptr + readSize, (size * nmemb) - readSize); + if (bytes <= 0) { + CSPOT_LOG(info, "unexpected end/error of stream"); + return readSize; + } + readSize += bytes; } return readSize; } diff --git a/components/spotify/cspot/src/MercuryManager.cpp b/components/spotify/cspot/src/MercuryManager.cpp index c7daf05c..2805516b 100644 --- a/components/spotify/cspot/src/MercuryManager.cpp +++ b/components/spotify/cspot/src/MercuryManager.cpp @@ -115,7 +115,6 @@ std::shared_ptr MercuryManager::fetchAudioChunk(std::vector this->session->shanConn->sendPacket(static_cast(MercuryType::AUDIO_CHUNK_REQUEST_COMMAND), buffer); // Used for broken connection detection -CSPOT_LOG(info, "requesting Chunk %hu", this->audioChunkSequence - 1); this->lastRequestTimestamp = this->timeProvider->getSyncedTimestamp(); return this->audioChunkManager->registerNewChunk(this->audioChunkSequence - 1, audioKey, startPos, endPos); } diff --git a/components/spotify/cspot/src/Player.cpp b/components/spotify/cspot/src/Player.cpp index a863e78e..0c0d387a 100644 --- a/components/spotify/cspot/src/Player.cpp +++ b/components/spotify/cspot/src/Player.cpp @@ -114,7 +114,7 @@ void Player::runTask() } else { - usleep(10000); + usleep(20000); } } @@ -147,7 +147,7 @@ void Player::cancelCurrentTrack() } } -void Player::handleLoad(std::shared_ptr trackReference, std::function& trackLoadedCallback, uint32_t position_ms, bool isPaused) +void Player::handleLoad(std::shared_ptr trackReference, std::function& trackLoadedCallback, uint32_t position_ms, bool isPaused) { std::lock_guard guard(loadTrackMutex); @@ -166,7 +166,9 @@ void Player::handleLoad(std::shared_ptr trackReference, std::fun this->nextTrack->trackInfoReceived = this->trackChanged; this->nextTrack->loadedTrackCallback = [this, framesCallback, trackLoadedCallback]() { - trackLoadedCallback(); + bool needFlush = currentTrack != nullptr && currentTrack->audioStream != nullptr && currentTrack->audioStream->isRunning; + cancelCurrentTrack(); + trackLoadedCallback(needFlush); this->nextTrackMutex.lock(); this->nextTrack->audioStream->streamFinishedCallback = this->endOfFileCallback; @@ -175,7 +177,6 @@ void Player::handleLoad(std::shared_ptr trackReference, std::fun this->nextTrack->loaded = true; this->nextTrackMutex.unlock(); - cancelCurrentTrack(); }; this->nextTrackMutex.unlock(); } diff --git a/components/spotify/cspot/src/SpircController.cpp b/components/spotify/cspot/src/SpircController.cpp index f490048d..0e4d6e0e 100644 --- a/components/spotify/cspot/src/SpircController.cpp +++ b/components/spotify/cspot/src/SpircController.cpp @@ -190,10 +190,10 @@ void SpircController::handleFrame(std::vector &data) { void SpircController::loadTrack(uint32_t position_ms, bool isPaused) { sendEvent(CSpotEventType::LOAD, (int) position_ms); state->setPlaybackState(PlaybackState::Loading); - std::function loadedLambda = [=]() { + std::function loadedLambda = [=](bool needFlush) { // Loading finished, notify that playback started setPause(isPaused, false); - sendEvent(CSpotEventType::PLAYBACK_START); + sendEvent(CSpotEventType::PLAYBACK_START, needFlush); }; player->handleLoad(state->getCurrentTrack(), loadedLambda, position_ms, diff --git a/components/spotify/cspot/src/SpotifyTrack.cpp b/components/spotify/cspot/src/SpotifyTrack.cpp index 477a09ba..c46bac23 100644 --- a/components/spotify/cspot/src/SpotifyTrack.cpp +++ b/components/spotify/cspot/src/SpotifyTrack.cpp @@ -106,7 +106,7 @@ void SpotifyTrack::trackInformationCallback(std::unique_ptr res altIndex++; CSPOT_LOG(info, "Trying alternative %d", altIndex); - if(altIndex > trackInfo.alternative_count) { + if(altIndex >= trackInfo.alternative_count) { // no alternatives for song return; } diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index 6ef2c7a1..3a220b1a 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -47,7 +47,7 @@ static EXT_RAM_ATTR struct { } raop_sync; #endif -static bool abort_sink ; +static enum { SINK_RUNNING, SINK_ABORT, SINK_DISCARD } sink_state; #define LOCK_O mutex_lock(outputbuf->mutex) #define UNLOCK_O mutex_unlock(outputbuf->mutex) @@ -77,10 +77,10 @@ static void sink_data_handler(const uint8_t *data, uint32_t len) } LOCK_O; - abort_sink = false; + if (sink_state == SINK_ABORT) sink_state = SINK_RUNNING; // there will always be room at some point - while (len && wait && !abort_sink) { + while (len && wait && sink_state == SINK_RUNNING) { bytes = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / (BYTES_PER_FRAME / 4); bytes = min(len, bytes); #if BYTES_PER_FRAME == 4 @@ -95,7 +95,7 @@ static void sink_data_handler(const uint8_t *data, uint32_t len) #endif _buf_inc_writep(outputbuf, bytes * BYTES_PER_FRAME / 4); space = _buf_space(outputbuf); - + len -= bytes; data += bytes; @@ -156,7 +156,7 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) _buf_flush(outputbuf); output.state = OUTPUT_STOPPED; output.stop_time = gettime_ms(); - abort_sink = true; + sink_state = SINK_ABORT; LOG_INFO("BT stop"); break; case BT_SINK_PAUSE: @@ -295,7 +295,7 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) _buf_flush(outputbuf); raop_state = event; if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; - abort_sink = true; + sink_state = SINK_ABORT; output.frames_played = 0; output.stop_time = gettime_ms(); break; @@ -357,35 +357,42 @@ static bool cspot_cmd_handler(cspot_event_t cmd, va_list args) break; case CSPOT_DISC: _buf_flush(outputbuf); - abort_sink = true; + sink_state = SINK_ABORT; output.external = 0; output.state = OUTPUT_STOPPED; output.stop_time = gettime_ms(); LOG_INFO("CSpot disconnected"); break; case CSPOT_TRACK: - _buf_flush(outputbuf); - abort_sink = true; LOG_INFO("CSpot sink new track rate %d", output.next_sample_rate); break; - case CSPOT_PLAY: + case CSPOT_PLAY: { + int flush = va_arg(args, int); + if (flush) { + _buf_flush(outputbuf); + sink_state = SINK_ABORT; + } else { + sink_state = SINK_RUNNING; + } output.state = OUTPUT_RUNNING; LOG_INFO("CSpot play"); break; + } case CSPOT_SEEK: - //TODO: can it be merged with flush (shall we stop) _buf_flush(outputbuf); - abort_sink = true; + sink_state = SINK_ABORT; LOG_INFO("CSpot seek by %d", va_arg(args, int)); break; case CSPOT_FLUSH: _buf_flush(outputbuf); - abort_sink = true; - __attribute__ ((fallthrough)); + sink_state = SINK_DISCARD; + output.state = OUTPUT_STOPPED; + LOG_INFO("CSpot flush"); + break; case CSPOT_PAUSE: output.state = OUTPUT_STOPPED; output.stop_time = gettime_ms(); - LOG_INFO("CSpot pause/flush"); + LOG_INFO("CSpot pause"); break; case CSPOT_VOLUME: { u32_t volume = va_arg(args, u32_t); diff --git a/components/wifi-manager/network_manager.c b/components/wifi-manager/network_manager.c index 4f67c832..2127ca70 100644 --- a/components/wifi-manager/network_manager.c +++ b/components/wifi-manager/network_manager.c @@ -294,7 +294,7 @@ void network_start() { } static void event_logger(uint32_t state_machine, uint32_t state, uint32_t event) { - ESP_LOGI(TAG, "Handling network manager event state Id %d->[%s]", state, event_to_string(event)); + ESP_LOGD(TAG, "Handling network manager event state Id %d->[%s]", state, event_to_string(event)); } static const char * get_state_machine_result_string(state_machine_result_t result) { switch(result) {