diff --git a/components/driver_bt/bt_app_handler.c b/components/driver_bt/bt_app_handler.c index bc37ff15..cf24d351 100644 --- a/components/driver_bt/bt_app_handler.c +++ b/components/driver_bt/bt_app_handler.c @@ -123,14 +123,20 @@ static uint32_t s_pkt_cnt = 0; static TimerHandle_t s_tmr; static struct { - struct arg_str *sink_name; - struct arg_int *control_delay; - struct arg_int *connect_timeout_delay; - struct arg_end *end; -} squeezelite_args; + int control_delay; + int connect_timeout_delay; + char sink_name[32]; +} squeezelite_conf; void hal_bluetooth_init(const char * options) { + struct { + struct arg_str *sink_name; + struct arg_int *control_delay; + struct arg_int *connect_timeout_delay; + struct arg_end *end; + } squeezelite_args; + ESP_LOGD(TAG,"Initializing Bluetooth HAL"); squeezelite_args.sink_name = arg_str1("n", "name", "", "the name of the bluetooth to connect to"); @@ -162,18 +168,24 @@ void hal_bluetooth_init(const char * options) if(squeezelite_args.sink_name->count == 0) { ESP_LOGD(TAG,"Using default sink name : %s",CONFIG_A2DP_SINK_NAME); - squeezelite_args.sink_name->sval[0] = CONFIG_A2DP_SINK_NAME; + strncpy(squeezelite_conf.sink_name, CONFIG_A2DP_SINK_NAME, 32); + } else { + strncpy(squeezelite_conf.sink_name, squeezelite_args.sink_name->sval[0], 32); } if(squeezelite_args.connect_timeout_delay->count == 0) { ESP_LOGD(TAG,"Using default connect timeout"); - squeezelite_args.connect_timeout_delay->ival[0]=CONFIG_A2DP_CONNECT_TIMEOUT_MS; + squeezelite_conf.connect_timeout_delay=CONFIG_A2DP_CONNECT_TIMEOUT_MS; + } else { + squeezelite_conf.connect_timeout_delay=squeezelite_args.connect_timeout_delay->ival[0]; } if(squeezelite_args.control_delay->count == 0) { ESP_LOGD(TAG,"Using default control delay"); - squeezelite_args.control_delay->ival[0]=CONFIG_A2DP_CONTROL_DELAY_MS; - } + squeezelite_conf.control_delay=CONFIG_A2DP_CONTROL_DELAY_MS; + } else { + squeezelite_conf.control_delay=squeezelite_args.control_delay->ival[0]; + } ESP_LOGD(TAG,"Freeing options"); free(argv); free(opts); @@ -228,6 +240,20 @@ void hal_bluetooth_init(const char * options) } +void hal_bluetooth_stop(void) { + /* this still does not work, can't figure out how to stop properly this BT stack */ + bt_app_task_shut_down(); + ESP_LOGI(TAG, "bt_app_task shutdown successfully"); + if (esp_bluedroid_disable() != ESP_OK) return; + ESP_LOGI(TAG, "esp_bluedroid_disable called successfully"); + if (esp_bluedroid_deinit() != ESP_OK) return; + ESP_LOGI(TAG, "esp_bluedroid_deinit called successfully"); + if (esp_bt_controller_disable() != ESP_OK) return; + ESP_LOGI(TAG, "esp_bt_controller_disable called successfully"); + if (esp_bt_controller_deinit() != ESP_OK) return; + ESP_LOGI(TAG, "bt stopped successfully"); +} + 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); @@ -454,7 +480,7 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param) ESP_LOGI(TAG,"--Device name is %s\n",s_peer_bdname); } - if (strcmp((char *)s_peer_bdname, CONFIG_A2DP_SINK_NAME) == 0) { + if (strcmp((char *)s_peer_bdname, squeezelite_conf.sink_name) == 0) { ESP_LOGI(TAG,"Found a target device! address %s, name %s", bda_str, s_peer_bdname); ESP_LOGI(TAG,"=======================\n"); if(esp_bt_gap_cancel_discovery()!=ESP_ERR_INVALID_STATE) @@ -470,7 +496,7 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param) } else { - ESP_LOGI(TAG,"Not the device we are looking for. Continuing scan."); + ESP_LOGI(TAG,"Not the device we are looking for (%s). Continuing scan", squeezelite_conf.sink_name); } } diff --git a/components/squeezelite/decode.c b/components/squeezelite/decode.c index c9c4eaec..60405e5c 100644 --- a/components/squeezelite/decode.c +++ b/components/squeezelite/decode.c @@ -234,7 +234,7 @@ void decode_close(void) { } running = false; UNLOCK_D; -#if LINUX || OSX || FREEBSD +#if LINUX || OSX || FREEBSD || EMBEDDED pthread_join(thread, NULL); #endif mutex_destroy(decode.mutex); diff --git a/components/squeezelite/embedded.h b/components/squeezelite/embedded.h index d10c4035..264d50c8 100644 --- a/components/squeezelite/embedded.h +++ b/components/squeezelite/embedded.h @@ -20,6 +20,7 @@ typedef int32_t s32_t; typedef int64_t s64_t; typedef unsigned long long u64_t; +// all exit() calls are made from main thread (or a function called in main thread) #define exit(code) { int ret = code; pthread_exit(&ret); } int pthread_setname_np(pthread_t thread, const char *name); diff --git a/components/squeezelite/output_bt.c b/components/squeezelite/output_bt.c index dd687166..d7080e21 100644 --- a/components/squeezelite/output_bt.c +++ b/components/squeezelite/output_bt.c @@ -37,8 +37,10 @@ extern u8_t *silencebuf; #define STATS_REPORT_DELAY_MS 15000 extern void hal_bluetooth_init(const char * options); +extern void hal_bluetooth_stop(void); static log_level loglevel; +static bool running = false; uint8_t * btout; static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, @@ -64,10 +66,18 @@ 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) { loglevel = level; - hal_bluetooth_init(device); + running = true; output.write_cb = &_write_frames; + hal_bluetooth_init(device); } +void output_close_bt(void) { + LOCK; + running = false; + UNLOCK; + hal_bluetooth_stop(); +} + 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) { @@ -109,7 +119,7 @@ static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t g 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 ) { + if (len < 0 || data == NULL || !running) { return 0; } @@ -145,6 +155,8 @@ int32_t output_bt_data(uint8_t *data, int32_t len) { void output_bt_tick(void) { static time_t lastTime=0; + if (!running) return; + LOCK_S; SET_MIN_MAX_SIZED(_buf_used(streambuf), stream_buf, streambuf->size); UNLOCK_S; @@ -171,5 +183,4 @@ void output_bt_tick(void) { LOG_INFO(" ==========+==========+===========+===========+"); RESET_ALL_MIN_MAX; } -} - +} \ No newline at end of file diff --git a/components/squeezelite/output_embedded.c b/components/squeezelite/output_embedded.c index 37ae892e..ebb13b13 100644 --- a/components/squeezelite/output_embedded.c +++ b/components/squeezelite/output_embedded.c @@ -33,6 +33,7 @@ extern void output_init_bt(log_level level, char *device, unsigned output_buf_si extern void output_init_i2s(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle); extern void output_close_i2s(void); +extern void output_close_bt(void); static log_level loglevel; @@ -46,15 +47,16 @@ void output_init_embedded(log_level level, char *device, unsigned output_buf_siz memset(&output, 0, sizeof(output)); output_init_common(level, device, output_buf_size, rates, idle); - output.start_frames = FRAME_BLOCK; + output.start_frames = FRAME_BLOCK; output.rate_delay = rate_delay; if (strstr(device, "BT ")) { LOG_INFO("init Bluetooth"); + close_cb = &output_close_bt; output_init_bt(level, device, output_buf_size, params, rates, rate_delay, idle); } else { LOG_INFO("init I2S"); - close_cb = output_close_i2s; + close_cb = &output_close_i2s; output_init_i2s(level, device, output_buf_size, params, rates, rate_delay, idle); } @@ -63,8 +65,8 @@ void output_init_embedded(log_level level, char *device, unsigned output_buf_siz void output_close_embedded(void) { LOG_INFO("close output"); - output_close_common(); if (close_cb) (*close_cb)(); + output_close_common(); } void set_volume(unsigned left, unsigned right) { diff --git a/components/squeezelite/output_i2s.c b/components/squeezelite/output_i2s.c index 70400a50..8f10788f 100644 --- a/components/squeezelite/output_i2s.c +++ b/components/squeezelite/output_i2s.c @@ -167,6 +167,11 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch * Terminate DAC output */ void output_close_i2s(void) { + LOCK; + running = false; + UNLOCK; + pthread_join(thread, NULL); + pthread_join(stats_thread, NULL); i2s_driver_uninstall(CONFIG_I2S_NUM); free(obuf); } diff --git a/components/squeezelite/slimproto.c b/components/squeezelite/slimproto.c index ec53d283..ba5e585f 100644 --- a/components/squeezelite/slimproto.c +++ b/components/squeezelite/slimproto.c @@ -775,6 +775,11 @@ in_addr_t discover_server(char *default_server) { char *buf; struct pollfd pollinfo; unsigned port; + int attempts = 0; + +#if EMBEDDED + attempts = 5; +#endif int disc_sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -811,7 +816,7 @@ in_addr_t discover_server(char *default_server) { server_addr(default_server, &s.sin_addr.s_addr, &port); } - } while (s.sin_addr.s_addr == 0 && running); + } while (s.sin_addr.s_addr == 0 && running && (!attempts || --attempts)); closesocket(disc_sock); @@ -896,7 +901,7 @@ void slimproto(log_level level, char *server, u8_t mac[6], const char *name, con new_server = 0; - while (running) { + while (running && slimproto_ip) { if (new_server) { previous_server = slimproto_ip; diff --git a/components/squeezelite/stream.c b/components/squeezelite/stream.c index 267a7581..59f9f693 100644 --- a/components/squeezelite/stream.c +++ b/components/squeezelite/stream.c @@ -428,7 +428,7 @@ void stream_close(void) { LOCK; running = false; UNLOCK; -#if LINUX || OSX || FREEBSD || POSIX +#if LINUX || OSX || FREEBSD || EMBEDDED pthread_join(thread, NULL); #endif free(stream.header); diff --git a/main/cmd_squeezelite.c b/main/cmd_squeezelite.c index 3fc2103a..c880d347 100644 --- a/main/cmd_squeezelite.c +++ b/main/cmd_squeezelite.c @@ -106,10 +106,7 @@ static int launchsqueezelite(int argc, char **argv) cfg.thread_name= "squeezelite"; cfg.inherit_cfg = true; esp_pthread_set_cfg(&cfg); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_create(&thread_squeezelite, &attr, squeezelite_thread,NULL); - pthread_attr_destroy(&attr); + pthread_create(&thread_squeezelite, NULL, squeezelite_thread,NULL); ESP_LOGD(TAG ,"Back to console thread!"); return 0; }