From c8bd4a25fcc8b868b17e376dfaa33770df822c2d Mon Sep 17 00:00:00 2001 From: skbeh <60107333+skbeh@users.noreply.github.com> Date: Wed, 5 Oct 2022 23:01:52 +0800 Subject: [PATCH] fix gtk warning and battery level not shown 1. Not reset gtk widgets when gtk main loop has stopped. 2. Wait until battery level info is received (currently always 1s), because level info is actually sent later so mostly `recv` returns before the client sends. --- src/av.c | 66 +++++++++++++++++++++++++++++++++--------------- src/connection.c | 16 ++++++------ src/connection.h | 15 ++++++----- src/droidcam.c | 11 +++++--- 4 files changed, 70 insertions(+), 38 deletions(-) diff --git a/src/av.c b/src/av.c index 851c99f..e157e93 100644 --- a/src/av.c +++ b/src/av.c @@ -12,6 +12,8 @@ #include "decoder.h" #include #include +#include +#include extern atomic_bool a_running; extern atomic_bool v_running; @@ -37,52 +39,76 @@ SOCKET GetConnection(void) { // Battry Check thread void *BatteryThreadProc(__attribute__((__unused__)) void *args) { SOCKET socket = INVALID_SOCKET; - char buf[128]; - char battery_value[32]; - int i, j; + char buf[96]; + char battery_value[5]; + struct timeval tv = {0}; + tv.tv_sec = 1; - memset(battery_value, 0, sizeof(battery_value)); dbgprint("Battery Thread Start\n"); usleep(500000); while (v_running || a_running) { + uint8_t battery_value_pos = 0; + size_t percent_len = 0; + socket = GetConnection(); if (socket == INVALID_SOCKET) { goto LOOP; } - if (Send(BATTERY_REQ, CSTR_LEN(BATTERY_REQ), socket) <= 0) { + if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, + sizeof(tv)) == -1) { + goto LOOP; + }; + + if (!Send(BATTERY_REQ, CSTR_LEN(BATTERY_REQ), socket)) { errprint("error sending battery status request\n"); goto LOOP; } memset(buf, 0, sizeof(buf)); - if (Recv(buf, sizeof(buf), socket) <= 0) { + memset(battery_value, 0, sizeof(battery_value)); + if (RecvAll(buf, sizeof(buf), socket) <= 0) { goto LOOP; } - for (i = 0; i < (sizeof(buf)-4); i++) { - if (buf[i] == '\r' && buf[i+1] == '\n' && buf[i+2] == '\r' && buf[i+3] == '\n') { - i += 4; - break; + for (uint8_t i = 0; i < (sizeof(buf) - 4); i += 4) { + char *tmp = memchr(&buf[i], '\r', sizeof(buf)); + if (!tmp) { + goto LOOP; + } + if (memcmp(tmp + 1, "\n\r\n", 3) == 0) { + battery_value_pos = (tmp - buf) + 4; + break; } } + if (!battery_value_pos || battery_value_pos > (sizeof(buf) - (4 + 1)) || + buf[battery_value_pos] == '0') { + goto LOOP; + } - j = 0; - while (i < sizeof(buf) && j < (sizeof(battery_value)-2) && buf[i] >= '0' && buf[i] <= '9') - battery_value[j++] = buf[i++]; + for (uint8_t j = 0; j < 3; j++) { + if (buf[battery_value_pos + j] >= '0' && + buf[battery_value_pos + j] <= '9') { + battery_value[j] = buf[battery_value_pos + j]; + percent_len++; + } else { + break; + } + } - if (j == 0) - battery_value[j++] = '-'; + if (percent_len == 0) { + battery_value[0] = '-'; + percent_len = 1; + } - battery_value[j++] = '%'; - battery_value[sizeof(battery_value) - 1] = 0; + battery_value[percent_len] = '%'; dbgprint("battery_value: %s\n", battery_value); UpdateBatteryLabel(battery_value); LOOP: disconnect(socket); - for (j = 0; j < 30000 && (v_running || a_running); j++) + for (uint16_t i = 0; i < 30000 && (v_running || a_running); i++) usleep(1000); } @@ -120,7 +146,7 @@ void *VideoThreadProc(void *args) { } len = snprintf(buf, sizeof(buf), VIDEO_REQ, decoder_get_video_width(), decoder_get_video_height()); - if (Send(buf, len, videoSocket) <= 0){ + if (!Send(buf, len, videoSocket)){ MSG_ERROR("Error sending request, DroidCam might be busy with another client."); goto early_out; } @@ -229,7 +255,7 @@ void *AudioThreadProc(void *arg) { return 0; } - if (Send(AUDIO_REQ, CSTR_LEN(AUDIO_REQ), socket) <= 0) { + if (!Send(AUDIO_REQ, CSTR_LEN(AUDIO_REQ), socket)) { MSG_ERROR("Error sending audio request"); goto early_out; } diff --git a/src/connection.c b/src/connection.c index 5a923f5..e5b8efc 100644 --- a/src/connection.c +++ b/src/connection.c @@ -85,41 +85,41 @@ SOCKET Connect(const char* ip, int port, const char **errormsg) { return sock; } -int Send(const char * buffer, int bytes, SOCKET s) { +bool Send(const char * buffer, int bytes, SOCKET s) { ssize_t w = 0; char *ptr = (char*) buffer; while (bytes > 0) { w = send(s, ptr, bytes, 0); if (w <= 0) { - return -1; + return false; } bytes -= w; ptr += w; } - return 1; + return true; } -int Recv(const char* buffer, int bytes, SOCKET s) { +ssize_t Recv(const char* buffer, int bytes, SOCKET s) { return recv(s, (char*)buffer, bytes, 0); } -int RecvAll(const char* buffer, int bytes, SOCKET s) { +ssize_t RecvAll(const char* buffer, int bytes, SOCKET s) { return recv(s, (char*)buffer, bytes, MSG_WAITALL); } -int RecvNonBlock(char * buffer, int bytes, SOCKET s) { +ssize_t RecvNonBlock(char * buffer, int bytes, SOCKET s) { int res = recv(s, buffer, bytes, MSG_DONTWAIT); return (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) ? 0 : res; } -int RecvNonBlockUDP(char * buffer, int bytes, SOCKET s) { +ssize_t RecvNonBlockUDP(char * buffer, int bytes, SOCKET s) { struct sockaddr_in from; socklen_t fromLen = sizeof(from); int res = recvfrom(s, buffer, bytes, MSG_DONTWAIT, (struct sockaddr *)&from, &fromLen); return (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) ? 0 : res; } -int SendUDPMessage(SOCKET s, const char *message, int length, char *ip, int port) { +ssize_t SendUDPMessage(SOCKET s, const char *message, int length, char *ip, int port) { struct sockaddr_in sin; sin.sin_port = htons((uint16_t)port); sin.sin_family = AF_INET; diff --git a/src/connection.h b/src/connection.h index 37a2668..f00afb8 100644 --- a/src/connection.h +++ b/src/connection.h @@ -9,6 +9,9 @@ #ifndef __CONN_H__ #define __CONN_H__ +#include +#include + #define INVALID_SOCKET -1 typedef int SOCKET; typedef long int SOCKET_PTR; @@ -19,11 +22,11 @@ void disconnect(SOCKET s); SOCKET accept_connection(int port); SOCKET CreateUdpSocket(void); -int Send(const char * buffer, int bytes, SOCKET s); -int Recv(const char * buffer, int bytes, SOCKET s); -int RecvAll(const char * buffer, int bytes, SOCKET s); -int RecvNonBlock(char * buffer, int bytes, SOCKET s); -int RecvNonBlockUDP(char * buffer, int bytes, SOCKET s); -int SendUDPMessage(SOCKET s, const char *message, int length, char *ip, int port); +bool Send(const char * buffer, int bytes, SOCKET s); +ssize_t Recv(const char * buffer, int bytes, SOCKET s); +ssize_t RecvAll(const char * buffer, int bytes, SOCKET s); +ssize_t RecvNonBlock(char * buffer, int bytes, SOCKET s); +ssize_t RecvNonBlockUDP(char * buffer, int bytes, SOCKET s); +ssize_t SendUDPMessage(SOCKET s, const char *message, int length, char *ip, int port); #endif diff --git a/src/droidcam.c b/src/droidcam.c index 9a466b6..cf10336 100644 --- a/src/droidcam.c +++ b/src/droidcam.c @@ -105,7 +105,7 @@ void UpdateBatteryLabel(char *battery_value) { gtk_label_set_text(GTK_LABEL(batteryText), battery_value); } -static void Stop(void) { +static void stop_av(void) { a_running = false; v_running = false; dbgprint("join\n"); @@ -125,7 +125,9 @@ static void Stop(void) { g_thread_join(hBatteryThread); hBatteryThread = NULL; } +} +static void reset_ui(void) { gtk_widget_set_sensitive(GTK_WIDGET(elButton), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(wbButton), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(menuButton), FALSE); @@ -255,7 +257,8 @@ static void the_callback(GtkWidget* widget, gpointer extra) switch (cb) { case CB_BUTTON: if (v_running || a_running) { - Stop(); + reset_ui(); + stop_av(); cb = (int)g_settings.connection; goto _up; } @@ -664,7 +667,7 @@ int main(int argc, char *argv[]) g_signal_connect(window, "delete-event", G_CALLBACK(delete_window_callback), window); gtk_widget_show_all(window); - Stop(); // reset the UI + reset_ui(); LoadSettings(&g_settings); if (argc >= 1) { parse_args(argc, argv); @@ -711,7 +714,7 @@ int main(int argc, char *argv[]) // main loop gtk_main(); - Stop(); + stop_av(); decoder_fini(); connection_cleanup(); SaveSettings(&g_settings);