From a79022147c1dbd23cbc9ee6ec7fbd4d14fe20cb2 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Mon, 16 Mar 2020 22:08:40 -0700 Subject: [PATCH 1/7] SSD1326 correction + prepare new slimproto message for artwork --- components/display/SSD1306.c | 15 +++------- components/display/core/gds_draw.c | 5 ++-- components/display/core/gds_private.h | 2 +- components/squeezelite/display.c | 42 +++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/components/display/SSD1306.c b/components/display/SSD1306.c index e1280b8b..fec88996 100644 --- a/components/display/SSD1306.c +++ b/components/display/SSD1306.c @@ -74,7 +74,7 @@ static void Update( struct GDS_Device* Device ) { CurrentPage = p + 1; // actual write - Device->WriteData( Device, Private->Shadowbuffer + p*width + first, last - first + 1 ); + Device->WriteData( Device, Private->Shadowbuffer + p*width + first, last - first + 1); } } #else @@ -114,10 +114,6 @@ static bool Init( struct GDS_Device* Device ) { // charge pump regulator, do direct init Device->WriteCommand( Device, 0x8D ); Device->WriteCommand( Device, 0x14 ); - - // set Clocks - Device->WriteCommand( Device, 0xD5 ); - Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); // COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something different Device->WriteCommand( Device, 0xDA ); @@ -126,12 +122,6 @@ static bool Init( struct GDS_Device* Device ) { // MUX Ratio Device->WriteCommand( Device, 0xA8 ); Device->WriteCommand( Device, Device->Height - 1); - // Page & GDDRAM Start Column High/Low - /* - Device->WriteCommand( Device, 0x00 ); - Device->WriteCommand( Device, 0x10 ); - Device->WriteCommand( Device, 0xB0 ); - */ // Display Offset Device->WriteCommand( Device, 0xD3 ); Device->WriteCommand( Device, 0 ); @@ -143,6 +133,9 @@ static bool Init( struct GDS_Device* Device ) { Device->SetHFlip( Device, false ); // no Display Inversion Device->WriteCommand( Device, 0xA6 ); + // set Clocks + Device->WriteCommand( Device, 0xD5 ); + Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); // set Adressing Mode Horizontal Device->WriteCommand( Device, 0x20 ); Device->WriteCommand( Device, 0 ); diff --git a/components/display/core/gds_draw.c b/components/display/core/gds_draw.c index c85d39e6..ca18dc94 100644 --- a/components/display/core/gds_draw.c +++ b/components/display/core/gds_draw.c @@ -212,6 +212,7 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int uint8_t *optr = Device->Framebuffer; int LineLen = Device->Width >> 1; Height >>= 3; + Color &= 0x0f; for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { uint8_t Byte = BitReverseTable256[*Data++]; // we need to linearize code to let compiler better optimize @@ -223,7 +224,7 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; Byte >>= 1; + *optr = (*optr & 0x0f) | (((Byte & 0x01)*Color)<<4); optr += LineLen; } else { *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; @@ -232,7 +233,7 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; - *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; Byte >>= 1; + *optr = (*optr & 0xf0) | (((Byte & 0x01)*Color)); optr += LineLen; } // end of a column, move to next one if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + (c >> 1); } diff --git a/components/display/core/gds_private.h b/components/display/core/gds_private.h index 6d3f46f1..816ddaf0 100644 --- a/components/display/core/gds_private.h +++ b/components/display/core/gds_private.h @@ -167,7 +167,7 @@ inline void IRAM_ATTR GDS_DrawPixel4Fast( struct GDS_Device* Device, int X, int uint8_t* FBOffset; FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1)); - *FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f)); + *FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f)); } inline void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) { diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index e7061477..555ee983 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -26,6 +26,7 @@ #include "gds.h" #include "gds_text.h" #include "gds_draw.h" +#include "gds_image.h" #pragma pack(push, 1) @@ -59,6 +60,12 @@ struct grfg_packet { u16_t width; // # of pixels of scrollable }; +struct grfa_packet { + char opcode[4]; + u32_t length; + u32_t offset; +}; + struct visu_packet { char opcode[4]; u8_t which; @@ -130,6 +137,11 @@ static struct scroller_s { u32_t width; } scroller; +static struct { + u8_t *data; + u32_t size; +} artwork; + #define MAX_BARS 32 static EXT_RAM_ATTR struct { int bar_gap, bar_width, bar_border; @@ -174,6 +186,7 @@ static void grfe_handler( u8_t *data, int len); static void grfb_handler(u8_t *data, int len); static void grfs_handler(u8_t *data, int len); static void grfg_handler(u8_t *data, int len); +static void grfa_handler(u8_t *data, int len); static void visu_handler(u8_t *data, int len); static void displayer_task(void* arg); @@ -360,6 +373,8 @@ static bool handler(u8_t *data, int len){ grfs_handler(data, len); } else if (!strncmp((char*) data, "grfg", 4)) { grfg_handler(data, len); + } else if (!strncmp((char*) data, "grfa", 4)) { + grfa_handler(data, len); } else if (!strncmp((char*) data, "visu", 4)) { visu_handler(data, len); } else { @@ -636,6 +651,33 @@ static void grfg_handler(u8_t *data, int len) { vTaskResume(displayer.task); } + +/**************************************************************************************** + * Artwork + */ +static void grfa_handler(u8_t *data, int len) { + struct grfa_packet *pkt = (struct grfa_packet*) data; + int size = len - sizeof(struct grfa_packet); + int offset = htonl(pkt->offset); + int length = htonl(pkt->length); + + LOG_INFO("gfra l:%u o:%u s:%u", length, offset, size); + + // new grfa artwork, allocate memory + if (!offset) { + if (artwork.data) free(artwork.data); + artwork.data = malloc(length); + artwork.size = 0; + } + + // copy artwork data + memcpy(artwork.data + offset, data + sizeof(struct grfa_packet), size); + artwork.size += size; + if (artwork.size == length) { + GDS_DrawJPEG(display, artwork.data, 0, 32, GDS_IMAGE_CENTER); + } +} + /**************************************************************************************** * Update visualization bars */ From 126d3f4e04ebe8fa0de2c3bbaba2bf6804301ea6 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Tue, 17 Mar 2020 19:01:44 -0700 Subject: [PATCH 2/7] airplay: fix some silly unsigned errors and handle network blackouts - release --- components/squeezelite/decode_external.c | 34 +++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/components/squeezelite/decode_external.c b/components/squeezelite/decode_external.c index 6a5a25fc..7b0f73b5 100644 --- a/components/squeezelite/decode_external.c +++ b/components/squeezelite/decode_external.c @@ -52,7 +52,7 @@ static raop_event_t raop_state; static EXT_RAM_ATTR struct { bool enabled; int sum, count, win, errors[SYNC_WIN_RUN]; - u32_t len; + s32_t len; u32_t start_time, playtime; } raop_sync; @@ -209,20 +209,21 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) // how many ms have we really played ms = now - output.updated + ((u64_t) (output.frames_played_dmp - output.device_frames) * 1000) / RAOP_SAMPLE_RATE; error = ms - (now - raop_sync.start_time); + LOG_INFO("backend played %u, desired %u, (delta:%d)", ms, now - raop_sync.start_time, ms - (now - raop_sync.start_time)); } else { - // in how many ms will the most recent block play - 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); - error = (raop_sync.playtime - now) - ms; + u32_t level = _buf_used(outputbuf); - // make sure impact of erroneous point is limited, but taken into account - if (abs(error) > 1000) { - LOG_INFO("limiting erroneous sync point %d", error); - error = (error > 0) ? SYNC_WIN_RUN : -SYNC_WIN_RUN; - } - - LOG_DEBUG("head local:%u, remote:%u (delta:%d)", ms, raop_sync.playtime - now, error); - LOG_DEBUG("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), raop_sync.len, output.device_frames, output.frames_in_process); + // in how many ms will the most recent block play + ms = (((s32_t)(level - raop_sync.len) / BYTES_PER_FRAME + output.device_frames + output.frames_in_process) * 10) / (RAOP_SAMPLE_RATE / 100) - (s32_t) (now - output.updated); + + // when outputbuf is empty, it means we have a network black-out or something + error = level ? (raop_sync.playtime - now) - ms : 0; + + if (loglevel == lDEBUG || !level) { + LOG_INFO("head local:%d, remote:%d (delta:%d)", ms, raop_sync.playtime - now, error); + LOG_INFO("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), raop_sync.len, output.device_frames, output.frames_in_process); + } } // calculate sum, error and update sliding window @@ -231,7 +232,10 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) error = raop_sync.sum / min(raop_sync.count, raop_sync.win); // move to normal mode if possible - if (raop_sync.win == SYNC_WIN_START && raop_sync.count >= SYNC_WIN_START && abs(error) < 10) raop_sync.win = SYNC_WIN_RUN; + if (raop_sync.win == SYNC_WIN_START && raop_sync.count >= SYNC_WIN_START && abs(error) < 10) { + raop_sync.win = SYNC_WIN_RUN; + LOG_INFO("switching to slow sync mode %u", raop_sync.win); + } // wait till e have enough data or there is a strong deviation if ((raop_sync.count >= raop_sync.win && abs(error) > 10) || (raop_sync.count >= SYNC_WIN_CHECK && abs(error) > 100)) { @@ -240,11 +244,11 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args) if (error < 0) { output.skip_frames = -(error * RAOP_SAMPLE_RATE) / 1000; output.state = OUTPUT_SKIP_FRAMES; - LOG_INFO("skipping %u frames", output.skip_frames); + LOG_INFO("skipping %u frames (count:%d)", output.skip_frames, raop_sync.count); } else { output.pause_frames = (error * RAOP_SAMPLE_RATE) / 1000; output.state = OUTPUT_PAUSE_FRAMES; - LOG_INFO("pausing for %u frames", output.pause_frames); + LOG_INFO("pausing for %u frames (count: %d)", output.pause_frames, raop_sync.count); } // reset sliding window From 5e5dc9ba29106ab6769950b2b71c76237dbcf423 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Wed, 18 Mar 2020 23:42:44 -0700 Subject: [PATCH 3/7] 1st artwork version --- components/display/core/gds.c | 4 ++ components/display/core/gds_image.c | 4 +- components/display/core/gds_image.h | 5 +- components/squeezelite/display.c | 41 +++++++----- plugin/SqueezeESP32.zip | Bin 7561 -> 7772 bytes plugin/SqueezeESP32/Graphics.pm | 27 ++++++-- .../plugins/SqueezeESP32/settings/basic.html | 20 ------ plugin/SqueezeESP32/Player.pm | 15 ++++- plugin/SqueezeESP32/PlayerSettings.pm | 10 ++- plugin/SqueezeESP32/Plugin.pm | 59 ++++++++++++++++++ plugin/SqueezeESP32/Settings.pm | 30 --------- plugin/SqueezeESP32/SqueezeESP32.zip | Bin 0 -> 7772 bytes plugin/SqueezeESP32/install.xml | 2 +- plugin/SqueezeESP32/strings.txt | 16 +++++ plugin/repo.xml | 4 +- 15 files changed, 158 insertions(+), 79 deletions(-) delete mode 100644 plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/basic.html delete mode 100644 plugin/SqueezeESP32/Settings.pm create mode 100644 plugin/SqueezeESP32/SqueezeESP32.zip diff --git a/components/display/core/gds.c b/components/display/core/gds.c index d315b027..26242a60 100644 --- a/components/display/core/gds.c +++ b/components/display/core/gds.c @@ -60,6 +60,10 @@ void GDS_Clear( struct GDS_Device* Device, int Color ) { } void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) { + // -1 means up to width/height + if (x2 < 0) x2 = Device->Width - 1; + if (y2 < 0) y2 = Device->Height - 1; + // driver can provide own optimized clear window if (Device->ClearWindow) { Device->ClearWindow( Device, x1, y1, x2, y2, Color ); diff --git a/components/display/core/gds_image.c b/components/display/core/gds_image.c index a5919f74..ebd274e1 100644 --- a/components/display/core/gds_image.c +++ b/components/display/core/gds_image.c @@ -218,8 +218,10 @@ bool GDS_DrawJPEG( struct GDS_Device* Device, uint8_t *Source, int x, int y, int // then place it if (Fit & GDS_IMAGE_CENTER_X) Context.XOfs = (Device->Width + x - Context.Width) / 2; + else if (Fit & GDS_IMAGE_RIGHT) Context.XOfs = Device->Width - Context.Width; if (Fit & GDS_IMAGE_CENTER_Y) Context.YOfs = (Device->Height + y - Context.Height) / 2; - + else if (Fit & GDS_IMAGE_BOTTOM) Context.YOfs = Device->Height - Context.Height; + Context.XMin = x - Context.XOfs; Context.YMin = y - Context.YOfs; diff --git a/components/display/core/gds_image.h b/components/display/core/gds_image.h index fa87001a..0becd94a 100644 --- a/components/display/core/gds_image.h +++ b/components/display/core/gds_image.h @@ -9,8 +9,11 @@ struct GDS_Device; enum { GDS_RGB565, GDS_RGB555, GDS_RGB444 }; -#define GDS_IMAGE_TOP 0x00 +#define GDS_IMAGE_LEFT 0x00 #define GDS_IMAGE_CENTER_X 0x01 +#define GDS_IMAGE_RIGHT 0x04 +#define GDS_IMAGE_TOP 0x00 +#define GDS_IMAGE_BOTTOM 0x08 #define GDS_IMAGE_CENTER_Y 0x02 #define GDS_IMAGE_CENTER (GDS_IMAGE_CENTER_X | GDS_IMAGE_CENTER_Y) #define GDS_IMAGE_FIT 0x10 diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index 555ee983..c85cf4a2 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -62,7 +62,9 @@ struct grfg_packet { struct grfa_packet { char opcode[4]; - u32_t length; + u32_t length; + u16_t x; + u16_t y; u32_t offset; }; @@ -140,6 +142,7 @@ static struct scroller_s { static struct { u8_t *data; u32_t size; + u16_t x, y; } artwork; #define MAX_BARS 32 @@ -313,7 +316,7 @@ static void send_server(void) { pkt_header.length = htonl(sizeof(pkt_header) - 8); pkt_header.mode = ANIC_resp; - send_packet((u8_t *)&pkt_header, sizeof(pkt_header)); + send_packet((uint8_t *) &pkt_header, sizeof(pkt_header)); ANIC_resp = ANIM_NONE; } @@ -321,18 +324,22 @@ static void send_server(void) { if (SETD_width) { struct SETD_header pkt_header; - LOG_INFO("sending width %u", SETD_width); - memset(&pkt_header, 0, sizeof(pkt_header)); memcpy(&pkt_header.opcode, "SETD", 4); pkt_header.id = 0xfe; // id 0xfe is width S:P:Squeezebox2 - pkt_header.length = htonl(sizeof(pkt_header) + 2 - 8); + pkt_header.length = htonl(sizeof(pkt_header) + 4 - 8); + + u16_t height = GDS_GetHeight(display); + LOG_INFO("sending dimension %ux%u", SETD_width, height); SETD_width = htons(SETD_width); - send_packet((u8_t *)&pkt_header, sizeof(pkt_header)); - send_packet((uint8_t*) &SETD_width, 2); - + height = htons(height); + + send_packet((uint8_t *) &pkt_header, sizeof(pkt_header)); + send_packet((uint8_t *) &SETD_width, 2); + send_packet((uint8_t *) &height, 2); + SETD_width = 0; } @@ -661,10 +668,10 @@ static void grfa_handler(u8_t *data, int len) { int offset = htonl(pkt->offset); int length = htonl(pkt->length); - LOG_INFO("gfra l:%u o:%u s:%u", length, offset, size); - // new grfa artwork, allocate memory if (!offset) { + artwork.x = htons(pkt->x); + artwork.y = htons(pkt->y); if (artwork.data) free(artwork.data); artwork.data = malloc(length); artwork.size = 0; @@ -674,8 +681,14 @@ static void grfa_handler(u8_t *data, int len) { memcpy(artwork.data + offset, data + sizeof(struct grfa_packet), size); artwork.size += size; if (artwork.size == length) { - GDS_DrawJPEG(display, artwork.data, 0, 32, GDS_IMAGE_CENTER); - } + GDS_ClearWindow(display, artwork.x, artwork.y, -1, -1, GDS_COLOR_BLACK); + GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < 32 ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); + free(artwork.data); + artwork.data = NULL; + artwork.size = 0; + } + + LOG_INFO("gfra l:%u x:%hu, y:%hu, o:%u s:%u", length, artwork.x, artwork.y, offset, size); } /**************************************************************************************** @@ -820,7 +833,7 @@ static void visu_handler( u8_t *data, int len) { visu.mode = pkt->which; // little trick to clean the taller screens when switching visu - if (visu.row >= SB_HEIGHT) GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1); + if (visu.row >= SB_HEIGHT) GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); if (visu.mode) { if (pkt->count >= 4) { @@ -878,7 +891,7 @@ static void visu_handler( u8_t *data, int len) { // reset bars maximum for (int i = visu.n; --i >= 0;) visu.bars[i].max = 0; - GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1); + GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); LOG_INFO("Visualizer with %u bars of width %d:%d:%d:%d (%w:%u,h:%u,c:%u,r:%u,s:%.02f)", visu.n, visu.bar_border, visu.bar_width, visu.bar_gap, visu.border, visu.width, visu.height, visu.col, visu.row, visu.spectrum_scale); } else { diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip index 871345cc5d83a05d2509da56db6515bef41c97b9..2a3b0eebcdb365ef11b617d71d3ffef688565697 100644 GIT binary patch delta 6209 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 v_Yv;TubSVv6#Hk|JNOue^A=02AAgNrC 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 diff --git a/plugin/SqueezeESP32/Graphics.pm b/plugin/SqueezeESP32/Graphics.pm index 225c907b..a8dead59 100644 --- a/plugin/SqueezeESP32/Graphics.pm +++ b/plugin/SqueezeESP32/Graphics.pm @@ -71,7 +71,12 @@ sub displayWidth { } if ($display->widthOverride) { - return $display->widthOverride + ($display->modes->[$mode || 0]{_width} || 0); + my $artwork = $prefs->client($client)->get('artwork'); + if ($artwork->{'enable'} && $artwork->{'y'} < 32) { + return $artwork->{x} + ($display->modes->[$mode || 0]{_width} || 0); + } else { + return $display->widthOverride + ($display->modes->[$mode || 0]{_width} || 0); + } } else { return $display->modes->[$mode || 0]{width}; } @@ -101,9 +106,21 @@ sub build_modes { my $cprefs = $prefs->client($client); my $width = shift || $cprefs->get('width') || 128; + my $artwork = $cprefs->get('artwork'); + + # if artwork is in main display, reduce width + $width = $artwork->{'x'} - 1 if $artwork->{'enable'} && $artwork->{y} < 32; + my $small_VU = $cprefs->get('small_VU'); my $spectrum = $cprefs->get('spectrum'); + my $small_spectrum_pos = { x => $width - int ($spectrum->{small}->{size} * $width / 100), + width => int ($spectrum->{small}->{size} * $width / 100), + }; + my $small_VU_pos = { x => $width - int ($small_VU * $width / 100), + width => int ($small_VU * $width / 100), + }; + my @modes = ( # mode 0 { desc => ['BLANK'], @@ -135,14 +152,14 @@ sub build_modes { params => [$VISUALIZER_NONE] }, # mode 7 { desc => ['VISUALIZER_VUMETER_SMALL'], - bar => 0, secs => 0, width => $width, _width => int -($small_VU*$width/100), + bar => 0, secs => 0, width => $width, _width => -$small_VU_pos->{'width'}, # extra parameters (width, height, col (< 0 = from right), row (< 0 = from bottom), left_space) - params => [$VISUALIZER_VUMETER, int ($small_VU*$width/100), 32, int -($small_VU*$width/100), 0, 2] }, + params => [$VISUALIZER_VUMETER, $small_VU_pos->{'width'}, 32, $small_VU_pos->{'x'}, 0, 2] }, # mode 8 { desc => ['VISUALIZER_SPECTRUM_ANALYZER_SMALL'], - bar => 0, secs => 0, width => $width, _width => int -($spectrum->{small}->{size}*$width/100), + bar => 0, secs => 0, width => $width, _width => -$small_spectrum_pos->{'width'}, # extra parameters (width, height, col (< 0 = from right), row (< 0 = from bottom), left_space, bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER, int ($spectrum->{small}->{size}*$width/100), 32, int -($spectrum->{small}->{size}*$width/100), 0, 2, int ($spectrum->{small}->{size}/100*$width/$spectrum->{small}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER, $small_spectrum_pos->{width}, 32, $small_spectrum_pos->{'x'}, 0, 2, $small_spectrum_pos->{'width'} / $spectrum->{small}->{band}, $spectrum->{scale}] }, # mode 9 { desc => ['VISUALIZER_VUMETER'], bar => 0, secs => 0, width => $width, diff --git a/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/basic.html b/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/basic.html deleted file mode 100644 index fdf77916..00000000 --- a/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/basic.html +++ /dev/null @@ -1,20 +0,0 @@ -[% PROCESS settings/header.html %] - - [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_BANNER" %] -
[% "PLUGIN_SQUEEZEESP32_BANNER_TEXT" | string %]
- [% END %] - -
- - [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_WIDTH" desc="PLUGIN_SQUEEZEESP32_WIDTH_DESC" %] - - [% END %] - - [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_SPECTRUM_SCALE" desc="PLUGIN_SQUEEZEESP32_SPECTRUM_SCALE_DESC" %] - - [% END %] - - -
- -[% PROCESS settings/footer.html %] diff --git a/plugin/SqueezeESP32/Player.pm b/plugin/SqueezeESP32/Player.pm index 946eb303..d3692e2e 100644 --- a/plugin/SqueezeESP32/Player.pm +++ b/plugin/SqueezeESP32/Player.pm @@ -20,8 +20,8 @@ sub playerSettingsFrame { my $value; my $id = unpack('C', $$data_ref); - - # New SETD command 0xfe for display width + + # New SETD command 0xfe for display width & height if ($id == 0xfe) { $value = (unpack('Cn', $$data_ref))[1]; if ($value > 100 && $value < 400) { @@ -30,7 +30,9 @@ sub playerSettingsFrame { $client->display->widthOverride(1, $value); $client->update; } - $log->info("Setting player width $value for ", $client->name); + my $height = (unpack('Cnn', $$data_ref))[2]; + $prefs->client($client)->set('height', $height || 0); + $log->info("Setting player $value" . "x" . "$height for ", $client->name); } $client->SUPER::playerSettingsFrame($data_ref); @@ -40,4 +42,11 @@ sub hasScrolling { return 1; } + +sub directMetadata { + my $client = shift; + $client->SUPER::directMetadata(@_); + Slim::Control::Request::notifyFromArray( $client, [ 'newmetadata' ] ); +} + 1; diff --git a/plugin/SqueezeESP32/PlayerSettings.pm b/plugin/SqueezeESP32/PlayerSettings.pm index 4c88dcfd..1ff4f7b9 100644 --- a/plugin/SqueezeESP32/PlayerSettings.pm +++ b/plugin/SqueezeESP32/PlayerSettings.pm @@ -30,7 +30,7 @@ sub page { sub prefs { my ($class, $client) = @_; - my @prefs = qw(width small_VU spectrum); + my @prefs = qw(width small_VU spectrum artwork); return ($prefs->client($client), @prefs); } @@ -47,6 +47,11 @@ sub handler { full => { band => $paramRef->{'pref_spectrum_full_band'} }, }; $cprefs->set('spectrum', $spectrum); + my $artwork = { enable => $paramRef->{'pref_artwork_enable'}, + x => $paramRef->{'pref_artwork_x'}, + y => $paramRef->{'pref_artwork_y'}, + }; + $cprefs->set('artwork', $artwork); $client->display->modes($client->display->build_modes); $client->display->update; } @@ -56,9 +61,10 @@ sub handler { # here I don't know why you need to set again spectrum which is a reference # to a hash. Using $paramRef->{prefs} does not work either. It seems that - # soem are copies of value, some are references, can't figure out.This whole + # some are copies of value, some are references, can't figure out. This whole # logic of "Settings" is beyond me and I really hate it $paramRef->{'pref_spectrum'} = $cprefs->get('spectrum'); + $paramRef->{'pref_artwork'} = $cprefs->get('artwork'); return $class->SUPER::handler($client, $paramRef); } diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm index 5078f66c..22a462d6 100644 --- a/plugin/SqueezeESP32/Plugin.pm +++ b/plugin/SqueezeESP32/Plugin.pm @@ -3,8 +3,12 @@ package Plugins::SqueezeESP32::Plugin; use strict; use base qw(Slim::Plugin::Base); + +use Digest::MD5 qw(md5); +use List::Util qw(min); use Slim::Utils::Prefs; use Slim::Utils::Log; +use Slim::Web::ImageProxy; my $prefs = preferences('plugin.squeezeesp32'); @@ -28,6 +32,61 @@ sub initPlugin { $class->SUPER::initPlugin(@_); Slim::Networking::Slimproto::addPlayerClass($class, 100, 'squeezeesp32', { client => 'Plugins::SqueezeESP32::Player', display => 'Plugins::SqueezeESP32::Graphics' }); $log->info("Added class 100 for SqueezeESP32"); + + Slim::Control::Request::subscribe(\&update_artwork, [ ['newmetadata'] ] ); + Slim::Control::Request::subscribe(\&update_artwork, [ ['playlist'], ['open', 'newsong'] ]); } +sub update_artwork { + my $request = shift; + my $client = $request->client; + my $cprefs = $prefs->client($client); + my $artwork = $cprefs->get('artwork'); + + return unless $client->model eq 'squeezeesp32' && $artwork->{'enable'}; + + my $reqstr = $request->getRequestString(); + #my $path = $request->getParam('_path'); + + my $s = $artwork->{'y'} >= 32 ? $cprefs->get('height') - $artwork->{'y'} : 32; + $s = min($s, $cprefs->get('width') - $artwork->{'x'}); + + my $path = 'music/current/cover_' . $s . 'x' . $s . '_o.jpg'; + my $body = Slim::Web::Graphics::artworkRequest($client, $path, undef, \&send_artwork, undef, HTTP::Response->new); + + send_artwork($client, undef, \$body) if $body; + + $log->info("artwork update notification $reqstr with $path"); +} + +sub send_artwork { + my ($client, $params, $dataref) = @_; + + # I'm not sure why we are called so often, so only send when needed + my $md5 = md5($$dataref); + return if $client->pluginData('artwork_md5') eq $md5; + + $client->pluginData('artwork', $dataref); + $client->pluginData('artwork_md5', $md5); + + my $artwork = $prefs->client($client)->get('artwork'); + my $length = length $$dataref; + my $offset = 0; + + $log->info("got resized artwork (length: ", length $$dataref, ")"); + + my $header = pack('Nnn', $length, $artwork->{'x'}, $artwork->{'y'}); + + while ($length > 0) { + $length = 1280 if $length > 1280; + $log->info("sending grfa $length"); + + my $data = $header . pack('N', $offset) . substr( $$dataref, 0, $length, '' ); + + $client->sendFrame( grfa => \$data ); + $offset += $length; + $length = length $$dataref; + } +} + 1; diff --git a/plugin/SqueezeESP32/Settings.pm b/plugin/SqueezeESP32/Settings.pm deleted file mode 100644 index 1ef18504..00000000 --- a/plugin/SqueezeESP32/Settings.pm +++ /dev/null @@ -1,30 +0,0 @@ -package Plugins::SqueezeESP32::Settings; -use base qw(Slim::Web::Settings); - -use strict; - -use Slim::Utils::Prefs; -use Slim::Utils::Log; - -my $log = logger('plugin.squeezeesp32'); - -sub name { - return 'PLUGIN_SQUEEZEESP32'; -} - -sub page { - return 'plugins/SqueezeESP32/settings/basic.html'; -} - -sub prefs { - return (preferences('plugin.squeezeesp32'), qw(width spectrum_scale)); -} - -sub handler { - my ($class, $client, $params, $callback, @args) = @_; - - $callback->($client, $params, $class->SUPER::handler($client, $params), @args); -} - - -1; diff --git a/plugin/SqueezeESP32/SqueezeESP32.zip b/plugin/SqueezeESP32/SqueezeESP32.zip new file mode 100644 index 0000000000000000000000000000000000000000..2a3b0eebcdb365ef11b617d71d3ffef688565697 GIT binary patch literal 7772 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 PLUGIN_SQUEEZEESP32_DESC Plugins::SqueezeESP32::Plugin - 0.31 + 0.40 Philippe diff --git a/plugin/SqueezeESP32/strings.txt b/plugin/SqueezeESP32/strings.txt index 1dd9e492..d5ed82c2 100644 --- a/plugin/SqueezeESP32/strings.txt +++ b/plugin/SqueezeESP32/strings.txt @@ -53,3 +53,19 @@ PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND_DESC EN The number of bands is the width of the screen divided by this factor + +PLUGIN_SQUEEZEESP32_ARTWORK + EN Artwork + +PLUGIN_SQUEEZEESP32_ARTWORK_DESC + EN When Y position is less than 32, then artwork is display at the right of the main screen and x defines the starting position + EN Using artwork on less than 16-levels grayscale display if really poor quality + +PLUGIN_SQUEEZEESP32_ARTWORK_ENABLE + EN Enable + +PLUGIN_SQUEEZEESP32_ARTWORK_X + EN X + +PLUGIN_SQUEEZEESP32_ARTWORK_Y + EN Y diff --git a/plugin/repo.xml b/plugin/repo.xml index 45a2e536..e0c81729 100644 --- a/plugin/repo.xml +++ b/plugin/repo.xml @@ -1,10 +1,10 @@ - + https://github.com/sle118/squeezelite-esp32 Philippe - 6dc35a0f9f9b287d205f7532cbb642b08407a284 + aa122a85db949c903ffa978d3e3b4ee3205e4ec2 philippe_44@outlook.com SqueezeESP32 additional player id (100) http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip From 606f1983c5ff83439008e9f9b3cd68dd57b605b0 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Thu, 19 Mar 2020 16:13:59 -0700 Subject: [PATCH 4/7] artwork support - release --- components/squeezelite/display.c | 17 ++++++++------- plugin/SqueezeESP32.zip | Bin 7772 -> 7873 bytes plugin/SqueezeESP32/Graphics.pm | 4 ++-- plugin/SqueezeESP32/Player.pm | 5 +++++ plugin/SqueezeESP32/PlayerSettings.pm | 3 +++ plugin/SqueezeESP32/Plugin.pm | 30 +++++++++++++++----------- plugin/SqueezeESP32/SqueezeESP32.zip | Bin 7772 -> 0 bytes plugin/SqueezeESP32/install.xml | 2 +- plugin/repo.xml | 4 ++-- 9 files changed, 40 insertions(+), 25 deletions(-) delete mode 100644 plugin/SqueezeESP32/SqueezeESP32.zip diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index c85cf4a2..cace344e 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -595,9 +595,6 @@ static void grfs_handler(u8_t *data, int len) { scroller.first = true; scroller.overflow = false; - // background excludes space taken by visu (if any) - scroller.back.width = displayer.width - ((visu.mode && visu.row < SB_HEIGHT) ? visu.width : 0); - // set scroller steps & beginning if (pkt->direction == 1) { scroller.scrolled = 0; @@ -634,6 +631,7 @@ static void grfg_handler(u8_t *data, int len) { // size of scrollable area (less than background) scroller.width = htons(pkt->width); + scroller.back.width = ((len - sizeof(struct grfg_packet)) * 8) / displayer.height; memcpy(scroller.back.frame, data + sizeof(struct grfg_packet), len - sizeof(struct grfg_packet)); // update display asynchronously (frames are organized by columns) @@ -670,13 +668,20 @@ static void grfa_handler(u8_t *data, int len) { // new grfa artwork, allocate memory if (!offset) { + // same trick to clean current/previous window + if (artwork.size) { + GDS_ClearWindow(display, artwork.x, artwork.y, -1, -1, GDS_COLOR_BLACK); + artwork.size = 0; + } + + // now use new parameters artwork.x = htons(pkt->x); artwork.y = htons(pkt->y); if (artwork.data) free(artwork.data); artwork.data = malloc(length); artwork.size = 0; } - + // copy artwork data memcpy(artwork.data + offset, data + sizeof(struct grfa_packet), size); artwork.size += size; @@ -685,7 +690,6 @@ static void grfa_handler(u8_t *data, int len) { GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < 32 ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); free(artwork.data); artwork.data = NULL; - artwork.size = 0; } LOG_INFO("gfra l:%u x:%hu, y:%hu, o:%u s:%u", length, artwork.x, artwork.y, offset, size); @@ -849,9 +853,6 @@ static void visu_handler( u8_t *data, int len) { visu.border = htonl(pkt->border); bars = htonl(pkt->bars); visu.spectrum_scale = htonl(pkt->spectrum_scale) / 100.; - - // might have a race condition with scroller message, so update width in case - if (scroller.active) scroller.back.width = displayer.width - visu.width; } else { // full screen visu, try to use bottom screen if available visu.width = displayer.width; diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip index 2a3b0eebcdb365ef11b617d71d3ffef688565697..cf1d7f509cfddcf36ec54844612cc4fc24675e57 100644 GIT binary patch delta 4062 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 S*L~nKR5+IknHuP?|M)+WPgb%3 diff --git a/plugin/SqueezeESP32/Graphics.pm b/plugin/SqueezeESP32/Graphics.pm index a8dead59..f90134ac 100644 --- a/plugin/SqueezeESP32/Graphics.pm +++ b/plugin/SqueezeESP32/Graphics.pm @@ -109,7 +109,7 @@ sub build_modes { my $artwork = $cprefs->get('artwork'); # if artwork is in main display, reduce width - $width = $artwork->{'x'} - 1 if $artwork->{'enable'} && $artwork->{y} < 32; + $width = $artwork->{'x'} if $artwork->{'enable'} && $artwork->{y} < 32; my $small_VU = $cprefs->get('small_VU'); my $spectrum = $cprefs->get('spectrum'); @@ -119,7 +119,7 @@ sub build_modes { }; my $small_VU_pos = { x => $width - int ($small_VU * $width / 100), width => int ($small_VU * $width / 100), - }; + }; my @modes = ( # mode 0 diff --git a/plugin/SqueezeESP32/Player.pm b/plugin/SqueezeESP32/Player.pm index d3692e2e..e0e6a3b7 100644 --- a/plugin/SqueezeESP32/Player.pm +++ b/plugin/SqueezeESP32/Player.pm @@ -42,6 +42,11 @@ sub hasScrolling { return 1; } +sub reconnect { + my $client = shift; + $client->pluginData('artwork_md5', ''); + $client->SUPER::reconnect(@_); +} sub directMetadata { my $client = shift; diff --git a/plugin/SqueezeESP32/PlayerSettings.pm b/plugin/SqueezeESP32/PlayerSettings.pm index 1ff4f7b9..4fd57722 100644 --- a/plugin/SqueezeESP32/PlayerSettings.pm +++ b/plugin/SqueezeESP32/PlayerSettings.pm @@ -54,6 +54,9 @@ sub handler { $cprefs->set('artwork', $artwork); $client->display->modes($client->display->build_modes); $client->display->update; + + # force update + Plugins::SqueezeESP32::Plugin::update_artwork($client, 1) if $artwork->{'enable'}; } # as there is nothing captured, we need to re-set these variables diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm index 22a462d6..37dcc055 100644 --- a/plugin/SqueezeESP32/Plugin.pm +++ b/plugin/SqueezeESP32/Plugin.pm @@ -33,38 +33,44 @@ sub initPlugin { Slim::Networking::Slimproto::addPlayerClass($class, 100, 'squeezeesp32', { client => 'Plugins::SqueezeESP32::Player', display => 'Plugins::SqueezeESP32::Graphics' }); $log->info("Added class 100 for SqueezeESP32"); - Slim::Control::Request::subscribe(\&update_artwork, [ ['newmetadata'] ] ); - Slim::Control::Request::subscribe(\&update_artwork, [ ['playlist'], ['open', 'newsong'] ]); + Slim::Control::Request::subscribe(\&onNotification, [ ['newmetadata'] ] ); + Slim::Control::Request::subscribe(\&onNotification, [ ['playlist'], ['open', 'newsong'] ]); +} + +sub onNotification { + my $request = shift; + my $client = $request->client; + + my $reqstr = $request->getRequestString(); + $log->info("artwork update notification $reqstr"); + #my $path = $request->getParam('_path'); + + update_artwork($client); } sub update_artwork { - my $request = shift; - my $client = $request->client; + my $client = shift; + my $force = shift || 0; my $cprefs = $prefs->client($client); my $artwork = $cprefs->get('artwork'); return unless $client->model eq 'squeezeesp32' && $artwork->{'enable'}; - my $reqstr = $request->getRequestString(); - #my $path = $request->getParam('_path'); - my $s = $artwork->{'y'} >= 32 ? $cprefs->get('height') - $artwork->{'y'} : 32; $s = min($s, $cprefs->get('width') - $artwork->{'x'}); my $path = 'music/current/cover_' . $s . 'x' . $s . '_o.jpg'; - my $body = Slim::Web::Graphics::artworkRequest($client, $path, undef, \&send_artwork, undef, HTTP::Response->new); + my $body = Slim::Web::Graphics::artworkRequest($client, $path, $force, \&send_artwork, undef, HTTP::Response->new); send_artwork($client, undef, \$body) if $body; - - $log->info("artwork update notification $reqstr with $path"); } sub send_artwork { - my ($client, $params, $dataref) = @_; + my ($client, $force, $dataref) = @_; # I'm not sure why we are called so often, so only send when needed my $md5 = md5($$dataref); - return if $client->pluginData('artwork_md5') eq $md5; + return if $client->pluginData('artwork_md5') eq $md5 && !$force; $client->pluginData('artwork', $dataref); $client->pluginData('artwork_md5', $md5); diff --git a/plugin/SqueezeESP32/SqueezeESP32.zip b/plugin/SqueezeESP32/SqueezeESP32.zip deleted file mode 100644 index 2a3b0eebcdb365ef11b617d71d3ffef688565697..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7772 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 PLUGIN_SQUEEZEESP32_DESC Plugins::SqueezeESP32::Plugin - 0.40 + 0.41 Philippe diff --git a/plugin/repo.xml b/plugin/repo.xml index e0c81729..41953d0e 100644 --- a/plugin/repo.xml +++ b/plugin/repo.xml @@ -1,10 +1,10 @@ - + https://github.com/sle118/squeezelite-esp32 Philippe - aa122a85db949c903ffa978d3e3b4ee3205e4ec2 + 88ecf433757f057351bcb88461c1db040caef884 philippe_44@outlook.com SqueezeESP32 additional player id (100) http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip From 755386c6eccc6b85a925cb541e252c6758cf6fdd Mon Sep 17 00:00:00 2001 From: philippe44 Date: Thu, 19 Mar 2020 16:23:36 -0700 Subject: [PATCH 5/7] html file was not updated --- plugin/SqueezeESP32.zip | Bin 7873 -> 7981 bytes .../plugins/SqueezeESP32/settings/player.html | 9 +++++++++ plugin/SqueezeESP32/install.xml | 2 +- plugin/repo.xml | 4 ++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip index cf1d7f509cfddcf36ec54844612cc4fc24675e57..2be3682231bb331f45d0b4c77ce8a9edbbf6990b 100644 GIT binary patch delta 986 zcmV<0110>yJ*_^l+6NN*v~o}>eus`50ssIx2><{w0Fyx*ACu1;36oG93xBPaU2mH( z6o#*pU*TEm?vib-dRHRR#NDE$DT8F$I!%ZVXF=sl*sL(^$M*msK$3#n=FV_lAHU~0 z2jpL8NKx;`MAHzXoICy>_F+Q}n?}P8_gr-LyWj7DXr;=ELex@(xWip4VP&@bJe}*> zwglNjexxSiC7GE&3DSxwC1p0(%W1Qvh^{(Cx23L+B#vJi9gtVL{9HR()1iqUh z%QYC2Fyl709SHb_2cj^dYyHu&`357$mhg7@*KlKqg6B-YhLsEs!-zTmAbNpEgTV-n zJ}%2kCi6+Yd};mKtvs9Q-3^;``^gASP43+^e0y8eVL+^?OnJf~x>@d5T?~?_dN)k3N3)Kb zWUBXqVAk>Jxyb5bb*FwUV6;j^KBrPj=JNGS;7hVL)Os+3qyfx`_+t<~=+rmN>~8~y zO>cHUD#5T2KyH-hp*Grq7zvpC(e1CZxuw^n=xOy>wepzrq%qdPb1Y)^=LyZGO|xl- z*|ctUf86@VZbj=L;I&)P6HrS71QY-O00;olf^$$~+&D#(;0Y&x)DfZF$tYSx5UGT5 z;ikm)ItKHoNjg-2z3FS}z%0)>U+yCp)~%A!4y_YLuj2D$5l7B*U2$nNuHqkb@tU5V z0Ja`=2f3i42rB&Gjr7cOj}$e3mskP$?+zR)E+nl#g%ov-#d3LL8ZV9cN=l=E^zlG? zZnx-f>spGE`_QR>w?m+WejNs+*U1%-y`Bl)PR?1#M>Xf7qD%_K(1uNc1le~a$6JEt z3Tghdd3by-*vlr%-m;A4mlr^~WZK`AR@B|2V`y=ou{$6mHJ4VVYGf!bo2}3;P1$#Y z_>29UG#zXp12s**8<$xm%P>Nx_T@^8+#5^t@qdAgPIoc{a&WUhvk43T5Dxpaa!@IL zhmIQp0021&lNKCN1}Gb-(6IfJZ5$pT(SmbOW864J5&-}J>Hz=%3jibl00000001BW z0024)ldBvV1;=fmL`9Ry96bSblLsAI0vHaHV;x}u(38a-S^;m9ARb%-Tp5#o9z6yT I8UO$Q03+nZ>Hq)$ delta 882 zcmV-&1C9KxKEXY(+6NK0nPpH0azYTV0RRBX1^@stlWYedlM4tHf0bWvf-n@tpY>C8 zO}01PALE;tIPEqQbqr)CE(<{@lLU~^vgxu9zYB%!&0NZjp=NN@B$IN#Z$aD?HB+R%)Ee9ID z;ejX!sjYuG7N26|SQ1{ApN1Pj7iNwHth$!LVHh#z8@e^ztW=tC^nO`lnG8Bf`CtEP zzt!vMuUd+rShGnXN5GG~2@Nsw9ACn>H&7UJ3E?_ajMG5Ee|20yg?WbS!uBbc?CB3S zSv!yCGz2nf4;8JitL;{gq##6;r{F+EJOXO+F!FR}8ZJ$##X+c=CmR#ri|#arC*eQVG; z>^T0(2&N{PLw#cS*3#5&L(EjHJY$F+v~AaEkVMt1FddJ^j`C#I?*+lwkpP$SzH7>! z&G^PO^$So-0|XQR000O8E^l*CaMJAllS~RHe?~`yawnr`5kaI9#)X>_+v^z2qbBK4 z{q?4=slqJJIbZH07dEYu(H^Z6Mz7;#vWO$+xvsc08rShRx_CoRPXJqwx`SL$Q3Msf z^G15+xkrkcze%is{B;Ko6&I4$A3}<{#$vU)HjS6Yd?uw)K>BzfJ-0jbH+3yV$$jY5 zf7>BYLca_H(yQbW$U)BpZztz0d2+}=Mt73_JN zWv^Mr@{4mIT{7+ON-OH_(J{2R%h)ZDk(x^@Q#CRam(5OSm!|BiLHxn~O_~likb#<} z-;c{IlGPGOrw-*xi`*Ma^YMRyj81nl2=eb{zfem91d~o37_*TJ;}8zFnPpH0azYTV z0RRBX29tsuQ3m=dFWp@8li3^|2rh4PP;k=h{*(V479h?E003!jb97;BY%X|hYzhD% z000000096P0GAKf{xFj@9X$aFlXD$f0;~;_&mCa_WRo!-S^)!-j2>J9@EDWo9z6!7 I82|tP0L#pfN&o-= diff --git a/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html b/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html index 17589674..5c0520fe 100644 --- a/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html +++ b/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html @@ -24,5 +24,14 @@ [% END %] + [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_ARTWORK" desc="PLUGIN_SQUEEZEESP32_ARTWORK_DESC" %] + [% "PLUGIN_SQUEEZEESP32_ARTWORK_ENABLE" | string %]  + + [% "PLUGIN_SQUEEZEESP32_ARTWORK_X" | string %]  + + [% "PLUGIN_SQUEEZEESP32_ARTWORK_Y" | string %]  + + [% END %] + [% PROCESS settings/footer.html %] diff --git a/plugin/SqueezeESP32/install.xml b/plugin/SqueezeESP32/install.xml index f2c4e542..48055b55 100644 --- a/plugin/SqueezeESP32/install.xml +++ b/plugin/SqueezeESP32/install.xml @@ -10,6 +10,6 @@ PLUGIN_SQUEEZEESP32 PLUGIN_SQUEEZEESP32_DESC Plugins::SqueezeESP32::Plugin - 0.41 + 0.42 Philippe diff --git a/plugin/repo.xml b/plugin/repo.xml index 41953d0e..99cd1761 100644 --- a/plugin/repo.xml +++ b/plugin/repo.xml @@ -1,10 +1,10 @@ - + https://github.com/sle118/squeezelite-esp32 Philippe - 88ecf433757f057351bcb88461c1db040caef884 + 91e09e914be97b25d258f257bf999a97700b0c55 philippe_44@outlook.com SqueezeESP32 additional player id (100) http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip From b5199650ff7f5a30b9c35776092dcb690f00b9cb Mon Sep 17 00:00:00 2001 From: philippe44 Date: Thu, 19 Mar 2020 17:16:43 -0700 Subject: [PATCH 6/7] notification correction --- plugin/SqueezeESP32.zip | Bin 7981 -> 7987 bytes plugin/SqueezeESP32/Plugin.pm | 4 ++-- plugin/SqueezeESP32/install.xml | 2 +- plugin/repo.xml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip index 2be3682231bb331f45d0b4c77ce8a9edbbf6990b..1f183d0fdba213b88a47c237d37269544a109314 100644 GIT binary patch delta 1532 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 diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm index 37dcc055..8d070910 100644 --- a/plugin/SqueezeESP32/Plugin.pm +++ b/plugin/SqueezeESP32/Plugin.pm @@ -33,8 +33,8 @@ sub initPlugin { Slim::Networking::Slimproto::addPlayerClass($class, 100, 'squeezeesp32', { client => 'Plugins::SqueezeESP32::Player', display => 'Plugins::SqueezeESP32::Graphics' }); $log->info("Added class 100 for SqueezeESP32"); - Slim::Control::Request::subscribe(\&onNotification, [ ['newmetadata'] ] ); - Slim::Control::Request::subscribe(\&onNotification, [ ['playlist'], ['open', 'newsong'] ]); + Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['newmetadata'] ] ); + Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['playlist'], ['open', 'newsong'] ]); } sub onNotification { diff --git a/plugin/SqueezeESP32/install.xml b/plugin/SqueezeESP32/install.xml index 48055b55..dbf8d9d4 100644 --- a/plugin/SqueezeESP32/install.xml +++ b/plugin/SqueezeESP32/install.xml @@ -10,6 +10,6 @@ PLUGIN_SQUEEZEESP32 PLUGIN_SQUEEZEESP32_DESC Plugins::SqueezeESP32::Plugin - 0.42 + 0.43 Philippe diff --git a/plugin/repo.xml b/plugin/repo.xml index 99cd1761..de7f3051 100644 --- a/plugin/repo.xml +++ b/plugin/repo.xml @@ -1,10 +1,10 @@ - + https://github.com/sle118/squeezelite-esp32 Philippe - 91e09e914be97b25d258f257bf999a97700b0c55 + 3460f07b43dcdb2cbdf4d10e6536da7abd87b3a1 philippe_44@outlook.com SqueezeESP32 additional player id (100) http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip From ff40290610320486e583f3dfb2afd0031e23d828 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Fri, 20 Mar 2020 23:55:26 -0700 Subject: [PATCH 7/7] handle "generic" visualizer - release --- components/squeezelite/display.c | 153 +++++++++++++++++++++----- plugin/SqueezeESP32.zip | Bin 7987 -> 7995 bytes plugin/SqueezeESP32/Graphics.pm | 24 ++-- plugin/SqueezeESP32/Player.pm | 10 +- plugin/SqueezeESP32/PlayerSettings.pm | 8 +- plugin/SqueezeESP32/Plugin.pm | 6 + plugin/SqueezeESP32/install.xml | 2 +- plugin/repo.xml | 4 +- 8 files changed, 154 insertions(+), 53 deletions(-) diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index cace344e..b20f1be5 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -86,6 +86,29 @@ struct visu_packet { u32_t bars; u32_t spectrum_scale; }; + struct { + u32_t mono; + u32_t bandwidth; + u32_t preemph; + struct { + u32_t pos; + u32_t width; + u32_t orient; + u32_t bar_width; + u32_t bar_space; + u32_t clipping; + u32_t bar_intens; + u32_t bar_cap_intens; + } channels[2]; + }; + struct { + u32_t mono; + u32_t style; + struct { + u32_t pos; + u32_t width; + } channels[2]; + } classical_vu; }; }; @@ -143,9 +166,11 @@ static struct { u8_t *data; u32_t size; u16_t x, y; + bool enable; } artwork; #define MAX_BARS 32 +#define VISU_ESP32 0x10 static EXT_RAM_ATTR struct { int bar_gap, bar_width, bar_border; struct { @@ -157,6 +182,11 @@ static EXT_RAM_ATTR struct { enum { VISU_BLANK, VISU_VUMETER, VISU_SPECTRUM, VISU_WAVEFORM } mode; int speed, wake; float fft[FFT_LEN*2], samples[FFT_LEN*2], hanning[FFT_LEN]; + struct { + u8_t *frame; + int width; + bool active; + } back; } visu; #define ANIM_NONE 0x00 @@ -221,6 +251,33 @@ static void displayer_task(void* arg); ANIM_SCREEN_2 0x08 # For scrollonce only, screen 2 was scrolling */ +/* classical visu not our specific version) + Parameters for the spectrum analyzer: + 0 - Channels: stereo == 0, mono == 1 + 1 - Bandwidth: 0..22050Hz == 0, 0..11025Hz == 1 + 2 - Preemphasis in dB per KHz + Left channel parameters: + 3 - Position in pixels + 4 - Width in pixels + 5 - orientation: left to right == 0, right to left == 1 + 6 - Bar width in pixels + 7 - Bar spacing in pixels + 8 - Clipping: show all subbands == 0, clip higher subbands == 1 + 9 - Bar intensity (greyscale): 1-3 + 10 - Bar cap intensity (greyscale): 1-3 + Right channel parameters (not required for mono): + 11-18 - same as left channel parameters + + Parameters for the vumeter: + 0 - Channels: stereo == 0, mono == 1 + 1 - Style: digital == 0, analog == 1 + Left channel parameters: + 2 - Position in pixels + 3 - Width in pixels + Right channel parameters (not required for mono): + 4-5 - same as left channel parameters +*/ + /**************************************************************************************** * */ @@ -242,6 +299,7 @@ bool sb_display_init(void) { // create visu configuration visu.bar_gap = 1; visu.speed = 100; + visu.back.frame = calloc(1, (displayer.width * displayer.height) / 8); dsps_fft2r_init_fc32(visu.fft, FFT_LEN); dsps_wind_hann_f32(visu.hanning, FFT_LEN); @@ -517,7 +575,7 @@ static void grfe_handler( u8_t *data, int len) { scroller.active = false; // we are not in control or we are displaying visu on a small screen, do not do screen update - if (visu.mode && !visu.col && visu.row < SB_HEIGHT) { + if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < SB_HEIGHT) { xSemaphoreGive(displayer.mutex); return; } @@ -531,6 +589,16 @@ static void grfe_handler( u8_t *data, int len) { // draw new frame, it might be less than full screen (small visu) int width = ((len - sizeof(struct grfe_packet)) * 8) / displayer.height; + + // when doing screensaver, that frame becomes a visu background + if (!(visu.mode & VISU_ESP32)) { + visu.back.width = width; + memset(visu.back.frame, 0, (displayer.width * displayer.height) / 8); + memcpy(visu.back.frame, data + sizeof(struct grfe_packet), (width * displayer.height) / 8); + // this is a bit tricky but basically that checks if frame if full of 0 + visu.back.active = *visu.back.frame || memcmp(visu.back.frame, visu.back.frame + 1, width - 1); + } + GDS_DrawBitmapCBR(display, data + sizeof(struct grfe_packet), width, displayer.height, GDS_COLOR_WHITE); GDS_Update(display); } @@ -570,7 +638,7 @@ static void grfs_handler(u8_t *data, int len) { int size = len - sizeof(struct grfs_packet); int offset = htons(pkt->offset); - LOG_DEBUG("gfrs s:%u d:%u p:%u sp:%u by:%hu m:%hu w:%hu o:%hu", + LOG_DEBUG("grfs s:%u d:%u p:%u sp:%u by:%hu m:%hu w:%hu o:%hu", (int) pkt->screen, (int) pkt->direction, // 1=left, 2=right htonl(pkt->pause), // in ms @@ -666,6 +734,14 @@ static void grfa_handler(u8_t *data, int len) { int offset = htonl(pkt->offset); int length = htonl(pkt->length); + artwork.enable = (length != 0); + + // clean up if we are disabling previously enabled artwork + if (!artwork.enable) { + if (artwork.size) GDS_ClearWindow(display, artwork.x, artwork.y, -1, -1, GDS_COLOR_BLACK); + return; + } + // new grfa artwork, allocate memory if (!offset) { // same trick to clean current/previous window @@ -679,7 +755,6 @@ static void grfa_handler(u8_t *data, int len) { artwork.y = htons(pkt->y); if (artwork.data) free(artwork.data); artwork.data = malloc(length); - artwork.size = 0; } // copy artwork data @@ -687,7 +762,7 @@ static void grfa_handler(u8_t *data, int len) { artwork.size += size; if (artwork.size == length) { GDS_ClearWindow(display, artwork.x, artwork.y, -1, -1, GDS_COLOR_BLACK); - GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < 32 ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); + GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < SB_HEIGHT ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); free(artwork.data); artwork.data = NULL; } @@ -701,9 +776,11 @@ static void grfa_handler(u8_t *data, int len) { static void visu_update(void) { // no need to protect against no woning the display as we are playing if (pthread_mutex_trylock(&visu_export.mutex)) return; + + int mode = visu.mode & ~VISU_ESP32; // not enough samples - if (visu_export.level < (visu.mode == VISU_VUMETER ? RMS_LEN : FFT_LEN) * 2 && visu_export.running) { + if (visu_export.level < (mode == VISU_VUMETER ? RMS_LEN : FFT_LEN) * 2 && visu_export.running) { pthread_mutex_unlock(&visu_export.mutex); return; } @@ -713,7 +790,7 @@ static void visu_update(void) { if (visu_export.running) { - if (visu.mode == VISU_VUMETER) { + if (mode == VISU_VUMETER) { s16_t *iptr = visu_export.buffer; // calculate sum(L²+R²), try to not overflow at the expense of some precision @@ -726,7 +803,7 @@ static void visu_update(void) { // convert to dB (1 bit remaining for getting X²/N, 60dB dynamic starting from 0dBFS = 3 bits back-off) for (int i = visu.n; --i >= 0;) { - visu.bars[i].current = 32 * (0.01667f*10*log10f(0.0000001f + (visu.bars[i].current >> 1)) - 0.2543f); + visu.bars[i].current = SB_HEIGHT * (0.01667f*10*log10f(0.0000001f + (visu.bars[i].current >> 1)) - 0.2543f); if (visu.bars[i].current > 31) visu.bars[i].current = 31; else if (visu.bars[i].current < 0) visu.bars[i].current = 0; } @@ -768,7 +845,7 @@ static void visu_update(void) { } // convert to dB and bars, same back-off - if (power) visu.bars[i].current = 32 * (0.01667f*10*(log10f(power) - log10f(FFT_LEN/2*2)) - 0.2543f); + if (power) visu.bars[i].current = SB_HEIGHT * (0.01667f*10*(log10f(power) - log10f(FFT_LEN/2*2)) - 0.2543f); if (visu.bars[i].current > 31) visu.bars[i].current = 31; else if (visu.bars[i].current < 0) visu.bars[i].current = 0; } @@ -783,6 +860,11 @@ static void visu_update(void) { int clear = 0; for (int i = visu.n; --i >= 0;) clear = max(clear, visu.bars[i].max); if (clear) GDS_ClearExt(display, false, false, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); + + // draw background if we are in screensaver mode + if (!(visu.mode & VISU_ESP32) && visu.back.active) { + GDS_DrawBitmapCBR(display, visu.back.frame, visu.back.width, displayer.height, GDS_COLOR_WHITE); + } // there is much more optimization to be done here, like not redrawing bars unless needed for (int i = visu.n; --i >= 0;) { @@ -840,31 +922,44 @@ static void visu_handler( u8_t *data, int len) { if (visu.row >= SB_HEIGHT) GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); if (visu.mode) { - if (pkt->count >= 4) { - // small visu, then go were we are told to - pkt->height = htonl(pkt->height); - pkt->row = htonl(pkt->row); - pkt->col = htonl(pkt->col); + // these will be overidden if necessary + visu.col = visu.border = 0; + visu.width = displayer.width; + + // what type of visu + if (visu.mode & VISU_ESP32) { + if (pkt->count >= 4) { + // more than 4 parameters, this is small visu, then go were we are told to + pkt->height = htonl(pkt->height); + pkt->row = htonl(pkt->row); + pkt->col = htonl(pkt->col); - visu.width = htonl(pkt->width); - visu.height = pkt->height ? pkt->height : SB_HEIGHT; - visu.col = pkt->col < 0 ? displayer.width + pkt->col : pkt->col; - visu.row = pkt->row < 0 ? GDS_GetHeight(display) + pkt->row : pkt->row; - visu.border = htonl(pkt->border); - bars = htonl(pkt->bars); - visu.spectrum_scale = htonl(pkt->spectrum_scale) / 100.; + visu.width = htonl(pkt->width); + visu.height = pkt->height ? pkt->height : SB_HEIGHT; + visu.col = pkt->col < 0 ? displayer.width + pkt->col : pkt->col; + visu.row = pkt->row < 0 ? GDS_GetHeight(display) + pkt->row : pkt->row; + visu.border = htonl(pkt->border); + bars = htonl(pkt->bars); + visu.spectrum_scale = htonl(pkt->spectrum_scale) / 100.; + } else { + // full screen visu, try to use bottom screen if available + visu.height = GDS_GetHeight(display) > SB_HEIGHT ? GDS_GetHeight(display) - SB_HEIGHT : GDS_GetHeight(display); + bars = htonl(pkt->full.bars); + visu.spectrum_scale = htonl(pkt->full.spectrum_scale) / 100.; + visu.row = GDS_GetHeight(display) - visu.height; + } } else { - // full screen visu, try to use bottom screen if available - visu.width = displayer.width; - visu.height = GDS_GetHeight(display) > SB_HEIGHT ? GDS_GetHeight(display) - SB_HEIGHT : GDS_GetHeight(display); - visu.col = visu.border = 0; - visu.row = GDS_GetHeight(display) - visu.height; - bars = htonl(pkt->full.bars); - visu.spectrum_scale = htonl(pkt->full.spectrum_scale) / 100.; - } + // classical (screensaver) mode, don't try to optimize screen usage & force some params + visu.row = 0; + visu.height = SB_HEIGHT; + visu.spectrum_scale = 0.25; + if (artwork.enable && artwork.y < SB_HEIGHT) visu.width = artwork.x - 1; + if (visu.mode == VISU_SPECTRUM) bars = visu.width / (htonl(pkt->channels[0].bar_width) + htonl(pkt->channels[0].bar_space)); + if (bars > MAX_BARS) bars = MAX_BARS; + } // try to adapt to what we have - if (visu.mode == VISU_SPECTRUM) { + if ((visu.mode & ~VISU_ESP32) == VISU_SPECTRUM) { visu.n = bars ? bars : MAX_BARS; if (visu.spectrum_scale <= 0 || visu.spectrum_scale > 0.5) visu.spectrum_scale = 0.5; spectrum_limits(0, visu.n, 0); diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip index 1f183d0fdba213b88a47c237d37269544a109314..239a3142e3eebd58fd808a9ea9bf0e730d8fba4f 100644 GIT binary patch delta 4976 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 O9x=!O8EOB%;(q~!2RvZ_ delta 5016 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 XCmk_accessor('array', 'modes'); @@ -72,7 +74,7 @@ sub displayWidth { if ($display->widthOverride) { my $artwork = $prefs->client($client)->get('artwork'); - if ($artwork->{'enable'} && $artwork->{'y'} < 32) { + if ($artwork->{'enable'} && $artwork->{'y'} < 32 && $client->isPlaying) { return $artwork->{x} + ($display->modes->[$mode || 0]{_width} || 0); } else { return $display->widthOverride + ($display->modes->[$mode || 0]{_width} || 0); @@ -105,7 +107,7 @@ sub build_modes { my $client = shift->client; my $cprefs = $prefs->client($client); - my $width = shift || $cprefs->get('width') || 128; + my $width = $cprefs->get('width') || 128; my $artwork = $cprefs->get('artwork'); # if artwork is in main display, reduce width @@ -154,39 +156,39 @@ sub build_modes { { desc => ['VISUALIZER_VUMETER_SMALL'], bar => 0, secs => 0, width => $width, _width => -$small_VU_pos->{'width'}, # extra parameters (width, height, col (< 0 = from right), row (< 0 = from bottom), left_space) - params => [$VISUALIZER_VUMETER, $small_VU_pos->{'width'}, 32, $small_VU_pos->{'x'}, 0, 2] }, + params => [$VISUALIZER_VUMETER_ESP32, $small_VU_pos->{'width'}, 32, $small_VU_pos->{'x'}, 0, 2] }, # mode 8 { desc => ['VISUALIZER_SPECTRUM_ANALYZER_SMALL'], bar => 0, secs => 0, width => $width, _width => -$small_spectrum_pos->{'width'}, - # extra parameters (width, height, col (< 0 = from right), row (< 0 = from bottom), left_space, bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER, $small_spectrum_pos->{width}, 32, $small_spectrum_pos->{'x'}, 0, 2, $small_spectrum_pos->{'width'} / $spectrum->{small}->{band}, $spectrum->{scale}] }, + # extra parameters (width, height, col (< 0 = from right), row (< 0 = from bottom), left_space, #bars, scale) + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, $small_spectrum_pos->{width}, 32, $small_spectrum_pos->{'x'}, 0, 2, $small_spectrum_pos->{'width'} / $spectrum->{small}->{band}, $spectrum->{scale}] }, # mode 9 { desc => ['VISUALIZER_VUMETER'], bar => 0, secs => 0, width => $width, - params => [$VISUALIZER_VUMETER] }, + params => [$VISUALIZER_VUMETER_ESP32] }, # mode 10 { desc => ['VISUALIZER_SPECTRUM_ANALYZER'], bar => 0, secs => 0, width => $width, # extra parameters (bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, # mode 11 { desc => ['VISUALIZER_VUMETER', 'AND', 'ELAPSED'], bar => 0, secs => 1, width => $width, - params => [$VISUALIZER_VUMETER] }, + params => [$VISUALIZER_VUMETER_ESP32] }, # mode 12 { desc => ['VISUALIZER_SPECTRUM_ANALYZER', 'AND', 'ELAPSED'], bar => 0, secs => 1, width => $width, # extra parameters (bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, # mode 13 { desc => ['VISUALIZER_VUMETER', 'AND', 'REMAINING'], bar => 0, secs => -1, width => $width, - params => [$VISUALIZER_VUMETER] }, + params => [$VISUALIZER_VUMETER_ESP32] }, # mode 14 { desc => ['VISUALIZER_SPECTRUM_ANALYZER', 'AND', 'REMAINING'], bar => 0, secs => -1, width => $width, # extra parameters (bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, ); return \@modes; diff --git a/plugin/SqueezeESP32/Player.pm b/plugin/SqueezeESP32/Player.pm index e0e6a3b7..3ae11b17 100644 --- a/plugin/SqueezeESP32/Player.pm +++ b/plugin/SqueezeESP32/Player.pm @@ -26,7 +26,7 @@ sub playerSettingsFrame { $value = (unpack('Cn', $$data_ref))[1]; if ($value > 100 && $value < 400) { $prefs->client($client)->set('width', $value); - $client->display->modes($client->display->build_modes($value)); + $client->display->modes($client->display->build_modes); $client->display->widthOverride(1, $value); $client->update; } @@ -38,7 +38,7 @@ sub playerSettingsFrame { $client->SUPER::playerSettingsFrame($data_ref); } -sub hasScrolling { +sub hasScrolling { return 1; } @@ -48,10 +48,4 @@ sub reconnect { $client->SUPER::reconnect(@_); } -sub directMetadata { - my $client = shift; - $client->SUPER::directMetadata(@_); - Slim::Control::Request::notifyFromArray( $client, [ 'newmetadata' ] ); -} - 1; diff --git a/plugin/SqueezeESP32/PlayerSettings.pm b/plugin/SqueezeESP32/PlayerSettings.pm index 4fd57722..eb95f098 100644 --- a/plugin/SqueezeESP32/PlayerSettings.pm +++ b/plugin/SqueezeESP32/PlayerSettings.pm @@ -55,8 +55,12 @@ sub handler { $client->display->modes($client->display->build_modes); $client->display->update; - # force update - Plugins::SqueezeESP32::Plugin::update_artwork($client, 1) if $artwork->{'enable'}; + # force update or disable artwork + if ($artwork->{'enable'}) { + Plugins::SqueezeESP32::Plugin::update_artwork($client, 1); + } else { + Plugins::SqueezeESP32::Plugin::disable_artwork($client); + } } # as there is nothing captured, we need to re-set these variables diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm index 8d070910..3e845542 100644 --- a/plugin/SqueezeESP32/Plugin.pm +++ b/plugin/SqueezeESP32/Plugin.pm @@ -95,4 +95,10 @@ sub send_artwork { } } +sub disable_artwork { + my ($client) = @_; + my $header = pack('N', 0); + $client->sendFrame( grfa => \$header ); +} + 1; diff --git a/plugin/SqueezeESP32/install.xml b/plugin/SqueezeESP32/install.xml index dbf8d9d4..d28e7f08 100644 --- a/plugin/SqueezeESP32/install.xml +++ b/plugin/SqueezeESP32/install.xml @@ -10,6 +10,6 @@ PLUGIN_SQUEEZEESP32 PLUGIN_SQUEEZEESP32_DESC Plugins::SqueezeESP32::Plugin - 0.43 + 0.50 Philippe diff --git a/plugin/repo.xml b/plugin/repo.xml index de7f3051..b0266385 100644 --- a/plugin/repo.xml +++ b/plugin/repo.xml @@ -1,10 +1,10 @@ - + https://github.com/sle118/squeezelite-esp32 Philippe - 3460f07b43dcdb2cbdf4d10e6536da7abd87b3a1 + 47feaf69a40ad4f87c58b34212d71e60dca99d3e philippe_44@outlook.com SqueezeESP32 additional player id (100) http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip