From a4d2017a0799b1fc6b08dac93d75e5310dee8496 Mon Sep 17 00:00:00 2001 From: Philippe G Date: Sun, 9 Jan 2022 16:47:28 -0800 Subject: [PATCH] tweak airplay artwork --- components/display/CMakeLists.txt | 1 + components/display/core/gds_image.c | 6 +++--- components/display/display.c | 22 +++++++++++++++++++--- components/display/note.jpg | Bin 0 -> 11563 bytes 4 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 components/display/note.jpg diff --git a/components/display/CMakeLists.txt b/components/display/CMakeLists.txt index 01886005..8a1944b9 100644 --- a/components/display/CMakeLists.txt +++ b/components/display/CMakeLists.txt @@ -2,6 +2,7 @@ idf_component_register(SRC_DIRS . core core/ifaces fonts INCLUDE_DIRS . fonts core REQUIRES platform_config tools esp_common PRIV_REQUIRES services freertos driver + EMBED_FILES note.jpg ) set_source_files_properties(display.c diff --git a/components/display/core/gds_image.c b/components/display/core/gds_image.c index cbb392e5..f47e3383 100644 --- a/components/display/core/gds_image.c +++ b/components/display/core/gds_image.c @@ -142,7 +142,7 @@ static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) { JpegCtx *Context = (JpegCtx*) Decoder->device; uint8_t *Pixels = (uint8_t*) Bitmap; int Shift = 8 - Context->Depth; - + // decoded image is RGB888, shift only make sense for grayscale if (Context->Mode == GDS_RGB888) { OUTHANDLERDIRECT(Scaler888, 0); @@ -167,7 +167,7 @@ static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) { static void* DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, bool SizeOnly, int RGB_Mode) { JDEC Decoder; JpegCtx Context; - char *Scratch = calloc(SCRATCH_SIZE, 1); + char *Scratch = malloc(SCRATCH_SIZE); if (!Scratch) { ESP_LOGE(TAG, "Cannot allocate workspace"); @@ -372,7 +372,7 @@ bool GDS_DrawJPEG(struct GDS_Device* Device, uint8_t *Source, int x, int y, int JDEC Decoder; JpegCtx Context; bool Ret = false; - char *Scratch = calloc(SCRATCH_SIZE, 1); + char *Scratch = malloc(SCRATCH_SIZE); if (!Scratch) { ESP_LOGE(TAG, "Cannot allocate workspace"); diff --git a/components/display/display.c b/components/display/display.c index 8d5d7e9c..b05e1223 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -33,6 +33,8 @@ static const char *TAG = "display"; #define DEFAULT_SLEEP 3600 #define ARTWORK_BORDER 1 +extern const uint8_t default_artwork[] asm("_binary_note_jpg_start"); + static EXT_RAM_ATTR struct { TaskHandle_t task; SemaphoreHandle_t mutex; @@ -51,6 +53,8 @@ static EXT_RAM_ATTR struct { } duration; struct { bool enable, fit; + bool updated; + int tick; int offset; } artwork; TickType_t tick; @@ -239,7 +243,12 @@ static void displayer_task(void *args) { // just re-write the whole line it's easier GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header); GDS_TextLine(display, 1, GDS_TEXT_RIGHT, GDS_TEXT_UPDATE, _line); - + + // if we have not received artwork after 5s, display a default icon + if (displayer.artwork.enable && !displayer.artwork.updated && tick - displayer.artwork.tick > pdMS_TO_TICKS(5000)) { + ESP_LOGI(TAG, "no artwork received, setting default"); + displayer_artwork((uint8_t*) default_artwork); + } timer_sleep = 1000; } else timer_sleep = max(1000 - elapsed, 0); } else timer_sleep = DEFAULT_SLEEP; @@ -252,7 +261,6 @@ static void displayer_task(void *args) { } } - /**************************************************************************************** * */ @@ -262,7 +270,14 @@ void displayer_artwork(uint8_t *data) { int x = displayer.artwork.offset ? displayer.artwork.offset + ARTWORK_BORDER : 0; int y = x ? 0 : 32; GDS_ClearWindow(display, x, y, -1, -1, GDS_COLOR_BLACK); - if (data) GDS_DrawJPEG(display, data, x, y, GDS_IMAGE_CENTER | (displayer.artwork.fit ? GDS_IMAGE_FIT : 0)); + if (data) { + displayer.artwork.updated = true; + GDS_DrawJPEG(display, data, x, y, GDS_IMAGE_CENTER | (displayer.artwork.fit ? GDS_IMAGE_FIT : 0)); + } else { + displayer.artwork.updated = false; + displayer.artwork.tick = xTaskGetTickCount(); + } + } /**************************************************************************************** @@ -428,6 +443,7 @@ void displayer_control(enum displayer_cmd_e cmd, ...) { case DISPLAYER_SHUTDOWN: // let the task self-suspend (we might be doing i2c_write) GDS_SetTextWidth(display, 0); + GDS_Clear(display, GDS_COLOR_BLACK); displayer.state = DISPLAYER_DOWN; display_bus(&displayer, DISPLAY_BUS_GIVE); break; diff --git a/components/display/note.jpg b/components/display/note.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6beb3ef7c6e5b7029d45bbf30c2e3594474c933e GIT binary patch literal 11563 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 literal 0 HcmV?d00001