Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master-cmake' into master-cmake

Conflicts:
	plugin/SqueezeESP32.zip
	plugin/SqueezeESP32/install.xml
	plugin/repo.xml

-- Fix Broken build on CMake-master
Sebastien 4 gadi atpakaļ
vecāks
revīzija
e125ff899f

+ 1 - 1
build-scripts/ESP32-A1S-sdkconfig.defaults

@@ -115,7 +115,7 @@ CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
 CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
 CONFIG_DEFAULT_AP_MAX_CONNECTIONS=4
 CONFIG_DEFAULT_AP_BEACON_INTERVAL=100
-CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"
+CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30 -W"
 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
 CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y

+ 1 - 1
build-scripts/I2S-4MFlash-sdkconfig.defaults

@@ -116,7 +116,7 @@ CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
 CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
 CONFIG_DEFAULT_AP_MAX_CONNECTIONS=4
 CONFIG_DEFAULT_AP_BEACON_INTERVAL=100
-CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"
+CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30 -W"
 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
 CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y

+ 1 - 1
build-scripts/SqueezeAmp4MBFlash-sdkconfig.defaults

@@ -128,7 +128,7 @@ CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
 CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
 CONFIG_DEFAULT_AP_MAX_CONNECTIONS=4
 CONFIG_DEFAULT_AP_BEACON_INTERVAL=100
-CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"
+CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30 -W"
 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
 CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y

+ 1 - 1
build-scripts/SqueezeAmp8MBFlash-sdkconfig.defaults

@@ -127,7 +127,7 @@ CONFIG_DEFAULT_AP_GATEWAY="192.168.4.1"
 CONFIG_DEFAULT_AP_NETMASK="255.255.255.0"
 CONFIG_DEFAULT_AP_MAX_CONNECTIONS=4
 CONFIG_DEFAULT_AP_BEACON_INTERVAL=100
-CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30"
+CONFIG_DEFAULT_COMMAND_LINE="squeezelite -o I2S -b 500:2000 -d all=info -C 30 -W"
 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
 CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y

+ 57 - 5
components/services/audio_controls.c

@@ -11,6 +11,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/timers.h"
 #include "esp_system.h"
 #include "esp_log.h"
 #include "cJSON.h"
@@ -35,6 +37,7 @@ static esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *c
 
 static esp_err_t actrls_init_json(const char *profile_name, bool create);
 static void control_rotary_handler(void *client, rotary_event_e event, bool long_press);
+static void rotary_timer( TimerHandle_t xTimer );
 
 static const actrls_config_map_t actrls_config_map[] =
 		{
@@ -70,6 +73,9 @@ static actrls_ir_handler_t *default_ir_handler, *current_ir_handler;
 static struct {
 	bool long_state;
 	bool volume_lock;
+	TimerHandle_t timer;
+	bool click_pending;
+	int left_count;
 } rotary;
 
 static const struct ir_action_map_s{
@@ -132,8 +138,16 @@ esp_err_t actrls_init(const char *profile_name) {
 		if ((p = strcasestr(config, "A")) != NULL) A = atoi(strchr(p, '=') + 1);
 		if ((p = strcasestr(config, "B")) != NULL) B = atoi(strchr(p, '=') + 1);
 		if ((p = strcasestr(config, "SW")) != NULL) SW = atoi(strchr(p, '=') + 1);
-		if ((p = strcasestr(config, "volume")) != NULL) rotary.volume_lock = true;
-		if ((p = strcasestr(config, "longpress")) != NULL) longpress = 1000;
+		if ((p = strcasestr(config, "knobonly")) != NULL) {
+			p = strchr(p, '=');
+			int double_press = p ? atoi(p + 1) : 350;
+			rotary.timer = xTimerCreate("knobTimer", double_press / portTICK_RATE_MS, pdFALSE, NULL, rotary_timer);
+			longpress = 500;
+			ESP_LOGI(TAG, "single knob navigation %d", double_press);
+		} else {
+			if ((p = strcasestr(config, "volume")) != NULL) rotary.volume_lock = true;
+			if ((p = strcasestr(config, "longpress")) != NULL) longpress = 1000;
+		}	
 				
 		// create rotary (no handling of long press)
 		err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL;
@@ -222,17 +236,42 @@ static void control_rotary_handler(void *client, rotary_event_e event, bool long
 	
 	switch(event) {
 	case ROTARY_LEFT:
-		if (rotary.long_state) action = ACTRLS_PREV;
+		if (rotary.timer) {
+			if (rotary.left_count) {
+				action = KNOB_LEFT;
+				// need to add a left button the first time
+				if (rotary.left_count == 1) (*current_controls[KNOB_LEFT])(true);
+			}
+			xTimerStart(rotary.timer, 20 / portTICK_RATE_MS);
+			rotary.left_count++;
+		}
+		else if (rotary.long_state) action = ACTRLS_PREV;
 		else if (rotary.volume_lock) action = ACTRLS_VOLDOWN;
 		else action = KNOB_LEFT;
 		break;
 	case ROTARY_RIGHT:
-		if (rotary.long_state) action = ACTRLS_NEXT;
+		if (rotary.timer) {
+			if (rotary.left_count == 1) {
+				action = ACTRLS_PAUSE;
+				rotary.left_count = 0;
+				xTimerStop(rotary.timer, 0);
+			} else action = KNOB_RIGHT;
+		}	
+		else if (rotary.long_state) action = ACTRLS_NEXT;
 		else if (rotary.volume_lock) action = ACTRLS_VOLUP;
 		else action = KNOB_RIGHT;
 		break;
 	case ROTARY_PRESSED:
-		if (long_press)	rotary.long_state = !rotary.long_state;
+		if (rotary.timer) {
+			if (long_press) action = ACTRLS_PLAY;
+			else if (rotary.click_pending) {
+				action = BCTRLS_LEFT;
+				xTimerStop(rotary.timer, 0);
+			} 
+			else xTimerStart(rotary.timer, 20 / portTICK_RATE_MS);
+			rotary.click_pending = !rotary.click_pending;
+		} 
+		else if (long_press) rotary.long_state = !rotary.long_state;
 		else if (rotary.volume_lock) action = ACTRLS_TOGGLE;
 		else action = KNOB_PUSH;
 		break;
@@ -243,6 +282,19 @@ static void control_rotary_handler(void *client, rotary_event_e event, bool long
 	if (action != ACTRLS_NONE) (*current_controls[action])(pressed);
 }
 
+/****************************************************************************************
+ * 
+ */
+static void rotary_timer( TimerHandle_t xTimer ) {
+	if (rotary.click_pending) {
+		(*current_controls[KNOB_PUSH])(true);
+		rotary.click_pending = false;
+	} else if (rotary.left_count) {
+		if (rotary.left_count == 1) (*current_controls[KNOB_LEFT])(true);
+		rotary.left_count = 0;
+	}
+}
+
 /****************************************************************************************
  * 
  */

+ 23 - 16
components/squeezelite/controls.c

@@ -49,6 +49,7 @@ struct IR_header {
 static in_addr_t server_ip;
 static u16_t server_hport;
 static u16_t server_cport;
+static int cli_sock = -1;
 static u8_t mac[6];
 static void	(*chained_notify)(in_addr_t, u16_t, u16_t);
 static bool raw_mode;
@@ -243,38 +244,44 @@ const actrls_t LMS_controls = {
  * 
  */
 static void cli_send_cmd(char *cmd) {
-	char packet[64];
-	struct sockaddr_in addr;
-	socklen_t addrlen = sizeof(addr);
-	int len, sock = socket(AF_INET, SOCK_STREAM, 0);
+	char packet[96];
+	int len;
 	
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = server_ip;
-	addr.sin_port = htons(server_cport);
-
-	if (connect(sock, (struct sockaddr *) &addr, addrlen) < 0) {
-		LOG_ERROR("unable to connect to server %s:%hu with cli", inet_ntoa(server_ip), server_cport);
-		return;
-	}
-
 	len = sprintf(packet, "%02x:%02x:%02x:%02x:%02x:%02x %s\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], cmd);
 	LOG_DEBUG("sending command %s at %s:%hu", packet, inet_ntoa(server_ip), server_cport);
 		
-	if (send(sock, packet, len, 0) < 0) {
+	if (send(cli_sock, packet, len, MSG_DONTWAIT) < 0) {
 		LOG_WARN("cannot send CLI %s", packet);
 	}
-
-	closesocket(sock);
+	
+	// need to empty the RX buffer otherwise we'll lock the TCP/IP stack
+	len = recv(cli_sock, packet, 96, MSG_DONTWAIT);
 }
 
 /****************************************************************************************
  * Notification when server changes
  */
 static void notify(in_addr_t ip, u16_t hport, u16_t cport) {
+	struct sockaddr_in addr;
+	socklen_t addrlen = sizeof(addr);
+	
 	server_ip = ip;
 	server_hport = hport;
 	server_cport = cport;
 	
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = server_ip;
+	addr.sin_port = htons(server_cport);
+	
+	// close existing CLI connection and open new one
+	if (cli_sock >= 0) closesocket(cli_sock);
+	cli_sock = socket(AF_INET, SOCK_STREAM, 0);
+
+	if (connect(cli_sock, (struct sockaddr *) &addr, addrlen) < 0) {
+		LOG_ERROR("unable to connect to server %s:%hu with cli", inet_ntoa(server_ip), server_cport);
+		cli_sock = -1;
+	}
+	
 	LOG_INFO("notified server %s hport %hu cport %hu", inet_ntoa(ip), hport, cport);
 	
 	if (chained_notify) (*chained_notify)(ip, hport, cport);

+ 4 - 3
components/squeezelite/display.c

@@ -646,12 +646,13 @@ static void grfb_handler(u8_t *data, int len) {
 	pkt->brightness = htons(pkt->brightness);
 	
 	xSemaphoreTake(displayer.mutex, portMAX_DELAY);
-	
-	if (pkt->brightness < 0) {
+
+	// LMS driver sends 0..5 value, we assume driver is highly log
+	if (pkt->brightness <= 0) {
 		GDS_DisplayOff(display); 
 	} else {
 		GDS_DisplayOn(display);
-		GDS_SetContrast(display, pkt->brightness);
+		GDS_SetContrast(display, 255 * powf(pkt->brightness / 5.0f, 3));
 	}
 	
 	xSemaphoreGive(displayer.mutex);

+ 4 - 2
components/squeezelite/equalizer.c

@@ -26,14 +26,16 @@ static struct {
  * open equalizer
  */
 void equalizer_open(u32_t sample_rate) {
+	// in any case, need to clear update flag
+	equalizer.update = false;
+	
 	if (sample_rate != 11025 && sample_rate != 22050 && sample_rate != 44100 && sample_rate != 48000) {
 		LOG_WARN("equalizer only supports 11025, 22050, 44100 and 48000 sample rates, not %u", sample_rate);
 		return;
 	}	
 	
 	equalizer.handle = esp_equalizer_init(2, sample_rate, EQ_BANDS, 0);
-	equalizer.update = false;
-    
+	    
 	if (equalizer.handle) {
 		bool active = false;
 		

+ 1 - 1
components/wifi-manager/code.js

@@ -50,7 +50,7 @@ var releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases
 var recovery = false;
 var enableAPTimer = true;
 var enableStatusTimer = true;
-var commandHeader = 'squeezelite -b 500:2000 -d all=info ';
+var commandHeader = 'squeezelite -b 500:2000 -d all=info -C 30 -W';
 var pname, ver, otapct, otadsc;
 var blockAjax = false;
 var blockFlashButton = false;

+ 1 - 1
components/wifi-manager/index.html

@@ -232,7 +232,7 @@
 
                     <h1>Squeezelite command to run</h1>
                     <section id="command-list">
-                        <textarea id="autoexec1" maxlength="120">squeezelite -o I2S -b 500:2000 -d all=info -M esp32</textarea>
+                        <textarea id="autoexec1" maxlength="120">squeezelite -o I2S -b 500:2000 -d all=info -C 30 - W</textarea>
                     </section>
                     <div class="buttons">
                         <input id="save-autoexec1" type="button" class="btn btn-success" value="Save" />

BIN
plugin/SqueezeESP32.zip


+ 1 - 1
plugin/SqueezeESP32/Graphics.pm

@@ -88,7 +88,7 @@ sub displayWidth {
 }
 
 sub brightnessMap {
-	return (65535, 10, 50, 100, 200);
+	return (0 .. 5);
 }
 
 =comment

+ 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.93</version>
+    <version>0.94</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.93" name="SqueezeESP32" minTarget="7.9" maxTarget="*">
+    <plugin version="0.94" name="SqueezeESP32" minTarget="7.9" maxTarget="*">
       <link>https://github.com/sle118/squeezelite-esp32</link>
       <creator>Philippe</creator>
-      <sha>42e9a5713355c5c7b8b318f4254a183e9bb86b8f</sha>
+      <sha>a9bf10b47d13508ba051e4067cdabc2c283f4824</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>