From 0cc92a25977c850f3e4038aa4a3f90976d02ea23 Mon Sep 17 00:00:00 2001 From: Karl Osterseher Date: Mon, 27 Jan 2025 23:16:36 +0100 Subject: [PATCH] improve netbuf state machine and decoding snapcast protocol bugfix for server settings failing to decode set compiler flag "no-implicit-fallthrough" for main.c disable inlay hints in eclipse through .clangd Signed-off-by: Karl Osterseher --- .clangd | 1 + main/CMakeLists.txt | 2 + main/main.c | 459 ++++++++++++++++++++++++-------------------- 3 files changed, 249 insertions(+), 213 deletions(-) diff --git a/.clangd b/.clangd index 22e5ea0..d8031c4 100644 --- a/.clangd +++ b/.clangd @@ -1,3 +1,4 @@ CompileFlags: CompilationDatabase: build Remove: [-m*, -f*] +InlayHints: {Enabled: false} diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index c4d9741..3226936 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -3,3 +3,5 @@ idf_component_register(SRCS "main.c" PRIV_REQUIRES esp_timer esp_wifi nvs_flash wifi_interface audio_board audio_hal audio_sal net_functions opus flac ota_server ui_http_server improv_wifi eth_interface ) + +set_source_files_properties(main.c PROPERTIES COMPILE_FLAGS -Wno-implicit-fallthrough) diff --git a/main/main.c b/main/main.c index 7cf48ad..5fb9ad1 100644 --- a/main/main.c +++ b/main/main.c @@ -256,7 +256,7 @@ static FLAC__StreamDecoderReadStatus read_callback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) { snapcastSetting_t *scSet = (snapcastSetting_t *)client_data; - decoderData_t *flacData; + // decoderData_t *flacData; (void)scSet; @@ -458,7 +458,6 @@ static void http_get_task(void *pvParameters) { uint16_t remotePort = 0; int rc1 = ERR_OK, rc2 = ERR_OK; struct netbuf *firstNetBuf = NULL; - struct netbuf *newNetBuf = NULL; uint16_t len; uint64_t timeout = FAST_SYNC_LATENCY_BUF; char *codecString = NULL; @@ -690,8 +689,7 @@ static void http_get_task(void *pvParameters) { scSet.muted = true; uint64_t startTime, endTime; - int32_t remainderSize = 0; - size_t currentPos = 0; + // size_t currentPos = 0; size_t typedMsgCurrentPos = 0; uint32_t typedMsgLen = 0; uint32_t offset = 0; @@ -729,7 +727,7 @@ static void http_get_task(void *pvParameters) { // now parse the data netbuf_first(firstNetBuf); do { - currentPos = 0; + // currentPos = 0; rc1 = netbuf_data(firstNetBuf, (void **)&start, &len); if (rc1 == ERR_OK) { @@ -901,7 +899,7 @@ static void http_get_task(void *pvParameters) { break; } - currentPos++; + // currentPos++;++; len--; start++; @@ -918,12 +916,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 1: { @@ -931,12 +931,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 2: { @@ -944,12 +946,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 3: { @@ -961,12 +965,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 4: { @@ -974,12 +980,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 5: { @@ -987,12 +995,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 6: { @@ -1000,12 +1010,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 7: { @@ -1017,12 +1029,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 8: { @@ -1030,12 +1044,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 9: { @@ -1043,12 +1059,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 10: { @@ -1056,12 +1074,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 11: { @@ -1069,7 +1089,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; @@ -1097,7 +1117,9 @@ static void http_get_task(void *pvParameters) { wire_chnk.timestamp.usec); #endif - break; + if (len == 0) { + break; + } } case 12: { @@ -1134,7 +1156,6 @@ static void http_get_task(void *pvParameters) { } tmpData = 0; - remainderSize = 0; payloadDataShift = 3; payloadOffset = 0; } @@ -1195,7 +1216,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos += tmp_size; start += tmp_size; - currentPos += tmp_size; + // currentPos += tmp_size; len -= tmp_size; if (typedMsgCurrentPos >= base_message_rx.size) { @@ -1519,12 +1540,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 1: { @@ -1532,12 +1555,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 2: { @@ -1545,12 +1570,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 3: { @@ -1574,12 +1601,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 4: { @@ -1590,7 +1619,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos += typedMsgLen; start += typedMsgLen; - currentPos += typedMsgLen; + // currentPos += typedMsgLen; len -= typedMsgLen; } else { memcpy(&codecString[offset], start, typedMsgLen); @@ -1599,7 +1628,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos += len; start += len; - currentPos += len; + // currentPos += len; len -= len; } @@ -1635,7 +1664,9 @@ static void http_get_task(void *pvParameters) { internalState++; } - break; + if (len == 0) { + break; + } } case 5: { @@ -1643,12 +1674,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 6: { @@ -1656,12 +1689,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 7: { @@ -1669,12 +1704,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 8: { @@ -1694,12 +1731,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 9: { @@ -1710,7 +1749,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos += typedMsgLen; start += typedMsgLen; - currentPos += typedMsgLen; + // currentPos += typedMsgLen; len -= typedMsgLen; } else { memcpy(&codecPayload[offset], start, len); @@ -1719,7 +1758,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos += len; start += len; - currentPos += len; + // currentPos += len; len -= len; } @@ -1869,49 +1908,18 @@ static void http_get_task(void *pvParameters) { case SNAPCAST_MESSAGE_SERVER_SETTINGS: { switch (internalState) { case 0: { - while ((netbuf_len(firstNetBuf) - currentPos) < - base_message_rx.size) { - ESP_LOGI(TAG, "need more data"); + typedMsgLen = *start & 0xFF; - // we need more data to process - rc1 = netconn_recv(lwipNetconn, &newNetBuf); - if (rc1 != ERR_OK) { - ESP_LOGE(TAG, "rx error for need more data"); + typedMsgCurrentPos++; + start++; + // currentPos++; + len--; - if (rc1 == ERR_CONN) { - // netconn_close(lwipNetconn); - // closing later, see first - // netconn_recv() in the loop + internalState++; - break; - } - - if (newNetBuf != NULL) { - netbuf_delete(newNetBuf); - - newNetBuf = NULL; - } - - continue; - } - - netbuf_chain(firstNetBuf, newNetBuf); + if (len == 0) { + break; } - - if (rc1 == ERR_OK) { - typedMsgLen = *start & 0xFF; - - typedMsgCurrentPos++; - start++; - currentPos++; - len--; - - internalState++; - } else { - ESP_LOGE(TAG, "some error"); - } - - break; } case 1: { @@ -1919,12 +1927,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 2: { @@ -1932,144 +1942,153 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 3: { typedMsgLen |= (*start & 0xFF) << 24; - // ESP_LOGI(TAG, - // "server settings string is %d - // long", typedMsgLen); + // ESP_LOGI(TAG,"server settings string is %lu" + // " long", typedMsgLen); - typedMsgCurrentPos++; - start++; - currentPos++; - len--; - - internalState++; - - break; - } - - case 4: { // now get some memory for server settings - // string at this point there is still - // plenty of RAM available, so we use - // malloc and netbuf_copy() here + // string serverSettingsString = malloc(typedMsgLen + 1); - if (serverSettingsString == NULL) { ESP_LOGE(TAG, "couldn't get memory for " "server settings string"); - } else { - netbuf_copy_partial(firstNetBuf, serverSettingsString, - typedMsgLen, currentPos); - - serverSettingsString[typedMsgLen] = - 0; // NULL terminate string - - // ESP_LOGI - //(TAG, "got string: %s", tmp); - - result = server_settings_message_deserialize( - &server_settings_message, serverSettingsString); - if (result) { - ESP_LOGE(TAG, - "Failed to read server " - "settings: %d", - result); - } else { - // log mute state, buffer, latency - ESP_LOGI(TAG, "Buffer length: %ld", - server_settings_message.buffer_ms); - ESP_LOGI(TAG, "Latency: %ld", - server_settings_message.latency); - ESP_LOGI(TAG, "Mute: %d", - server_settings_message.muted); - ESP_LOGI(TAG, "Setting volume: %ld", - server_settings_message.volume); - } - - // Volume setting using ADF HAL - // abstraction - if (scSet.muted != server_settings_message.muted) { -#if SNAPCAST_USE_SOFT_VOL - if (server_settings_message.muted) { - dsp_processor_set_volome(0.0); - } else { - dsp_processor_set_volome( - (double)server_settings_message.volume / 100); - } -#endif - audio_hal_set_mute(board_handle->audio_hal, - server_settings_message.muted); - } - - if (scSet.volume != server_settings_message.volume) { -#if SNAPCAST_USE_SOFT_VOL - if (!server_settings_message.muted) { - dsp_processor_set_volome( - (double)server_settings_message.volume / 100); - } -#else - audio_hal_set_volume(board_handle->audio_hal, - server_settings_message.volume); -#endif - } - - scSet.cDacLat_ms = server_settings_message.latency; - scSet.buf_ms = server_settings_message.buffer_ms; - scSet.muted = server_settings_message.muted; - scSet.volume = server_settings_message.volume; - - if (player_send_snapcast_setting(&scSet) != pdPASS) { - ESP_LOGE(TAG, - "Failed to notify sync task. " - "Did you init player?"); - - return; - } - - free(serverSettingsString); - serverSettingsString = NULL; } + typedMsgCurrentPos++; + start++; + // currentPos++; + len--; + internalState++; - // fall through + + offset = 0; + + if (len == 0) { + break; + } } - case 5: { + case 4: { size_t tmpSize = base_message_rx.size - typedMsgCurrentPos; if (len > 0) { if (tmpSize < len) { + if (serverSettingsString) { + memcpy(&serverSettingsString[offset], start, + tmpSize); + } + offset += tmpSize; + start += tmpSize; - currentPos += tmpSize; // will be - // incremented by 1 - // later so -1 here + // currentPos += tmpSize; // will be + // incremented by 1 + // later so -1 here typedMsgCurrentPos += tmpSize; len -= tmpSize; } else { + if (serverSettingsString) { + memcpy(&serverSettingsString[offset], start, len); + } + offset += len; + start += len; - currentPos += len; // will be incremented - // by 1 later so -1 - // here + // currentPos += len; // will be incremented + // by 1 later so -1 + // here typedMsgCurrentPos += len; len = 0; } } if (typedMsgCurrentPos >= base_message_rx.size) { - // ESP_LOGI(TAG, - // "done server settings"); + if (serverSettingsString) { + // ESP_LOGI(TAG, "done server settings %lu/%lu", + // offset, + // typedMsgLen); + + // NULL terminate string + serverSettingsString[typedMsgLen] = 0; + + // ESP_LOGI(TAG, "got string: %s", + // serverSettingsString); + + result = server_settings_message_deserialize( + &server_settings_message, serverSettingsString); + if (result) { + ESP_LOGE(TAG, + "Failed to read server " + "settings: %d", + result); + } else { + // log mute state, buffer, latency + ESP_LOGI(TAG, "Buffer length: %ld", + server_settings_message.buffer_ms); + ESP_LOGI(TAG, "Latency: %ld", + server_settings_message.latency); + ESP_LOGI(TAG, "Mute: %d", + server_settings_message.muted); + ESP_LOGI(TAG, "Setting volume: %ld", + server_settings_message.volume); + } + + // Volume setting using ADF HAL + // abstraction + if (scSet.muted != server_settings_message.muted) { +#if SNAPCAST_USE_SOFT_VOL + if (server_settings_message.muted) { + dsp_processor_set_volome(0.0); + } else { + dsp_processor_set_volome( + (double)server_settings_message.volume / 100); + } +#endif + audio_hal_set_mute(board_handle->audio_hal, + server_settings_message.muted); + } + + if (scSet.volume != server_settings_message.volume) { +#if SNAPCAST_USE_SOFT_VOL + if (!server_settings_message.muted) { + dsp_processor_set_volome( + (double)server_settings_message.volume / 100); + } +#else + audio_hal_set_volume( + board_handle->audio_hal, + server_settings_message.volume); +#endif + } + + scSet.cDacLat_ms = server_settings_message.latency; + scSet.buf_ms = server_settings_message.buffer_ms; + scSet.muted = server_settings_message.muted; + scSet.volume = server_settings_message.volume; + + if (player_send_snapcast_setting(&scSet) != pdPASS) { + ESP_LOGE(TAG, + "Failed to notify sync task. " + "Did you init player?"); + + return; + } + + free(serverSettingsString); + serverSettingsString = NULL; + } state = BASE_MESSAGE_STATE; internalState = 0; @@ -2097,12 +2116,12 @@ static void http_get_task(void *pvParameters) { if (tmpSize < len) { start += tmpSize; - currentPos += tmpSize; + // currentPos += tmpSize; typedMsgCurrentPos += tmpSize; len -= tmpSize; } else { start += len; - currentPos += len; + // currentPos += len; typedMsgCurrentPos += len; len = 0; @@ -2131,12 +2150,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 1: { @@ -2144,12 +2165,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 2: { @@ -2157,12 +2180,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 3: { @@ -2170,12 +2195,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 4: { @@ -2183,12 +2210,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 5: { @@ -2196,12 +2225,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 6: { @@ -2209,12 +2240,14 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; internalState++; - break; + if (len == 0) { + break; + } } case 7: { @@ -2222,7 +2255,7 @@ static void http_get_task(void *pvParameters) { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; if (typedMsgCurrentPos >= base_message_rx.size) { // ESP_LOGI(TAG, "done time message"); @@ -2340,7 +2373,7 @@ static void http_get_task(void *pvParameters) { default: { typedMsgCurrentPos++; start++; - currentPos++; + // currentPos++; len--; if (typedMsgCurrentPos >= base_message_rx.size) {