Quellcode durchsuchen

Give some love to AIrPlay/BT screens + better "safe TCB release" - release

Philippe G vor 3 Jahren
Ursprung
Commit
975f34f01b

+ 4 - 2
components/display/core/gds_font.c

@@ -98,12 +98,14 @@ void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y,
     }
 }
 
-bool GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ) {
+struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ) {
+	const struct GDS_FontDef* OldFont = Display->Font;
+
     Display->FontForceProportional = false;
     Display->FontForceMonospace = false;
     Display->Font = Font;
 
-    return true;
+    return OldFont;
 }
 
 void GDS_FontForceProportional( struct GDS_Device* Display, bool Force ) {

+ 3 - 2
components/display/core/gds_font.h

@@ -46,7 +46,7 @@ typedef enum {
     TextAnchor_Center
 } TextAnchor;
 
-bool GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font );
+struct GDS_FontDef* GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font );
 
 void GDS_FontForceProportional( struct GDS_Device* Display, bool Force );
 void GDS_FontForceMonospace( struct GDS_Device* Display, bool Force );
@@ -59,7 +59,8 @@ int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display );
 
 int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character );
 int GDS_FontGetCharHeight( struct GDS_Device* Display );
-int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text );\
+int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text );
+int GDS_FontMeasureStringLine( struct GDS_Device* Display, int Line, const char* Text );
 
 void GDS_FontDrawChar( struct GDS_Device* Display, char Character, int x, int y, int Color );
 void GDS_FontDrawString( struct GDS_Device* Display, int x, int y, const char* Text, int Color );

+ 13 - 0
components/display/core/gds_text.c

@@ -121,6 +121,19 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex
 	return Width + X < Device->Width;
 }
 
+/****************************************************************************************
+ * 
+ */
+int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text) {
+	struct GDS_FontDef *Font = GDS_SetFont( Device, Device->Lines[N-1].Font );	
+
+	if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true );
+	int Width = GDS_FontMeasureString( Device, Text );
+	GDS_SetFont( Device, Font );
+
+	return Width;
+}
+
 /****************************************************************************************
  * Try to align string for better scrolling visual. there is probably much better to do
  */

+ 1 - 0
components/display/core/gds_text.h

@@ -31,5 +31,6 @@ struct GDS_Device;
 bool 	GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space);
 bool 	GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space);
 bool 	GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text);
+int		GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text);
 int 	GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max);
 void 	GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...);

+ 52 - 17
components/display/display.c

@@ -41,7 +41,12 @@ static EXT_RAM_ATTR struct {
 	int offset, boundary;
 	char *metadata_config;
 	bool timer, refresh;
-	uint32_t elapsed, duration;
+	uint32_t elapsed;
+	struct {
+		uint32_t value;
+		char string[8]; // H:MM:SS
+		bool visible;
+	} duration;
 	TickType_t tick;
 } displayer;
 
@@ -126,7 +131,7 @@ void display_init(char *welcome) {
 		static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
 		static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__ ((aligned (4)));
 		
-		GDS_SetLayout( display, strcasestr(config, "HFlip"), strcasestr(config, "VFlip"), strcasestr(config, "rotate"));
+		GDS_SetLayout(display, strcasestr(config, "HFlip"), strcasestr(config, "VFlip"), strcasestr(config, "rotate"));
 		GDS_SetFont(display, &Font_droid_sans_fallback_15x17 );
 		GDS_TextPos(display, GDS_FONT_MEDIUM, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome);
 
@@ -193,23 +198,34 @@ static void displayer_task(void *args) {
 		
 		// handler elapsed track time
 		if (displayer.timer && displayer.state == DISPLAYER_ACTIVE) {
-			char line[20], duration[12] = "";
+			char line[19] = "-", *_line = line + 1; // [-]H:MM:SS / H:MM:SS
 			TickType_t tick = xTaskGetTickCount();
 			uint32_t elapsed = (tick - displayer.tick) * portTICK_PERIOD_MS;
-			
+
 			if (elapsed >= 1000) {
 				xSemaphoreTake(displayer.mutex, portMAX_DELAY);
 				displayer.tick = tick;
-				displayer.elapsed += elapsed / 1000;
-				xSemaphoreGive(displayer.mutex);				
-				if (displayer.duration > 0) {
-					if (displayer.duration < 3600) snprintf(duration, sizeof(duration), " / %u:%02u", displayer.duration / 60, displayer.duration % 60);
-					else snprintf(duration, sizeof(duration), " / %u:%02u:%02u", (displayer.duration / 3600) % 100, (displayer.duration % 3600) / 60, displayer.duration % 60);
-				}			
-				if (displayer.elapsed < 3600) snprintf(line, sizeof(line), "%*u:%02u", sizeof(line) - 1 - strlen(duration) - 3, displayer.elapsed / 60, displayer.elapsed % 60);
-				else snprintf(line, sizeof(line), "%*u:%02u:%02u", sizeof(line) - 1 - strlen(duration) - 6, (displayer.elapsed / 3600) % 100, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60);
-				strcat(line, duration);
-				GDS_TextLine(display, 1, GDS_TEXT_RIGHT, (GDS_TEXT_CLEAR | GDS_TEXT_CLEAR_EOL) | GDS_TEXT_UPDATE, line);
+				elapsed = displayer.elapsed += elapsed / 1000;
+				xSemaphoreGive(displayer.mutex);
+
+				// when we have duration but no space, display remaining time
+				if (displayer.duration.value && !displayer.duration.visible) elapsed = displayer.duration.value - elapsed;
+
+				if (elapsed < 3600) sprintf(_line, "%u:%02u", elapsed / 60, elapsed % 60);
+				else sprintf(_line, "%u:%02u:%02u", (elapsed / 3600) % 100, (elapsed % 3600) / 60, elapsed % 60);
+
+				// concatenate if we have room for elapsed / duration
+				if (displayer.duration.visible) {
+					strcat(_line, "/");
+					strcat(_line, displayer.duration.string);
+				} else if (displayer.duration.value) {
+					_line--;
+				}
+
+				// just re-write the whole line it's easier
+				GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, displayer.header);	
+				GDS_TextLine(display, 1, GDS_TEXT_RIGHT, GDS_TEXT_UPDATE, _line);
+
 				timer_sleep = 1000;
 			} else timer_sleep = max(1000 - elapsed, 0);	
 		} else timer_sleep = DEFAULT_SLEEP;
@@ -323,9 +339,27 @@ void displayer_timer(enum displayer_time_e mode, int elapsed, int duration) {
 	
 	xSemaphoreTake(displayer.mutex, portMAX_DELAY);
 
-	if (elapsed >= 0) displayer.elapsed = elapsed / 1000;	
-	if (duration >= 0) displayer.duration = duration / 1000;
 	if (displayer.timer) displayer.tick = xTaskGetTickCount();
+	if (elapsed >= 0) displayer.elapsed = elapsed / 1000;	
+	if (duration > 0) {
+		displayer.duration.visible = true;
+		displayer.duration.value = duration / 1000;
+
+		if (displayer.duration.value > 3600) sprintf(displayer.duration.string, "%u:%02u:%02u", (displayer.duration.value / 3600) % 10,
+													(displayer.duration.value % 3600) / 60, displayer.duration.value % 60);
+		else sprintf(displayer.duration.string, "%u:%02u", displayer.duration.value / 60, displayer.duration.value % 60);
+
+		char *buf;
+		asprintf(&buf, "%s %s/%s", displayer.header, displayer.duration.string, displayer.duration.string);
+		if (GDS_GetTextWidth(display, 1, 0, buf) > GDS_GetWidth(display)) {
+			ESP_LOGW(TAG, "Can't fit duration %s (%d) on screen using elapsed only", buf, GDS_GetTextWidth(display, 1, 0, buf));
+			displayer.duration.visible = false;
+		}
+		free(buf);
+	} else if (!duration) {
+		displayer.duration.visible = false;
+		displayer.duration.value = 0;
+	}
 		
 	xSemaphoreGive(displayer.mutex);
 }	
@@ -350,7 +384,8 @@ void displayer_control(enum displayer_cmd_e cmd, ...) {
 		displayer.timer = false;
 		displayer.refresh = true;
 		displayer.string[0] = '\0';
-		displayer.elapsed = displayer.duration = 0;
+		displayer.elapsed = displayer.duration.value = 0;
+		displayer.duration.visible = false;
 		displayer.offset = displayer.boundary = 0;
 		display_bus(&displayer, DISPLAY_BUS_TAKE);
 		vTaskResume(displayer.task);

+ 1 - 1
components/display/fonts/font_line_1.c

@@ -26,7 +26,7 @@ static const uint8_t Square721_BT11x14[] = {
         0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ,
         0x04, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char -
         0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char .
-        0x04, 0x00, 0x0C, 0x80, 0x03, 0x70, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char /
+        0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x80, 0x03, 0x70, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char /
         0x08, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 0
         0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x04, 0x08, 0x04, 0xF8, 0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 1
         0x08, 0x00, 0x00, 0x00, 0x00, 0x30, 0x07, 0x08, 0x05, 0x88, 0x04, 0x88, 0x04, 0x88, 0x04, 0x70, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 2

+ 2 - 3
components/raop/raop.c

@@ -255,7 +255,7 @@ void raop_delete(struct raop_ctx_s *ctx) {
 	vTaskDelay(100 / portTICK_PERIOD_MS);
 	ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
 	vTaskDelete(ctx->thread);
-	SAFE_TCB_FREE(ctx->xTaskBuffer);
+	SAFE_PTR_FREE(ctx->xTaskBuffer);
 
 	// cleanup all session-created items
 	cleanup_rtsp(ctx, true);
@@ -607,7 +607,6 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
 			sscanf(p, "%*[^:]:%u/%u/%u", &start, &current, &stop);
 			current = ((current - start) / 44100) * 1000;
 			if (stop) stop = ((stop - start) / 44100) * 1000;
-			else stop = -1;
 			LOG_INFO("[%p]: SET PARAMETER progress %d/%u %s", ctx, current, stop, p);
 			success = ctx->cmd_cb(RAOP_PROGRESS, max(current, 0), stop);
 		} else if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && !strcasecmp(p, "application/x-dmap-tagged")) {
@@ -674,7 +673,7 @@ void cleanup_rtsp(raop_ctx_t *ctx, bool abort) {
 		ctx->active_remote.running = false;
 		xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY);
 		vTaskDelete(ctx->active_remote.thread);
-		SAFE_TCB_FREE(ctx->active_remote.xTaskBuffer);
+		SAFE_PTR_FREE(ctx->active_remote.xTaskBuffer);
 		vSemaphoreDelete(ctx->active_remote.thread);
 #endif
 		memset(&ctx->active_remote, 0, sizeof(ctx->active_remote));

+ 1 - 1
components/raop/rtp.c

@@ -313,7 +313,7 @@ void rtp_end(rtp_t *ctx)
 #else
 		ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
 		vTaskDelete(ctx->thread);
-		SAFE_TCB_FREE(ctx->xTaskBuffer);
+		SAFE_PTR_FREE(ctx->xTaskBuffer);
 #endif
 	}
 	

+ 15 - 8
components/raop/util.h

@@ -18,6 +18,11 @@
 #include "platform.h"
 #include "pthread.h"
 
+#ifndef WIN32
+#include "freertos/FreeRTOS.h"
+#include "freertos/timers.h"
+#endif
+
 #define NFREE(p) if (p) { free(p); p = NULL; }
 
 typedef struct metadata_s {
@@ -46,19 +51,21 @@ char 		*strndup(const char *s, size_t n);
 int 		asprintf(char **strp, const char *fmt, ...);
 void 		winsock_init(void);
 void 		winsock_close(void);
-
#else
+#define		SAFE_PTR_FREE(P) free(P)
#else
 char 		*strlwr(char *str);
 
 // reason is that TCB might be cleanup in idle task
-#define SAFE_TCB_FREE(T)							\
+#define SAFE_PTR_FREE(P)							\
 	do {											\
-		int priority = uxTaskPriorityGet(NULL);		\
-		vTaskPrioritySet(NULL, tskIDLE_PRIORITY);	\
-		vTaskDelay(1);								\
-		vTaskPrioritySet(NULL, priority);			\
-		heap_caps_free(T);							\
-	} while (0)
+		TimerHandle_t timer = xTimerCreate("cleanup", pdMS_TO_TICKS(5000), pdFALSE, P, _delayed_free);	\
+		xTimerStart(timer, portMAX_DELAY);			\
+	} while (0)				
+static void inline _delayed_free(TimerHandle_t xTimer) {
+	free(pvTimerGetTimerID(xTimer));
+	xTimerDelete(xTimer, portMAX_DELAY);
+}	
 #endif
+
 char* 		strextract(char *s1, char *beg, char *end);
 in_addr_t 	get_localhost(char **name);
 void 		get_mac(u8_t mac[]);