From 9f23b79818d8ec1f3ac0c9d88e3181af1bf82bb8 Mon Sep 17 00:00:00 2001 From: Michael Herger Date: Tue, 5 May 2020 22:45:54 +0200 Subject: [PATCH] Fix some issues when SqueezeAmp doesn't have a display * only push simple prefs on the list of automatically managed items - hashes and lists can't be managed by the Settings super class * only push display/artwork related prefs on the list if deal with a player which has a display * move most artwork/display handling code out of the plugin to the Player class * rename `eq` pref to `equalizer`, as `eq` is a reserved word * automatically update the player when the `equalizer` pref is changed * strip down Plugin to the bare minimum needed with any SqueezeAMP, no matter whether it has a display or not --- .../plugins/SqueezeESP32/settings/player.html | 43 +++--- plugin/SqueezeESP32/Player.pm | 90 ++++++++++-- plugin/SqueezeESP32/PlayerSettings.pm | 69 +++++---- plugin/SqueezeESP32/Plugin.pm | 135 +++++++----------- 4 files changed, 183 insertions(+), 154 deletions(-) diff --git a/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html b/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html index 70baae8e..ade09afe 100644 --- a/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html +++ b/plugin/SqueezeESP32/HTML/EN/plugins/SqueezeESP32/settings/player.html @@ -3,74 +3,75 @@ [% IF prefs.pref_width %] [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_WIDTH" desc="PLUGIN_SQUEEZEESP32_WIDTH_DESC" %] + [% prefs.pref_width %] [% END %] - + [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_SMALL_VU" desc="PLUGIN_SQUEEZEESP32_SMALL_VU_DESC" %] [% END %] - + [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_SPECTRUM_SCALE" desc="PLUGIN_SQUEEZEESP32_SPECTRUM_SCALE_DESC" %] [% END %] - + [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_SMALL_SPECTRUM" desc="PLUGIN_SQUEEZEESP32_SMALL_SPECTRUM_DESC" %] [% "PLUGIN_SQUEEZEESP32_SMALL_SPECTRUM_SIZE" | string %]  [% "PLUGIN_SQUEEZEESP32_SMALL_SPECTRUM_BAND" | string %]  [% END %] - + [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND" desc="PLUGIN_SQUEEZEESP32_FULL_SPECTRUM_BAND_DESC" %] [% 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 %] -
- [% END %] - +
+ [% END %] + [% WRAPPER setting title="PLUGIN_SQUEEZEESP32_EQUALIZER" desc="" %] [% END %] - + [% WRAPPER settingSection %] [% WRAPPER settingGroup title='31Hz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='62Hz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='125Hz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='250Hz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='500Hz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='1kHz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='2kHz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='4kHz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='8kHz' desc="" %] - + [% END %] [% WRAPPER settingGroup title='16kHz' desc="" %] - + [% END %] [% END %] - + [% PROCESS settings/footer.html %] diff --git a/plugin/SqueezeESP32/Player.pm b/plugin/SqueezeESP32/Player.pm index 7e638201..19d19f2a 100644 --- a/plugin/SqueezeESP32/Player.pm +++ b/plugin/SqueezeESP32/Player.pm @@ -3,6 +3,9 @@ package Plugins::SqueezeESP32::Player; use strict; use base qw(Slim::Player::SqueezePlay); +use Digest::MD5 qw(md5); +use List::Util qw(min); + use Slim::Utils::Log; use Slim::Utils::Prefs; @@ -16,34 +19,34 @@ sub hasIR { 0 } sub init { my $client = shift; $client->SUPER::init(@_); - Plugins::SqueezeESP32::Plugin::config_artwork($client); + $client->config_artwork(); } # Allow the player to define it's display width (and probably more) sub playerSettingsFrame { my $client = shift; my $data_ref = shift; - + my $value; my $id = unpack('C', $$data_ref); - + # New SETD command 0xfe for display width & height - if ($id == 0xfe) { + if ($id == 0xfe) { $value = (unpack('Cn', $$data_ref))[1]; if ($value > 100 && $value < 400) { $prefs->client($client)->set('width', $value); - + my $height = (unpack('Cnn', $$data_ref))[2]; $prefs->client($client)->set('height', $height || 0); $client->display->modes($client->display->build_modes); $client->display->widthOverride(1, $value); $client->update; - - $log->info("Setting player $value" . "x" . "$height for ", $client->name); - } + + main::INFOLOG && $log->is_info && $log->info("Setting player $value" . "x" . "$height for ", $client->name); + } } - + $client->SUPER::playerSettingsFrame($data_ref); } @@ -51,10 +54,77 @@ sub hasScrolling { return 1; } +sub update_artwork { + my $client = shift; + my $cprefs = $prefs->client($client); + + my $artwork = $cprefs->get('artwork') || return; + + return unless $artwork->{'enable'}; + + my $s = min($cprefs->get('height') - $artwork->{'y'}, $cprefs->get('width') - $artwork->{'x'}); + + my $params = { force => shift || 0 }; + 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); + + send_artwork($client, undef, \$body) if $body; +} + +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 && !$params->{'force'}; + + $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; + } +} + +sub clear_artwork { + my ($client, $request) = @_; + + my $artwork = $prefs->client($client)->get('artwork'); + + if ($artwork && $artwork->{'enable'}) { + main::INFOLOG && $log->is_info && $log->info("artwork stop/clear " . $request->getRequestString()); + $client->pluginData('artwork_md5', ''); + } +} + +sub config_artwork { + my ($client) = @_; + + if ( my $artwork = $prefs->client($client)->get('artwork') ) { + my $header = pack('Nnn', $artwork->{'enable'}, $artwork->{'x'}, $artwork->{'y'}); + $client->sendFrame( grfa => \$header ); + } +} + sub reconnect { my $client = shift; $client->pluginData('artwork_md5', ''); $client->SUPER::reconnect(@_); -} +} 1; diff --git a/plugin/SqueezeESP32/PlayerSettings.pm b/plugin/SqueezeESP32/PlayerSettings.pm index 9b331d87..4f0af9cf 100644 --- a/plugin/SqueezeESP32/PlayerSettings.pm +++ b/plugin/SqueezeESP32/PlayerSettings.pm @@ -30,63 +30,60 @@ sub page { sub prefs { my ($class, $client) = @_; - my @prefs = qw(width small_VU spectrum artwork eq); + my @prefs; + push @prefs, qw(width small_VU) if $client->displayWidth; return ($prefs->client($client), @prefs); } sub handler { my ($class, $client, $paramRef) = @_; - + my ($cprefs, @prefs) = $class->prefs($client); - + if ($paramRef->{'saveSettings'}) { if ($client->displayWidth) { $cprefs->set('small_VU', $paramRef->{'pref_small_VU'} || 15); - my $spectrum = { scale => $paramRef->{'pref_spectrum_scale'} || 25, - small => { size => $paramRef->{'pref_spectrum_small_size'} || 25, - band => $paramRef->{'pref_spectrum_small_band'} || 5.33 }, - full => { band => $paramRef->{'pref_spectrum_full_band'} } || 8, - }; + my $spectrum = { + scale => $paramRef->{'pref_spectrum_scale'} || 25, + small => { size => $paramRef->{'pref_spectrum_small_size'} || 25, + band => $paramRef->{'pref_spectrum_small_band'} || 5.33 }, + full => { band => $paramRef->{'pref_spectrum_full_band'} } || 8, + }; $cprefs->set('spectrum', $spectrum); - - my $artwork = { enable => $paramRef->{'pref_artwork_enable'}, - x => $paramRef->{'pref_artwork_x'} || 0, - y => $paramRef->{'pref_artwork_y'} || 0, - }; - $cprefs->set('artwork', $artwork); + + my $artwork = { + enable => $paramRef->{'pref_artwork_enable'}, + x => $paramRef->{'pref_artwork_x'} || 0, + y => $paramRef->{'pref_artwork_y'} || 0, + }; + $cprefs->set('artwork', $artwork); $client->display->modes($client->display->build_modes); $client->display->update; - + # force update or disable artwork if ($artwork->{'enable'}) { - Plugins::SqueezeESP32::Plugin::update_artwork($client, 1); + $client->update_artwork(1); } else { - Plugins::SqueezeESP32::Plugin::config_artwork($client); - } - } - - my $eq = $cprefs->get('eq'); - for my $i (0 .. $#{$eq}) { - $eq->[$i] = $paramRef->{"pref_eq.$i"}; + $client->config_artwork(); + } } - $cprefs->set('eq', $eq); - Plugins::SqueezeESP32::Plugin::send_equalizer($client); + + my $equalizer = $cprefs->get('equalizer'); + for my $i (0 .. $#{$equalizer}) { + $equalizer->[$i] = $paramRef->{"pref_equalizer.$i"} || 0; + } + $cprefs->set('equalizer', $equalizer); } - + if ($client->displayWidth) { - # as there is nothing captured, we need to re-set these variables - $paramRef->{'pref_width'} = $cprefs->get('width'); - - # 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 - # 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 + # the Settings super class can't handle anything but scalar values + # we need to populate the $paramRef for the other prefs manually $paramRef->{'pref_spectrum'} = $cprefs->get('spectrum'); $paramRef->{'pref_artwork'} = $cprefs->get('artwork'); } - - $paramRef->{'pref_eq'} = $cprefs->get('eq'); - + + $paramRef->{'pref_equalizer'} = $cprefs->get('equalizer'); + return $class->SUPER::handler($client, $paramRef); } diff --git a/plugin/SqueezeESP32/Plugin.pm b/plugin/SqueezeESP32/Plugin.pm index ca533c24..f146cdb7 100644 --- a/plugin/SqueezeESP32/Plugin.pm +++ b/plugin/SqueezeESP32/Plugin.pm @@ -4,8 +4,6 @@ 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; @@ -16,121 +14,84 @@ my $log = Slim::Utils::Log->addLogCategory({ 'category' => 'plugin.squeezeesp32', 'defaultLevel' => 'INFO', 'description' => Slim::Utils::Strings::string('SqueezeESP32'), -}); +}); + +# migrate 'eq' pref, as that's a reserved word and could cause problems in the future +$prefs->migrateClient(1, sub { + my ($cprefs, $client) = @_; + $cprefs->set('equalizer', $cprefs->get('eq')); + $cprefs->remove('eq'); + 1; +}); + +$prefs->setChange(sub { + send_equalizer($_[2]); +}, 'equalizer'); sub initPlugin { my $class = shift; - + if ( main::WEBUI ) { require Plugins::SqueezeESP32::PlayerSettings; Plugins::SqueezeESP32::PlayerSettings->new; - + # require Plugins::SqueezeESP32::Settings; # Plugins::SqueezeESP32::Settings->new; } - + $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( sub { onNotification(@_) }, [ ['newmetadata'] ] ); - Slim::Control::Request::subscribe( sub { onNotification(@_) }, [ ['playlist'], ['open', 'newsong'] ]); + main::INFOLOG && $log->is_info && $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( \&onStopClear, [ ['playlist'], ['stop', 'clear'] ]); + + # the custom player class is only initialized if it has a display - thus we need to listen to connect events in order to initializes other player prefs Slim::Control::Request::subscribe( \&onPlayer,[ ['client'], [ 'new', 'reconnect' ] ] ); } 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', '') - } + my $request = shift; + my $client = $request->client || return; + + if ($client->isa('Plugins::SqueezeESP32::Player')) { + $client->clear_artwork($request); + } } sub onPlayer { - my $request = shift; - my $client = $request->client; + my $request = shift; + my $client = $request->client || return; - if ($client->model eq 'squeezeesp32') { - $prefs->client($client)->init( { - eq => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - } ); - Plugins::SqueezeESP32::Plugin::send_equalizer($client); + if ($client->model eq 'squeezeesp32') { + main::INFOLOG && $log->is_info && $log->info("SqueezeESP player connected: " . $client->id); + + $prefs->client($client)->init( { + equalizer => [(0) x 10], + } ); + send_equalizer($client); } } sub onNotification { - my $request = shift; - my $client = $request->client; - - my $reqstr = $request->getRequestString(); + my $request = shift; + my $client = $request->client || return; - update_artwork($client); -} - -sub update_artwork { - my $client = shift; - my $params = { force => shift || 0 }; - my $cprefs = $prefs->client($client); - my $artwork = $cprefs->get('artwork'); - - return unless $client->model eq 'squeezeesp32' && $artwork->{'enable'}; - - 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); - - send_artwork($client, undef, \$body) if $body; -} - -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 && !$params->{'force'}; - - $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; + if ($client->isa('Plugins::SqueezeESP32::Player')) { + $client->update_artwork(); } -} +} sub send_equalizer { my ($client) = @_; - my $equalizer = $prefs->client($client)->get('eq'); - my $size = @$equalizer; - my $data = pack("c[$size]", @{$equalizer}); - $client->sendFrame( eqlz => \$data ); -} -sub config_artwork { - my ($client) = @_; - my $artwork = $prefs->client($client)->get('artwork'); - my $header = pack('Nnn', $artwork->{'enable'}, $artwork->{'x'}, $artwork->{'y'}); - $client->sendFrame( grfa => \$header ); + if ($client->model eq 'squeezeesp32') { + my $equalizer = $prefs->client($client)->get('equalizer') || [(0) x 10]; + my $size = @$equalizer; + my $data = pack("c[$size]", @{$equalizer}); + $client->sendFrame( eqlz => \$data ); + } } 1;