Skip to content

Commit

Permalink
mad fix through library + ST77xx memory corruption + add full screen …
Browse files Browse the repository at this point in the history
…+ poll mutex for stream - release
  • Loading branch information
philippe44 committed Aug 30, 2020
1 parent ff5fb3a commit 26d3d99
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 26 deletions.
Binary file modified components/codecs/lib/libmad.a
Binary file not shown.
4 changes: 2 additions & 2 deletions components/display/ST77xx.c
Expand Up @@ -90,7 +90,7 @@ static void Update16( struct GDS_Device* Device ) {
for (int i = FirstRow; i <= LastRow; i++) {
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize);
optr += ChunkSize;
if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue;
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
optr = Private->iRAM;
}
Expand Down Expand Up @@ -157,7 +157,7 @@ static void Update24( struct GDS_Device* Device ) {
for (int i = FirstRow; i <= LastRow; i++) {
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize);
optr += ChunkSize;
if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue;
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
optr = Private->iRAM;
}
Expand Down
20 changes: 13 additions & 7 deletions components/squeezelite/display.c
Expand Up @@ -628,8 +628,9 @@ 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 < displayer.height) {
// full screen artwork or for small screen, full screen visu has priority
if (((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) ||
(artwork.enable && artwork.x == 0 && artwork.y == 0)) {
xSemaphoreGive(displayer.mutex);
return;
}
Expand Down Expand Up @@ -751,8 +752,11 @@ 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 < displayer.height) return;
// full screen artwork or for small screen, visu has priority when full screen
if (((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) ||
(artwork.enable && artwork.x == 0 && artwork.y == 0)) {
return;
}

xSemaphoreTake(displayer.mutex, portMAX_DELAY);

Expand Down Expand Up @@ -795,7 +799,7 @@ static void grfa_handler(u8_t *data, int len) {

// when using full screen visualizer on small screen there is a brief overlay
artwork.enable = (length != 0);

// just a config or an actual artwork
if (length < 32) {
if (artwork.enable) {
Expand Down Expand Up @@ -840,8 +844,10 @@ static void grfa_handler(u8_t *data, int len) {
* Update visualization bars
*/
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;
// no update when artwork is full screen (but no need to protect against not owning the display as we are playing
if ((artwork.enable && artwork.x == 0 && artwork.y == 0) || pthread_mutex_trylock(&visu_export.mutex)) {
return;
}

int mode = visu.mode & ~VISU_ESP32;

Expand Down
2 changes: 0 additions & 2 deletions components/squeezelite/mad.c
Expand Up @@ -243,8 +243,6 @@ static decode_state mad_decode(void) {
MAD(m, synth_frame, &m->synth, &m->frame);

if (decode.new_stream) {
// seems that mad can use some help in term of sync detection
if (m->stream.next_frame[0] != 0xff || (m->stream.next_frame[1] & 0xf0) != 0xf0) continue;
LOCK_O;
LOG_INFO("setting track_start");
output.next_sample_rate = decode_newstream(m->synth.pcm.samplerate, output.supported_rates);
Expand Down
5 changes: 5 additions & 0 deletions components/squeezelite/output_i2s.c
Expand Up @@ -234,6 +234,11 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
set_i2s_pin(spdif_config, &i2s_spdif_pin);
set_i2s_pin(dac_config, &i2s_dac_pin);

/* BEWARE: i2s. must be patched to set tx_msb_right/rx_msb_right to 1
* or SPDIF will not work. These settings are not accessible from
* userland and I don't know why
*/

// common I2S initialization
i2s_config.mode = I2S_MODE_MASTER | I2S_MODE_TX;
i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
Expand Down
42 changes: 37 additions & 5 deletions components/squeezelite/stream.c
Expand Up @@ -42,8 +42,30 @@ static log_level loglevel;
static struct buffer buf;
struct buffer *streambuf = &buf;

#define LOCK mutex_lock(streambuf->mutex)
#define UNLOCK mutex_unlock(streambuf->mutex)
#define LOCK mutex_lock(streambuf->mutex)
#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()
*/
#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 sockfd fd;

Expand Down Expand Up @@ -187,6 +209,7 @@ static void *stream_thread() {

} else {

LOCK_L;
pollinfo.fd = fd;
pollinfo.events = POLLIN;
if (stream.state == SEND_HEADERS) {
Expand All @@ -195,9 +218,10 @@ static void *stream_thread() {
}

UNLOCK;

if (_poll(ssl, &pollinfo, 100)) {

UNLOCK_L;
LOCK;

// check socket has not been closed while in poll
Expand Down Expand Up @@ -350,7 +374,7 @@ static void *stream_thread() {
UNLOCK;

} else {

UNLOCK_L;
LOG_SDEBUG("poll timeout");
}
}
Expand Down Expand Up @@ -403,6 +427,9 @@ 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);
Expand Down Expand Up @@ -432,13 +459,16 @@ 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) {
buf_flush(streambuf);

LOCK;

stream.header_len = header_len;
memcpy(stream.header, header, header_len);
*(stream.header+header_len) = '\0';
Expand Down Expand Up @@ -473,7 +503,9 @@ 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;
int sock = socket(AF_INET, SOCK_STREAM, 0);
UNLOCK_L;

if (sock < 0) {
LOG_ERROR("failed to create socket");
Expand Down
Binary file modified plugin/SqueezeESP32.zip
Binary file not shown.
8 changes: 4 additions & 4 deletions plugin/SqueezeESP32/Graphics.pm
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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');
Expand Down
5 changes: 5 additions & 0 deletions plugin/SqueezeESP32/Player.pm
Expand Up @@ -221,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;
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions plugin/SqueezeESP32/PlayerSettings.pm
Expand Up @@ -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);
}

Expand All @@ -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,
Expand Down Expand Up @@ -76,7 +76,7 @@ sub handler {
$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');
Expand Down
2 changes: 1 addition & 1 deletion plugin/SqueezeESP32/install.xml
Expand Up @@ -10,6 +10,6 @@
<name>PLUGIN_SQUEEZEESP32</name>
<description>PLUGIN_SQUEEZEESP32_DESC</description>
<module>Plugins::SqueezeESP32::Plugin</module>
<version>0.103</version>
<version>0.104</version>
<creator>Philippe</creator>
</extensions>
4 changes: 2 additions & 2 deletions plugin/repo.xml
@@ -1,10 +1,10 @@
<?xml version='1.0' standalone='yes'?>
<extensions>
<plugins>
<plugin version="0.103" 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>d07bb3b0a283fbde50e5533dca695a4505971f03</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>
Expand Down

0 comments on commit 26d3d99

Please sign in to comment.