Compare commits
6 Commits
sc_socket.
...
server_thr
Author | SHA1 | Date | |
---|---|---|---|
781bb7397b | |||
b876cf9ddc | |||
34eb10ea0b | |||
27fa23846d | |||
e4d5c1ce36 | |||
ac23bec144 |
@ -16,6 +16,7 @@ src = [
|
|||||||
'src/keyboard_inject.c',
|
'src/keyboard_inject.c',
|
||||||
'src/mouse_inject.c',
|
'src/mouse_inject.c',
|
||||||
'src/opengl.c',
|
'src/opengl.c',
|
||||||
|
'src/options.c',
|
||||||
'src/receiver.c',
|
'src/receiver.c',
|
||||||
'src/recorder.c',
|
'src/recorder.c',
|
||||||
'src/scrcpy.c',
|
'src/scrcpy.c',
|
||||||
@ -184,6 +185,7 @@ if get_option('buildtype') == 'debug'
|
|||||||
['test_cli', [
|
['test_cli', [
|
||||||
'tests/test_cli.c',
|
'tests/test_cli.c',
|
||||||
'src/cli.c',
|
'src/cli.c',
|
||||||
|
'src/options.c',
|
||||||
'src/util/str_util.c',
|
'src/util/str_util.c',
|
||||||
]],
|
]],
|
||||||
['test_clock', [
|
['test_clock', [
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#include <libusb-1.0/libusb.h>
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
#include "scrcpy.h"
|
|
||||||
#include "util/cbuf.h"
|
#include "util/cbuf.h"
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/tick.h"
|
#include "util/tick.h"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/str_util.h"
|
#include "util/str_util.h"
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
|
|
||||||
struct scrcpy_cli_args {
|
struct scrcpy_cli_args {
|
||||||
struct scrcpy_options opts;
|
struct scrcpy_options opts;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "fps_counter.h"
|
#include "fps_counter.h"
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "trait/key_processor.h"
|
#include "trait/key_processor.h"
|
||||||
#include "trait/mouse_processor.h"
|
#include "trait/mouse_processor.h"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
#include "trait/key_processor.h"
|
#include "trait/key_processor.h"
|
||||||
|
|
||||||
struct sc_keyboard_inject {
|
struct sc_keyboard_inject {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#include "scrcpy.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -13,6 +11,8 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "scrcpy.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -48,7 +48,7 @@ main(int argc, char *argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct scrcpy_cli_args args = {
|
struct scrcpy_cli_args args = {
|
||||||
.opts = SCRCPY_OPTIONS_DEFAULT,
|
.opts = scrcpy_options_default,
|
||||||
.help = false,
|
.help = false,
|
||||||
.version = false,
|
.version = false,
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "scrcpy.h"
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "trait/mouse_processor.h"
|
#include "trait/mouse_processor.h"
|
||||||
|
|
||||||
|
54
app/src/options.c
Normal file
54
app/src/options.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "options.h"
|
||||||
|
|
||||||
|
const struct scrcpy_options scrcpy_options_default = {
|
||||||
|
.serial = NULL,
|
||||||
|
.crop = NULL,
|
||||||
|
.record_filename = NULL,
|
||||||
|
.window_title = NULL,
|
||||||
|
.push_target = NULL,
|
||||||
|
.render_driver = NULL,
|
||||||
|
.codec_options = NULL,
|
||||||
|
.encoder_name = NULL,
|
||||||
|
#ifdef HAVE_V4L2
|
||||||
|
.v4l2_device = NULL,
|
||||||
|
#endif
|
||||||
|
.log_level = SC_LOG_LEVEL_INFO,
|
||||||
|
.record_format = SC_RECORD_FORMAT_AUTO,
|
||||||
|
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_INJECT,
|
||||||
|
.port_range = {
|
||||||
|
.first = DEFAULT_LOCAL_PORT_RANGE_FIRST,
|
||||||
|
.last = DEFAULT_LOCAL_PORT_RANGE_LAST,
|
||||||
|
},
|
||||||
|
.shortcut_mods = {
|
||||||
|
.data = {SC_MOD_LALT, SC_MOD_LSUPER},
|
||||||
|
.count = 2,
|
||||||
|
},
|
||||||
|
.max_size = 0,
|
||||||
|
.bit_rate = DEFAULT_BIT_RATE,
|
||||||
|
.max_fps = 0,
|
||||||
|
.lock_video_orientation = SC_LOCK_VIDEO_ORIENTATION_UNLOCKED,
|
||||||
|
.rotation = 0,
|
||||||
|
.window_x = SC_WINDOW_POSITION_UNDEFINED,
|
||||||
|
.window_y = SC_WINDOW_POSITION_UNDEFINED,
|
||||||
|
.window_width = 0,
|
||||||
|
.window_height = 0,
|
||||||
|
.display_id = 0,
|
||||||
|
.display_buffer = 0,
|
||||||
|
.v4l2_buffer = 0,
|
||||||
|
.show_touches = false,
|
||||||
|
.fullscreen = false,
|
||||||
|
.always_on_top = false,
|
||||||
|
.control = true,
|
||||||
|
.display = true,
|
||||||
|
.turn_screen_off = false,
|
||||||
|
.prefer_text = false,
|
||||||
|
.window_borderless = false,
|
||||||
|
.mipmaps = true,
|
||||||
|
.stay_awake = false,
|
||||||
|
.force_adb_forward = false,
|
||||||
|
.disable_screensaver = false,
|
||||||
|
.forward_key_repeat = true,
|
||||||
|
.forward_all_clicks = false,
|
||||||
|
.legacy_paste = false,
|
||||||
|
.power_off_on_close = false,
|
||||||
|
};
|
113
app/src/options.h
Normal file
113
app/src/options.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#ifndef SCRCPY_OPTIONS_H
|
||||||
|
#define SCRCPY_OPTIONS_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "util/tick.h"
|
||||||
|
|
||||||
|
enum sc_log_level {
|
||||||
|
SC_LOG_LEVEL_VERBOSE,
|
||||||
|
SC_LOG_LEVEL_DEBUG,
|
||||||
|
SC_LOG_LEVEL_INFO,
|
||||||
|
SC_LOG_LEVEL_WARN,
|
||||||
|
SC_LOG_LEVEL_ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sc_record_format {
|
||||||
|
SC_RECORD_FORMAT_AUTO,
|
||||||
|
SC_RECORD_FORMAT_MP4,
|
||||||
|
SC_RECORD_FORMAT_MKV,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sc_lock_video_orientation {
|
||||||
|
SC_LOCK_VIDEO_ORIENTATION_UNLOCKED = -1,
|
||||||
|
// lock the current orientation when scrcpy starts
|
||||||
|
SC_LOCK_VIDEO_ORIENTATION_INITIAL = -2,
|
||||||
|
SC_LOCK_VIDEO_ORIENTATION_0 = 0,
|
||||||
|
SC_LOCK_VIDEO_ORIENTATION_1,
|
||||||
|
SC_LOCK_VIDEO_ORIENTATION_2,
|
||||||
|
SC_LOCK_VIDEO_ORIENTATION_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sc_keyboard_input_mode {
|
||||||
|
SC_KEYBOARD_INPUT_MODE_INJECT,
|
||||||
|
SC_KEYBOARD_INPUT_MODE_HID,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SC_MAX_SHORTCUT_MODS 8
|
||||||
|
|
||||||
|
enum sc_shortcut_mod {
|
||||||
|
SC_MOD_LCTRL = 1 << 0,
|
||||||
|
SC_MOD_RCTRL = 1 << 1,
|
||||||
|
SC_MOD_LALT = 1 << 2,
|
||||||
|
SC_MOD_RALT = 1 << 3,
|
||||||
|
SC_MOD_LSUPER = 1 << 4,
|
||||||
|
SC_MOD_RSUPER = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sc_shortcut_mods {
|
||||||
|
unsigned data[SC_MAX_SHORTCUT_MODS];
|
||||||
|
unsigned count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sc_port_range {
|
||||||
|
uint16_t first;
|
||||||
|
uint16_t last;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SC_WINDOW_POSITION_UNDEFINED (-0x8000)
|
||||||
|
|
||||||
|
struct scrcpy_options {
|
||||||
|
const char *serial;
|
||||||
|
const char *crop;
|
||||||
|
const char *record_filename;
|
||||||
|
const char *window_title;
|
||||||
|
const char *push_target;
|
||||||
|
const char *render_driver;
|
||||||
|
const char *codec_options;
|
||||||
|
const char *encoder_name;
|
||||||
|
#ifdef HAVE_V4L2
|
||||||
|
const char *v4l2_device;
|
||||||
|
#endif
|
||||||
|
enum sc_log_level log_level;
|
||||||
|
enum sc_record_format record_format;
|
||||||
|
enum sc_keyboard_input_mode keyboard_input_mode;
|
||||||
|
struct sc_port_range port_range;
|
||||||
|
struct sc_shortcut_mods shortcut_mods;
|
||||||
|
uint16_t max_size;
|
||||||
|
uint32_t bit_rate;
|
||||||
|
uint16_t max_fps;
|
||||||
|
enum sc_lock_video_orientation lock_video_orientation;
|
||||||
|
uint8_t rotation;
|
||||||
|
int16_t window_x; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
||||||
|
int16_t window_y; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
||||||
|
uint16_t window_width;
|
||||||
|
uint16_t window_height;
|
||||||
|
uint32_t display_id;
|
||||||
|
sc_tick display_buffer;
|
||||||
|
sc_tick v4l2_buffer;
|
||||||
|
bool show_touches;
|
||||||
|
bool fullscreen;
|
||||||
|
bool always_on_top;
|
||||||
|
bool control;
|
||||||
|
bool display;
|
||||||
|
bool turn_screen_off;
|
||||||
|
bool prefer_text;
|
||||||
|
bool window_borderless;
|
||||||
|
bool mipmaps;
|
||||||
|
bool stay_awake;
|
||||||
|
bool force_adb_forward;
|
||||||
|
bool disable_screensaver;
|
||||||
|
bool forward_key_repeat;
|
||||||
|
bool forward_all_clicks;
|
||||||
|
bool legacy_paste;
|
||||||
|
bool power_off_on_close;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct scrcpy_options scrcpy_options_default;
|
||||||
|
|
||||||
|
#endif
|
@ -7,7 +7,7 @@
|
|||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
|
|
||||||
#include "coords.h"
|
#include "coords.h"
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
#include "trait/packet_sink.h"
|
#include "trait/packet_sink.h"
|
||||||
#include "util/queue.h"
|
#include "util/queue.h"
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
|
@ -258,10 +258,6 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
static struct scrcpy scrcpy;
|
static struct scrcpy scrcpy;
|
||||||
struct scrcpy *s = &scrcpy;
|
struct scrcpy *s = &scrcpy;
|
||||||
|
|
||||||
if (!server_init(&s->server)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
bool server_started = false;
|
bool server_started = false;
|
||||||
@ -297,7 +293,12 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
.force_adb_forward = options->force_adb_forward,
|
.force_adb_forward = options->force_adb_forward,
|
||||||
.power_off_on_close = options->power_off_on_close,
|
.power_off_on_close = options->power_off_on_close,
|
||||||
};
|
};
|
||||||
if (!server_start(&s->server, ¶ms)) {
|
|
||||||
|
if (!server_init(&s->server, ¶ms)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server_start(&s->server)) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +317,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options->display && options->control) {
|
if (options->display && options->control) {
|
||||||
if (!file_handler_init(&s->file_handler, s->server.serial,
|
if (!file_handler_init(&s->file_handler, options->serial,
|
||||||
options->push_target)) {
|
options->push_target)) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
153
app/src/scrcpy.h
153
app/src/scrcpy.h
@ -4,158 +4,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include "options.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "util/tick.h"
|
|
||||||
|
|
||||||
enum sc_log_level {
|
|
||||||
SC_LOG_LEVEL_VERBOSE,
|
|
||||||
SC_LOG_LEVEL_DEBUG,
|
|
||||||
SC_LOG_LEVEL_INFO,
|
|
||||||
SC_LOG_LEVEL_WARN,
|
|
||||||
SC_LOG_LEVEL_ERROR,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sc_record_format {
|
|
||||||
SC_RECORD_FORMAT_AUTO,
|
|
||||||
SC_RECORD_FORMAT_MP4,
|
|
||||||
SC_RECORD_FORMAT_MKV,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sc_lock_video_orientation {
|
|
||||||
SC_LOCK_VIDEO_ORIENTATION_UNLOCKED = -1,
|
|
||||||
// lock the current orientation when scrcpy starts
|
|
||||||
SC_LOCK_VIDEO_ORIENTATION_INITIAL = -2,
|
|
||||||
SC_LOCK_VIDEO_ORIENTATION_0 = 0,
|
|
||||||
SC_LOCK_VIDEO_ORIENTATION_1,
|
|
||||||
SC_LOCK_VIDEO_ORIENTATION_2,
|
|
||||||
SC_LOCK_VIDEO_ORIENTATION_3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sc_keyboard_input_mode {
|
|
||||||
SC_KEYBOARD_INPUT_MODE_INJECT,
|
|
||||||
SC_KEYBOARD_INPUT_MODE_HID,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SC_MAX_SHORTCUT_MODS 8
|
|
||||||
|
|
||||||
enum sc_shortcut_mod {
|
|
||||||
SC_MOD_LCTRL = 1 << 0,
|
|
||||||
SC_MOD_RCTRL = 1 << 1,
|
|
||||||
SC_MOD_LALT = 1 << 2,
|
|
||||||
SC_MOD_RALT = 1 << 3,
|
|
||||||
SC_MOD_LSUPER = 1 << 4,
|
|
||||||
SC_MOD_RSUPER = 1 << 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sc_shortcut_mods {
|
|
||||||
unsigned data[SC_MAX_SHORTCUT_MODS];
|
|
||||||
unsigned count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sc_port_range {
|
|
||||||
uint16_t first;
|
|
||||||
uint16_t last;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SC_WINDOW_POSITION_UNDEFINED (-0x8000)
|
|
||||||
|
|
||||||
struct scrcpy_options {
|
|
||||||
const char *serial;
|
|
||||||
const char *crop;
|
|
||||||
const char *record_filename;
|
|
||||||
const char *window_title;
|
|
||||||
const char *push_target;
|
|
||||||
const char *render_driver;
|
|
||||||
const char *codec_options;
|
|
||||||
const char *encoder_name;
|
|
||||||
const char *v4l2_device;
|
|
||||||
enum sc_log_level log_level;
|
|
||||||
enum sc_record_format record_format;
|
|
||||||
enum sc_keyboard_input_mode keyboard_input_mode;
|
|
||||||
struct sc_port_range port_range;
|
|
||||||
struct sc_shortcut_mods shortcut_mods;
|
|
||||||
uint16_t max_size;
|
|
||||||
uint32_t bit_rate;
|
|
||||||
uint16_t max_fps;
|
|
||||||
enum sc_lock_video_orientation lock_video_orientation;
|
|
||||||
uint8_t rotation;
|
|
||||||
int16_t window_x; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
|
||||||
int16_t window_y; // SC_WINDOW_POSITION_UNDEFINED for "auto"
|
|
||||||
uint16_t window_width;
|
|
||||||
uint16_t window_height;
|
|
||||||
uint32_t display_id;
|
|
||||||
sc_tick display_buffer;
|
|
||||||
sc_tick v4l2_buffer;
|
|
||||||
bool show_touches;
|
|
||||||
bool fullscreen;
|
|
||||||
bool always_on_top;
|
|
||||||
bool control;
|
|
||||||
bool display;
|
|
||||||
bool turn_screen_off;
|
|
||||||
bool prefer_text;
|
|
||||||
bool window_borderless;
|
|
||||||
bool mipmaps;
|
|
||||||
bool stay_awake;
|
|
||||||
bool force_adb_forward;
|
|
||||||
bool disable_screensaver;
|
|
||||||
bool forward_key_repeat;
|
|
||||||
bool forward_all_clicks;
|
|
||||||
bool legacy_paste;
|
|
||||||
bool power_off_on_close;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SCRCPY_OPTIONS_DEFAULT { \
|
|
||||||
.serial = NULL, \
|
|
||||||
.crop = NULL, \
|
|
||||||
.record_filename = NULL, \
|
|
||||||
.window_title = NULL, \
|
|
||||||
.push_target = NULL, \
|
|
||||||
.render_driver = NULL, \
|
|
||||||
.codec_options = NULL, \
|
|
||||||
.encoder_name = NULL, \
|
|
||||||
.v4l2_device = NULL, \
|
|
||||||
.log_level = SC_LOG_LEVEL_INFO, \
|
|
||||||
.record_format = SC_RECORD_FORMAT_AUTO, \
|
|
||||||
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_INJECT, \
|
|
||||||
.port_range = { \
|
|
||||||
.first = DEFAULT_LOCAL_PORT_RANGE_FIRST, \
|
|
||||||
.last = DEFAULT_LOCAL_PORT_RANGE_LAST, \
|
|
||||||
}, \
|
|
||||||
.shortcut_mods = { \
|
|
||||||
.data = {SC_MOD_LALT, SC_MOD_LSUPER}, \
|
|
||||||
.count = 2, \
|
|
||||||
}, \
|
|
||||||
.max_size = 0, \
|
|
||||||
.bit_rate = DEFAULT_BIT_RATE, \
|
|
||||||
.max_fps = 0, \
|
|
||||||
.lock_video_orientation = SC_LOCK_VIDEO_ORIENTATION_UNLOCKED, \
|
|
||||||
.rotation = 0, \
|
|
||||||
.window_x = SC_WINDOW_POSITION_UNDEFINED, \
|
|
||||||
.window_y = SC_WINDOW_POSITION_UNDEFINED, \
|
|
||||||
.window_width = 0, \
|
|
||||||
.window_height = 0, \
|
|
||||||
.display_id = 0, \
|
|
||||||
.display_buffer = 0, \
|
|
||||||
.v4l2_buffer = 0, \
|
|
||||||
.show_touches = false, \
|
|
||||||
.fullscreen = false, \
|
|
||||||
.always_on_top = false, \
|
|
||||||
.control = true, \
|
|
||||||
.display = true, \
|
|
||||||
.turn_screen_off = false, \
|
|
||||||
.prefer_text = false, \
|
|
||||||
.window_borderless = false, \
|
|
||||||
.mipmaps = true, \
|
|
||||||
.stay_awake = false, \
|
|
||||||
.force_adb_forward = false, \
|
|
||||||
.disable_screensaver = false, \
|
|
||||||
.forward_key_repeat = true, \
|
|
||||||
.forward_all_clicks = false, \
|
|
||||||
.legacy_paste = false, \
|
|
||||||
.power_off_on_close = false, \
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy(struct scrcpy_options *options);
|
scrcpy(struct scrcpy_options *options);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
#include "video_buffer.h"
|
#include "video_buffer.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
|
153
app/src/server.c
153
app/src/server.c
@ -61,6 +61,44 @@ get_server_path(void) {
|
|||||||
return server_path;
|
return server_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
server_params_destroy(struct server_params *params) {
|
||||||
|
// The server stores a copy of the params provided by the user
|
||||||
|
free((char *) params->serial);
|
||||||
|
free((char *) params->crop);
|
||||||
|
free((char *) params->codec_options);
|
||||||
|
free((char *) params->encoder_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
server_params_copy(struct server_params *dst, const struct server_params *src) {
|
||||||
|
*dst = *src;
|
||||||
|
|
||||||
|
// The params reference user-allocated memory, so we must copy them to
|
||||||
|
// handle them from another thread
|
||||||
|
|
||||||
|
#define COPY(FIELD) \
|
||||||
|
dst->FIELD = NULL; \
|
||||||
|
if (src->FIELD) { \
|
||||||
|
dst->FIELD = strdup(src->FIELD); \
|
||||||
|
if (!dst->FIELD) { \
|
||||||
|
goto error; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
COPY(serial);
|
||||||
|
COPY(crop);
|
||||||
|
COPY(codec_options);
|
||||||
|
COPY(encoder_name);
|
||||||
|
#undef COPY
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
server_params_destroy(dst);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
push_server(const char *serial) {
|
push_server(const char *serial) {
|
||||||
char *server_path = get_server_path();
|
char *server_path = get_server_path();
|
||||||
@ -103,10 +141,11 @@ disable_tunnel_forward(const char *serial, uint16_t local_port) {
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
disable_tunnel(struct server *server) {
|
disable_tunnel(struct server *server) {
|
||||||
|
const char *serial = server->params.serial;
|
||||||
if (server->tunnel_forward) {
|
if (server->tunnel_forward) {
|
||||||
return disable_tunnel_forward(server->serial, server->local_port);
|
return disable_tunnel_forward(serial, server->local_port);
|
||||||
}
|
}
|
||||||
return disable_tunnel_reverse(server->serial);
|
return disable_tunnel_reverse(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sc_socket
|
static sc_socket
|
||||||
@ -118,9 +157,10 @@ listen_on_port(uint16_t port) {
|
|||||||
static bool
|
static bool
|
||||||
enable_tunnel_reverse_any_port(struct server *server,
|
enable_tunnel_reverse_any_port(struct server *server,
|
||||||
struct sc_port_range port_range) {
|
struct sc_port_range port_range) {
|
||||||
|
const char *serial = server->params.serial;
|
||||||
uint16_t port = port_range.first;
|
uint16_t port = port_range.first;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!enable_tunnel_reverse(server->serial, port)) {
|
if (!enable_tunnel_reverse(serial, port)) {
|
||||||
// the command itself failed, it will fail on any port
|
// the command itself failed, it will fail on any port
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -139,7 +179,7 @@ enable_tunnel_reverse_any_port(struct server *server,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// failure, disable tunnel and try another port
|
// failure, disable tunnel and try another port
|
||||||
if (!disable_tunnel_reverse(server->serial)) {
|
if (!disable_tunnel_reverse(serial)) {
|
||||||
LOGW("Could not remove reverse tunnel on port %" PRIu16, port);
|
LOGW("Could not remove reverse tunnel on port %" PRIu16, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,9 +205,11 @@ static bool
|
|||||||
enable_tunnel_forward_any_port(struct server *server,
|
enable_tunnel_forward_any_port(struct server *server,
|
||||||
struct sc_port_range port_range) {
|
struct sc_port_range port_range) {
|
||||||
server->tunnel_forward = true;
|
server->tunnel_forward = true;
|
||||||
|
|
||||||
|
const char *serial = server->params.serial;
|
||||||
uint16_t port = port_range.first;
|
uint16_t port = port_range.first;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (enable_tunnel_forward(server->serial, port)) {
|
if (enable_tunnel_forward(serial, port)) {
|
||||||
// success
|
// success
|
||||||
server->local_port = port;
|
server->local_port = port;
|
||||||
return true;
|
return true;
|
||||||
@ -229,6 +271,8 @@ log_level_to_server_string(enum sc_log_level level) {
|
|||||||
|
|
||||||
static process_t
|
static process_t
|
||||||
execute_server(struct server *server, const struct server_params *params) {
|
execute_server(struct server *server, const struct server_params *params) {
|
||||||
|
const char *serial = server->params.serial;
|
||||||
|
|
||||||
char max_size_string[6];
|
char max_size_string[6];
|
||||||
char bit_rate_string[11];
|
char bit_rate_string[11];
|
||||||
char max_fps_string[6];
|
char max_fps_string[6];
|
||||||
@ -286,7 +330,7 @@ execute_server(struct server *server, const struct server_params *params) {
|
|||||||
// Port: 5005
|
// Port: 5005
|
||||||
// Then click on "Debug"
|
// Then click on "Debug"
|
||||||
#endif
|
#endif
|
||||||
return adb_execute(server->serial, cmd, ARRAY_LEN(cmd));
|
return adb_execute(serial, cmd, ARRAY_LEN(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static sc_socket
|
static sc_socket
|
||||||
@ -323,30 +367,26 @@ connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
|
|||||||
return SC_INVALID_SOCKET;
|
return SC_INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
close_socket(sc_socket socket) {
|
|
||||||
assert(socket != SC_INVALID_SOCKET);
|
|
||||||
net_shutdown(socket, SHUT_RDWR);
|
|
||||||
if (!net_close(socket)) {
|
|
||||||
LOGW("Could not close socket");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
server_init(struct server *server) {
|
server_init(struct server *server, const struct server_params *params) {
|
||||||
server->serial = NULL;
|
bool ok = server_params_copy(&server->params, params);
|
||||||
server->process = PROCESS_NONE;
|
|
||||||
atomic_flag_clear_explicit(&server->server_socket_closed,
|
|
||||||
memory_order_relaxed);
|
|
||||||
|
|
||||||
bool ok = sc_mutex_init(&server->mutex);
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
LOGE("Could not copy server params");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
server->process = PROCESS_NONE;
|
||||||
|
|
||||||
|
ok = sc_mutex_init(&server->mutex);
|
||||||
|
if (!ok) {
|
||||||
|
server_params_destroy(&server->params);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = sc_cond_init(&server->process_terminated_cond);
|
ok = sc_cond_init(&server->process_terminated_cond);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
sc_mutex_destroy(&server->mutex);
|
sc_mutex_destroy(&server->mutex);
|
||||||
|
server_params_destroy(&server->params);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,24 +416,18 @@ run_wait_server(void *data) {
|
|||||||
|
|
||||||
// no need for synchronization, server_socket is initialized before this
|
// no need for synchronization, server_socket is initialized before this
|
||||||
// thread was created
|
// thread was created
|
||||||
if (server->server_socket != SC_INVALID_SOCKET
|
if (server->server_socket != SC_INVALID_SOCKET) {
|
||||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
// Unblock any accept()
|
||||||
// On Linux, accept() is unblocked by shutdown(), but on Windows, it is
|
net_interrupt(server->server_socket);
|
||||||
// unblocked by closesocket(). Therefore, call both (close_socket()).
|
|
||||||
close_socket(server->server_socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGD("Server terminated");
|
LOGD("Server terminated");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
server_start(struct server *server, const struct server_params *params) {
|
server_start(struct server *server) {
|
||||||
if (params->serial) {
|
const struct server_params *params = &server->params;
|
||||||
server->serial = strdup(params->serial);
|
|
||||||
if (!server->serial) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!push_server(params->serial)) {
|
if (!push_server(params->serial)) {
|
||||||
/* server->serial will be freed on server_destroy() */
|
/* server->serial will be freed on server_destroy() */
|
||||||
@ -430,14 +464,8 @@ server_start(struct server *server, const struct server_params *params) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (!server->tunnel_forward) {
|
// The server socket (if any) will be closed on server_destroy()
|
||||||
bool was_closed =
|
|
||||||
atomic_flag_test_and_set(&server->server_socket_closed);
|
|
||||||
// the thread is not started, the flag could not be already set
|
|
||||||
assert(!was_closed);
|
|
||||||
(void) was_closed;
|
|
||||||
close_socket(server->server_socket);
|
|
||||||
}
|
|
||||||
disable_tunnel(server);
|
disable_tunnel(server);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -479,11 +507,11 @@ server_connect_to(struct server *server, char *device_name, struct size *size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we don't need the server socket anymore
|
// we don't need the server socket anymore
|
||||||
if (!atomic_flag_test_and_set(&server->server_socket_closed)) {
|
if (!net_close(server->server_socket)) {
|
||||||
// close it from here
|
LOGW("Could not close server socket on connect");
|
||||||
close_socket(server->server_socket);
|
|
||||||
// otherwise, it is closed by run_wait_server()
|
|
||||||
}
|
}
|
||||||
|
// Do not attempt to close it again on server_destroy()
|
||||||
|
server->server_socket = SC_INVALID_SOCKET;
|
||||||
} else {
|
} else {
|
||||||
uint32_t attempts = 100;
|
uint32_t attempts = 100;
|
||||||
uint32_t delay = 100; // ms
|
uint32_t delay = 100; // ms
|
||||||
@ -511,15 +539,20 @@ server_connect_to(struct server *server, char *device_name, struct size *size) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
server_stop(struct server *server) {
|
server_stop(struct server *server) {
|
||||||
if (server->server_socket != SC_INVALID_SOCKET
|
if (server->server_socket != SC_INVALID_SOCKET) {
|
||||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
if (!net_interrupt(server->server_socket)) {
|
||||||
close_socket(server->server_socket);
|
LOGW("Could not interrupt server socket");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (server->video_socket != SC_INVALID_SOCKET) {
|
if (server->video_socket != SC_INVALID_SOCKET) {
|
||||||
close_socket(server->video_socket);
|
if (!net_interrupt(server->video_socket)) {
|
||||||
|
LOGW("Could not interrupt video socket");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (server->control_socket != SC_INVALID_SOCKET) {
|
if (server->control_socket != SC_INVALID_SOCKET) {
|
||||||
close_socket(server->control_socket);
|
if (!net_interrupt(server->control_socket)) {
|
||||||
|
LOGW("Could not interrupt control socket");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(server->process != PROCESS_NONE);
|
assert(server->process != PROCESS_NONE);
|
||||||
@ -556,7 +589,23 @@ server_stop(struct server *server) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
server_destroy(struct server *server) {
|
server_destroy(struct server *server) {
|
||||||
free(server->serial);
|
if (server->server_socket != SC_INVALID_SOCKET) {
|
||||||
|
if (!net_close(server->server_socket)) {
|
||||||
|
LOGW("Could not close server socket");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server->video_socket != SC_INVALID_SOCKET) {
|
||||||
|
if (!net_close(server->video_socket)) {
|
||||||
|
LOGW("Could not close video socket");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server->control_socket != SC_INVALID_SOCKET) {
|
||||||
|
if (!net_close(server->control_socket)) {
|
||||||
|
LOGW("Could not close control socket");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server_params_destroy(&server->params);
|
||||||
sc_cond_destroy(&server->process_terminated_cond);
|
sc_cond_destroy(&server->process_terminated_cond);
|
||||||
sc_mutex_destroy(&server->mutex);
|
sc_mutex_destroy(&server->mutex);
|
||||||
}
|
}
|
||||||
|
@ -9,29 +9,11 @@
|
|||||||
|
|
||||||
#include "adb.h"
|
#include "adb.h"
|
||||||
#include "coords.h"
|
#include "coords.h"
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/net.h"
|
#include "util/net.h"
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
|
|
||||||
struct server {
|
|
||||||
char *serial;
|
|
||||||
process_t process;
|
|
||||||
sc_thread wait_server_thread;
|
|
||||||
atomic_flag server_socket_closed;
|
|
||||||
|
|
||||||
sc_mutex mutex;
|
|
||||||
sc_cond process_terminated_cond;
|
|
||||||
bool process_terminated;
|
|
||||||
|
|
||||||
sc_socket server_socket; // only used if !tunnel_forward
|
|
||||||
sc_socket video_socket;
|
|
||||||
sc_socket control_socket;
|
|
||||||
uint16_t local_port; // selected from port_range
|
|
||||||
bool tunnel_enabled;
|
|
||||||
bool tunnel_forward; // use "adb forward" instead of "adb reverse"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct server_params {
|
struct server_params {
|
||||||
const char *serial;
|
const char *serial;
|
||||||
enum sc_log_level log_level;
|
enum sc_log_level log_level;
|
||||||
@ -51,13 +33,32 @@ struct server_params {
|
|||||||
bool power_off_on_close;
|
bool power_off_on_close;
|
||||||
};
|
};
|
||||||
|
|
||||||
// init default values
|
struct server {
|
||||||
|
// The internal allocated strings are copies owned by the server
|
||||||
|
struct server_params params;
|
||||||
|
|
||||||
|
process_t process;
|
||||||
|
sc_thread wait_server_thread;
|
||||||
|
|
||||||
|
sc_mutex mutex;
|
||||||
|
sc_cond process_terminated_cond;
|
||||||
|
bool process_terminated;
|
||||||
|
|
||||||
|
sc_socket server_socket; // only used if !tunnel_forward
|
||||||
|
sc_socket video_socket;
|
||||||
|
sc_socket control_socket;
|
||||||
|
uint16_t local_port; // selected from port_range
|
||||||
|
bool tunnel_enabled;
|
||||||
|
bool tunnel_forward; // use "adb forward" instead of "adb reverse"
|
||||||
|
};
|
||||||
|
|
||||||
|
// init the server with the given params
|
||||||
bool
|
bool
|
||||||
server_init(struct server *server);
|
server_init(struct server *server, const struct server_params *params);
|
||||||
|
|
||||||
// push, enable tunnel et start the server
|
// push, enable tunnel et start the server
|
||||||
bool
|
bool
|
||||||
server_start(struct server *server, const struct server_params *params);
|
server_start(struct server *server);
|
||||||
|
|
||||||
#define DEVICE_NAME_FIELD_LENGTH 64
|
#define DEVICE_NAME_FIELD_LENGTH 64
|
||||||
// block until the communication with the server is established
|
// block until the communication with the server is established
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <SDL2/SDL_log.h>
|
#include <SDL2/SDL_log.h>
|
||||||
|
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
|
|
||||||
#define LOGV(...) SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
#define LOGV(...) SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
||||||
#define LOGD(...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
#define LOGD(...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
#include <SDL2/SDL_platform.h>
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ wrap(sc_raw_socket sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
socket->socket = sock;
|
socket->socket = sock;
|
||||||
|
socket->closed = (atomic_flag) ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
return socket;
|
return socket;
|
||||||
#else
|
#else
|
||||||
@ -195,18 +197,33 @@ net_send_all(sc_socket socket, const void *buf, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
net_shutdown(sc_socket socket, int how) {
|
net_interrupt(sc_socket socket) {
|
||||||
|
assert(socket != SC_INVALID_SOCKET);
|
||||||
|
|
||||||
sc_raw_socket raw_sock = unwrap(socket);
|
sc_raw_socket raw_sock = unwrap(socket);
|
||||||
return !shutdown(raw_sock, how);
|
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
if (!atomic_flag_test_and_set(&socket->closed)) {
|
||||||
|
return !closesocket(raw_sock);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return !shutdown(raw_sock, SHUT_RDWR);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
bool
|
bool
|
||||||
net_close(sc_socket socket) {
|
net_close(sc_socket socket) {
|
||||||
sc_raw_socket raw_sock = unwrap(socket);
|
sc_raw_socket raw_sock = unwrap(socket);
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
bool ret = true;
|
||||||
|
if (!atomic_flag_test_and_set(&socket->closed)) {
|
||||||
|
ret = !closesocket(raw_sock);
|
||||||
|
}
|
||||||
free(socket);
|
free(socket);
|
||||||
return !closesocket(raw_sock);
|
return ret;
|
||||||
#else
|
#else
|
||||||
return !close(raw_sock);
|
return !close(raw_sock);
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,12 +10,11 @@
|
|||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# define SHUT_RD SD_RECEIVE
|
# include <stdatomic.h>
|
||||||
# define SHUT_WR SD_SEND
|
|
||||||
# define SHUT_RDWR SD_BOTH
|
|
||||||
# define SC_INVALID_SOCKET NULL
|
# define SC_INVALID_SOCKET NULL
|
||||||
typedef struct sc_socket_windows {
|
typedef struct sc_socket_windows {
|
||||||
SOCKET socket;
|
SOCKET socket;
|
||||||
|
atomic_flag closed;
|
||||||
} *sc_socket;
|
} *sc_socket;
|
||||||
|
|
||||||
#else // not __WINDOWS__
|
#else // not __WINDOWS__
|
||||||
@ -53,10 +52,13 @@ net_send(sc_socket socket, const void *buf, size_t len);
|
|||||||
ssize_t
|
ssize_t
|
||||||
net_send_all(sc_socket socket, const void *buf, size_t len);
|
net_send_all(sc_socket socket, const void *buf, size_t len);
|
||||||
|
|
||||||
// how is SHUT_RD (read), SHUT_WR (write) or SHUT_RDWR (both)
|
// Shutdown the socket (or close on Windows) so that any blocking send() or
|
||||||
|
// recv() are interrupted.
|
||||||
bool
|
bool
|
||||||
net_shutdown(sc_socket socket, int how);
|
net_interrupt(sc_socket socket);
|
||||||
|
|
||||||
|
// Close the socket.
|
||||||
|
// A socket must always be closed, even if net_interrupt() has been called.
|
||||||
bool
|
bool
|
||||||
net_close(sc_socket socket);
|
net_close(sc_socket socket);
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
#include "scrcpy.h"
|
#include "options.h"
|
||||||
|
|
||||||
static void test_flag_version(void) {
|
static void test_flag_version(void) {
|
||||||
struct scrcpy_cli_args args = {
|
struct scrcpy_cli_args args = {
|
||||||
.opts = SCRCPY_OPTIONS_DEFAULT,
|
.opts = scrcpy_options_default,
|
||||||
.help = false,
|
.help = false,
|
||||||
.version = false,
|
.version = false,
|
||||||
};
|
};
|
||||||
@ -23,7 +23,7 @@ static void test_flag_version(void) {
|
|||||||
|
|
||||||
static void test_flag_help(void) {
|
static void test_flag_help(void) {
|
||||||
struct scrcpy_cli_args args = {
|
struct scrcpy_cli_args args = {
|
||||||
.opts = SCRCPY_OPTIONS_DEFAULT,
|
.opts = scrcpy_options_default,
|
||||||
.help = false,
|
.help = false,
|
||||||
.version = false,
|
.version = false,
|
||||||
};
|
};
|
||||||
@ -38,7 +38,7 @@ static void test_flag_help(void) {
|
|||||||
|
|
||||||
static void test_options(void) {
|
static void test_options(void) {
|
||||||
struct scrcpy_cli_args args = {
|
struct scrcpy_cli_args args = {
|
||||||
.opts = SCRCPY_OPTIONS_DEFAULT,
|
.opts = scrcpy_options_default,
|
||||||
.help = false,
|
.help = false,
|
||||||
.version = false,
|
.version = false,
|
||||||
};
|
};
|
||||||
@ -100,7 +100,7 @@ static void test_options(void) {
|
|||||||
|
|
||||||
static void test_options2(void) {
|
static void test_options2(void) {
|
||||||
struct scrcpy_cli_args args = {
|
struct scrcpy_cli_args args = {
|
||||||
.opts = SCRCPY_OPTIONS_DEFAULT,
|
.opts = scrcpy_options_default,
|
||||||
.help = false,
|
.help = false,
|
||||||
.version = false,
|
.version = false,
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user