Bladeren bron

squeezelite cmdline error + cspot tweaks

philippe44 2 jaren geleden
bovenliggende
commit
e8cbfde41a

+ 1 - 1
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")

+ 14 - 5
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;i<thread_parms.argc;i++){
@@ -71,13 +72,21 @@ static void squeezelite_thread(void *arg){
 	ESP_LOGV(TAG ,"Freeing argv pointer");
 	free(thread_parms.argv);
 	
-	ESP_LOGE(TAG, "Exited from squeezelite thread, something's wrong ... rebooting (wait 30s for user to take action)");
 	if(!wait_for_commit()){
 		ESP_LOGW(TAG,"Unable to commit configuration. ");
 	}
-
-	vTaskDelay( pdMS_TO_TICKS( 30*1000 ) );
-    esp_restart();
+    
+    messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "squeezelite exited with error code %d", ret);   
+
+    if (ret == 1) {
+        int wait = 60;
+        messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Rebooting in %d sec", wait); 
+        vTaskDelay( pdMS_TO_TICKS(wait * 1000));
+        esp_restart();
+    } else {
+        messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Correct command line and reboot"); 
+        vTaskSuspend(NULL);
+    }
 }
 
 static int launchsqueezelite(int argc, char **argv) {

+ 0 - 20
components/platform_console/cmd_system.c

@@ -69,7 +69,6 @@ static void register_deep_sleep();
 static void register_light_sleep();
 static void register_factory_boot();
 static void register_restart_ota();
-//static void register_update_certs();
 static void register_set_services();
 #if WITH_TASKS_INFO
 static void register_tasks();
@@ -86,7 +85,6 @@ void register_system()
     register_restart();
     register_deep_sleep();
     register_light_sleep();
-    //register_update_certs();
     register_factory_boot();
     register_restart_ota();
 #if WITH_TASKS_INFO
@@ -562,24 +560,6 @@ static void register_tasks()
 
 #endif // WITH_TASKS_INFO
 
-/*
-extern esp_err_t update_certificates(bool force);
-static int force_update_cert(int argc, char **argv){
-	return update_certificates(true);
-}
-
-static void register_update_certs()
-{
-    const esp_console_cmd_t cmd = {
-        .command = "update_certificates",
-        .help = "Force updating the certificates from binary",
-        .hint = NULL,
-        .func = &force_update_cert,
-    };
-    ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
-}
-*/
-
 
 /** 'deep_sleep' command puts the chip into deep sleep mode */
 

+ 79 - 46
components/spotify/Shim.cpp

@@ -164,47 +164,57 @@ esp_err_t cspotPlayer::handleGET(httpd_req_t *request) {
     }
 
     httpd_resp_set_hdr(request, "Content-type", "application/json");
-    httpd_resp_set_hdr(request, "Content-length", std::to_string(body.size()).c_str());
     httpd_resp_send(request, body.c_str(), body.size());
 
     return ESP_OK;
 }
 
 esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) {
-   cJSON* response= cJSON_CreateObject();
-
-   cJSON_AddNumberToObject(response, "status", 101);
-   cJSON_AddStringToObject(response, "statusString", "ERROR-OK");
-   cJSON_AddNumberToObject(response, "spotifyError", 0);
-
-    // 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, "&");
-
-        std::map<std::string, std::string> queryMap;
-
-        while (key) {
-            char *value = strchr(key, '=');
-            *value++ = '\0';
-            queryMap[key] = value;
-            key = strtok(NULL, "&");
-        };
-
-        free(body);
-
-        // Pass user's credentials to the blob and give the token
-        blob->loadZeroconfQuery(queryMap);
-        clientConnected.give();
+    cJSON* response= cJSON_CreateObject();
+   
+    // try a command that will tell us if the sink is available */
+    if (cmdHandler(CSPOT_BUSY)) {
+        cJSON_AddNumberToObject(response, "status", 101);
+        cJSON_AddStringToObject(response, "statusString", "OK");
+        cJSON_AddNumberToObject(response, "spotifyError", 0);
+
+        // 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, "&");
+
+            std::map<std::string, std::string> queryMap;
+
+            while (key) {
+                char *value = strchr(key, '=');
+                *value++ = '\0';
+                queryMap[key] = value;
+                key = strtok(NULL, "&");
+            };
+
+            free(body);
+
+            // 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<cspot::SpircHandler::Event> 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;

+ 1 - 1
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, ...);				

+ 0 - 2
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;

+ 8 - 1
components/squeezelite/embedded.c

@@ -8,6 +8,7 @@
  *  https://opensource.org/licenses/MIT
  *
  */
+#include <setjmp.h>
 #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);

+ 3 - 2
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);

+ 6 - 1
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, "-")) {

+ 3 - 3
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);
 	)

+ 1 - 122
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 );