diff --git a/components/display/SSD1322.c b/components/display/SSD1322.c new file mode 100644 index 00000000..ea449aea --- /dev/null +++ b/components/display/SSD1322.c @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2017-2018 Tara Keeling + * 2020 Philippe G. + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include + +#include "gds.h" +#include "gds_private.h" + +#define SHADOW_BUFFER +#define PAGE_BLOCK 1024 + +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +static char TAG[] = "SSD1322"; + +struct PrivateSpace { + uint8_t *iRAM, *Shadowbuffer; + uint8_t ReMap, PageSize; + uint8_t Offset; +}; + +// Functions are not declared to minimize # of lines + +static void WriteDataByte( struct GDS_Device* Device, uint8_t Data ) { + Device->WriteData( Device, &Data, 1); +} + +static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { + Device->WriteCommand( Device, 0x15 ); + Device->WriteData( Device, &Start, 1 ); + Device->WriteData( Device, &End, 1 ); +} +static void SetRowAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { + Device->WriteCommand( Device, 0x75 ); + Device->WriteData( Device, &Start, 1 ); + Device->WriteData( Device, &End, 1 ); +} + +static void Update( struct GDS_Device* Device ) { + struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; + + // RAM is by columns of 4 pixels ... + SetColumnAddress( Device, Private->Offset, Private->Offset + Device->Width / 4 - 1); + +#ifdef SHADOW_BUFFER + uint16_t *optr = (uint16_t*) Private->Shadowbuffer, *iptr = (uint16_t*) Device->Framebuffer; + bool dirty = false; + + for (int r = 0, page = 0; r < Device->Height; r++) { + // look for change and update shadow (cheap optimization = width always / by 2) + for (int c = Device->Width / 2 / 2; --c >= 0;) { + if (*optr != *iptr) { + dirty = true; + *optr = *iptr; + } + iptr++; optr++; + } + + // one line done, check for page boundary + if (++page == Private->PageSize) { + if (dirty) { + uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Private->Shadowbuffer + (r - page + 1) * Device->Width / 2); + SetRowAddress( Device, r - page + 1, r ); + for (int i = page * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8); + //memcpy(Private->iRAM, Private->Shadowbuffer + (r - page + 1) * Device->Width / 2, page * Device->Width / 2 ); + Device->WriteCommand( Device, 0x5c ); + Device->WriteData( Device, Private->iRAM, Device->Width * page / 2 ); + dirty = false; + } + page = 0; + } + } +#else + for (int r = 0; r < Device->Height; r += Private->PageSize) { + SetRowAddress( Device, r, r + Private->PageSize - 1 ); + Device->WriteCommand( Device, 0x5c ); + if (Private->iRAM) { + uint16_t *optr = (uint16_t*) Private->iRAM, *iptr = (uint16_t*) (Device->Framebuffer + r * Device->Width / 2); + for (int i = Private->PageSize * Device->Width / 2 / 2; --i >= 0; iptr++) *optr++ = (*iptr >> 8) | (*iptr << 8); + //memcpy(Private->iRAM, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); + Device->WriteData( Device, Private->iRAM, Private->PageSize * Device->Width / 2 ); + } else { + Device->WriteData( Device, Device->Framebuffer + r * Device->Width / 2, Private->PageSize * Device->Width / 2 ); + } + } +#endif +} + +static void SetHFlip( struct GDS_Device* Device, bool On ) { + struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; + Private->ReMap = On ? (Private->ReMap & ~(1 << 1)) : (Private->ReMap | (1 << 1)); + Device->WriteCommand( Device, 0xA0 ); + Device->WriteData( Device, &Private->ReMap, 1 ); + WriteDataByte( Device, 0x11 ); +} + +static void SetVFlip( struct GDS_Device *Device, bool On ) { + struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; + Private->ReMap = On ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4)); + Device->WriteCommand( Device, 0xA0 ); + Device->WriteData( Device, &Private->ReMap, 1 ); + WriteDataByte( Device, 0x11 ); +} + +static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } +static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } + +static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { + Device->WriteCommand( Device, 0xC1 ); + Device->WriteData( Device, &Contrast, 1 ); +} + +static bool Init( struct GDS_Device* Device ) { + struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private; + + // these displays seems to be layout centered (1 column = 4 pixels of 4 bits each, little endian) + Private->Offset = (480 - Device->Width) / 4 / 2; + + // find a page size that is not too small is an integer of height + Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2)); + Private->PageSize = Device->Height / (Device->Height / Private->PageSize) ; + +#ifdef SHADOW_BUFFER + Private->Shadowbuffer = malloc( Device->FramebufferSize ); + memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize); +#endif + Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); + + ESP_LOGI(TAG, "SSD1322 with offset %u, page %u, iRAM %p", Private->Offset, Private->PageSize, Private->iRAM); + + // need to be off and disable display RAM + Device->DisplayOff( Device ); + Device->WriteCommand( Device, 0xA5 ); + + // Display Offset + Device->WriteCommand( Device, 0xA2 ); + WriteDataByte( Device, 0 ); + + // Display Start Line + Device->WriteCommand( Device, 0xA1 ); + WriteDataByte( Device, 0x00 ); + + // set flip modes + Private->ReMap = 0; + Device->SetVFlip( Device, false ); + Device->SetHFlip( Device, false ); + + // set Clocks + Device->WriteCommand( Device, 0xB3 ); + WriteDataByte( Device, 0x91 ); + + // set MUX + Device->WriteCommand( Device, 0xCA ); + WriteDataByte( Device, Device->Height - 1 ); + + // phase 1 & 2 period (needed?) + Device->WriteCommand( Device, 0xB1 ); + WriteDataByte( Device, 0xE2 ); + + // set pre-charge V (needed?°) + Device->WriteCommand( Device, 0xBB ); + WriteDataByte( Device, 0x1F ); + + // set COM deselect voltage (needed?) + Device->WriteCommand( Device, 0xBE ); + WriteDataByte( Device, 0x07 ); + + // no Display Inversion + Device->WriteCommand( Device, 0xA6 ); + + // gone with the wind + Device->DisplayOn( Device ); + Device->Update( Device ); + + return true; +} + +static const struct GDS_Device SSD1322 = { + .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, + .SetVFlip = SetVFlip, .SetHFlip = SetHFlip, + .Update = Update, .Init = Init, +}; + +struct GDS_Device* SSD1322_Detect(char *Driver, struct GDS_Device* Device) { + if (!strcasestr(Driver, "SSD1322")) return NULL; + + if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); + + *Device = SSD1322; + Device->Depth = 4; + + return Device; +} \ No newline at end of file diff --git a/components/display/display.c b/components/display/display.c index 1da64344..82110397 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -59,8 +59,8 @@ static EXT_RAM_ATTR struct { static void displayer_task(void *args); struct GDS_Device *display; -extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect, SSD1675_Detect; -GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, SSD1675_Detect, NULL }; +extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect, SSD1675_Detect, SSD1322_Detect; +GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, SSD1675_Detect, SSD1322_Detect, NULL }; /**************************************************************************************** * diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index a7e36e4f..982c83cf 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -73,12 +73,15 @@ struct visu_packet { u8_t which; u8_t count; union { - union { - struct { + struct { + u32_t width; + union { + struct { u32_t bars; u32_t spectrum_scale; - }; - u32_t style; + }; + u32_t style; + }; } full; struct { u32_t width; @@ -613,22 +616,22 @@ static void grfe_handler( u8_t *data, int len) { scroller.active = false; // visu has priority when full screen on small screens - if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < SB_HEIGHT) { + if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) { xSemaphoreGive(displayer.mutex); return; } // are we in control if (displayer.owned) { - // did we have something that might have write on the bottom of a SB_HEIGHT+ display - if (displayer.dirty) { - GDS_ClearExt(display, true); + // draw new frame, it might be less than full screen (small visu) + int width = ((len - sizeof(struct grfe_packet)) * 8) / displayer.height; + + // did we have something that might have written on the bottom of a displayer's height + display + if (displayer.dirty || (artwork.enable && width == displayer.width && artwork.y < displayer.height)) { + GDS_Clear(display, GDS_COLOR_BLACK); displayer.dirty = false; } - // 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; @@ -735,7 +738,7 @@ static void grfg_handler(u8_t *data, int len) { LOG_DEBUG("gfrg s:%hu w:%hu (len:%u)", htons(pkt->screen), htons(pkt->width), len); // on small screen, visu has priority when full screen - if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < SB_HEIGHT) return; + if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) return; xSemaphoreTake(displayer.mutex, portMAX_DELAY); @@ -755,7 +758,7 @@ static void grfg_handler(u8_t *data, int len) { } // now we can active scrolling, but only if we are not on a small screen - if (!visu.mode || visu.col || visu.row >= SB_HEIGHT) scroller.active = true; + if (!visu.mode || visu.col || visu.row >= displayer.height) scroller.active = true; // if we just got a content update, let the scroller manage the screen LOG_DEBUG("resuming scrolling task"); @@ -811,7 +814,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 < SB_HEIGHT ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); + GDS_DrawJPEG(display, artwork.data, artwork.x, artwork.y, artwork.y < displayer.height ? (GDS_IMAGE_RIGHT | GDS_IMAGE_TOP) : GDS_IMAGE_CENTER); free(artwork.data); artwork.data = NULL; } @@ -852,7 +855,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 = SB_HEIGHT * (0.01667f*10*log10f(0.0000001f + (visu.bars[i].current >> 1)) - 0.2543f); + visu.bars[i].current = visu.max * (0.01667f*10*log10f(0.0000001f + (visu.bars[i].current >> 1)) - 0.2543f); if (visu.bars[i].current > visu.max) visu.bars[i].current = visu.max; else if (visu.bars[i].current < 0) visu.bars[i].current = 0; } @@ -894,7 +897,7 @@ static void visu_update(void) { } // convert to dB and bars, same back-off - if (power) visu.bars[i].current = SB_HEIGHT * (0.01667f*10*(log10f(power) - log10f(FFT_LEN/2*2)) - 0.2543f); + if (power) visu.bars[i].current = visu.max * (0.01667f*10*(log10f(power) - log10f(FFT_LEN/2*2)) - 0.2543f); if (visu.bars[i].current > visu.max) visu.bars[i].current = visu.max; else if (visu.bars[i].current < 0) visu.bars[i].current = 0; } @@ -934,11 +937,11 @@ static void visu_update(void) { } } } else if (displayer.width / 2 > 3 * VU_WIDTH / 4) { - draw_VU(display, vu_bitmap, visu.bars[0].current, 0, visu.row, displayer.width / 2); - draw_VU(display, vu_bitmap, visu.bars[1].current, displayer.width / 2, visu.row, displayer.width / 2); + draw_VU(display, vu_bitmap, visu.bars[0].current, 0, visu.row, visu.width / 2); + draw_VU(display, vu_bitmap, visu.bars[1].current, visu.width / 2, visu.row, visu.width / 2); } else { int level = (visu.bars[0].current + visu.bars[1].current) / 2; - draw_VU(display, vu_bitmap, level, 0, visu.row, displayer.width); + draw_VU(display, vu_bitmap, level, 0, visu.row, visu.width); } } @@ -976,12 +979,11 @@ 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 >= displayer.height) GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); if (visu.mode) { // these will be overidden if necessary visu.col = visu.border = 0; - visu.width = displayer.width; // what type of visu if (visu.mode & VISU_ESP32) { @@ -993,7 +995,7 @@ static void visu_handler( u8_t *data, int len) { visu.style = 0; visu.width = htonl(pkt->width); - visu.height = pkt->height ? pkt->height : SB_HEIGHT; + visu.height = pkt->height ? pkt->height : displayer.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); @@ -1001,7 +1003,8 @@ static void visu_handler( u8_t *data, int len) { 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); + visu.width = htonl(pkt->full.width); + visu.height = GDS_GetHeight(display) > displayer.height ? GDS_GetHeight(display) - displayer.height : GDS_GetHeight(display); visu.row = GDS_GetHeight(display) - visu.height; // is this spectrum or analogue/digital @@ -1016,22 +1019,27 @@ static void visu_handler( u8_t *data, int len) { } else { // classical (screensaver) mode, don't try to optimize screen usage & force some params visu.row = 0; - visu.height = SB_HEIGHT; + visu.height = GDS_GetHeight(display); + visu.width = displayer.width; visu.spectrum_scale = 0.25; - if (visu.mode == VISU_SPECTRUM) bars = visu.width / (htonl(pkt->channels[0].bar_width) + htonl(pkt->channels[0].bar_space)); - else visu.style = htonl(pkt->classical_vu.style); + if (visu.mode == VISU_SPECTRUM) { + bars = visu.width / (htonl(pkt->channels[0].bar_width) + htonl(pkt->channels[0].bar_space)); + } else { + visu.style = htonl(pkt->classical_vu.style); + if (visu.style) visu.row = visu.height - VU_HEIGHT; + } if (bars > MAX_BARS) bars = MAX_BARS; } // try to adapt to what we have if ((visu.mode & ~VISU_ESP32) == VISU_SPECTRUM) { visu.n = bars ? bars : MAX_BARS; - visu.max = displayer.height - 1; + visu.max = visu.height - 1; if (visu.spectrum_scale <= 0 || visu.spectrum_scale > 0.5) visu.spectrum_scale = 0.5; spectrum_limits(0, visu.n, 0); } else { visu.n = 2; - visu.max = visu.style ? (VU_COUNT - 1) : (displayer.height - 1); + visu.max = visu.style ? (VU_COUNT - 1) : (visu.height - 1); } do { @@ -1039,14 +1047,14 @@ static void visu_handler( u8_t *data, int len) { if (visu.bar_width > 0) break; } while (--visu.n); visu.bar_border = (visu.width - visu.border - (visu.bar_width + visu.bar_gap) * visu.n + visu.bar_gap) / 2; - + // give up if not enough space if (visu.bar_width < 0) { visu.mode = VISU_BLANK; LOG_WARN("Not enough room for displaying visu"); } else { // de-activate scroller if we are taking main screen - if (visu.row < SB_HEIGHT) scroller.active = false; + if (visu.row < displayer.height) scroller.active = false; vTaskResume(displayer.task); } visu.wake = 0; diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip index 8edf88e5..81d7585a 100644 Binary files a/plugin/SqueezeESP32.zip and b/plugin/SqueezeESP32.zip differ diff --git a/plugin/SqueezeESP32/Graphics.pm b/plugin/SqueezeESP32/Graphics.pm index 5506fdf7..43144ac3 100644 --- a/plugin/SqueezeESP32/Graphics.pm +++ b/plugin/SqueezeESP32/Graphics.pm @@ -77,7 +77,7 @@ sub displayWidth { if ($display->widthOverride) { my $artwork = $prefs->client($client)->get('artwork'); - if ($artwork->{'enable'} && $artwork->{'y'} < 32 && $client->isPlaying) { + if ($artwork->{'enable'} && $artwork->{'y'} < 32 && ($client->isPlaying || $client->isPaused)) { return $artwork->{x} + ($display->modes->[$mode || 0]{_width} || 0); } else { return $display->widthOverride + ($display->modes->[$mode || 0]{_width} || 0); @@ -168,45 +168,58 @@ sub build_modes { # mode 9 { desc => ['VISUALIZER_VUMETER'], bar => 0, secs => 0, width => $width, - params => [$VISUALIZER_VUMETER_ESP32, 0] }, + params => [$VISUALIZER_VUMETER_ESP32, $width, 0] }, # mode 10 { desc => ['VISUALIZER_ANALOG_VUMETER'], bar => 0, secs => 0, width => $width, - params => [$VISUALIZER_VUMETER_ESP32, 1] }, + params => [$VISUALIZER_VUMETER_ESP32, $width, 1] }, # mode 11 { desc => ['VISUALIZER_SPECTRUM_ANALYZER'], bar => 0, secs => 0, width => $width, # extra parameters (bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, $width, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, ); my @extra = ( # mode E1 { desc => ['VISUALIZER_VUMETER', 'AND', 'ELAPSED'], bar => 0, secs => 1, width => $width, - params => [$VISUALIZER_VUMETER_ESP32, 0] }, + params => [$VISUALIZER_VUMETER_ESP32, $width, 0] }, # mode E2 { desc => ['VISUALIZER_ANALOG_VUMETER', 'AND', 'ELAPSED'], bar => 0, secs => 1, width => $width, - params => [$VISUALIZER_VUMETER_ESP32, 1] }, + params => [$VISUALIZER_VUMETER_ESP32, $width, 1] }, # mode E3 { desc => ['VISUALIZER_SPECTRUM_ANALYZER', 'AND', 'ELAPSED'], bar => 0, secs => 1, width => $width, # extra parameters (bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, $width, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, # mode E4 { desc => ['VISUALIZER_VUMETER', 'AND', 'REMAINING'], bar => 0, secs => -1, width => $width, - params => [$VISUALIZER_VUMETER_ESP32, 0] }, + params => [$VISUALIZER_VUMETER_ESP32, $width, 0] }, # mode E5 { desc => ['VISUALIZER_ANALOG_VUMETER', 'AND', 'REMAINING'], bar => 0, secs => -1, width => $width, - params => [$VISUALIZER_VUMETER_ESP32, 1] }, + params => [$VISUALIZER_VUMETER_ESP32, $width, 1] }, # mode E6 { desc => ['VISUALIZER_SPECTRUM_ANALYZER', 'AND', 'REMAINING'], bar => 0, secs => -1, width => $width, # extra parameters (bars) - params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, $width, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, + # mode E7 + { desc => ['VISUALIZER_VUMETER', 'AND', 'PROGRESS_BAR', 'AND', 'REMAINING'], + bar => 1, secs => -1, width => $width, + params => [$VISUALIZER_VUMETER_ESP32, $width, 0] }, + # mode E8 + { desc => ['VISUALIZER_ANALOG_VUMETER', 'AND', 'PROGRESS_BAR', 'AND', 'REMAINING'], + bar => 1, secs => -1, width => $width, + params => [$VISUALIZER_VUMETER_ESP32, $width, 1] }, + # mode E9 + { desc => ['VISUALIZER_SPECTRUM_ANALYZER', 'AND', 'PROGRESS_BAR', 'AND', 'REMAINING'], + bar => 1, secs => -1, width => $width, + # extra parameters (bars) + params => [$VISUALIZER_SPECTRUM_ANALYZER_ESP32, $width, int ($width/$spectrum->{full}->{band}), $spectrum->{scale}] }, ); @modes = (@modes, @extra) if $cprefs->get('height') > 32; diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm index 36627ad0..dd9aee47 100644 --- a/plugin/SqueezeESP32/Plugin.pm +++ b/plugin/SqueezeESP32/Plugin.pm @@ -35,8 +35,22 @@ sub initPlugin { Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['newmetadata'] ] ); Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['playlist'], ['open', 'newsong'] ]); + Slim::Control::Request::subscribe( \&onStopClear, [ ['playlist'], ['stop', 'clear'] ]); } +sub onStopClear { + my $request = shift; + my $client = $request->client; + my $artwork = $prefs->client($client)->get('artwork'); + + if ($client->model eq 'squeezeesp32' && $artwork->{'enable'}) { + my $reqstr = $request->getRequestString(); + $log->info("artwork stop/clear $reqstr"); + $client->pluginData('artwork_md5', '') + } +} + + sub onNotification { my $request = shift; my $client = $request->client; @@ -56,8 +70,7 @@ sub update_artwork { return unless $client->model eq 'squeezeesp32' && $artwork->{'enable'}; - my $s = $artwork->{'y'} >= 32 ? $cprefs->get('height') - $artwork->{'y'} : 32; - $s = min($s, $cprefs->get('width') - $artwork->{'x'}); + my $s = min($cprefs->get('height') - $artwork->{'y'}, $cprefs->get('width') - $artwork->{'x'}); my $path = 'music/current/cover_' . $s . 'x' . $s . '_o.jpg'; my $body = Slim::Web::Graphics::artworkRequest($client, $path, $params, \&send_artwork, undef, HTTP::Response->new); diff --git a/plugin/SqueezeESP32/install.xml b/plugin/SqueezeESP32/install.xml index fd652e0f..9d5f45b6 100644 --- a/plugin/SqueezeESP32/install.xml +++ b/plugin/SqueezeESP32/install.xml @@ -10,6 +10,6 @@ PLUGIN_SQUEEZEESP32 PLUGIN_SQUEEZEESP32_DESC Plugins::SqueezeESP32::Plugin - 0.61 + 0.70 Philippe diff --git a/plugin/repo.xml b/plugin/repo.xml index 23c2d1b0..677847de 100644 --- a/plugin/repo.xml +++ b/plugin/repo.xml @@ -1,10 +1,10 @@ - + https://github.com/sle118/squeezelite-esp32 Philippe - 5c45fed832e6f79f709bef5f2da511071d1c776e + 2a8cb954928e0cd8f521acd94b90ce9f34a7a1f0 philippe_44@outlook.com SqueezeESP32 additional player id (100) http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip