diff --git a/CMakeLists.txt b/CMakeLists.txt index 07b16aa1..4e5af2d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ add_definitions(-DHIERARCHICAL_STATES=1) #add_definitions(-DNETWORK_HANDLERS_LOG_LEVEL=ESP_LOG_DEBUG) #add_definitions(-DNETWORK_WIFI_LOG_LEVEL=ESP_LOG_DEBUG) #add_definitions(-DNETWORK_MANAGER_LOG_LEVEL=ESP_LOG_DEBUG) -add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG) +#add_definitions(-DNETWORK_HTTP_SERVER_LOG_LEVEL=ESP_LOG_DEBUG) if(NOT DEFINED DEPTH) set(DEPTH "16") diff --git a/components/raop/raop.c b/components/raop/raop.c index e419736d..05103a74 100644 --- a/components/raop/raop.c +++ b/components/raop/raop.c @@ -196,7 +196,8 @@ struct raop_ctx_s *raop_create(struct in_addr host, char *name, ESP_ERROR_CHECK( mdns_service_add(id, "_raop", "_tcp", ctx->port, txt, sizeof(txt) / sizeof(mdns_txt_item_t)) ); ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtsp_thread, "RTSP_thread", RTSP_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 2, ctx->xStack, ctx->xTaskBuffer); + ctx->thread = xTaskCreateStaticPinnedToCore( (TaskFunction_t) rtsp_thread, "RTSP_thread", RTSP_STACK_SIZE, ctx, + ESP_TASK_PRIO_MIN + 2, ctx->xStack, ctx->xTaskBuffer, CONFIG_PTHREAD_TASK_CORE_DEFAULT); #endif return ctx; @@ -518,7 +519,9 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) ctx->active_remote.running = true; ctx->active_remote.destroy_mutex = xSemaphoreCreateBinary(); ctx->active_remote.xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - ctx->active_remote.thread = xTaskCreateStatic( (TaskFunction_t) search_remote, "search_remote", SEARCH_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 2, ctx->active_remote.xStack, ctx->active_remote.xTaskBuffer); + ctx->active_remote.thread = xTaskCreateStaticPinnedToCore( (TaskFunction_t) search_remote, "search_remote", SEARCH_STACK_SIZE, ctx, + ESP_TASK_PRIO_MIN + 2, ctx->active_remote.xStack, ctx->active_remote.xTaskBuffer, + CONFIG_PTHREAD_TASK_CORE_DEFAULT ); #endif } else if (!strcmp(method, "SETUP") && ((buf = kd_lookup(headers, "Transport")) != NULL)) { diff --git a/components/raop/rtp.c b/components/raop/rtp.c index 11218483..2aead7f2 100644 --- a/components/raop/rtp.c +++ b/components/raop/rtp.c @@ -281,8 +281,9 @@ rtp_resp_t rtp_init(struct in_addr host, int latency, char *aeskey, char *aesiv, pthread_create(&ctx->thread, NULL, rtp_thread_func, (void *) ctx); #else ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx, - CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer ); + ctx->thread = xTaskCreateStaticPinnedToCore( (TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx, + CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer, + CONFIG_PTHREAD_TASK_CORE_DEFAULT ); #endif // cleanup everything if we failed diff --git a/components/raop/util.h b/components/raop/util.h index 94001895..75016521 100644 --- a/components/raop/util.h +++ b/components/raop/util.h @@ -57,7 +57,7 @@ char *strlwr(char *str); // reason is that TCB might be cleanup in idle task #define SAFE_PTR_FREE(P) \ do { \ - TimerHandle_t timer = xTimerCreate("cleanup", pdMS_TO_TICKS(5000), pdFALSE, P, _delayed_free); \ + TimerHandle_t timer = xTimerCreate("cleanup", pdMS_TO_TICKS(10000), pdFALSE, P, _delayed_free); \ xTimerStart(timer, portMAX_DELAY); \ } while (0) static void inline _delayed_free(TimerHandle_t xTimer) { diff --git a/components/spotify/Shim.cpp b/components/spotify/Shim.cpp index 64dcd3a2..bcb110cc 100644 --- a/components/spotify/Shim.cpp +++ b/components/spotify/Shim.cpp @@ -107,10 +107,7 @@ static void cspotTask(void *pvParameters) { ESP_LOGI(TAG, "Creating Spotify(CSpot) player"); // Auth successful - if (token.size() > 0) { - // tell sink that we are taking over - cspot.cHandler(CSPOT_SETUP, 44100); - + if (token.size() > 0 && cspot.cHandler(CSPOT_SETUP, 44100)) { auto audioSink = std::make_shared(); // @TODO Actually store this token somewhere @@ -137,7 +134,6 @@ static void cspotTask(void *pvParameters) { break; case CSpotEventType::DISC: cspot.cHandler(CSPOT_DISC); - spircController->stopPlayer(); mercuryManager->stop(); break; case CSpotEventType::PREV: @@ -163,11 +159,13 @@ static void cspotTask(void *pvParameters) { }; mercuryManager->handleQueue(); - } + + // release controllers + mercuryManager.reset(); + spircController.reset(); + } - // release all ownership - mercuryManager.reset(); - spircController.reset(); + // release auth blob cspot.blob.reset(); // flush files @@ -200,6 +198,9 @@ struct cspot_s* cspot_create(const char *name, cspot_cmd_cb_t cmd_cb, cspot_data * Commands sent by local buttons/actions */ bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) { + // we might have not controller left + if (!spircController.use_count()) return false; + switch(event) { case CSPOT_PREV: spircController->prevSong(); @@ -217,8 +218,7 @@ bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) { spircController->setPause(false); break; case CSPOT_DISC: - spircController->stopPlayer(); - mercuryManager->stop(); + spircController->disconnect(); break; case CSPOT_STOP: spircController->stopPlayer(); diff --git a/components/spotify/cspot/bell/include/HTTPStream.h b/components/spotify/cspot/bell/include/HTTPStream.h index 33a4f049..cb252f92 100644 --- a/components/spotify/cspot/bell/include/HTTPStream.h +++ b/components/spotify/cspot/bell/include/HTTPStream.h @@ -34,6 +34,7 @@ namespace bell bool hasFixedSize = false; + std::vector remainingData; size_t contentLength = -1; size_t currentPos = -1; diff --git a/components/spotify/cspot/bell/src/HTTPStream.cpp b/components/spotify/cspot/bell/src/HTTPStream.cpp index ebda808b..5a6fe223 100644 --- a/components/spotify/cspot/bell/src/HTTPStream.cpp +++ b/components/spotify/cspot/bell/src/HTTPStream.cpp @@ -175,7 +175,7 @@ size_t bell::HTTPStream::read(uint8_t *buf, size_t nbytes) if (nread < nbytes) { - return read(buf + nread, nbytes - nread); + return nread + read(buf + nread, nbytes - nread); } return nread; } diff --git a/components/spotify/cspot/include/SpircController.h b/components/spotify/cspot/include/SpircController.h index 16d2e37d..3d98681b 100644 --- a/components/spotify/cspot/include/SpircController.h +++ b/components/spotify/cspot/include/SpircController.h @@ -99,6 +99,11 @@ public: void nextSong(); void setEventHandler(cspotEventHandler handler); void stopPlayer(); + + /** + * @brief Disconnect players and notify + */ + void disconnect(); }; #endif diff --git a/components/spotify/cspot/src/ApResolve.cpp b/components/spotify/cspot/src/ApResolve.cpp index 33b47763..3282faa8 100644 --- a/components/spotify/cspot/src/ApResolve.cpp +++ b/components/spotify/cspot/src/ApResolve.cpp @@ -76,6 +76,8 @@ std::string ApResolve::getApList() jsonData += cur; } + close(sockFd); + return jsonData; } diff --git a/components/spotify/cspot/src/MercuryManager.cpp b/components/spotify/cspot/src/MercuryManager.cpp index df99140d..45c855aa 100644 --- a/components/spotify/cspot/src/MercuryManager.cpp +++ b/components/spotify/cspot/src/MercuryManager.cpp @@ -192,7 +192,6 @@ void MercuryManager::stop() { isRunning = false; audioChunkManager->close(); std::scoped_lock(audioChunkManager->runningMutex, this->runningMutex); - this->session->close(); CSPOT_LOG(debug, "mercury stopped"); } diff --git a/components/spotify/cspot/src/PlainConnection.cpp b/components/spotify/cspot/src/PlainConnection.cpp index 76be44a1..0aaba929 100644 --- a/components/spotify/cspot/src/PlainConnection.cpp +++ b/components/spotify/cspot/src/PlainConnection.cpp @@ -164,7 +164,8 @@ size_t PlainConnection::writeBlock(const std::vector &data) void PlainConnection::closeSocket() { - CSPOT_LOG(info, "Closing socket..."); - shutdown(this->apSock, SHUT_RDWR); - close(this->apSock); + CSPOT_LOG(info, "Closing socket..."); + shutdown(this->apSock, SHUT_RDWR); + close(this->apSock); + this->apSock = -1; } diff --git a/components/spotify/cspot/src/SpircController.cpp b/components/spotify/cspot/src/SpircController.cpp index ff07d8db..cf83979a 100644 --- a/components/spotify/cspot/src/SpircController.cpp +++ b/components/spotify/cspot/src/SpircController.cpp @@ -43,13 +43,20 @@ void SpircController::setPause(bool isPaused, bool notifyPlayer) { CSPOT_LOG(debug, "External pause command"); if (notifyPlayer) player->pause(); state->setPlaybackState(PlaybackState::Paused); - notify(); } else { CSPOT_LOG(debug, "External play command"); if (notifyPlayer) player->play(); state->setPlaybackState(PlaybackState::Playing); - notify(); } + notify(); +} + +void SpircController::disconnect(void) { + player->cancelCurrentTrack(); + stopPlayer(); + state->setActive(false); + notify(); + sendEvent(CSpotEventType::DISC); } void SpircController::playToggle() { @@ -104,10 +111,7 @@ void SpircController::handleFrame(std::vector &data) { // Pause the playback if another player took control if (state->isActive() && state->remoteFrame.device_state->is_active.value()) { - sendEvent(CSpotEventType::DISC); - state->setActive(false); - notify(); - player->cancelCurrentTrack(); + disconnect(); } break; } diff --git a/components/spotify/cspot_sink.c b/components/spotify/cspot_sink.c index 6a5b6c22..48d6bcc6 100644 --- a/components/spotify/cspot_sink.c +++ b/components/spotify/cspot_sink.c @@ -199,6 +199,6 @@ void cspot_sink_init(cspot_cmd_vcb_t cmd_cb, cspot_data_cb_t data_cb) { void cspot_disconnect(void) { ESP_LOGI(TAG, "forced disconnection"); displayer_control(DISPLAYER_SHUTDOWN); - cspot_cmd(cspot, CSPOT_FLUSH, NULL); + cspot_cmd(cspot, CSPOT_DISC, NULL); actrls_unset(); } diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index 75cd0069..1c7d1fcb 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -143,6 +143,7 @@ static bool bt_sink_cmd_handler(bt_sink_cmd_t cmd, va_list args) case BT_SINK_AUDIO_STOPPED: if (output.external == DECODE_BT) { if (output.state > OUTPUT_STOPPED) output.state = OUTPUT_STOPPED; + output.external = 0; output.stop_time = gettime_ms(); LOG_INFO("BT sink stopped"); } @@ -287,6 +288,8 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) output.next_sample_rate = output.current_sample_rate = RAOP_SAMPLE_RATE; break; case RAOP_STOP: + output.external = 0; + __attribute__ ((fallthrough)); case RAOP_FLUSH: LOG_INFO("%s", event == RAOP_FLUSH ? "Flush" : "Stop"); _buf_flush(outputbuf); @@ -355,6 +358,7 @@ static bool cspot_cmd_handler(cspot_event_t cmd, va_list args) case CSPOT_DISC: _buf_flush(outputbuf); abort_sink = true; + output.external = 0; output.state = OUTPUT_STOPPED; output.stop_time = gettime_ms(); LOG_INFO("CSpot disconnected"); diff --git a/components/squeezelite/displayer.c b/components/squeezelite/displayer.c index 8d29bb5c..bb50d610 100644 --- a/components/squeezelite/displayer.c +++ b/components/squeezelite/displayer.c @@ -361,7 +361,7 @@ bool sb_displayer_init(void) { // create displayer management task displayer.mutex = xSemaphoreCreateMutex(); - displayer.task = xTaskCreateStatic( (TaskFunction_t) displayer_task, "squeeze_displayer", SCROLL_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer); + displayer.task = xTaskCreateStatic( (TaskFunction_t) displayer_task, "sb_displayer", SCROLL_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer); // chain handlers slimp_handler_chain = slimp_handler; @@ -1315,6 +1315,7 @@ static void displayer_task(void *args) { // need to make sure we own display if (display && displayer.owned) GDS_Update(display); + else if (!led_display) displayer.wake = LONG_WAKE; // release semaphore and sleep what's needed xSemaphoreGive(displayer.mutex); diff --git a/components/squeezelite/slimproto.c b/components/squeezelite/slimproto.c index 2fb65d27..5b3f6fde 100644 --- a/components/squeezelite/slimproto.c +++ b/components/squeezelite/slimproto.c @@ -387,11 +387,14 @@ static void process_strm(u8_t *pkt, int len) { } sendSTAT("STMc", 0); sentSTMu = sentSTMo = sentSTMl = false; - LOCK_O; #if EMBEDDED + // not protected so that restore can call synchronously sink handlers if (output.external) decode_restore(output.external); + LOCK_O; output.external = 0; _buf_limit(outputbuf, 0); +#else + LOCK_O; #endif output.threshold = strm->output_threshold; output.next_replay_gain = unpackN(&strm->replay_gain); diff --git a/sdkconfig b/sdkconfig index 33eb957d..aaa52f80 100644 --- a/sdkconfig +++ b/sdkconfig @@ -277,31 +277,26 @@ CONFIG_ROTARY_ENCODER="" # # LED configuration # -CONFIG_LED_GREEN_GPIO=12 -CONFIG_LED_GREEN_GPIO_LEVEL=0 -CONFIG_LED_RED_GPIO=13 -CONFIG_LED_RED_GPIO_LEVEL=0 +CONFIG_LED_GREEN_GPIO=-1 +CONFIG_LED_RED_GPIO=-1 # end of LED configuration # # Audio JACK # -CONFIG_JACK_GPIO=34 -CONFIG_JACK_GPIO_LEVEL=0 +CONFIG_JACK_GPIO=-1 # end of Audio JACK # # Speaker Fault # -CONFIG_SPKFAULT_GPIO=2 -CONFIG_SPKFAULT_GPIO_LEVEL=0 +CONFIG_SPKFAULT_GPIO=-1 # end of Speaker Fault # # Battery measure # -CONFIG_BAT_CHANNEL=7 -CONFIG_BAT_SCALE="20.24" +CONFIG_BAT_CHANNEL=-1 # end of Battery measure CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30 -W"