Compare commits

...

5 Commits

Author SHA1 Message Date
Romain Vimont
9497f39fb4 Do not fail if SDL_INIT_VIDEO fails without video
The SDL video subsystem may be initialized so that clipboard
synchronization works even without video playback.

But if the video subsystem initialization fails (e.g. because no video
device is available), consider it as an error only if video playback is
enabled.

Refs 5e59ed3135
Fixes #4477 <https://github.com/Genymobile/scrcpy/issues/4477>
2023-11-29 12:16:05 +01:00
Romain Vimont
bf056b1fee Do not initialize SDL video when not necessary
The SDL video subsystem is required for video playback and clipboard
synchronization.

If neither is used, it is not necessary to initialize it.

Refs 5e59ed3135
Refs 110b3a16f6
Refs #4418 <https://github.com/Genymobile/scrcpy/issues/4418>
Refs #4477 <https://github.com/Genymobile/scrcpy/issues/4477>
2023-11-29 12:14:07 +01:00
Romain Vimont
140a49b8be Add workaround for Samsung devices issues
On some Samsung devices, DisplayManagerGlobal.getDisplayInfoLocked()
calls ActivityThread.currentActivityThread().getConfiguration(), which
requires a non-null ConfigurationController.

Fixes <https://github.com/Genymobile/scrcpy/issues/4467>
2023-11-27 09:29:06 +01:00
Romain Vimont
4135c411af Fix compilation error
Fix the following warning/error:

    ../app/src/cli.c:2158:17: warning: a label can only be part of a
    statement and a declaration is not a statement [-Wpedantic]

With some compilers, this is an error rather than a pedantic warning.

Refs <https://github.com/Genymobile/scrcpy/issues/2256#issuecomment-1467008307>
2023-11-25 23:56:46 +01:00
Romain Vimont
5e061636f6 Update links to v2.3 2023-11-25 22:15:07 +01:00
7 changed files with 60 additions and 21 deletions

View File

@@ -1,4 +1,4 @@
# scrcpy (v2.2) # scrcpy (v2.3)
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" /> <img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />

View File

@@ -2154,7 +2154,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return false; return false;
} }
break; break;
case OPT_ORIENTATION: case OPT_ORIENTATION: {
enum sc_orientation orientation; enum sc_orientation orientation;
if (!parse_orientation(optarg, &orientation)) { if (!parse_orientation(optarg, &orientation)) {
return false; return false;
@@ -2162,6 +2162,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
opts->display_orientation = orientation; opts->display_orientation = orientation;
opts->record_orientation = orientation; opts->record_orientation = orientation;
break; break;
}
case OPT_RENDER_DRIVER: case OPT_RENDER_DRIVER:
opts->render_driver = optarg; opts->render_driver = optarg;
break; break;

View File

@@ -419,12 +419,21 @@ scrcpy(struct scrcpy_options *options) {
sdl_set_hints(options->render_driver); sdl_set_hints(options->render_driver);
} }
// Initialize the video subsystem even if --no-video or --no-video-playback if (options->video_playback ||
// is passed so that clipboard synchronization still works. (options->control && options->clipboard_autosync)) {
// <https://github.com/Genymobile/scrcpy/issues/4418> // Initialize the video subsystem even if --no-video or
if (SDL_Init(SDL_INIT_VIDEO)) { // --no-video-playback is passed so that clipboard synchronization
LOGE("Could not initialize SDL video: %s", SDL_GetError()); // still works.
goto end; // <https://github.com/Genymobile/scrcpy/issues/4418>
if (SDL_Init(SDL_INIT_VIDEO)) {
// If it fails, it is an error only if video playback is enabled
if (options->video_playback) {
LOGE("Could not initialize SDL video: %s", SDL_GetError());
goto end;
} else {
LOGW("Could not initialize SDL video: %s", SDL_GetError());
}
}
} }
if (options->audio_playback) { if (options->audio_playback) {

View File

@@ -233,10 +233,10 @@ install` must be run as root)._
#### Option 2: Use prebuilt server #### Option 2: Use prebuilt server
- [`scrcpy-server-v2.2`][direct-scrcpy-server] - [`scrcpy-server-v2.3`][direct-scrcpy-server]
<sub>SHA-256: `c85c4aa84305efb69115cd497a120ebdd10258993b4cf123a8245b3d99d49874`</sub> <sub>SHA-256: `8daed514d7796fca6987dc973e201bd15ba51d0f7258973dec92d9ded00dbd5f`</sub>
[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.2/scrcpy-server-v2.2 [direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v2.3/scrcpy-server-v2.3
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:

View File

@@ -4,14 +4,14 @@
Download the [latest release]: Download the [latest release]:
- [`scrcpy-win64-v2.2.zip`][direct-win64] (64-bit) - [`scrcpy-win64-v2.3.zip`][direct-win64] (64-bit)
<sub>SHA-256: `9f9da88ac4c8319dcb9bf852f2d9bba942bac663413383419cddf64eaa5685bd`</sub> <sub>SHA-256: `a2fdd2733bd337261bb493e77d990078a23e7a40149dd0c0dc45725c929a715f`</sub>
- [`scrcpy-win32-v2.2.zip`][direct-win32] (32-bit) - [`scrcpy-win32-v2.3.zip`][direct-win32] (32-bit)
<sub>SHA-256: `cb84269fc847b8b880e320879492a1ae6c017b42175f03e199530f7a53be9d74`</sub> <sub>SHA-256: `dfdbb69a872d717aed5bcfe352e571564c357fdb7a9c172d69f450fdf5154a0a`</sub>
[latest release]: https://github.com/Genymobile/scrcpy/releases/latest [latest release]: https://github.com/Genymobile/scrcpy/releases/latest
[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.2/scrcpy-win64-v2.2.zip [direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v2.3/scrcpy-win64-v2.3.zip
[direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.2/scrcpy-win32-v2.2.zip [direct-win32]: https://github.com/Genymobile/scrcpy/releases/download/v2.3/scrcpy-win32-v2.3.zip
and extract it. and extract it.

View File

@@ -2,8 +2,8 @@
set -e set -e
BUILDDIR=build-auto BUILDDIR=build-auto
PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.2/scrcpy-server-v2.2 PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v2.3/scrcpy-server-v2.3
PREBUILT_SERVER_SHA256=c85c4aa84305efb69115cd497a120ebdd10258993b4cf123a8245b3d99d49874 PREBUILT_SERVER_SHA256=8daed514d7796fca6987dc973e201bd15ba51d0f7258973dec92d9ded00dbd5f
echo "[scrcpy] Downloading prebuilt server..." echo "[scrcpy] Downloading prebuilt server..."
wget "$PREBUILT_SERVER_URL" -O scrcpy-server wget "$PREBUILT_SERVER_URL" -O scrcpy-server

View File

@@ -49,6 +49,7 @@ public final class Workarounds {
} }
public static void apply(boolean audio, boolean camera) { public static void apply(boolean audio, boolean camera) {
boolean mustFillConfigurationController = false;
boolean mustFillAppInfo = false; boolean mustFillAppInfo = false;
boolean mustFillAppContext = false; boolean mustFillAppContext = false;
@@ -85,11 +86,23 @@ public final class Workarounds {
mustFillAppContext = true; mustFillAppContext = true;
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// On some Samsung devices, DisplayManagerGlobal.getDisplayInfoLocked() calls ActivityThread.currentActivityThread().getConfiguration(),
// which requires a non-null ConfigurationController.
// ConfigurationController was introduced in Android 12, so do not attempt to set it on lower versions.
// <https://github.com/Genymobile/scrcpy/issues/4467>
mustFillConfigurationController = true;
}
if (mustFillConfigurationController) {
// Must be call before fillAppContext() because it is necessary to get a valid system context
fillConfigurationController();
}
if (mustFillAppInfo) { if (mustFillAppInfo) {
Workarounds.fillAppInfo(); fillAppInfo();
} }
if (mustFillAppContext) { if (mustFillAppContext) {
Workarounds.fillAppContext(); fillAppContext();
} }
} }
@@ -149,6 +162,22 @@ public final class Workarounds {
} }
} }
private static void fillConfigurationController() {
try {
Class<?> configurationControllerClass = Class.forName("android.app.ConfigurationController");
Class<?> activityThreadInternalClass = Class.forName("android.app.ActivityThreadInternal");
Constructor<?> configurationControllerConstructor = configurationControllerClass.getDeclaredConstructor(activityThreadInternalClass);
configurationControllerConstructor.setAccessible(true);
Object configurationController = configurationControllerConstructor.newInstance(ACTIVITY_THREAD);
Field configurationControllerField = ACTIVITY_THREAD_CLASS.getDeclaredField("mConfigurationController");
configurationControllerField.setAccessible(true);
configurationControllerField.set(ACTIVITY_THREAD, configurationController);
} catch (Throwable throwable) {
Ln.d("Could not fill configuration: " + throwable.getMessage());
}
}
static Context getSystemContext() { static Context getSystemContext() {
try { try {
Method getSystemContextMethod = ACTIVITY_THREAD_CLASS.getDeclaredMethod("getSystemContext"); Method getSystemContextMethod = ACTIVITY_THREAD_CLASS.getDeclaredMethod("getSystemContext");