From e8cbfde41a5c1c7426400e2fbbd393115e7e805f Mon Sep 17 00:00:00 2001 From: philippe44 Date: Tue, 28 Mar 2023 23:15:40 -0700 Subject: [PATCH] squeezelite cmdline error + cspot tweaks --- .../app_squeezelite/CMakeLists.txt | 2 +- .../app_squeezelite/cmd_squeezelite.c | 17 ++- components/platform_console/cmd_system.c | 20 --- components/spotify/Shim.cpp | 113 ++++++++++------ components/spotify/cspot_sink.h | 2 +- components/squeezelite-ota/squeezelite-ota.c | 2 - components/squeezelite/embedded.c | 9 +- components/squeezelite/embedded.h | 5 +- components/squeezelite/main.c | 7 +- components/squeezelite/output.c | 6 +- main/esp_app_main.c | 123 +----------------- 11 files changed, 109 insertions(+), 197 deletions(-) diff --git a/components/platform_console/app_squeezelite/CMakeLists.txt b/components/platform_console/app_squeezelite/CMakeLists.txt index f7f98b9f..9fdf664d 100644 --- a/components/platform_console/app_squeezelite/CMakeLists.txt +++ b/components/platform_console/app_squeezelite/CMakeLists.txt @@ -1,7 +1,7 @@ idf_build_get_property(idf_path IDF_PATH) idf_component_register( SRCS cmd_squeezelite.c INCLUDE_DIRS . - PRIV_REQUIRES spi_flash bootloader_support partition_table bootloader_support console codecs squeezelite newlib pthread tools platform_config display tools) + PRIV_REQUIRES spi_flash bootloader_support partition_table bootloader_support console codecs squeezelite newlib pthread tools platform_config display tools services) target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--undefined=feof") diff --git a/components/platform_console/app_squeezelite/cmd_squeezelite.c b/components/platform_console/app_squeezelite/cmd_squeezelite.c index 248c3ab2..cdfa8025 100644 --- a/components/platform_console/app_squeezelite/cmd_squeezelite.c +++ b/components/platform_console/app_squeezelite/cmd_squeezelite.c @@ -12,6 +12,7 @@ #include "platform_config.h" #include "esp_app_format.h" #include "tools.h" +#include "messaging.h" extern esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t length); static const char * TAG = "squeezelite_cmd"; @@ -61,7 +62,7 @@ static void squeezelite_thread(void *arg){ } ESP_LOGI(TAG ,"Calling squeezelite"); - main(thread_parms.argc,thread_parms.argv); + int ret = main(thread_parms.argc,thread_parms.argv); ESP_LOGV(TAG ,"Exited from squeezelite's main(). Freeing argv structure."); for(int i=0;icontent_len) { + char* body = (char*) calloc(1, request->content_len + 1); + int size = httpd_req_recv(request, body, request->content_len); - // get body if any (add '\0' at the end if used as string) - if (request->content_len) { - char* body = (char*) calloc(1, request->content_len + 1); - int size = httpd_req_recv(request, body, request->content_len); + // I know this is very crude and unsafe... + url_decode(body); + char *key = strtok(body, "&"); - // I know this is very crude and unsafe... - url_decode(body); - char *key = strtok(body, "&"); + std::map queryMap; - std::map queryMap; + while (key) { + char *value = strchr(key, '='); + *value++ = '\0'; + queryMap[key] = value; + key = strtok(NULL, "&"); + }; - while (key) { - char *value = strchr(key, '='); - *value++ = '\0'; - queryMap[key] = value; - key = strtok(NULL, "&"); - }; + free(body); - free(body); - - // Pass user's credentials to the blob and give the token - blob->loadZeroconfQuery(queryMap); - clientConnected.give(); + // Pass user's credentials to the blob and give the token + blob->loadZeroconfQuery(queryMap); + clientConnected.give(); + } + } else { + cJSON_AddNumberToObject(response, "status", 104); + cJSON_AddStringToObject(response, "statusString", "ERROR-NOT-IMPLEMENTED"); + cJSON_AddNumberToObject(response, "spotifyError", 501); + + httpd_resp_set_status(request, "501 Not Implemented"); + CSPOT_LOG(info, "sink is busy, can't accept request"); } char *responseStr = cJSON_PrintUnformatted(response); cJSON_Delete(response); - + + httpd_resp_set_hdr(request, "Content-type", "application/json"); esp_err_t rc = httpd_resp_send(request, responseStr, strlen(responseStr)); free(responseStr); @@ -224,7 +234,7 @@ void cspotPlayer::eventHandler(std::unique_ptr event spirc->setRemoteVolume(volume); cmdHandler(CSPOT_START, 44100); - CSPOT_LOG(info, "restart"); + CSPOT_LOG(info, "(re)start playing"); break; } case cspot::SpircHandler::EventType::PLAY_PAUSE: { @@ -288,22 +298,47 @@ void cspotPlayer::command(cspot_event_t event) { if (!spirc) return; // switch...case consume a ton of extra .rodata - if (event == CSPOT_PREV) spirc->previousSong(); - else if (event == CSPOT_NEXT) spirc->nextSong(); - else if (event == CSPOT_TOGGLE) spirc->setPause(!chunker->isPaused); - else if (event == CSPOT_STOP || event == CSPOT_PAUSE) spirc->setPause(true); - else if (event == CSPOT_PLAY) spirc->setPause(false); - else if (event == CSPOT_DISC) spirc->disconnect(); - else if (event == CSPOT_VOLUME_UP) { + switch (event) { + // nextSong/previousSong come back through cspot::event as a FLUSH + case CSPOT_PREV: + spirc->previousSong(); + break; + case CSPOT_NEXT: + spirc->nextSong(); + break; + // setPause comes back through cspot::event with PLAY/PAUSE + case CSPOT_TOGGLE: + spirc->setPause(!chunker->isPaused); + break; + case CSPOT_STOP: + case CSPOT_PAUSE: + spirc->setPause(true); + break; + case CSPOT_PLAY: + spirc->setPause(false); + break; + // calling spirc->disconnect() might have been logical but it does not + // generate any cspot::event, so we need to manually force exiting player + // loop through chunker which will eventually do the disconnect + case CSPOT_DISC: + cmdHandler(CSPOT_DISC); + chunker->teardown(); + break; + // spirc->setRemoteVolume does not generate a cspot::event so call cmdHandler + case CSPOT_VOLUME_UP: volume += (UINT16_MAX / 50); volume = std::min(volume, UINT16_MAX); cmdHandler(CSPOT_VOLUME, volume); spirc->setRemoteVolume(volume); - } else if (event == CSPOT_VOLUME_DOWN) { + break; + case CSPOT_VOLUME_DOWN: volume -= (UINT16_MAX / 50); volume = std::max(volume, 0); cmdHandler(CSPOT_VOLUME, volume); spirc->setRemoteVolume(volume); + break; + default: + break; } } @@ -371,10 +406,10 @@ void cspotPlayer::runTask() { }, [this](const uint8_t* data, size_t bytes) { return dataHandler(data, bytes); - }); - - // set volume at connection - cmdHandler(CSPOT_VOLUME, volume); + }); + + // set volume at connection + cmdHandler(CSPOT_VOLUME, volume); // exit when player has stopped (received a DISC) while (chunker->isRunning) { @@ -425,7 +460,6 @@ void cspotPlayer::runTask() { /**************************************************************************************** * API to create and start a cspot instance */ - struct cspot_s* cspot_create(const char *name, httpd_handle_t server, int port, cspot_cmd_cb_t cmd_cb, cspot_data_cb_t data_cb) { bell::setDefaultLogger(); player = new cspotPlayer(name, server, port, cmd_cb, data_cb); @@ -436,7 +470,6 @@ struct cspot_s* cspot_create(const char *name, httpd_handle_t server, int port, /**************************************************************************************** * Commands sent by local buttons/actions */ - bool cspot_cmd(struct cspot_s* ctx, cspot_event_t event, void *param) { player->command(event); return true; diff --git a/components/spotify/cspot_sink.h b/components/spotify/cspot_sink.h index 31cc529b..36ed4ce5 100644 --- a/components/spotify/cspot_sink.h +++ b/components/spotify/cspot_sink.h @@ -20,7 +20,7 @@ typedef enum { CSPOT_START, CSPOT_DISC, CSPOT_FLUSH, CSPOT_STOP, CSPOT_PLAY, CS CSPOT_NEXT, CSPOT_PREV, CSPOT_TOGGLE, CSPOT_TRACK_INFO, CSPOT_TRACK_MARK, CSPOT_VOLUME, CSPOT_VOLUME_UP, CSPOT_VOLUME_DOWN, - CSPOT_QUERY_STARTED, CSPOT_QUERY_REMAINING, + CSPOT_BUSY, CSPOT_QUERY_STARTED, CSPOT_QUERY_REMAINING, } cspot_event_t; typedef bool (*cspot_cmd_cb_t)(cspot_event_t event, ...); diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index 7f63d216..472b65a7 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -40,7 +40,6 @@ #include "globdefs.h" #include "tools.h" -extern const char * get_certificate(); #define IF_DISPLAY(x) if(display) { x; } #ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 @@ -349,7 +348,6 @@ esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){ } switch (ota_status->ota_type) { case OTA_TYPE_HTTP: - //http_client_config.cert_pem =get_certificate(); http_client_config.event_handler = _http_event_handler; http_client_config.disable_auto_redirect=false; http_client_config.skip_cert_common_name_check = false; diff --git a/components/squeezelite/embedded.c b/components/squeezelite/embedded.c index 720365aa..4d16afa5 100644 --- a/components/squeezelite/embedded.c +++ b/components/squeezelite/embedded.c @@ -8,6 +8,7 @@ * https://opensource.org/licenses/MIT * */ +#include #include "squeezelite.h" #include "pthread.h" #include "esp_pthread.h" @@ -18,6 +19,7 @@ #include "platform_config.h" mutex_type slimp_mutex; +static jmp_buf jumpbuf; void get_mac(u8_t mac[]) { esp_read_mac(mac, ESP_MAC_WIFI_STA); @@ -49,12 +51,17 @@ extern bool sb_displayer_init(void); u8_t custom_player_id = 12; -void embedded_init(void) { +int embedded_init(void) { mutex_create(slimp_mutex); sb_controls_init(); custom_player_id = sb_displayer_init() ? 100 : 101; + return setjmp(jumpbuf); } +void embedded_exit(int code) { + longjmp(jumpbuf, code + 1); +} + u16_t get_RSSI(void) { wifi_ap_record_t wifidata; esp_wifi_sta_get_ap_info(&wifidata); diff --git a/components/squeezelite/embedded.h b/components/squeezelite/embedded.h index 984cb6bc..2d3e38f8 100644 --- a/components/squeezelite/embedded.h +++ b/components/squeezelite/embedded.h @@ -52,7 +52,8 @@ extern u8_t custom_player_id; #define EXT_BSS __attribute__((section(".ext_ram.bss"))) // all exit() calls are made from main thread (or a function called in main thread) -#define exit(code) { int ret = code; pthread_exit(&ret); } +void embedded_exit(int code); +#define exit(code) do { embedded_exit(code); } while (0) #define gettime_ms _gettime_ms_ #define mutex_create_p(m) mutex_create(m) @@ -62,7 +63,7 @@ int pthread_create_name(pthread_t *thread, _CONST pthread_attr_t *attr, void *(*start_routine)( void * ), void *arg, char *name); // must provide of #define as empty macros -void embedded_init(void); +int embedded_init(void); void register_external(void); void deregister_external(void); void decode_restore(int external); diff --git a/components/squeezelite/main.c b/components/squeezelite/main.c index 464ded30..9e343d29 100644 --- a/components/squeezelite/main.c +++ b/components/squeezelite/main.c @@ -316,6 +316,11 @@ int main(int argc, char **argv) { #if IR char *lircrc = NULL; #endif + +#if EMBEDDED + int err = embedded_init(); + if (err) return err; +#endif log_level log_output = lWARN; log_level log_stream = lWARN; @@ -674,6 +679,7 @@ int main(int argc, char **argv) { case 't': license(); exit(0); + break; case '?': usage(argv[0]); exit(0); @@ -756,7 +762,6 @@ int main(int argc, char **argv) { stream_init(log_stream, stream_buf_size); #if EMBEDDED - embedded_init(); output_init_embedded(log_output, output_device, output_buf_size, output_params, rates, rate_delay, idle); #else if (!strcmp(output_device, "-")) { diff --git a/components/squeezelite/output.c b/components/squeezelite/output.c index 3cdb5fbc..8594f9ef 100644 --- a/components/squeezelite/output.c +++ b/components/squeezelite/output.c @@ -359,13 +359,13 @@ void output_init_common(log_level level, const char *device, unsigned output_buf buf_init(outputbuf, output_buf_size); if (!outputbuf->buf) { LOG_ERROR("unable to malloc output buffer"); - exit(0); + exit(2); } silencebuf = malloc(MAX_SILENCE_FRAMES * BYTES_PER_FRAME); if (!silencebuf) { LOG_ERROR("unable to malloc silence buffer"); - exit(0); + exit(2); } memset(silencebuf, 0, MAX_SILENCE_FRAMES * BYTES_PER_FRAME); @@ -373,7 +373,7 @@ void output_init_common(log_level level, const char *device, unsigned output_buf silencebuf_dsd = malloc(MAX_SILENCE_FRAMES * BYTES_PER_FRAME); if (!silencebuf_dsd) { LOG_ERROR("unable to malloc silence dsd buffer"); - exit(0); + exit(2); } dsd_silence_frames((u32_t *)silencebuf_dsd, MAX_SILENCE_FRAMES); ) diff --git a/main/esp_app_main.c b/main/esp_app_main.c index 5f4ec490..5f3e49bd 100644 --- a/main/esp_app_main.c +++ b/main/esp_app_main.c @@ -47,11 +47,6 @@ #include "cmd_system.h" #include "tools.h" -/* -static const char certs_namespace[] = "certificates"; -static const char certs_key[] = "blob"; -static const char certs_version[] = "version"; -*/ const char unknown_string_placeholder[] = "unknown"; const char null_string_placeholder[] = "null"; EventGroupHandle_t network_event_group; @@ -69,10 +64,6 @@ RTC_NOINIT_ATTR uint16_t ColdBootIndicatorFlag; bool cold_boot=true; static bool bNetworkConnected=false; -/* -extern const uint8_t server_cert_pem_start[] asm("_binary_github_pem_start"); -extern const uint8_t server_cert_pem_end[] asm("_binary_github_pem_end"); -*/ // as an exception _init function don't need include extern void services_init(void); @@ -158,123 +149,11 @@ esp_log_level_t get_log_level_from_char(char * level){ if(!strcasecmp(level, "VERBOSE" )) { return ESP_LOG_VERBOSE;} return ESP_LOG_WARN; } + void set_log_level(char * tag, char * level){ esp_log_level_set(tag, get_log_level_from_char(level)); } - -/* -esp_err_t update_certificates(bool force){ - nvs_handle handle; - esp_err_t esp_err; - esp_app_desc_t running_app_info; - - ESP_LOGI(TAG, "About to check if certificates need to be updated in flash"); - esp_err = nvs_open_from_partition(settings_partition, certs_namespace, NVS_READWRITE, &handle); - if (esp_err != ESP_OK) { - LOG_SEND(MESSAGING_INFO,"Unable to update HTTPS certificates. Could not open NVS namespace %s. Error %s", certs_namespace, esp_err_to_name(esp_err)); - return esp_err; - } - - const esp_partition_t *running = esp_ota_get_running_partition(); - ESP_LOGI(TAG, "Running partition [%s] type %d subtype %d (offset 0x%08x)", running->label, running->type, running->subtype, running->address); - - if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Running version: %s", running_app_info.version); - } - - size_t len=0; - char *str=NULL; - bool changed=false; - if ( (esp_err= nvs_get_str(handle, certs_version, NULL, &len)) == ESP_OK) { - str=(char *)malloc_init_external(len+1); - if(str){ - if ( (esp_err = nvs_get_str(handle, certs_version, str, &len)) == ESP_OK) { - ESP_LOGI(TAG,"Certificate version: %s", str); - } - } - } - if(str!=NULL && running->subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){ - // If certificates were found in nvs, only update if we're not - // running recovery. This will prevent rolling back to an older version - if(strcmp((char *)running_app_info.version,(char *)str )){ - // Versions are different - ESP_LOGW(TAG,"Found a different software version. Updating certificates"); - changed=true; - } - free(str); - } - else if(str==NULL){ - ESP_LOGW(TAG,"No certificate found. Adding certificates"); - changed=true; - } - - if(changed || force){ - - esp_err = nvs_set_blob(handle, certs_key, server_cert_pem_start, (server_cert_pem_end-server_cert_pem_start)); - if(esp_err!=ESP_OK){ - log_send_messaging(MESSAGING_ERROR,"Failed to store certificate data: %s", esp_err_to_name(esp_err)); - } - else { - esp_err = nvs_set_str(handle, certs_version, running_app_info.version); - if(esp_err!=ESP_OK){ - log_send_messaging(MESSAGING_ERROR,"Unable to update HTTPS Certificates version: %s",esp_err_to_name(esp_err)); - } - else { - esp_err = nvs_commit(handle); - if(esp_err!=ESP_OK){ - log_send_messaging(MESSAGING_ERROR,"Failed to commit certificates changes : %s",esp_err_to_name(esp_err)); - } - else { - log_send_messaging(MESSAGING_INFO,"HTTPS Certificates were updated with version: %s",running_app_info.version); - } - } - } - } - - nvs_close(handle); - return ESP_OK; -} -*/ - -/* -const char * get_certificate(){ - nvs_handle handle; - esp_err_t esp_err; - char *blob =NULL; -// - ESP_LOGD(TAG, "Fetching certificate."); - esp_err = nvs_open_from_partition(settings_partition, certs_namespace, NVS_READONLY, &handle); - if(esp_err == ESP_OK){ - size_t len; - esp_err = nvs_get_blob(handle, certs_key, NULL, &len); - if( esp_err == ESP_OK) { - blob = (char *) malloc_init_external(len+1); - if(!blob){ - log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. %s","Memory allocation failed"); - return ""; - } - memset(blob,0x00,len+1); - esp_err = nvs_get_blob(handle, certs_key, blob, &len); - if ( esp_err == ESP_OK) { - ESP_LOGD(TAG,"Certificates content is %d bytes long: ", len); - } - else { - log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. Get blob failed: %s", esp_err_to_name(esp_err)); - } - } - else{ - log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. Get blob failed: %s",esp_err_to_name(esp_err)); - } - nvs_close(handle); - } - else{ - log_send_messaging(MESSAGING_ERROR,"Unable to retrieve HTTPS certificates. NVS name space %s open failed: %s",certs_namespace, esp_err_to_name(esp_err)); - } - return blob; -} -*/ - #define DEFAULT_NAME_WITH_MAC(var,defval) char var[strlen(defval)+sizeof(macStr)]; strcpy(var,defval); strcat(var,macStr) void register_default_string_val(const char * key, char * value){ char * existing =(char *)config_alloc_get(NVS_TYPE_STR,key );