Compare commits

..

1 Commits

Author SHA1 Message Date
Romain Vimont
5cbdd567bd Fix process execution on Windows 7
According to this bug report on Firefox:
<https://bugzilla.mozilla.org/show_bug.cgi?id=1460995>

> CreateProcess fails with ERROR_NO_SYSTEM_RESOURCES on Windows 7. It
> looks like the reason why is because PROC_THREAD_ATTRIBUTE_HANDLE_LIST
> doesn't like console handles.

To avoid the problem, do not pass console handles to
PROC_THREAD_ATTRIBUTE_HANDLE_LIST.

Refs #2783 <https://github.com/Genymobile/scrcpy/pull/2783>
Refs f801d8b312
Fixes #2838 <https://github.com/Genymobile/scrcpy/issues/2838>
2021-11-30 12:22:12 +01:00
32 changed files with 94 additions and 257 deletions

View File

@@ -49,11 +49,9 @@ conf.set('_XOPEN_SOURCE', '700')
conf.set('_GNU_SOURCE', true)
if host_machine.system() == 'windows'
windows = import('windows')
src += [
'src/sys/win/file.c',
'src/sys/win/process.c',
windows.compile_resources('scrcpy-windows.rc'),
]
conf.set('_WIN32_WINNT', '0x0600')
conf.set('WINVER', '0x0600')
@@ -86,10 +84,10 @@ if not get_option('crossbuild_windows')
# native build
dependencies = [
dependency('libavformat', version: '>= 57.33'),
dependency('libavcodec', version: '>= 57.37'),
dependency('libavformat'),
dependency('libavcodec'),
dependency('libavutil'),
dependency('sdl2', version: '>= 2.0.5'),
dependency('sdl2'),
]
if v4l2_support

View File

@@ -1,20 +0,0 @@
0 ICON "../data/icon.ico"
1 VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription", "Display and control your Android device"
VALUE "InternalName", "scrcpy"
VALUE "LegalCopyright", "Romain Vimont, Genymobile"
VALUE "OriginalFilename", "scrcpy.exe"
VALUE "ProductName", "scrcpy"
VALUE "ProductVersion", "1.21"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END

View File

@@ -413,15 +413,11 @@ Push file to device (see \fB\-\-push\-target\fR)
.TP
.B ADB
Path to adb.
.TP
.B SCRCPY_ICON_PATH
Path to the program icon.
Specify the path to adb.
.TP
.B SCRCPY_SERVER_PATH
Path to the server binary.
Specify the path to server binary.
.SH AUTHORS

View File

@@ -373,7 +373,7 @@ bool
sc_aoa_start(struct sc_aoa *aoa) {
LOGD("Starting AOA thread");
bool ok = sc_thread_create(&aoa->thread, run_aoa_thread, "scrcpy-aoa", aoa);
bool ok = sc_thread_create(&aoa->thread, run_aoa_thread, "aoa_thread", aoa);
if (!ok) {
LOGC("Could not start AOA thread");
return false;

View File

@@ -71,11 +71,6 @@ struct sc_shortcut {
const char *text;
};
struct sc_envvar {
const char *name;
const char *text;
};
struct sc_getopt_adapter {
char *optstring;
struct option *longopts;
@@ -590,21 +585,6 @@ static const struct sc_shortcut shortcuts[] = {
},
};
static const struct sc_envvar envvars[] = {
{
.name = "ADB",
.text = "Path to adb executable",
},
{
.name = "SCRCPY_ICON_PATH",
.text = "Path to the program icon",
},
{
.name = "SCRCPY_SERVER_PATH",
.text = "Path to the server binary",
}
};
static char *
sc_getopt_adapter_create_optstring(void) {
struct sc_strbuf buf;
@@ -698,7 +678,7 @@ sc_getopt_adapter_init(struct sc_getopt_adapter *adapter) {
}
return true;
}
};
static void
sc_getopt_adapter_destroy(struct sc_getopt_adapter *adapter) {
@@ -796,7 +776,7 @@ print_shortcuts_intro(unsigned cols) {
return;
}
printf("\n%s\n", intro);
printf("%s\n", intro);
free(intro);
}
@@ -824,23 +804,6 @@ print_shortcut(const struct sc_shortcut *shortcut, unsigned cols) {
free(text);
}
static void
print_envvar(const struct sc_envvar *envvar, unsigned cols) {
assert(cols > 8); // sc_str_wrap_lines() requires indent < columns
assert(envvar->name);
assert(envvar->text);
printf("\n %s\n", envvar->name);
char *text = sc_str_wrap_lines(envvar->text, cols, 8);
if (!text) {
printf("<ERROR>\n");
return;
}
printf("%s\n", text);
free(text);
}
void
scrcpy_print_usage(const char *arg0) {
#define SC_TERM_COLS_DEFAULT 80
@@ -868,17 +831,11 @@ scrcpy_print_usage(const char *arg0) {
}
// Print shortcuts section
printf("\nShortcuts:\n");
printf("\nShortcuts:\n\n");
print_shortcuts_intro(cols);
for (size_t i = 0; i < ARRAY_LEN(shortcuts); ++i) {
print_shortcut(&shortcuts[i], cols);
}
// Print environment variables section
printf("\nEnvironment variables:\n");
for (size_t i = 0; i < ARRAY_LEN(envvars); ++i) {
print_envvar(&envvars[i], cols);
}
}
static bool

View File

@@ -35,6 +35,15 @@
# define SCRCPY_LAVF_HAS_AVFORMATCONTEXT_URL
#endif
#if SDL_VERSION_ATLEAST(2, 0, 5)
// <https://wiki.libsdl.org/SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH>
# define SCRCPY_SDL_HAS_HINT_MOUSE_FOCUS_CLICKTHROUGH
// <https://wiki.libsdl.org/SDL_GetDisplayUsableBounds>
# define SCRCPY_SDL_HAS_GET_DISPLAY_USABLE_BOUNDS
// <https://wiki.libsdl.org/SDL_WindowFlags>
# define SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP
#endif
#if SDL_VERSION_ATLEAST(2, 0, 6)
// <https://github.com/libsdl-org/SDL/commit/d7a318de563125e5bb465b1000d6bc9576fbc6fc>
# define SCRCPY_SDL_HAS_HINT_TOUCH_MOUSE_EVENTS

View File

@@ -41,7 +41,7 @@ static const char *const android_motionevent_action_labels[] = {
"pointer-up",
"hover-move",
"scroll",
"hover-enter",
"hover-enter"
"hover-exit",
"btn-press",
"btn-release",
@@ -69,7 +69,7 @@ write_position(uint8_t *buf, const struct sc_position *position) {
buffer_write16be(&buf[10], position->screen_size.height);
}
// write length (4 bytes) + string (non null-terminated)
// write length (2 bytes) + string (non nul-terminated)
static size_t
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
size_t len = sc_str_utf8_truncation_index(utf8, max_len);

View File

@@ -14,8 +14,8 @@
#define CONTROL_MSG_MAX_SIZE (1 << 18) // 256k
#define CONTROL_MSG_INJECT_TEXT_MAX_LENGTH 300
// type: 1 byte; sequence: 8 bytes; paste flag: 1 byte; length: 4 bytes
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 14)
// type: 1 byte; paste flag: 1 byte; length: 4 bytes
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6)
#define POINTER_ID_MOUSE UINT64_C(-1)
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2)

View File

@@ -110,7 +110,7 @@ controller_start(struct controller *controller) {
LOGD("Starting controller thread");
bool ok = sc_thread_create(&controller->thread, run_controller,
"scrcpy-ctl", controller);
"controller", controller);
if (!ok) {
LOGC("Could not start controller thread");
return false;

View File

@@ -46,8 +46,6 @@ decoder_open(struct decoder *decoder, const AVCodec *codec) {
return false;
}
decoder->codec_ctx->flags |= AV_CODEC_FLAG_LOW_DELAY;
if (avcodec_open2(decoder->codec_ctx, codec, NULL) < 0) {
LOGE("Could not open codec");
avcodec_free_context(&decoder->codec_ctx);

View File

@@ -154,7 +154,7 @@ file_handler_start(struct file_handler *file_handler) {
LOGD("Starting file_handler thread");
bool ok = sc_thread_create(&file_handler->thread, run_file_handler,
"scrcpy-file", file_handler);
"file_handler", file_handler);
if (!ok) {
LOGC("Could not start file_handler thread");
return false;

View File

@@ -108,7 +108,7 @@ fps_counter_start(struct fps_counter *counter) {
// same thread, no need to lock
if (!counter->thread_started) {
bool ok = sc_thread_create(&counter->thread, run_fps_counter,
"scrcpy-fps", counter);
"fps counter", counter);
if (!ok) {
LOGE("Could not start FPS counter thread");
return false;

View File

@@ -111,8 +111,8 @@ bool
receiver_start(struct receiver *receiver) {
LOGD("Starting receiver thread");
bool ok = sc_thread_create(&receiver->thread, run_receiver,
"scrcpy-receiver", receiver);
bool ok = sc_thread_create(&receiver->thread, run_receiver, "receiver",
receiver);
if (!ok) {
LOGC("Could not start receiver thread");
return false;

View File

@@ -287,8 +287,8 @@ recorder_open(struct recorder *recorder, const AVCodec *input_codec) {
}
LOGD("Starting recorder thread");
ok = sc_thread_create(&recorder->thread, run_recorder, "scrcpy-recorder",
recorder);
ok = sc_thread_create(&recorder->thread, run_recorder, "recorder",
recorder);
if (!ok) {
LOGC("Could not start recorder thread");
goto error_avio_close;

View File

@@ -94,10 +94,12 @@ sdl_set_hints(const char *render_driver) {
LOGW("Could not enable linear filtering");
}
#ifdef SCRCPY_SDL_HAS_HINT_MOUSE_FOCUS_CLICKTHROUGH
// Handle a click to gain focus as any other click
if (!SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")) {
LOGW("Could not enable mouse focus clickthrough");
}
#endif
#ifdef SCRCPY_SDL_HAS_HINT_TOUCH_MOUSE_EVENTS
// Disable synthetic mouse events from touch events

View File

@@ -64,7 +64,12 @@ set_window_size(struct screen *screen, struct sc_size new_size) {
static bool
get_preferred_display_bounds(struct sc_size *bounds) {
SDL_Rect rect;
if (SDL_GetDisplayUsableBounds(0, &rect)) {
#ifdef SCRCPY_SDL_HAS_GET_DISPLAY_USABLE_BOUNDS
# define GET_DISPLAY_BOUNDS(i, r) SDL_GetDisplayUsableBounds((i), (r))
#else
# define GET_DISPLAY_BOUNDS(i, r) SDL_GetDisplayBounds((i), (r))
#endif
if (GET_DISPLAY_BOUNDS(0, &rect)) {
LOGW("Could not get display usable bounds: %s", SDL_GetError());
return false;
}
@@ -389,7 +394,12 @@ screen_init(struct screen *screen, const struct screen_params *params) {
| SDL_WINDOW_RESIZABLE
| SDL_WINDOW_ALLOW_HIGHDPI;
if (params->always_on_top) {
#ifdef SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
#else
LOGW("The 'always on top' flag is not available "
"(compile with SDL >= 2.0.5 to enable it)");
#endif
}
if (params->window_borderless) {
window_flags |= SDL_WINDOW_BORDERLESS;

View File

@@ -388,7 +388,6 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
assert(tunnel->enabled);
const char *serial = server->params.serial;
bool control = server->params.control;
sc_socket video_socket = SC_SOCKET_NONE;
sc_socket control_socket = SC_SOCKET_NONE;
@@ -398,12 +397,9 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
goto fail;
}
if (control) {
control_socket =
net_accept_intr(&server->intr, tunnel->server_socket);
if (control_socket == SC_SOCKET_NONE) {
goto fail;
}
control_socket = net_accept_intr(&server->intr, tunnel->server_socket);
if (control_socket == SC_SOCKET_NONE) {
goto fail;
}
} else {
uint32_t tunnel_host = server->params.tunnel_host;
@@ -424,18 +420,15 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
goto fail;
}
if (control) {
// we know that the device is listening, we don't need several
// attempts
control_socket = net_socket();
if (control_socket == SC_SOCKET_NONE) {
goto fail;
}
bool ok = net_connect_intr(&server->intr, control_socket,
tunnel_host, tunnel_port);
if (!ok) {
goto fail;
}
// we know that the device is listening, we don't need several attempts
control_socket = net_socket();
if (control_socket == SC_SOCKET_NONE) {
goto fail;
}
bool ok = net_connect_intr(&server->intr, control_socket, tunnel_host,
tunnel_port);
if (!ok) {
goto fail;
}
}
@@ -449,7 +442,7 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
}
assert(video_socket != SC_SOCKET_NONE);
assert(!control || control_socket != SC_SOCKET_NONE);
assert(control_socket != SC_SOCKET_NONE);
server->video_socket = video_socket;
server->control_socket = control_socket;
@@ -763,17 +756,6 @@ run_server(void *data) {
}
sc_mutex_unlock(&server->mutex);
// Interrupt sockets to wake up socket blocking calls on the server
assert(server->video_socket != SC_SOCKET_NONE);
net_interrupt(server->video_socket);
net_close(server->video_socket);
if (server->control_socket != SC_SOCKET_NONE) {
// There is no control_socket if --no-control is set
net_interrupt(server->control_socket);
net_close(server->control_socket);
}
// Give some delay for the server to terminate properly
#define WATCHDOG_DELAY SC_TICK_FROM_SEC(1)
sc_tick deadline = sc_tick_now() + WATCHDOG_DELAY;
@@ -804,8 +786,7 @@ error_connection_failed:
bool
sc_server_start(struct sc_server *server) {
bool ok =
sc_thread_create(&server->thread, run_server, "scrcpy-server", server);
bool ok = sc_thread_create(&server->thread, run_server, "server", server);
if (!ok) {
LOGE("Could not create server thread");
return false;

View File

@@ -284,8 +284,7 @@ bool
stream_start(struct stream *stream) {
LOGD("Starting stream thread");
bool ok =
sc_thread_create(&stream->thread, run_stream, "scrcpy-stream", stream);
bool ok = sc_thread_create(&stream->thread, run_stream, "stream", stream);
if (!ok) {
LOGC("Could not start stream thread");
return false;

View File

@@ -64,7 +64,7 @@ sc_process_observer_init(struct sc_process_observer *observer, sc_pid pid,
observer->listener_userdata = listener_userdata;
observer->terminated = false;
ok = sc_thread_create(&observer->thread, run_observer, "scrcpy-proc",
ok = sc_thread_create(&observer->thread, run_observer, "process_observer",
observer);
if (!ok) {
sc_cond_destroy(&observer->cond_terminated);

View File

@@ -8,10 +8,6 @@
bool
sc_thread_create(sc_thread *thread, sc_thread_fn fn, const char *name,
void *userdata) {
// The thread name length is limited on some systems. Never use a name
// longer than 16 bytes (including the final '\0')
assert(strlen(name) <= 15);
SDL_Thread *sdl_thread = SDL_CreateThread(fn, name, userdata);
if (!sdl_thread) {
LOG_OOM();

View File

@@ -1,55 +1,16 @@
#include "tick.h"
#include <assert.h>
#include <time.h>
#ifdef _WIN32
# include <windows.h>
#endif
#include <SDL2/SDL_timer.h>
sc_tick
sc_tick_now(void) {
#ifndef _WIN32
// Maximum sc_tick precision (microsecond)
struct timespec ts;
int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
if (ret) {
abort();
}
return SC_TICK_FROM_SEC(ts.tv_sec) + SC_TICK_FROM_NS(ts.tv_nsec);
#else
LARGE_INTEGER c;
// On systems that run Windows XP or later, the function will always
// succeed and will thus never return zero.
// <https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter>
// <https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancefrequency>
BOOL ok = QueryPerformanceCounter(&c);
assert(ok);
(void) ok;
LONGLONG counter = c.QuadPart;
static LONGLONG frequency;
if (!frequency) {
// Initialize on first call
LARGE_INTEGER f;
ok = QueryPerformanceFrequency(&f);
assert(ok);
frequency = f.QuadPart;
assert(frequency);
}
if (frequency % SC_TICK_FREQ == 0) {
// Expected case (typically frequency = 10000000, i.e. 100ns precision)
sc_tick div = frequency / SC_TICK_FREQ;
return SC_TICK_FROM_US(counter / div);
}
// Split the division to avoid overflow
sc_tick secs = SC_TICK_FROM_SEC(counter / frequency);
sc_tick subsec = SC_TICK_FREQ * (counter % frequency) / frequency;
return secs + subsec;
#endif
// SDL_GetTicks() resolution is in milliseconds, but sc_tick are expressed
// in microseconds to store PTS without precision loss.
//
// As an alternative, SDL_GetPerformanceCounter() and
// SDL_GetPerformanceFrequency() could be used, but:
// - the conversions (avoiding overflow) are expansive, since the
// frequency is not known at compile time;
// - in practice, we don't need more precision for now.
return (sc_tick) SDL_GetTicks() * 1000;
}

View File

@@ -10,11 +10,9 @@ typedef int64_t sc_tick;
#define SC_TICK_FREQ 1000000 // microsecond
// To be adapted if SC_TICK_FREQ changes
#define SC_TICK_TO_NS(tick) ((tick) * 1000)
#define SC_TICK_TO_US(tick) (tick)
#define SC_TICK_TO_MS(tick) ((tick) / 1000)
#define SC_TICK_TO_SEC(tick) ((tick) / 1000000)
#define SC_TICK_FROM_NS(ns) ((ns) / 1000)
#define SC_TICK_FROM_US(us) (us)
#define SC_TICK_FROM_MS(ms) ((ms) * 1000)
#define SC_TICK_FROM_SEC(sec) ((sec) * 1000000)

View File

@@ -272,7 +272,7 @@ sc_v4l2_sink_open(struct sc_v4l2_sink *vs) {
vs->stopped = false;
LOGD("Starting v4l2 thread");
ok = sc_thread_create(&vs->thread, run_v4l2_sink, "scrcpy-v4l2", vs);
ok = sc_thread_create(&vs->thread, run_v4l2_sink, "v4l2", vs);
if (!ok) {
LOGC("Could not start v4l2 thread");
goto error_av_packet_free;

View File

@@ -170,7 +170,7 @@ bool
sc_video_buffer_start(struct sc_video_buffer *vb) {
if (vb->buffering_time) {
bool ok =
sc_thread_create(&vb->b.thread, run_buffering, "scrcpy-vbuf", vb);
sc_thread_create(&vb->b.thread, run_buffering, "buffering", vb);
if (!ok) {
LOGE("Could not start buffering thread");
return false;

View File

@@ -169,4 +169,4 @@ int main(int argc, char *argv[]) {
test_options2();
test_parse_shortcut_mods();
return 0;
}
};

View File

@@ -54,7 +54,7 @@ static void test_serialize_inject_text_long(void) {
struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_INJECT_TEXT;
char text[CONTROL_MSG_INJECT_TEXT_MAX_LENGTH + 1];
memset(text, 'a', CONTROL_MSG_INJECT_TEXT_MAX_LENGTH);
memset(text, 'a', sizeof(text));
text[CONTROL_MSG_INJECT_TEXT_MAX_LENGTH] = '\0';
msg.inject_text.text = text;
@@ -250,40 +250,6 @@ static void test_serialize_set_clipboard(void) {
assert(!memcmp(buf, expected, sizeof(expected)));
}
static void test_serialize_set_clipboard_long(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_SET_CLIPBOARD,
.set_clipboard = {
.sequence = UINT64_C(0x0102030405060708),
.paste = true,
.text = NULL,
},
};
char text[CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH + 1];
memset(text, 'a', CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH);
text[CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH] = '\0';
msg.set_clipboard.text = text;
unsigned char buf[CONTROL_MSG_MAX_SIZE];
size_t size = control_msg_serialize(&msg, buf);
assert(size == CONTROL_MSG_MAX_SIZE);
unsigned char expected[CONTROL_MSG_MAX_SIZE] = {
CONTROL_MSG_TYPE_SET_CLIPBOARD,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // sequence
1, // paste
// text length
CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH >> 24,
(CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH >> 16) & 0xff,
(CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH >> 8) & 0xff,
CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH & 0xff,
};
memset(expected + 14, 'a', CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH);
assert(!memcmp(buf, expected, sizeof(expected)));
}
static void test_serialize_set_screen_power_mode(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
@@ -333,7 +299,6 @@ int main(int argc, char *argv[]) {
test_serialize_collapse_panels();
test_serialize_get_clipboard();
test_serialize_set_clipboard();
test_serialize_set_clipboard_long();
test_serialize_set_screen_power_mode();
test_serialize_rotate_device();
return 0;

View File

@@ -7,7 +7,6 @@ cpp = 'i686-w64-mingw32-g++'
ar = 'i686-w64-mingw32-ar'
strip = 'i686-w64-mingw32-strip'
pkgconfig = 'i686-w64-mingw32-pkg-config'
windres = 'i686-w64-mingw32-windres'
[host_machine]
system = 'windows'

View File

@@ -7,7 +7,6 @@ cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
strip = 'x86_64-w64-mingw32-strip'
pkgconfig = 'x86_64-w64-mingw32-pkg-config'
windres = 'x86_64-w64-mingw32-windres'
[host_machine]
system = 'windows'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -14,7 +14,8 @@ set -e
SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=1.21
PLATFORM=${ANDROID_PLATFORM:-31}
PLATFORM_VERSION=31
PLATFORM=${ANDROID_PLATFORM:-$PLATFORM_VERSION}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-31.0.0}
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
@@ -56,7 +57,7 @@ javac -bootclasspath "$ANDROID_JAR" -cp "$CLASSES_DIR" -d "$CLASSES_DIR" \
echo "Dexing..."
cd "$CLASSES_DIR"
if [[ $PLATFORM -lt 31 ]]
if [[ $PLATFORM_VERSION -lt 31 ]]
then
# use dx
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \

View File

@@ -30,13 +30,8 @@ public final class DesktopConnection implements Closeable {
private DesktopConnection(LocalSocket videoSocket, LocalSocket controlSocket) throws IOException {
this.videoSocket = videoSocket;
this.controlSocket = controlSocket;
if (controlSocket != null) {
controlInputStream = controlSocket.getInputStream();
controlOutputStream = controlSocket.getOutputStream();
} else {
controlInputStream = null;
controlOutputStream = null;
}
controlInputStream = controlSocket.getInputStream();
controlOutputStream = controlSocket.getOutputStream();
videoFd = videoSocket.getFileDescriptor();
}
@@ -46,35 +41,31 @@ public final class DesktopConnection implements Closeable {
return localSocket;
}
public static DesktopConnection open(Device device, boolean tunnelForward, boolean control) throws IOException {
public static DesktopConnection open(Device device, boolean tunnelForward) throws IOException {
LocalSocket videoSocket;
LocalSocket controlSocket = null;
LocalSocket controlSocket;
if (tunnelForward) {
LocalServerSocket localServerSocket = new LocalServerSocket(SOCKET_NAME);
try {
videoSocket = localServerSocket.accept();
// send one byte so the client may read() to detect a connection error
videoSocket.getOutputStream().write(0);
if (control) {
try {
controlSocket = localServerSocket.accept();
} catch (IOException | RuntimeException e) {
videoSocket.close();
throw e;
}
try {
controlSocket = localServerSocket.accept();
} catch (IOException | RuntimeException e) {
videoSocket.close();
throw e;
}
} finally {
localServerSocket.close();
}
} else {
videoSocket = connect(SOCKET_NAME);
if (control) {
try {
controlSocket = connect(SOCKET_NAME);
} catch (IOException | RuntimeException e) {
videoSocket.close();
throw e;
}
try {
controlSocket = connect(SOCKET_NAME);
} catch (IOException | RuntimeException e) {
videoSocket.close();
throw e;
}
}
@@ -88,11 +79,9 @@ public final class DesktopConnection implements Closeable {
videoSocket.shutdownInput();
videoSocket.shutdownOutput();
videoSocket.close();
if (controlSocket != null) {
controlSocket.shutdownInput();
controlSocket.shutdownOutput();
controlSocket.close();
}
controlSocket.shutdownInput();
controlSocket.shutdownOutput();
controlSocket.close();
}
private void send(String deviceName, int width, int height) throws IOException {

View File

@@ -66,15 +66,14 @@ public final class Server {
Thread initThread = startInitThread(options);
boolean tunnelForward = options.isTunnelForward();
boolean control = options.getControl();
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward, control)) {
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions,
options.getEncoderName());
Thread controllerThread = null;
Thread deviceMessageSenderThread = null;
if (control) {
if (options.getControl()) {
final Controller controller = new Controller(device, connection, options.getClipboardAutosync());
// asynchronous