Update code style
Limit source code to 80 chars, and declare functions return type and modifiers on a separate line. This allows to avoid very long lines, and all function names are aligned. (We do this on VLC, and I like it.)
This commit is contained in:
parent
b2fe005498
commit
aeda583a2c
45 changed files with 813 additions and 409 deletions
|
@ -3,23 +3,27 @@
|
||||||
|
|
||||||
#include <SDL2/SDL_stdinc.h>
|
#include <SDL2/SDL_stdinc.h>
|
||||||
|
|
||||||
static inline void buffer_write16be(Uint8 *buf, Uint16 value) {
|
static inline void
|
||||||
|
buffer_write16be(Uint8 *buf, Uint16 value) {
|
||||||
buf[0] = value >> 8;
|
buf[0] = value >> 8;
|
||||||
buf[1] = value;
|
buf[1] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void buffer_write32be(Uint8 *buf, Uint32 value) {
|
static inline void
|
||||||
|
buffer_write32be(Uint8 *buf, Uint32 value) {
|
||||||
buf[0] = value >> 24;
|
buf[0] = value >> 24;
|
||||||
buf[1] = value >> 16;
|
buf[1] = value >> 16;
|
||||||
buf[2] = value >> 8;
|
buf[2] = value >> 8;
|
||||||
buf[3] = value;
|
buf[3] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Uint32 buffer_read32be(Uint8 *buf) {
|
static inline Uint32
|
||||||
|
buffer_read32be(Uint8 *buf) {
|
||||||
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Uint64 buffer_read64be(Uint8 *buf) {
|
static inline
|
||||||
|
Uint64 buffer_read64be(Uint8 *buf) {
|
||||||
Uint32 msb = buffer_read32be(buf);
|
Uint32 msb = buffer_read32be(buf);
|
||||||
Uint32 lsb = buffer_read32be(&buf[4]);
|
Uint32 lsb = buffer_read32be(&buf[4]);
|
||||||
return ((Uint64) msb << 32) | lsb;
|
return ((Uint64) msb << 32) | lsb;
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
static const char *adb_command;
|
static const char *adb_command;
|
||||||
|
|
||||||
static inline const char *get_adb_command(void) {
|
static inline const char *
|
||||||
|
get_adb_command(void) {
|
||||||
if (!adb_command) {
|
if (!adb_command) {
|
||||||
adb_command = getenv("ADB");
|
adb_command = getenv("ADB");
|
||||||
if (!adb_command)
|
if (!adb_command)
|
||||||
|
@ -19,7 +20,8 @@ static inline const char *get_adb_command(void) {
|
||||||
return adb_command;
|
return adb_command;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_adb_err_msg(enum process_result err) {
|
static void
|
||||||
|
show_adb_err_msg(enum process_result err) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case PROCESS_ERROR_GENERIC:
|
case PROCESS_ERROR_GENERIC:
|
||||||
LOGE("Failed to execute adb");
|
LOGE("Failed to execute adb");
|
||||||
|
@ -34,7 +36,8 @@ static void show_adb_err_msg(enum process_result err) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_execute(const char *serial, const char *const adb_cmd[], int len) {
|
process_t
|
||||||
|
adb_execute(const char *serial, const char *const adb_cmd[], int len) {
|
||||||
const char *cmd[len + 4];
|
const char *cmd[len + 4];
|
||||||
int i;
|
int i;
|
||||||
process_t process;
|
process_t process;
|
||||||
|
@ -57,7 +60,9 @@ process_t adb_execute(const char *serial, const char *const adb_cmd[], int len)
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_forward(const char *serial, uint16_t local_port, const char *device_socket_name) {
|
process_t
|
||||||
|
adb_forward(const char *serial, uint16_t local_port,
|
||||||
|
const char *device_socket_name) {
|
||||||
char local[4 + 5 + 1]; // tcp:PORT
|
char local[4 + 5 + 1]; // tcp:PORT
|
||||||
char remote[108 + 14 + 1]; // localabstract:NAME
|
char remote[108 + 14 + 1]; // localabstract:NAME
|
||||||
sprintf(local, "tcp:%" PRIu16, local_port);
|
sprintf(local, "tcp:%" PRIu16, local_port);
|
||||||
|
@ -66,14 +71,17 @@ process_t adb_forward(const char *serial, uint16_t local_port, const char *devic
|
||||||
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_forward_remove(const char *serial, uint16_t local_port) {
|
process_t
|
||||||
|
adb_forward_remove(const char *serial, uint16_t local_port) {
|
||||||
char local[4 + 5 + 1]; // tcp:PORT
|
char local[4 + 5 + 1]; // tcp:PORT
|
||||||
sprintf(local, "tcp:%" PRIu16, local_port);
|
sprintf(local, "tcp:%" PRIu16, local_port);
|
||||||
const char *const adb_cmd[] = {"forward", "--remove", local};
|
const char *const adb_cmd[] = {"forward", "--remove", local};
|
||||||
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_reverse(const char *serial, const char *device_socket_name, uint16_t local_port) {
|
process_t
|
||||||
|
adb_reverse(const char *serial, const char *device_socket_name,
|
||||||
|
uint16_t local_port) {
|
||||||
char local[4 + 5 + 1]; // tcp:PORT
|
char local[4 + 5 + 1]; // tcp:PORT
|
||||||
char remote[108 + 14 + 1]; // localabstract:NAME
|
char remote[108 + 14 + 1]; // localabstract:NAME
|
||||||
sprintf(local, "tcp:%" PRIu16, local_port);
|
sprintf(local, "tcp:%" PRIu16, local_port);
|
||||||
|
@ -82,14 +90,16 @@ process_t adb_reverse(const char *serial, const char *device_socket_name, uint16
|
||||||
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_reverse_remove(const char *serial, const char *device_socket_name) {
|
process_t
|
||||||
|
adb_reverse_remove(const char *serial, const char *device_socket_name) {
|
||||||
char remote[108 + 14 + 1]; // localabstract:NAME
|
char remote[108 + 14 + 1]; // localabstract:NAME
|
||||||
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
|
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
|
||||||
const char *const adb_cmd[] = {"reverse", "--remove", remote};
|
const char *const adb_cmd[] = {"reverse", "--remove", remote};
|
||||||
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_push(const char *serial, const char *local, const char *remote) {
|
process_t
|
||||||
|
adb_push(const char *serial, const char *local, const char *remote) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// Windows will parse the string, so the paths must be quoted
|
// Windows will parse the string, so the paths must be quoted
|
||||||
// (see sys/win/command.c)
|
// (see sys/win/command.c)
|
||||||
|
@ -115,7 +125,8 @@ process_t adb_push(const char *serial, const char *local, const char *remote) {
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t adb_install(const char *serial, const char *local) {
|
process_t
|
||||||
|
adb_install(const char *serial, const char *local) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// Windows will parse the string, so the local name must be quoted
|
// Windows will parse the string, so the local name must be quoted
|
||||||
// (see sys/win/command.c)
|
// (see sys/win/command.c)
|
||||||
|
@ -135,7 +146,8 @@ process_t adb_install(const char *serial, const char *local) {
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool process_check_success(process_t proc, const char *name) {
|
SDL_bool
|
||||||
|
process_check_success(process_t proc, const char *name) {
|
||||||
if (proc == PROCESS_NONE) {
|
if (proc == PROCESS_NONE) {
|
||||||
LOGE("Could not execute \"%s\"", name);
|
LOGE("Could not execute \"%s\"", name);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
# include <winsock2.h> // not needed here, but must never be included AFTER windows.h
|
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||||
|
# include <winsock2.h>
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# define PRIexitcode "lu"
|
# define PRIexitcode "lu"
|
||||||
// <https://stackoverflow.com/a/44383330/1987178>
|
// <https://stackoverflow.com/a/44383330/1987178>
|
||||||
|
@ -38,20 +39,41 @@ enum process_result {
|
||||||
PROCESS_ERROR_MISSING_BINARY,
|
PROCESS_ERROR_MISSING_BINARY,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum process_result cmd_execute(const char *path, const char *const argv[], process_t *process);
|
enum process_result
|
||||||
SDL_bool cmd_terminate(process_t pid);
|
cmd_execute(const char *path, const char *const argv[], process_t *process);
|
||||||
SDL_bool cmd_simple_wait(process_t pid, exit_code_t *exit_code);
|
|
||||||
|
|
||||||
process_t adb_execute(const char *serial, const char *const adb_cmd[], int len);
|
SDL_bool
|
||||||
process_t adb_forward(const char *serial, uint16_t local_port, const char *device_socket_name);
|
cmd_terminate(process_t pid);
|
||||||
process_t adb_forward_remove(const char *serial, uint16_t local_port);
|
|
||||||
process_t adb_reverse(const char *serial, const char *device_socket_name, uint16_t local_port);
|
SDL_bool
|
||||||
process_t adb_reverse_remove(const char *serial, const char *device_socket_name);
|
cmd_simple_wait(process_t pid, exit_code_t *exit_code);
|
||||||
process_t adb_push(const char *serial, const char *local, const char *remote);
|
|
||||||
process_t adb_install(const char *serial, const char *local);
|
process_t
|
||||||
|
adb_execute(const char *serial, const char *const adb_cmd[], int len);
|
||||||
|
|
||||||
|
process_t
|
||||||
|
adb_forward(const char *serial, uint16_t local_port,
|
||||||
|
const char *device_socket_name);
|
||||||
|
|
||||||
|
process_t
|
||||||
|
adb_forward_remove(const char *serial, uint16_t local_port);
|
||||||
|
|
||||||
|
process_t
|
||||||
|
adb_reverse(const char *serial, const char *device_socket_name,
|
||||||
|
uint16_t local_port);
|
||||||
|
|
||||||
|
process_t
|
||||||
|
adb_reverse_remove(const char *serial, const char *device_socket_name);
|
||||||
|
|
||||||
|
process_t
|
||||||
|
adb_push(const char *serial, const char *local, const char *remote);
|
||||||
|
|
||||||
|
process_t
|
||||||
|
adb_install(const char *serial, const char *local);
|
||||||
|
|
||||||
// convenience function to wait for a successful process execution
|
// convenience function to wait for a successful process execution
|
||||||
// automatically log process errors with the provided process name
|
// automatically log process errors with the provided process name
|
||||||
SDL_bool process_check_success(process_t process, const char *name);
|
SDL_bool
|
||||||
|
process_check_success(process_t process, const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,8 @@ struct point {
|
||||||
|
|
||||||
struct position {
|
struct position {
|
||||||
// The video screen size may be different from the real device screen size,
|
// The video screen size may be different from the real device screen size,
|
||||||
// so store to which size the absolute position apply, to scale it accordingly.
|
// so store to which size the absolute position apply, to scale it
|
||||||
|
// accordingly.
|
||||||
struct size screen_size;
|
struct size screen_size;
|
||||||
struct point point;
|
struct point point;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,14 +7,16 @@
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
static void write_position(Uint8 *buf, const struct position *position) {
|
static void
|
||||||
|
write_position(Uint8 *buf, const struct position *position) {
|
||||||
buffer_write32be(&buf[0], position->point.x);
|
buffer_write32be(&buf[0], position->point.x);
|
||||||
buffer_write32be(&buf[4], position->point.y);
|
buffer_write32be(&buf[4], position->point.y);
|
||||||
buffer_write16be(&buf[8], position->screen_size.width);
|
buffer_write16be(&buf[8], position->screen_size.width);
|
||||||
buffer_write16be(&buf[10], position->screen_size.height);
|
buffer_write16be(&buf[10], position->screen_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int control_event_serialize(const struct control_event *event, unsigned char *buf) {
|
int
|
||||||
|
control_event_serialize(const struct control_event *event, unsigned char *buf) {
|
||||||
buf[0] = event->type;
|
buf[0] = event->type;
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case CONTROL_EVENT_TYPE_KEYCODE:
|
case CONTROL_EVENT_TYPE_KEYCODE:
|
||||||
|
@ -52,28 +54,33 @@ int control_event_serialize(const struct control_event *event, unsigned char *bu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void control_event_destroy(struct control_event *event) {
|
void
|
||||||
|
control_event_destroy(struct control_event *event) {
|
||||||
if (event->type == CONTROL_EVENT_TYPE_TEXT) {
|
if (event->type == CONTROL_EVENT_TYPE_TEXT) {
|
||||||
SDL_free(event->text_event.text);
|
SDL_free(event->text_event.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool control_event_queue_is_empty(const struct control_event_queue *queue) {
|
SDL_bool
|
||||||
|
control_event_queue_is_empty(const struct control_event_queue *queue) {
|
||||||
return queue->head == queue->tail;
|
return queue->head == queue->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool control_event_queue_is_full(const struct control_event_queue *queue) {
|
SDL_bool
|
||||||
|
control_event_queue_is_full(const struct control_event_queue *queue) {
|
||||||
return (queue->head + 1) % CONTROL_EVENT_QUEUE_SIZE == queue->tail;
|
return (queue->head + 1) % CONTROL_EVENT_QUEUE_SIZE == queue->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool control_event_queue_init(struct control_event_queue *queue) {
|
SDL_bool
|
||||||
|
control_event_queue_init(struct control_event_queue *queue) {
|
||||||
queue->head = 0;
|
queue->head = 0;
|
||||||
queue->tail = 0;
|
queue->tail = 0;
|
||||||
// the current implementation may not fail
|
// the current implementation may not fail
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void control_event_queue_destroy(struct control_event_queue *queue) {
|
void
|
||||||
|
control_event_queue_destroy(struct control_event_queue *queue) {
|
||||||
int i = queue->tail;
|
int i = queue->tail;
|
||||||
while (i != queue->head) {
|
while (i != queue->head) {
|
||||||
control_event_destroy(&queue->data[i]);
|
control_event_destroy(&queue->data[i]);
|
||||||
|
@ -81,7 +88,9 @@ void control_event_queue_destroy(struct control_event_queue *queue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool control_event_queue_push(struct control_event_queue *queue, const struct control_event *event) {
|
SDL_bool
|
||||||
|
control_event_queue_push(struct control_event_queue *queue,
|
||||||
|
const struct control_event *event) {
|
||||||
if (control_event_queue_is_full(queue)) {
|
if (control_event_queue_is_full(queue)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +99,9 @@ SDL_bool control_event_queue_push(struct control_event_queue *queue, const struc
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool control_event_queue_take(struct control_event_queue *queue, struct control_event *event) {
|
SDL_bool
|
||||||
|
control_event_queue_take(struct control_event_queue *queue,
|
||||||
|
struct control_event *event) {
|
||||||
if (control_event_queue_is_empty(queue)) {
|
if (control_event_queue_is_empty(queue)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,18 +60,31 @@ struct control_event_queue {
|
||||||
};
|
};
|
||||||
|
|
||||||
// buf size must be at least SERIALIZED_EVENT_MAX_SIZE
|
// buf size must be at least SERIALIZED_EVENT_MAX_SIZE
|
||||||
int control_event_serialize(const struct control_event *event, unsigned char *buf);
|
int
|
||||||
|
control_event_serialize(const struct control_event *event, unsigned char *buf);
|
||||||
|
|
||||||
SDL_bool control_event_queue_init(struct control_event_queue *queue);
|
SDL_bool
|
||||||
void control_event_queue_destroy(struct control_event_queue *queue);
|
control_event_queue_init(struct control_event_queue *queue);
|
||||||
|
|
||||||
SDL_bool control_event_queue_is_empty(const struct control_event_queue *queue);
|
void
|
||||||
SDL_bool control_event_queue_is_full(const struct control_event_queue *queue);
|
control_event_queue_destroy(struct control_event_queue *queue);
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
control_event_queue_is_empty(const struct control_event_queue *queue);
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
control_event_queue_is_full(const struct control_event_queue *queue);
|
||||||
|
|
||||||
// event is copied, the queue does not use the event after the function returns
|
// event is copied, the queue does not use the event after the function returns
|
||||||
SDL_bool control_event_queue_push(struct control_event_queue *queue, const struct control_event *event);
|
SDL_bool
|
||||||
SDL_bool control_event_queue_take(struct control_event_queue *queue, struct control_event *event);
|
control_event_queue_push(struct control_event_queue *queue,
|
||||||
|
const struct control_event *event);
|
||||||
|
|
||||||
void control_event_destroy(struct control_event *event);
|
SDL_bool
|
||||||
|
control_event_queue_take(struct control_event_queue *queue,
|
||||||
|
struct control_event *event);
|
||||||
|
|
||||||
|
void
|
||||||
|
control_event_destroy(struct control_event *event);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
SDL_bool controller_init(struct controller *controller, socket_t video_socket) {
|
SDL_bool
|
||||||
|
controller_init(struct controller *controller, socket_t video_socket) {
|
||||||
if (!control_event_queue_init(&controller->queue)) {
|
if (!control_event_queue_init(&controller->queue)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -25,13 +26,16 @@ SDL_bool controller_init(struct controller *controller, socket_t video_socket) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void controller_destroy(struct controller *controller) {
|
void
|
||||||
|
controller_destroy(struct controller *controller) {
|
||||||
SDL_DestroyCond(controller->event_cond);
|
SDL_DestroyCond(controller->event_cond);
|
||||||
SDL_DestroyMutex(controller->mutex);
|
SDL_DestroyMutex(controller->mutex);
|
||||||
control_event_queue_destroy(&controller->queue);
|
control_event_queue_destroy(&controller->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool controller_push_event(struct controller *controller, const struct control_event *event) {
|
SDL_bool
|
||||||
|
controller_push_event(struct controller *controller,
|
||||||
|
const struct control_event *event) {
|
||||||
SDL_bool res;
|
SDL_bool res;
|
||||||
mutex_lock(controller->mutex);
|
mutex_lock(controller->mutex);
|
||||||
SDL_bool was_empty = control_event_queue_is_empty(&controller->queue);
|
SDL_bool was_empty = control_event_queue_is_empty(&controller->queue);
|
||||||
|
@ -43,7 +47,9 @@ SDL_bool controller_push_event(struct controller *controller, const struct contr
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool process_event(struct controller *controller, const struct control_event *event) {
|
static SDL_bool
|
||||||
|
process_event(struct controller *controller,
|
||||||
|
const struct control_event *event) {
|
||||||
unsigned char serialized_event[SERIALIZED_EVENT_MAX_SIZE];
|
unsigned char serialized_event[SERIALIZED_EVENT_MAX_SIZE];
|
||||||
int length = control_event_serialize(event, serialized_event);
|
int length = control_event_serialize(event, serialized_event);
|
||||||
if (!length) {
|
if (!length) {
|
||||||
|
@ -53,12 +59,14 @@ static SDL_bool process_event(struct controller *controller, const struct contro
|
||||||
return w == length;
|
return w == length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_controller(void *data) {
|
static int
|
||||||
|
run_controller(void *data) {
|
||||||
struct controller *controller = data;
|
struct controller *controller = data;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
mutex_lock(controller->mutex);
|
mutex_lock(controller->mutex);
|
||||||
while (!controller->stopped && control_event_queue_is_empty(&controller->queue)) {
|
while (!controller->stopped
|
||||||
|
&& control_event_queue_is_empty(&controller->queue)) {
|
||||||
cond_wait(controller->event_cond, controller->mutex);
|
cond_wait(controller->event_cond, controller->mutex);
|
||||||
}
|
}
|
||||||
if (controller->stopped) {
|
if (controller->stopped) {
|
||||||
|
@ -67,7 +75,8 @@ static int run_controller(void *data) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
struct control_event event;
|
struct control_event event;
|
||||||
SDL_bool non_empty = control_event_queue_take(&controller->queue, &event);
|
SDL_bool non_empty = control_event_queue_take(&controller->queue,
|
||||||
|
&event);
|
||||||
SDL_assert(non_empty);
|
SDL_assert(non_empty);
|
||||||
mutex_unlock(controller->mutex);
|
mutex_unlock(controller->mutex);
|
||||||
|
|
||||||
|
@ -81,10 +90,12 @@ static int run_controller(void *data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool controller_start(struct controller *controller) {
|
SDL_bool
|
||||||
|
controller_start(struct controller *controller) {
|
||||||
LOGD("Starting controller thread");
|
LOGD("Starting controller thread");
|
||||||
|
|
||||||
controller->thread = SDL_CreateThread(run_controller, "controller", controller);
|
controller->thread = SDL_CreateThread(run_controller, "controller",
|
||||||
|
controller);
|
||||||
if (!controller->thread) {
|
if (!controller->thread) {
|
||||||
LOGC("Could not start controller thread");
|
LOGC("Could not start controller thread");
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -93,13 +104,15 @@ SDL_bool controller_start(struct controller *controller) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void controller_stop(struct controller *controller) {
|
void
|
||||||
|
controller_stop(struct controller *controller) {
|
||||||
mutex_lock(controller->mutex);
|
mutex_lock(controller->mutex);
|
||||||
controller->stopped = SDL_TRUE;
|
controller->stopped = SDL_TRUE;
|
||||||
cond_signal(controller->event_cond);
|
cond_signal(controller->event_cond);
|
||||||
mutex_unlock(controller->mutex);
|
mutex_unlock(controller->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void controller_join(struct controller *controller) {
|
void
|
||||||
|
controller_join(struct controller *controller) {
|
||||||
SDL_WaitThread(controller->thread, NULL);
|
SDL_WaitThread(controller->thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,24 @@ struct controller {
|
||||||
struct control_event_queue queue;
|
struct control_event_queue queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool controller_init(struct controller *controller, socket_t video_socket);
|
SDL_bool
|
||||||
void controller_destroy(struct controller *controller);
|
controller_init(struct controller *controller, socket_t video_socket);
|
||||||
|
|
||||||
SDL_bool controller_start(struct controller *controller);
|
void
|
||||||
void controller_stop(struct controller *controller);
|
controller_destroy(struct controller *controller);
|
||||||
void controller_join(struct controller *controller);
|
|
||||||
|
SDL_bool
|
||||||
|
controller_start(struct controller *controller);
|
||||||
|
|
||||||
|
void
|
||||||
|
controller_stop(struct controller *controller);
|
||||||
|
|
||||||
|
void
|
||||||
|
controller_join(struct controller *controller);
|
||||||
|
|
||||||
// expose simple API to hide control_event_queue
|
// expose simple API to hide control_event_queue
|
||||||
SDL_bool controller_push_event(struct controller *controller, const struct control_event *event);
|
SDL_bool
|
||||||
|
controller_push_event(struct controller *controller,
|
||||||
|
const struct control_event *event);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
#define MAP(FROM, TO) case FROM: *to = TO; return SDL_TRUE
|
#define MAP(FROM, TO) case FROM: *to = TO; return SDL_TRUE
|
||||||
#define FAIL default: return SDL_FALSE
|
#define FAIL default: return SDL_FALSE
|
||||||
|
|
||||||
static SDL_bool convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to) {
|
static SDL_bool
|
||||||
|
convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to) {
|
||||||
switch (from) {
|
switch (from) {
|
||||||
MAP(SDL_KEYDOWN, AKEY_EVENT_ACTION_DOWN);
|
MAP(SDL_KEYDOWN, AKEY_EVENT_ACTION_DOWN);
|
||||||
MAP(SDL_KEYUP, AKEY_EVENT_ACTION_UP);
|
MAP(SDL_KEYUP, AKEY_EVENT_ACTION_UP);
|
||||||
|
@ -11,7 +12,8 @@ static SDL_bool convert_keycode_action(SDL_EventType from, enum android_keyevent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum android_metastate autocomplete_metastate(enum android_metastate metastate) {
|
static enum android_metastate
|
||||||
|
autocomplete_metastate(enum android_metastate metastate) {
|
||||||
// fill dependant flags
|
// fill dependant flags
|
||||||
if (metastate & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
|
if (metastate & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
|
||||||
metastate |= AMETA_SHIFT_ON;
|
metastate |= AMETA_SHIFT_ON;
|
||||||
|
@ -30,7 +32,8 @@ static enum android_metastate autocomplete_metastate(enum android_metastate meta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static enum android_metastate convert_meta_state(SDL_Keymod mod) {
|
static enum android_metastate
|
||||||
|
convert_meta_state(SDL_Keymod mod) {
|
||||||
enum android_metastate metastate = 0;
|
enum android_metastate metastate = 0;
|
||||||
if (mod & KMOD_LSHIFT) {
|
if (mod & KMOD_LSHIFT) {
|
||||||
metastate |= AMETA_SHIFT_LEFT_ON;
|
metastate |= AMETA_SHIFT_LEFT_ON;
|
||||||
|
@ -70,7 +73,8 @@ static enum android_metastate convert_meta_state(SDL_Keymod mod) {
|
||||||
return autocomplete_metastate(metastate);
|
return autocomplete_metastate(metastate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool convert_keycode(SDL_Keycode from, enum android_keycode *to, Uint16 mod) {
|
static SDL_bool
|
||||||
|
convert_keycode(SDL_Keycode from, enum android_keycode *to, Uint16 mod) {
|
||||||
switch (from) {
|
switch (from) {
|
||||||
MAP(SDLK_RETURN, AKEYCODE_ENTER);
|
MAP(SDLK_RETURN, AKEYCODE_ENTER);
|
||||||
MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER);
|
MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER);
|
||||||
|
@ -123,7 +127,8 @@ static SDL_bool convert_keycode(SDL_Keycode from, enum android_keycode *to, Uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
|
static SDL_bool
|
||||||
|
convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
|
||||||
switch (from) {
|
switch (from) {
|
||||||
MAP(SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN);
|
MAP(SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN);
|
||||||
MAP(SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP);
|
MAP(SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP);
|
||||||
|
@ -131,7 +136,8 @@ static SDL_bool convert_mouse_action(SDL_EventType from, enum android_motioneven
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum android_motionevent_buttons convert_mouse_buttons(Uint32 state) {
|
static enum android_motionevent_buttons
|
||||||
|
convert_mouse_buttons(Uint32 state) {
|
||||||
enum android_motionevent_buttons buttons = 0;
|
enum android_motionevent_buttons buttons = 0;
|
||||||
if (state & SDL_BUTTON_LMASK) {
|
if (state & SDL_BUTTON_LMASK) {
|
||||||
buttons |= AMOTION_EVENT_BUTTON_PRIMARY;
|
buttons |= AMOTION_EVENT_BUTTON_PRIMARY;
|
||||||
|
@ -151,8 +157,9 @@ static enum android_motionevent_buttons convert_mouse_buttons(Uint32 state) {
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
SDL_bool
|
||||||
struct control_event *to) {
|
input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||||
|
struct control_event *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_KEYCODE;
|
to->type = CONTROL_EVENT_TYPE_KEYCODE;
|
||||||
|
|
||||||
if (!convert_keycode_action(from->type, &to->keycode_event.action)) {
|
if (!convert_keycode_action(from->type, &to->keycode_event.action)) {
|
||||||
|
@ -169,9 +176,10 @@ SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
SDL_bool
|
||||||
struct size screen_size,
|
mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||||
struct control_event *to) {
|
struct size screen_size,
|
||||||
|
struct control_event *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
||||||
|
|
||||||
if (!convert_mouse_action(from->type, &to->mouse_event.action)) {
|
if (!convert_mouse_action(from->type, &to->mouse_event.action)) {
|
||||||
|
@ -186,9 +194,10 @@ SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
SDL_bool
|
||||||
struct size screen_size,
|
mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||||
struct control_event *to) {
|
struct size screen_size,
|
||||||
|
struct control_event *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
||||||
to->mouse_event.action = AMOTION_EVENT_ACTION_MOVE;
|
to->mouse_event.action = AMOTION_EVENT_ACTION_MOVE;
|
||||||
to->mouse_event.buttons = convert_mouse_buttons(from->state);
|
to->mouse_event.buttons = convert_mouse_buttons(from->state);
|
||||||
|
@ -199,9 +208,10 @@ SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
SDL_bool
|
||||||
struct position position,
|
mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
||||||
struct control_event *to) {
|
struct position position,
|
||||||
|
struct control_event *to) {
|
||||||
to->type = CONTROL_EVENT_TYPE_SCROLL;
|
to->type = CONTROL_EVENT_TYPE_SCROLL;
|
||||||
|
|
||||||
to->scroll_event.position = position;
|
to->scroll_event.position = position;
|
||||||
|
|
|
@ -15,21 +15,26 @@ struct complete_mouse_wheel_event {
|
||||||
struct point position;
|
struct point position;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
SDL_bool
|
||||||
struct control_event *to);
|
input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||||
SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
struct control_event *to);
|
||||||
struct size screen_size,
|
|
||||||
struct control_event *to);
|
|
||||||
|
|
||||||
// the video size may be different from the real device size, so we need the size
|
SDL_bool
|
||||||
// to which the absolute position apply, to scale it accordingly
|
mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||||
SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
struct size screen_size,
|
||||||
struct size screen_size,
|
struct control_event *to);
|
||||||
struct control_event *to);
|
|
||||||
|
// the video size may be different from the real device size, so we need the
|
||||||
|
// size to which the absolute position apply, to scale it accordingly
|
||||||
|
SDL_bool
|
||||||
|
mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||||
|
struct size screen_size,
|
||||||
|
struct control_event *to);
|
||||||
|
|
||||||
// on Android, a scroll event requires the current mouse position
|
// on Android, a scroll event requires the current mouse position
|
||||||
SDL_bool mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
SDL_bool
|
||||||
struct position position,
|
mouse_wheel_from_sdl_to_android(const SDL_MouseWheelEvent *from,
|
||||||
struct control_event *to);
|
struct position position,
|
||||||
|
struct control_event *to);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,8 +18,10 @@
|
||||||
#include "video_buffer.h"
|
#include "video_buffer.h"
|
||||||
|
|
||||||
// set the decoded frame as ready for rendering, and notify
|
// set the decoded frame as ready for rendering, and notify
|
||||||
static void push_frame(struct decoder *decoder) {
|
static void
|
||||||
SDL_bool previous_frame_consumed = video_buffer_offer_decoded_frame(decoder->video_buffer);
|
push_frame(struct decoder *decoder) {
|
||||||
|
SDL_bool previous_frame_consumed =
|
||||||
|
video_buffer_offer_decoded_frame(decoder->video_buffer);
|
||||||
if (!previous_frame_consumed) {
|
if (!previous_frame_consumed) {
|
||||||
// the previous EVENT_NEW_FRAME will consume this frame
|
// the previous EVENT_NEW_FRAME will consume this frame
|
||||||
return;
|
return;
|
||||||
|
@ -30,11 +32,13 @@ static void push_frame(struct decoder *decoder) {
|
||||||
SDL_PushEvent(&new_frame_event);
|
SDL_PushEvent(&new_frame_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decoder_init(struct decoder *decoder, struct video_buffer *vb) {
|
void
|
||||||
|
decoder_init(struct decoder *decoder, struct video_buffer *vb) {
|
||||||
decoder->video_buffer = vb;
|
decoder->video_buffer = vb;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool decoder_open(struct decoder *decoder, AVCodec *codec) {
|
SDL_bool
|
||||||
|
decoder_open(struct decoder *decoder, AVCodec *codec) {
|
||||||
decoder->codec_ctx = avcodec_alloc_context3(codec);
|
decoder->codec_ctx = avcodec_alloc_context3(codec);
|
||||||
if (!decoder->codec_ctx) {
|
if (!decoder->codec_ctx) {
|
||||||
LOGC("Could not allocate decoder context");
|
LOGC("Could not allocate decoder context");
|
||||||
|
@ -50,12 +54,14 @@ SDL_bool decoder_open(struct decoder *decoder, AVCodec *codec) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decoder_close(struct decoder *decoder) {
|
void
|
||||||
|
decoder_close(struct decoder *decoder) {
|
||||||
avcodec_close(decoder->codec_ctx);
|
avcodec_close(decoder->codec_ctx);
|
||||||
avcodec_free_context(&decoder->codec_ctx);
|
avcodec_free_context(&decoder->codec_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool decoder_push(struct decoder *decoder, AVPacket *packet) {
|
SDL_bool
|
||||||
|
decoder_push(struct decoder *decoder, AVPacket *packet) {
|
||||||
// the new decoding/encoding API has been introduced by:
|
// the new decoding/encoding API has been introduced by:
|
||||||
// <http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=7fc329e2dd6226dfecaa4a1d7adf353bf2773726>
|
// <http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=7fc329e2dd6226dfecaa4a1d7adf353bf2773726>
|
||||||
#ifdef SCRCPY_LAVF_HAS_NEW_ENCODING_DECODING_API
|
#ifdef SCRCPY_LAVF_HAS_NEW_ENCODING_DECODING_API
|
||||||
|
@ -90,6 +96,7 @@ SDL_bool decoder_push(struct decoder *decoder, AVPacket *packet) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decoder_interrupt(struct decoder *decoder) {
|
void
|
||||||
|
decoder_interrupt(struct decoder *decoder) {
|
||||||
video_buffer_interrupt(decoder->video_buffer);
|
video_buffer_interrupt(decoder->video_buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,19 @@ struct decoder {
|
||||||
AVCodecContext *codec_ctx;
|
AVCodecContext *codec_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
void decoder_init(struct decoder *decoder, struct video_buffer *vb);
|
void
|
||||||
|
decoder_init(struct decoder *decoder, struct video_buffer *vb);
|
||||||
|
|
||||||
SDL_bool decoder_open(struct decoder *decoder, AVCodec *codec);
|
SDL_bool
|
||||||
void decoder_close(struct decoder *decoder);
|
decoder_open(struct decoder *decoder, AVCodec *codec);
|
||||||
|
|
||||||
SDL_bool decoder_push(struct decoder *decoder, AVPacket *packet);
|
void
|
||||||
void decoder_interrupt(struct decoder *decoder);
|
decoder_close(struct decoder *decoder);
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
decoder_push(struct decoder *decoder, AVPacket *packet);
|
||||||
|
|
||||||
|
void
|
||||||
|
decoder_interrupt(struct decoder *decoder);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
SDL_bool device_read_info(socket_t device_socket, char *device_name, struct size *size) {
|
SDL_bool
|
||||||
|
device_read_info(socket_t device_socket, char *device_name, struct size *size) {
|
||||||
unsigned char buf[DEVICE_NAME_FIELD_LENGTH + 4];
|
unsigned char buf[DEVICE_NAME_FIELD_LENGTH + 4];
|
||||||
int r = net_recv_all(device_socket, buf, sizeof(buf));
|
int r = net_recv_all(device_socket, buf, sizeof(buf));
|
||||||
if (r < DEVICE_NAME_FIELD_LENGTH + 4) {
|
if (r < DEVICE_NAME_FIELD_LENGTH + 4) {
|
||||||
LOGE("Could not retrieve device information");
|
LOGE("Could not retrieve device information");
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
buf[DEVICE_NAME_FIELD_LENGTH - 1] = '\0'; // in case the client sends garbage
|
// in case the client sends garbage
|
||||||
// strcpy is safe here, since name contains at least DEVICE_NAME_FIELD_LENGTH bytes
|
buf[DEVICE_NAME_FIELD_LENGTH - 1] = '\0';
|
||||||
// and strlen(buf) < DEVICE_NAME_FIELD_LENGTH
|
// strcpy is safe here, since name contains at least
|
||||||
|
// DEVICE_NAME_FIELD_LENGTH bytes and strlen(buf) < DEVICE_NAME_FIELD_LENGTH
|
||||||
strcpy(device_name, (char *) buf);
|
strcpy(device_name, (char *) buf);
|
||||||
size->width = (buf[DEVICE_NAME_FIELD_LENGTH] << 8) | buf[DEVICE_NAME_FIELD_LENGTH + 1];
|
size->width = (buf[DEVICE_NAME_FIELD_LENGTH] << 8)
|
||||||
size->height = (buf[DEVICE_NAME_FIELD_LENGTH + 2] << 8) | buf[DEVICE_NAME_FIELD_LENGTH + 3];
|
| buf[DEVICE_NAME_FIELD_LENGTH + 1];
|
||||||
|
size->height = (buf[DEVICE_NAME_FIELD_LENGTH + 2] << 8)
|
||||||
|
| buf[DEVICE_NAME_FIELD_LENGTH + 3];
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define DEVICE_SDCARD_PATH "/sdcard/"
|
#define DEVICE_SDCARD_PATH "/sdcard/"
|
||||||
|
|
||||||
// name must be at least DEVICE_NAME_FIELD_LENGTH bytes
|
// name must be at least DEVICE_NAME_FIELD_LENGTH bytes
|
||||||
SDL_bool device_read_info(socket_t device_socket, char *name, struct size *frame_size);
|
SDL_bool
|
||||||
|
device_read_info(socket_t device_socket, char *name, struct size *frame_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,7 +13,8 @@ struct request {
|
||||||
const char *file;
|
const char *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct request *request_new(file_handler_action_t action, const char *file) {
|
static struct request *
|
||||||
|
request_new(file_handler_action_t action, const char *file) {
|
||||||
struct request *req = SDL_malloc(sizeof(*req));
|
struct request *req = SDL_malloc(sizeof(*req));
|
||||||
if (!req) {
|
if (!req) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -23,7 +24,8 @@ static struct request *request_new(file_handler_action_t action, const char *fil
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void request_free(struct request *req) {
|
static void
|
||||||
|
request_free(struct request *req) {
|
||||||
if (!req) {
|
if (!req) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -31,21 +33,25 @@ static void request_free(struct request *req) {
|
||||||
SDL_free((void *) req);
|
SDL_free((void *) req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool request_queue_is_empty(const struct request_queue *queue) {
|
static SDL_bool
|
||||||
|
request_queue_is_empty(const struct request_queue *queue) {
|
||||||
return queue->head == queue->tail;
|
return queue->head == queue->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool request_queue_is_full(const struct request_queue *queue) {
|
static SDL_bool
|
||||||
|
request_queue_is_full(const struct request_queue *queue) {
|
||||||
return (queue->head + 1) % REQUEST_QUEUE_SIZE == queue->tail;
|
return (queue->head + 1) % REQUEST_QUEUE_SIZE == queue->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool request_queue_init(struct request_queue *queue) {
|
static SDL_bool
|
||||||
|
request_queue_init(struct request_queue *queue) {
|
||||||
queue->head = 0;
|
queue->head = 0;
|
||||||
queue->tail = 0;
|
queue->tail = 0;
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void request_queue_destroy(struct request_queue *queue) {
|
static void
|
||||||
|
request_queue_destroy(struct request_queue *queue) {
|
||||||
int i = queue->tail;
|
int i = queue->tail;
|
||||||
while (i != queue->head) {
|
while (i != queue->head) {
|
||||||
request_free(queue->reqs[i]);
|
request_free(queue->reqs[i]);
|
||||||
|
@ -53,7 +59,8 @@ static void request_queue_destroy(struct request_queue *queue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool request_queue_push(struct request_queue *queue, struct request *req) {
|
static SDL_bool
|
||||||
|
request_queue_push(struct request_queue *queue, struct request *req) {
|
||||||
if (request_queue_is_full(queue)) {
|
if (request_queue_is_full(queue)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +69,8 @@ static SDL_bool request_queue_push(struct request_queue *queue, struct request *
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool request_queue_take(struct request_queue *queue, struct request **req) {
|
static SDL_bool
|
||||||
|
request_queue_take(struct request_queue *queue, struct request **req) {
|
||||||
if (request_queue_is_empty(queue)) {
|
if (request_queue_is_empty(queue)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +80,8 @@ static SDL_bool request_queue_take(struct request_queue *queue, struct request *
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool file_handler_init(struct file_handler *file_handler, const char *serial) {
|
SDL_bool
|
||||||
|
file_handler_init(struct file_handler *file_handler, const char *serial) {
|
||||||
|
|
||||||
if (!request_queue_init(&file_handler->queue)) {
|
if (!request_queue_init(&file_handler->queue)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -107,24 +116,28 @@ SDL_bool file_handler_init(struct file_handler *file_handler, const char *serial
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_handler_destroy(struct file_handler *file_handler) {
|
void
|
||||||
|
file_handler_destroy(struct file_handler *file_handler) {
|
||||||
SDL_DestroyCond(file_handler->event_cond);
|
SDL_DestroyCond(file_handler->event_cond);
|
||||||
SDL_DestroyMutex(file_handler->mutex);
|
SDL_DestroyMutex(file_handler->mutex);
|
||||||
request_queue_destroy(&file_handler->queue);
|
request_queue_destroy(&file_handler->queue);
|
||||||
SDL_free((void *) file_handler->serial);
|
SDL_free((void *) file_handler->serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static process_t install_apk(const char *serial, const char *file) {
|
static process_t
|
||||||
|
install_apk(const char *serial, const char *file) {
|
||||||
return adb_install(serial, file);
|
return adb_install(serial, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static process_t push_file(const char *serial, const char *file) {
|
static process_t
|
||||||
|
push_file(const char *serial, const char *file) {
|
||||||
return adb_push(serial, file, DEVICE_SDCARD_PATH);
|
return adb_push(serial, file, DEVICE_SDCARD_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool file_handler_request(struct file_handler *file_handler,
|
SDL_bool
|
||||||
file_handler_action_t action,
|
file_handler_request(struct file_handler *file_handler,
|
||||||
const char *file) {
|
file_handler_action_t action,
|
||||||
|
const char *file) {
|
||||||
SDL_bool res;
|
SDL_bool res;
|
||||||
|
|
||||||
// start file_handler if it's used for the first time
|
// start file_handler if it's used for the first time
|
||||||
|
@ -135,7 +148,8 @@ SDL_bool file_handler_request(struct file_handler *file_handler,
|
||||||
file_handler->initialized = SDL_TRUE;
|
file_handler->initialized = SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGI("Request to %s %s", action == ACTION_INSTALL_APK ? "install" : "push", file);
|
LOGI("Request to %s %s", action == ACTION_INSTALL_APK ? "install" : "push",
|
||||||
|
file);
|
||||||
struct request *req = request_new(action, file);
|
struct request *req = request_new(action, file);
|
||||||
if (!req) {
|
if (!req) {
|
||||||
LOGE("Could not create request");
|
LOGE("Could not create request");
|
||||||
|
@ -152,13 +166,15 @@ SDL_bool file_handler_request(struct file_handler *file_handler,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_file_handler(void *data) {
|
static int
|
||||||
|
run_file_handler(void *data) {
|
||||||
struct file_handler *file_handler = data;
|
struct file_handler *file_handler = data;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
mutex_lock(file_handler->mutex);
|
mutex_lock(file_handler->mutex);
|
||||||
file_handler->current_process = PROCESS_NONE;
|
file_handler->current_process = PROCESS_NONE;
|
||||||
while (!file_handler->stopped && request_queue_is_empty(&file_handler->queue)) {
|
while (!file_handler->stopped
|
||||||
|
&& request_queue_is_empty(&file_handler->queue)) {
|
||||||
cond_wait(file_handler->event_cond, file_handler->mutex);
|
cond_wait(file_handler->event_cond, file_handler->mutex);
|
||||||
}
|
}
|
||||||
if (file_handler->stopped) {
|
if (file_handler->stopped) {
|
||||||
|
@ -200,10 +216,12 @@ static int run_file_handler(void *data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool file_handler_start(struct file_handler *file_handler) {
|
SDL_bool
|
||||||
|
file_handler_start(struct file_handler *file_handler) {
|
||||||
LOGD("Starting file_handler thread");
|
LOGD("Starting file_handler thread");
|
||||||
|
|
||||||
file_handler->thread = SDL_CreateThread(run_file_handler, "file_handler", file_handler);
|
file_handler->thread = SDL_CreateThread(run_file_handler, "file_handler",
|
||||||
|
file_handler);
|
||||||
if (!file_handler->thread) {
|
if (!file_handler->thread) {
|
||||||
LOGC("Could not start file_handler thread");
|
LOGC("Could not start file_handler thread");
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -212,7 +230,8 @@ SDL_bool file_handler_start(struct file_handler *file_handler) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_handler_stop(struct file_handler *file_handler) {
|
void
|
||||||
|
file_handler_stop(struct file_handler *file_handler) {
|
||||||
mutex_lock(file_handler->mutex);
|
mutex_lock(file_handler->mutex);
|
||||||
file_handler->stopped = SDL_TRUE;
|
file_handler->stopped = SDL_TRUE;
|
||||||
cond_signal(file_handler->event_cond);
|
cond_signal(file_handler->event_cond);
|
||||||
|
@ -226,6 +245,7 @@ void file_handler_stop(struct file_handler *file_handler) {
|
||||||
mutex_unlock(file_handler->mutex);
|
mutex_unlock(file_handler->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_handler_join(struct file_handler *file_handler) {
|
void
|
||||||
|
file_handler_join(struct file_handler *file_handler) {
|
||||||
SDL_WaitThread(file_handler->thread, NULL);
|
SDL_WaitThread(file_handler->thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,24 @@ struct file_handler {
|
||||||
struct request_queue queue;
|
struct request_queue queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool file_handler_init(struct file_handler *file_handler, const char *serial);
|
SDL_bool
|
||||||
void file_handler_destroy(struct file_handler *file_handler);
|
file_handler_init(struct file_handler *file_handler, const char *serial);
|
||||||
|
|
||||||
SDL_bool file_handler_start(struct file_handler *file_handler);
|
void
|
||||||
void file_handler_stop(struct file_handler *file_handler);
|
file_handler_destroy(struct file_handler *file_handler);
|
||||||
void file_handler_join(struct file_handler *file_handler);
|
|
||||||
|
|
||||||
SDL_bool file_handler_request(struct file_handler *file_handler,
|
SDL_bool
|
||||||
file_handler_action_t action,
|
file_handler_start(struct file_handler *file_handler);
|
||||||
const char *file);
|
|
||||||
|
void
|
||||||
|
file_handler_stop(struct file_handler *file_handler);
|
||||||
|
|
||||||
|
void
|
||||||
|
file_handler_join(struct file_handler *file_handler);
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
file_handler_request(struct file_handler *file_handler,
|
||||||
|
file_handler_action_t action,
|
||||||
|
const char *file);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
void fps_counter_init(struct fps_counter *counter) {
|
void
|
||||||
|
fps_counter_init(struct fps_counter *counter) {
|
||||||
counter->started = SDL_FALSE;
|
counter->started = SDL_FALSE;
|
||||||
// no need to initialize the other fields, they are meaningful only when
|
// no need to initialize the other fields, they are meaningful only when
|
||||||
// started is true
|
// started is true
|
||||||
}
|
}
|
||||||
|
|
||||||
void fps_counter_start(struct fps_counter *counter) {
|
void
|
||||||
|
fps_counter_start(struct fps_counter *counter) {
|
||||||
counter->started = SDL_TRUE;
|
counter->started = SDL_TRUE;
|
||||||
counter->slice_start = SDL_GetTicks();
|
counter->slice_start = SDL_GetTicks();
|
||||||
counter->nr_rendered = 0;
|
counter->nr_rendered = 0;
|
||||||
|
@ -19,14 +21,17 @@ void fps_counter_start(struct fps_counter *counter) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void fps_counter_stop(struct fps_counter *counter) {
|
void
|
||||||
|
fps_counter_stop(struct fps_counter *counter) {
|
||||||
counter->started = SDL_FALSE;
|
counter->started = SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_fps(struct fps_counter *counter) {
|
static void
|
||||||
|
display_fps(struct fps_counter *counter) {
|
||||||
#ifdef SKIP_FRAMES
|
#ifdef SKIP_FRAMES
|
||||||
if (counter->nr_skipped) {
|
if (counter->nr_skipped) {
|
||||||
LOGI("%d fps (+%d frames skipped)", counter->nr_rendered, counter->nr_skipped);
|
LOGI("%d fps (+%d frames skipped)", counter->nr_rendered,
|
||||||
|
counter->nr_skipped);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
LOGI("%d fps", counter->nr_rendered);
|
LOGI("%d fps", counter->nr_rendered);
|
||||||
|
@ -35,7 +40,8 @@ static void display_fps(struct fps_counter *counter) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_expired(struct fps_counter *counter) {
|
static void
|
||||||
|
check_expired(struct fps_counter *counter) {
|
||||||
Uint32 now = SDL_GetTicks();
|
Uint32 now = SDL_GetTicks();
|
||||||
if (now - counter->slice_start >= 1000) {
|
if (now - counter->slice_start >= 1000) {
|
||||||
display_fps(counter);
|
display_fps(counter);
|
||||||
|
@ -49,13 +55,15 @@ static void check_expired(struct fps_counter *counter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
void
|
||||||
|
fps_counter_add_rendered_frame(struct fps_counter *counter) {
|
||||||
check_expired(counter);
|
check_expired(counter);
|
||||||
++counter->nr_rendered;
|
++counter->nr_rendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SKIP_FRAMES
|
#ifdef SKIP_FRAMES
|
||||||
void fps_counter_add_skipped_frame(struct fps_counter *counter) {
|
void
|
||||||
|
fps_counter_add_skipped_frame(struct fps_counter *counter) {
|
||||||
check_expired(counter);
|
check_expired(counter);
|
||||||
++counter->nr_skipped;
|
++counter->nr_skipped;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,21 @@ struct fps_counter {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void fps_counter_init(struct fps_counter *counter);
|
void
|
||||||
void fps_counter_start(struct fps_counter *counter);
|
fps_counter_init(struct fps_counter *counter);
|
||||||
void fps_counter_stop(struct fps_counter *counter);
|
|
||||||
|
void
|
||||||
|
fps_counter_start(struct fps_counter *counter);
|
||||||
|
|
||||||
|
void
|
||||||
|
fps_counter_stop(struct fps_counter *counter);
|
||||||
|
|
||||||
|
void
|
||||||
|
fps_counter_add_rendered_frame(struct fps_counter *counter);
|
||||||
|
|
||||||
void fps_counter_add_rendered_frame(struct fps_counter *counter);
|
|
||||||
#ifdef SKIP_FRAMES
|
#ifdef SKIP_FRAMES
|
||||||
void fps_counter_add_skipped_frame(struct fps_counter *counter);
|
void
|
||||||
|
fps_counter_add_skipped_frame(struct fps_counter *counter);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
// Convert window coordinates (as provided by SDL_GetMouseState() to renderer coordinates (as provided in SDL mouse events)
|
// Convert window coordinates (as provided by SDL_GetMouseState() to renderer
|
||||||
|
// coordinates (as provided in SDL mouse events)
|
||||||
//
|
//
|
||||||
// See my question:
|
// See my question:
|
||||||
// <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>
|
// <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>
|
||||||
static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int *y) {
|
static void
|
||||||
|
convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int *y) {
|
||||||
SDL_Rect viewport;
|
SDL_Rect viewport;
|
||||||
float scale_x, scale_y;
|
float scale_x, scale_y;
|
||||||
SDL_RenderGetViewport(renderer, &viewport);
|
SDL_RenderGetViewport(renderer, &viewport);
|
||||||
|
@ -18,7 +20,8 @@ static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int
|
||||||
*y = (int) (*y / scale_y) - viewport.y;
|
*y = (int) (*y / scale_y) - viewport.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct point get_mouse_point(struct screen *screen) {
|
static struct point
|
||||||
|
get_mouse_point(struct screen *screen) {
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
SDL_GetMouseState(&x, &y);
|
SDL_GetMouseState(&x, &y);
|
||||||
|
@ -32,7 +35,9 @@ static struct point get_mouse_point(struct screen *screen) {
|
||||||
static const int ACTION_DOWN = 1;
|
static const int ACTION_DOWN = 1;
|
||||||
static const int ACTION_UP = 1 << 1;
|
static const int ACTION_UP = 1 << 1;
|
||||||
|
|
||||||
static void send_keycode(struct controller *controller, enum android_keycode keycode, int actions, const char *name) {
|
static void
|
||||||
|
send_keycode(struct controller *controller, enum android_keycode keycode,
|
||||||
|
int actions, const char *name) {
|
||||||
// send DOWN event
|
// send DOWN event
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_KEYCODE;
|
control_event.type = CONTROL_EVENT_TYPE_KEYCODE;
|
||||||
|
@ -55,66 +60,80 @@ static void send_keycode(struct controller *controller, enum android_keycode key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_home(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_home(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_HOME, actions, "HOME");
|
send_keycode(controller, AKEYCODE_HOME, actions, "HOME");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_back(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_back(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_BACK, actions, "BACK");
|
send_keycode(controller, AKEYCODE_BACK, actions, "BACK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_app_switch(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_app_switch(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_APP_SWITCH, actions, "APP_SWITCH");
|
send_keycode(controller, AKEYCODE_APP_SWITCH, actions, "APP_SWITCH");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_power(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_power(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_POWER, actions, "POWER");
|
send_keycode(controller, AKEYCODE_POWER, actions, "POWER");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_volume_up(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_volume_up(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_VOLUME_UP, actions, "VOLUME_UP");
|
send_keycode(controller, AKEYCODE_VOLUME_UP, actions, "VOLUME_UP");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_volume_down(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_volume_down(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_VOLUME_DOWN, actions, "VOLUME_DOWN");
|
send_keycode(controller, AKEYCODE_VOLUME_DOWN, actions, "VOLUME_DOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void action_menu(struct controller *controller, int actions) {
|
static inline void
|
||||||
|
action_menu(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_MENU, actions, "MENU");
|
send_keycode(controller, AKEYCODE_MENU, actions, "MENU");
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn the screen on if it was off, press BACK otherwise
|
// turn the screen on if it was off, press BACK otherwise
|
||||||
static void press_back_or_turn_screen_on(struct controller *controller) {
|
static void
|
||||||
|
press_back_or_turn_screen_on(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
|
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
|
||||||
control_event.command_event.action = CONTROL_EVENT_COMMAND_BACK_OR_SCREEN_ON;
|
control_event.command_event.action =
|
||||||
|
CONTROL_EVENT_COMMAND_BACK_OR_SCREEN_ON;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_event(controller, &control_event)) {
|
||||||
LOGW("Cannot turn screen on");
|
LOGW("Cannot turn screen on");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expand_notification_panel(struct controller *controller) {
|
static void
|
||||||
|
expand_notification_panel(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
|
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
|
||||||
control_event.command_event.action = CONTROL_EVENT_COMMAND_EXPAND_NOTIFICATION_PANEL;
|
control_event.command_event.action =
|
||||||
|
CONTROL_EVENT_COMMAND_EXPAND_NOTIFICATION_PANEL;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_event(controller, &control_event)) {
|
||||||
LOGW("Cannot expand notification panel");
|
LOGW("Cannot expand notification panel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collapse_notification_panel(struct controller *controller) {
|
static void
|
||||||
|
collapse_notification_panel(struct controller *controller) {
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
|
control_event.type = CONTROL_EVENT_TYPE_COMMAND;
|
||||||
control_event.command_event.action = CONTROL_EVENT_COMMAND_COLLAPSE_NOTIFICATION_PANEL;
|
control_event.command_event.action =
|
||||||
|
CONTROL_EVENT_COMMAND_COLLAPSE_NOTIFICATION_PANEL;
|
||||||
|
|
||||||
if (!controller_push_event(controller, &control_event)) {
|
if (!controller_push_event(controller, &control_event)) {
|
||||||
LOGW("Cannot collapse notification panel");
|
LOGW("Cannot collapse notification panel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void switch_fps_counter_state(struct video_buffer *vb) {
|
static void
|
||||||
|
switch_fps_counter_state(struct video_buffer *vb) {
|
||||||
mutex_lock(vb->mutex);
|
mutex_lock(vb->mutex);
|
||||||
if (vb->fps_counter.started) {
|
if (vb->fps_counter.started) {
|
||||||
LOGI("FPS counter stopped");
|
LOGI("FPS counter stopped");
|
||||||
|
@ -126,7 +145,8 @@ static void switch_fps_counter_state(struct video_buffer *vb) {
|
||||||
mutex_unlock(vb->mutex);
|
mutex_unlock(vb->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clipboard_paste(struct controller *controller) {
|
static void
|
||||||
|
clipboard_paste(struct controller *controller) {
|
||||||
char *text = SDL_GetClipboardText();
|
char *text = SDL_GetClipboardText();
|
||||||
if (!text) {
|
if (!text) {
|
||||||
LOGW("Cannot get clipboard text: %s", SDL_GetError());
|
LOGW("Cannot get clipboard text: %s", SDL_GetError());
|
||||||
|
@ -147,8 +167,9 @@ static void clipboard_paste(struct controller *controller) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_manager_process_text_input(struct input_manager *input_manager,
|
void
|
||||||
const SDL_TextInputEvent *event) {
|
input_manager_process_text_input(struct input_manager *input_manager,
|
||||||
|
const SDL_TextInputEvent *event) {
|
||||||
char c = event->text[0];
|
char c = event->text[0];
|
||||||
if (isalpha(c) || c == ' ') {
|
if (isalpha(c) || c == ' ') {
|
||||||
SDL_assert(event->text[1] == '\0');
|
SDL_assert(event->text[1] == '\0');
|
||||||
|
@ -168,8 +189,9 @@ void input_manager_process_text_input(struct input_manager *input_manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_manager_process_key(struct input_manager *input_manager,
|
void
|
||||||
const SDL_KeyboardEvent *event) {
|
input_manager_process_key(struct input_manager *input_manager,
|
||||||
|
const SDL_KeyboardEvent *event) {
|
||||||
SDL_bool ctrl = event->keysym.mod & (KMOD_LCTRL | KMOD_RCTRL);
|
SDL_bool ctrl = event->keysym.mod & (KMOD_LCTRL | KMOD_RCTRL);
|
||||||
SDL_bool alt = event->keysym.mod & (KMOD_LALT | KMOD_RALT);
|
SDL_bool alt = event->keysym.mod & (KMOD_LALT | KMOD_RALT);
|
||||||
SDL_bool meta = event->keysym.mod & (KMOD_LGUI | KMOD_RGUI);
|
SDL_bool meta = event->keysym.mod & (KMOD_LGUI | KMOD_RGUI);
|
||||||
|
@ -285,29 +307,33 @@ void input_manager_process_key(struct input_manager *input_manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_manager_process_mouse_motion(struct input_manager *input_manager,
|
void
|
||||||
const SDL_MouseMotionEvent *event) {
|
input_manager_process_mouse_motion(struct input_manager *input_manager,
|
||||||
|
const SDL_MouseMotionEvent *event) {
|
||||||
if (!event->state) {
|
if (!event->state) {
|
||||||
// do not send motion events when no button is pressed
|
// do not send motion events when no button is pressed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
if (mouse_motion_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) {
|
if (mouse_motion_from_sdl_to_android(event,
|
||||||
|
input_manager->screen->frame_size,
|
||||||
|
&control_event)) {
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_event(input_manager->controller, &control_event)) {
|
||||||
LOGW("Cannot send mouse motion event");
|
LOGW("Cannot send mouse motion event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool is_outside_device_screen(struct input_manager *input_manager,
|
static SDL_bool
|
||||||
int x, int y)
|
is_outside_device_screen(struct input_manager *input_manager, int x, int y)
|
||||||
{
|
{
|
||||||
return x < 0 || x >= input_manager->screen->frame_size.width ||
|
return x < 0 || x >= input_manager->screen->frame_size.width ||
|
||||||
y < 0 || y >= input_manager->screen->frame_size.height;
|
y < 0 || y >= input_manager->screen->frame_size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_manager_process_mouse_button(struct input_manager *input_manager,
|
void
|
||||||
const SDL_MouseButtonEvent *event) {
|
input_manager_process_mouse_button(struct input_manager *input_manager,
|
||||||
|
const SDL_MouseButtonEvent *event) {
|
||||||
if (event->type == SDL_MOUSEBUTTONDOWN) {
|
if (event->type == SDL_MOUSEBUTTONDOWN) {
|
||||||
if (event->button == SDL_BUTTON_RIGHT) {
|
if (event->button == SDL_BUTTON_RIGHT) {
|
||||||
press_back_or_turn_screen_on(input_manager->controller);
|
press_back_or_turn_screen_on(input_manager->controller);
|
||||||
|
@ -331,15 +357,18 @@ void input_manager_process_mouse_button(struct input_manager *input_manager,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
if (mouse_button_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) {
|
if (mouse_button_from_sdl_to_android(event,
|
||||||
|
input_manager->screen->frame_size,
|
||||||
|
&control_event)) {
|
||||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
if (!controller_push_event(input_manager->controller, &control_event)) {
|
||||||
LOGW("Cannot send mouse button event");
|
LOGW("Cannot send mouse button event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_manager_process_mouse_wheel(struct input_manager *input_manager,
|
void
|
||||||
const SDL_MouseWheelEvent *event) {
|
input_manager_process_mouse_wheel(struct input_manager *input_manager,
|
||||||
|
const SDL_MouseWheelEvent *event) {
|
||||||
struct position position = {
|
struct position position = {
|
||||||
.screen_size = input_manager->screen->frame_size,
|
.screen_size = input_manager->screen->frame_size,
|
||||||
.point = get_mouse_point(input_manager->screen),
|
.point = get_mouse_point(input_manager->screen),
|
||||||
|
|
|
@ -13,15 +13,24 @@ struct input_manager {
|
||||||
struct screen *screen;
|
struct screen *screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
void input_manager_process_text_input(struct input_manager *input_manager,
|
void
|
||||||
const SDL_TextInputEvent *event);
|
input_manager_process_text_input(struct input_manager *input_manager,
|
||||||
void input_manager_process_key(struct input_manager *input_manager,
|
const SDL_TextInputEvent *event);
|
||||||
const SDL_KeyboardEvent *event);
|
|
||||||
void input_manager_process_mouse_motion(struct input_manager *input_manager,
|
void
|
||||||
const SDL_MouseMotionEvent *event);
|
input_manager_process_key(struct input_manager *input_manager,
|
||||||
void input_manager_process_mouse_button(struct input_manager *input_manager,
|
const SDL_KeyboardEvent *event);
|
||||||
const SDL_MouseButtonEvent *event);
|
|
||||||
void input_manager_process_mouse_wheel(struct input_manager *input_manager,
|
void
|
||||||
const SDL_MouseWheelEvent *event);
|
input_manager_process_mouse_motion(struct input_manager *input_manager,
|
||||||
|
const SDL_MouseMotionEvent *event);
|
||||||
|
|
||||||
|
void
|
||||||
|
input_manager_process_mouse_button(struct input_manager *input_manager,
|
||||||
|
const SDL_MouseButtonEvent *event);
|
||||||
|
|
||||||
|
void
|
||||||
|
input_manager_process_mouse_wheel(struct input_manager *input_manager,
|
||||||
|
const SDL_MouseWheelEvent *event);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,28 +4,32 @@
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
void mutex_lock(SDL_mutex *mutex) {
|
void
|
||||||
|
mutex_lock(SDL_mutex *mutex) {
|
||||||
if (SDL_LockMutex(mutex)) {
|
if (SDL_LockMutex(mutex)) {
|
||||||
LOGC("Could not lock mutex");
|
LOGC("Could not lock mutex");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mutex_unlock(SDL_mutex *mutex) {
|
void
|
||||||
|
mutex_unlock(SDL_mutex *mutex) {
|
||||||
if (SDL_UnlockMutex(mutex)) {
|
if (SDL_UnlockMutex(mutex)) {
|
||||||
LOGC("Could not unlock mutex");
|
LOGC("Could not unlock mutex");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_wait(SDL_cond *cond, SDL_mutex *mutex) {
|
void
|
||||||
|
cond_wait(SDL_cond *cond, SDL_mutex *mutex) {
|
||||||
if (SDL_CondWait(cond, mutex)) {
|
if (SDL_CondWait(cond, mutex)) {
|
||||||
LOGC("Could not wait on condition");
|
LOGC("Could not wait on condition");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_signal(SDL_cond *cond) {
|
void
|
||||||
|
cond_signal(SDL_cond *cond) {
|
||||||
if (SDL_CondSignal(cond)) {
|
if (SDL_CondSignal(cond)) {
|
||||||
LOGC("Could not signal a condition");
|
LOGC("Could not signal a condition");
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -5,9 +5,16 @@
|
||||||
typedef struct SDL_mutex SDL_mutex;
|
typedef struct SDL_mutex SDL_mutex;
|
||||||
typedef struct SDL_cond SDL_cond;
|
typedef struct SDL_cond SDL_cond;
|
||||||
|
|
||||||
void mutex_lock(SDL_mutex *mutex);
|
void
|
||||||
void mutex_unlock(SDL_mutex *mutex);
|
mutex_lock(SDL_mutex *mutex);
|
||||||
void cond_wait(SDL_cond *cond, SDL_mutex *mutex);
|
|
||||||
void cond_signal(SDL_cond *cond);
|
void
|
||||||
|
mutex_unlock(SDL_mutex *mutex);
|
||||||
|
|
||||||
|
void
|
||||||
|
cond_wait(SDL_cond *cond, SDL_mutex *mutex);
|
||||||
|
|
||||||
|
void
|
||||||
|
cond_signal(SDL_cond *cond);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -145,17 +145,26 @@ static void usage(const char *arg0) {
|
||||||
DEFAULT_LOCAL_PORT);
|
DEFAULT_LOCAL_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_version(void) {
|
static void
|
||||||
|
print_version(void) {
|
||||||
fprintf(stderr, "scrcpy %s\n\n", SCRCPY_VERSION);
|
fprintf(stderr, "scrcpy %s\n\n", SCRCPY_VERSION);
|
||||||
|
|
||||||
fprintf(stderr, "dependencies:\n");
|
fprintf(stderr, "dependencies:\n");
|
||||||
fprintf(stderr, " - SDL %d.%d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
|
fprintf(stderr, " - SDL %d.%d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION,
|
||||||
fprintf(stderr, " - libavcodec %d.%d.%d\n", LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO);
|
SDL_PATCHLEVEL);
|
||||||
fprintf(stderr, " - libavformat %d.%d.%d\n", LIBAVFORMAT_VERSION_MAJOR, LIBAVFORMAT_VERSION_MINOR, LIBAVFORMAT_VERSION_MICRO);
|
fprintf(stderr, " - libavcodec %d.%d.%d\n", LIBAVCODEC_VERSION_MAJOR,
|
||||||
fprintf(stderr, " - libavutil %d.%d.%d\n", LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO);
|
LIBAVCODEC_VERSION_MINOR,
|
||||||
|
LIBAVCODEC_VERSION_MICRO);
|
||||||
|
fprintf(stderr, " - libavformat %d.%d.%d\n", LIBAVFORMAT_VERSION_MAJOR,
|
||||||
|
LIBAVFORMAT_VERSION_MINOR,
|
||||||
|
LIBAVFORMAT_VERSION_MICRO);
|
||||||
|
fprintf(stderr, " - libavutil %d.%d.%d\n", LIBAVUTIL_VERSION_MAJOR,
|
||||||
|
LIBAVUTIL_VERSION_MINOR,
|
||||||
|
LIBAVUTIL_VERSION_MICRO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool parse_bit_rate(char *optarg, Uint32 *bit_rate) {
|
static SDL_bool
|
||||||
|
parse_bit_rate(char *optarg, Uint32 *bit_rate) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
if (*optarg == '\0') {
|
if (*optarg == '\0') {
|
||||||
LOGE("Bit-rate parameter is empty");
|
LOGE("Bit-rate parameter is empty");
|
||||||
|
@ -186,7 +195,8 @@ static SDL_bool parse_bit_rate(char *optarg, Uint32 *bit_rate) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool parse_max_size(char *optarg, Uint16 *max_size) {
|
static SDL_bool
|
||||||
|
parse_max_size(char *optarg, Uint16 *max_size) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
if (*optarg == '\0') {
|
if (*optarg == '\0') {
|
||||||
LOGE("Max size parameter is empty");
|
LOGE("Max size parameter is empty");
|
||||||
|
@ -206,7 +216,8 @@ static SDL_bool parse_max_size(char *optarg, Uint16 *max_size) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool parse_port(char *optarg, Uint16 *port) {
|
static SDL_bool
|
||||||
|
parse_port(char *optarg, Uint16 *port) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
if (*optarg == '\0') {
|
if (*optarg == '\0') {
|
||||||
LOGE("Invalid port parameter is empty");
|
LOGE("Invalid port parameter is empty");
|
||||||
|
@ -256,7 +267,8 @@ guess_record_format(const char *filename) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
static SDL_bool
|
||||||
|
parse_args(struct args *args, int argc, char *argv[]) {
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{"always-on-top", no_argument, NULL, 'T'},
|
{"always-on-top", no_argument, NULL, 'T'},
|
||||||
{"bit-rate", required_argument, NULL, 'b'},
|
{"bit-rate", required_argument, NULL, 'b'},
|
||||||
|
@ -274,7 +286,8 @@ static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
||||||
{NULL, 0, NULL, 0 },
|
{NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:np:r:s:tTv", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "b:c:fF:hm:np:r:s:tTv", long_options,
|
||||||
|
NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
if (!parse_bit_rate(optarg, &args->bit_rate)) {
|
if (!parse_bit_rate(optarg, &args->bit_rate)) {
|
||||||
|
@ -362,7 +375,8 @@ static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int
|
||||||
|
main(int argc, char *argv[]) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// disable buffering, we want logs immediately
|
// disable buffering, we want logs immediately
|
||||||
// even line buffering (setvbuf() with mode _IOLBF) is not sufficient
|
// even line buffering (setvbuf() with mode _IOLBF) is not sufficient
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
typedef struct in_addr IN_ADDR;
|
typedef struct in_addr IN_ADDR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
socket_t net_connect(Uint32 addr, Uint16 port) {
|
socket_t
|
||||||
|
net_connect(Uint32 addr, Uint16 port) {
|
||||||
socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
|
socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
|
@ -38,7 +39,8 @@ socket_t net_connect(Uint32 addr, Uint16 port) {
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket_t net_listen(Uint32 addr, Uint16 port, int backlog) {
|
socket_t
|
||||||
|
net_listen(Uint32 addr, Uint16 port, int backlog) {
|
||||||
socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
|
socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
|
@ -46,7 +48,8 @@ socket_t net_listen(Uint32 addr, Uint16 port, int backlog) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int reuse = 1;
|
int reuse = 1;
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(reuse)) == -1) {
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse,
|
||||||
|
sizeof(reuse)) == -1) {
|
||||||
perror("setsockopt(SO_REUSEADDR)");
|
perror("setsockopt(SO_REUSEADDR)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,25 +71,30 @@ socket_t net_listen(Uint32 addr, Uint16 port, int backlog) {
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket_t net_accept(socket_t server_socket) {
|
socket_t
|
||||||
|
net_accept(socket_t server_socket) {
|
||||||
SOCKADDR_IN csin;
|
SOCKADDR_IN csin;
|
||||||
socklen_t sinsize = sizeof(csin);
|
socklen_t sinsize = sizeof(csin);
|
||||||
return accept(server_socket, (SOCKADDR *) &csin, &sinsize);
|
return accept(server_socket, (SOCKADDR *) &csin, &sinsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t net_recv(socket_t socket, void *buf, size_t len) {
|
ssize_t
|
||||||
|
net_recv(socket_t socket, void *buf, size_t len) {
|
||||||
return recv(socket, buf, len, 0);
|
return recv(socket, buf, len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t net_recv_all(socket_t socket, void *buf, size_t len) {
|
ssize_t
|
||||||
|
net_recv_all(socket_t socket, void *buf, size_t len) {
|
||||||
return recv(socket, buf, len, MSG_WAITALL);
|
return recv(socket, buf, len, MSG_WAITALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t net_send(socket_t socket, const void *buf, size_t len) {
|
ssize_t
|
||||||
|
net_send(socket_t socket, const void *buf, size_t len) {
|
||||||
return send(socket, buf, len, 0);
|
return send(socket, buf, len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t net_send_all(socket_t socket, const void *buf, size_t len) {
|
ssize_t
|
||||||
|
net_send_all(socket_t socket, const void *buf, size_t len) {
|
||||||
ssize_t w = 0;
|
ssize_t w = 0;
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
w = send(socket, buf, len, 0);
|
w = send(socket, buf, len, 0);
|
||||||
|
@ -99,6 +107,7 @@ ssize_t net_send_all(socket_t socket, const void *buf, size_t len) {
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool net_shutdown(socket_t socket, int how) {
|
SDL_bool
|
||||||
|
net_shutdown(socket_t socket, int how) {
|
||||||
return !shutdown(socket, how);
|
return !shutdown(socket, how);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,39 @@
|
||||||
typedef int socket_t;
|
typedef int socket_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_bool net_init(void);
|
SDL_bool
|
||||||
void net_cleanup(void);
|
net_init(void);
|
||||||
|
|
||||||
socket_t net_connect(Uint32 addr, Uint16 port);
|
void
|
||||||
socket_t net_listen(Uint32 addr, Uint16 port, int backlog);
|
net_cleanup(void);
|
||||||
socket_t net_accept(socket_t server_socket);
|
|
||||||
|
socket_t
|
||||||
|
net_connect(Uint32 addr, Uint16 port);
|
||||||
|
|
||||||
|
socket_t
|
||||||
|
net_listen(Uint32 addr, Uint16 port, int backlog);
|
||||||
|
|
||||||
|
socket_t
|
||||||
|
net_accept(socket_t server_socket);
|
||||||
|
|
||||||
// the _all versions wait/retry until len bytes have been written/read
|
// the _all versions wait/retry until len bytes have been written/read
|
||||||
ssize_t net_recv(socket_t socket, void *buf, size_t len);
|
ssize_t
|
||||||
ssize_t net_recv_all(socket_t socket, void *buf, size_t len);
|
net_recv(socket_t socket, void *buf, size_t len);
|
||||||
ssize_t net_send(socket_t socket, const void *buf, size_t len);
|
|
||||||
ssize_t net_send_all(socket_t socket, const void *buf, size_t len);
|
ssize_t
|
||||||
|
net_recv_all(socket_t socket, void *buf, size_t len);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
net_send(socket_t socket, const void *buf, size_t len);
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
net_send_all(socket_t socket, const void *buf, size_t len);
|
||||||
|
|
||||||
// how is SHUT_RD (read), SHUT_WR (write) or SHUT_RDWR (both)
|
// how is SHUT_RD (read), SHUT_WR (write) or SHUT_RDWR (both)
|
||||||
SDL_bool net_shutdown(socket_t socket, int how);
|
SDL_bool
|
||||||
SDL_bool net_close(socket_t socket);
|
net_shutdown(socket_t socket, int how);
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
net_close(socket_t socket);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us
|
static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us
|
||||||
|
|
||||||
static const AVOutputFormat *find_muxer(const char *name) {
|
static const AVOutputFormat *
|
||||||
|
find_muxer(const char *name) {
|
||||||
#ifdef SCRCPY_LAVF_HAS_NEW_MUXER_ITERATOR_API
|
#ifdef SCRCPY_LAVF_HAS_NEW_MUXER_ITERATOR_API
|
||||||
void *opaque = NULL;
|
void *opaque = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,10 +26,11 @@ static const AVOutputFormat *find_muxer(const char *name) {
|
||||||
return oformat;
|
return oformat;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool recorder_init(struct recorder *recorder,
|
SDL_bool
|
||||||
const char *filename,
|
recorder_init(struct recorder *recorder,
|
||||||
enum recorder_format format,
|
const char *filename,
|
||||||
struct size declared_frame_size) {
|
enum recorder_format format,
|
||||||
|
struct size declared_frame_size) {
|
||||||
recorder->filename = SDL_strdup(filename);
|
recorder->filename = SDL_strdup(filename);
|
||||||
if (!recorder->filename) {
|
if (!recorder->filename) {
|
||||||
LOGE("Cannot strdup filename");
|
LOGE("Cannot strdup filename");
|
||||||
|
@ -42,7 +44,8 @@ SDL_bool recorder_init(struct recorder *recorder,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void recorder_destroy(struct recorder *recorder) {
|
void
|
||||||
|
recorder_destroy(struct recorder *recorder) {
|
||||||
SDL_free(recorder->filename);
|
SDL_free(recorder->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +58,8 @@ recorder_get_format_name(enum recorder_format format) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
SDL_bool
|
||||||
|
recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
||||||
const char *format_name = recorder_get_format_name(recorder->format);
|
const char *format_name = recorder_get_format_name(recorder->format);
|
||||||
SDL_assert(format_name);
|
SDL_assert(format_name);
|
||||||
const AVOutputFormat *format = find_muxer(format_name);
|
const AVOutputFormat *format = find_muxer(format_name);
|
||||||
|
@ -110,7 +114,8 @@ SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void recorder_close(struct recorder *recorder) {
|
void
|
||||||
|
recorder_close(struct recorder *recorder) {
|
||||||
int ret = av_write_trailer(recorder->ctx);
|
int ret = av_write_trailer(recorder->ctx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LOGE("Failed to write trailer to %s", recorder->filename);
|
LOGE("Failed to write trailer to %s", recorder->filename);
|
||||||
|
@ -161,7 +166,8 @@ recorder_rescale_packet(struct recorder *recorder, AVPacket *packet) {
|
||||||
av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base);
|
av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool recorder_write(struct recorder *recorder, AVPacket *packet) {
|
SDL_bool
|
||||||
|
recorder_write(struct recorder *recorder, AVPacket *packet) {
|
||||||
if (!recorder->header_written) {
|
if (!recorder->header_written) {
|
||||||
SDL_bool ok = recorder_write_header(recorder, packet);
|
SDL_bool ok = recorder_write_header(recorder, packet);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
|
|
@ -19,16 +19,20 @@ struct recorder {
|
||||||
SDL_bool header_written;
|
SDL_bool header_written;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool recorder_init(struct recorder *recoder,
|
SDL_bool
|
||||||
const char *filename,
|
recorder_init(struct recorder *recoder, const char *filename,
|
||||||
enum recorder_format format,
|
enum recorder_format format, struct size declared_frame_size);
|
||||||
struct size declared_frame_size);
|
|
||||||
|
|
||||||
void recorder_destroy(struct recorder *recorder);
|
void
|
||||||
|
recorder_destroy(struct recorder *recorder);
|
||||||
|
|
||||||
SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec);
|
SDL_bool
|
||||||
void recorder_close(struct recorder *recorder);
|
recorder_open(struct recorder *recorder, AVCodec *input_codec);
|
||||||
|
|
||||||
SDL_bool recorder_write(struct recorder *recorder, AVPacket *packet);
|
void
|
||||||
|
recorder_close(struct recorder *recorder);
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
recorder_write(struct recorder *recorder, AVPacket *packet);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,8 +51,10 @@ static struct input_manager input_manager = {
|
||||||
//
|
//
|
||||||
// <https://bugzilla.libsdl.org/show_bug.cgi?id=2077>
|
// <https://bugzilla.libsdl.org/show_bug.cgi?id=2077>
|
||||||
// <https://stackoverflow.com/a/40693139/1987178>
|
// <https://stackoverflow.com/a/40693139/1987178>
|
||||||
static int event_watcher(void *data, SDL_Event *event) {
|
static int
|
||||||
if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_RESIZED) {
|
event_watcher(void *data, SDL_Event *event) {
|
||||||
|
if (event->type == SDL_WINDOWEVENT
|
||||||
|
&& event->window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||||
// called from another thread, not very safe, but it's a workaround!
|
// called from another thread, not very safe, but it's a workaround!
|
||||||
screen_render(&screen);
|
screen_render(&screen);
|
||||||
}
|
}
|
||||||
|
@ -60,12 +62,14 @@ static int event_watcher(void *data, SDL_Event *event) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static SDL_bool is_apk(const char *file) {
|
static SDL_bool
|
||||||
|
is_apk(const char *file) {
|
||||||
const char *ext = strrchr(file, '.');
|
const char *ext = strrchr(file, '.');
|
||||||
return ext && !strcmp(ext, ".apk");
|
return ext && !strcmp(ext, ".apk");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool event_loop(void) {
|
static SDL_bool
|
||||||
|
event_loop(void) {
|
||||||
#ifdef CONTINUOUS_RESIZING_WORKAROUND
|
#ifdef CONTINUOUS_RESIZING_WORKAROUND
|
||||||
SDL_AddEventWatch(event_watcher, NULL);
|
SDL_AddEventWatch(event_watcher, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -104,14 +108,17 @@ static SDL_bool event_loop(void) {
|
||||||
input_manager_process_key(&input_manager, &event.key);
|
input_manager_process_key(&input_manager, &event.key);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
input_manager_process_mouse_motion(&input_manager, &event.motion);
|
input_manager_process_mouse_motion(&input_manager,
|
||||||
|
&event.motion);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEWHEEL:
|
case SDL_MOUSEWHEEL:
|
||||||
input_manager_process_mouse_wheel(&input_manager, &event.wheel);
|
input_manager_process_mouse_wheel(&input_manager,
|
||||||
|
&event.wheel);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
case SDL_MOUSEBUTTONUP:
|
case SDL_MOUSEBUTTONUP:
|
||||||
input_manager_process_mouse_button(&input_manager, &event.button);
|
input_manager_process_mouse_button(&input_manager,
|
||||||
|
&event.button);
|
||||||
break;
|
break;
|
||||||
case SDL_DROPFILE: {
|
case SDL_DROPFILE: {
|
||||||
file_handler_action_t action;
|
file_handler_action_t action;
|
||||||
|
@ -128,7 +135,8 @@ static SDL_bool event_loop(void) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static process_t set_show_touches_enabled(const char *serial, SDL_bool enabled) {
|
static process_t
|
||||||
|
set_show_touches_enabled(const char *serial, SDL_bool enabled) {
|
||||||
const char *value = enabled ? "1" : "0";
|
const char *value = enabled ? "1" : "0";
|
||||||
const char *const adb_cmd[] = {
|
const char *const adb_cmd[] = {
|
||||||
"shell", "settings", "put", "system", "show_touches", value
|
"shell", "settings", "put", "system", "show_touches", value
|
||||||
|
@ -136,12 +144,14 @@ static process_t set_show_touches_enabled(const char *serial, SDL_bool enabled)
|
||||||
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wait_show_touches(process_t process) {
|
static void
|
||||||
|
wait_show_touches(process_t process) {
|
||||||
// reap the process, ignore the result
|
// reap the process, ignore the result
|
||||||
process_check_success(process, "show_touches");
|
process_check_success(process, "show_touches");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_LogPriority sdl_priority_from_av_level(int level) {
|
static SDL_LogPriority
|
||||||
|
sdl_priority_from_av_level(int level) {
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case AV_LOG_PANIC:
|
case AV_LOG_PANIC:
|
||||||
case AV_LOG_FATAL:
|
case AV_LOG_FATAL:
|
||||||
|
@ -175,7 +185,8 @@ av_log_callback(void *avcl, int level, const char *fmt, va_list vl) {
|
||||||
SDL_free(local_fmt);
|
SDL_free(local_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool scrcpy(const struct scrcpy_options *options) {
|
SDL_bool
|
||||||
|
scrcpy(const struct scrcpy_options *options) {
|
||||||
SDL_bool record = !!options->record_filename;
|
SDL_bool record = !!options->record_filename;
|
||||||
if (!server_start(&server, options->serial, options->port,
|
if (!server_start(&server, options->serial, options->port,
|
||||||
options->max_size, options->bit_rate, options->crop,
|
options->max_size, options->bit_rate, options->crop,
|
||||||
|
@ -208,9 +219,9 @@ SDL_bool scrcpy(const struct scrcpy_options *options) {
|
||||||
char device_name[DEVICE_NAME_FIELD_LENGTH];
|
char device_name[DEVICE_NAME_FIELD_LENGTH];
|
||||||
struct size frame_size;
|
struct size frame_size;
|
||||||
|
|
||||||
// screenrecord does not send frames when the screen content does not change
|
// screenrecord does not send frames when the screen content does not
|
||||||
// therefore, we transmit the screen size before the video stream, to be able
|
// change therefore, we transmit the screen size before the video stream,
|
||||||
// to init the window immediately
|
// to be able to init the window immediately
|
||||||
if (!device_read_info(device_socket, device_name, &frame_size)) {
|
if (!device_read_info(device_socket, device_name, &frame_size)) {
|
||||||
server_stop(&server);
|
server_stop(&server);
|
||||||
ret = SDL_FALSE;
|
ret = SDL_FALSE;
|
||||||
|
@ -273,7 +284,8 @@ SDL_bool scrcpy(const struct scrcpy_options *options) {
|
||||||
goto finally_destroy_controller;
|
goto finally_destroy_controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!screen_init_rendering(&screen, device_name, frame_size, options->always_on_top)) {
|
if (!screen_init_rendering(&screen, device_name, frame_size,
|
||||||
|
options->always_on_top)) {
|
||||||
ret = SDL_FALSE;
|
ret = SDL_FALSE;
|
||||||
goto finally_stop_and_join_controller;
|
goto finally_stop_and_join_controller;
|
||||||
}
|
}
|
||||||
|
@ -328,7 +340,8 @@ finally_destroy_server:
|
||||||
wait_show_touches(proc_show_touches);
|
wait_show_touches(proc_show_touches);
|
||||||
}
|
}
|
||||||
LOGI("Disable show_touches");
|
LOGI("Disable show_touches");
|
||||||
proc_show_touches = set_show_touches_enabled(options->serial, SDL_FALSE);
|
proc_show_touches = set_show_touches_enabled(options->serial,
|
||||||
|
SDL_FALSE);
|
||||||
wait_show_touches(proc_show_touches);
|
wait_show_touches(proc_show_touches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct scrcpy_options {
|
||||||
SDL_bool no_window;
|
SDL_bool no_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool scrcpy(const struct scrcpy_options *options);
|
SDL_bool
|
||||||
|
scrcpy(const struct scrcpy_options *options);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
112
app/src/screen.c
112
app/src/screen.c
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
#define DISPLAY_MARGINS 96
|
#define DISPLAY_MARGINS 96
|
||||||
|
|
||||||
SDL_bool sdl_init_and_configure(void) {
|
SDL_bool
|
||||||
|
sdl_init_and_configure(void) {
|
||||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
LOGC("Could not initialize SDL: %s", SDL_GetError());
|
LOGC("Could not initialize SDL: %s", SDL_GetError());
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -39,7 +40,8 @@ SDL_bool sdl_init_and_configure(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the window size in a struct size
|
// get the window size in a struct size
|
||||||
static struct size get_native_window_size(SDL_Window *window) {
|
static struct size
|
||||||
|
get_native_window_size(SDL_Window *window) {
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
SDL_GetWindowSize(window, &width, &height);
|
SDL_GetWindowSize(window, &width, &height);
|
||||||
|
@ -51,7 +53,8 @@ static struct size get_native_window_size(SDL_Window *window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the windowed window size
|
// get the windowed window size
|
||||||
static struct size get_window_size(const struct screen *screen) {
|
static struct size
|
||||||
|
get_window_size(const struct screen *screen) {
|
||||||
if (screen->fullscreen) {
|
if (screen->fullscreen) {
|
||||||
return screen->windowed_window_size;
|
return screen->windowed_window_size;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +62,8 @@ static struct size get_window_size(const struct screen *screen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the window size to be applied when fullscreen is disabled
|
// set the window size to be applied when fullscreen is disabled
|
||||||
static void set_window_size(struct screen *screen, struct size new_size) {
|
static void
|
||||||
|
set_window_size(struct screen *screen, struct size new_size) {
|
||||||
// setting the window size during fullscreen is implementation defined,
|
// setting the window size during fullscreen is implementation defined,
|
||||||
// so apply the resize only after fullscreen is disabled
|
// so apply the resize only after fullscreen is disabled
|
||||||
if (screen->fullscreen) {
|
if (screen->fullscreen) {
|
||||||
|
@ -71,7 +75,8 @@ static void set_window_size(struct screen *screen, struct size new_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the preferred display bounds (i.e. the screen bounds with some margins)
|
// get the preferred display bounds (i.e. the screen bounds with some margins)
|
||||||
static SDL_bool get_preferred_display_bounds(struct size *bounds) {
|
static SDL_bool
|
||||||
|
get_preferred_display_bounds(struct size *bounds) {
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
#ifdef SCRCPY_SDL_HAS_GET_DISPLAY_USABLE_BOUNDS
|
#ifdef SCRCPY_SDL_HAS_GET_DISPLAY_USABLE_BOUNDS
|
||||||
# define GET_DISPLAY_BOUNDS(i, r) SDL_GetDisplayUsableBounds((i), (r))
|
# define GET_DISPLAY_BOUNDS(i, r) SDL_GetDisplayUsableBounds((i), (r))
|
||||||
|
@ -89,10 +94,12 @@ static SDL_bool get_preferred_display_bounds(struct size *bounds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the optimal size of the window, with the following constraints:
|
// return the optimal size of the window, with the following constraints:
|
||||||
// - it attempts to keep at least one dimension of the current_size (i.e. it crops the black borders)
|
// - it attempts to keep at least one dimension of the current_size (i.e. it
|
||||||
|
// crops the black borders)
|
||||||
// - it keeps the aspect ratio
|
// - it keeps the aspect ratio
|
||||||
// - it scales down to make it fit in the display_size
|
// - it scales down to make it fit in the display_size
|
||||||
static struct size get_optimal_size(struct size current_size, struct size frame_size) {
|
static struct size
|
||||||
|
get_optimal_size(struct size current_size, struct size frame_size) {
|
||||||
if (frame_size.width == 0 || frame_size.height == 0) {
|
if (frame_size.width == 0 || frame_size.height == 0) {
|
||||||
// avoid division by 0
|
// avoid division by 0
|
||||||
return current_size;
|
return current_size;
|
||||||
|
@ -117,7 +124,8 @@ static struct size get_optimal_size(struct size current_size, struct size frame_
|
||||||
// remove black borders on top and bottom
|
// remove black borders on top and bottom
|
||||||
h = frame_size.height * w / frame_size.width;
|
h = frame_size.height * w / frame_size.width;
|
||||||
} else {
|
} else {
|
||||||
// remove black borders on left and right (or none at all if it already fits)
|
// remove black borders on left and right (or none at all if it already
|
||||||
|
// fits)
|
||||||
w = frame_size.width * h / frame_size.height;
|
w = frame_size.width * h / frame_size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,29 +135,33 @@ static struct size get_optimal_size(struct size current_size, struct size frame_
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as get_optimal_size(), but read the current size from the window
|
// same as get_optimal_size(), but read the current size from the window
|
||||||
static inline struct size get_optimal_window_size(const struct screen *screen, struct size frame_size) {
|
static inline struct size
|
||||||
|
get_optimal_window_size(const struct screen *screen, struct size frame_size) {
|
||||||
struct size current_size = get_window_size(screen);
|
struct size current_size = get_window_size(screen);
|
||||||
return get_optimal_size(current_size, frame_size);
|
return get_optimal_size(current_size, frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initially, there is no current size, so use the frame size as current size
|
// initially, there is no current size, so use the frame size as current size
|
||||||
static inline struct size get_initial_optimal_size(struct size frame_size) {
|
static inline struct size
|
||||||
|
get_initial_optimal_size(struct size frame_size) {
|
||||||
return get_optimal_size(frame_size, frame_size);
|
return get_optimal_size(frame_size, frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_init(struct screen *screen) {
|
void
|
||||||
|
screen_init(struct screen *screen) {
|
||||||
*screen = (struct screen) SCREEN_INITIALIZER;
|
*screen = (struct screen) SCREEN_INITIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline SDL_Texture *create_texture(SDL_Renderer *renderer, struct size frame_size) {
|
static inline SDL_Texture *
|
||||||
return SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING,
|
create_texture(SDL_Renderer *renderer, struct size frame_size) {
|
||||||
|
return SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
|
||||||
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
frame_size.width, frame_size.height);
|
frame_size.width, frame_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool screen_init_rendering(struct screen *screen,
|
SDL_bool
|
||||||
const char *device_name,
|
screen_init_rendering(struct screen *screen, const char *device_name,
|
||||||
struct size frame_size,
|
struct size frame_size, SDL_bool always_on_top) {
|
||||||
SDL_bool always_on_top) {
|
|
||||||
screen->frame_size = frame_size;
|
screen->frame_size = frame_size;
|
||||||
|
|
||||||
struct size window_size = get_initial_optimal_size(frame_size);
|
struct size window_size = get_initial_optimal_size(frame_size);
|
||||||
|
@ -166,21 +178,25 @@ SDL_bool screen_init_rendering(struct screen *screen,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
screen->window = SDL_CreateWindow(device_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
screen->window = SDL_CreateWindow(device_name, SDL_WINDOWPOS_UNDEFINED,
|
||||||
window_size.width, window_size.height, window_flags);
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
window_size.width, window_size.height,
|
||||||
|
window_flags);
|
||||||
if (!screen->window) {
|
if (!screen->window) {
|
||||||
LOGC("Could not create window: %s", SDL_GetError());
|
LOGC("Could not create window: %s", SDL_GetError());
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
screen->renderer = SDL_CreateRenderer(screen->window, -1, SDL_RENDERER_ACCELERATED);
|
screen->renderer = SDL_CreateRenderer(screen->window, -1,
|
||||||
|
SDL_RENDERER_ACCELERATED);
|
||||||
if (!screen->renderer) {
|
if (!screen->renderer) {
|
||||||
LOGC("Could not create renderer: %s", SDL_GetError());
|
LOGC("Could not create renderer: %s", SDL_GetError());
|
||||||
screen_destroy(screen);
|
screen_destroy(screen);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width, frame_size.height)) {
|
if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width,
|
||||||
|
frame_size.height)) {
|
||||||
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
||||||
screen_destroy(screen);
|
screen_destroy(screen);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -195,7 +211,8 @@ SDL_bool screen_init_rendering(struct screen *screen,
|
||||||
SDL_SetWindowIcon(screen->window, icon);
|
SDL_SetWindowIcon(screen->window, icon);
|
||||||
SDL_FreeSurface(icon);
|
SDL_FreeSurface(icon);
|
||||||
|
|
||||||
LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width, frame_size.height);
|
LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width,
|
||||||
|
frame_size.height);
|
||||||
screen->texture = create_texture(screen->renderer, frame_size);
|
screen->texture = create_texture(screen->renderer, frame_size);
|
||||||
if (!screen->texture) {
|
if (!screen->texture) {
|
||||||
LOGC("Could not create texture: %s", SDL_GetError());
|
LOGC("Could not create texture: %s", SDL_GetError());
|
||||||
|
@ -206,11 +223,13 @@ SDL_bool screen_init_rendering(struct screen *screen,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_show_window(struct screen *screen) {
|
void
|
||||||
|
screen_show_window(struct screen *screen) {
|
||||||
SDL_ShowWindow(screen->window);
|
SDL_ShowWindow(screen->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_destroy(struct screen *screen) {
|
void
|
||||||
|
screen_destroy(struct screen *screen) {
|
||||||
if (screen->texture) {
|
if (screen->texture) {
|
||||||
SDL_DestroyTexture(screen->texture);
|
SDL_DestroyTexture(screen->texture);
|
||||||
}
|
}
|
||||||
|
@ -223,9 +242,12 @@ void screen_destroy(struct screen *screen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// recreate the texture and resize the window if the frame size has changed
|
// recreate the texture and resize the window if the frame size has changed
|
||||||
static SDL_bool prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
static SDL_bool
|
||||||
if (screen->frame_size.width != new_frame_size.width || screen->frame_size.height != new_frame_size.height) {
|
prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
||||||
if (SDL_RenderSetLogicalSize(screen->renderer, new_frame_size.width, new_frame_size.height)) {
|
if (screen->frame_size.width != new_frame_size.width
|
||||||
|
|| screen->frame_size.height != new_frame_size.height) {
|
||||||
|
if (SDL_RenderSetLogicalSize(screen->renderer, new_frame_size.width,
|
||||||
|
new_frame_size.height)) {
|
||||||
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -235,8 +257,10 @@ static SDL_bool prepare_for_frame(struct screen *screen, struct size new_frame_s
|
||||||
|
|
||||||
struct size current_size = get_window_size(screen);
|
struct size current_size = get_window_size(screen);
|
||||||
struct size target_size = {
|
struct size target_size = {
|
||||||
(Uint32) current_size.width * new_frame_size.width / screen->frame_size.width,
|
(Uint32) current_size.width * new_frame_size.width
|
||||||
(Uint32) current_size.height * new_frame_size.height / screen->frame_size.height,
|
/ screen->frame_size.width,
|
||||||
|
(Uint32) current_size.height * new_frame_size.height
|
||||||
|
/ screen->frame_size.height,
|
||||||
};
|
};
|
||||||
target_size = get_optimal_size(target_size, new_frame_size);
|
target_size = get_optimal_size(target_size, new_frame_size);
|
||||||
set_window_size(screen, target_size);
|
set_window_size(screen, target_size);
|
||||||
|
@ -256,14 +280,16 @@ static SDL_bool prepare_for_frame(struct screen *screen, struct size new_frame_s
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the frame into the texture
|
// write the frame into the texture
|
||||||
static void update_texture(struct screen *screen, const AVFrame *frame) {
|
static void
|
||||||
|
update_texture(struct screen *screen, const AVFrame *frame) {
|
||||||
SDL_UpdateYUVTexture(screen->texture, NULL,
|
SDL_UpdateYUVTexture(screen->texture, NULL,
|
||||||
frame->data[0], frame->linesize[0],
|
frame->data[0], frame->linesize[0],
|
||||||
frame->data[1], frame->linesize[1],
|
frame->data[1], frame->linesize[1],
|
||||||
frame->data[2], frame->linesize[2]);
|
frame->data[2], frame->linesize[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
SDL_bool
|
||||||
|
screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
||||||
mutex_lock(vb->mutex);
|
mutex_lock(vb->mutex);
|
||||||
const AVFrame *frame = video_buffer_consume_rendered_frame(vb);
|
const AVFrame *frame = video_buffer_consume_rendered_frame(vb);
|
||||||
struct size new_frame_size = {frame->width, frame->height};
|
struct size new_frame_size = {frame->width, frame->height};
|
||||||
|
@ -278,13 +304,15 @@ SDL_bool screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_render(struct screen *screen) {
|
void
|
||||||
|
screen_render(struct screen *screen) {
|
||||||
SDL_RenderClear(screen->renderer);
|
SDL_RenderClear(screen->renderer);
|
||||||
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
|
SDL_RenderCopy(screen->renderer, screen->texture, NULL, NULL);
|
||||||
SDL_RenderPresent(screen->renderer);
|
SDL_RenderPresent(screen->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_switch_fullscreen(struct screen *screen) {
|
void
|
||||||
|
screen_switch_fullscreen(struct screen *screen) {
|
||||||
if (!screen->fullscreen) {
|
if (!screen->fullscreen) {
|
||||||
// going to fullscreen, store the current windowed window size
|
// going to fullscreen, store the current windowed window size
|
||||||
screen->windowed_window_size = get_native_window_size(screen->window);
|
screen->windowed_window_size = get_native_window_size(screen->window);
|
||||||
|
@ -298,24 +326,30 @@ void screen_switch_fullscreen(struct screen *screen) {
|
||||||
screen->fullscreen = !screen->fullscreen;
|
screen->fullscreen = !screen->fullscreen;
|
||||||
if (!screen->fullscreen) {
|
if (!screen->fullscreen) {
|
||||||
// fullscreen disabled, restore expected windowed window size
|
// fullscreen disabled, restore expected windowed window size
|
||||||
SDL_SetWindowSize(screen->window, screen->windowed_window_size.width, screen->windowed_window_size.height);
|
SDL_SetWindowSize(screen->window, screen->windowed_window_size.width,
|
||||||
|
screen->windowed_window_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGD("Switched to %s mode", screen->fullscreen ? "fullscreen" : "windowed");
|
LOGD("Switched to %s mode", screen->fullscreen ? "fullscreen" : "windowed");
|
||||||
screen_render(screen);
|
screen_render(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_resize_to_fit(struct screen *screen) {
|
void
|
||||||
|
screen_resize_to_fit(struct screen *screen) {
|
||||||
if (!screen->fullscreen) {
|
if (!screen->fullscreen) {
|
||||||
struct size optimal_size = get_optimal_window_size(screen, screen->frame_size);
|
struct size optimal_size = get_optimal_window_size(screen,
|
||||||
SDL_SetWindowSize(screen->window, optimal_size.width, optimal_size.height);
|
screen->frame_size);
|
||||||
|
SDL_SetWindowSize(screen->window, optimal_size.width,
|
||||||
|
optimal_size.height);
|
||||||
LOGD("Resized to optimal size");
|
LOGD("Resized to optimal size");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_resize_to_pixel_perfect(struct screen *screen) {
|
void
|
||||||
|
screen_resize_to_pixel_perfect(struct screen *screen) {
|
||||||
if (!screen->fullscreen) {
|
if (!screen->fullscreen) {
|
||||||
SDL_SetWindowSize(screen->window, screen->frame_size.width, screen->frame_size.height);
|
SDL_SetWindowSize(screen->window, screen->frame_size.width,
|
||||||
|
screen->frame_size.height);
|
||||||
LOGD("Resized to pixel-perfect");
|
LOGD("Resized to pixel-perfect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,36 +38,44 @@ struct screen {
|
||||||
}
|
}
|
||||||
|
|
||||||
// init SDL and set appropriate hints
|
// init SDL and set appropriate hints
|
||||||
SDL_bool sdl_init_and_configure(void);
|
SDL_bool
|
||||||
|
sdl_init_and_configure(void);
|
||||||
|
|
||||||
// initialize default values
|
// initialize default values
|
||||||
void screen_init(struct screen *screen);
|
void
|
||||||
|
screen_init(struct screen *screen);
|
||||||
|
|
||||||
// initialize screen, create window, renderer and texture (window is hidden)
|
// initialize screen, create window, renderer and texture (window is hidden)
|
||||||
SDL_bool screen_init_rendering(struct screen *screen,
|
SDL_bool
|
||||||
const char *device_name,
|
screen_init_rendering(struct screen *screen, const char *device_name,
|
||||||
struct size frame_size,
|
struct size frame_size, SDL_bool always_on_top);
|
||||||
SDL_bool always_on_top);
|
|
||||||
|
|
||||||
// show the window
|
// show the window
|
||||||
void screen_show_window(struct screen *screen);
|
void
|
||||||
|
screen_show_window(struct screen *screen);
|
||||||
|
|
||||||
// destroy window, renderer and texture (if any)
|
// destroy window, renderer and texture (if any)
|
||||||
void screen_destroy(struct screen *screen);
|
void
|
||||||
|
screen_destroy(struct screen *screen);
|
||||||
|
|
||||||
// resize if necessary and write the rendered frame into the texture
|
// resize if necessary and write the rendered frame into the texture
|
||||||
SDL_bool screen_update_frame(struct screen *screen, struct video_buffer *vb);
|
SDL_bool
|
||||||
|
screen_update_frame(struct screen *screen, struct video_buffer *vb);
|
||||||
|
|
||||||
// render the texture to the renderer
|
// render the texture to the renderer
|
||||||
void screen_render(struct screen *screen);
|
void
|
||||||
|
screen_render(struct screen *screen);
|
||||||
|
|
||||||
// switch the fullscreen mode
|
// switch the fullscreen mode
|
||||||
void screen_switch_fullscreen(struct screen *screen);
|
void
|
||||||
|
screen_switch_fullscreen(struct screen *screen);
|
||||||
|
|
||||||
// resize window to optimal size (remove black borders)
|
// resize window to optimal size (remove black borders)
|
||||||
void screen_resize_to_fit(struct screen *screen);
|
void
|
||||||
|
screen_resize_to_fit(struct screen *screen);
|
||||||
|
|
||||||
// resize window to 1:1 (pixel-perfect)
|
// resize window to 1:1 (pixel-perfect)
|
||||||
void screen_resize_to_pixel_perfect(struct screen *screen);
|
void
|
||||||
|
screen_resize_to_pixel_perfect(struct screen *screen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
|
|
||||||
#define DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.jar"
|
#define DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.jar"
|
||||||
|
|
||||||
static const char *get_server_path(void) {
|
static const char *
|
||||||
|
get_server_path(void) {
|
||||||
const char *server_path = getenv("SCRCPY_SERVER_PATH");
|
const char *server_path = getenv("SCRCPY_SERVER_PATH");
|
||||||
if (!server_path) {
|
if (!server_path) {
|
||||||
server_path = DEFAULT_SERVER_PATH;
|
server_path = DEFAULT_SERVER_PATH;
|
||||||
|
@ -29,32 +30,38 @@ static const char *get_server_path(void) {
|
||||||
return server_path;
|
return server_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool push_server(const char *serial) {
|
static SDL_bool
|
||||||
|
push_server(const char *serial) {
|
||||||
process_t process = adb_push(serial, get_server_path(), DEVICE_SERVER_PATH);
|
process_t process = adb_push(serial, get_server_path(), DEVICE_SERVER_PATH);
|
||||||
return process_check_success(process, "adb push");
|
return process_check_success(process, "adb push");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool enable_tunnel_reverse(const char *serial, Uint16 local_port) {
|
static SDL_bool
|
||||||
|
enable_tunnel_reverse(const char *serial, Uint16 local_port) {
|
||||||
process_t process = adb_reverse(serial, SOCKET_NAME, local_port);
|
process_t process = adb_reverse(serial, SOCKET_NAME, local_port);
|
||||||
return process_check_success(process, "adb reverse");
|
return process_check_success(process, "adb reverse");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool disable_tunnel_reverse(const char *serial) {
|
static SDL_bool
|
||||||
|
disable_tunnel_reverse(const char *serial) {
|
||||||
process_t process = adb_reverse_remove(serial, SOCKET_NAME);
|
process_t process = adb_reverse_remove(serial, SOCKET_NAME);
|
||||||
return process_check_success(process, "adb reverse --remove");
|
return process_check_success(process, "adb reverse --remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool enable_tunnel_forward(const char *serial, Uint16 local_port) {
|
static SDL_bool
|
||||||
|
enable_tunnel_forward(const char *serial, Uint16 local_port) {
|
||||||
process_t process = adb_forward(serial, local_port, SOCKET_NAME);
|
process_t process = adb_forward(serial, local_port, SOCKET_NAME);
|
||||||
return process_check_success(process, "adb forward");
|
return process_check_success(process, "adb forward");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool disable_tunnel_forward(const char *serial, Uint16 local_port) {
|
static SDL_bool
|
||||||
|
disable_tunnel_forward(const char *serial, Uint16 local_port) {
|
||||||
process_t process = adb_forward_remove(serial, local_port);
|
process_t process = adb_forward_remove(serial, local_port);
|
||||||
return process_check_success(process, "adb forward --remove");
|
return process_check_success(process, "adb forward --remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool enable_tunnel(struct server *server) {
|
static SDL_bool
|
||||||
|
enable_tunnel(struct server *server) {
|
||||||
if (enable_tunnel_reverse(server->serial, server->local_port)) {
|
if (enable_tunnel_reverse(server->serial, server->local_port)) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -64,17 +71,19 @@ static SDL_bool enable_tunnel(struct server *server) {
|
||||||
return enable_tunnel_forward(server->serial, server->local_port);
|
return enable_tunnel_forward(server->serial, server->local_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool disable_tunnel(struct server *server) {
|
static SDL_bool
|
||||||
|
disable_tunnel(struct server *server) {
|
||||||
if (server->tunnel_forward) {
|
if (server->tunnel_forward) {
|
||||||
return disable_tunnel_forward(server->serial, server->local_port);
|
return disable_tunnel_forward(server->serial, server->local_port);
|
||||||
}
|
}
|
||||||
return disable_tunnel_reverse(server->serial);
|
return disable_tunnel_reverse(server->serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static process_t execute_server(const char *serial,
|
static process_t
|
||||||
Uint16 max_size, Uint32 bit_rate,
|
execute_server(const char *serial,
|
||||||
SDL_bool tunnel_forward, const char *crop,
|
Uint16 max_size, Uint32 bit_rate,
|
||||||
SDL_bool send_frame_meta) {
|
SDL_bool tunnel_forward, const char *crop,
|
||||||
|
SDL_bool send_frame_meta) {
|
||||||
char max_size_string[6];
|
char max_size_string[6];
|
||||||
char bit_rate_string[11];
|
char bit_rate_string[11];
|
||||||
sprintf(max_size_string, "%"PRIu16, max_size);
|
sprintf(max_size_string, "%"PRIu16, max_size);
|
||||||
|
@ -96,11 +105,13 @@ static process_t execute_server(const char *serial,
|
||||||
|
|
||||||
#define IPV4_LOCALHOST 0x7F000001
|
#define IPV4_LOCALHOST 0x7F000001
|
||||||
|
|
||||||
static socket_t listen_on_port(Uint16 port) {
|
static socket_t
|
||||||
|
listen_on_port(Uint16 port) {
|
||||||
return net_listen(IPV4_LOCALHOST, port, 1);
|
return net_listen(IPV4_LOCALHOST, port, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static socket_t connect_and_read_byte(Uint16 port) {
|
static socket_t
|
||||||
|
connect_and_read_byte(Uint16 port) {
|
||||||
socket_t socket = net_connect(IPV4_LOCALHOST, port);
|
socket_t socket = net_connect(IPV4_LOCALHOST, port);
|
||||||
if (socket == INVALID_SOCKET) {
|
if (socket == INVALID_SOCKET) {
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
@ -116,7 +127,8 @@ static socket_t connect_and_read_byte(Uint16 port) {
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
static socket_t connect_to_server(Uint16 port, Uint32 attempts, Uint32 delay) {
|
static socket_t
|
||||||
|
connect_to_server(Uint16 port, Uint32 attempts, Uint32 delay) {
|
||||||
do {
|
do {
|
||||||
LOGD("Remaining connection attempts: %d", (int) attempts);
|
LOGD("Remaining connection attempts: %d", (int) attempts);
|
||||||
socket_t socket = connect_and_read_byte(port);
|
socket_t socket = connect_and_read_byte(port);
|
||||||
|
@ -131,7 +143,8 @@ static socket_t connect_to_server(Uint16 port, Uint32 attempts, Uint32 delay) {
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_socket(socket_t *socket) {
|
static void
|
||||||
|
close_socket(socket_t *socket) {
|
||||||
SDL_assert(*socket != INVALID_SOCKET);
|
SDL_assert(*socket != INVALID_SOCKET);
|
||||||
net_shutdown(*socket, SHUT_RDWR);
|
net_shutdown(*socket, SHUT_RDWR);
|
||||||
if (!net_close(*socket)) {
|
if (!net_close(*socket)) {
|
||||||
|
@ -141,13 +154,15 @@ static void close_socket(socket_t *socket) {
|
||||||
*socket = INVALID_SOCKET;
|
*socket = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_init(struct server *server) {
|
void
|
||||||
|
server_init(struct server *server) {
|
||||||
*server = (struct server) SERVER_INITIALIZER;
|
*server = (struct server) SERVER_INITIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool server_start(struct server *server, const char *serial,
|
SDL_bool
|
||||||
Uint16 local_port, Uint16 max_size, Uint32 bit_rate,
|
server_start(struct server *server, const char *serial,
|
||||||
const char *crop, SDL_bool send_frame_meta) {
|
Uint16 local_port, Uint16 max_size, Uint32 bit_rate,
|
||||||
|
const char *crop, SDL_bool send_frame_meta) {
|
||||||
server->local_port = local_port;
|
server->local_port = local_port;
|
||||||
|
|
||||||
if (serial) {
|
if (serial) {
|
||||||
|
@ -173,8 +188,9 @@ SDL_bool server_start(struct server *server, const char *serial,
|
||||||
// At the application level, the device part is "the server" because it
|
// At the application level, the device part is "the server" because it
|
||||||
// serves video stream and control. However, at the network level, the
|
// serves video stream and control. However, at the network level, the
|
||||||
// client listens and the server connects to the client. That way, the
|
// client listens and the server connects to the client. That way, the
|
||||||
// client can listen before starting the server app, so there is no need to
|
// client can listen before starting the server app, so there is no
|
||||||
// try to connect until the server socket is listening on the device.
|
// need to try to connect until the server socket is listening on the
|
||||||
|
// device.
|
||||||
|
|
||||||
server->server_socket = listen_on_port(local_port);
|
server->server_socket = listen_on_port(local_port);
|
||||||
if (server->server_socket == INVALID_SOCKET) {
|
if (server->server_socket == INVALID_SOCKET) {
|
||||||
|
@ -204,13 +220,15 @@ SDL_bool server_start(struct server *server, const char *serial,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket_t server_connect_to(struct server *server) {
|
socket_t
|
||||||
|
server_connect_to(struct server *server) {
|
||||||
if (!server->tunnel_forward) {
|
if (!server->tunnel_forward) {
|
||||||
server->device_socket = net_accept(server->server_socket);
|
server->device_socket = net_accept(server->server_socket);
|
||||||
} else {
|
} else {
|
||||||
Uint32 attempts = 100;
|
Uint32 attempts = 100;
|
||||||
Uint32 delay = 100; // ms
|
Uint32 delay = 100; // ms
|
||||||
server->device_socket = connect_to_server(server->local_port, attempts, delay);
|
server->device_socket = connect_to_server(server->local_port, attempts,
|
||||||
|
delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->device_socket == INVALID_SOCKET) {
|
if (server->device_socket == INVALID_SOCKET) {
|
||||||
|
@ -229,7 +247,8 @@ socket_t server_connect_to(struct server *server) {
|
||||||
return server->device_socket;
|
return server->device_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_stop(struct server *server) {
|
void
|
||||||
|
server_stop(struct server *server) {
|
||||||
SDL_assert(server->process != PROCESS_NONE);
|
SDL_assert(server->process != PROCESS_NONE);
|
||||||
|
|
||||||
if (!cmd_terminate(server->process)) {
|
if (!cmd_terminate(server->process)) {
|
||||||
|
@ -245,7 +264,8 @@ void server_stop(struct server *server) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_destroy(struct server *server) {
|
void
|
||||||
|
server_destroy(struct server *server) {
|
||||||
if (server->server_socket != INVALID_SOCKET) {
|
if (server->server_socket != INVALID_SOCKET) {
|
||||||
close_socket(&server->server_socket);
|
close_socket(&server->server_socket);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,20 +27,25 @@ struct server {
|
||||||
}
|
}
|
||||||
|
|
||||||
// init default values
|
// init default values
|
||||||
void server_init(struct server *server);
|
void
|
||||||
|
server_init(struct server *server);
|
||||||
|
|
||||||
// push, enable tunnel et start the server
|
// push, enable tunnel et start the server
|
||||||
SDL_bool server_start(struct server *server, const char *serial,
|
SDL_bool
|
||||||
|
server_start(struct server *server, const char *serial,
|
||||||
Uint16 local_port, Uint16 max_size, Uint32 bit_rate,
|
Uint16 local_port, Uint16 max_size, Uint32 bit_rate,
|
||||||
const char *crop, SDL_bool send_frame_meta);
|
const char *crop, SDL_bool send_frame_meta);
|
||||||
|
|
||||||
// block until the communication with the server is established
|
// block until the communication with the server is established
|
||||||
socket_t server_connect_to(struct server *server);
|
socket_t
|
||||||
|
server_connect_to(struct server *server);
|
||||||
|
|
||||||
// disconnect and kill the server process
|
// disconnect and kill the server process
|
||||||
void server_stop(struct server *server);
|
void
|
||||||
|
server_stop(struct server *server);
|
||||||
|
|
||||||
// close and release sockets
|
// close and release sockets
|
||||||
void server_destroy(struct server *server);
|
void
|
||||||
|
server_destroy(struct server *server);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
# include <tchar.h>
|
# include <tchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t xstrncpy(char *dest, const char *src, size_t n) {
|
size_t
|
||||||
|
xstrncpy(char *dest, const char *src, size_t n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < n - 1 && src[i] != '\0'; ++i)
|
for (i = 0; i < n - 1 && src[i] != '\0'; ++i)
|
||||||
dest[i] = src[i];
|
dest[i] = src[i];
|
||||||
|
@ -17,7 +18,8 @@ size_t xstrncpy(char *dest, const char *src, size_t n) {
|
||||||
return src[i] == '\0' ? i : n;
|
return src[i] == '\0' ? i : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t xstrjoin(char *dst, const char *const tokens[], char sep, size_t n) {
|
size_t
|
||||||
|
xstrjoin(char *dst, const char *const tokens[], char sep, size_t n) {
|
||||||
const char *const *remaining = tokens;
|
const char *const *remaining = tokens;
|
||||||
const char *token = *remaining++;
|
const char *token = *remaining++;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -40,7 +42,8 @@ truncated:
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strquote(const char *src) {
|
char *
|
||||||
|
strquote(const char *src) {
|
||||||
size_t len = strlen(src);
|
size_t len = strlen(src);
|
||||||
char *quoted = malloc(len + 3);
|
char *quoted = malloc(len + 3);
|
||||||
if (!quoted) {
|
if (!quoted) {
|
||||||
|
@ -55,7 +58,8 @@ char *strquote(const char *src) {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
wchar_t *utf8_to_wide_char(const char *utf8) {
|
wchar_t *
|
||||||
|
utf8_to_wide_char(const char *utf8) {
|
||||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
||||||
if (!len) {
|
if (!len) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -9,21 +9,25 @@
|
||||||
// - it does not write useless bytes if strlen(src) < n
|
// - it does not write useless bytes if strlen(src) < n
|
||||||
// - it returns the number of chars actually written (max n-1) if src has
|
// - it returns the number of chars actually written (max n-1) if src has
|
||||||
// been copied completely, or n if src has been truncated
|
// been copied completely, or n if src has been truncated
|
||||||
size_t xstrncpy(char *dest, const char *src, size_t n);
|
size_t
|
||||||
|
xstrncpy(char *dest, const char *src, size_t n);
|
||||||
|
|
||||||
// join tokens by sep into dst
|
// join tokens by sep into dst
|
||||||
// returns the number of chars actually written (max n-1) if no trucation
|
// returns the number of chars actually written (max n-1) if no trucation
|
||||||
// occurred, or n if truncated
|
// occurred, or n if truncated
|
||||||
size_t xstrjoin(char *dst, const char *const tokens[], char sep, size_t n);
|
size_t
|
||||||
|
xstrjoin(char *dst, const char *const tokens[], char sep, size_t n);
|
||||||
|
|
||||||
// quote a string
|
// quote a string
|
||||||
// returns the new allocated string, to be freed by the caller
|
// returns the new allocated string, to be freed by the caller
|
||||||
char *strquote(const char *src);
|
char *
|
||||||
|
strquote(const char *src);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// convert a UTF-8 string to a wchar_t string
|
// convert a UTF-8 string to a wchar_t string
|
||||||
// returns the new allocated string, to be freed by the caller
|
// returns the new allocated string, to be freed by the caller
|
||||||
wchar_t *utf8_to_wide_char(const char *utf8);
|
wchar_t *
|
||||||
|
utf8_to_wide_char(const char *utf8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
#define HEADER_SIZE 12
|
#define HEADER_SIZE 12
|
||||||
#define NO_PTS UINT64_C(-1)
|
#define NO_PTS UINT64_C(-1)
|
||||||
|
|
||||||
static struct frame_meta *frame_meta_new(Uint64 pts) {
|
static struct frame_meta *
|
||||||
|
frame_meta_new(Uint64 pts) {
|
||||||
struct frame_meta *meta = malloc(sizeof(*meta));
|
struct frame_meta *meta = malloc(sizeof(*meta));
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
return meta;
|
return meta;
|
||||||
|
@ -32,12 +33,13 @@ static struct frame_meta *frame_meta_new(Uint64 pts) {
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_meta_delete(struct frame_meta *frame_meta) {
|
static void
|
||||||
|
frame_meta_delete(struct frame_meta *frame_meta) {
|
||||||
free(frame_meta);
|
free(frame_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_bool receiver_state_push_meta(struct receiver_state *state,
|
static SDL_bool
|
||||||
Uint64 pts) {
|
receiver_state_push_meta(struct receiver_state *state, Uint64 pts) {
|
||||||
struct frame_meta *frame_meta = frame_meta_new(pts);
|
struct frame_meta *frame_meta = frame_meta_new(pts);
|
||||||
if (!frame_meta) {
|
if (!frame_meta) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -53,7 +55,8 @@ static SDL_bool receiver_state_push_meta(struct receiver_state *state,
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint64 receiver_state_take_meta(struct receiver_state *state) {
|
static Uint64
|
||||||
|
receiver_state_take_meta(struct receiver_state *state) {
|
||||||
struct frame_meta *frame_meta = state->frame_meta_queue; // first item
|
struct frame_meta *frame_meta = state->frame_meta_queue; // first item
|
||||||
SDL_assert(frame_meta); // must not be empty
|
SDL_assert(frame_meta); // must not be empty
|
||||||
Uint64 pts = frame_meta->pts;
|
Uint64 pts = frame_meta->pts;
|
||||||
|
@ -62,7 +65,8 @@ static Uint64 receiver_state_take_meta(struct receiver_state *state) {
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_packet_with_meta(void *opaque, uint8_t *buf, int buf_size) {
|
static int
|
||||||
|
read_packet_with_meta(void *opaque, uint8_t *buf, int buf_size) {
|
||||||
struct stream *stream = opaque;
|
struct stream *stream = opaque;
|
||||||
struct receiver_state *state = &stream->receiver_state;
|
struct receiver_state *state = &stream->receiver_state;
|
||||||
|
|
||||||
|
@ -121,7 +125,8 @@ static int read_packet_with_meta(void *opaque, uint8_t *buf, int buf_size) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_raw_packet(void *opaque, uint8_t *buf, int buf_size) {
|
static int
|
||||||
|
read_raw_packet(void *opaque, uint8_t *buf, int buf_size) {
|
||||||
struct stream *stream = opaque;
|
struct stream *stream = opaque;
|
||||||
ssize_t r = net_recv(stream->socket, buf, buf_size);
|
ssize_t r = net_recv(stream->socket, buf, buf_size);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
|
@ -133,13 +138,15 @@ static int read_raw_packet(void *opaque, uint8_t *buf, int buf_size) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void notify_stopped(void) {
|
static void
|
||||||
|
notify_stopped(void) {
|
||||||
SDL_Event stop_event;
|
SDL_Event stop_event;
|
||||||
stop_event.type = EVENT_STREAM_STOPPED;
|
stop_event.type = EVENT_STREAM_STOPPED;
|
||||||
SDL_PushEvent(&stop_event);
|
SDL_PushEvent(&stop_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_stream(void *data) {
|
static int
|
||||||
|
run_stream(void *data) {
|
||||||
struct stream *stream = data;
|
struct stream *stream = data;
|
||||||
|
|
||||||
AVFormatContext *format_ctx = avformat_alloc_context();
|
AVFormatContext *format_ctx = avformat_alloc_context();
|
||||||
|
@ -246,14 +253,16 @@ end:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stream_init(struct stream *stream, socket_t socket,
|
void
|
||||||
struct decoder *decoder, struct recorder *recorder) {
|
stream_init(struct stream *stream, socket_t socket,
|
||||||
|
struct decoder *decoder, struct recorder *recorder) {
|
||||||
stream->socket = socket;
|
stream->socket = socket;
|
||||||
stream->decoder = decoder,
|
stream->decoder = decoder,
|
||||||
stream->recorder = recorder;
|
stream->recorder = recorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool stream_start(struct stream *stream) {
|
SDL_bool
|
||||||
|
stream_start(struct stream *stream) {
|
||||||
LOGD("Starting stream thread");
|
LOGD("Starting stream thread");
|
||||||
|
|
||||||
stream->thread = SDL_CreateThread(run_stream, "stream", stream);
|
stream->thread = SDL_CreateThread(run_stream, "stream", stream);
|
||||||
|
@ -264,12 +273,14 @@ SDL_bool stream_start(struct stream *stream) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stream_stop(struct stream *stream) {
|
void
|
||||||
|
stream_stop(struct stream *stream) {
|
||||||
if (stream->decoder) {
|
if (stream->decoder) {
|
||||||
decoder_interrupt(stream->decoder);
|
decoder_interrupt(stream->decoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stream_join(struct stream *stream) {
|
void
|
||||||
|
stream_join(struct stream *stream) {
|
||||||
SDL_WaitThread(stream->thread, NULL);
|
SDL_WaitThread(stream->thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,17 @@ struct stream {
|
||||||
} receiver_state;
|
} receiver_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
void stream_init(struct stream *stream, socket_t socket,
|
void
|
||||||
struct decoder *decoder, struct recorder *recorder);
|
stream_init(struct stream *stream, socket_t socket,
|
||||||
SDL_bool stream_start(struct stream *stream);
|
struct decoder *decoder, struct recorder *recorder);
|
||||||
void stream_stop(struct stream *stream);
|
|
||||||
void stream_join(struct stream *stream);
|
SDL_bool
|
||||||
|
stream_start(struct stream *stream);
|
||||||
|
|
||||||
|
void
|
||||||
|
stream_stop(struct stream *stream);
|
||||||
|
|
||||||
|
void
|
||||||
|
stream_join(struct stream *stream);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
enum process_result cmd_execute(const char *path, const char *const argv[], pid_t *pid) {
|
enum process_result
|
||||||
|
cmd_execute(const char *path, const char *const argv[], pid_t *pid) {
|
||||||
int fd[2];
|
int fd[2];
|
||||||
|
|
||||||
if (pipe(fd) == -1) {
|
if (pipe(fd) == -1) {
|
||||||
|
@ -72,15 +73,18 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool cmd_terminate(pid_t pid) {
|
SDL_bool
|
||||||
|
cmd_terminate(pid_t pid) {
|
||||||
if (pid <= 0) {
|
if (pid <= 0) {
|
||||||
LOGC("Requested to kill %d, this is an error. Please report the bug.\n", (int) pid);
|
LOGC("Requested to kill %d, this is an error. Please report the bug.\n",
|
||||||
|
(int) pid);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return kill(pid, SIGTERM) != -1;
|
return kill(pid, SIGTERM) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool cmd_simple_wait(pid_t pid, int *exit_code) {
|
SDL_bool
|
||||||
|
cmd_simple_wait(pid_t pid, int *exit_code) {
|
||||||
int status;
|
int status;
|
||||||
int code;
|
int code;
|
||||||
if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) {
|
if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) {
|
||||||
|
|
|
@ -2,15 +2,18 @@
|
||||||
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
|
||||||
SDL_bool net_init(void) {
|
SDL_bool
|
||||||
|
net_init(void) {
|
||||||
// do nothing
|
// do nothing
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_cleanup(void) {
|
void
|
||||||
|
net_cleanup(void) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool net_close(socket_t socket) {
|
SDL_bool
|
||||||
|
net_close(socket_t socket) {
|
||||||
return !close(socket);
|
return !close(socket);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "str_util.h"
|
#include "str_util.h"
|
||||||
|
|
||||||
static int build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
static int
|
||||||
|
build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
||||||
// Windows command-line parsing is WTF:
|
// Windows command-line parsing is WTF:
|
||||||
// <http://daviddeley.com/autohotkey/parameters/parameters.htm#WINPASS>
|
// <http://daviddeley.com/autohotkey/parameters/parameters.htm#WINPASS>
|
||||||
// only make it work for this very specific program
|
// only make it work for this very specific program
|
||||||
|
@ -17,7 +18,8 @@ static int build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum process_result cmd_execute(const char *path, const char *const argv[], HANDLE *handle) {
|
enum process_result
|
||||||
|
cmd_execute(const char *path, const char *const argv[], HANDLE *handle) {
|
||||||
STARTUPINFOW si;
|
STARTUPINFOW si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
memset(&si, 0, sizeof(si));
|
memset(&si, 0, sizeof(si));
|
||||||
|
@ -40,7 +42,8 @@ enum process_result cmd_execute(const char *path, const char *const argv[], HAND
|
||||||
#else
|
#else
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
#endif
|
#endif
|
||||||
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi)) {
|
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si,
|
||||||
|
&pi)) {
|
||||||
free(wide);
|
free(wide);
|
||||||
*handle = NULL;
|
*handle = NULL;
|
||||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||||
|
@ -54,13 +57,16 @@ enum process_result cmd_execute(const char *path, const char *const argv[], HAND
|
||||||
return PROCESS_SUCCESS;
|
return PROCESS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool cmd_terminate(HANDLE handle) {
|
SDL_bool
|
||||||
|
cmd_terminate(HANDLE handle) {
|
||||||
return TerminateProcess(handle, 1) && CloseHandle(handle);
|
return TerminateProcess(handle, 1) && CloseHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
|
SDL_bool
|
||||||
|
cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
|
||||||
DWORD code;
|
DWORD code;
|
||||||
if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0 || !GetExitCodeProcess(handle, &code)) {
|
if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
|
||||||
|
|| !GetExitCodeProcess(handle, &code)) {
|
||||||
// cannot wait or retrieve the exit code
|
// cannot wait or retrieve the exit code
|
||||||
code = -1; // max value, it's unsigned
|
code = -1; // max value, it's unsigned
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
SDL_bool net_init(void) {
|
SDL_bool
|
||||||
|
net_init(void) {
|
||||||
WSADATA wsa;
|
WSADATA wsa;
|
||||||
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
|
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
@ -12,10 +13,12 @@ SDL_bool net_init(void) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_cleanup(void) {
|
void
|
||||||
|
net_cleanup(void) {
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool net_close(socket_t socket) {
|
SDL_bool
|
||||||
|
net_close(socket_t socket) {
|
||||||
return !closesocket(socket);
|
return !closesocket(socket);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ struct index {
|
||||||
Uint32 color;
|
Uint32 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
static SDL_bool find_color(struct index *index, int len, char c, Uint32 *color) {
|
static SDL_bool
|
||||||
|
find_color(struct index *index, int len, char c, Uint32 *color) {
|
||||||
// there are typically very few color, so it's ok to iterate over the array
|
// there are typically very few color, so it's ok to iterate over the array
|
||||||
for (int i = 0; i < len; ++i) {
|
for (int i = 0; i < len; ++i) {
|
||||||
if (index[i].c == c) {
|
if (index[i].c == c) {
|
||||||
|
@ -30,7 +31,8 @@ static SDL_bool find_color(struct index *index, int len, char c, Uint32 *color)
|
||||||
//
|
//
|
||||||
// Parameter is not "const char *" because XPM formats are generally stored in a
|
// Parameter is not "const char *" because XPM formats are generally stored in a
|
||||||
// (non-const) "char *"
|
// (non-const) "char *"
|
||||||
SDL_Surface *read_xpm(char *xpm[]) {
|
SDL_Surface *
|
||||||
|
read_xpm(char *xpm[]) {
|
||||||
#if SDL_ASSERT_LEVEL >= 2
|
#if SDL_ASSERT_LEVEL >= 2
|
||||||
// patch the XPM to change the icon color in debug mode
|
// patch the XPM to change the icon color in debug mode
|
||||||
xpm[2] = ". c #CC00CC";
|
xpm[2] = ". c #CC00CC";
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
SDL_Surface *read_xpm(char *xpm[]);
|
SDL_Surface *
|
||||||
|
read_xpm(char *xpm[]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
SDL_bool video_buffer_init(struct video_buffer *vb) {
|
SDL_bool
|
||||||
|
video_buffer_init(struct video_buffer *vb) {
|
||||||
if (!(vb->decoding_frame = av_frame_alloc())) {
|
if (!(vb->decoding_frame = av_frame_alloc())) {
|
||||||
goto error_0;
|
goto error_0;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,8 @@ error_0:
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void video_buffer_destroy(struct video_buffer *vb) {
|
void
|
||||||
|
video_buffer_destroy(struct video_buffer *vb) {
|
||||||
#ifndef SKIP_FRAMES
|
#ifndef SKIP_FRAMES
|
||||||
SDL_DestroyCond(vb->rendering_frame_consumed_cond);
|
SDL_DestroyCond(vb->rendering_frame_consumed_cond);
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,13 +56,15 @@ void video_buffer_destroy(struct video_buffer *vb) {
|
||||||
av_frame_free(&vb->decoding_frame);
|
av_frame_free(&vb->decoding_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void video_buffer_swap_frames(struct video_buffer *vb) {
|
static void
|
||||||
|
video_buffer_swap_frames(struct video_buffer *vb) {
|
||||||
AVFrame *tmp = vb->decoding_frame;
|
AVFrame *tmp = vb->decoding_frame;
|
||||||
vb->decoding_frame = vb->rendering_frame;
|
vb->decoding_frame = vb->rendering_frame;
|
||||||
vb->rendering_frame = tmp;
|
vb->rendering_frame = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool video_buffer_offer_decoded_frame(struct video_buffer *vb) {
|
SDL_bool
|
||||||
|
video_buffer_offer_decoded_frame(struct video_buffer *vb) {
|
||||||
mutex_lock(vb->mutex);
|
mutex_lock(vb->mutex);
|
||||||
#ifndef SKIP_FRAMES
|
#ifndef SKIP_FRAMES
|
||||||
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
|
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
|
||||||
|
@ -83,7 +87,8 @@ SDL_bool video_buffer_offer_decoded_frame(struct video_buffer *vb) {
|
||||||
return previous_frame_consumed;
|
return previous_frame_consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AVFrame *video_buffer_consume_rendered_frame(struct video_buffer *vb) {
|
const AVFrame *
|
||||||
|
video_buffer_consume_rendered_frame(struct video_buffer *vb) {
|
||||||
SDL_assert(!vb->rendering_frame_consumed);
|
SDL_assert(!vb->rendering_frame_consumed);
|
||||||
vb->rendering_frame_consumed = SDL_TRUE;
|
vb->rendering_frame_consumed = SDL_TRUE;
|
||||||
if (vb->fps_counter.started) {
|
if (vb->fps_counter.started) {
|
||||||
|
@ -97,7 +102,8 @@ const AVFrame *video_buffer_consume_rendered_frame(struct video_buffer *vb) {
|
||||||
return vb->rendering_frame;
|
return vb->rendering_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void video_buffer_interrupt(struct video_buffer *vb) {
|
void
|
||||||
|
video_buffer_interrupt(struct video_buffer *vb) {
|
||||||
#ifdef SKIP_FRAMES
|
#ifdef SKIP_FRAMES
|
||||||
(void) vb; // unused
|
(void) vb; // unused
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -22,21 +22,27 @@ struct video_buffer {
|
||||||
struct fps_counter fps_counter;
|
struct fps_counter fps_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool video_buffer_init(struct video_buffer *vb);
|
SDL_bool
|
||||||
void video_buffer_destroy(struct video_buffer *vb);
|
video_buffer_init(struct video_buffer *vb);
|
||||||
|
|
||||||
|
void
|
||||||
|
video_buffer_destroy(struct video_buffer *vb);
|
||||||
|
|
||||||
// set the decoded frame as ready for rendering
|
// set the decoded frame as ready for rendering
|
||||||
// this function locks frames->mutex during its execution
|
// this function locks frames->mutex during its execution
|
||||||
// returns true if the previous frame had been consumed
|
// returns true if the previous frame had been consumed
|
||||||
SDL_bool video_buffer_offer_decoded_frame(struct video_buffer *vb);
|
SDL_bool
|
||||||
|
video_buffer_offer_decoded_frame(struct video_buffer *vb);
|
||||||
|
|
||||||
// mark the rendering frame as consumed and return it
|
// mark the rendering frame as consumed and return it
|
||||||
// MUST be called with frames->mutex locked!!!
|
// MUST be called with frames->mutex locked!!!
|
||||||
// the caller is expected to render the returned frame to some texture before
|
// the caller is expected to render the returned frame to some texture before
|
||||||
// unlocking frames->mutex
|
// unlocking frames->mutex
|
||||||
const AVFrame *video_buffer_consume_rendered_frame(struct video_buffer *vb);
|
const AVFrame *
|
||||||
|
video_buffer_consume_rendered_frame(struct video_buffer *vb);
|
||||||
|
|
||||||
// wake up and avoid any blocking call
|
// wake up and avoid any blocking call
|
||||||
void video_buffer_interrupt(struct video_buffer *vb);
|
void
|
||||||
|
video_buffer_interrupt(struct video_buffer *vb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue