mirror of
https://github.com/Genymobile/scrcpy
synced 2024-12-22 07:10:34 +00:00
Add device event receiver
Create a separate component to handle device events, managed by the controller.
This commit is contained in:
parent
f9d2d99166
commit
6112095e75
@ -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',
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
108
app/src/receiver.c
Normal file
108
app/src/receiver.c
Normal 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
32
app/src/receiver.h
Normal 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
|
Loading…
Reference in New Issue
Block a user