Compare commits
17 Commits
doc-rotate
...
pr2004
Author | SHA1 | Date | |
---|---|---|---|
192fbd8450 | |||
c5c5fc18ae | |||
f682b87ba5 | |||
10b749e27d | |||
05e8c1a3c5 | |||
83910d3b9c | |||
90f8356630 | |||
3ba51211d6 | |||
ea3582d2c3 | |||
112adbba87 | |||
d039a7a39a | |||
6ab80e4ce8 | |||
230afd8966 | |||
a46733906a | |||
431c9ee33b | |||
43d3dcbd97 | |||
a5f4f58295 |
6
BUILD.md
6
BUILD.md
@ -254,10 +254,10 @@ You can then [run](README.md#run) _scrcpy_.
|
|||||||
|
|
||||||
## Prebuilt server
|
## Prebuilt server
|
||||||
|
|
||||||
- [`scrcpy-server-v1.16`][direct-scrcpy-server]
|
- [`scrcpy-server-v1.17`][direct-scrcpy-server]
|
||||||
_(SHA-256: 94a79e05b4498d0460ab7bd9d12cbf05156e3a47bf0c5d1420cee1d4493b3832)_
|
_(SHA-256: 11b5ad2d1bc9b9730fb7254a78efd71a8ff46b1938ff468e47a21b653a1b6725_
|
||||||
|
|
||||||
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.16/scrcpy-server-v1.16
|
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.17/scrcpy-server-v1.17
|
||||||
|
|
||||||
Download the prebuilt server somewhere, and specify its path during the Meson
|
Download the prebuilt server somewhere, and specify its path during the Meson
|
||||||
configuration:
|
configuration:
|
||||||
|
36
FAQ.md
36
FAQ.md
@ -201,3 +201,39 @@ scrcpy -m 800
|
|||||||
```
|
```
|
||||||
|
|
||||||
You could also try another [encoder](README.md#encoder).
|
You could also try another [encoder](README.md#encoder).
|
||||||
|
|
||||||
|
|
||||||
|
## Command line on Windows
|
||||||
|
|
||||||
|
Some Windows users are not familiar with the command line. Here is how to open a
|
||||||
|
terminal and run `scrcpy` with arguments:
|
||||||
|
|
||||||
|
1. Press <kbd>Windows</kbd>+<kbd>r</kbd>, this opens a dialog box.
|
||||||
|
2. Type `cmd` and press <kbd>Enter</kbd>, this opens a terminal.
|
||||||
|
3. Go to your _scrcpy_ directory, by typing (adapt the path):
|
||||||
|
|
||||||
|
```bat
|
||||||
|
cd C:\Users\user\Downloads\scrcpy-win64-xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
and press <kbd>Enter</kbd>
|
||||||
|
4. Type your command. For example:
|
||||||
|
|
||||||
|
```bat
|
||||||
|
scrcpy --record file.mkv
|
||||||
|
```
|
||||||
|
|
||||||
|
If you plan to always use the same arguments, create a file `myscrcpy.bat`
|
||||||
|
(enable [show file extensions] to avoid confusion) in the `scrcpy` directory,
|
||||||
|
containing your command. For example:
|
||||||
|
|
||||||
|
```bat
|
||||||
|
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/
|
||||||
|
2
LICENSE
2
LICENSE
@ -188,7 +188,7 @@
|
|||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -675,7 +675,7 @@ Baca [halaman pengembang].
|
|||||||
## Lisensi
|
## Lisensi
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -477,7 +477,7 @@ _²화면이 꺼진 상태에서 우클릭 시 다시 켜지며, 그 외의 상
|
|||||||
## 라이선스
|
## 라이선스
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
22
README.md
22
README.md
@ -1,4 +1,4 @@
|
|||||||
# scrcpy (v1.16)
|
# scrcpy (v1.17)
|
||||||
|
|
||||||
[Read in another language](#translations)
|
[Read in another language](#translations)
|
||||||
|
|
||||||
@ -77,10 +77,10 @@ hard).
|
|||||||
For Windows, for simplicity, a prebuilt archive with all the dependencies
|
For Windows, for simplicity, a prebuilt archive with all the dependencies
|
||||||
(including `adb`) is available:
|
(including `adb`) is available:
|
||||||
|
|
||||||
- [`scrcpy-win64-v1.16.zip`][direct-win64]
|
- [`scrcpy-win64-v1.17.zip`][direct-win64]
|
||||||
_(SHA-256: 3f30dc5db1a2f95c2b40a0f5de91ec1642d9f53799250a8c529bc882bc0918f0)_
|
_(SHA-256: 8b9e57993c707367ed10ebfe0e1ef563c7a29d9af4a355cd8b6a52a317c73eea)_
|
||||||
|
|
||||||
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.16/scrcpy-win64-v1.16.zip
|
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.17/scrcpy-win64-v1.17.zip
|
||||||
|
|
||||||
It is also available in [Chocolatey]:
|
It is also available in [Chocolatey]:
|
||||||
|
|
||||||
@ -116,6 +116,10 @@ brew install scrcpy
|
|||||||
You need `adb`, accessible from your `PATH`. If you don't have it yet:
|
You need `adb`, accessible from your `PATH`. If you don't have it yet:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Homebrew >= 2.6.0
|
||||||
|
brew install --cask android-platform-tools
|
||||||
|
|
||||||
|
# Homebrew < 2.6.0
|
||||||
brew cask install android-platform-tools
|
brew cask install android-platform-tools
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -202,6 +206,8 @@ scrcpy --lock-video-orientation 3 # 90° clockwise
|
|||||||
|
|
||||||
This affects recording orientation.
|
This affects recording orientation.
|
||||||
|
|
||||||
|
The [window may also be rotated](#rotation) independently.
|
||||||
|
|
||||||
|
|
||||||
#### Encoder
|
#### Encoder
|
||||||
|
|
||||||
@ -407,9 +413,9 @@ Note that _scrcpy_ manages 3 different rotations:
|
|||||||
- <kbd>MOD</kbd>+<kbd>r</kbd> requests the device to switch between portrait
|
- <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
|
and landscape (the current running app may refuse, if it does support the
|
||||||
requested orientation).
|
requested orientation).
|
||||||
- `--lock-video-orientation` changes the mirroring orientation (the orientation
|
- [`--lock-video-orientation`](#lock-video-orientation) changes the mirroring
|
||||||
of the video sent from the device to the computer). This affects the
|
orientation (the orientation of the video sent from the device to the
|
||||||
recording.
|
computer). This affects the recording.
|
||||||
- `--rotation` (or <kbd>MOD</kbd>+<kbd>←</kbd>/<kbd>MOD</kbd>+<kbd>→</kbd>)
|
- `--rotation` (or <kbd>MOD</kbd>+<kbd>←</kbd>/<kbd>MOD</kbd>+<kbd>→</kbd>)
|
||||||
rotates only the window content. This affects only the display, not the
|
rotates only the window content. This affects only the display, not the
|
||||||
recording.
|
recording.
|
||||||
@ -766,7 +772,7 @@ Read the [developers page].
|
|||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -508,7 +508,7 @@ Leia a [developers page].
|
|||||||
## Licença
|
## Licença
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -703,7 +703,7 @@ _³需要安卓版本 Android >= 7。_
|
|||||||
## 许可协议
|
## 许可协议
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -682,7 +682,7 @@ _³只支援 Android 7+。_
|
|||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
Copyright (C) 2018 Genymobile
|
Copyright (C) 2018 Genymobile
|
||||||
Copyright (C) 2018-2020 Romain Vimont
|
Copyright (C) 2018-2021 Romain Vimont
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -119,9 +119,6 @@ conf.set('DEFAULT_BIT_RATE', '8000000') # 8Mbps
|
|||||||
# enable High DPI support
|
# enable High DPI support
|
||||||
conf.set('HIDPI_SUPPORT', get_option('hidpi_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
|
# run a server debugger and wait for a client to be attached
|
||||||
conf.set('SERVER_DEBUGGER', get_option('server_debugger'))
|
conf.set('SERVER_DEBUGGER', get_option('server_debugger'))
|
||||||
|
|
||||||
@ -132,18 +129,11 @@ configure_file(configuration: conf, output: 'config.h')
|
|||||||
|
|
||||||
src_dir = include_directories('src')
|
src_dir = include_directories('src')
|
||||||
|
|
||||||
if get_option('windows_noconsole')
|
|
||||||
link_args = [ '-Wl,--subsystem,windows' ]
|
|
||||||
else
|
|
||||||
link_args = []
|
|
||||||
endif
|
|
||||||
|
|
||||||
executable('scrcpy', src,
|
executable('scrcpy', src,
|
||||||
dependencies: dependencies,
|
dependencies: dependencies,
|
||||||
include_directories: src_dir,
|
include_directories: src_dir,
|
||||||
install: true,
|
install: true,
|
||||||
c_args: [],
|
c_args: [])
|
||||||
link_args: link_args)
|
|
||||||
|
|
||||||
install_man('scrcpy.1')
|
install_man('scrcpy.1')
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/net.h"
|
#include "util/net.h"
|
||||||
|
|
||||||
static struct server server = SERVER_INITIALIZER;
|
static struct server server;
|
||||||
static struct screen screen = SCREEN_INITIALIZER;
|
static struct screen screen = SCREEN_INITIALIZER;
|
||||||
static struct fps_counter fps_counter;
|
static struct fps_counter fps_counter;
|
||||||
static struct video_buffer video_buffer;
|
static struct video_buffer video_buffer;
|
||||||
@ -304,6 +304,19 @@ av_log_callback(void *avcl, int level, const char *fmt, va_list vl) {
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy(const struct scrcpy_options *options) {
|
scrcpy(const struct scrcpy_options *options) {
|
||||||
|
if (!server_init(&server)) {
|
||||||
|
return 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;
|
bool record = !!options->record_filename;
|
||||||
struct server_params params = {
|
struct server_params params = {
|
||||||
.log_level = options->log_level,
|
.log_level = options->log_level,
|
||||||
@ -322,18 +335,10 @@ scrcpy(const struct scrcpy_options *options) {
|
|||||||
.force_adb_forward = options->force_adb_forward,
|
.force_adb_forward = options->force_adb_forward,
|
||||||
};
|
};
|
||||||
if (!server_start(&server, options->serial, ¶ms)) {
|
if (!server_start(&server, options->serial, ¶ms)) {
|
||||||
return false;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = false;
|
server_started = true;
|
||||||
|
|
||||||
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,
|
if (!sdl_init_and_configure(options->display, options->render_driver,
|
||||||
options->disable_screensaver)) {
|
options->disable_screensaver)) {
|
||||||
@ -444,7 +449,7 @@ scrcpy(const struct scrcpy_options *options) {
|
|||||||
|
|
||||||
input_manager_init(&input_manager, options);
|
input_manager_init(&input_manager, options);
|
||||||
|
|
||||||
ret = event_loop(options);
|
bool ret = event_loop(options);
|
||||||
LOGD("quit...");
|
LOGD("quit...");
|
||||||
|
|
||||||
screen_destroy(&screen);
|
screen_destroy(&screen);
|
||||||
@ -465,8 +470,10 @@ end:
|
|||||||
fps_counter_interrupt(&fps_counter);
|
fps_counter_interrupt(&fps_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (server_started) {
|
||||||
// shutdown the sockets and kill the server
|
// shutdown the sockets and kill the server
|
||||||
server_stop(&server);
|
server_stop(&server);
|
||||||
|
}
|
||||||
|
|
||||||
// now that the sockets are shutdown, the stream and controller are
|
// now that the sockets are shutdown, the stream and controller are
|
||||||
// interrupted, we can join them
|
// interrupted, we can join them
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "util/lock.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/net.h"
|
#include "util/net.h"
|
||||||
#include "util/str_util.h"
|
#include "util/str_util.h"
|
||||||
@ -353,15 +354,51 @@ close_socket(socket_t socket) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
server_init(struct server *server) {
|
server_init(struct server *server) {
|
||||||
*server = (struct server) SERVER_INITIALIZER;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
run_wait_server(void *data) {
|
run_wait_server(void *data) {
|
||||||
struct server *server = data;
|
struct server *server = data;
|
||||||
cmd_simple_wait(server->process, NULL); // ignore exit code
|
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||||
|
|
||||||
|
mutex_lock(server->mutex);
|
||||||
|
server->process_terminated = true;
|
||||||
|
cond_signal(server->process_terminated_cond);
|
||||||
|
mutex_unlock(server->mutex);
|
||||||
|
|
||||||
// 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 != INVALID_SOCKET
|
if (server->server_socket != INVALID_SOCKET
|
||||||
@ -493,17 +530,39 @@ server_stop(struct server *server) {
|
|||||||
|
|
||||||
assert(server->process != PROCESS_NONE);
|
assert(server->process != PROCESS_NONE);
|
||||||
|
|
||||||
cmd_terminate(server->process);
|
|
||||||
|
|
||||||
if (server->tunnel_enabled) {
|
if (server->tunnel_enabled) {
|
||||||
// ignore failure
|
// ignore failure
|
||||||
disable_tunnel(server);
|
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) {
|
||||||
|
// FIXME There is a race condition here: there is a small chance that
|
||||||
|
// the process is already terminated, and the PID assigned to a new
|
||||||
|
// process.
|
||||||
|
LOGW("Killing the server...");
|
||||||
|
cmd_terminate(server->process);
|
||||||
|
}
|
||||||
|
|
||||||
SDL_WaitThread(server->wait_server_thread, NULL);
|
SDL_WaitThread(server->wait_server_thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_destroy(struct server *server) {
|
server_destroy(struct server *server) {
|
||||||
SDL_free(server->serial);
|
SDL_free(server->serial);
|
||||||
|
SDL_DestroyCond(server->process_terminated_cond);
|
||||||
|
SDL_DestroyMutex(server->mutex);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,11 @@ struct server {
|
|||||||
process_t process;
|
process_t process;
|
||||||
SDL_Thread *wait_server_thread;
|
SDL_Thread *wait_server_thread;
|
||||||
atomic_flag server_socket_closed;
|
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 server_socket; // only used if !tunnel_forward
|
||||||
socket_t video_socket;
|
socket_t video_socket;
|
||||||
socket_t control_socket;
|
socket_t control_socket;
|
||||||
@ -27,23 +32,6 @@ struct server {
|
|||||||
bool tunnel_forward; // use "adb forward" instead of "adb reverse"
|
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 {
|
struct server_params {
|
||||||
enum sc_log_level log_level;
|
enum sc_log_level log_level;
|
||||||
const char *crop;
|
const char *crop;
|
||||||
@ -62,7 +50,7 @@ struct server_params {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// init default values
|
// init default values
|
||||||
void
|
bool
|
||||||
server_init(struct server *server);
|
server_init(struct server *server);
|
||||||
|
|
||||||
// push, enable tunnel et start the server
|
// push, enable tunnel et start the server
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -39,12 +39,7 @@ cmd_execute(const char *const argv[], HANDLE *handle) {
|
|||||||
return PROCESS_ERROR_GENERIC;
|
return PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WINDOWS_NOCONSOLE
|
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, 0, NULL, NULL, &si,
|
||||||
int flags = CREATE_NO_WINDOW;
|
|
||||||
#else
|
|
||||||
int flags = 0;
|
|
||||||
#endif
|
|
||||||
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si,
|
|
||||||
&pi)) {
|
&pi)) {
|
||||||
SDL_free(wide);
|
SDL_free(wide);
|
||||||
*handle = NULL;
|
*handle = NULL;
|
||||||
@ -61,7 +56,7 @@ cmd_execute(const char *const argv[], HANDLE *handle) {
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
cmd_terminate(HANDLE handle) {
|
cmd_terminate(HANDLE handle) {
|
||||||
return TerminateProcess(handle, 1) && CloseHandle(handle);
|
return TerminateProcess(handle, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -75,6 +70,7 @@ cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
|
|||||||
if (exit_code) {
|
if (exit_code) {
|
||||||
*exit_code = code;
|
*exit_code = code;
|
||||||
}
|
}
|
||||||
|
CloseHandle(handle);
|
||||||
return !code;
|
return !code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,4 +17,4 @@ endian = 'little'
|
|||||||
[properties]
|
[properties]
|
||||||
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win32-shared'
|
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win32-shared'
|
||||||
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win32-dev'
|
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win32-dev'
|
||||||
prebuilt_sdl2 = 'SDL2-2.0.12/i686-w64-mingw32'
|
prebuilt_sdl2 = 'SDL2-2.0.14/i686-w64-mingw32'
|
||||||
|
@ -17,4 +17,4 @@ endian = 'little'
|
|||||||
[properties]
|
[properties]
|
||||||
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win64-shared'
|
prebuilt_ffmpeg_shared = 'ffmpeg-4.3.1-win64-shared'
|
||||||
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win64-dev'
|
prebuilt_ffmpeg_dev = 'ffmpeg-4.3.1-win64-dev'
|
||||||
prebuilt_sdl2 = 'SDL2-2.0.12/x86_64-w64-mingw32'
|
prebuilt_sdl2 = 'SDL2-2.0.14/x86_64-w64-mingw32'
|
||||||
|
1
data/scrcpy-noconsole.vbs
Normal file
1
data/scrcpy-noconsole.vbs
Normal file
@ -0,0 +1 @@
|
|||||||
|
CreateObject("Wscript.Shell").Run "cmd /c scrcpy.exe", 0, false
|
@ -1,5 +1,5 @@
|
|||||||
project('scrcpy', 'c',
|
project('scrcpy', 'c',
|
||||||
version: '1.16',
|
version: '1.17',
|
||||||
meson_version: '>= 0.48',
|
meson_version: '>= 0.48',
|
||||||
default_options: [
|
default_options: [
|
||||||
'c_std=c11',
|
'c_std=c11',
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
option('compile_app', type: 'boolean', value: true, description: 'Build the client')
|
option('compile_app', type: 'boolean', value: true, description: 'Build the client')
|
||||||
option('compile_server', type: 'boolean', value: true, description: 'Build the server')
|
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('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('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('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')
|
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')
|
||||||
|
@ -30,9 +30,9 @@ prepare-ffmpeg-dev-win64:
|
|||||||
ffmpeg-4.3.1-win64-dev
|
ffmpeg-4.3.1-win64-dev
|
||||||
|
|
||||||
prepare-sdl2:
|
prepare-sdl2:
|
||||||
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.12-mingw.tar.gz \
|
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.14-mingw.tar.gz \
|
||||||
e614a60f797e35ef9f3f96aef3dc6a1d786de3cc7ca6216f97e435c0b6aafc46 \
|
405eaff3eb18f2e08fe669ef9e63bc9a8710b7d343756f238619761e9b60407d \
|
||||||
SDL2-2.0.12
|
SDL2-2.0.14
|
||||||
|
|
||||||
prepare-adb:
|
prepare-adb:
|
||||||
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r30.0.5-windows.zip \
|
@./prepare-dep https://dl.google.com/android/repository/platform-tools_r30.0.5-windows.zip \
|
||||||
|
@ -9,21 +9,20 @@
|
|||||||
# the server to the device.
|
# the server to the device.
|
||||||
|
|
||||||
.PHONY: default clean \
|
.PHONY: default clean \
|
||||||
|
test \
|
||||||
build-server \
|
build-server \
|
||||||
prepare-deps-win32 prepare-deps-win64 \
|
prepare-deps-win32 prepare-deps-win64 \
|
||||||
build-win32 build-win32-noconsole \
|
build-win32 build-win64 \
|
||||||
build-win64 build-win64-noconsole \
|
|
||||||
dist-win32 dist-win64 \
|
dist-win32 dist-win64 \
|
||||||
zip-win32 zip-win64 \
|
zip-win32 zip-win64 \
|
||||||
sums release
|
release
|
||||||
|
|
||||||
GRADLE ?= ./gradlew
|
GRADLE ?= ./gradlew
|
||||||
|
|
||||||
|
TEST_BUILD_DIR := build-test
|
||||||
SERVER_BUILD_DIR := build-server
|
SERVER_BUILD_DIR := build-server
|
||||||
WIN32_BUILD_DIR := build-win32
|
WIN32_BUILD_DIR := build-win32
|
||||||
WIN32_NOCONSOLE_BUILD_DIR := build-win32-noconsole
|
|
||||||
WIN64_BUILD_DIR := build-win64
|
WIN64_BUILD_DIR := build-win64
|
||||||
WIN64_NOCONSOLE_BUILD_DIR := build-win64-noconsole
|
|
||||||
|
|
||||||
DIST := dist
|
DIST := dist
|
||||||
WIN32_TARGET_DIR := scrcpy-win32
|
WIN32_TARGET_DIR := scrcpy-win32
|
||||||
@ -33,18 +32,34 @@ VERSION := $(shell git describe --tags --always)
|
|||||||
WIN32_TARGET := $(WIN32_TARGET_DIR)-$(VERSION).zip
|
WIN32_TARGET := $(WIN32_TARGET_DIR)-$(VERSION).zip
|
||||||
WIN64_TARGET := $(WIN64_TARGET_DIR)-$(VERSION).zip
|
WIN64_TARGET := $(WIN64_TARGET_DIR)-$(VERSION).zip
|
||||||
|
|
||||||
release: clean zip-win32 zip-win64 sums
|
RELEASE_DIR := release-$(VERSION)
|
||||||
@echo "Windows archives generated in $(DIST)/"
|
|
||||||
|
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)/"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(GRADLE) clean
|
$(GRADLE) clean
|
||||||
rm -rf "$(SERVER_BUILD_DIR)" "$(WIN32_BUILD_DIR)" "$(WIN64_BUILD_DIR)" \
|
rm -rf "$(DIST)" "$(TEST_BUILD_DIR)" "$(SERVER_BUILD_DIR)" \
|
||||||
"$(WIN32_NOCONSOLE_BUILD_DIR)" "$(WIN64_NOCONSOLE_BUILD_DIR)" "$(DIST)"
|
"$(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
|
||||||
|
|
||||||
build-server:
|
build-server:
|
||||||
[ -d "$(SERVER_BUILD_DIR)" ] || ( mkdir "$(SERVER_BUILD_DIR)" && \
|
[ -d "$(SERVER_BUILD_DIR)" ] || ( mkdir "$(SERVER_BUILD_DIR)" && \
|
||||||
meson "$(SERVER_BUILD_DIR)" \
|
meson "$(SERVER_BUILD_DIR)" --buildtype release -Dcompile_app=false )
|
||||||
--buildtype release -Dcompile_app=false )
|
|
||||||
ninja -C "$(SERVER_BUILD_DIR)"
|
ninja -C "$(SERVER_BUILD_DIR)"
|
||||||
|
|
||||||
prepare-deps-win32:
|
prepare-deps-win32:
|
||||||
@ -60,17 +75,6 @@ build-win32: prepare-deps-win32
|
|||||||
-Dportable=true )
|
-Dportable=true )
|
||||||
ninja -C "$(WIN32_BUILD_DIR)"
|
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:
|
prepare-deps-win64:
|
||||||
-$(MAKE) -C prebuilt-deps prepare-win64
|
-$(MAKE) -C prebuilt-deps prepare-win64
|
||||||
|
|
||||||
@ -84,23 +88,12 @@ build-win64: prepare-deps-win64
|
|||||||
-Dportable=true )
|
-Dportable=true )
|
||||||
ninja -C "$(WIN64_BUILD_DIR)"
|
ninja -C "$(WIN64_BUILD_DIR)"
|
||||||
|
|
||||||
build-win64-noconsole: prepare-deps-win64
|
dist-win32: build-server build-win32
|
||||||
[ -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)"
|
mkdir -p "$(DIST)/$(WIN32_TARGET_DIR)"
|
||||||
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server "$(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_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-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/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/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||||
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||||
@ -109,14 +102,14 @@ dist-win32: build-server build-win32 build-win32-noconsole
|
|||||||
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
|
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/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||||
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||||
cp prebuilt-deps/SDL2-2.0.12/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
cp prebuilt-deps/SDL2-2.0.14/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||||
|
|
||||||
dist-win64: build-server build-win64 build-win64-noconsole
|
dist-win64: build-server build-win64
|
||||||
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
|
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
|
||||||
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server "$(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_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-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/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/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||||
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||||
@ -125,7 +118,7 @@ dist-win64: build-server build-win64 build-win64-noconsole
|
|||||||
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
|
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/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||||
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||||
cp prebuilt-deps/SDL2-2.0.12/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
cp prebuilt-deps/SDL2-2.0.14/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||||
|
|
||||||
zip-win32: dist-win32
|
zip-win32: dist-win32
|
||||||
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \
|
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \
|
||||||
@ -134,7 +127,3 @@ zip-win32: dist-win32
|
|||||||
zip-win64: dist-win64
|
zip-win64: dist-win64
|
||||||
cd "$(DIST)/$(WIN64_TARGET_DIR)"; \
|
cd "$(DIST)/$(WIN64_TARGET_DIR)"; \
|
||||||
zip -r "../$(WIN64_TARGET)" .
|
zip -r "../$(WIN64_TARGET)" .
|
||||||
|
|
||||||
sums:
|
|
||||||
cd "$(DIST)"; \
|
|
||||||
sha256sum *.zip > SHA256SUMS.txt
|
|
44
release.sh
44
release.sh
@ -1,44 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
make -f release.mk
|
||||||
|
|
||||||
# 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/"
|
|
||||||
|
@ -6,8 +6,8 @@ android {
|
|||||||
applicationId "com.genymobile.scrcpy"
|
applicationId "com.genymobile.scrcpy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 19
|
versionCode 20
|
||||||
versionName "1.16"
|
versionName "1.17"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRCPY_DEBUG=false
|
SCRCPY_DEBUG=false
|
||||||
SCRCPY_VERSION_NAME=1.16
|
SCRCPY_VERSION_NAME=1.17
|
||||||
|
|
||||||
PLATFORM=${ANDROID_PLATFORM:-30}
|
PLATFORM=${ANDROID_PLATFORM:-30}
|
||||||
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-30.0.0}
|
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-30.0.0}
|
||||||
|
@ -58,12 +58,14 @@ public final class Server {
|
|||||||
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions,
|
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions,
|
||||||
options.getEncoderName());
|
options.getEncoderName());
|
||||||
|
|
||||||
|
Thread controllerThread = null;
|
||||||
|
Thread deviceMessageSenderThread = null;
|
||||||
if (options.getControl()) {
|
if (options.getControl()) {
|
||||||
final Controller controller = new Controller(device, connection);
|
final Controller controller = new Controller(device, connection);
|
||||||
|
|
||||||
// asynchronous
|
// asynchronous
|
||||||
startController(controller);
|
controllerThread = startController(controller);
|
||||||
startDeviceMessageSender(controller.getSender());
|
deviceMessageSenderThread = startDeviceMessageSender(controller.getSender());
|
||||||
|
|
||||||
device.setClipboardListener(new Device.ClipboardListener() {
|
device.setClipboardListener(new Device.ClipboardListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -79,12 +81,19 @@ public final class Server {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// this is expected on close
|
// this is expected on close
|
||||||
Ln.d("Screen streaming stopped");
|
Ln.d("Screen streaming stopped");
|
||||||
|
} finally {
|
||||||
|
if (controllerThread != null) {
|
||||||
|
controllerThread.interrupt();
|
||||||
|
}
|
||||||
|
if (deviceMessageSenderThread != null) {
|
||||||
|
deviceMessageSenderThread.interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startController(final Controller controller) {
|
private static Thread startController(final Controller controller) {
|
||||||
new Thread(new Runnable() {
|
Thread thread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
@ -94,11 +103,13 @@ public final class Server {
|
|||||||
Ln.d("Controller stopped");
|
Ln.d("Controller stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
});
|
||||||
|
thread.start();
|
||||||
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startDeviceMessageSender(final DeviceMessageSender sender) {
|
private static Thread startDeviceMessageSender(final DeviceMessageSender sender) {
|
||||||
new Thread(new Runnable() {
|
Thread thread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
@ -108,7 +119,9 @@ public final class Server {
|
|||||||
Ln.d("Device message sender stopped");
|
Ln.d("Device message sender stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
});
|
||||||
|
thread.start();
|
||||||
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Options createOptions(String... args) {
|
private static Options createOptions(String... args) {
|
||||||
|
Reference in New Issue
Block a user