1st artwork version

This commit is contained in:
philippe44
2020-03-18 23:42:44 -07:00
parent 126d3f4e04
commit 5e5dc9ba29
15 changed files with 158 additions and 79 deletions

View File

@@ -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 ) { 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 // driver can provide own optimized clear window
if (Device->ClearWindow) { if (Device->ClearWindow) {
Device->ClearWindow( Device, x1, y1, x2, y2, Color ); Device->ClearWindow( Device, x1, y1, x2, y2, Color );

View File

@@ -218,7 +218,9 @@ bool GDS_DrawJPEG( struct GDS_Device* Device, uint8_t *Source, int x, int y, int
// then place it // then place it
if (Fit & GDS_IMAGE_CENTER_X) Context.XOfs = (Device->Width + x - Context.Width) / 2; 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; 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.XMin = x - Context.XOfs;
Context.YMin = y - Context.YOfs; Context.YMin = y - Context.YOfs;

View File

@@ -9,8 +9,11 @@ struct GDS_Device;
enum { GDS_RGB565, GDS_RGB555, GDS_RGB444 }; 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_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_Y 0x02
#define GDS_IMAGE_CENTER (GDS_IMAGE_CENTER_X | GDS_IMAGE_CENTER_Y) #define GDS_IMAGE_CENTER (GDS_IMAGE_CENTER_X | GDS_IMAGE_CENTER_Y)
#define GDS_IMAGE_FIT 0x10 #define GDS_IMAGE_FIT 0x10

View File

@@ -63,6 +63,8 @@ struct grfg_packet {
struct grfa_packet { struct grfa_packet {
char opcode[4]; char opcode[4];
u32_t length; u32_t length;
u16_t x;
u16_t y;
u32_t offset; u32_t offset;
}; };
@@ -140,6 +142,7 @@ static struct scroller_s {
static struct { static struct {
u8_t *data; u8_t *data;
u32_t size; u32_t size;
u16_t x, y;
} artwork; } artwork;
#define MAX_BARS 32 #define MAX_BARS 32
@@ -313,7 +316,7 @@ static void send_server(void) {
pkt_header.length = htonl(sizeof(pkt_header) - 8); pkt_header.length = htonl(sizeof(pkt_header) - 8);
pkt_header.mode = ANIC_resp; 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; ANIC_resp = ANIM_NONE;
} }
@@ -321,17 +324,21 @@ static void send_server(void) {
if (SETD_width) { if (SETD_width) {
struct SETD_header pkt_header; struct SETD_header pkt_header;
LOG_INFO("sending width %u", SETD_width);
memset(&pkt_header, 0, sizeof(pkt_header)); memset(&pkt_header, 0, sizeof(pkt_header));
memcpy(&pkt_header.opcode, "SETD", 4); memcpy(&pkt_header.opcode, "SETD", 4);
pkt_header.id = 0xfe; // id 0xfe is width S:P:Squeezebox2 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); SETD_width = htons(SETD_width);
send_packet((u8_t *)&pkt_header, sizeof(pkt_header)); height = htons(height);
send_packet((uint8_t*) &SETD_width, 2);
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; SETD_width = 0;
} }
@@ -661,10 +668,10 @@ static void grfa_handler(u8_t *data, int len) {
int offset = htonl(pkt->offset); int offset = htonl(pkt->offset);
int length = htonl(pkt->length); int length = htonl(pkt->length);
LOG_INFO("gfra l:%u o:%u s:%u", length, offset, size);
// new grfa artwork, allocate memory // new grfa artwork, allocate memory
if (!offset) { if (!offset) {
artwork.x = htons(pkt->x);
artwork.y = htons(pkt->y);
if (artwork.data) free(artwork.data); if (artwork.data) free(artwork.data);
artwork.data = malloc(length); artwork.data = malloc(length);
artwork.size = 0; 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); memcpy(artwork.data + offset, data + sizeof(struct grfa_packet), size);
artwork.size += size; artwork.size += size;
if (artwork.size == length) { 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; visu.mode = pkt->which;
// little trick to clean the taller screens when switching visu // 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 (visu.mode) {
if (pkt->count >= 4) { if (pkt->count >= 4) {
@@ -878,7 +891,7 @@ static void visu_handler( u8_t *data, int len) {
// reset bars maximum // reset bars maximum
for (int i = visu.n; --i >= 0;) visu.bars[i].max = 0; 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); 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 { } else {

Binary file not shown.

View File

@@ -71,7 +71,12 @@ sub displayWidth {
} }
if ($display->widthOverride) { 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 { } else {
return $display->modes->[$mode || 0]{width}; return $display->modes->[$mode || 0]{width};
} }
@@ -101,9 +106,21 @@ sub build_modes {
my $cprefs = $prefs->client($client); my $cprefs = $prefs->client($client);
my $width = shift || $cprefs->get('width') || 128; 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 $small_VU = $cprefs->get('small_VU');
my $spectrum = $cprefs->get('spectrum'); 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 = ( my @modes = (
# mode 0 # mode 0
{ desc => ['BLANK'], { desc => ['BLANK'],
@@ -135,14 +152,14 @@ sub build_modes {
params => [$VISUALIZER_NONE] }, params => [$VISUALIZER_NONE] },
# mode 7 # mode 7
{ desc => ['VISUALIZER_VUMETER_SMALL'], { 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) # 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 # mode 8
{ desc => ['VISUALIZER_SPECTRUM_ANALYZER_SMALL'], { 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) # 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 # mode 9
{ desc => ['VISUALIZER_VUMETER'], { desc => ['VISUALIZER_VUMETER'],
bar => 0, secs => 0, width => $width, bar => 0, secs => 0, width => $width,

View File

@@ -1,20 +0,0 @@
[% PROCESS settings/header.html %]
[% WRAPPER setting title="PLUGIN_SQUEEZEESP32_BANNER" %]
<div>[% "PLUGIN_SQUEEZEESP32_BANNER_TEXT" | string %]</div>
[% END %]
<div class="prefDesc">
[% WRAPPER setting title="PLUGIN_SQUEEZEESP32_WIDTH" desc="PLUGIN_SQUEEZEESP32_WIDTH_DESC" %]
<input type="text" class="stdedit" name="pref_width" id="pref_width" value="[% prefs.pref_width %]" size="3">
[% END %]
[% WRAPPER setting title="PLUGIN_SQUEEZEESP32_SPECTRUM_SCALE" desc="PLUGIN_SQUEEZEESP32_SPECTRUM_SCALE_DESC" %]
<input type="number" min="10" max= "50" step="5" class="stdedit" name="pref_spectrum_scale" id="pref_spectrum_scale" value="[% prefs.pref_spectrum_scale %]" size="3">
[% END %]
</div>
[% PROCESS settings/footer.html %]

View File

@@ -21,7 +21,7 @@ sub playerSettingsFrame {
my $value; my $value;
my $id = unpack('C', $$data_ref); my $id = unpack('C', $$data_ref);
# New SETD command 0xfe for display width # New SETD command 0xfe for display width & height
if ($id == 0xfe) { if ($id == 0xfe) {
$value = (unpack('Cn', $$data_ref))[1]; $value = (unpack('Cn', $$data_ref))[1];
if ($value > 100 && $value < 400) { if ($value > 100 && $value < 400) {
@@ -30,7 +30,9 @@ sub playerSettingsFrame {
$client->display->widthOverride(1, $value); $client->display->widthOverride(1, $value);
$client->update; $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); $client->SUPER::playerSettingsFrame($data_ref);
@@ -40,4 +42,11 @@ sub hasScrolling {
return 1; return 1;
} }
sub directMetadata {
my $client = shift;
$client->SUPER::directMetadata(@_);
Slim::Control::Request::notifyFromArray( $client, [ 'newmetadata' ] );
}
1; 1;

View File

@@ -30,7 +30,7 @@ sub page {
sub prefs { sub prefs {
my ($class, $client) = @_; my ($class, $client) = @_;
my @prefs = qw(width small_VU spectrum); my @prefs = qw(width small_VU spectrum artwork);
return ($prefs->client($client), @prefs); return ($prefs->client($client), @prefs);
} }
@@ -47,6 +47,11 @@ sub handler {
full => { band => $paramRef->{'pref_spectrum_full_band'} }, full => { band => $paramRef->{'pref_spectrum_full_band'} },
}; };
$cprefs->set('spectrum', $spectrum); $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->modes($client->display->build_modes);
$client->display->update; $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 # 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 # 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 # logic of "Settings" is beyond me and I really hate it
$paramRef->{'pref_spectrum'} = $cprefs->get('spectrum'); $paramRef->{'pref_spectrum'} = $cprefs->get('spectrum');
$paramRef->{'pref_artwork'} = $cprefs->get('artwork');
return $class->SUPER::handler($client, $paramRef); return $class->SUPER::handler($client, $paramRef);
} }

View File

@@ -3,8 +3,12 @@ package Plugins::SqueezeESP32::Plugin;
use strict; use strict;
use base qw(Slim::Plugin::Base); use base qw(Slim::Plugin::Base);
use Digest::MD5 qw(md5);
use List::Util qw(min);
use Slim::Utils::Prefs; use Slim::Utils::Prefs;
use Slim::Utils::Log; use Slim::Utils::Log;
use Slim::Web::ImageProxy;
my $prefs = preferences('plugin.squeezeesp32'); my $prefs = preferences('plugin.squeezeesp32');
@@ -28,6 +32,61 @@ sub initPlugin {
$class->SUPER::initPlugin(@_); $class->SUPER::initPlugin(@_);
Slim::Networking::Slimproto::addPlayerClass($class, 100, 'squeezeesp32', { client => 'Plugins::SqueezeESP32::Player', display => 'Plugins::SqueezeESP32::Graphics' }); Slim::Networking::Slimproto::addPlayerClass($class, 100, 'squeezeesp32', { client => 'Plugins::SqueezeESP32::Player', display => 'Plugins::SqueezeESP32::Graphics' });
$log->info("Added class 100 for SqueezeESP32"); $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; 1;

View File

@@ -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;

Binary file not shown.

View File

@@ -10,6 +10,6 @@
<name>PLUGIN_SQUEEZEESP32</name> <name>PLUGIN_SQUEEZEESP32</name>
<description>PLUGIN_SQUEEZEESP32_DESC</description> <description>PLUGIN_SQUEEZEESP32_DESC</description>
<module>Plugins::SqueezeESP32::Plugin</module> <module>Plugins::SqueezeESP32::Plugin</module>
<version>0.31</version> <version>0.40</version>
<creator>Philippe</creator> <creator>Philippe</creator>
</extensions> </extensions>

View File

@@ -53,3 +53,19 @@ PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND
PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND_DESC PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND_DESC
EN The number of bands is the width of the screen divided by this factor 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

View File

@@ -1,10 +1,10 @@
<?xml version='1.0' standalone='yes'?> <?xml version='1.0' standalone='yes'?>
<extensions> <extensions>
<plugins> <plugins>
<plugin version="0.31" name="SqueezeESP32" minTarget="7.5" maxTarget="*"> <plugin version="0.40" name="SqueezeESP32" minTarget="7.5" maxTarget="*">
<link>https://github.com/sle118/squeezelite-esp32</link> <link>https://github.com/sle118/squeezelite-esp32</link>
<creator>Philippe</creator> <creator>Philippe</creator>
<sha>6dc35a0f9f9b287d205f7532cbb642b08407a284</sha> <sha>aa122a85db949c903ffa978d3e3b4ee3205e4ec2</sha>
<email>philippe_44@outlook.com</email> <email>philippe_44@outlook.com</email>
<desc lang="EN">SqueezeESP32 additional player id (100)</desc> <desc lang="EN">SqueezeESP32 additional player id (100)</desc>
<url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip</url> <url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip</url>