Explorar o código

mad fix through library + ST77xx memory corruption + add full screen + poll mutex for stream - release

Philippe G %!s(int64=4) %!d(string=hai) anos
pai
achega
26d3d99738

BIN=BIN
components/codecs/lib/libmad.a


+ 2 - 2
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;
 			}	

+ 13 - 7
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;
 				

+ 0 - 2
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);

+ 5 - 0
components/squeezelite/output_i2s.c

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

+ 37 - 5
components/squeezelite/stream.c

@@ -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;
 
@@ -187,6 +209,7 @@ static void *stream_thread() {
 
 		} else {
 
+			LOCK_L;
 			pollinfo.fd = fd;
 			pollinfo.events = POLLIN;
 			if (stream.state == SEND_HEADERS) {
@@ -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
@@ -350,7 +374,7 @@ static void *stream_thread() {
 			UNLOCK;
 			
 		} else {
-			
+			UNLOCK_L;
 			LOG_SDEBUG("poll timeout");
 		}
 	}
@@ -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);
@@ -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';
@@ -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");

BIN=BIN
plugin/SqueezeESP32.zip


+ 4 - 4
plugin/SqueezeESP32/Graphics.pm

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

+ 5 - 0
plugin/SqueezeESP32/Player.pm

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

+ 3 - 3
plugin/SqueezeESP32/PlayerSettings.pm

@@ -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,
@@ -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');

+ 1 - 1
plugin/SqueezeESP32/install.xml

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

+ 2 - 2
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>