mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-03-05 19:54:41 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
236cd4ff6f | ||
|
|
24e1005a07 | ||
|
|
a7991323e4 |
6
BUILD.md
6
BUILD.md
@@ -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:
|
||||
|
||||
36
FAQ.md
36
FAQ.md
@@ -201,39 +201,3 @@ scrcpy -m 800
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
22
README.md
22
README.md
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -8,6 +8,7 @@ src = [
|
||||
'src/device.c',
|
||||
'src/device_msg.c',
|
||||
'src/event_converter.c',
|
||||
'src/icon.c',
|
||||
'src/file_handler.c',
|
||||
'src/fps_counter.c',
|
||||
'src/input_manager.c',
|
||||
@@ -18,7 +19,6 @@ src = [
|
||||
'src/screen.c',
|
||||
'src/server.c',
|
||||
'src/stream.c',
|
||||
'src/tiny_xpm.c',
|
||||
'src/video_buffer.c',
|
||||
'src/util/net.c',
|
||||
'src/util/str_util.c'
|
||||
@@ -136,6 +136,9 @@ executable('scrcpy', src,
|
||||
c_args: [])
|
||||
|
||||
install_man('scrcpy.1')
|
||||
install_data('../data/icon.png',
|
||||
rename: 'scrcpy.png',
|
||||
install_dir: 'share/icons/hicolor/512x512/apps')
|
||||
|
||||
|
||||
### TESTS
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "command.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -229,3 +230,31 @@ process_check_success(process_t proc, const char *name) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *
|
||||
get_local_file_path(const char *name) {
|
||||
char *executable_path = get_executable_path();
|
||||
if (!executable_path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *dir = dirname(executable_path);
|
||||
size_t dirlen = strlen(dir);
|
||||
size_t namelen = strlen(name);
|
||||
|
||||
size_t len = dirlen + namelen + 2; // +2: '/' and '\0`
|
||||
char *file_path = SDL_malloc(len);
|
||||
if (!file_path) {
|
||||
LOGE("Could not alloc path");
|
||||
SDL_free(executable_path);
|
||||
}
|
||||
|
||||
memcpy(file_path, dir, dirlen);
|
||||
file_path[dirlen] = PATH_SEPARATOR;
|
||||
// namelen + 1 to copy the final '\0'
|
||||
memcpy(&file_path[dirlen + 1], name, namelen + 1);
|
||||
|
||||
SDL_free(executable_path);
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
@@ -90,4 +90,9 @@ get_executable_path(void);
|
||||
bool
|
||||
is_regular_file(const char *path);
|
||||
|
||||
// return the absolute path of a file in the same directory as the executable
|
||||
// may be NULL on error; to be freed by SDL_free
|
||||
char *
|
||||
get_local_file_path(const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
282
app/src/icon.c
Normal file
282
app/src/icon.c
Normal file
@@ -0,0 +1,282 @@
|
||||
#include "icon.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/pixfmt.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "command.h"
|
||||
#include "compat.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str_util.h"
|
||||
|
||||
#define SCRCPY_PORTABLE_ICON_FILENAME "icon.png"
|
||||
#define SCRCPY_DEFAULT_ICON_PATH PREFIX \
|
||||
"/share/icons/hicolor/512x512/apps/scrcpy.png"
|
||||
|
||||
static char *
|
||||
get_icon_path(void) {
|
||||
#ifdef __WINDOWS__
|
||||
const wchar_t *icon_path_env = _wgetenv(L"SCRCPY_ICON_PATH");
|
||||
#else
|
||||
const char *icon_path_env = getenv("SCRCPY_ICON_PATH");
|
||||
#endif
|
||||
if (icon_path_env) {
|
||||
// if the envvar is set, use it
|
||||
#ifdef __WINDOWS__
|
||||
char *icon_path = utf8_from_wide_char(icon_path_env);
|
||||
#else
|
||||
char *icon_path = SDL_strdup(icon_path_env);
|
||||
#endif
|
||||
if (!icon_path) {
|
||||
LOGE("Could not allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
LOGD("Using SCRCPY_ICON_PATH: %s", icon_path);
|
||||
return icon_path;
|
||||
}
|
||||
|
||||
#ifndef PORTABLE
|
||||
char *icon_path = SDL_strdup(SCRCPY_DEFAULT_ICON_PATH);
|
||||
if (!icon_path) {
|
||||
LOGE("Could not allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
char *icon_path = get_local_file_path(SCRCPY_PORTABLE_ICON_FILENAME);
|
||||
if (!icon_path) {
|
||||
LOGE("Could not get icon path");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return icon_path;
|
||||
}
|
||||
|
||||
static AVFrame *
|
||||
decode_image(const char *path) {
|
||||
AVFrame *result = NULL;
|
||||
|
||||
AVFormatContext *ctx = avformat_alloc_context();
|
||||
if (!ctx) {
|
||||
LOGE("Could not allocate image decoder context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (avformat_open_input(&ctx, path, NULL, NULL) < 0) {
|
||||
LOGE("Could not open image codec");
|
||||
goto free_ctx;
|
||||
}
|
||||
|
||||
if (avformat_find_stream_info(ctx, NULL) < 0) {
|
||||
LOGE("Could not find image stream info");
|
||||
goto close_input;
|
||||
}
|
||||
|
||||
int stream = av_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
|
||||
if (stream < 0 ) {
|
||||
LOGE("Could not find best image stream");
|
||||
goto close_input;
|
||||
}
|
||||
|
||||
#ifdef SCRCPY_LAVF_HAS_NEW_CODEC_PARAMS_API
|
||||
AVCodecParameters *params = ctx->streams[stream]->codecpar;
|
||||
|
||||
AVCodec *codec = avcodec_find_decoder(params->codec_id);
|
||||
if (!codec) {
|
||||
LOGE("Could not find image decoder");
|
||||
goto close_input;
|
||||
}
|
||||
|
||||
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
|
||||
if (avcodec_parameters_to_context(codec_ctx, params) < 0) {
|
||||
LOGE("Could not fill codec context");
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
#else
|
||||
AVCodecContext *codec_ctx = ctx->streams[stream]->codec;
|
||||
|
||||
AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
|
||||
if (!codec) {
|
||||
LOGE("Could not find image decoder");
|
||||
goto close_input;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
|
||||
LOGE("Could not open image codec");
|
||||
goto free_codec_ctx;
|
||||
}
|
||||
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
if (!frame) {
|
||||
LOGE("Could not allocate frame");
|
||||
goto close_codec;
|
||||
}
|
||||
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
|
||||
if (av_read_frame(ctx, &packet) < 0) {
|
||||
LOGE("Could not read frame");
|
||||
av_frame_free(&frame);
|
||||
goto close_input;
|
||||
}
|
||||
|
||||
#ifdef SCRCPY_LAVF_HAS_NEW_ENCODING_DECODING_API
|
||||
int ret;
|
||||
if ((ret = avcodec_send_packet(codec_ctx, &packet)) < 0) {
|
||||
LOGE("Could not send icon packet: %d", ret);
|
||||
av_frame_free(&frame);
|
||||
goto close_input;
|
||||
}
|
||||
|
||||
if ((ret = avcodec_receive_frame(codec_ctx, frame)) != 0) {
|
||||
LOGE("Could not receive icon frame: %d", ret);
|
||||
av_frame_free(&frame);
|
||||
goto close_input;
|
||||
}
|
||||
|
||||
#else
|
||||
int got_picture;
|
||||
int len = avcodec_decode_video2(codec_ctx, frame, &got_picture, &packet);
|
||||
if (len < 0 || !got_picture) {
|
||||
LOGE("Could not decode icon: %d", len);
|
||||
av_frame_free(&frame);
|
||||
goto close_input;
|
||||
}
|
||||
#endif
|
||||
|
||||
av_packet_unref(&packet);
|
||||
|
||||
result = frame;
|
||||
|
||||
close_codec:
|
||||
avcodec_close(codec_ctx);
|
||||
free_codec_ctx:
|
||||
#ifdef SCRCPY_LAVF_HAS_NEW_CODEC_PARAMS_API
|
||||
avcodec_free_context(&codec_ctx);
|
||||
#endif
|
||||
close_input:
|
||||
avformat_close_input(&ctx);
|
||||
free_ctx:
|
||||
avformat_free_context(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static SDL_PixelFormatEnum
|
||||
to_sdl_pixel_format(enum AVPixelFormat fmt) {
|
||||
switch (fmt) {
|
||||
case AV_PIX_FMT_RGB24: return SDL_PIXELFORMAT_RGB24;
|
||||
case AV_PIX_FMT_BGR24: return SDL_PIXELFORMAT_BGR24;
|
||||
case AV_PIX_FMT_ARGB: return SDL_PIXELFORMAT_ARGB32;
|
||||
case AV_PIX_FMT_RGBA: return SDL_PIXELFORMAT_RGBA32;
|
||||
case AV_PIX_FMT_ABGR: return SDL_PIXELFORMAT_ABGR32;
|
||||
case AV_PIX_FMT_BGRA: return SDL_PIXELFORMAT_BGRA32;
|
||||
case AV_PIX_FMT_RGB565BE: return SDL_PIXELFORMAT_RGB565;
|
||||
case AV_PIX_FMT_RGB555BE: return SDL_PIXELFORMAT_RGB555;
|
||||
case AV_PIX_FMT_BGR565BE: return SDL_PIXELFORMAT_BGR565;
|
||||
case AV_PIX_FMT_BGR555BE: return SDL_PIXELFORMAT_BGR555;
|
||||
case AV_PIX_FMT_RGB444BE: return SDL_PIXELFORMAT_RGB444;
|
||||
case AV_PIX_FMT_BGR444BE: return SDL_PIXELFORMAT_BGR444;
|
||||
case AV_PIX_FMT_PAL8: return SDL_PIXELFORMAT_INDEX8;
|
||||
default: return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface *
|
||||
scrcpy_icon_load() {
|
||||
char *icon_path = get_icon_path();
|
||||
assert(icon_path);
|
||||
|
||||
AVFrame *frame = decode_image(icon_path);
|
||||
SDL_free(icon_path);
|
||||
if (!frame) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
|
||||
if (!desc) {
|
||||
LOGE("Could not get icon format descriptor");
|
||||
goto error;
|
||||
}
|
||||
|
||||
bool is_packed = !(desc->flags & AV_PIX_FMT_FLAG_PLANAR);
|
||||
if (!is_packed) {
|
||||
LOGE("Could not load non-packed icon");
|
||||
goto error;
|
||||
}
|
||||
|
||||
SDL_PixelFormatEnum format = to_sdl_pixel_format(frame->format);
|
||||
if (format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
LOGE("Unsupported icon pixel format: %s (%d)", desc->name,
|
||||
frame->format);
|
||||
goto error;
|
||||
}
|
||||
|
||||
int bits_per_pixel = av_get_bits_per_pixel(desc);
|
||||
SDL_Surface *surface =
|
||||
SDL_CreateRGBSurfaceWithFormatFrom(frame->data[0],
|
||||
frame->width, frame->height,
|
||||
bits_per_pixel,
|
||||
frame->linesize[0],
|
||||
format);
|
||||
|
||||
if (!surface) {
|
||||
LOGE("Could not create icon surface");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (frame->format == AV_PIX_FMT_PAL8) {
|
||||
// Initialize the SDL palette
|
||||
uint8_t *data = frame->data[1];
|
||||
SDL_Color colors[256];
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
SDL_Color *color = &colors[i];
|
||||
|
||||
// The palette is transported in AVFrame.data[1], is 1024 bytes
|
||||
// long (256 4-byte entries) and is formatted the same as in
|
||||
// AV_PIX_FMT_RGB32 described above (i.e., it is also
|
||||
// endian-specific).
|
||||
// <https://ffmpeg.org/doxygen/4.1/pixfmt_8h.html#a9a8e335cf3be472042bc9f0cf80cd4c5>
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
color->a = data[i * 4];
|
||||
color->r = data[i * 4 + 1];
|
||||
color->g = data[i * 4 + 2];
|
||||
color->b = data[i * 4 + 3];
|
||||
#else
|
||||
color->a = data[i * 4 + 3];
|
||||
color->r = data[i * 4 + 2];
|
||||
color->g = data[i * 4 + 1];
|
||||
color->b = data[i * 4];
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_Palette *palette = surface->format->palette;
|
||||
assert(palette);
|
||||
int ret = SDL_SetPaletteColors(palette, colors, 0, 256);
|
||||
if (ret) {
|
||||
LOGE("Could not set palette colors");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
surface->userdata = frame; // frame owns the data
|
||||
|
||||
return surface;
|
||||
|
||||
error:
|
||||
av_frame_free(&frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
scrcpy_icon_destroy(SDL_Surface *icon) {
|
||||
AVFrame *frame = icon->userdata;
|
||||
assert(frame);
|
||||
av_frame_free(&frame);
|
||||
SDL_FreeSurface(icon);
|
||||
}
|
||||
16
app/src/icon.h
Normal file
16
app/src/icon.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ICON_H
|
||||
#define ICON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
SDL_Surface *
|
||||
scrcpy_icon_load(void);
|
||||
|
||||
void
|
||||
scrcpy_icon_destroy(SDL_Surface *icon);
|
||||
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
/* XPM */
|
||||
static char * icon_xpm[] = {
|
||||
"48 48 2 1",
|
||||
" c None",
|
||||
". c #96C13E",
|
||||
" .. .. ",
|
||||
" ... ... ",
|
||||
" ... ...... ... ",
|
||||
" ................ ",
|
||||
" .............. ",
|
||||
" ................ ",
|
||||
" .................. ",
|
||||
" .................... ",
|
||||
" ..... ........ ..... ",
|
||||
" ..... ........ ..... ",
|
||||
" ...................... ",
|
||||
" ........................ ",
|
||||
" ........................ ",
|
||||
" ........................ ",
|
||||
" ",
|
||||
" ",
|
||||
" .... ........................ .... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" ...... ........................ ...... ",
|
||||
" .... ........................ .... ",
|
||||
" ........................ ",
|
||||
" ...................... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" ...... ...... ",
|
||||
" .... .... "};
|
||||
@@ -28,13 +28,12 @@
|
||||
#include "screen.h"
|
||||
#include "server.h"
|
||||
#include "stream.h"
|
||||
#include "tiny_xpm.h"
|
||||
#include "video_buffer.h"
|
||||
#include "util/lock.h"
|
||||
#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;
|
||||
@@ -304,19 +303,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 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,
|
||||
@@ -335,10 +321,18 @@ scrcpy(const struct scrcpy_options *options) {
|
||||
.force_adb_forward = options->force_adb_forward,
|
||||
};
|
||||
if (!server_start(&server, options->serial, ¶ms)) {
|
||||
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)) {
|
||||
@@ -449,7 +443,7 @@ scrcpy(const struct scrcpy_options *options) {
|
||||
|
||||
input_manager_init(&input_manager, options);
|
||||
|
||||
bool ret = event_loop(options);
|
||||
ret = event_loop(options);
|
||||
LOGD("quit...");
|
||||
|
||||
screen_destroy(&screen);
|
||||
@@ -470,10 +464,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
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "compat.h"
|
||||
#include "icon.xpm"
|
||||
#include "icon.h"
|
||||
#include "scrcpy.h"
|
||||
#include "tiny_xpm.h"
|
||||
#include "video_buffer.h"
|
||||
#include "util/lock.h"
|
||||
#include "util/log.h"
|
||||
@@ -309,10 +308,10 @@ screen_init_rendering(struct screen *screen, const char *window_title,
|
||||
LOGD("Trilinear filtering disabled (not an OpenGL renderer)");
|
||||
}
|
||||
|
||||
SDL_Surface *icon = read_xpm(icon_xpm);
|
||||
SDL_Surface *icon = scrcpy_icon_load();
|
||||
if (icon) {
|
||||
SDL_SetWindowIcon(screen->window, icon);
|
||||
SDL_FreeSurface(icon);
|
||||
scrcpy_icon_destroy(icon);
|
||||
} else {
|
||||
LOGW("Could not load icon");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
@@ -11,7 +10,6 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "command.h"
|
||||
#include "util/lock.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net.h"
|
||||
#include "util/str_util.h"
|
||||
@@ -54,35 +52,13 @@ get_server_path(void) {
|
||||
// the absolute path is hardcoded
|
||||
return server_path;
|
||||
#else
|
||||
|
||||
// use scrcpy-server in the same directory as the executable
|
||||
char *executable_path = get_executable_path();
|
||||
if (!executable_path) {
|
||||
LOGE("Could not get executable path, "
|
||||
"using " SERVER_FILENAME " from current directory");
|
||||
// not found, use current directory
|
||||
return SERVER_FILENAME;
|
||||
}
|
||||
char *dir = dirname(executable_path);
|
||||
size_t dirlen = strlen(dir);
|
||||
|
||||
// sizeof(SERVER_FILENAME) gives statically the size including the null byte
|
||||
size_t len = dirlen + 1 + sizeof(SERVER_FILENAME);
|
||||
char *server_path = SDL_malloc(len);
|
||||
char *server_path = get_local_file_path(SERVER_FILENAME);
|
||||
if (!server_path) {
|
||||
LOGE("Could not alloc server path string, "
|
||||
LOGE("Could not get local file path, "
|
||||
"using " SERVER_FILENAME " from current directory");
|
||||
SDL_free(executable_path);
|
||||
return SERVER_FILENAME;
|
||||
}
|
||||
|
||||
memcpy(server_path, dir, dirlen);
|
||||
server_path[dirlen] = PATH_SEPARATOR;
|
||||
memcpy(&server_path[dirlen + 1], SERVER_FILENAME, sizeof(SERVER_FILENAME));
|
||||
// the final null byte has been copied with SERVER_FILENAME
|
||||
|
||||
SDL_free(executable_path);
|
||||
|
||||
LOGD("Using server (portable): %s", server_path);
|
||||
return server_path;
|
||||
#endif
|
||||
@@ -354,51 +330,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;
|
||||
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
|
||||
// thread was created
|
||||
if (server->server_socket != INVALID_SOCKET
|
||||
@@ -530,39 +470,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) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
void
|
||||
server_destroy(struct server *server) {
|
||||
SDL_free(server->serial);
|
||||
SDL_DestroyCond(server->process_terminated_cond);
|
||||
SDL_DestroyMutex(server->mutex);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -50,7 +62,7 @@ struct server_params {
|
||||
};
|
||||
|
||||
// init default values
|
||||
bool
|
||||
void
|
||||
server_init(struct server *server);
|
||||
|
||||
// push, enable tunnel et start the server
|
||||
|
||||
@@ -56,7 +56,7 @@ cmd_execute(const char *const argv[], HANDLE *handle) {
|
||||
|
||||
bool
|
||||
cmd_terminate(HANDLE handle) {
|
||||
return TerminateProcess(handle, 1);
|
||||
return TerminateProcess(handle, 1) && CloseHandle(handle);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -70,7 +70,6 @@ cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
|
||||
if (exit_code) {
|
||||
*exit_code = code;
|
||||
}
|
||||
CloseHandle(handle);
|
||||
return !code;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
#include "tiny_xpm.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
|
||||
struct index {
|
||||
char c;
|
||||
uint32_t color;
|
||||
};
|
||||
|
||||
static bool
|
||||
find_color(struct index *index, int len, char c, uint32_t *color) {
|
||||
// there are typically very few color, so it's ok to iterate over the array
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (index[i].c == c) {
|
||||
*color = index[i].color;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*color = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We encounter some problems with SDL2_image on MSYS2 (Windows),
|
||||
// so here is our own XPM parsing not to depend on SDL_image.
|
||||
//
|
||||
// We do not hardcode the binary image to keep some flexibility to replace the
|
||||
// icon easily (just by replacing icon.xpm).
|
||||
//
|
||||
// Parameter is not "const char *" because XPM formats are generally stored in a
|
||||
// (non-const) "char *"
|
||||
SDL_Surface *
|
||||
read_xpm(char *xpm[]) {
|
||||
#ifndef NDEBUG
|
||||
// patch the XPM to change the icon color in debug mode
|
||||
xpm[2] = ". c #CC00CC";
|
||||
#endif
|
||||
|
||||
char *endptr;
|
||||
// *** No error handling, assume the XPM source is valid ***
|
||||
// (it's in our source repo)
|
||||
// Assertions are only checked in debug
|
||||
int width = strtol(xpm[0], &endptr, 10);
|
||||
int height = strtol(endptr + 1, &endptr, 10);
|
||||
int colors = strtol(endptr + 1, &endptr, 10);
|
||||
int chars = strtol(endptr + 1, &endptr, 10);
|
||||
|
||||
// sanity checks
|
||||
assert(0 <= width && width < 256);
|
||||
assert(0 <= height && height < 256);
|
||||
assert(0 <= colors && colors < 256);
|
||||
assert(chars == 1); // this implementation does not support more
|
||||
|
||||
(void) chars;
|
||||
|
||||
// init index
|
||||
struct index index[colors];
|
||||
for (int i = 0; i < colors; ++i) {
|
||||
const char *line = xpm[1+i];
|
||||
index[i].c = line[0];
|
||||
assert(line[1] == '\t');
|
||||
assert(line[2] == 'c');
|
||||
assert(line[3] == ' ');
|
||||
if (line[4] == '#') {
|
||||
index[i].color = 0xff000000 | strtol(&line[5], &endptr, 0x10);
|
||||
assert(*endptr == '\0');
|
||||
} else {
|
||||
assert(!strcmp("None", &line[4]));
|
||||
index[i].color = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// parse image
|
||||
uint32_t *pixels = SDL_malloc(4 * width * height);
|
||||
if (!pixels) {
|
||||
LOGE("Could not allocate icon memory");
|
||||
return NULL;
|
||||
}
|
||||
for (int y = 0; y < height; ++y) {
|
||||
const char *line = xpm[1 + colors + y];
|
||||
for (int x = 0; x < width; ++x) {
|
||||
char c = line[x];
|
||||
uint32_t color;
|
||||
bool color_found = find_color(index, colors, c, &color);
|
||||
assert(color_found);
|
||||
(void) color_found;
|
||||
pixels[y * width + x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
uint32_t amask = 0x000000ff;
|
||||
uint32_t rmask = 0x0000ff00;
|
||||
uint32_t gmask = 0x00ff0000;
|
||||
uint32_t bmask = 0xff000000;
|
||||
#else // little endian, like x86
|
||||
uint32_t amask = 0xff000000;
|
||||
uint32_t rmask = 0x00ff0000;
|
||||
uint32_t gmask = 0x0000ff00;
|
||||
uint32_t bmask = 0x000000ff;
|
||||
#endif
|
||||
|
||||
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(pixels,
|
||||
width, height,
|
||||
32, 4 * width,
|
||||
rmask, gmask, bmask, amask);
|
||||
if (!surface) {
|
||||
LOGE("Could not create icon surface");
|
||||
return NULL;
|
||||
}
|
||||
// make the surface own the raw pixels
|
||||
surface->flags &= ~SDL_PREALLOC;
|
||||
return surface;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef TINYXPM_H
|
||||
#define TINYXPM_H
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
SDL_Surface *
|
||||
read_xpm(char *xpm[]);
|
||||
|
||||
#endif
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
BIN
data/icon.png
Normal file
BIN
data/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
@@ -1,5 +1,5 @@
|
||||
project('scrcpy', 'c',
|
||||
version: '1.17',
|
||||
version: '1.16',
|
||||
meson_version: '>= 0.48',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -94,6 +94,7 @@ dist-win32: build-server build-win32
|
||||
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
|
||||
cp data/scrcpy-console.bat "$(DIST)/$(WIN32_TARGET_DIR)"
|
||||
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN32_TARGET_DIR)"
|
||||
cp data/icon.png "$(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,7 +103,7 @@ 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
|
||||
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
|
||||
@@ -110,6 +111,7 @@ dist-win64: build-server build-win64
|
||||
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
|
||||
cp data/scrcpy-console.bat "$(DIST)/$(WIN64_TARGET_DIR)"
|
||||
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN64_TARGET_DIR)"
|
||||
cp data/icon.png "$(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 +120,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)"; \
|
||||
@@ -1,2 +1,2 @@
|
||||
#!/bin/bash
|
||||
make -f release.mk
|
||||
make -f release.make
|
||||
|
||||
4
run
4
run
@@ -20,4 +20,6 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" "$BUILDDIR/app/scrcpy" "$@"
|
||||
SCRCPY_ICON_PATH="data/icon.png" \
|
||||
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \
|
||||
"$BUILDDIR/app/scrcpy" "$@"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user