Compare commits

...

8 Commits

Author SHA1 Message Date
Sebastien
a46bbb409f Fixes #50 - Green led flash state reset on wifi connect - release 2020-09-01 15:11:45 -04:00
Sebastien
08d16c2ca2 Led configuration wasn't correctly reported in logs 2020-09-01 12:03:31 -04:00
Philippe G
b501352ddc Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32 into master-cmake 2020-08-31 15:36:21 -07:00
Philippe G
1c51598366 shift i2c address by 1 for consistency - release 2020-08-31 15:36:17 -07:00
Sebastien
db839a9ccd Add new status field: is_i2c_locked to help with the new config page 2020-08-31 16:56:54 -04:00
Philippe G
5aba426b98 no mutex needed for polling - release 2020-08-30 12:30:30 -07:00
Philippe G
6c184efa92 faster & simpler solution for stream poll() - release 2020-08-30 11:22:03 -07:00
Philippe G
028a090864 update plugin files 2020-08-29 22:20:26 -07:00
13 changed files with 111 additions and 73 deletions

View File

@@ -5,7 +5,6 @@
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -84,8 +83,8 @@ static void vCallbackFunction( TimerHandle_t xTimer ) {
*/
bool led_blink_core(int idx, int ontime, int offtime, bool pushed) {
if (!leds[idx].gpio || leds[idx].gpio < 0 ) return false;
ESP_LOGD(TAG,"led_blink_core");
ESP_LOGD(TAG,"led_blink_core led idx %d, ontime %d, offtime %d, pushing %s. Led state: pushedon %d, pushedoff %d, timer %s, pushed %s", idx,ontime,offtime,pushed?"TRUE":"FALSE", leds[idx].pushedon,leds[idx].pushedoff,leds[idx].timer?"TRUE":"FALSE", leds[idx].pushed?"TRUE":"FALSE");
if (leds[idx].timer) {
// normal requests waits if a pop is pending
if (!pushed && leds[idx].pushed) {
@@ -98,15 +97,18 @@ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) {
// save current state if not already pushed
if (!leds[idx].pushed) {
ESP_LOGD(TAG,"Pushing state. Ontime %d->%d. Offtime %d->%d",leds[idx].pushedon,leds[idx].ontime, leds[idx].pushedoff,leds[idx].offtime);
leds[idx].pushedon = leds[idx].ontime;
leds[idx].pushedoff = leds[idx].offtime;
leds[idx].pushed = pushed;
}
// then set new one
leds[idx].ontime = ontime;
leds[idx].offtime = offtime;
if (ontime == 0) {
ESP_LOGD(TAG,"led %d, setting reverse level", idx);
set_level(leds + idx, false);
@@ -124,7 +126,8 @@ bool led_blink_core(int idx, int ontime, int offtime, bool pushed) {
ESP_LOGD(TAG,"led %d, Setting gpio %d and starting timer", idx, leds[idx].gpio);
if (xTimerStart(leds[idx].timer, BLOCKTIME) == pdFAIL) return false;
}
ESP_LOGD(TAG,"led_blink_core END led idx %d, ontime %d, offtime %d, pushing %s. Led state: pushedon %d, pushedoff %d, timer %s, pushed %s", idx,ontime,offtime,pushed?"TRUE":"FALSE", leds[idx].pushedon,leds[idx].pushedoff,leds[idx].timer?"TRUE":"FALSE", leds[idx].pushed?"TRUE":"FALSE");
return true;
}
@@ -231,15 +234,13 @@ void led_svc_init(void) {
#ifndef CONFIG_LED_LOCKED
parse_set_GPIO(set_led_gpio);
#endif
ESP_LOGI(TAG,"Configuring LEDs green:%d (active:%d %d%%), red:%d (active:%d %d%%)", green.gpio, green.active, green.pwm, green.gpio, green.active, green.pwm );
char *nvs_item = config_alloc_get(NVS_TYPE_STR, "led_brightness"), *p;
if (nvs_item) {
if ((p = strcasestr(nvs_item, "green")) != NULL) green.pwm = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "red")) != NULL) red.pwm = atoi(strchr(p, '=') + 1);
free(nvs_item);
}
ESP_LOGI(TAG,"Configuring LEDs green:%d (active:%d %d%%), red:%d (active:%d %d%%)", green.gpio, green.active, green.pwm, red.gpio, red.active, red.pwm );
led_config(LED_GREEN, green.gpio, green.active, green.pwm);
led_config(LED_RED, red.gpio, red.active, red.pwm);
}

View File

@@ -128,7 +128,7 @@ static esp_err_t i2c_write_reg(uint8_t reg, uint8_t val) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, val, I2C_MASTER_NACK);
@@ -153,11 +153,11 @@ static uint8_t i2c_read_reg(uint8_t reg) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, i2c_addr | I2C_MASTER_READ, I2C_MASTER_NACK);
i2c_master_write_byte(cmd, (i2c_addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK);
i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK);
i2c_master_stop(cmd);

View File

@@ -46,27 +46,17 @@ struct buffer *streambuf = &buf;
#define UNLOCK mutex_unlock(streambuf->mutex)
/*
After a lot of hesitation, I've added that "poll mutex" to prevent
socket from being allocated while we are still in poll(). The issue
happens is we have a close quickly followed by an open, we might still
be in the poll() and simple OS fail as they re-allocate the same socket
on which a thread is still waiting.
Ideally, you want to set the lock in the disconnect() but that would mean
very often we'd have to always wait for the end of the poll(), i.e. up to
100ms for nothing most of the time where if it is in the open(), it is
less elegant as closing a socket on which there is a poll() is not good
but it's more efficient as it is very rare that you'd have an open() less
then 100ms after a close()
When LMS sends a close/open sequence very quickly, the stream thread might
still be waiting in the poll() on the closed socket. It is never recommended
to have a thread closing a socket used by another thread but it works, as
opposed to an infinite select().
In stream_sock() a new socket is created and full OS will allocate a different
one but on RTOS and simple IP stack, the same might be re-used and that causes
an exception as a thread is already waiting on a newly allocated socket
A simple variable that forces stream_sock() to wait until we are out of poll()
is enough and much faster than a mutex
*/
#if EMBEDDED
static mutex_type poll_mutex;
#define LOCK_L mutex_lock(poll_mutex)
#define UNLOCK_L mutex_unlock(poll_mutex)
#else
#define LOCK_L
#define UNLOCK_L
#endif
static bool polling;
static sockfd fd;
struct streamstate stream;
@@ -209,7 +199,6 @@ static void *stream_thread() {
} else {
LOCK_L;
pollinfo.fd = fd;
pollinfo.events = POLLIN;
if (stream.state == SEND_HEADERS) {
@@ -218,10 +207,12 @@ static void *stream_thread() {
}
UNLOCK;
// no mutex needed - we just want to know if we are inside poll()
polling = true;
if (_poll(ssl, &pollinfo, 100)) {
UNLOCK_L;
polling = false;
LOCK;
// check socket has not been closed while in poll
@@ -374,7 +365,7 @@ static void *stream_thread() {
UNLOCK;
} else {
UNLOCK_L;
polling = false;
LOG_SDEBUG("poll timeout");
}
}
@@ -427,9 +418,6 @@ void stream_init(log_level level, unsigned stream_buf_size) {
*stream.header = '\0';
fd = -1;
#if EMBEDDED
mutex_create_p(poll_mutex);
#endif
#if LINUX || FREEBSD
touch_memory(streambuf->buf, streambuf->size);
@@ -459,9 +447,6 @@ void stream_close(void) {
#endif
free(stream.header);
buf_destroy(streambuf);
#if EMBEDDED
mutex_destroy(poll_mutex);
#endif
}
void stream_file(const char *header, size_t header_len, unsigned threshold) {
@@ -503,9 +488,12 @@ void stream_file(const char *header, size_t header_len, unsigned threshold) {
void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
struct sockaddr_in addr;
LOCK_L;
#if EMBEDDED
// wait till we are not polling anymore
while (polling && running) { usleep(10000); }
#endif
int sock = socket(AF_INET, SOCK_STREAM, 0);
UNLOCK_L;
if (sock < 0) {
LOG_ERROR("failed to create socket");

View File

@@ -462,7 +462,11 @@ cJSON * wifi_manager_get_basic_info(cJSON **old){
cJSON_AddNumberToObject(root,"Voltage", battery_value_svc());
cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect );
cJSON_AddNumberToObject(root,"avg_conn_time", num_disconnect>0?(total_connected_time/num_disconnect):0 );
#if CONFIG_I2C_LOCKED
cJSON_AddTrueToObject(root, "is_i2c_locked");
#else
cJSON_AddFalseToObject(root, "is_i2c_locked");
#endif
ESP_LOGV(TAG, "wifi_manager_get_basic_info done");
return root;
}
@@ -689,6 +693,8 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_
ESP_LOGD(TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s",stac->aid,STR_OR_BLANK(mac));
FREE_AND_NULL(mac);
xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT);
wifi_manager_send_message(EVENT_STA_CONNECTED, NULL);
}
break;
case WIFI_EVENT_AP_STADISCONNECTED:
@@ -1476,6 +1482,9 @@ void wifi_manager( void * pvParameters ){
/* callback */
if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
break;
case EVENT_STA_CONNECTED:
if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
break;
case UPDATE_CONNECTION_OK:
/* refresh JSON */
if(wifi_manager_lock_json_buffer( portMAX_DELAY )){

View File

@@ -191,7 +191,8 @@ typedef enum message_code_t {
ORDER_RESTART_RECOVERY = 16,
ORDER_RESTART_OTA_URL = 17,
ORDER_RESTART = 18,
MESSAGE_CODE_COUNT = 19 /* important for the callback array */
EVENT_STA_CONNECTED = 19,
MESSAGE_CODE_COUNT = 20 /* important for the callback array */
}message_code_t;

View File

@@ -44,7 +44,7 @@ menu "Squeezelite-ESP32"
string
default "model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0" if SQUEEZEAMP
default "model=AC101,bck=27,ws=26,do=25,di=35,sda=33,scl=32" if A1S
default "model=I2S,bck=26,ws=25,do=33,i2c=106,sda=21,scl=22" if TWATCH2020
default "model=I2S,bck=26,ws=25,do=33,i2c=53,sda=21,scl=22" if TWATCH2020
default ""
config SPDIF_CONFIG
string

View File

@@ -95,6 +95,10 @@ void cb_connection_sta_disconnected(void *pvParameter){
bWifiConnected=false;
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
}
void cb_connection_sta_connected(void *pvParameter){
}
bool wait_for_wifi(){
bool connected=(xEventGroupGetBits(wifi_event_group) & CONNECTED_BIT)!=0;
if(!connected){
@@ -447,7 +451,7 @@ void app_main()
/* start the wifi manager */
ESP_LOGD(TAG,"Blinking led");
led_blink(LED_GREEN, 250, 250);
led_blink_pushed(LED_GREEN, 250, 250);
if(bypass_wifi_manager){
ESP_LOGW(TAG,"*******************************************************************************************");
@@ -463,6 +467,7 @@ void app_main()
* This can be either after we're started the AP mode, or after we've started the STA mode */
wifi_manager_set_callback(ORDER_START_AP, &start_telnet);
wifi_manager_set_callback(ORDER_CONNECT_STA, &start_telnet);
wifi_manager_set_callback(EVENT_STA_CONNECTED, &cb_connection_sta_connected);
}
console_start();

Binary file not shown.

View File

@@ -78,7 +78,7 @@ sub displayWidth {
if ($display->widthOverride) {
my $artwork = $prefs->client($client)->get('artwork');
if ($artwork->{'enable'} && $artwork->{'y'} < 32 && ($client->isPlaying || $client->isPaused)) {
return $artwork->{x} + ($display->modes->[$mode || 0]{_width} || 0);
return ($artwork->{x} || $display->widthOverride) + ($display->modes->[$mode || 0]{_width} || 0);
} else {
return $display->widthOverride + ($display->modes->[$mode || 0]{_width} || 0);
}
@@ -113,9 +113,9 @@ sub build_modes {
my $artwork = $cprefs->get('artwork');
my $disp_width = $cprefs->get('width') || 128;
# if artwork is in main display, reduce width
my $width = ($artwork->{'enable'} && $artwork->{'y'} < 32) ? $artwork->{'x'} : $disp_width;
my $width_low = ($artwork->{'enable'} && ($artwork->{'y'} >= 32 || $disp_width - $artwork->{'x'} > 32)) ? $artwork->{'x'} : $disp_width;
# if artwork is in main display, reduce width but when artwork is (0,0) fake it
my $width = ($artwork->{'enable'} && $artwork->{'y'} < 32 && $artwork->{'x'}) ? $artwork->{'x'} : $disp_width;
my $width_low = ($artwork->{'enable'} && $artwork->{'x'} && ($artwork->{'y'} >= 32 || $disp_width - $artwork->{'x'} > 32)) ? $artwork->{'x'} : $disp_width;
my $small_VU = $cprefs->get('small_VU');
my $spectrum = $cprefs->get('spectrum');

View File

@@ -13,6 +13,19 @@ my $sprefs = preferences('server');
my $prefs = preferences('plugin.squeezeesp32');
my $log = logger('plugin.squeezeesp32');
{
__PACKAGE__->mk_accessor('rw', 'tone_update');
}
sub new {
my $class = shift;
my $client = $class->SUPER::new(@_);
$client->init_accessor(
tone_update => 0,
);
return $client;
}
our $defaultPrefs = {
'analogOutMode' => 0,
'bass' => 0,
@@ -44,7 +57,6 @@ sub hasIR { 1 }
# TODO: add in settings when ready
sub hasLineIn { 0 }
sub hasHeadSubOut { 1 }
# TODO: LMS sliders are hard-coded in html file from -23 to +23
sub maxTreble { 20 }
sub minTreble { -13 }
sub maxBass { 20 }
@@ -54,7 +66,7 @@ sub init {
my $client = shift;
if (!$handlersAdded) {
# Add a handler for line-in/out status changes
Slim::Networking::Slimproto::addHandler( LIOS => \&lineInOutStatus );
@@ -117,25 +129,41 @@ sub playerSettingsFrame {
}
sub bass {
return tone(2, @_);
}
sub treble {
return tone(8, @_);
my ($client, $new) = @_;
my $value = $client->SUPER::bass($new);
$client->update_equalizer($value, [2, 1, 3]) if defined $new;
return $value;
}
sub tone {
my ($center, $client, $value) = @_;
my $equalizer = $prefs->client($client)->get('equalizer');
sub treble {
my ($client, $new) = @_;
my $value = $client->SUPER::treble($new);
if (defined($value)) {
$equalizer->[$center-1] = int($value * 0.2 + 0.5);
$equalizer->[$center] = int($value * 0.7 + 0.5);
$equalizer->[$center+1] = int($value * 0.1 + 0.5);
$prefs->client($client)->set('equalizer', $equalizer);
}
$client->update_equalizer($value, [8, 9, 7]) if defined $new;
return int($equalizer->[$center-1] * 0.2 + $equalizer->[$center] * 0.7 + $equalizer->[$center+1] * 0.1);
return $value;
}
sub update_equalizer {
my ($client, $value, $index) = @_;
return if $client->tone_update;
my $equalizer = $prefs->client($client)->get('equalizer');
$equalizer->[$index->[0]] = $value;
$equalizer->[$index->[1]] = int($value / 2 + 0.5);
$equalizer->[$index->[2]] = int($value / 4 + 0.5);
$prefs->client($client)->set('equalizer', $equalizer);
}
sub update_tones {
my ($client, $equalizer) = @_;
$client->tone_update(1);
$sprefs->client($client)->set('bass', int(($equalizer->[1] * 2 + $equalizer->[2] + $equalizer->[3] * 4) / 7 + 0.5));
$sprefs->client($client)->set('treble', int(($equalizer->[7] * 4 + $equalizer->[8] + $equalizer->[9] * 2) / 7 + 0.5));
$client->tone_update(0);
}
sub update_artwork {
@@ -193,6 +221,11 @@ sub clear_artwork {
if ($artwork && $artwork->{'enable'}) {
main::INFOLOG && $log->is_info && $log->info("artwork stop/clear " . $request->getRequestString());
$client->pluginData('artwork_md5', '');
# refresh screen and disable artwork when artwork was full screen (hack)
if (!$artwork->{'x'} && !$artwork->{'y'}) {
$client->sendFrame(grfa => \("\x00"x4)) unless $artwork->{'x'} || $artwork->{'y'};
$client->display->update;
}
}
}

View File

@@ -31,7 +31,7 @@ sub page {
sub prefs {
my ($class, $client) = @_;
my @prefs;
push @prefs, qw(width small_VU) if $client->displayWidth;
push @prefs, qw(width small_VU) if defined $client->displayWidth;
return ($prefs->client($client), @prefs);
}
@@ -41,7 +41,7 @@ sub handler {
my ($cprefs, @prefs) = $class->prefs($client);
if ($paramRef->{'saveSettings'}) {
if ($client->displayWidth) {
if (defined $client->displayWidth) {
$cprefs->set('small_VU', $paramRef->{'pref_small_VU'} || 15);
my $spectrum = {
scale => $paramRef->{'pref_spectrum_scale'} || 25,
@@ -73,9 +73,10 @@ sub handler {
$equalizer->[$i] = $paramRef->{"pref_equalizer.$i"} || 0;
}
$cprefs->set('equalizer', $equalizer);
$client->update_tones($equalizer);
}
if ($client->displayWidth) {
if (defined $client->displayWidth) {
# 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');

View File

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

View File

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