From 6112095e756cc93a2ba16e81c228a876ae66d07d Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 30 May 2019 00:25:37 +0200 Subject: [PATCH] Add device event receiver Create a separate component to handle device events, managed by the controller. --- app/meson.build | 1 + app/src/controller.c | 15 ++++++ app/src/controller.h | 2 + app/src/receiver.c | 108 +++++++++++++++++++++++++++++++++++++++++++ app/src/receiver.h | 32 +++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 app/src/receiver.c create mode 100644 app/src/receiver.h diff --git a/app/meson.build b/app/meson.build index 326a6656..5e832537 100644 --- a/app/meson.build +++ b/app/meson.build @@ -12,6 +12,7 @@ src = [ 'src/input_manager.c', 'src/lock_util.c', 'src/net.c', + 'src/receiver.c', 'src/recorder.c', 'src/scrcpy.c', 'src/screen.c', diff --git a/app/src/controller.c b/app/src/controller.c index 5e74daba..53ea2e26 100644 --- a/app/src/controller.c +++ b/app/src/controller.c @@ -10,11 +10,17 @@ bool controller_init(struct controller *controller, socket_t control_socket) { cbuf_init(&controller->queue); + if (!receiver_init(&controller->receiver, control_socket)) { + return false; + } + if (!(controller->mutex = SDL_CreateMutex())) { + receiver_destroy(&controller->receiver); return false; } if (!(controller->event_cond = SDL_CreateCond())) { + receiver_destroy(&controller->receiver); SDL_DestroyMutex(controller->mutex); return false; } @@ -34,6 +40,8 @@ controller_destroy(struct controller *controller) { while (cbuf_take(&controller->queue, &event)) { control_event_destroy(&event); } + + receiver_destroy(&controller->receiver); } bool @@ -101,6 +109,12 @@ controller_start(struct controller *controller) { return false; } + if (!receiver_start(&controller->receiver)) { + controller_stop(controller); + SDL_WaitThread(controller->thread, NULL); + return false; + } + return true; } @@ -115,4 +129,5 @@ controller_stop(struct controller *controller) { void controller_join(struct controller *controller) { SDL_WaitThread(controller->thread, NULL); + receiver_join(&controller->receiver); } diff --git a/app/src/controller.h b/app/src/controller.h index c006b791..a54859a7 100644 --- a/app/src/controller.h +++ b/app/src/controller.h @@ -8,6 +8,7 @@ #include "cbuf.h" #include "control_event.h" #include "net.h" +#include "receiver.h" struct control_event_queue CBUF(struct control_event, 64); @@ -18,6 +19,7 @@ struct controller { SDL_cond *event_cond; bool stopped; struct control_event_queue queue; + struct receiver receiver; }; bool diff --git a/app/src/receiver.c b/app/src/receiver.c new file mode 100644 index 00000000..683b61fa --- /dev/null +++ b/app/src/receiver.c @@ -0,0 +1,108 @@ +#include "receiver.h" + +#include +#include + +#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); +} diff --git a/app/src/receiver.h b/app/src/receiver.h new file mode 100644 index 00000000..c119b827 --- /dev/null +++ b/app/src/receiver.h @@ -0,0 +1,32 @@ +#ifndef RECEIVER_H +#define RECEIVER_H + +#include +#include +#include + +#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