Skip to content

Commit 9a8968a

Browse files
committed
Add battery level check and label
1 parent 81f60fe commit 9a8968a

File tree

8 files changed

+135
-43
lines changed

8 files changed

+135
-43
lines changed

src/av.c

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,75 @@ extern struct settings g_settings;
1818

1919
const char *thread_cmd_val_str;
2020

21+
SOCKET GetConnection(void) {
22+
SOCKET socket = INVALID_SOCKET;
23+
24+
if (g_settings.connection == CB_RADIO_IOS) {
25+
socket = CheckiOSDevices(g_settings.port);
26+
if (socket <= 0) socket = INVALID_SOCKET;
27+
} else {
28+
socket = Connect(g_settings.ip, g_settings.port);
29+
}
30+
31+
return socket;
32+
}
33+
34+
// Battry Chcek thread
35+
void *BatteryThreadProc(__attribute__((__unused__)) void *args) {
36+
SOCKET socket = INVALID_SOCKET;
37+
char buf[128];
38+
char battery_value[32];
39+
int i, j;
40+
41+
memset(battery_value, 0, sizeof(battery_value));
42+
dbgprint("Battery Thread Start\n");
43+
44+
usleep(500000);
45+
while (v_running || a_running) {
46+
socket = GetConnection();
47+
if (socket == INVALID_SOCKET) {
48+
goto LOOP;
49+
}
50+
51+
if (Send(BATTERY_REQ, CSTR_LEN(BATTERY_REQ), socket) <= 0) {
52+
errprint("error sending battery status request\n");
53+
goto LOOP;
54+
}
55+
56+
memset(buf, 0, sizeof(buf));
57+
if (Recv(buf, sizeof(buf), socket) <= 0) {
58+
goto LOOP;
59+
}
60+
61+
for (i = 0; i < (sizeof(buf)-4); i++) {
62+
if (buf[i] == '\r' && buf[i+1] == '\n' && buf[i+2] == '\r' && buf[i+3] == '\n') {
63+
i += 4;
64+
break;
65+
}
66+
}
67+
68+
j = 0;
69+
while (i < sizeof(buf) && j < (sizeof(battery_value)-2) && buf[i] >= '0' && buf[i] <= '9')
70+
battery_value[j++] = buf[i++];
71+
72+
if (j == 0)
73+
battery_value[j++] = '-';
74+
75+
battery_value[j++] = '%';
76+
battery_value[sizeof(battery_value) - 1] = 0;
77+
dbgprint("battery_value: %s\n", battery_value);
78+
UpdateBatteryLabel(battery_value);
79+
80+
LOOP:
81+
disconnect(socket);
82+
for (j = 0; j < 30000 && (v_running || a_running); j++)
83+
usleep(1000);
84+
}
85+
86+
dbgprint("Battery Thread End\n");
87+
return 0;
88+
}
89+
2190
void *DecodeThreadProc(__attribute__((__unused__)) void *args) {
2291
dbgprint("Decode Thread Start\n");
2392
while (v_running != 0) {
@@ -48,13 +117,13 @@ void *VideoThreadProc(void *args) {
48117
}
49118

50119
len = snprintf(buf, sizeof(buf), VIDEO_REQ, decoder_get_video_width(), decoder_get_video_height());
51-
if (SendRecv(true, buf, len, videoSocket) <= 0){
120+
if (Send(buf, len, videoSocket) <= 0){
52121
MSG_ERROR("Error sending request, DroidCam might be busy with another client.");
53122
goto early_out;
54123
}
55124

56125
memset(buf, 0, sizeof(buf));
57-
if (SendRecv(false, buf, 9, videoSocket) <= 0) {
126+
if (RecvAll(buf, 9, videoSocket) <= 0) {
58127
MSG_ERROR("Connection reset!\nIs the app running?");
59128
goto early_out;
60129
}
@@ -73,17 +142,17 @@ void *VideoThreadProc(void *args) {
73142
len = snprintf(buf, sizeof(buf), OTHER_REQ, thread_cmd);
74143
}
75144
if (len) {
76-
SendRecv(true, buf, len, videoSocket);
145+
Send(buf, len, videoSocket);
77146
}
78147
thread_cmd = 0;
79148
}
80149

81150
JPGFrame *f = pull_empty_jpg_frame();
82-
if (SendRecv(false, buf, 4, videoSocket) <= 0)
151+
if (RecvAll(buf, 4, videoSocket) <= 0)
83152
break;
84153

85154
f->length = le32toh(*(uint32_t*) buf);
86-
if (SendRecv(false, (char*)f->data, f->length, videoSocket) <= 0)
155+
if (RecvAll((const char*)f->data, f->length, videoSocket) <= 0)
87156
break;
88157

89158
push_jpg_frame(f, false);
@@ -151,25 +220,20 @@ void *AudioThreadProc(void *arg) {
151220
TCP_ONLY:
152221
dbgprint("UDP didnt work, trying TCP\n");
153222
mode = TCP_STREAM;
154-
if (g_settings.connection == CB_RADIO_IOS) {
155-
socket = CheckiOSDevices(g_settings.port);
156-
if (socket <= 0) socket = INVALID_SOCKET;
157-
} else {
158-
socket = Connect(g_settings.ip, g_settings.port);
159-
}
223+
socket = GetConnection();
160224

161225
if (socket == INVALID_SOCKET) {
162-
errprint("Audio: Connect failed to %s:%d\n", g_settings.ip, g_settings.port);
226+
errprint("Audio Connection failed\n");
163227
return 0;
164228
}
165229

166-
if (SendRecv(true, (char*) AUDIO_REQ, CSTR_LEN(AUDIO_REQ), socket) <= 0) {
230+
if (Send(AUDIO_REQ, CSTR_LEN(AUDIO_REQ), socket) <= 0) {
167231
MSG_ERROR("Error sending audio request");
168232
goto early_out;
169233
}
170234

171235
memset(stream_buf, 0, 6);
172-
if (SendRecv(false, stream_buf, 6, socket) <= 0) {
236+
if (RecvAll(stream_buf, 6, socket) <= 0) {
173237
MSG_ERROR("Audio connection reset!");
174238
goto early_out;
175239
}

src/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ void ShowError(const char*, const char*);
2727
#define STOP_REQ "CMD /v1/stop"
2828

2929
#define PING_REQ "CMD /ping"
30+
#define BATTERY_REQ "GET /battery HTTP/1.0\r\n\r\n"
3031

3132
#define CSTR_LEN(x) (sizeof(x)-1)
3233
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))

src/connection.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,26 @@ SOCKET Connect(const char* ip, int port) {
7676
return sock;
7777
}
7878

79-
int SendRecv(int doSend, const char * buffer, int bytes, SOCKET s) {
80-
int retCode;
81-
char * ptr = (char *)buffer;
82-
79+
int Send(const char * buffer, int bytes, SOCKET s) {
80+
ssize_t w = 0;
81+
char *ptr = (char*) buffer;
8382
while (bytes > 0) {
84-
retCode = (doSend) ? send(s, ptr, bytes, 0) : recv(s, ptr, bytes, 0);
85-
if (retCode <= 0 ){ // closed or error
86-
goto _error_out;
83+
w = send(s, ptr, bytes, 0);
84+
if (w <= 0) {
85+
return -1;
8786
}
88-
ptr += retCode;
89-
bytes -= retCode;
87+
bytes -= w;
88+
ptr += w;
9089
}
90+
return 1;
91+
}
9192

92-
retCode = 1;
93+
int Recv(const char* buffer, int bytes, SOCKET s) {
94+
return recv(s, (char*)buffer, bytes, 0);
95+
}
9396

94-
_error_out:
95-
return retCode;
97+
int RecvAll(const char* buffer, int bytes, SOCKET s) {
98+
return recv(s, (char*)buffer, bytes, MSG_WAITALL);
9699
}
97100

98101
int RecvNonBlock(char * buffer, int bytes, SOCKET s) {

src/connection.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ void disconnect(SOCKET s);
1919

2020
SOCKET accept_connection(int port);
2121
SOCKET CreateUdpSocket(void);
22-
int SendRecv(int doSend, const char * buffer, int bytes, SOCKET s);
22+
int Send(const char * buffer, int bytes, SOCKET s);
23+
int Recv(const char * buffer, int bytes, SOCKET s);
24+
int RecvAll(const char * buffer, int bytes, SOCKET s);
2325
int RecvNonBlock(char * buffer, int bytes, SOCKET s);
2426
int RecvNonBlockUDP(char * buffer, int bytes, SOCKET s);
2527
int SendUDPMessage(SOCKET s, const char *message, int length, char *ip, int port);

src/droidcam-cli.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ void ShowError(const char * title, const char * msg) {
4646
errprint("%s: %s\n", title, msg);
4747
}
4848

49+
void UpdateBatteryLabel(char *battery_value) {
50+
(void) battery_value;
51+
}
52+
4953
static inline void usage(__attribute__((__unused__)) int argc, char *argv[]) {
5054
fprintf(stderr, "Usage: \n"
5155
" %s -l <port>\n"
@@ -269,7 +273,7 @@ int main(int argc, char *argv[]) {
269273
if (athread.rc == 0) pthread_join(athread.t, NULL);
270274
if (vthread.rc == 0) pthread_join(vthread.t, NULL);
271275
if (dthread.rc == 0) pthread_join(dthread.t, NULL);
272-
276+
273277
decoder_fini();
274278
dbgprint("exit\n");
275279
return 0;

src/droidcam.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ GtkWidget *wbMenu;
2222
GtkWidget *wbButton;
2323
GtkWidget *elButton;
2424
GtkWidget *infoText;
25+
GtkWidget *batteryText;
2526
GtkWidget *audioCheckbox;
2627
GtkWidget *videoCheckbox;
2728
GtkEntry * ipEntry;
@@ -30,12 +31,12 @@ GtkButton *start_button;
3031
GThread* hVideoThread;
3132
GThread* hAudioThread;
3233
GThread* hDecodeThread;
34+
GThread* hBatteryThread;
3335

3436
char *v4l2_dev = 0;
3537
int a_running = 0;
3638
int v_running = 0;
3739
int thread_cmd = 0;
38-
3940
struct settings g_settings = {0};
4041

4142
extern const char *thread_cmd_val_str;
@@ -46,6 +47,7 @@ const char *APP_ICON_FILE = "/opt/droidcam-icon.png";
4647
void * AudioThreadProc(void * args);
4748
void * VideoThreadProc(void * args);
4849
void * DecodeThreadProc(void * args);
50+
void * BatteryThreadProc(void * args);
4951

5052
const char* wb_options[] = {
5153
"Automatic",
@@ -73,8 +75,7 @@ const char* wb_values[] = {
7375
char title[256];
7476
char msg[256];
7577

76-
gboolean ShowError_GTK(gpointer data)
77-
{
78+
gboolean ShowError_GTK(gpointer data) {
7879
GtkWidget *dialog = gtk_message_dialog_new(NULL,
7980
(GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL),
8081
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
@@ -84,17 +85,19 @@ gboolean ShowError_GTK(gpointer data)
8485
return FALSE;
8586
}
8687

87-
void ShowError(const char* in_title, const char* in_msg)
88-
{
88+
void ShowError(const char* in_title, const char* in_msg) {
8989
strncpy(msg, in_msg, sizeof(msg) - 1);
9090
msg[sizeof(msg) - 1] = '\0';
9191
strncpy(title, in_title, sizeof(title) - 1);
9292
title[sizeof(title) - 1] = '\0';
9393
gdk_threads_add_idle(ShowError_GTK, NULL);
9494
}
9595

96-
static void Stop(void)
97-
{
96+
void UpdateBatteryLabel(char *battery_value) {
97+
gtk_label_set_text(GTK_LABEL(batteryText), battery_value);
98+
}
99+
100+
static void Stop(void) {
98101
a_running = 0;
99102
v_running = 0;
100103
dbgprint("join\n");
@@ -110,14 +113,18 @@ static void Stop(void)
110113
g_thread_join(hDecodeThread);
111114
hDecodeThread = NULL;
112115
}
116+
if (hBatteryThread) {
117+
g_thread_join(hBatteryThread);
118+
hBatteryThread = NULL;
119+
}
113120

114121
gtk_widget_set_sensitive(GTK_WIDGET(elButton), FALSE);
115122
gtk_widget_set_sensitive(GTK_WIDGET(wbButton), FALSE);
116123
gtk_widget_set_sensitive(GTK_WIDGET(menuButton), FALSE);
124+
UpdateBatteryLabel("");
117125
}
118126

119-
static void Start(void)
120-
{
127+
static void Start(void) {
121128
const char* ip = NULL;
122129
SOCKET s = INVALID_SOCKET;
123130
int port = strtoul(gtk_entry_get_text(portEntry), NULL, 10);
@@ -186,6 +193,8 @@ static void Start(void)
186193
hAudioThread = g_thread_new(NULL, AudioThreadProc, NULL);
187194
}
188195

196+
hBatteryThread = g_thread_new(NULL, BatteryThreadProc, NULL);
197+
189198
EARLY_OUT:
190199
gtk_button_set_label(start_button, "Stop");
191200
gtk_widget_set_sensitive(GTK_WIDGET(ipEntry), FALSE);
@@ -584,19 +593,23 @@ int main(int argc, char *argv[])
584593

585594
// Put menu button in the grid, so it's not full column width, but smaller.
586595
menuGrid = gtk_grid_new();
587-
gtk_grid_attach(GTK_GRID(menuGrid), widget, 0, 0, 1, 1);
596+
gtk_grid_attach(GTK_GRID(menuGrid), widget, 0, 1, 1, 1);
597+
598+
// Battery level label
599+
batteryText = gtk_label_new(NULL);
600+
gtk_grid_attach(GTK_GRID(menuGrid), batteryText, 0, 0, 1, 1);
588601

589602
// Add [EL] Menu button
590603
widget = gtk_toggle_button_new_with_label("EL");
591604
gtk_widget_set_tooltip_text(widget, "Exposure Locked");
592605
g_signal_connect(widget, "clicked", G_CALLBACK(the_callback), (gpointer)CB_BTN_EL);
593-
gtk_grid_attach(GTK_GRID(menuGrid), widget, 1, 0, 1, 1);
606+
gtk_grid_attach(GTK_GRID(menuGrid), widget, 1, 1, 1, 1);
594607
elButton = widget;
595608

596609
// Add [...] Menu button
597610
widget = gtk_button_new_with_label("...");
598611
g_signal_connect(widget, "clicked", G_CALLBACK(the_callback), (gpointer)CB_BTN_OTR);
599-
gtk_grid_attach(GTK_GRID(menuGrid), widget, 2, 0, 1, 1);
612+
gtk_grid_attach(GTK_GRID(menuGrid), widget, 2, 1, 1, 1);
600613
menuButton = widget;
601614

602615
// attach the buttons to the column

src/settings.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ void LoadSettings(struct settings* settings) {
8686
}
8787

8888
if (1 == sscanf(buf, "type=%d\n",&settings->connection)) continue;
89+
if (1 == sscanf(buf, "adb_auto_start=%d\n",&settings->adb_auto_start)) continue;
8990
if (1 == sscanf(buf, "confirm_close=%d\n",&settings->confirm_close)) continue;
9091
if (1 == sscanf(buf, "vertical_flip=%d\n",&settings->vertical_flip)) continue;
9192
if (1 == sscanf(buf, "horizontal_flip=%d\n",&settings->horizontal_flip)) continue;
@@ -99,6 +100,7 @@ void LoadSettings(struct settings* settings) {
99100
"settings: audio=%d\n"
100101
"settings: video=%d\n"
101102
"settings: size=%dx%d\n"
103+
"settings: adb_auto_start=%d\n"
102104
"settings: confirm_close=%d\n"
103105
"settings: vertical_flip=%d\n"
104106
"settings: horizontal_flip=%d\n"
@@ -109,6 +111,7 @@ void LoadSettings(struct settings* settings) {
109111
settings->audio,
110112
settings->video,
111113
settings->v4l2_width, settings->v4l2_height,
114+
settings->adb_auto_start,
112115
settings->confirm_close,
113116
settings->vertical_flip,
114117
settings->horizontal_flip,
@@ -127,6 +130,7 @@ void SaveSettings(struct settings* settings) {
127130
"audio=%d\n"
128131
"video=%d\n"
129132
"size=%dx%d\n"
133+
// TODO "adb_auto_start=%d\n"
130134
"confirm_close=%d\n"
131135
"vertical_flip=%d\n"
132136
"horizontal_flip=%d\n"

0 commit comments

Comments
 (0)