From 5d07344b4d24ad793df8b95a3925dad0a78b8f6d Mon Sep 17 00:00:00 2001 From: philippe44 Date: Thu, 30 Jan 2020 22:48:36 -0800 Subject: [PATCH] handle case w/o display - release --- components/driver_bt/bt_app_sink.c | 8 ++-- components/services/display.c | 40 ++++++++++++++----- components/services/driver_SSD1306.c | 2 +- .../services/tarablessd1306/ssd1306_font.c | 2 +- components/squeezelite/decode_external.c | 2 +- components/squeezelite/display.c | 10 ++++- components/squeezelite/embedded.c | 6 ++- components/squeezelite/embedded.h | 5 ++- components/squeezelite/slimproto.c | 2 +- 9 files changed, 55 insertions(+), 22 deletions(-) diff --git a/components/driver_bt/bt_app_sink.c b/components/driver_bt/bt_app_sink.c index 56cd4ca3..cff29501 100644 --- a/components/driver_bt/bt_app_sink.c +++ b/components/driver_bt/bt_app_sink.c @@ -162,7 +162,7 @@ static bool cmd_handler(bt_sink_cmd_t cmd, ...) { va_end(args); return false; } - + // now handle events for display switch(cmd) { case BT_SINK_AUDIO_STARTED: @@ -175,7 +175,7 @@ static bool cmd_handler(bt_sink_cmd_t cmd, ...) { displayer_control(DISPLAYER_TIMER_RUN); break; case BT_SINK_STOP: - // not sure of difference between pause and stop for displayer + // not sure of difference between pause and stop for displayer case BT_SINK_PAUSE: displayer_control(DISPLAYER_TIMER_PAUSE); break; @@ -397,7 +397,7 @@ void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_param bt_av_playback_changed(); break; case ESP_AVRC_RN_PLAY_POS_CHANGED: - ESP_LOGI(BT_AV_TAG, "Play position changed: %d-ms", event_parameter->play_pos); + ESP_LOGD(BT_AV_TAG, "Play position changed: %d (ms)", event_parameter->play_pos); (*bt_app_a2d_cmd_cb)(BT_SINK_PROGRESS, event_parameter->play_pos, -1); bt_av_play_pos_changed(); break; @@ -440,7 +440,7 @@ static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param) break; } case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { - ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); + ESP_LOGD(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id); bt_av_notify_evt_handler(rc->change_ntf.event_id, &rc->change_ntf.event_parameter); break; } diff --git a/components/services/display.c b/components/services/display.c index 6b6ab350..7dd7050f 100644 --- a/components/services/display.c +++ b/components/services/display.c @@ -29,7 +29,7 @@ // here we should include all possible drivers extern struct display_s SSD1306_display; -struct display_s *display; +struct display_s *display = NULL; static const char *TAG = "display"; @@ -72,6 +72,7 @@ void display_init(char *welcome) { init = true; ESP_LOGI(TAG, "Display initialization successful"); } else { + display = NULL; ESP_LOGE(TAG, "Display initialization failed"); } } else { @@ -103,7 +104,7 @@ void display_init(char *welcome) { } /**************************************************************************************** - * This is not really thread-safe as displayer_task might be in the middle of line drawing + * This is not thread-safe as displayer_task might be in the middle of line drawing * but it won't crash (I think) and making it thread-safe would be complicated for a * feature which is secondary (the LMS version of scrolling is thread-safe) */ @@ -128,11 +129,19 @@ static void displayer_task(void *args) { if (scroll_sleep <= 10) { // something to scroll (or we'll wake-up every pause ms ... no big deal) if (*displayer.string && displayer.state == DISPLAYER_ACTIVE) { - display->line(2, -displayer.offset, DISPLAY_CLEAR | DISPLAY_UPDATE, displayer.string); xSemaphoreTake(displayer.mutex, portMAX_DELAY); + + // need to work with local copies as we don't want to suspend caller + int offset = -displayer.offset; + char *string = strdup(displayer.string); scroll_sleep = displayer.offset ? displayer.speed : displayer.pause; displayer.offset = displayer.offset >= displayer.boundary ? 0 : (displayer.offset + min(displayer.by, displayer.boundary - displayer.offset)); - xSemaphoreGive(displayer.mutex); + + xSemaphoreGive(displayer.mutex); + + // now display using safe copies, can be lengthy + display->line(2, offset, DISPLAY_CLEAR | DISPLAY_UPDATE, string); + free(string); } else { scroll_sleep = DEFAULT_SLEEP; } @@ -149,8 +158,8 @@ static void displayer_task(void *args) { displayer.tick = tick; displayer.elapsed += elapsed / 1000; xSemaphoreGive(displayer.mutex); - if (displayer.elapsed < 3600) sprintf(counter, "%2u:%02u", displayer.elapsed / 60, displayer.elapsed % 60); - else sprintf(counter, "%2u:%2u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60); + if (displayer.elapsed < 3600) sprintf(counter, "%5u:%02u", displayer.elapsed / 60, displayer.elapsed % 60); + else sprintf(counter, "%2u:%02u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60); display->line(1, DISPLAY_RIGHT, (DISPLAY_CLEAR | DISPLAY_ONLY_EOL) | DISPLAY_UPDATE, counter); timer_sleep = 1000; } else timer_sleep = max(1000 - elapsed, 0); @@ -171,6 +180,10 @@ void displayer_metadata(char *artist, char *album, char *title) { char *string = displayer.string, *p; int len = SCROLLABLE_SIZE; + // need a display! + if (!display) return; + + // just do title if there is no config set if (!displayer.metadata_config) { strncpy(displayer.string, title ? title : "", SCROLLABLE_SIZE); return; @@ -218,7 +231,7 @@ void displayer_metadata(char *artist, char *album, char *title) { p = strchr(q + 1, '%'); } } else { - string = strdup(title ? title : ""); + strncpy(string, title ? title : "", SCROLLABLE_SIZE); } // get optional scroll speed @@ -232,11 +245,13 @@ void displayer_metadata(char *artist, char *album, char *title) { xSemaphoreGive(displayer.mutex); } - /**************************************************************************************** * */ void displayer_scroll(char *string, int speed) { + // need a display! + if (!display) return; + xSemaphoreTake(displayer.mutex, portMAX_DELAY); if (speed) displayer.speed = speed; @@ -252,10 +267,13 @@ void displayer_scroll(char *string, int speed) { * */ void displayer_timer(enum displayer_time_e mode, int elapsed, int duration) { + // need a display! + if (!display) return; + xSemaphoreTake(displayer.mutex, portMAX_DELAY); - if (elapsed >= 0) displayer.elapsed = elapsed; - if (duration >= 0) displayer.duration = duration; + if (elapsed >= 0) displayer.elapsed = elapsed / 1000; + if (duration >= 0) displayer.duration = duration / 1000; if (displayer.timer) displayer.tick = xTaskGetTickCount(); xSemaphoreGive(displayer.mutex); @@ -267,6 +285,8 @@ void displayer_timer(enum displayer_time_e mode, int elapsed, int duration) { void displayer_control(enum displayer_cmd_e cmd, ...) { va_list args; + if (!display) return; + va_start(args, cmd); xSemaphoreTake(displayer.mutex, portMAX_DELAY); diff --git a/components/services/driver_SSD1306.c b/components/services/driver_SSD1306.c index 6e2319e5..835e6f0e 100644 --- a/components/services/driver_SSD1306.c +++ b/components/services/driver_SSD1306.c @@ -164,7 +164,7 @@ static bool set_font(int num, enum display_font_e font, int space) { lines[0].y = lines[0].space; for (int i = 1; i <= num; i++) lines[i].y = lines[i-1].y + lines[i-1].font->Height + lines[i].space; - ESP_LOGI(TAG, "adding line %u at %u (height:%u)", num + 1, lines[num].y, lines[num].font->Height); + ESP_LOGI(TAG, "adding line %u at %d (height:%u)", num + 1, lines[num].y, lines[num].font->Height); if (lines[num].y + lines[num].font->Height > Display.Height) { ESP_LOGW(TAG, "line does not fit display"); diff --git a/components/services/tarablessd1306/ssd1306_font.c b/components/services/tarablessd1306/ssd1306_font.c index afc1c19f..7a178fd1 100644 --- a/components/services/tarablessd1306/ssd1306_font.c +++ b/components/services/tarablessd1306/ssd1306_font.c @@ -47,7 +47,7 @@ void SSD1306_FontDrawChar( struct SSD1306_Device* DisplayHandle, char Character, NullCheck( ( GlyphData = GetCharPtr( DisplayHandle->Font, Character ) ), return ); - if ( Character >= DisplayHandle->Font->StartChar || Character <= DisplayHandle->Font->EndChar ) { + if ( Character >= DisplayHandle->Font->StartChar && Character <= DisplayHandle->Font->EndChar ) { /* The first byte in the glyph data is the width of the character in pixels, skip over */ GlyphData++; GlyphColumnLen = RoundUpFontHeight( DisplayHandle->Font ) / 8; diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index a79d4d16..3cf0c698 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -207,7 +207,7 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) ms = ((u64_t) ((_buf_used(outputbuf) - raop_sync.len) / BYTES_PER_FRAME + output.device_frames + output.frames_in_process) * 1000) / RAOP_SAMPLE_RATE - (now - output.updated); raop_sync.error[raop_sync.idx] = (raop_sync.playtime - now) - ms; sync_nb = SYNC_NB; - LOG_INFO("head local:%u, remote:%u (delta:%d)", ms, raop_sync.playtime - now, raop_sync.error[raop_sync.idx]); + LOG_DEBUG("head local:%u, remote:%u (delta:%d)", ms, raop_sync.playtime - now, raop_sync.error[raop_sync.idx]); LOG_DEBUG("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), raop_sync.len, output.device_frames, output.frames_in_process); } diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index 2b5663c1..12b30a42 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -137,10 +137,16 @@ static void scroll_task(void* arg); /**************************************************************************************** * */ -void sb_display_init(void) { +bool sb_display_init(void) { static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); static EXT_RAM_ATTR StackType_t xStack[SCROLL_STACK_SIZE] __attribute__ ((aligned (4))); + // no display, just make sure we won't have requests + if (!display || display->height == 0 || display->width == 0) { + LOG_INFO("no display for LMS"); + return false; + } + // need to force height to 32 maximum display_width = display->width; display_height = min(display->height, 32); @@ -163,6 +169,8 @@ void sb_display_init(void) { notify_chain = server_notify; server_notify = server; + + return true; } /**************************************************************************************** diff --git a/components/squeezelite/embedded.c b/components/squeezelite/embedded.c index 6dc3aed0..89a2aa83 100644 --- a/components/squeezelite/embedded.c +++ b/components/squeezelite/embedded.c @@ -50,9 +50,11 @@ uint32_t _gettime_ms_(void) { } extern void sb_controls_init(void); -extern void sb_display_init(void); +extern bool sb_display_init(void); + +u8_t custom_player_id = 12; void embedded_init(void) { sb_controls_init(); - sb_display_init(); + if (sb_display_init()) custom_player_id = 100; } diff --git a/components/squeezelite/embedded.h b/components/squeezelite/embedded.h index 5f75cd77..1d22876e 100644 --- a/components/squeezelite/embedded.h +++ b/components/squeezelite/embedded.h @@ -26,7 +26,10 @@ #define OUTPUT_THREAD_STACK_SIZE 6 * 1024 #define IR_THREAD_STACK_SIZE 6 * 1024 -#define PLAYER_ID 100 +// or can be as simple as #define PLAYER_ID 100 +#define PLAYER_ID custom_player_id; +extern u8_t custom_player_id; + #define BASE_CAP "Model=squeezeesp32,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION #define EXT_BSS __attribute__((section(".ext_ram.bss"))) diff --git a/components/squeezelite/slimproto.c b/components/squeezelite/slimproto.c index 982f3b0f..34c8f193 100644 --- a/components/squeezelite/slimproto.c +++ b/components/squeezelite/slimproto.c @@ -45,7 +45,7 @@ static sockfd sock = -1; static in_addr_t slimproto_ip = 0; static u16_t slimproto_hport = 9000; static u16_t slimproto_cport = 9090; -static u8_t player_id = PLAYER_ID; +static u8_t player_id; extern struct buffer *streambuf; extern struct buffer *outputbuf;