소스 검색

refactor step 1 - BT

philippe44 5 년 전
부모
커밋
6c5ce6ba80

+ 1 - 0
.gitignore

@@ -65,3 +65,4 @@ libs/
 
 
 /cdump.cmd
 /cdump.cmd
 /_codecs
 /_codecs
+sdkconfig

+ 38 - 211
components/platform_esp32/platform_esp32.c → components/platform_esp32/bt_app_handler.c

@@ -1,54 +1,32 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <string.h>
 #include <string.h>
 #include <ctype.h>
 #include <ctype.h>
-#include "esp_log.h"
-#include "esp_system.h"
-#include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
+
+#include "esp_log.h"
 #include "esp_bt.h"
 #include "esp_bt.h"
 #include "esp_bt_device.h"
 #include "esp_bt_device.h"
 #include "esp_bt_main.h"
 #include "esp_bt_main.h"
 #include "esp_gap_bt_api.h"
 #include "esp_gap_bt_api.h"
 #include "esp_a2dp_api.h"
 #include "esp_a2dp_api.h"
-#include "esp_avrc_api.h"
 #include "esp_console.h"
 #include "esp_console.h"
 #include "esp_pthread.h"
 #include "esp_pthread.h"
 #include "esp_system.h"
 #include "esp_system.h"
 #include "esp_wifi.h"
 #include "esp_wifi.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/event_groups.h"
-#include "freertos/task.h"
 #include "freertos/timers.h"
 #include "freertos/timers.h"
-#include "nvs.h"
-#include "nvs_flash.h"
-#include "nvs_utilities.h"
-#include "pthread.h"
-#include "string.h"
-//#include "esp_event.h"
-#include "sys/socket.h"
-#include <signal.h>
-
-#include <signal.h>
-#include "platform_esp32.h"
-#include "../../main/squeezelite.h"
 #include "argtable3/argtable3.h"
 #include "argtable3/argtable3.h"
 
 
-#define STATS_REPORT_DELAY_MS 15000
+#include "bt_app_core.h"
+
+#include "platform_esp32.h"
+
 static const char * TAG = "platform";
 static const char * TAG = "platform";
-extern char * get_output_state_desc(output_state state);
-
-extern struct outputstate output;
-extern struct buffer *outputbuf;
-extern struct buffer *streambuf;
-extern uint8_t * btout;
-time_t disconnect_time=0;
-#define LOCK_S   pthread_mutex_lock(&(streambuf->mutex))
-#define UNLOCK_S pthread_mutex_unlock(&(streambuf->mutex))
-
-#define LOCK   pthread_mutex_lock(&(outputbuf->mutex))
-#define UNLOCK pthread_mutex_unlock(&(outputbuf->mutex))
+
+extern int32_t 	output_bt_data(uint8_t *data, int32_t len);
+extern void 	output_bt_tick(void);
+extern char*	output_state_str(void);
+extern bool		output_stopped(void);
+
 int64_t connecting_timeout = 0;
 int64_t connecting_timeout = 0;
 
 
 static const char *  art_a2dp_connected[]={"\n",
 static const char *  art_a2dp_connected[]={"\n",
@@ -76,34 +54,8 @@ static void bt_app_av_state_connecting(uint16_t event, void *param);
 #define A2DP_TIMER_INIT connecting_timeout = esp_timer_get_time() +(CONFIG_A2DP_CONNECT_TIMEOUT_MS * 1000)
 #define A2DP_TIMER_INIT connecting_timeout = esp_timer_get_time() +(CONFIG_A2DP_CONNECT_TIMEOUT_MS * 1000)
 #define IS_A2DP_TIMER_OVER esp_timer_get_time() >= connecting_timeout
 #define IS_A2DP_TIMER_OVER esp_timer_get_time() >= connecting_timeout
 
 
-#define FRAME_TO_BYTES(f) f*BYTES_PER_FRAME
-#define BYTES_TO_FRAME(b) b/BYTES_PER_FRAME
-
-
-#define RESET_ALL_MIN_MAX RESET_MIN_MAX(req); RESET_MIN_MAX(rec); RESET_MIN_MAX(bt);RESET_MIN_MAX(under); RESET_MIN_MAX_DURATION(stream_buf); RESET_MIN_MAX_DURATION(lock_out_time)
-
-DECLARE_MIN_MAX(stream_buf);
-DECLARE_MIN_MAX(req);
-DECLARE_MIN_MAX(rec);
-DECLARE_MIN_MAX(bt);
-DECLARE_MIN_MAX(under);
-DECLARE_MIN_MAX_DURATION(lock_out_time);
-
 static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param);
 static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param);
 
 
-void get_mac(u8_t mac[]) {
-    esp_read_mac(mac, ESP_MAC_WIFI_STA);
-}
-
-_sig_func_ptr signal(int sig, _sig_func_ptr func) {
-	return NULL;
-}
-
-void *audio_calloc(size_t nmemb, size_t size) {
-		return calloc(nmemb, size);
-}
-
-
 /* event for handler "bt_av_hdl_stack_up */
 /* event for handler "bt_av_hdl_stack_up */
 enum {
 enum {
     BT_APP_EVT_STACK_UP = 0,
     BT_APP_EVT_STACK_UP = 0,
@@ -181,16 +133,12 @@ static struct {
 void hal_bluetooth_init(const char * options)
 void hal_bluetooth_init(const char * options)
 {
 {
 	ESP_LOGD(TAG,"Initializing Bluetooth HAL");
 	ESP_LOGD(TAG,"Initializing Bluetooth HAL");
-	//CONFIG_A2DP_SINK_NAME
-	//CONFIG_A2DP_CONTROL_DELAY_MS
-	//CONFIG_A2DP_CONNECT_TIMEOUT_MS
 
 
 	squeezelite_args.sink_name = arg_str1("n", "name", "<sink name>", "the name of the bluetooth to connect to");
 	squeezelite_args.sink_name = arg_str1("n", "name", "<sink name>", "the name of the bluetooth to connect to");
 	squeezelite_args.control_delay = arg_int0("d", "delay", "<control delay>", "the delay between each pass at the A2DP control loop");
 	squeezelite_args.control_delay = arg_int0("d", "delay", "<control delay>", "the delay between each pass at the A2DP control loop");
 	squeezelite_args.connect_timeout_delay = arg_int0("t","timeout", "<timeout>", "the timeout duration for connecting to the A2DP sink");
 	squeezelite_args.connect_timeout_delay = arg_int0("t","timeout", "<timeout>", "the timeout duration for connecting to the A2DP sink");
 	squeezelite_args.end = arg_end(2);
 	squeezelite_args.end = arg_end(2);
 
 
-
 	ESP_LOGD(TAG,"Copying parameters");
 	ESP_LOGD(TAG,"Copying parameters");
 	char * opts = strdup(options);
 	char * opts = strdup(options);
 	char **argv = malloc(sizeof(char**)*15);
 	char **argv = malloc(sizeof(char**)*15);
@@ -280,42 +228,7 @@ void hal_bluetooth_init(const char * options)
 	esp_bt_gap_set_pin(pin_type, 0, pin_code);
 	esp_bt_gap_set_pin(pin_type, 0, pin_code);
 
 
 }
 }
-static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t len)
-{
-	int32_t avail_data=0,wanted_len=0, start_timer=0;
-
-	if (len < 0 || data == NULL ) {
-		return 0;
-	}
-	btout=data;
-
-	// This is how the BTC layer calculates the number of bytes to
-	// for us to send. (BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16) - availPcmBytes
-	wanted_len=len;
-	SET_MIN_MAX(len,req);
-	TIME_MEASUREMENT_START(start_timer);
-	LOCK;
-	output.device_frames = 0; // todo: check if this is the right way do to this.
-	output.updated = gettime_ms();
-	output.frames_played_dmp = output.frames_played;
-	SET_MIN_MAX_SIZED(_buf_used(outputbuf),bt,outputbuf->size);
-	do {
-		avail_data = _output_frames( wanted_len/BYTES_PER_FRAME )*BYTES_PER_FRAME; // Keep the transfer buffer full
-		wanted_len-=avail_data;
-	} while (wanted_len > 0 && avail_data != 0);
-	if(wanted_len>0)
-	{
-		SET_MIN_MAX(wanted_len, under);
-	}
 
 
-	UNLOCK;
-	SET_MIN_MAX(TIME_MEASUREMENT_GET(start_timer),lock_out_time);
-	SET_MIN_MAX((len-wanted_len), rec);
-	TIME_MEASUREMENT_START(start_timer);
-	output_bt_check_buffer();
-
-	return len-wanted_len;
-}
 static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
 static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
 {
 {
     bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL);
     bt_app_work_dispatch(bt_app_av_sm_hdlr, event, param, sizeof(esp_a2d_cb_param_t), NULL);
@@ -415,10 +328,10 @@ static void bt_app_av_sm_hdlr(uint16_t event, void *param)
 {
 {
     switch (s_a2d_state) {
     switch (s_a2d_state) {
     case APP_AV_STATE_DISCOVERING:
     case APP_AV_STATE_DISCOVERING:
-    	ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", APP_AV_STATE_DESC[s_a2d_state], event, get_output_state_desc(output.state));
+    	ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", APP_AV_STATE_DESC[s_a2d_state], event, output_state_str());
     	break;
     	break;
     case APP_AV_STATE_DISCOVERED:
     case APP_AV_STATE_DISCOVERED:
-    	ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", APP_AV_STATE_DESC[s_a2d_state], event, get_output_state_desc(output.state));
+    	ESP_LOGV(TAG,"state %s, evt 0x%x, output state: %s", APP_AV_STATE_DESC[s_a2d_state], event, output_state_str());
         break;
         break;
     case APP_AV_STATE_UNCONNECTED:
     case APP_AV_STATE_UNCONNECTED:
         bt_app_av_state_unconnected(event, param);
         bt_app_av_state_unconnected(event, param);
@@ -562,7 +475,6 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param)
     }
     }
 }
 }
 
 
-
 static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
 static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
 {
 {
 
 
@@ -579,7 +491,7 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
 
 
         /* initialize A2DP source */
         /* initialize A2DP source */
         esp_a2d_register_callback(&bt_app_a2d_cb);
         esp_a2d_register_callback(&bt_app_a2d_cb);
-        esp_a2d_source_register_data_callback(bt_app_a2d_data_cb);
+        esp_a2d_source_register_data_callback(&output_bt_data);
         esp_a2d_source_init();
         esp_a2d_source_init();
 
 
         /* set discoverable and connectable mode */
         /* set discoverable and connectable mode */
@@ -605,39 +517,15 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
     }
     }
 }
 }
 
 
-#ifdef BTAUDIO
-bool test_open(const char *device, unsigned rates[], bool userdef_rates) {
-
-//	running_test  = true;
-//	while(running_test)
-//	{
-//		// wait until BT playback has started
-//		// this will allow querying the sample rate
-//		usleep(100000);
-//	}
-
-	memset(rates, 0, MAX_SUPPORTED_SAMPLERATES * sizeof(unsigned));
-	if (!strcmp(device, "BT")) {
-		rates[0] = 44100;
-	} else {
-		unsigned _rates[] = { 96000, 88200, 48000, 44100, 32000, 0 };
-		memcpy(rates, _rates, sizeof(_rates));
-	}
-	return true;
-}
-#endif
 static void bt_app_av_media_proc(uint16_t event, void *param)
 static void bt_app_av_media_proc(uint16_t event, void *param)
 {
 {
     esp_a2d_cb_param_t *a2d = NULL;
     esp_a2d_cb_param_t *a2d = NULL;
-    LOCK;
-    output_state out_state=output.state;
-    UNLOCK;
     switch (s_media_state) {
     switch (s_media_state) {
     case APP_AV_MEDIA_STATE_IDLE: {
     case APP_AV_MEDIA_STATE_IDLE: {
     	if (event == BT_APP_HEART_BEAT_EVT) {
     	if (event == BT_APP_HEART_BEAT_EVT) {
-            if(out_state > OUTPUT_STOPPED)
+            if(!output_stopped())
             {
             {
-            	ESP_LOGI(TAG,"Output state is %s, Checking if A2DP is ready.", get_output_state_desc(out_state));
+            	ESP_LOGI(TAG,"Output state is %s, Checking if A2DP is ready.", output_state_str());
             	esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY);
             	esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_CHECK_SRC_RDY);
             }
             }
 
 
@@ -671,40 +559,12 @@ static void bt_app_av_media_proc(uint16_t event, void *param)
     }
     }
     case APP_AV_MEDIA_STATE_STARTED: {
     case APP_AV_MEDIA_STATE_STARTED: {
         if (event == BT_APP_HEART_BEAT_EVT) {
         if (event == BT_APP_HEART_BEAT_EVT) {
-        	if(out_state <= OUTPUT_STOPPED) {
-        		ESP_LOGI(TAG,"Output state is %s. Stopping a2dp media ...", get_output_state_desc(out_state));
+        	if(output_stopped()) {
+        		ESP_LOGI(TAG,"Output state is %s. Stopping a2dp media ...", output_state_str());
                 s_media_state = APP_AV_MEDIA_STATE_STOPPING;
                 s_media_state = APP_AV_MEDIA_STATE_STOPPING;
                 esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
                 esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
-            }
-        	else
-        	{
-        		LOCK_S;
-        		SET_MIN_MAX_SIZED(_buf_used(streambuf),stream_buf,streambuf->size);
-        		UNLOCK_S;
-        		static time_t lastTime=0;
-        		if (lastTime <= gettime_ms() )
-				{
-					lastTime = gettime_ms() + 15000;
-					ESP_LOGD(TAG, "Statistics over %u secs. " , STATS_REPORT_DELAY_MS/1000);
-					ESP_LOGD(TAG, "              +==========+==========+================+=====+================+");
-					ESP_LOGD(TAG, "              |      max |      min |        average | avg |          count |");
-					ESP_LOGD(TAG, "              |  (bytes) |  (bytes) |        (bytes) | pct |                |");
-					ESP_LOGD(TAG, "              +==========+==========+================+=====+================+");
-					ESP_LOGD(TAG,LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("stream avl",stream_buf));
-					ESP_LOGD(TAG,LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("output avl",bt));
-					ESP_LOGD(TAG,LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("requested",req));
-					ESP_LOGD(TAG,LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("received",rec));
-					ESP_LOGD(TAG,LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("underrun",under));
-					ESP_LOGD(TAG, "              +==========+==========+================+=====+================+");
-					ESP_LOGD(TAG,"\n");
-					ESP_LOGD(TAG,"              ==========+==========+===========+===========+  ");
-					ESP_LOGD(TAG,"              max (us)  | min (us) |   avg(us) |  count    |  ");
-					ESP_LOGD(TAG,"              ==========+==========+===========+===========+  ");
-					ESP_LOGD(TAG,LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("Out Buf Lock",lock_out_time));
-					ESP_LOGD(TAG,"              ==========+==========+===========+===========+");
-					RESET_ALL_MIN_MAX;
-				}
-
+            } else {
+				output_bt_tick();	
         	}
         	}
         }
         }
         break;
         break;
@@ -716,16 +576,7 @@ static void bt_app_av_media_proc(uint16_t event, void *param)
             if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_STOP &&
             if (a2d->media_ctrl_stat.cmd == ESP_A2D_MEDIA_CTRL_STOP &&
                     a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) {
                     a2d->media_ctrl_stat.status == ESP_A2D_MEDIA_CTRL_ACK_SUCCESS) {
                 ESP_LOGI(TAG,"a2dp media stopped successfully...");
                 ESP_LOGI(TAG,"a2dp media stopped successfully...");
-                //s_media_state = APP_AV_MEDIA_STATE_WAIT_DISCONNECT;
-              //  if(CONFIG_A2DP_DISCONNECT_MS==0){
-                	// we're not going to disconnect.
-                	s_media_state = APP_AV_MEDIA_STATE_IDLE;
-//                }
-//                else
-//                {
-//                	disconnect_time = gettime_ms()+CONFIG_A2DP_DISCONNECT_MS;
-//                	s_media_state = APP_AV_MEDIA_STATE_WAIT_DISCONNECT;
-//                }
+               	s_media_state = APP_AV_MEDIA_STATE_IDLE;
             } else {
             } else {
                 ESP_LOGI(TAG,"a2dp media stopping...");
                 ESP_LOGI(TAG,"a2dp media stopping...");
                 esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
                 esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
@@ -735,20 +586,15 @@ static void bt_app_av_media_proc(uint16_t event, void *param)
     }
     }
 
 
     case APP_AV_MEDIA_STATE_WAIT_DISCONNECT:{
     case APP_AV_MEDIA_STATE_WAIT_DISCONNECT:{
-    	if(gettime_ms()>disconnect_time){
-    		// we've reached timeout
-			esp_a2d_source_disconnect(s_peer_bda);
-			s_a2d_state = APP_AV_STATE_DISCONNECTING;
-    	}
+    	esp_a2d_source_disconnect(s_peer_bda);
+		s_a2d_state = APP_AV_STATE_DISCONNECTING;
+		ESP_LOGI(TAG,"a2dp disconnecting...");
     }
     }
     }
     }
 }
 }
 
 
 static void bt_app_av_state_unconnected(uint16_t event, void *param)
 static void bt_app_av_state_unconnected(uint16_t event, void *param)
 {
 {
-//	LOCK;
-//	output_state out_state= output.state;
-//	UNLOCK;
 	switch (event) {
 	switch (event) {
     case ESP_A2D_CONNECTION_STATE_EVT:
     case ESP_A2D_CONNECTION_STATE_EVT:
     	ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_CONNECTION_STATE_EVT));
     	ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_CONNECTION_STATE_EVT));
@@ -772,8 +618,6 @@ static void bt_app_av_state_unconnected(uint16_t event, void *param)
     	ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT));
     	ESP_LOG_DEBUG_EVENT(TAG,QUOTE(ESP_A2D_MEDIA_CTRL_ACK_EVT));
     	break;
     	break;
     case BT_APP_HEART_BEAT_EVT: {
     case BT_APP_HEART_BEAT_EVT: {
-       // uint8_t *p = s_peer_bda;
-       // ESP_LOGI(TAG,"BT_APP_HEART_BEAT_EVT a2dp connecting to peer: %02x:%02x:%02x:%02x:%02x:%02x",p[0], p[1], p[2], p[3], p[4], p[5]);
         switch (esp_bluedroid_get_status()) {
         switch (esp_bluedroid_get_status()) {
 		case ESP_BLUEDROID_STATUS_UNINITIALIZED:
 		case ESP_BLUEDROID_STATUS_UNINITIALIZED:
 			ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_UNINITIALIZED.");
 			ESP_LOGV(TAG,"BlueDroid Status is ESP_BLUEDROID_STATUS_UNINITIALIZED.");
@@ -787,21 +631,18 @@ static void bt_app_av_state_unconnected(uint16_t event, void *param)
 		default:
 		default:
 			break;
 			break;
 		}
 		}
-//        if(out_state > OUTPUT_STOPPED){
-        	// only attempt a connect when playback isn't stopped
-			for(uint8_t l=0;art_a2dp_connecting[l][0]!='\0';l++){
-				ESP_LOGI(TAG,"%s",art_a2dp_connecting[l]);
-			}
-			ESP_LOGI(TAG,"Device: %s", s_peer_bdname);
-			if(esp_a2d_source_connect(s_peer_bda)==ESP_OK) {
-				A2DP_TIMER_INIT;
-				s_a2d_state = APP_AV_STATE_CONNECTING;
-			}
-			else {
-				// there was an issue connecting... continue to discover
-				ESP_LOGE(TAG,"Attempt at connecting failed, restart at discover...");
-				esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
-	//		}
+		for(uint8_t l=0;art_a2dp_connecting[l][0]!='\0';l++){
+			ESP_LOGI(TAG,"%s",art_a2dp_connecting[l]);
+		}
+		ESP_LOGI(TAG,"Device: %s", s_peer_bdname);
+		if(esp_a2d_source_connect(s_peer_bda)==ESP_OK) {
+			A2DP_TIMER_INIT;
+			s_a2d_state = APP_AV_STATE_CONNECTING;
+		}
+		else {
+			// there was an issue connecting... continue to discover
+			ESP_LOGE(TAG,"Attempt at connecting failed, restart at discover...");
+			esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
         }
         }
         break;
         break;
     }
     }
@@ -928,18 +769,4 @@ static void bt_app_av_state_disconnecting(uint16_t event, void *param)
         ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
         ESP_LOGE(TAG,"%s unhandled evt %d", __func__, event);
         break;
         break;
     }
     }
-}
-const char *loc_logtime(void) {
-	static char buf[100];
-#if WIN
-	SYSTEMTIME lt;
-	GetLocalTime(&lt);
-	sprintf(buf, "[%02d:%02d:%02d.%03d]", lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
-#else
-	struct timeval tv;
-	gettimeofday(&tv, NULL);
-	strftime(buf, sizeof(buf), "[%T.", localtime(&tv.tv_sec));
-	sprintf(buf+strlen(buf), "%06ld]", (long)tv.tv_usec);
-#endif
-	return buf;
-}
+}

+ 1 - 0
components/platform_esp32/cmd_squeezelite.c

@@ -7,6 +7,7 @@
 
 
 #include "esp_log.h"
 #include "esp_log.h"
 #include "esp_console.h"
 #include "esp_console.h"
+#include "esp_pthread.h"
 #include "argtable3/argtable3.h"
 #include "argtable3/argtable3.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/event_groups.h"
 #include "freertos/event_groups.h"

+ 0 - 1
components/platform_esp32/component.mk

@@ -6,5 +6,4 @@
 # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
 # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
 # please read the SDK documents if you need to do this.
 # please read the SDK documents if you need to do this.
 #
 #
-CFLAGS += -Os -DPOSIX -DLINKALL -DLOOPBACK -DNO_FAAD -DEMBEDDED -DTREMOR_ONLY -DBYTES_PER_FRAME=4 	
 CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG
 CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG

+ 21 - 141
components/platform_esp32/esp_app_main.c

@@ -1,147 +1,27 @@
-/* Scan Example
-
-   This example code is in the Public Domain (or CC0 licensed, at your option.)
-
-   Unless required by applicable law or agreed to in writing, this
-   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-   CONDITIONS OF ANY KIND, either express or implied.
-*/
-
-/*
-    This example shows how to use the All Channel Scan or Fast Scan to connect
-    to a Wi-Fi network.
-
-    In the Fast Scan mode, the scan will stop as soon as the first network matching
-    the SSID is found. In this mode, an application can set threshold for the
-    authentication mode and the Signal strength. Networks that do not meet the
-    threshold requirements will be ignored.
-
-    In the All Channel Scan mode, the scan will end only after all the channels
-    are scanned, and connection will start with the best network. The networks
-    can be sorted based on Authentication Mode or Signal Strength. The priority
-    for the Authentication mode is:  WPA2 > WPA > WEP > Open
-*/
+/* 
+ *  Squeezelite for esp32
+ *
+ *  (c) Sebastien 2019
+ *      Philippe G. 2019, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+ 
 #include "platform_esp32.h"
 #include "platform_esp32.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include "esp_bt.h"
-#include "esp_bt_device.h"
-#include "esp_bt_main.h"
-#include "esp_gap_bt_api.h"
-#include "esp_a2dp_api.h"
-#include "esp_avrc_api.h"
-#include "esp_log.h"
-#include "esp_pthread.h"
-#include "esp_system.h"
-#include "esp_wifi.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/event_groups.h"
-#include "freertos/task.h"
-#include "freertos/timers.h"
-#include "nvs.h"
-#include "nvs_flash.h"
-#include "nvs_utilities.h"
-#include "pthread.h"
-#include "string.h"
-#include "sys/socket.h"
-#include <signal.h>
-#include "esp_system.h"
-#include <signal.h>
-
-/*Set the SSID and Password via "make menuconfig"*/
-#define DEFAULT_SSID CONFIG_WIFI_SSID
-#define DEFAULT_PWD CONFIG_WIFI_PASSWORD
-
-#if CONFIG_WIFI_ALL_CHANNEL_SCAN
-#define DEFAULT_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN
-#elif CONFIG_WIFI_FAST_SCAN
-#define DEFAULT_SCAN_METHOD WIFI_FAST_SCAN
-#else
-#define DEFAULT_SCAN_METHOD WIFI_FAST_SCAN
-#endif /*CONFIG_SCAN_METHOD*/
-
-#if CONFIG_WIFI_CONNECT_AP_BY_SIGNAL
-#define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
-#elif CONFIG_WIFI_CONNECT_AP_BY_SECURITY
-#define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY
-#else
-#define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
-#endif /*CONFIG_SORT_METHOD*/
-
-#if CONFIG_FAST_SCAN_THRESHOLD
-#define DEFAULT_RSSI CONFIG_FAST_SCAN_MINIMUM_SIGNAL
-#if CONFIG_EXAMPLE_OPEN
-#define DEFAULT_AUTHMODE WIFI_AUTH_OPEN
-#elif CONFIG_EXAMPLE_WEP
-#define DEFAULT_AUTHMODE WIFI_AUTH_WEP
-#elif CONFIG_EXAMPLE_WPA
-#define DEFAULT_AUTHMODE WIFI_AUTH_WPA_PSK
-#elif CONFIG_EXAMPLE_WPA2
-#define DEFAULT_AUTHMODE WIFI_AUTH_WPA2_PSK
-#else
-#define DEFAULT_AUTHMODE WIFI_AUTH_OPEN
-#endif
-#else
-#define DEFAULT_RSSI -127
-#define DEFAULT_AUTHMODE WIFI_AUTH_OPEN
-#endif /*CONFIG_FAST_SCAN_THRESHOLD*/
-extern char current_namespace[];
-static const char * TAG = "platform_esp32";
-
-
-
-//static void event_handler(void* arg, esp_event_base_t event_base,
-//                                int32_t event_id, void* event_data)
-//{
-//    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
-//        esp_wifi_connect();
-//    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
-//        esp_wifi_connect();
-//    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
-//        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
-//        ESP_LOGI(TAG, "got ip: %s.", ip4addr_ntoa(&event->ip_info.ip));
-//        ESP_LOGD(TAG,"Signaling wifi connected. Locking.\n");
-//    	pthread_mutex_lock(&wifi_connect_suspend_mutex);
-//    	ESP_LOGD(TAG,"Signaling wifi connected. Broadcasting.\n");
-//		pthread_cond_broadcast(&wifi_connect_suspend_cond);
-//		ESP_LOGD(TAG,"Signaling wifi connected. Unlocking.\n");
-//		pthread_mutex_unlock(&wifi_connect_suspend_mutex);
-//    }
-//}
-//
-///* Initialize Wi-Fi as sta and set scan method */
-//static void wifi_scan(void)
-//{
-//
-//    tcpip_adapter_init();
-//    ESP_ERROR_CHECK(esp_event_loop_create_default());
-//
-//    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-//    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
-//
-//    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
-//    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
-//
-//    wifi_config_t wifi_config = {
-//        .sta = {
-//            .ssid = DEFAULT_SSID,
-//            .password = DEFAULT_PWD,
-//            .scan_method = DEFAULT_SCAN_METHOD,
-//            .sort_method = DEFAULT_SORT_METHOD,
-//            .threshold.rssi = DEFAULT_RSSI,
-//            .threshold.authmode = DEFAULT_AUTHMODE,
-//        },
-//    };
-//    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
-//    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
-//    ESP_ERROR_CHECK(esp_wifi_start());
-//}
-
 
 
 void app_main()
 void app_main()
 {
 {
-
 	console_start();
 	console_start();
 }
 }

+ 23 - 3
components/platform_esp32/perf_trace.h

@@ -1,8 +1,28 @@
-
+/* 
+ *  Squeezelite for esp32
+ *
+ *  (c) Sebastien 2019
+ *      Philippe G. 2019, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+ 
 #pragma once
 #pragma once
-#include "time.h"
+
 #include "sys/time.h"
 #include "sys/time.h"
-#include "esp_system.h"
+
 #define PERF_MAX LONG_MAX
 #define PERF_MAX LONG_MAX
 #define MIN_MAX_VAL(x) x==PERF_MAX?0:x
 #define MIN_MAX_VAL(x) x==PERF_MAX?0:x
 #define CURR_SAMPLE_RATE output.current_sample_rate>0?output.current_sample_rate:1
 #define CURR_SAMPLE_RATE output.current_sample_rate>0?output.current_sample_rate:1

+ 28 - 77
components/platform_esp32/platform_esp32.h

@@ -1,93 +1,44 @@
+/* 
+ *  Squeezelite for esp32
+ *
+ *  (c) Sebastien 2019
+ *      Philippe G. 2019, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+ 
 #pragma once
 #pragma once
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
-#include "bt_app_core.h"
-#include "perf_trace.h"
+
 #include "esp_pthread.h"
 #include "esp_pthread.h"
+
 #ifndef QUOTE
 #ifndef QUOTE
 #define QUOTE(name) #name
 #define QUOTE(name) #name
-#define STR(macro)  QUOTE(macro)
 #endif
 #endif
+
+#define ESP_LOG_DEBUG_EVENT(tag,e) ESP_LOGD(tag,"evt: " e)
+
 extern void run_command(char * line);
 extern void run_command(char * line);
 extern bool wait_for_wifi();
 extern bool wait_for_wifi();
-
-//typedef struct {
-//	char opt_slimproto_logging[11];
-//	char opt_stream_logging[11];
-//	char opt_decode_logging[11];
-//	char opt_output_logging[11];
-//	char opt_player_name[11];
-//	char opt_output_rates[21];
-//	char opt_buffer[11];
-//} str_squeezelite_options ;
 extern void console_start();
 extern void console_start();
 extern pthread_cond_t wifi_connect_suspend_cond;
 extern pthread_cond_t wifi_connect_suspend_cond;
 extern pthread_t wifi_connect_suspend_mutex;
 extern pthread_t wifi_connect_suspend_mutex;
-//static const char * art_wifi[]={
-//		"\n",
-//		"o          `O ooOoOOo OOooOoO ooOoOOo\n",
-//		"O           o    O    o          O   \n",
-//		"o           O    o    O          o   \n",
-//		"O           O    O    oOooO      O   \n",
-//		"o     o     o    o    O          o   \n",
-//		"O     O     O    O    o          O   \n",
-//		"`o   O o   O'    O    o          O   \n",
-//		" `OoO' `OoO'  ooOOoOo O'      ooOOoOo\n",
-//		"\n",
-//		""
-//};
-//static const char * art_wifi_connecting[]={
-//		" .oOOOo.",
-//		".O     o                                        o               \n",
-//		"o                                           O                   \n",
-//		"o                                          oOo                  \n",
-//		"o         .oOo. 'OoOo. 'OoOo. .oOo. .oOo    o   O  'OoOo. .oOoO \n",
-//		"O         O   o  o   O  o   O OooO' O       O   o   o   O o   O \n",
-//		"`o     .o o   O  O   o  O   o O     o       o   O   O   o O   o \n",
-//		" `OoooO'  `OoO'  o   O  o   O `OoO' `OoO'   `oO o'  o   O `OoOo \n",
-//		"                                                              O \n",
-//		"                                                           OoO' \n",
-//		"\n",
-//		""
-//};
-//static const char * art_wifi_connected[]={
-//		" .oOOOo.                                                   o       oO\n",
-//		".O     o                                                  O        OO\n",
-//		"o                                           O             o        oO\n",
-//		"o                                          oOo            o        Oo\n",
-//		"o         .oOo. 'OoOo. 'OoOo. .oOo. .oOo    o   .oOo. .oOoO        oO\n",
-//		"O         O   o  o   O  o   O OooO' O       O   OooO' o   O          \n",
-//		"`o     .o o   O  O   o  O   o O     o       o   O     O   o        Oo\n",
-//		" `OoooO'  `OoO'  o   O  o   O `OoO' `OoO'   `oO `OoO' `OoO'o       oO\n",
-//		"\n",
-//		""
-//};
-#define ESP_LOG_DEBUG_EVENT(tag,e) ESP_LOGD(tag,"evt: " e)
-const char *loc_logtime(void);
-//#define MY_ESP_LOG
-#ifdef MY_ESP_LOG
-#ifdef ESP_LOGI
-#undef ESP_LOGI
-#define ESP_LOGI(tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO,    tag, "%s %d " format,loc_logtime(),  __LINE__, ##__VA_ARGS__)
-#endif
-#ifdef ESP_LOGE
-#undef ESP_LOGE
-#define ESP_LOGE(tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR,    tag, "%s %d " format,loc_logtime(),  __LINE__, ##__VA_ARGS__)
-#endif
-#ifdef ESP_LOGW
-#undef ESP_LOGW
-#define ESP_LOGW(tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN,    tag, "%s %d " format,loc_logtime(),  __LINE__, ##__VA_ARGS__)
-#endif
-#ifdef ESP_LOGD
-#undef ESP_LOGD
-#define ESP_LOGD(tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG,    tag, "%s %d " format,loc_logtime(),  __LINE__, ##__VA_ARGS__)
-#endif
-#ifdef ESP_LOGV
-#undef ESP_LOGV
-#define ESP_LOGV(tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, "%s %d " format,loc_logtime(),  __LINE__, ##__VA_ARGS__)
-#endif
-#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 1 - 8
main/Kconfig.projbuild

@@ -134,7 +134,7 @@ menu "Squeezelite-ESP32"
 		    
 		    
 		config OUTPUT_RATES
 		config OUTPUT_RATES
 			string "Output rates"
 			string "Output rates"
-			default "48000,44100"
+			default "44100"
 			help
 			help
 				<rates>[:<delay>]	Sample rates supported, allows output to be off when squeezelite is started; rates = <maxrate>|<minrate>-<maxrate>|<rate1>,<rate2>,<rate3>; delay = optional delay switching rates in ms
 				<rates>[:<delay>]	Sample rates supported, allows output to be off when squeezelite is started; rates = <maxrate>|<minrate>-<maxrate>|<rate1>,<rate2>,<rate3>; delay = optional delay switching rates in ms
 		menu "DAC I2S settings"  
 		menu "DAC I2S settings"  
@@ -196,13 +196,6 @@ menu "Squeezelite-ESP32"
 		        default 1000
 		        default 1000
 		        help
 		        help
 		            Increasing this value will give more chance for less stable connections to be established.	   
 		            Increasing this value will give more chance for less stable connections to be established.	   
-	        config A2DP_DISCONNECT_MS
-	        	int "Time in ms before disconnecting from A2DP audio sink. Set to 0 for no disconnect."
-	        	default 10000
-	        	help
-	        		Controls how long to wait before disconnecting from the A2DP audio sink after playback is stopped
-	        		Longer delay will ensure better responsiveness at the expense of locking the audio sink for a longer period. 
-	        		A shorter period may cause the player to disconnect between tracks change.
 		endmenu
 		endmenu
 	endmenu
 	endmenu
 
 

+ 2 - 2
main/component.mk

@@ -2,7 +2,7 @@
 # "main" pseudo-component makefile.
 # "main" pseudo-component makefile.
 #
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
-CFLAGS += -O3 -DPOSIX -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ONLY -DBYTES_PER_FRAME=4 	\
+CFLAGS += -O3 -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ONLY -DBYTES_PER_FRAME=4 	\
 	-I$(COMPONENT_PATH)/../components/codecs/inc			\
 	-I$(COMPONENT_PATH)/../components/codecs/inc			\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/mad 		\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/mad 		\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/alac		\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/alac		\
@@ -10,7 +10,7 @@ CFLAGS += -O3 -DPOSIX -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DT
 	-I$(COMPONENT_PATH)/../components/codecs/inc/vorbis 	\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/vorbis 	\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/soxr 		\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/soxr 		\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/resample16	\
 	-I$(COMPONENT_PATH)/../components/codecs/inc/resample16	\
-	-I$(COMPONENT_PATH)/../components/platform_esp32 
+	-I$(COMPONENT_PATH)/../components/platform_esp32
 	
 	
 LDFLAGS += -s
 LDFLAGS += -s
 
 

+ 5 - 2
main/decode.c

@@ -199,8 +199,8 @@ void decode_init(log_level level, const char *include_codecs, const char *exclud
 	LOG_DEBUG("include codecs: %s exclude codecs: %s", include_codecs ? include_codecs : "", exclude_codecs);
 	LOG_DEBUG("include codecs: %s exclude codecs: %s", include_codecs ? include_codecs : "", exclude_codecs);
 
 
 	mutex_create(decode.mutex);
 	mutex_create(decode.mutex);
-	PTHREAD_SET_NAME("decode");
-#if LINUX || OSX || FREEBSD || POSIX
+
+#if LINUX || OSX || FREEBSD || EMBEDDED
 	pthread_attr_t attr;
 	pthread_attr_t attr;
 	pthread_attr_init(&attr);
 	pthread_attr_init(&attr);
 #ifdef PTHREAD_STACK_MIN
 #ifdef PTHREAD_STACK_MIN
@@ -208,6 +208,9 @@ void decode_init(log_level level, const char *include_codecs, const char *exclud
 #endif
 #endif
 	pthread_create(&thread, &attr, decode_thread, NULL);
 	pthread_create(&thread, &attr, decode_thread, NULL);
 	pthread_attr_destroy(&attr);
 	pthread_attr_destroy(&attr);
+#if HAS_PTHREAD_SETNAME_NP	
+	pthread_setname_np(thread, "decode");
+#endif
 #endif
 #endif
 #if WIN
 #if WIN
 	thread = CreateThread(NULL, DECODE_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&decode_thread, NULL, 0, NULL);
 	thread = CreateThread(NULL, DECODE_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&decode_thread, NULL, 0, NULL);

+ 44 - 0
main/embedded.c

@@ -0,0 +1,44 @@
+/* 
+ *  Squeezelite for esp32
+ *
+ *  (c) Sebastien 2019
+ *      Philippe G. 2019, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "squeezelite.h"
+#include "esp_pthread.h"
+#include "esp_system.h"
+
+void get_mac(u8_t mac[]) {
+    esp_read_mac(mac, ESP_MAC_WIFI_STA);
+}
+
+_sig_func_ptr signal(int sig, _sig_func_ptr func) {
+	return NULL;
+}
+
+void *audio_calloc(size_t nmemb, size_t size) {
+		return calloc(nmemb, size);
+}
+
+int pthread_setname_np(pthread_t thread, const char *name) { 
+	esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); 
+	cfg.thread_name= name; 
+	cfg.inherit_cfg = true; 
+	return esp_pthread_set_cfg(&cfg); 
+}
+
+

+ 21 - 5
main/embedded.h

@@ -1,6 +1,22 @@
-#pragma once
-#if defined(ESP_PLATFORM)
-#include "sdkconfig.h"
-#include "esp_pthread.h"
-#define PTHREAD_SET_NAME(n) 	{ esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); cfg.thread_name= n; cfg.inherit_cfg = true; esp_pthread_set_cfg(&cfg); }
+#ifndef EMBEDDED_H
+#define EMBEDDED_H
+
+#include <inttypes.h>
+
+#define HAS_MUTEX_CREATE_P		0
+#define HAS_PTHREAD_SETNAME_NP	1
+
+#ifndef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN	256
 #endif
 #endif
+
+typedef int16_t   s16_t;
+typedef int32_t   s32_t;
+typedef int64_t   s64_t;
+typedef unsigned long long u64_t;
+
+#define exit(code) { int ret = code; pthread_exit(&ret); }
+
+int pthread_setname_np(pthread_t thread, const char *name);
+
+#endif // EMBEDDED_H

+ 17 - 21
main/main.c

@@ -169,6 +169,9 @@ static void usage(const char *argv0) {
 		   "18"
 		   "18"
 #endif
 #endif
 #endif
 #endif
+#if EMBEDDED
+			" EMBEDDED"
+#endif	
 #if EVENTFD
 #if EVENTFD
 		   " EVENTFD"
 		   " EVENTFD"
 #endif
 #endif
@@ -381,7 +384,7 @@ int main(int argc, char **argv) {
 		} else {
 		} else {
 			fprintf(stderr, "\nOption error: -%s\n\n", opt);
 			fprintf(stderr, "\nOption error: -%s\n\n", opt);
 			usage(argv[0]);
 			usage(argv[0]);
-			local_exit(1);
+			exit(1);
 		}
 		}
 
 
 		switch (opt[0]) {
 		switch (opt[0]) {
@@ -432,7 +435,7 @@ int main(int argc, char **argv) {
 				} else {
 				} else {
 					fprintf(stderr, "\nDebug settings error: -d %s\n\n", optarg);
 					fprintf(stderr, "\nDebug settings error: -d %s\n\n", optarg);
 					usage(argv[0]);
 					usage(argv[0]);
-					local_exit(1);
+					exit(1);
 				}
 				}
 			}
 			}
 			break;
 			break;
@@ -532,7 +535,7 @@ int main(int argc, char **argv) {
 			pidfile = optarg;
 			pidfile = optarg;
 			break;
 			break;
 #endif
 #endif
-#if !CONFIG_DACAUDIO && !CONFIG_BTAUDIO
+#ifndef EMBEDDED
 		case 'l':
 		case 'l':
 			list_devices();
 			list_devices();
 			exit(0);
 			exit(0);
@@ -675,12 +678,11 @@ int main(int argc, char **argv) {
 #endif
 #endif
 		case 't':
 		case 't':
 			license();
 			license();
-			local_exit(0);
-			break; // mute compiler warning
+			exit(0);
 		case '?':
 		case '?':
 			usage(argv[0]);
 			usage(argv[0]);
-			local_exit(0);
-			break; // mute compiler warning
+			exit(0);
+			break;
 		default:
 		default:
 			fprintf(stderr, "Arg error: %s\n", argv[optind]);
 			fprintf(stderr, "Arg error: %s\n", argv[optind]);
 			break;
 			break;
@@ -691,7 +693,7 @@ int main(int argc, char **argv) {
 	if (optind < argc) {
 	if (optind < argc) {
 		fprintf(stderr, "\nError: command line argument error\n\n");
 		fprintf(stderr, "\nError: command line argument error\n\n");
 		usage(argv[0]);
 		usage(argv[0]);
-		local_exit(1);
+		exit(1);
 	}
 	}
 
 
 	signal(SIGINT, sighandler);
 	signal(SIGINT, sighandler);
@@ -757,13 +759,9 @@ int main(int argc, char **argv) {
 #endif
 #endif
 
 
 	stream_init(log_stream, stream_buf_size);
 	stream_init(log_stream, stream_buf_size);
-#ifdef EMBEDDED
-if(strstr(output_device,"BT")!=NULL || strstr(output_device,"bt")!=NULL) {
-	output_init_bt(log_output, output_device, output_buf_size, output_params, rates, rate_delay, idle);
-}
-else if(strstr(output_device,"DAC")!=NULL || strstr(output_device,"dac")!=NULL){
-	output_init_dac(log_output, output_device, output_buf_size, output_params, rates, rate_delay, idle);
-}
+
+#if EMBEDDED
+	output_init_embedded(log_output, output_device, output_buf_size, output_params, rates, rate_delay, idle);
 #else
 #else
 	if (!strcmp(output_device, "-")) {
 	if (!strcmp(output_device, "-")) {
 		output_init_stdout(log_output, output_buf_size, output_params, rates, rate_delay);
 		output_init_stdout(log_output, output_buf_size, output_params, rates, rate_delay);
@@ -804,7 +802,7 @@ else if(strstr(output_device,"DAC")!=NULL || strstr(output_device,"dac")!=NULL){
 
 
 	if (name && namefile) {
 	if (name && namefile) {
 		fprintf(stderr, "-n and -N option should not be used at same time\n");
 		fprintf(stderr, "-n and -N option should not be used at same time\n");
-		local_exit(1);
+		exit(1);
 	}
 	}
 
 
 	slimproto(log_slimproto, server, mac, name, namefile, modelname, maxSampleRate);
 	slimproto(log_slimproto, server, mac, name, namefile, modelname, maxSampleRate);
@@ -812,10 +810,8 @@ else if(strstr(output_device,"DAC")!=NULL || strstr(output_device,"dac")!=NULL){
 	decode_close();
 	decode_close();
 	stream_close();
 	stream_close();
 
 
-#if CONFIG_DACAUDIO
-	output_close_dac();	
-#elif CONFIG_BTAUDIO
-	output_close_bt();
+#if EMBEDDED
+	output_close_embedded();	
 #else
 #else
 	if (!strcmp(output_device, "-")) {
 	if (!strcmp(output_device, "-")) {
 		output_close_stdout();
 		output_close_stdout();
@@ -848,5 +844,5 @@ else if(strstr(output_device,"DAC")!=NULL || strstr(output_device,"dac")!=NULL){
 	free_ssl_symbols();
 	free_ssl_symbols();
 #endif	
 #endif	
 
 
-	local_exit(0);
+	exit(0);
 }
 }

+ 3 - 3
main/output.c

@@ -352,13 +352,13 @@ void output_init_common(log_level level, const char *device, unsigned output_buf
 	buf_init(outputbuf, output_buf_size);
 	buf_init(outputbuf, output_buf_size);
 	if (!outputbuf->buf) {
 	if (!outputbuf->buf) {
 		LOG_ERROR("unable to malloc output buffer");
 		LOG_ERROR("unable to malloc output buffer");
-		local_exit(0);
+		exit(0);
 	}
 	}
 
 
 	silencebuf = malloc(MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
 	silencebuf = malloc(MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
 	if (!silencebuf) {
 	if (!silencebuf) {
 		LOG_ERROR("unable to malloc silence buffer");
 		LOG_ERROR("unable to malloc silence buffer");
-		local_exit(0);
+		exit(0);
 	}
 	}
 	memset(silencebuf, 0, MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
 	memset(silencebuf, 0, MAX_SILENCE_FRAMES * BYTES_PER_FRAME);
 
 
@@ -389,7 +389,7 @@ void output_init_common(log_level level, const char *device, unsigned output_buf
 	else {
 	else {
 		if (!test_open(output.device, output.supported_rates, user_rates)) {
 		if (!test_open(output.device, output.supported_rates, user_rates)) {
 			LOG_ERROR("unable to open output device: %s", output.device);
 			LOG_ERROR("unable to open output device: %s", output.device);
-			local_exit(0);
+			exit(0);
 		}
 		}
 	}
 	}
 
 

+ 91 - 317
main/output_bt.c

@@ -1,352 +1,59 @@
 #include "squeezelite.h"
 #include "squeezelite.h"
 #include "perf_trace.h"
 #include "perf_trace.h"
 
 
-static log_level loglevel;
-
-static bool running = true;
-
 extern struct outputstate output;
 extern struct outputstate output;
 extern struct buffer *outputbuf;
 extern struct buffer *outputbuf;
 extern struct buffer *streambuf;
 extern struct buffer *streambuf;
-
+extern u8_t *silencebuf;
 
 
 #define LOCK   mutex_lock(outputbuf->mutex)
 #define LOCK   mutex_lock(outputbuf->mutex)
 #define UNLOCK mutex_unlock(outputbuf->mutex)
 #define UNLOCK mutex_unlock(outputbuf->mutex)
-
-#ifdef USE_BT_RING_BUFFER
-size_t bt_buffer_size=0;
-uint8_t bt_buf_used_threshold = 25;
-uint16_t output_bt_thread_heartbeat_ms=1000;
-thread_type thread_bt;
-#define LOCK_BT   mutex_lock(btbuf->mutex)
-#define UNLOCK_BT mutex_unlock(btbuf->mutex)
-thread_cond_type output_bt_suspend_cond;
-mutex_type output_bt_suspend_mutex;
-static struct buffer bt_buf_structure;
-struct buffer *btbuf=&bt_buf_structure;
-static void *output_thread_bt();
-extern void wait_for_frames(size_t frames, uint8_t pct);
-#else
-uint8_t * btout;
-#endif
+#define LOCK_S   mutex_lock(streambuf->mutex)
+#define UNLOCK_S mutex_unlock(streambuf->mutex)
 
 
 #define FRAME_BLOCK MAX_SILENCE_FRAMES
 #define FRAME_BLOCK MAX_SILENCE_FRAMES
-extern u8_t *silencebuf;
+
+#define STATS_REPORT_DELAY_MS 15000
 
 
 extern void hal_bluetooth_init(const char * options);
 extern void hal_bluetooth_init(const char * options);
 
 
+static log_level loglevel;
+uint8_t * btout;
+
 static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
 static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
 								s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
 								s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
+								
 #define DECLARE_ALL_MIN_MAX \
 #define DECLARE_ALL_MIN_MAX \
 	DECLARE_MIN_MAX(req);\
 	DECLARE_MIN_MAX(req);\
 	DECLARE_MIN_MAX(rec);\
 	DECLARE_MIN_MAX(rec);\
-	DECLARE_MIN_MAX(o);\
-	DECLARE_MIN_MAX(s);\
-	DECLARE_MIN_MAX(locbtbuff);\
+	DECLARE_MIN_MAX(bt);\
 	DECLARE_MIN_MAX(under);\
 	DECLARE_MIN_MAX(under);\
-	DECLARE_MIN_MAX_DURATION(mutex1);\
-	DECLARE_MIN_MAX_DURATION(mutex2);\
-	DECLARE_MIN_MAX_DURATION(buffering);\
-	DECLARE_MIN_MAX_DURATION(sleep_time);
+	DECLARE_MIN_MAX(stream_buf);\
+	DECLARE_MIN_MAX_DURATION(lock_out_time)								
+	
 #define RESET_ALL_MIN_MAX \
 #define RESET_ALL_MIN_MAX \
-	RESET_MIN_MAX(o); \
-	RESET_MIN_MAX(s); \
-	RESET_MIN_MAX(locbtbuff); \
+	RESET_MIN_MAX(bt);	\
 	RESET_MIN_MAX(req);  \
 	RESET_MIN_MAX(req);  \
 	RESET_MIN_MAX(rec);  \
 	RESET_MIN_MAX(rec);  \
 	RESET_MIN_MAX(under);  \
 	RESET_MIN_MAX(under);  \
-	RESET_MIN_MAX_DURATION(mutex1);  \
-	RESET_MIN_MAX_DURATION(mutex2);  \
-	RESET_MIN_MAX_DURATION(sleep_time);  \
-	RESET_MIN_MAX_DURATION(buffering);
-
-
-#if CONFIG_BTAUDIO
-void set_volume_bt(unsigned left, unsigned right) {
-	LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
-	LOCK;
-	output.gainL = left;
-	output.gainR = right;
-	UNLOCK;
-}
-#endif
-
-
-
-void output_bt_check_buffer()
-{
-#ifdef USE_BT_RING_BUFFER
-	LOCK_BT;
-	uint8_t tot_buf_used_pct=100*_buf_used(btbuf)/btbuf->size;
-	UNLOCK_BT;
-	if(tot_buf_used_pct<bt_buf_used_threshold)
-	{
-		// tell the thread to resume
-		LOG_SDEBUG("Below threshold. Locking suspend mutex.");
-		mutex_lock(output_bt_suspend_mutex);
-		LOG_SDEBUG("Broadcasting suspend condition.");
-		mutex_broadcast_cond(output_bt_suspend_cond);
-		LOG_SDEBUG("Unlocking suspend mutex.");
-		mutex_unlock(output_bt_suspend_mutex);
-	}
-#endif
-}
-void output_bt_suspend()
-{
-#ifdef USE_BT_RING_BUFFER
-	struct timespec   ts;
-	struct timeval    tp;
-	int               rc;
-
-
-	// if suspended, suspend until resumed
-	LOG_SDEBUG("Locking suspend mutex.");
-	mutex_lock(output_bt_suspend_mutex);
-	LOG_SDEBUG("Waiting on condition to be signaled.");
-
-	// suspend for up to a predetermined wait time.
-	// this will allow flushing the BT buffer when the
-	// playback stops.
-	gettimeofday(&tp, NULL);
-	/* Convert from timeval to timespec */
-	ts.tv_sec  = tp.tv_sec;
-	ts.tv_nsec = tp.tv_usec * 1000;
-	ts.tv_nsec +=  output_bt_thread_heartbeat_ms*1000000; // micro seconds to nanosecs
-
-	rc = pthread_cond_timedwait(&output_bt_suspend_cond,&output_bt_suspend_mutex,&ts);
-	if(rc==ETIMEDOUT)
-	{
-		LOG_SDEBUG("Wait timed out. Resuming output.");
-	}
-    LOG_SDEBUG("Unlocking suspend mutex.");
-    mutex_unlock(output_bt_suspend_mutex);
-#endif
-}
-
+	RESET_MIN_MAX(stream_buf); \
+	RESET_MIN_MAX_DURATION(lock_out_time)
+	
+DECLARE_ALL_MIN_MAX;	
+	
 void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
 void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
 	loglevel = level;
 	loglevel = level;
-
-	LOG_INFO("init output BT");
-
-	memset(&output, 0, sizeof(output));
-
-	// ensure output rate is specified to avoid test open
-	if (!rates[0]) {
-		rates[0] = 44100;
-	}
 	hal_bluetooth_init(device);
 	hal_bluetooth_init(device);
-/*
- * Bluetooth audio source init Start
- */
-//	device = CONFIG_OUTPUT_NAME;
-	output_init_common(level, device, output_buf_size, rates, idle);
-#ifdef USE_BT_RING_BUFFER
-	LOG_DEBUG("Allocating local BT transfer buffer of %u bytes.",bt_buffer_size);
-	buf_init(btbuf, bt_buffer_size );
-	if (!btbuf->buf) {
-		LOG_ERROR("unable to malloc BT buffer");
-		exit(0);
-	}
-	mutex_create_p(output_bt_suspend_mutex);
-	mutex_cond_init(output_bt_suspend_cond);
-	PTHREAD_SET_NAME("output_bt");
-
-#if LINUX || OSX || FREEBSD || POSIX
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-#ifdef PTHREAD_STACK_MIN
-	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + OUTPUT_THREAD_STACK_SIZE);
-#endif
-
-	pthread_create(&thread_bt, &attr, output_thread_bt, NULL);
-#endif
-	pthread_attr_destroy(&attr);
-
-#if WIN
-	thread = CreateThread(NULL, OUTPUT_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&output_thread_bt, NULL, 0, NULL);
-#endif
-#else
-	output.start_frames =  FRAME_BLOCK;
 	output.write_cb = &_write_frames;
 	output.write_cb = &_write_frames;
-	output.rate_delay = rate_delay;
-#endif
-	LOG_INFO("Init completed.");
-
-}
-
-/****************************************************************************************
- * Main output thread
- */
-#ifdef USE_BT_RING_BUFFER
-static void *output_thread_bt() {
-
-	frames_t frames=0;
-	frames_t requested_frames=0;
-	uint32_t timer_start=0, mutex_start=0;
-	unsigned btbuf_used=0;
-	output_state state;
-	DECLARE_ALL_MIN_MAX;
-	while (running) {
-		frames=0;
-		requested_frames=0;
-		TIME_MEASUREMENT_START(timer_start);
-
-		// Get output state
-		TIME_MEASUREMENT_START(mutex_start);
-		LOCK;
-		state=output.state;
-		SET_MIN_MAX(TIME_MEASUREMENT_GET(mutex_start),mutex1);
-
-		if(state < OUTPUT_STOPPED ){
-			// Flushing the buffer will automatically
-			// lock the mutex
-			LOG_SDEBUG("Flushing BT buffer");
-			buf_flush(btbuf);
-		}
-		if (state == OUTPUT_OFF) {
-			UNLOCK;
-			LOG_SDEBUG("Output state is off.");
-			usleep(200000);
-			continue;
-		}
-		output.device_frames = 0; // todo: check if this is the right way do to this.
-		output.updated = gettime_ms();
-		output.frames_played_dmp = output.frames_played;
-
-		TIME_MEASUREMENT_START(mutex_start);
-		LOCK_BT;
-		SET_MIN_MAX(TIME_MEASUREMENT_GET(mutex_start),mutex2);
-		btbuf_used=_buf_used(btbuf);
-		SET_MIN_MAX_SIZED(btbuf_used,locbtbuff,btbuf->size);
-
-
-		// only output more frames if we need them
-		// so we can release the mutex as quickly as possible
-		requested_frames = min(_buf_space(btbuf), _buf_cont_write(btbuf))/BYTES_PER_FRAME;
-		SET_MIN_MAX( requested_frames*BYTES_PER_FRAME,req);
-		SET_MIN_MAX_SIZED(_buf_used(outputbuf),o,outputbuf->size);
-		SET_MIN_MAX_SIZED(_buf_used(streambuf),s,streambuf->size);
-		if(requested_frames>0)
-		{
-			frames = _output_frames( requested_frames ); // Keep the transfer buffer full
-			SET_MIN_MAX(frames*BYTES_PER_FRAME,rec);
-			if(requested_frames>frames){
-				SET_MIN_MAX((requested_frames-frames)*BYTES_PER_FRAME,under);
-			}
-		}
-
-		UNLOCK;
-		UNLOCK_BT;
-		SET_MIN_MAX( TIME_MEASUREMENT_GET(timer_start),buffering);
-		SET_MIN_MAX( requested_frames,req);
-
-		// When playback has started, we want to
-		// hold the BT out thread
-		// so the BT data callback isn't constantly interrupted.
-		TIME_MEASUREMENT_START(timer_start);
-		if(state>OUTPUT_BUFFER){
-			output_bt_suspend();
-		}
-		SET_MIN_MAX(TIME_MEASUREMENT_GET(timer_start),sleep_time);
-
-		/*
-		 * Statistics reporting
-		 */
-		static time_t lastTime=0;
-		if (lastTime <= gettime_ms() )
-		{
-#define STATS_PERIOD_MS 15000
-			lastTime = gettime_ms() + STATS_PERIOD_MS;
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_HEAD1);
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_HEAD2);
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_HEAD3);
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_HEAD4);
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_STREAM, LINE_MIN_MAX_STREAM("stream",s));
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("output",o));
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("local bt buf",locbtbuff));
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_FOOTER );
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("requested",req));
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("received",rec));
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("Underrun",under));
-			LOG_DEBUG(LINE_MIN_MAX_FORMAT_FOOTER );
-			LOG_DEBUG("");
-			LOG_DEBUG("              ----------+----------+-----------+-----------+  ");
-			LOG_DEBUG("              max (us)  | min (us) |   avg(us) |  count    |  ");
-			LOG_DEBUG("              ----------+----------+-----------+-----------+  ");
-			LOG_DEBUG(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("Buffering(us)",buffering));
-			LOG_DEBUG(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("Output mux(us)",mutex1));
-			LOG_DEBUG(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("BT mux(us)",mutex2));
-			LOG_DEBUG(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("sleep(us)",mutex2));
-			LOG_DEBUG("              ----------+----------+-----------+-----------+");
-			RESET_ALL_MIN_MAX;
-		}
-		/*
-		 * End Statistics reporting
-		 */
-
-
-
-	}
-	return NULL;
-}
-#endif
-void output_close_bt(void) {
-	LOG_INFO("close output");
-	LOCK;
-	running = false;
-	UNLOCK;
-#ifdef USE_BT_RING_BUFFER
-	LOCK_BT;
-	buf_destroy(btbuf);
-	UNLOCK_BT;
-#endif
-	output_close_common();
 }
 }
 
 
 static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
 static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
 						 s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr) {
 						 s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr) {
-#ifdef USE_BT_RING_BUFFER
-	if (!silence ) {
-		DEBUG_LOG_TIMED(200,"Not silence, Writing audio out.");
-		// TODO need 16 bit fix
-
-		if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
-			_apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
-		}
-
-		if (gainL != FIXED_ONE || gainR!= FIXED_ONE) {
-			_apply_gain(outputbuf, out_frames, gainL, gainR);
-		}
-
-#if BYTES_PER_FRAME == 4
-
-		memcpy(btbuf->writep, outputbuf->readp, out_frames * BYTES_PER_FRAME);
-		_buf_inc_writep(btbuf,out_frames * BYTES_PER_FRAME);
-
-#else
-	{
-		frames_t count = out_frames;
-		s32_t *_iptr = (s32_t*) outputbuf->readp;
-		s16_t *_optr = (s16_t*) bt_optr;
-		while (count--) {
-			*_optr++ = *_iptr++ >> 16;
-			*_optr++ = *_iptr++ >> 16;
-		}
-	}
-#endif
-
-	} else if(output.state >OUTPUT_BUFFER){
-		// Don't fill our local buffer with silence frames.
-		u8_t *buf = silencebuf;
-		memcpy(btbuf->writep, buf, out_frames * BYTES_PER_FRAME);
-		_buf_inc_writep(btbuf,out_frames * BYTES_PER_FRAME);
-	}
-#else
-	assert(btout!=NULL);
+	
+	assert(btout != NULL);
+	
 	if (!silence ) {
 	if (!silence ) {
-		DEBUG_LOG_TIMED(200,"Not silence, Writing audio out.");
-		// TODO need 16 bit fix
-
+				
 		if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
 		if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
 			_apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
 			_apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
 		}
 		}
@@ -374,7 +81,74 @@ static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t g
 		u8_t *buf = silencebuf;
 		u8_t *buf = silencebuf;
 		memcpy(btout, buf, out_frames * BYTES_PER_FRAME);
 		memcpy(btout, buf, out_frames * BYTES_PER_FRAME);
 	}
 	}
-#endif
 
 
 	return (int)out_frames;
 	return (int)out_frames;
 }
 }
+
+int32_t output_bt_data(uint8_t *data, int32_t len) {
+	int32_t avail_data = 0, wanted_len = 0, start_timer = 0;
+
+	if (len < 0 || data == NULL ) {
+		return 0;
+	}
+	
+	btout = data;
+
+	// This is how the BTC layer calculates the number of bytes to
+	// for us to send. (BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16) - availPcmBytes
+	wanted_len=len;
+	SET_MIN_MAX(len,req);
+	TIME_MEASUREMENT_START(start_timer);
+	LOCK;
+	output.device_frames = 0; // todo: check if this is the right way do to this.
+	output.updated = gettime_ms();
+	output.frames_played_dmp = output.frames_played;
+	SET_MIN_MAX_SIZED(_buf_used(outputbuf),bt,outputbuf->size);
+	do {
+		avail_data = _output_frames( wanted_len/BYTES_PER_FRAME )*BYTES_PER_FRAME; // Keep the transfer buffer full
+		wanted_len-=avail_data;
+	} while (wanted_len > 0 && avail_data != 0);
+	
+	if (wanted_len > 0) {
+		SET_MIN_MAX(wanted_len, under);
+	}
+
+	UNLOCK;
+	SET_MIN_MAX(TIME_MEASUREMENT_GET(start_timer),lock_out_time);
+	SET_MIN_MAX((len-wanted_len), rec);
+	TIME_MEASUREMENT_START(start_timer);
+
+	return len-wanted_len;
+}
+
+void output_bt_tick(void) {
+	static time_t lastTime=0;
+	
+	LOCK_S;
+    SET_MIN_MAX_SIZED(_buf_used(streambuf), stream_buf, streambuf->size);
+    UNLOCK_S;
+	
+	if (lastTime <= gettime_ms() )
+	{
+		lastTime = gettime_ms() + STATS_REPORT_DELAY_MS;
+		LOG_INFO("Statistics over %u secs. " , STATS_REPORT_DELAY_MS/1000);
+		LOG_INFO("              +==========+==========+================+=====+================+");
+		LOG_INFO("              |      max |      min |        average | avg |          count |");
+		LOG_INFO("              |  (bytes) |  (bytes) |        (bytes) | pct |                |");
+		LOG_INFO("              +==========+==========+================+=====+================+");
+		LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("stream avl",stream_buf));
+		LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("output avl",bt));
+		LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("requested",req));
+		LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("received",rec));
+		LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("underrun",under));
+		LOG_INFO( "              +==========+==========+================+=====+================+");
+		LOG_INFO("\n");
+		LOG_INFO("              ==========+==========+===========+===========+  ");
+		LOG_INFO("              max (us)  | min (us) |   avg(us) |  count    |  ");
+		LOG_INFO("              ==========+==========+===========+===========+  ");
+		LOG_INFO(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("Out Buf Lock",lock_out_time));
+		LOG_INFO("              ==========+==========+===========+===========+");
+		RESET_ALL_MIN_MAX;
+	}	
+}	
+

+ 0 - 162
main/output_dac.c.tes

@@ -1,162 +0,0 @@
-#include "squeezelite.h"
-#include "driver/i2s.h"
-
-static log_level loglevel;
-
-static bool running = true;
-
-extern struct outputstate output;
-extern struct buffer *outputbuf;
-extern struct buffer *streambuf;
-
-#define LOCK   mutex_lock(outputbuf->mutex)
-#define UNLOCK mutex_unlock(outputbuf->mutex)
-
-#define FRAME_BLOCK MAX_SILENCE_FRAMES
-
-extern u8_t *silencebuf;
-
-#define I2S_NUM         (0)
-#define WAVE_FREQ_HZ    (100)
-#define PI              (3.14159265)
-#define I2S_BCK_IO      (GPIO_NUM_26)
-#define I2S_WS_IO       (GPIO_NUM_25)
-#define I2S_DO_IO       (GPIO_NUM_22)
-#define I2S_DI_IO       (-1)
-// buffer length is expressed in number of samples
-#define I2S_BUF_LEN		60
-
-static int _write_frames(frames_t out_frames, bool silence, s32_t gainL,
-		s32_t gainR, s32_t cross_gain_in, s32_t cross_gain_out,
-		ISAMPLE_T **cross_ptr);
-
-void set_volume(unsigned left, unsigned right) {
-	LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
-	LOCK;
-	output.gainL = left;
-	output.gainR = right;
-	// TODO
-	output.gainL = FIXED_ONE;
-	output.gainR = FIXED_ONE;
-	UNLOCK;
-}
-
-static void *output_thread(void *arg) {
-	bool start = true;
-	bool output_off = (output.state == OUTPUT_OFF);
-	bool probe_device = (arg != NULL);
-	int err;
-
-	while (running) {
-		// todo: implement output off logic?
-		// todo: call i2s_set_clock here if rate is changed
-		LOCK;
-
-		output.device_frames = 0;
-		output.updated = gettime_ms();
-		output.frames_played_dmp = output.frames_played;
-
-		_output_frames(I2S_BUF_LEN*2); // fill at least one DMA buffer with stereo signal
-
-		UNLOCK;
-	}
-
-	return 0;
-}
-
-static pthread_t thread;
-
-void output_init_dac(log_level level, char *device, unsigned output_buf_size,
-		char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
-	loglevel = level;
-
-	LOG_INFO("init output DAC");
-
-	memset(&output, 0, sizeof(output));
-
-	output.start_frames = 0; //CONFIG_ //FRAME_BLOCK * 2;
-	output.write_cb = &_write_frames;
-	output.rate_delay = rate_delay;
-
-	// ensure output rate is specified to avoid test open
-	if (!rates[0]) {
-		rates[0] = 44100;
-	}
-	device = "DAC";
-	output_init_common(level, device, output_buf_size, rates, idle);
-
-	i2s_config_t i2s_config = {
-			.mode = I2S_MODE_MASTER | I2S_MODE_TX,                    // Only TX
-			.sample_rate = output.current_sample_rate,
-			.bits_per_sample = BYTES_PER_FRAME * 8,
-			.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,           //2-channels
-			.communication_format = I2S_COMM_FORMAT_I2S
-					| I2S_COMM_FORMAT_I2S_MSB,
-			.dma_buf_count = 6, //todo: tune this parameter. Expressed in numbrer of buffers
-			.dma_buf_len = I2S_BUF_LEN, // todo: tune this parameter. Expressed in number of samples. Byte size depends on bit depth
-			.use_apll = false,
-			.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
-			};
-	i2s_pin_config_t pin_config = { .bck_io_num = I2S_BCK_IO, .ws_io_num =
-			I2S_WS_IO, .data_out_num = I2S_DO_IO, .data_in_num = I2S_DI_IO //Not used
-			};
-	i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
-	i2s_set_pin(I2S_NUM, &pin_config);
-	i2s_set_clk(I2S_NUM, output.current_sample_rate, i2s_config.bits_per_sample, 2);
-
-#if LINUX || OSX || FREEBSD || POSIX
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-#ifdef PTHREAD_STACK_MIN
-	pthread_attr_setstacksize(&attr,
-			PTHREAD_STACK_MIN + OUTPUT_THREAD_STACK_SIZE);
-#endif
-	pthread_create(&thread, &attr, output_thread, NULL);
-	pthread_attr_destroy(&attr);
-#endif
-#if WIN
-	thread = CreateThread(NULL, OUTPUT_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&output_thread, NULL, 0, NULL);
-#endif
-
-}
-
-void output_close_dac(void) {
-	LOG_INFO("close output");
-	LOCK;
-	running = false;
-	UNLOCK;
-
-	output_close_common();
-}
-
-static int _write_frames(frames_t out_frames, bool silence, s32_t gainL,
-		s32_t gainR, s32_t cross_gain_in, s32_t cross_gain_out,
-		ISAMPLE_T **cross_ptr) {
-
-	u8_t *obuf;
-	size_t i2s_bytes_write = 0;
-
-	if (!silence) {
-
-		if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
-			_apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
-		}
-
-		obuf = outputbuf->readp;
-
-	} else {
-
-		obuf = silencebuf;
-	}
-
-	//_scale_and_pack_frames(buf + buffill * bytes_per_frame, (s32_t *)(void *)obuf, out_frames, gainL, gainR, output.format);
-
-//	buffill += out_frames;
-	   i2s_write(I2S_NUM, obuf, out_frames  *BYTES_PER_FRAME, &i2s_bytes_write, 100);
-
-
-
-	return (int)i2s_bytes_write * BYTES_PER_FRAME;
-
-}
-

+ 119 - 0
main/output_embedded.c

@@ -0,0 +1,119 @@
+/* 
+ *  Squeezelite for esp32
+ *
+ *  (c) Sebastien 2019
+ *      Philippe G. 2019, philippe_44@outlook.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "squeezelite.h"
+
+extern struct outputstate output;
+extern struct buffer *outputbuf;
+
+#define FRAME_BLOCK MAX_SILENCE_FRAMES
+
+#define LOCK   mutex_lock(outputbuf->mutex)
+#define UNLOCK mutex_unlock(outputbuf->mutex)
+
+extern void set_volume_i2s(unsigned left, unsigned right);
+extern void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, 
+						  unsigned rates[], unsigned rate_delay, unsigned idle);
+extern void output_init_i2s(log_level level, char *device, unsigned output_buf_size, char *params, 
+						  unsigned rates[], unsigned rate_delay, unsigned idle);							  
+
+static log_level loglevel;
+
+static void (*volume_cb)(unsigned left, unsigned right);
+static void (*close_cb)(void);
+
+void output_init_embedded(log_level level, char *device, unsigned output_buf_size, char *params, 
+						  unsigned rates[], unsigned rate_delay, unsigned idle) {
+	loglevel = level;						
+	LOG_INFO("init device: %s", device);
+	
+	memset(&output, 0, sizeof(output));
+	output_init_common(level, device, output_buf_size, rates, idle);
+	output.start_frames =  FRAME_BLOCK;
+	output.rate_delay = rate_delay;
+	
+	if (strstr(device, "BT ")) {
+		LOG_INFO("init Bluetooth");
+		output_init_bt(level, device, output_buf_size, params, rates, rate_delay, idle);
+	} else {
+		LOG_INFO("init I2S");
+		//volume_cb = set_volume_i2s;
+		//close_cb = output_close_i2s;
+		//output_init_i2s(level, device, output_buf_size, params, rates, rate_delay, idle);
+	}	
+	
+	LOG_INFO("init completed.");
+}	
+
+void output_close_embedded(void) {
+	LOG_INFO("close output");
+	output_close_common();
+	if (close_cb) (*close_cb)();		
+}
+
+void set_volume(unsigned left, unsigned right) { 
+	LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
+	if (!volume_cb) {
+		LOCK;
+		output.gainL = left;
+		output.gainR = right;
+		UNLOCK;
+	} else (*volume_cb)(left, right); 	
+}
+
+bool test_open(const char *device, unsigned rates[], bool userdef_rates) {
+	memset(rates, 0, MAX_SUPPORTED_SAMPLERATES * sizeof(unsigned));
+	if (!strcmp(device, "BT")) {
+		rates[0] = 44100;	
+	} else {
+		unsigned _rates[] = { 96000, 88200, 48000, 44100, 32000, 0 };	
+		memcpy(rates, _rates, sizeof(_rates));
+	}
+	return true;
+}
+
+char* output_state_str(void){
+	output_state state;
+	LOCK;
+	state = output.state;
+	UNLOCK;
+	switch (state) {
+	case OUTPUT_OFF: 			return STR(OUTPUT_OFF);
+	case OUTPUT_STOPPED:		return STR(OUTPUT_STOPPED);
+	case OUTPUT_BUFFER:			return STR(OUTPUT_BUFFER);
+	case OUTPUT_RUNNING:		return STR(OUTPUT_RUNNING);
+	case OUTPUT_PAUSE_FRAMES: 	return STR(OUTPUT_PAUSE_FRAMES);
+	case OUTPUT_SKIP_FRAMES:	return STR(OUTPUT_SKIP_FRAMES);
+	case OUTPUT_START_AT:		return STR(OUTPUT_START_AT);
+	default:					return "OUTPUT_UNKNOWN_STATE";
+	}
+}
+
+bool output_stopped(void) {
+	output_state state;
+	LOCK;
+	state = output.state;
+	UNLOCK;
+	return state <= OUTPUT_STOPPED;
+}	
+	
+
+
+

+ 1 - 6
main/slimproto.c

@@ -436,13 +436,8 @@ static void process_audg(u8_t *pkt, int len) {
 	audg->gainR = unpackN(&audg->gainR);
 	audg->gainR = unpackN(&audg->gainR);
 
 
 	LOG_DEBUG("audg gainL: %u gainR: %u adjust: %u", audg->gainL, audg->gainR, audg->adjust);
 	LOG_DEBUG("audg gainL: %u gainR: %u adjust: %u", audg->gainL, audg->gainR, audg->adjust);
-#if CONFIG_BTAUDIO
-	set_volume_bt(audg->adjust ? audg->gainL : FIXED_ONE, audg->adjust ? audg->gainR : FIXED_ONE);
-#elif CONFIG_DACAUDIO
-	set_volume_dac(audg->adjust ? audg->gainL : FIXED_ONE, audg->adjust ? audg->gainR : FIXED_ONE);
-#else
+
 	set_volume(audg->adjust ? audg->gainL : FIXED_ONE, audg->adjust ? audg->gainR : FIXED_ONE);
 	set_volume(audg->adjust ? audg->gainL : FIXED_ONE, audg->adjust ? audg->gainR : FIXED_ONE);
-#endif
 }
 }
 
 
 static void process_setd(u8_t *pkt, int len) {
 static void process_setd(u8_t *pkt, int len) {

+ 31 - 85
main/squeezelite.h

@@ -34,6 +34,7 @@
 #define VERSION "v" MAJOR_VERSION "." MINOR_VERSION "-" MICRO_VERSION
 #define VERSION "v" MAJOR_VERSION "." MINOR_VERSION "-" MICRO_VERSION
 #endif
 #endif
 
 
+
 #if !defined(MODEL_NAME)
 #if !defined(MODEL_NAME)
 #define MODEL_NAME SqueezeLite
 #define MODEL_NAME SqueezeLite
 #endif
 #endif
@@ -42,16 +43,11 @@
 #define STR(macro)  QUOTE(macro)
 #define STR(macro)  QUOTE(macro)
 #define MODEL_NAME_STRING STR(MODEL_NAME)
 #define MODEL_NAME_STRING STR(MODEL_NAME)
 
 
-#if defined(EMBEDDED)
-#define POSIX 1
-#include "embedded.h"
-#endif
-#ifndef PTHREAD_SET_NAME
-#define PTHREAD_SET_NAME(n)
-#endif
-
-// build detection
-#if defined(linux)
+// build detection 
+#if defined (EMBEDDED)
+#undef EMBEDDED
+#define EMBEDDED  1
+#elif defined(linux)
 #define LINUX     1
 #define LINUX     1
 #define OSX       0
 #define OSX       0
 #define WIN       0
 #define WIN       0
@@ -78,27 +74,19 @@
 #define PA18API   1
 #define PA18API   1
 #define OSX       0
 #define OSX       0
 #define WIN       0
 #define WIN       0
-#elif defined (POSIX)
-#undef POSIX
-#define POSIX 	  1
 #else
 #else
 #error unknown target
 #error unknown target
 #endif
 #endif
 
 
-
-#if defined(CONFIG_DACAUDIO)
-#undef CONFIG_DACAUDIO
-#define CONFIG_DACAUDIO  1
-#elif defined(CONFIG_BTAUDIO)
-#undef CONFIG_BTAUDIO
-#define CONFIG_BTAUDIO 1
-#elif LINUX && !defined(PORTAUDIO)
+#if !EMBEDDED
+#if LINUX && !defined(PORTAUDIO)
 #define ALSA      1
 #define ALSA      1
 #define PORTAUDIO 0
 #define PORTAUDIO 0
 #else
 #else
 #define ALSA      0
 #define ALSA      0
 #define PORTAUDIO 1
 #define PORTAUDIO 1
 #endif
 #endif
+#endif
 
 
 #if !defined(LOOPBACK)
 #if !defined(LOOPBACK)
 #if SUN
 #if SUN
@@ -278,18 +266,18 @@
 #include <limits.h>
 #include <limits.h>
 #include <sys/types.h>
 #include <sys/types.h>
 
 
-#if LINUX || OSX || FREEBSD || POSIX
+#if EMBEDDED
+#include "embedded.h"
+#endif
+	
+#if LINUX || OSX || FREEBSD || EMBEDDED
 #include <unistd.h>
 #include <unistd.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/inet.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
-#if POSIX
 #include <sys/poll.h>
 #include <sys/poll.h>
-#else
-#include <poll.h>
-#endif
 #if !LINKALL
 #if !LINKALL
 #include <dlfcn.h>
 #include <dlfcn.h>
 #endif
 #endif
@@ -299,14 +287,10 @@
 #include <sys/types.h>
 #include <sys/types.h>
 #endif /* SUN */
 #endif /* SUN */
 
 
-#ifndef PTHREAD_STACK_MIN
-#define PTHREAD_STACK_MIN	256
-#endif
-
-#define STREAM_THREAD_STACK_SIZE  8 * 1024
-#define DECODE_THREAD_STACK_SIZE 20 * 1024
-#define OUTPUT_THREAD_STACK_SIZE  8 * 1024
-#define IR_THREAD_STACK_SIZE      8 * 1024
+#define STREAM_THREAD_STACK_SIZE  64 * 1024
+#define DECODE_THREAD_STACK_SIZE 128 * 1024
+#define OUTPUT_THREAD_STACK_SIZE  64 * 1024
+#define IR_THREAD_STACK_SIZE      64 * 1024
 #if !OSX
 #if !OSX
 #define thread_t pthread_t;
 #define thread_t pthread_t;
 #endif
 #endif
@@ -314,13 +298,12 @@
 #define last_error() errno
 #define last_error() errno
 #define ERROR_WOULDBLOCK EWOULDBLOCK
 #define ERROR_WOULDBLOCK EWOULDBLOCK
 
 
+#if !EMBEDDED
 #ifdef SUN
 #ifdef SUN
 typedef uint8_t  u8_t;
 typedef uint8_t  u8_t;
 typedef uint16_t u16_t;
 typedef uint16_t u16_t;
 typedef uint32_t u32_t;
 typedef uint32_t u32_t;
 typedef uint64_t u64_t;
 typedef uint64_t u64_t;
-#elif POSIX
-typedef unsigned long long u64_t;
 #else
 #else
 typedef u_int8_t  u8_t;
 typedef u_int8_t  u8_t;
 typedef u_int16_t u16_t;
 typedef u_int16_t u16_t;
@@ -330,29 +313,20 @@ typedef u_int64_t u64_t;
 typedef int16_t   s16_t;
 typedef int16_t   s16_t;
 typedef int32_t   s32_t;
 typedef int32_t   s32_t;
 typedef int64_t   s64_t;
 typedef int64_t   s64_t;
+#endif
 
 
 #define mutex_type pthread_mutex_t
 #define mutex_type pthread_mutex_t
 #define mutex_create(m) pthread_mutex_init(&m, NULL)
 #define mutex_create(m) pthread_mutex_init(&m, NULL)
-#if POSIX
-#define mutex_create_p(m) mutex_create(m)
-#else
+#if HAS_MUTEX_CREATE_P
 #define mutex_create_p(m) pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); pthread_mutex_init(&m, &attr); pthread_mutexattr_destroy(&attr)
 #define mutex_create_p(m) pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); pthread_mutex_init(&m, &attr); pthread_mutexattr_destroy(&attr)
+#else
+#define mutex_create_p(m) mutex_create(m)
 #endif
 #endif
 #define mutex_lock(m) pthread_mutex_lock(&m)
 #define mutex_lock(m) pthread_mutex_lock(&m)
 #define mutex_unlock(m) pthread_mutex_unlock(&m)
 #define mutex_unlock(m) pthread_mutex_unlock(&m)
 #define mutex_destroy(m) pthread_mutex_destroy(&m)
 #define mutex_destroy(m) pthread_mutex_destroy(&m)
-#define mutex_broadcast_cond(m) pthread_cond_broadcast(&m)
-#define mutex_cond_wait(c,m) pthread_cond_wait(&c, &m)
-#define mutex_cond_init(c) pthread_cond_init(&c, NULL)
-#define thread_cond_type pthread_cond_t
 #define thread_type pthread_t
 #define thread_type pthread_t
 #endif
 #endif
-#ifdef EMBEDDED
-#define local_exit(r) {static int ret=r; pthread_exit(&ret);}
-#else
-#define local_exit(r) exit(r)
-#endif
-
 
 
 #if WIN
 #if WIN
 
 
@@ -491,24 +465,7 @@ void logprint(const char *fmt, ...);
 #define LOG_INFO(fmt, ...)  if (loglevel >= lINFO)  logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #define LOG_INFO(fmt, ...)  if (loglevel >= lINFO)  logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #define LOG_DEBUG(fmt, ...) if (loglevel >= lDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #define LOG_DEBUG(fmt, ...) if (loglevel >= lDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #define LOG_SDEBUG(fmt, ...) if (loglevel >= lSDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #define LOG_SDEBUG(fmt, ...) if (loglevel >= lSDEBUG) logprint("%s %s:%d " fmt "\n", logtime(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-static inline void DEBUG_LOG_TIMED(uint32_t delayms, char * strFmt, ...)
-{
-	static log_level loglevel;
-	va_list args;
-	va_start(args, strFmt);
-	static uint32_t nextDebugLog=0;
-	if(esp_timer_get_time()>nextDebugLog)
-	{
-		if (loglevel >= lDEBUG)
-		{
-			logprint("%s %s:%d ", logtime(), __FUNCTION__, __LINE__);
-			logprint(strFmt , args);
-			logprint("\n");
-		}
-
-		nextDebugLog=esp_timer_get_time()+delayms*1000;
-	}
-}
+
 // utils.c (non logging)
 // utils.c (non logging)
 typedef enum { EVENT_TIMEOUT = 0, EVENT_READ, EVENT_WAKE } event_type;
 typedef enum { EVENT_TIMEOUT = 0, EVENT_READ, EVENT_WAKE } event_type;
 #if WIN && USE_SSL
 #if WIN && USE_SSL
@@ -670,8 +627,6 @@ typedef enum { S32_LE, S24_LE, S24_3LE, S16_LE, U8, U16_LE, U16_BE, U32_LE, U32_
 #else
 #else
 typedef enum { S32_LE, S24_LE, S24_3LE, S16_LE, S24_BE, S24_3BE, S16_BE, S8_BE } output_format;
 typedef enum { S32_LE, S24_LE, S24_3LE, S16_LE, S24_BE, S24_3BE, S16_BE, S8_BE } output_format;
 #endif
 #endif
-extern uint8_t get_bytes_per_frame(output_format fmt);
-
 
 
 typedef enum { FADE_INACTIVE = 0, FADE_DUE, FADE_ACTIVE } fade_state;
 typedef enum { FADE_INACTIVE = 0, FADE_DUE, FADE_ACTIVE } fade_state;
 typedef enum { FADE_UP = 1, FADE_DOWN, FADE_CROSS } fade_dir;
 typedef enum { FADE_UP = 1, FADE_DOWN, FADE_CROSS } fade_dir;
@@ -763,26 +718,17 @@ void output_close_pa(void);
 void _pa_open(void);
 void _pa_open(void);
 #endif
 #endif
 
 
-// output_dac.c
-
-void set_volume_dac(unsigned left, unsigned right);
-bool test_open(const char *device, unsigned rates[], bool userdef_rates);
-void output_init_dac(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle);
-void output_close_dac(void);
-void hal_dac_init(const char * options);
-
-//output_bt.c
-void set_volume_bt(unsigned left, unsigned right);
+// output_embedded.c
+#if EMBEDDED
+void set_volume(unsigned left, unsigned right);
 bool test_open(const char *device, unsigned rates[], bool userdef_rates);
 bool test_open(const char *device, unsigned rates[], bool userdef_rates);
-void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle);
-void output_close_bt(void);
-extern void hal_bluetooth_init(const char * options);
-void output_bt_check_buffer();
-
-
+void output_init_embedded(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle);
+void output_close_embedded(void);
+#else 
 // output_stdout.c
 // output_stdout.c
 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay);
 void output_init_stdout(log_level level, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay);
 void output_close_stdout(void);
 void output_close_stdout(void);
+#endif
 
 
 // output_pack.c
 // output_pack.c
 void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, output_format format);
 void _scale_and_pack_frames(void *outputptr, s32_t *inputptr, frames_t cnt, s32_t gainL, s32_t gainR, output_format format);

+ 6 - 3
main/stream.c

@@ -373,7 +373,7 @@ void stream_init(log_level level, unsigned stream_buf_size) {
 	buf_init(streambuf, stream_buf_size);
 	buf_init(streambuf, stream_buf_size);
 	if (streambuf->buf == NULL) {
 	if (streambuf->buf == NULL) {
 		LOG_ERROR("unable to malloc buffer");
 		LOG_ERROR("unable to malloc buffer");
-		local_exit(0);
+		exit(0);
 	}
 	}
 	
 	
 #if USE_SSL
 #if USE_SSL
@@ -405,8 +405,8 @@ void stream_init(log_level level, unsigned stream_buf_size) {
 #if LINUX || FREEBSD
 #if LINUX || FREEBSD
 	touch_memory(streambuf->buf, streambuf->size);
 	touch_memory(streambuf->buf, streambuf->size);
 #endif
 #endif
-PTHREAD_SET_NAME("stream");
-#if LINUX || OSX || FREEBSD || POSIX
+
+#if LINUX || OSX || FREEBSD || EMBEDDED
 	pthread_attr_t attr;
 	pthread_attr_t attr;
 	pthread_attr_init(&attr);
 	pthread_attr_init(&attr);
 #ifdef PTHREAD_STACK_MIN	
 #ifdef PTHREAD_STACK_MIN	
@@ -414,6 +414,9 @@ PTHREAD_SET_NAME("stream");
 #endif
 #endif
 	pthread_create(&thread, &attr, stream_thread, NULL);
 	pthread_create(&thread, &attr, stream_thread, NULL);
 	pthread_attr_destroy(&attr);
 	pthread_attr_destroy(&attr);
+#if HAS_PTHREAD_SETNAME_NP	
+	pthread_setname_np(thread, "stream");
+#endif
 #endif
 #endif
 #if WIN
 #if WIN
 	thread = CreateThread(NULL, STREAM_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&stream_thread, NULL, 0, NULL);
 	thread = CreateThread(NULL, STREAM_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&stream_thread, NULL, 0, NULL);

+ 2 - 76
main/utils.c

@@ -21,7 +21,7 @@
 
 
 #include "squeezelite.h"
 #include "squeezelite.h"
 
 
-#if LINUX || OSX || FREEBSD || POSIX
+#if LINUX || OSX || FREEBSD || EMBEDDED
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
 #include <net/if.h>
 #include <netdb.h>
 #include <netdb.h>
@@ -103,7 +103,7 @@ u32_t gettime_ms(void) {
 #if WIN
 #if WIN
 	return GetTickCount();
 	return GetTickCount();
 #else
 #else
-#if LINUX || FREEBSD || POSIX
+#if LINUX || FREEBSD || EMBEDDED
 	struct timespec ts;
 	struct timespec ts;
 #ifdef CLOCK_MONOTONIC
 #ifdef CLOCK_MONOTONIC
 	if (!clock_gettime(CLOCK_MONOTONIC, &ts)) {
 	if (!clock_gettime(CLOCK_MONOTONIC, &ts)) {
@@ -561,77 +561,3 @@ char *strcasestr(const char *haystack, const char *needle) {
 	return NULL;
 	return NULL;
 }
 }
 #endif
 #endif
-uint8_t get_bytes_per_frame(output_format fmt)
-{
-	uint8_t bpf=0;
-
-	switch (fmt) {
-		case S32_LE:
-			bpf=4*2;
-			break;
-		case S24_LE:
-			bpf=3*2;
-			break;
-		case S24_3LE:
-			bpf=3*2;
-			break;
-		case S16_LE:
-			bpf=2*2;
-			break;
-		case S24_BE:
-			bpf=3*2;
-			break;
-		case S24_3BE:
-			bpf=3*2;
-			break;
-		case S16_BE:
-			bpf=2*2;
-			break;
-		case S8_BE:
-			bpf=2*2;
-			break;
-#if DSD
-		case U8:
-			bpf=1*2;
-			break;
-		case U16_LE:
-			bpf=2*2;
-			break;
-		case U16_BE:
-			bpf=2*2;
-			break;
-		case U32_LE:
-			bpf=4*2;
-			break;
-		case U32_BE:
-			bpf=4*2;
-			break;
-#endif
-		default:
-			break;
-	}
-	assert(bpf>0);
-	return bpf;
-}
-
-char * get_output_state_desc(output_state state){
-	switch (state) {
-	case OUTPUT_OFF:
-		return STR(OUTPUT_OFF);
-	case OUTPUT_STOPPED:
-		return STR(OUTPUT_STOPPED);
-	case OUTPUT_BUFFER:
-		return STR(OUTPUT_BUFFER);
-	case OUTPUT_RUNNING:
-		return STR(OUTPUT_RUNNING);
-	case OUTPUT_PAUSE_FRAMES:
-		return STR(OUTPUT_PAUSE_FRAMES);
-	case OUTPUT_SKIP_FRAMES:
-		return STR(OUTPUT_SKIP_FRAMES);
-	case OUTPUT_START_AT:
-		return STR(OUTPUT_START_AT);
-	default:
-		return "OUTPUT_UNKNOWN_STATE";
-	}
-	return "";
-}