Compare commits

..

1 Commits

Author SHA1 Message Date
cc6db6776c Document Windows command line usage 2020-12-20 08:18:32 +01:00
83 changed files with 381 additions and 450 deletions

View File

@ -254,10 +254,10 @@ You can then [run](README.md#run) _scrcpy_.
## Prebuilt server
- [`scrcpy-server-v1.17`][direct-scrcpy-server]
_(SHA-256: 11b5ad2d1bc9b9730fb7254a78efd71a8ff46b1938ff468e47a21b653a1b6725_
- [`scrcpy-server-v1.16`][direct-scrcpy-server]
_(SHA-256: 94a79e05b4498d0460ab7bd9d12cbf05156e3a47bf0c5d1420cee1d4493b3832)_
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.17/scrcpy-server-v1.17
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.16/scrcpy-server-v1.16
Download the prebuilt server somewhere, and specify its path during the Meson
configuration:

3
FAQ.md
View File

@ -233,7 +233,4 @@ scrcpy --prefer-text --turn-screen-off --stay-awake
Then just double-click on that file.
You could also edit (a copy of) `scrcpy-console.bat` or `scrcpy-noconsole.vbs`
to add some arguments.
[show file extensions]: https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/

View File

@ -188,7 +188,7 @@
identification within third-party archives.
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -9,20 +9,21 @@
# the server to the device.
.PHONY: default clean \
test \
build-server \
prepare-deps-win32 prepare-deps-win64 \
build-win32 build-win64 \
build-win32 build-win32-noconsole \
build-win64 build-win64-noconsole \
dist-win32 dist-win64 \
zip-win32 zip-win64 \
release
sums release
GRADLE ?= ./gradlew
TEST_BUILD_DIR := build-test
SERVER_BUILD_DIR := build-server
WIN32_BUILD_DIR := build-win32
WIN32_NOCONSOLE_BUILD_DIR := build-win32-noconsole
WIN64_BUILD_DIR := build-win64
WIN64_NOCONSOLE_BUILD_DIR := build-win64-noconsole
DIST := dist
WIN32_TARGET_DIR := scrcpy-win32
@ -32,35 +33,19 @@ VERSION := $(shell git describe --tags --always)
WIN32_TARGET := $(WIN32_TARGET_DIR)-$(VERSION).zip
WIN64_TARGET := $(WIN64_TARGET_DIR)-$(VERSION).zip
RELEASE_DIR := release-$(VERSION)
release: clean test build-server zip-win32 zip-win64
mkdir -p "$(RELEASE_DIR)"
cp "$(SERVER_BUILD_DIR)/server/scrcpy-server" \
"$(RELEASE_DIR)/scrcpy-server-$(VERSION)"
cp "$(DIST)/$(WIN32_TARGET)" "$(RELEASE_DIR)"
cp "$(DIST)/$(WIN64_TARGET)" "$(RELEASE_DIR)"
cd "$(RELEASE_DIR)" && \
sha256sum "scrcpy-server-$(VERSION)" \
"scrcpy-win32-$(VERSION).zip" \
"scrcpy-win64-$(VERSION).zip" > SHA256SUMS.txt
@echo "Release generated in $(RELEASE_DIR)/"
release: clean zip-win32 zip-win64 sums
@echo "Windows archives generated in $(DIST)/"
clean:
$(GRADLE) clean
rm -rf "$(DIST)" "$(TEST_BUILD_DIR)" "$(SERVER_BUILD_DIR)" \
"$(WIN32_BUILD_DIR)" "$(WIN64_BUILD_DIR)"
test:
[ -d "$(TEST_BUILD_DIR)" ] || ( mkdir "$(TEST_BUILD_DIR)" && \
meson "$(TEST_BUILD_DIR)" -Db_sanitize=address )
ninja -C "$(TEST_BUILD_DIR)"
$(GRADLE) -p server check
rm -rf "$(SERVER_BUILD_DIR)" "$(WIN32_BUILD_DIR)" "$(WIN64_BUILD_DIR)" \
"$(WIN32_NOCONSOLE_BUILD_DIR)" "$(WIN64_NOCONSOLE_BUILD_DIR)" "$(DIST)"
build-server:
[ -d "$(SERVER_BUILD_DIR)" ] || ( mkdir "$(SERVER_BUILD_DIR)" && \
meson "$(SERVER_BUILD_DIR)" --buildtype release -Dcompile_app=false )
ninja -C "$(SERVER_BUILD_DIR)"
meson "$(SERVER_BUILD_DIR)" \
--buildtype release -Dcompile_app=false )
ninja -C "$(SERVER_BUILD_DIR)"
prepare-deps-win32:
-$(MAKE) -C prebuilt-deps prepare-win32
@ -75,6 +60,17 @@ build-win32: prepare-deps-win32
-Dportable=true )
ninja -C "$(WIN32_BUILD_DIR)"
build-win32-noconsole: prepare-deps-win32
[ -d "$(WIN32_NOCONSOLE_BUILD_DIR)" ] || ( mkdir "$(WIN32_NOCONSOLE_BUILD_DIR)" && \
meson "$(WIN32_NOCONSOLE_BUILD_DIR)" \
--cross-file cross_win32.txt \
--buildtype release --strip -Db_lto=true \
-Dcrossbuild_windows=true \
-Dcompile_server=false \
-Dwindows_noconsole=true \
-Dportable=true )
ninja -C "$(WIN32_NOCONSOLE_BUILD_DIR)"
prepare-deps-win64:
-$(MAKE) -C prebuilt-deps prepare-win64
@ -88,12 +84,23 @@ build-win64: prepare-deps-win64
-Dportable=true )
ninja -C "$(WIN64_BUILD_DIR)"
dist-win32: build-server build-win32
build-win64-noconsole: prepare-deps-win64
[ -d "$(WIN64_NOCONSOLE_BUILD_DIR)" ] || ( mkdir "$(WIN64_NOCONSOLE_BUILD_DIR)" && \
meson "$(WIN64_NOCONSOLE_BUILD_DIR)" \
--cross-file cross_win64.txt \
--buildtype release --strip -Db_lto=true \
-Dcrossbuild_windows=true \
-Dcompile_server=false \
-Dwindows_noconsole=true \
-Dportable=true )
ninja -C "$(WIN64_NOCONSOLE_BUILD_DIR)"
dist-win32: build-server build-win32 build-win32-noconsole
mkdir -p "$(DIST)/$(WIN32_TARGET_DIR)"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/scrcpy-noconsole.exe"
cp data/scrcpy-console.bat "$(DIST)/$(WIN32_TARGET_DIR)"
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN32_TARGET_DIR)"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
@ -102,14 +109,14 @@ dist-win32: build-server build-win32
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/SDL2-2.0.14/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/SDL2-2.0.12/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
dist-win64: build-server build-win64
dist-win64: build-server build-win64 build-win64-noconsole
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/scrcpy-noconsole.exe"
cp data/scrcpy-console.bat "$(DIST)/$(WIN64_TARGET_DIR)"
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN64_TARGET_DIR)"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
@ -118,7 +125,7 @@ dist-win64: build-server build-win64
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/SDL2-2.0.14/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/SDL2-2.0.12/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
zip-win32: dist-win32
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \
@ -127,3 +134,7 @@ zip-win32: dist-win32
zip-win64: dist-win64
cd "$(DIST)/$(WIN64_TARGET_DIR)"; \
zip -r "../$(WIN64_TARGET)" .
sums:
cd "$(DIST)"; \
sha256sum *.zip > SHA256SUMS.txt

View File

@ -675,7 +675,7 @@ Baca [halaman pengembang].
## Lisensi
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -477,7 +477,7 @@ _²화면이 꺼진 상태에서 우클릭 시 다시 켜지며, 그 외의 상
## 라이선스
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# scrcpy (v1.17)
# scrcpy (v1.16)
[Read in another language](#translations)
@ -77,10 +77,10 @@ hard).
For Windows, for simplicity, a prebuilt archive with all the dependencies
(including `adb`) is available:
- [`scrcpy-win64-v1.17.zip`][direct-win64]
_(SHA-256: 8b9e57993c707367ed10ebfe0e1ef563c7a29d9af4a355cd8b6a52a317c73eea)_
- [`scrcpy-win64-v1.16.zip`][direct-win64]
_(SHA-256: 3f30dc5db1a2f95c2b40a0f5de91ec1642d9f53799250a8c529bc882bc0918f0)_
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.17/scrcpy-win64-v1.17.zip
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.16/scrcpy-win64-v1.16.zip
It is also available in [Chocolatey]:
@ -116,10 +116,6 @@ brew install scrcpy
You need `adb`, accessible from your `PATH`. If you don't have it yet:
```bash
# Homebrew >= 2.6.0
brew install --cask android-platform-tools
# Homebrew < 2.6.0
brew cask install android-platform-tools
```
@ -206,8 +202,6 @@ scrcpy --lock-video-orientation 3 # 90° clockwise
This affects recording orientation.
The [window may also be rotated](#rotation) independently.
#### Encoder
@ -413,9 +407,9 @@ Note that _scrcpy_ manages 3 different rotations:
- <kbd>MOD</kbd>+<kbd>r</kbd> requests the device to switch between portrait
and landscape (the current running app may refuse, if it does support the
requested orientation).
- [`--lock-video-orientation`](#lock-video-orientation) changes the mirroring
orientation (the orientation of the video sent from the device to the
computer). This affects the recording.
- `--lock-video-orientation` changes the mirroring orientation (the orientation
of the video sent from the device to the computer). This affects the
recording.
- `--rotation` (or <kbd>MOD</kbd>+<kbd>←</kbd>/<kbd>MOD</kbd>+<kbd>→</kbd>)
rotates only the window content. This affects only the display, not the
recording.
@ -772,7 +766,7 @@ Read the [developers page].
## Licence
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -508,7 +508,7 @@ Leia a [developers page].
## Licença
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -703,7 +703,7 @@ _³需要安卓版本 Android >= 7。_
## 许可协议
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -682,7 +682,7 @@ _³只支援 Android 7+。_
## Licence
Copyright (C) 2018 Genymobile
Copyright (C) 2018-2021 Romain Vimont
Copyright (C) 2018-2020 Romain Vimont
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,7 +1,7 @@
src = [
'src/main.c',
'src/adb.c',
'src/cli.c',
'src/command.c',
'src/control_msg.c',
'src/controller.c',
'src/decoder.c',
@ -21,16 +21,9 @@ src = [
'src/tiny_xpm.c',
'src/video_buffer.c',
'src/util/net.c',
'src/util/process.c',
'src/util/str_util.c'
]
if host_machine.system() == 'windows'
src += [ 'src/sys/win/process.c' ]
else
src += [ 'src/sys/unix/process.c' ]
endif
if not get_option('crossbuild_windows')
# native build
@ -83,7 +76,10 @@ endif
cc = meson.get_compiler('c')
if host_machine.system() == 'windows'
src += [ 'src/sys/win/command.c' ]
dependencies += cc.find_library('ws2_32')
else
src += [ 'src/sys/unix/command.c' ]
endif
conf = configuration_data()
@ -123,6 +119,9 @@ conf.set('DEFAULT_BIT_RATE', '8000000') # 8Mbps
# enable High DPI support
conf.set('HIDPI_SUPPORT', get_option('hidpi_support'))
# disable console on Windows
conf.set('WINDOWS_NOCONSOLE', get_option('windows_noconsole'))
# run a server debugger and wait for a client to be attached
conf.set('SERVER_DEBUGGER', get_option('server_debugger'))
@ -133,11 +132,18 @@ configure_file(configuration: conf, output: 'config.h')
src_dir = include_directories('src')
if get_option('windows_noconsole')
link_args = [ '-Wl,--subsystem,windows' ]
else
link_args = []
endif
executable('scrcpy', src,
dependencies: dependencies,
include_directories: src_dir,
install: true,
c_args: [])
c_args: [],
link_args: link_args)
install_man('scrcpy.1')

View File

@ -1,34 +0,0 @@
#ifndef SC_ADB_H
#define SC_ADB_H
#include "common.h"
#include <stdbool.h>
#include <inttypes.h>
#include "util/process.h"
process_t
adb_execute(const char *serial, const char *const adb_cmd[], size_t 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);
#endif

View File

@ -6,6 +6,7 @@
#include <stdio.h>
#include <unistd.h>
#include "config.h"
#include "scrcpy.h"
#include "util/log.h"
#include "util/str_util.h"
@ -477,14 +478,14 @@ parse_port_range(const char *s, struct sc_port_range *port_range) {
}
static bool
parse_display_id(const char *s, uint32_t *display_id) {
parse_display_id(const char *s, uint16_t *display_id) {
long value;
bool ok = parse_integer_arg(s, &value, false, 0, 0x7FFFFFFF, "display id");
bool ok = parse_integer_arg(s, &value, false, 0, 0xFFFF, "display id");
if (!ok) {
return false;
}
*display_id = (uint32_t) value;
*display_id = (uint16_t) value;
return true;
}

View File

@ -1,10 +1,9 @@
#ifndef SCRCPY_CLI_H
#define SCRCPY_CLI_H
#include "common.h"
#include <stdbool.h>
#include "config.h"
#include "scrcpy.h"
struct scrcpy_cli_args {

View File

@ -1,10 +1,12 @@
#include "adb.h"
#include "command.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "common.h"
#include "util/log.h"
#include "util/str_util.h"
@ -68,7 +70,7 @@ show_adb_installation_msg() {
{"pacman", "pacman -S android-tools"},
};
for (size_t i = 0; i < ARRAY_LEN(pkg_managers); ++i) {
if (search_executable(pkg_managers[i].binary)) {
if (cmd_search(pkg_managers[i].binary)) {
LOGI("You may install 'adb' by \"%s\"", pkg_managers[i].command);
return;
}
@ -116,7 +118,7 @@ adb_execute(const char *serial, const char *const adb_cmd[], size_t len) {
memcpy(&cmd[i], adb_cmd, len * sizeof(const char *));
cmd[len + i] = NULL;
enum process_result r = process_execute(cmd, &process);
enum process_result r = cmd_execute(cmd, &process);
if (r != PROCESS_SUCCESS) {
show_adb_err_msg(r, cmd);
return PROCESS_NONE;
@ -209,3 +211,21 @@ adb_install(const char *serial, const char *local) {
return proc;
}
bool
process_check_success(process_t proc, const char *name) {
if (proc == PROCESS_NONE) {
LOGE("Could not execute \"%s\"", name);
return false;
}
exit_code_t exit_code;
if (!cmd_simple_wait(proc, &exit_code)) {
if (exit_code != NO_EXIT_CODE) {
LOGE("\"%s\" returned with value %" PRIexitcode, name, exit_code);
} else {
LOGE("\"%s\" exited unexpectedly", name);
}
return false;
}
return true;
}

View File

@ -1,9 +1,8 @@
#ifndef SC_PROCESS_H
#define SC_PROCESS_H
#include "common.h"
#ifndef COMMAND_H
#define COMMAND_H
#include <stdbool.h>
#include <inttypes.h>
#ifdef _WIN32
@ -32,45 +31,56 @@
#endif
#include "config.h"
enum process_result {
PROCESS_SUCCESS,
PROCESS_ERROR_GENERIC,
PROCESS_ERROR_MISSING_BINARY,
};
// execute the command and write the result to the output parameter "process"
#ifndef __WINDOWS__
bool
cmd_search(const char *file);
#endif
enum process_result
process_execute(const char *const argv[], process_t *process);
cmd_execute(const char *const argv[], process_t *process);
// kill the process
bool
process_terminate(process_t pid);
cmd_terminate(process_t pid);
// wait and close the process (like waitpid())
bool
process_wait(process_t pid, exit_code_t *exit_code);
cmd_simple_wait(process_t pid, exit_code_t *exit_code);
// wait (but does not close) the process (waitid() with WNOWAIT)
bool
process_wait_noclose(process_t pid, exit_code_t *exit_code);
process_t
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
// close the process
//
// Semantically, process_wait = process_wait_noclose + process_close.
void
process_close(process_t pid);
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
// automatically log process errors with the provided process name
bool
process_check_success(process_t proc, const char *name);
#ifndef _WIN32
// only used to find package manager, not implemented for Windows
bool
search_executable(const char *file);
#endif
// return the absolute path of the executable (the scrcpy binary)
// may be NULL on error; to be freed by SDL_free
char *

View File

@ -1,11 +1,35 @@
#ifndef COMMON_H
#define COMMON_H
#include <stdint.h>
#include "config.h"
#include "compat.h"
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
#define MIN(X,Y) (X) < (Y) ? (X) : (Y)
#define MAX(X,Y) (X) > (Y) ? (X) : (Y)
struct size {
uint16_t width;
uint16_t height;
};
struct point {
int32_t x;
int32_t y;
};
struct position {
// 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.
struct size screen_size;
struct point point;
};
struct port_range {
uint16_t first;
uint16_t last;
};
#endif

View File

@ -1,14 +1,6 @@
#ifndef COMPAT_H
#define COMPAT_H
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700
#define _GNU_SOURCE
#ifdef __APPLE__
# define _DARWIN_C_SOURCE
#endif
#include <libavcodec/version.h>
#include <libavformat/version.h>
#include <SDL2/SDL_version.h>

View File

@ -3,6 +3,7 @@
#include <assert.h>
#include <string.h>
#include "config.h"
#include "util/buffer_util.h"
#include "util/log.h"
#include "util/str_util.h"

View File

@ -1,15 +1,14 @@
#ifndef CONTROLMSG_H
#define CONTROLMSG_H
#include "common.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "config.h"
#include "android/input.h"
#include "android/keycodes.h"
#include "coords.h"
#include "common.h"
#define CONTROL_MSG_MAX_SIZE (1 << 18) // 256k

View File

@ -2,6 +2,7 @@
#include <assert.h>
#include "config.h"
#include "util/lock.h"
#include "util/log.h"

View File

@ -1,12 +1,11 @@
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_thread.h>
#include "config.h"
#include "control_msg.h"
#include "receiver.h"
#include "util/cbuf.h"

View File

@ -1,24 +0,0 @@
#ifndef SC_COORDS
#define SC_COORDS
#include <stdint.h>
struct size {
uint16_t width;
uint16_t height;
};
struct point {
int32_t x;
int32_t y;
};
struct position {
// 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.
struct size screen_size;
struct point point;
};
#endif

View File

@ -7,6 +7,8 @@
#include <SDL2/SDL_thread.h>
#include <unistd.h>
#include "config.h"
#include "compat.h"
#include "events.h"
#include "recorder.h"
#include "video_buffer.h"

View File

@ -1,11 +1,11 @@
#ifndef DECODER_H
#define DECODER_H
#include "common.h"
#include <stdbool.h>
#include <libavformat/avformat.h>
#include "config.h"
struct video_buffer;
struct decoder {

View File

@ -1,5 +1,6 @@
#include "device.h"
#include "config.h"
#include "util/log.h"
bool

View File

@ -1,11 +1,10 @@
#ifndef DEVICE_H
#define DEVICE_H
#include "common.h"
#include <stdbool.h>
#include "coords.h"
#include "config.h"
#include "common.h"
#include "util/net.h"
#define DEVICE_NAME_FIELD_LENGTH 64

View File

@ -2,6 +2,7 @@
#include <string.h>
#include "config.h"
#include "util/buffer_util.h"
#include "util/log.h"

View File

@ -1,12 +1,12 @@
#ifndef DEVICEMSG_H
#define DEVICEMSG_H
#include "common.h"
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include "config.h"
#define DEVICE_MSG_MAX_SIZE (1 << 18) // 256k
// type: 1 byte; length: 4 bytes
#define DEVICE_MSG_TEXT_MAX_LENGTH (DEVICE_MSG_MAX_SIZE - 5)

View File

@ -1,5 +1,7 @@
#include "event_converter.h"
#include "config.h"
#define MAP(FROM, TO) case FROM: *to = TO; return true
#define FAIL default: return false

View File

@ -1,11 +1,10 @@
#ifndef CONVERT_H
#define CONVERT_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL_events.h>
#include "config.h"
#include "control_msg.h"
bool

View File

@ -3,7 +3,8 @@
#include <assert.h>
#include <string.h>
#include "adb.h"
#include "config.h"
#include "command.h"
#include "util/lock.h"
#include "util/log.h"
@ -175,10 +176,10 @@ file_handler_stop(struct file_handler *file_handler) {
file_handler->stopped = true;
cond_signal(file_handler->event_cond);
if (file_handler->current_process != PROCESS_NONE) {
if (!process_terminate(file_handler->current_process)) {
if (!cmd_terminate(file_handler->current_process)) {
LOGW("Could not terminate install process");
}
process_wait(file_handler->current_process, NULL);
cmd_simple_wait(file_handler->current_process, NULL);
file_handler->current_process = PROCESS_NONE;
}
mutex_unlock(file_handler->mutex);

View File

@ -1,13 +1,12 @@
#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_thread.h>
#include "adb.h"
#include "config.h"
#include "command.h"
#include "util/cbuf.h"
typedef enum {

View File

@ -3,6 +3,7 @@
#include <assert.h>
#include <SDL2/SDL_timer.h>
#include "config.h"
#include "util/lock.h"
#include "util/log.h"

View File

@ -1,14 +1,14 @@
#ifndef FPSCOUNTER_H
#define FPSCOUNTER_H
#include "common.h"
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_thread.h>
#include "config.h"
struct fps_counter {
SDL_Thread *thread;
SDL_mutex *mutex;

View File

@ -3,6 +3,7 @@
#include <assert.h>
#include <SDL2/SDL_keycode.h>
#include "config.h"
#include "event_converter.h"
#include "util/lock.h"
#include "util/log.h"

View File

@ -1,12 +1,12 @@
#ifndef INPUTMANAGER_H
#define INPUTMANAGER_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL.h>
#include "config.h"
#include "common.h"
#include "controller.h"
#include "fps_counter.h"
#include "scrcpy.h"

View File

@ -1,7 +1,5 @@
#include "scrcpy.h"
#include "common.h"
#include <assert.h>
#include <stdbool.h>
#include <unistd.h>
@ -9,7 +7,9 @@
#define SDL_MAIN_HANDLED // avoid link error on Linux Windows Subsystem
#include <SDL2/SDL.h>
#include "config.h"
#include "cli.h"
#include "compat.h"
#include "util/log.h"
static void

View File

@ -1,11 +1,11 @@
#ifndef SC_OPENGL_H
#define SC_OPENGL_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL_opengl.h>
#include "config.h"
struct sc_opengl {
const char *version;
bool is_opengles;

View File

@ -3,6 +3,7 @@
#include <assert.h>
#include <SDL2/SDL_clipboard.h>
#include "config.h"
#include "device_msg.h"
#include "util/lock.h"
#include "util/log.h"

View File

@ -1,12 +1,11 @@
#ifndef RECEIVER_H
#define RECEIVER_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_thread.h>
#include "config.h"
#include "util/net.h"
// receive events from the device

View File

@ -3,6 +3,8 @@
#include <assert.h>
#include <libavutil/time.h>
#include "config.h"
#include "compat.h"
#include "util/lock.h"
#include "util/log.h"

View File

@ -1,14 +1,13 @@
#ifndef RECORDER_H
#define RECORDER_H
#include "common.h"
#include <stdbool.h>
#include <libavformat/avformat.h>
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_thread.h>
#include "coords.h"
#include "config.h"
#include "common.h"
#include "scrcpy.h"
#include "util/queue.h"

View File

@ -13,6 +13,10 @@
# include <windows.h>
#endif
#include "config.h"
#include "command.h"
#include "common.h"
#include "compat.h"
#include "controller.h"
#include "decoder.h"
#include "device.h"
@ -30,7 +34,7 @@
#include "util/log.h"
#include "util/net.h"
static struct server server;
static struct server server = SERVER_INITIALIZER;
static struct screen screen = SCREEN_INITIALIZER;
static struct fps_counter fps_counter;
static struct video_buffer video_buffer;
@ -300,21 +304,6 @@ av_log_callback(void *avcl, int level, const char *fmt, va_list vl) {
bool
scrcpy(const struct scrcpy_options *options) {
if (!server_init(&server)) {
return false;
}
bool ret = false;
bool server_started = false;
bool fps_counter_initialized = false;
bool video_buffer_initialized = false;
bool file_handler_initialized = false;
bool recorder_initialized = false;
bool stream_started = false;
bool controller_initialized = false;
bool controller_started = false;
bool record = !!options->record_filename;
struct server_params params = {
.log_level = options->log_level,
@ -333,10 +322,18 @@ scrcpy(const struct scrcpy_options *options) {
.force_adb_forward = options->force_adb_forward,
};
if (!server_start(&server, options->serial, &params)) {
goto end;
return false;
}
server_started = true;
bool ret = false;
bool fps_counter_initialized = false;
bool video_buffer_initialized = false;
bool file_handler_initialized = false;
bool recorder_initialized = false;
bool stream_started = false;
bool controller_initialized = false;
bool controller_started = false;
if (!sdl_init_and_configure(options->display, options->render_driver,
options->disable_screensaver)) {
@ -468,10 +465,8 @@ end:
fps_counter_interrupt(&fps_counter);
}
if (server_started) {
// shutdown the sockets and kill the server
server_stop(&server);
}
// shutdown the sockets and kill the server
server_stop(&server);
// now that the sockets are shutdown, the stream and controller are
// interrupted, we can join them

View File

@ -1,12 +1,12 @@
#ifndef SCRCPY_H
#define SCRCPY_H
#include "common.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "config.h"
enum sc_log_level {
SC_LOG_LEVEL_DEBUG,
SC_LOG_LEVEL_INFO,
@ -65,7 +65,7 @@ struct scrcpy_options {
int16_t window_y; // SC_WINDOW_POSITION_UNDEFINED for "auto"
uint16_t window_width;
uint16_t window_height;
uint32_t display_id;
uint16_t display_id;
bool show_touches;
bool fullscreen;
bool always_on_top;

View File

@ -4,6 +4,9 @@
#include <string.h>
#include <SDL2/SDL.h>
#include "config.h"
#include "common.h"
#include "compat.h"
#include "icon.xpm"
#include "scrcpy.h"
#include "tiny_xpm.h"

View File

@ -1,13 +1,12 @@
#ifndef SCREEN_H
#define SCREEN_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <libavformat/avformat.h>
#include "coords.h"
#include "config.h"
#include "common.h"
#include "opengl.h"
struct video_buffer;

View File

@ -9,8 +9,8 @@
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_platform.h>
#include "adb.h"
#include "util/lock.h"
#include "config.h"
#include "command.h"
#include "util/log.h"
#include "util/net.h"
#include "util/str_util.h"
@ -257,12 +257,12 @@ execute_server(struct server *server, const struct server_params *params) {
char bit_rate_string[11];
char max_fps_string[6];
char lock_video_orientation_string[5];
char display_id_string[11];
char display_id_string[6];
sprintf(max_size_string, "%"PRIu16, params->max_size);
sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
sprintf(max_fps_string, "%"PRIu16, params->max_fps);
sprintf(lock_video_orientation_string, "%"PRIi8, params->lock_video_orientation);
sprintf(display_id_string, "%"PRIu32, params->display_id);
sprintf(display_id_string, "%"PRIu16, params->display_id);
const char *const cmd[] = {
"shell",
"CLASSPATH=" DEVICE_SERVER_PATH,
@ -353,51 +353,15 @@ close_socket(socket_t socket) {
}
}
bool
void
server_init(struct server *server) {
server->serial = NULL;
server->process = PROCESS_NONE;
server->wait_server_thread = NULL;
atomic_flag_clear_explicit(&server->server_socket_closed,
memory_order_relaxed);
server->mutex = SDL_CreateMutex();
if (!server->mutex) {
return false;
}
server->process_terminated_cond = SDL_CreateCond();
if (!server->process_terminated_cond) {
SDL_DestroyMutex(server->mutex);
return false;
}
server->process_terminated = false;
server->server_socket = INVALID_SOCKET;
server->video_socket = INVALID_SOCKET;
server->control_socket = INVALID_SOCKET;
server->port_range.first = 0;
server->port_range.last = 0;
server->local_port = 0;
server->tunnel_enabled = false;
server->tunnel_forward = false;
return true;
*server = (struct server) SERVER_INITIALIZER;
}
static int
run_wait_server(void *data) {
struct server *server = data;
process_wait_noclose(server->process, NULL); // ignore exit code
mutex_lock(server->mutex);
server->process_terminated = true;
cond_signal(server->process_terminated_cond);
mutex_unlock(server->mutex);
cmd_simple_wait(server->process, NULL); // ignore exit code
// no need for synchronization, server_socket is initialized before this
// thread was created
if (server->server_socket != INVALID_SOCKET
@ -446,8 +410,8 @@ server_start(struct server *server, const char *serial,
server->wait_server_thread =
SDL_CreateThread(run_wait_server, "wait-server", server);
if (!server->wait_server_thread) {
process_terminate(server->process);
process_wait(server->process, NULL); // ignore exit code
cmd_terminate(server->process);
cmd_simple_wait(server->process, NULL); // ignore exit code
goto error2;
}
@ -529,39 +493,17 @@ server_stop(struct server *server) {
assert(server->process != PROCESS_NONE);
cmd_terminate(server->process);
if (server->tunnel_enabled) {
// ignore failure
disable_tunnel(server);
}
// Give some delay for the server to terminate properly
mutex_lock(server->mutex);
int r = 0;
if (!server->process_terminated) {
#define WATCHDOG_DELAY_MS 1000
r = cond_wait_timeout(server->process_terminated_cond,
server->mutex,
WATCHDOG_DELAY_MS);
}
mutex_unlock(server->mutex);
// After this delay, kill the server if it's not dead already.
// On some devices, closing the sockets is not sufficient to wake up the
// blocking calls while the device is asleep.
if (r == SDL_MUTEX_TIMEDOUT) {
// The process is terminated, but not reaped (closed) yet, so its PID
// is still valid.
LOGW("Killing the server...");
process_terminate(server->process);
}
SDL_WaitThread(server->wait_server_thread, NULL);
process_close(server->process);
}
void
server_destroy(struct server *server) {
SDL_free(server->serial);
SDL_DestroyCond(server->process_terminated_cond);
SDL_DestroyMutex(server->mutex);
}

View File

@ -1,14 +1,14 @@
#ifndef SERVER_H
#define SERVER_H
#include "common.h"
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <SDL2/SDL_thread.h>
#include "adb.h"
#include "config.h"
#include "command.h"
#include "common.h"
#include "scrcpy.h"
#include "util/log.h"
#include "util/net.h"
@ -18,11 +18,6 @@ struct server {
process_t process;
SDL_Thread *wait_server_thread;
atomic_flag server_socket_closed;
SDL_mutex *mutex;
SDL_cond *process_terminated_cond;
bool process_terminated;
socket_t server_socket; // only used if !tunnel_forward
socket_t video_socket;
socket_t control_socket;
@ -32,6 +27,23 @@ struct server {
bool tunnel_forward; // use "adb forward" instead of "adb reverse"
};
#define SERVER_INITIALIZER { \
.serial = NULL, \
.process = PROCESS_NONE, \
.wait_server_thread = NULL, \
.server_socket_closed = ATOMIC_FLAG_INIT, \
.server_socket = INVALID_SOCKET, \
.video_socket = INVALID_SOCKET, \
.control_socket = INVALID_SOCKET, \
.port_range = { \
.first = 0, \
.last = 0, \
}, \
.local_port = 0, \
.tunnel_enabled = false, \
.tunnel_forward = false, \
}
struct server_params {
enum sc_log_level log_level;
const char *crop;
@ -43,14 +55,14 @@ struct server_params {
uint16_t max_fps;
int8_t lock_video_orientation;
bool control;
uint32_t display_id;
uint16_t display_id;
bool show_touches;
bool stay_awake;
bool force_adb_forward;
};
// init default values
bool
void
server_init(struct server *server);
// push, enable tunnel et start the server

View File

@ -8,6 +8,8 @@
#include <SDL2/SDL_thread.h>
#include <unistd.h>
#include "config.h"
#include "compat.h"
#include "decoder.h"
#include "events.h"
#include "recorder.h"

View File

@ -1,14 +1,13 @@
#ifndef STREAM_H
#define STREAM_H
#include "common.h"
#include <stdbool.h>
#include <stdint.h>
#include <libavformat/avformat.h>
#include <SDL2/SDL_atomic.h>
#include <SDL2/SDL_thread.h>
#include "config.h"
#include "util/net.h"
struct video_buffer;

View File

@ -1,4 +1,17 @@
#include "util/process.h"
// for portability (kill, readlink, strdup, strtok_r)
#define _POSIX_C_SOURCE 200809L
#define _BSD_SOURCE
// modern glibc will complain without this
#define _DEFAULT_SOURCE
#ifdef __APPLE__
# define _DARWIN_C_SOURCE // for strdup(), strtok_r(), memset_pattern4()
#endif
#include "command.h"
#include "config.h"
#include <errno.h>
#include <fcntl.h>
@ -8,13 +21,14 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "util/log.h"
bool
search_executable(const char *file) {
cmd_search(const char *file) {
char *path = getenv("PATH");
if (!path)
return false;
@ -50,7 +64,7 @@ search_executable(const char *file) {
}
enum process_result
process_execute(const char *const argv[], pid_t *pid) {
cmd_execute(const char *const argv[], pid_t *pid) {
int fd[2];
if (pipe(fd) == -1) {
@ -112,7 +126,7 @@ end:
}
bool
process_terminate(pid_t pid) {
cmd_terminate(pid_t pid) {
if (pid <= 0) {
LOGC("Requested to kill %d, this is an error. Please report the bug.\n",
(int) pid);
@ -121,21 +135,15 @@ process_terminate(pid_t pid) {
return kill(pid, SIGTERM) != -1;
}
static bool
process_wait_internal(pid_t pid, int *exit_code, bool close) {
bool
cmd_simple_wait(pid_t pid, int *exit_code) {
int status;
int code;
int options = WEXITED;
if (!close) {
options |= WNOWAIT;
}
siginfo_t info;
int r = waitid(P_PID, pid, &info, options);
if (r == -1 || info.si_code != CLD_EXITED) {
if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) {
// could not wait, or exited unexpectedly, probably by a signal
code = -1;
} else {
code = info.si_status;
code = WEXITSTATUS(status);
}
if (exit_code) {
*exit_code = code;
@ -143,21 +151,6 @@ process_wait_internal(pid_t pid, int *exit_code, bool close) {
return !code;
}
bool
process_wait(pid_t pid, int *exit_code) {
return process_wait_internal(pid, exit_code, true);
}
bool
process_wait_noclose(pid_t pid, int *exit_code) {
return process_wait_internal(pid, exit_code, false);
}
void
process_close(pid_t pid) {
process_wait_internal(pid, NULL, true);
}
char *
get_executable_path(void) {
// <https://stackoverflow.com/a/1024937/1987178>

View File

@ -1,8 +1,8 @@
#include "util/process.h"
#include "command.h"
#include <assert.h>
#include <sys/stat.h>
#include "config.h"
#include "util/log.h"
#include "util/str_util.h"
@ -21,7 +21,7 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
}
enum process_result
process_execute(const char *const argv[], HANDLE *handle) {
cmd_execute(const char *const argv[], HANDLE *handle) {
STARTUPINFOW si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
@ -39,7 +39,12 @@ process_execute(const char *const argv[], HANDLE *handle) {
return PROCESS_ERROR_GENERIC;
}
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, 0, NULL, NULL, &si,
#ifdef WINDOWS_NOCONSOLE
int flags = CREATE_NO_WINDOW;
#else
int flags = 0;
#endif
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si,
&pi)) {
SDL_free(wide);
*handle = NULL;
@ -55,12 +60,12 @@ process_execute(const char *const argv[], HANDLE *handle) {
}
bool
process_terminate(HANDLE handle) {
return TerminateProcess(handle, 1);
cmd_terminate(HANDLE handle) {
return TerminateProcess(handle, 1) && CloseHandle(handle);
}
static bool
process_wait_internal(HANDLE handle, DWORD *exit_code, bool close) {
bool
cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
DWORD code;
if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
|| !GetExitCodeProcess(handle, &code)) {
@ -70,29 +75,9 @@ process_wait_internal(HANDLE handle, DWORD *exit_code, bool close) {
if (exit_code) {
*exit_code = code;
}
if (close) {
CloseHandle(handle);
}
return !code;
}
bool
process_wait(HANDLE handle, DWORD *exit_code) {
return process_wait_internal(handle, exit_code, true);
}
bool
process_wait_noclose(HANDLE handle, DWORD *exit_code) {
return process_wait_internal(handle, exit_code, false);
}
void
process_close(HANDLE handle) {
bool closed = CloseHandle(handle);
assert(closed);
(void) closed;
}
char *
get_executable_path(void) {
HMODULE hModule = GetModuleHandleW(NULL);

View File

@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util/log.h"
struct index {

View File

@ -1,10 +1,10 @@
#ifndef TINYXPM_H
#define TINYXPM_H
#include "common.h"
#include <SDL2/SDL.h>
#include "config.h"
SDL_Surface *
read_xpm(char *xpm[]);

View File

@ -1,11 +1,11 @@
#ifndef BUFFER_UTIL_H
#define BUFFER_UTIL_H
#include "common.h"
#include <stdbool.h>
#include <stdint.h>
#include "config.h"
static inline void
buffer_write16be(uint8_t *buf, uint16_t value) {
buf[0] = value >> 8;

View File

@ -2,11 +2,11 @@
#ifndef CBUF_H
#define CBUF_H
#include "common.h"
#include <stdbool.h>
#include <unistd.h>
#include "config.h"
// To define a circular buffer type of 20 ints:
// struct cbuf_int CBUF(int, 20);
//

View File

@ -1,11 +1,10 @@
#ifndef LOCK_H
#define LOCK_H
#include "common.h"
#include <stdint.h>
#include <SDL2/SDL_mutex.h>
#include "config.h"
#include "log.h"
static inline void

View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include <SDL2/SDL_platform.h>
#include "config.h"
#include "log.h"
#ifdef __WINDOWS__

View File

@ -1,8 +1,6 @@
#ifndef NET_H
#define NET_H
#include "common.h"
#include <stdbool.h>
#include <stdint.h>
#include <SDL2/SDL_platform.h>
@ -19,6 +17,8 @@
typedef int socket_t;
#endif
#include "config.h"
bool
net_init(void);

View File

@ -1,21 +0,0 @@
#include "process.h"
#include "log.h"
bool
process_check_success(process_t proc, const char *name) {
if (proc == PROCESS_NONE) {
LOGE("Could not execute \"%s\"", name);
return false;
}
exit_code_t exit_code;
if (!process_wait(proc, &exit_code)) {
if (exit_code != NO_EXIT_CODE) {
LOGE("\"%s\" returned with value %" PRIexitcode, name, exit_code);
} else {
LOGE("\"%s\" exited unexpectedly", name);
}
return false;
}
return true;
}

View File

@ -2,12 +2,12 @@
#ifndef QUEUE_H
#define QUEUE_H
#include "common.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include "config.h"
// To define a queue type of "struct foo":
// struct queue_foo QUEUE(struct foo);
#define QUEUE(TYPE) { \

View File

@ -12,6 +12,8 @@
#include <SDL2/SDL_stdinc.h>
#include "config.h"
size_t
xstrncpy(char *dest, const char *src, size_t n) {
size_t i;

View File

@ -1,11 +1,11 @@
#ifndef STRUTIL_H
#define STRUTIL_H
#include "common.h"
#include <stdbool.h>
#include <stddef.h>
#include "config.h"
// like strncpy, except:
// - it copies at most n-1 chars
// - the dest string is nul-terminated

View File

@ -5,6 +5,7 @@
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>
#include "config.h"
#include "util/lock.h"
#include "util/log.h"

View File

@ -1,11 +1,10 @@
#ifndef VIDEO_BUFFER_H
#define VIDEO_BUFFER_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL_mutex.h>
#include "config.h"
#include "fps_counter.h"
// forward declarations

View File

@ -1,5 +1,3 @@
#include "common.h"
#include <assert.h>
#include "util/buffer_util.h"

View File

@ -1,5 +1,3 @@
#include "common.h"
#include <assert.h>
#include <string.h>

View File

@ -1,9 +1,8 @@
#include "common.h"
#include <assert.h>
#include <string.h>
#include "cli.h"
#include "common.h"
#include "scrcpy.h"
static void test_flag_version(void) {

View File

@ -1,5 +1,3 @@
#include "common.h"
#include <assert.h>
#include <string.h>

View File

@ -1,5 +1,3 @@
#include "common.h"
#include <assert.h>
#include <string.h>

View File

@ -1,5 +1,3 @@
#include "common.h"
#include <assert.h>
#include "util/queue.h"

View File

@ -1,5 +1,3 @@
#include "common.h"
#include <assert.h>
#include <limits.h>
#include <stdio.h>

View File

@ -17,4 +17,4 @@ endian = 'little'
[properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win32-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win32-dev'
prebuilt_sdl2 = 'SDL2-2.0.14/i686-w64-mingw32'
prebuilt_sdl2 = 'SDL2-2.0.12/i686-w64-mingw32'

View File

@ -17,4 +17,4 @@ endian = 'little'
[properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win64-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win64-dev'
prebuilt_sdl2 = 'SDL2-2.0.14/x86_64-w64-mingw32'
prebuilt_sdl2 = 'SDL2-2.0.12/x86_64-w64-mingw32'

View File

@ -1 +0,0 @@
CreateObject("Wscript.Shell").Run "cmd /c scrcpy.exe", 0, false

View File

@ -1,5 +1,5 @@
project('scrcpy', 'c',
version: '1.17',
version: '1.16',
meson_version: '>= 0.48',
default_options: [
'c_std=c11',

View File

@ -1,6 +1,7 @@
option('compile_app', type: 'boolean', value: true, description: 'Build the client')
option('compile_server', type: 'boolean', value: true, description: 'Build the server')
option('crossbuild_windows', type: 'boolean', value: false, description: 'Build for Windows from Linux')
option('windows_noconsole', type: 'boolean', value: false, description: 'Disable console on Windows (pass -mwindows flag)')
option('prebuilt_server', type: 'string', description: 'Path of the prebuilt server')
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server from the same directory as the scrcpy executable')
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')

View File

@ -30,9 +30,9 @@ prepare-ffmpeg-dev-win64:
ffmpeg-4.3.1-win64-dev
prepare-sdl2:
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.14-mingw.tar.gz \
405eaff3eb18f2e08fe669ef9e63bc9a8710b7d343756f238619761e9b60407d \
SDL2-2.0.14
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.12-mingw.tar.gz \
e614a60f797e35ef9f3f96aef3dc6a1d786de3cc7ca6216f97e435c0b6aafc46 \
SDL2-2.0.12
prepare-adb:
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r30.0.5-windows.zip \

View File

@ -1,2 +1,44 @@
#!/bin/bash
make -f release.mk
set -e
# test locally
TESTDIR=build_test
rm -rf "$TESTDIR"
# run client tests with ASAN enabled
meson "$TESTDIR" -Db_sanitize=address
ninja -C"$TESTDIR" test
# test server
GRADLE=${GRADLE:-./gradlew}
$GRADLE -p server check
BUILDDIR=build_release
rm -rf "$BUILDDIR"
meson "$BUILDDIR" --buildtype release --strip -Db_lto=true
cd "$BUILDDIR"
ninja
cd -
# build Windows releases
make -f Makefile.CrossWindows
# the generated server must be the same everywhere
cmp "$BUILDDIR/server/scrcpy-server" dist/scrcpy-win32/scrcpy-server
cmp "$BUILDDIR/server/scrcpy-server" dist/scrcpy-win64/scrcpy-server
# get version name
TAG=$(git describe --tags --always)
# create release directory
mkdir -p "release-$TAG"
cp "$BUILDDIR/server/scrcpy-server" "release-$TAG/scrcpy-server-$TAG"
cp "dist/scrcpy-win32-$TAG.zip" "release-$TAG/"
cp "dist/scrcpy-win64-$TAG.zip" "release-$TAG/"
# generate checksums
cd "release-$TAG"
sha256sum "scrcpy-server-$TAG" \
"scrcpy-win32-$TAG.zip" \
"scrcpy-win64-$TAG.zip" > SHA256SUMS.txt
echo "Release generated in release-$TAG/"

View File

@ -6,8 +6,8 @@ android {
applicationId "com.genymobile.scrcpy"
minSdkVersion 21
targetSdkVersion 30
versionCode 20
versionName "1.17"
versionCode 19
versionName "1.16"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {

View File

@ -12,7 +12,7 @@
set -e
SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=1.17
SCRCPY_VERSION_NAME=1.16
PLATFORM=${ANDROID_PLATFORM:-30}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-30.0.0}

View File

@ -58,14 +58,12 @@ public final class Server {
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions,
options.getEncoderName());
Thread controllerThread = null;
Thread deviceMessageSenderThread = null;
if (options.getControl()) {
final Controller controller = new Controller(device, connection);
// asynchronous
controllerThread = startController(controller);
deviceMessageSenderThread = startDeviceMessageSender(controller.getSender());
startController(controller);
startDeviceMessageSender(controller.getSender());
device.setClipboardListener(new Device.ClipboardListener() {
@Override
@ -81,19 +79,12 @@ public final class Server {
} catch (IOException e) {
// this is expected on close
Ln.d("Screen streaming stopped");
} finally {
if (controllerThread != null) {
controllerThread.interrupt();
}
if (deviceMessageSenderThread != null) {
deviceMessageSenderThread.interrupt();
}
}
}
}
private static Thread startController(final Controller controller) {
Thread thread = new Thread(new Runnable() {
private static void startController(final Controller controller) {
new Thread(new Runnable() {
@Override
public void run() {
try {
@ -103,13 +94,11 @@ public final class Server {
Ln.d("Controller stopped");
}
}
});
thread.start();
return thread;
}).start();
}
private static Thread startDeviceMessageSender(final DeviceMessageSender sender) {
Thread thread = new Thread(new Runnable() {
private static void startDeviceMessageSender(final DeviceMessageSender sender) {
new Thread(new Runnable() {
@Override
public void run() {
try {
@ -119,9 +108,7 @@ public final class Server {
Ln.d("Device message sender stopped");
}
}
});
thread.start();
return thread;
}).start();
}
private static Options createOptions(String... args) {