diff --git a/build_parser.sh b/build_parser.sh index 3f2417a..ebcbdc2 100755 --- a/build_parser.sh +++ b/build_parser.sh @@ -3,3 +3,6 @@ echo "-- Building parser from Ragel source --" ragel -L -G0 user/ansi_parser.rl -o user/ansi_parser.c + +sed -i "s/static const char _ansi_actions\[\]/static const char _ansi_actions\[\] ESP_CONST_DATA/" user/ansi_parser.c +sed -i "s/static const char _ansi_eof_actions\[\]/static const char _ansi_eof_actions\[\] ESP_CONST_DATA/" user/ansi_parser.c diff --git a/user/ansi_parser.c b/user/ansi_parser.c index 3f53c87..7b01ded 100644 --- a/user/ansi_parser.c +++ b/user/ansi_parser.c @@ -9,7 +9,7 @@ /* Ragel constants block */ /* #line 12 "user/ansi_parser.c" */ -static const char _ansi_actions[] = { +static const char _ansi_actions[] ESP_CONST_DATA = { 0, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, @@ -17,7 +17,7 @@ static const char _ansi_actions[] = { 15 }; -static const char _ansi_eof_actions[] = { +static const char _ansi_eof_actions[] ESP_CONST_DATA = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }; diff --git a/user/cgi_sockets.c b/user/cgi_sockets.c index 2c58514..f3adcb8 100644 --- a/user/cgi_sockets.c +++ b/user/cgi_sockets.c @@ -8,7 +8,6 @@ #include "ansi_parser.h" #include "jstring.h" #include "uart_driver.h" -#include "cgi_logging.h" // Heartbeat interval in ms #define HB_TIME 1000 @@ -17,9 +16,12 @@ // Must be less than httpd sendbuf #define SOCK_BUF_LEN 2000 +// flags for screen update timeouts volatile bool notify_available = true; volatile bool notify_cooldown = false; +/** True if we sent XOFF to browser to stop uploading, + * and we have to tell it we're ready again */ volatile bool browser_wants_xon = false; static ETSTimer notifyContentTim; @@ -27,6 +29,8 @@ static ETSTimer notifyLabelsTim; static ETSTimer notifyCooldownTim; static ETSTimer heartbeatTim; +volatile int active_clients = 0; + // we're trying to do a kind of mutex here, without the actual primitives // this might glitch, very rarely. // it's recommended to put some delay between setting labels and updating the screen. @@ -115,6 +119,8 @@ notifyLabelsTimCb(void *arg) void ICACHE_FLASH_ATTR send_beep(void) { + if (active_clients == 0) return; + // here's some potential for a race error with the other broadcast functions :C cgiWebsockBroadcast(URL_WS_UPDATE, "B", 1, 0); } @@ -124,6 +130,8 @@ send_beep(void) void ICACHE_FLASH_ATTR notify_growl(char *msg) { + if (active_clients == 0) return; + // TODO via timer... // here's some potential for a race error with the other broadcast functions :C cgiWebsockBroadcast(URL_WS_UPDATE, msg, (int) strlen(msg), 0); @@ -137,8 +145,9 @@ notify_growl(char *msg) */ void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyChangeTopic topic) { - // this is not the most ideal/cleanest implementation - // PRs are welcome for a nicer update "queue" solution + if (active_clients == 0) return; + + // this is probably not needed here - ensure timeout is not 0 if (termconf->display_tout_ms == 0) termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS; // NOTE: the timers are restarted if already running @@ -297,20 +306,44 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags) /** Send a heartbeat msg */ void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused) { - if (notify_available) { + if (notify_available && active_clients > 0) { // Heartbeat packet - indicate we're still connected // JS reloads the page if heartbeat is lost for a couple seconds cgiWebsockBroadcast(URL_WS_UPDATE, ".", 1, 0); } } +void ICACHE_FLASH_ATTR closeSockCb(Websock *ws) +{ + active_clients--; + if (active_clients <= 0) { + active_clients = 0; + + if (mouse_tracking.focus_tracking) { + UART_SendAsync("\x1b[O", 3); + } + + // stop the timer + os_timer_disarm(&heartbeatTim); + } +} + /** Socket connected for updates */ void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws) { inp_info("Socket connected to "URL_WS_UPDATE); ws->recvCb = updateSockRx; + ws->closeCb = closeSockCb; + + if (active_clients == 0) { + if (mouse_tracking.focus_tracking) { + UART_SendAsync("\x1b[I", 3); + } + + TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 1); + } - TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 1); + active_clients++; } ETSTimer xonTim; diff --git a/user/user_main.c b/user/user_main.c index e56f597..7b9a98f 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -79,7 +79,6 @@ static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) // Deferred init static void user_start(void *unused); -static void user_start2(void *unused); static ETSTimer userStartTimer; static ETSTimer prHeapTimer; @@ -121,7 +120,6 @@ void ICACHE_FLASH_ATTR user_init(void) TIMER_START(&userStartTimer, user_start, 10, 0); } - static void ICACHE_FLASH_ATTR user_start(void *unused) { // Load and apply stored settings, or defaults if stored settings are invalid