diff --git a/components/codecs/lib/libmad.a b/components/codecs/lib/libmad.a index fdb17fae..fa9aced8 100644 Binary files a/components/codecs/lib/libmad.a and b/components/codecs/lib/libmad.a differ diff --git a/components/display/ST77xx.c b/components/display/ST77xx.c index 3deaee2a..78d59d87 100644 --- a/components/display/ST77xx.c +++ b/components/display/ST77xx.c @@ -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; } @@ -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; } diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index af263eab..20b8547d 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -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; } @@ -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); @@ -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) { @@ -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; diff --git a/components/squeezelite/mad.c b/components/squeezelite/mad.c index 5f809305..3e0b4502 100644 --- a/components/squeezelite/mad.c +++ b/components/squeezelite/mad.c @@ -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); diff --git a/components/squeezelite/stream.c b/components/squeezelite/stream.c index 20d2e547..73d097ce 100644 --- a/components/squeezelite/stream.c +++ b/components/squeezelite/stream.c @@ -40,13 +40,32 @@ static log_level loglevel; static struct buffer buf; -static mutex_type poll_mutex; struct buffer *streambuf = &buf; #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; @@ -408,7 +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); @@ -438,14 +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'; @@ -480,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"); @@ -588,13 +613,11 @@ bool stream_disconnect(void) { ssl = NULL; } #endif - LOCK_L; if (fd != -1) { closesocket(fd); fd = -1; disc = true; } - UNLOCK_L, stream.state = STOPPED; UNLOCK; return disc;