Add device event receiver

Create a separate component to handle device events, managed by the
controller.
This commit is contained in:
Romain Vimont 2019-05-30 00:25:37 +02:00
parent f9d2d99166
commit 6112095e75
5 changed files with 158 additions and 0 deletions

View file

@ -12,6 +12,7 @@ src = [
'src/input_manager.c', 'src/input_manager.c',
'src/lock_util.c', 'src/lock_util.c',
'src/net.c', 'src/net.c',
'src/receiver.c',
'src/recorder.c', 'src/recorder.c',
'src/scrcpy.c', 'src/scrcpy.c',
'src/screen.c', 'src/screen.c',

View file

@ -10,11 +10,17 @@ bool
controller_init(struct controller *controller, socket_t control_socket) { controller_init(struct controller *controller, socket_t control_socket) {
cbuf_init(&controller->queue); cbuf_init(&controller->queue);
if (!receiver_init(&controller->receiver, control_socket)) {
return false;
}
if (!(controller->mutex = SDL_CreateMutex())) { if (!(controller->mutex = SDL_CreateMutex())) {
receiver_destroy(&controller->receiver);
return false; return false;
} }
if (!(controller->event_cond = SDL_CreateCond())) { if (!(controller->event_cond = SDL_CreateCond())) {
receiver_destroy(&controller->receiver);
SDL_DestroyMutex(controller->mutex); SDL_DestroyMutex(controller->mutex);
return false; return false;
} }
@ -34,6 +40,8 @@ controller_destroy(struct controller *controller) {
while (cbuf_take(&controller->queue, &event)) { while (cbuf_take(&controller->queue, &event)) {
control_event_destroy(&event); control_event_destroy(&event);
} }
receiver_destroy(&controller->receiver);
} }
bool bool
@ -101,6 +109,12 @@ controller_start(struct controller *controller) {
return false; return false;
} }
if (!receiver_start(&controller->receiver)) {
controller_stop(controller);
SDL_WaitThread(controller->thread, NULL);
return false;
}
return true; return true;
} }
@ -115,4 +129,5 @@ controller_stop(struct controller *controller) {
void void
controller_join(struct controller *controller) { controller_join(struct controller *controller) {
SDL_WaitThread(controller->thread, NULL); SDL_WaitThread(controller->thread, NULL);
receiver_join(&controller->receiver);
} }

View file

@ -8,6 +8,7 @@
#include "cbuf.h" #include "cbuf.h"
#include "control_event.h" #include "control_event.h"
#include "net.h" #include "net.h"
#include "receiver.h"
struct control_event_queue CBUF(struct control_event, 64); struct control_event_queue CBUF(struct control_event, 64);
@ -18,6 +19,7 @@ struct controller {
SDL_cond *event_cond; SDL_cond *event_cond;
bool stopped; bool stopped;
struct control_event_queue queue; struct control_event_queue queue;
struct receiver receiver;
}; };
bool bool

108
app/src/receiver.c Normal file
View file

@ -0,0 +1,108 @@
#include "receiver.h"
#include <SDL2/SDL_assert.h>
#include <SDL2/SDL_clipboard.h>
#include "config.h"
#include "device_event.h"
#include "events.h"
#include "lock_util.h"
#include "log.h"
bool
receiver_init(struct receiver *receiver, socket_t control_socket) {
if (!(receiver->mutex = SDL_CreateMutex())) {
return false;
}
receiver->control_socket = control_socket;
return true;
}
void
receiver_destroy(struct receiver *receiver) {
SDL_DestroyMutex(receiver->mutex);
}
static void
process_event(struct receiver *receiver, struct device_event *event) {
switch (event->type) {
case DEVICE_EVENT_TYPE_GET_CLIPBOARD:
SDL_SetClipboardText(event->clipboard_event.text);
break;
}
}
static ssize_t
process_events(struct receiver *receiver, const unsigned char *buf,
size_t len) {
size_t head = 0;
for (;;) {
struct device_event event;
ssize_t r = device_event_deserialize(&buf[head], len - head, &event);
if (r == -1) {
return -1;
}
if (r == 0) {
return head;
}
process_event(receiver, &event);
device_event_destroy(&event);
head += r;
SDL_assert(head <= len);
if (head == len) {
return head;
}
}
}
static int
run_receiver(void *data) {
struct receiver *receiver = data;
unsigned char buf[DEVICE_EVENT_SERIALIZED_MAX_SIZE];
size_t head = 0;
for (;;) {
SDL_assert(head < DEVICE_EVENT_SERIALIZED_MAX_SIZE);
ssize_t r = net_recv(receiver->control_socket, buf,
DEVICE_EVENT_SERIALIZED_MAX_SIZE - head);
if (r <= 0) {
LOGD("Receiver stopped");
break;
}
ssize_t consumed = process_events(receiver, buf, r);
if (consumed == -1) {
// an error occurred
break;
}
if (consumed) {
// shift the remaining data in the buffer
memmove(buf, &buf[consumed], r - consumed);
head = r - consumed;
}
}
return 0;
}
bool
receiver_start(struct receiver *receiver) {
LOGD("Starting receiver thread");
receiver->thread = SDL_CreateThread(run_receiver, "receiver", receiver);
if (!receiver->thread) {
LOGC("Could not start receiver thread");
return false;
}
return true;
}
void
receiver_join(struct receiver *receiver) {
SDL_WaitThread(receiver->thread, NULL);
}

32
app/src/receiver.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef RECEIVER_H
#define RECEIVER_H
#include <stdbool.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_thread.h>
#include "net.h"
// receive events from the device
// managed by the controller
struct receiver {
socket_t control_socket;
SDL_Thread *thread;
SDL_mutex *mutex;
};
bool
receiver_init(struct receiver *receiver, socket_t control_socket);
void
receiver_destroy(struct receiver *receiver);
bool
receiver_start(struct receiver *receiver);
// no receiver_stop(), it will automatically stop on control_socket shutdown
void
receiver_join(struct receiver *receiver);
#endif