Add --pause-on-exit

Add an option to make scrcpy pause on exit.

Three behaviors are possible:
 - always pause on exit:
    --pause-on-exit
    --pause-on-exit=true
 - never pause on exit:
    (no option)
    --pause-on-exit=false
 - pause when scrcpy returns with an error (a non-zero exit code):
    --pause-on-exit=if-error

This is useful to prevent the terminal window from automatically
closing, so that error messages can be read.

Refs #3817 <https://github.com/Genymobile/scrcpy/pull/3817>
Refs #3822 <https://github.com/Genymobile/scrcpy/pull/3822>
PR #4130 <https://github.com/Genymobile/scrcpy/pull/4130>
This commit is contained in:
Romain Vimont 2023-06-29 21:36:52 +02:00
parent a7c3c9a54c
commit 1650b7c058
6 changed files with 125 additions and 7 deletions

View File

@ -44,6 +44,8 @@ _scrcpy() {
--no-video-playback
--otg
-p --port=
--pause-on-exit
--pause-on-exit=
--power-off-on-close
--prefer-text
--print-fps
@ -97,6 +99,10 @@ _scrcpy() {
COMPREPLY=($(compgen -W 'unlocked initial 0 1 2 3' -- "$cur"))
return
;;
--pause-on-exit)
COMPREPLY=($(compgen -W 'true false if-error' -- "$cur"))
return
;;
-r|--record)
COMPREPLY=($(compgen -f -- "$cur"))
return

View File

@ -50,6 +50,7 @@ arguments=(
'--no-video-playback[Disable video playback]'
'--otg[Run in OTG mode \(simulating physical keyboard and mouse\)]'
{-p,--port=}'[\[port\[\:port\]\] Set the TCP port \(range\) used by the client to listen]'
'--pause-on-exit=[Make scrcpy pause before exiting]:mode:(true false if-error)'
'--power-off-on-close[Turn the device screen off when closing scrcpy]'
'--prefer-text[Inject alpha characters and space as text events instead of key events]'
'--print-fps[Start FPS counter, to print frame logs to the console]'

View File

@ -267,6 +267,16 @@ Set the TCP port (range) used by the client to listen.
Default is 27183:27199.
.TP
\fB\-\-pause\-on\-exit\fR[=\fImode\fR]
Configure pause on exit. Possible values are "true" (always pause on exit), "false" (never pause on exit) and "if-error" (pause only if an error occured).
This is useful to prevent the terminal window from automatically closing, so that error messages can be read.
Default is "false".
Passing the option without argument is equivalent to passing "true".
.TP
.B \-\-power\-off\-on\-close
Turn the device screen off when closing scrcpy.

View File

@ -79,6 +79,7 @@ enum {
OPT_AUDIO_SOURCE,
OPT_KILL_ADB_ON_CLOSE,
OPT_TIME_LIMIT,
OPT_PAUSE_ON_EXIT,
};
struct sc_option {
@ -463,6 +464,20 @@ static const struct sc_option options[] = {
"Default is " STR(DEFAULT_LOCAL_PORT_RANGE_FIRST) ":"
STR(DEFAULT_LOCAL_PORT_RANGE_LAST) ".",
},
{
.longopt_id = OPT_PAUSE_ON_EXIT,
.longopt = "pause-on-exit",
.argdesc = "mode",
.optional_arg = true,
.text = "Configure pause on exit. Possible values are \"true\" (always "
"pause on exit), \"false\" (never pause on exit) and "
"\"if-error\" (pause only if an error occured).\n"
"This is useful to prevent the terminal window from "
"automatically closing, so that error messages can be read.\n"
"Default is \"false\".\n"
"Passing the option without argument is equivalent to passing "
"\"true\".",
},
{
.longopt_id = OPT_POWER_OFF_ON_CLOSE,
.longopt = "power-off-on-close",
@ -1637,6 +1652,29 @@ parse_time_limit(const char *s, sc_tick *tick) {
return true;
}
static bool
parse_pause_on_exit(const char *s, enum sc_pause_on_exit *pause_on_exit) {
if (!s || !strcmp(s, "true")) {
*pause_on_exit = SC_PAUSE_ON_EXIT_TRUE;
return true;
}
if (!strcmp(s, "false")) {
*pause_on_exit = SC_PAUSE_ON_EXIT_FALSE;
return true;
}
if (!strcmp(s, "if-error")) {
*pause_on_exit = SC_PAUSE_ON_EXIT_IF_ERROR;
return true;
}
LOGE("Unsupported pause on exit mode: %s "
"(expected true, false or if-error)", optarg);
return false;
}
static bool
parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
const char *optstring, const struct option *longopts) {
@ -1977,6 +2015,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return false;
}
break;
case OPT_PAUSE_ON_EXIT:
if (!parse_pause_on_exit(optarg, &args->pause_on_exit)) {
return false;
}
break;
default:
// getopt prints the error message on stderr
return false;
@ -2190,6 +2233,37 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return true;
}
static enum sc_pause_on_exit
sc_get_pause_on_exit(int argc, char *argv[]) {
// Read arguments backwards so that the last --pause-on-exit is considered
// (same behavior as getopt())
for (int i = argc - 1; i >= 1; --i) {
const char *arg = argv[i];
// Starts with "--pause-on-exit"
if (!strncmp("--pause-on-exit", arg, 15)) {
if (arg[15] == '\0') {
// No argument
return SC_PAUSE_ON_EXIT_TRUE;
}
if (arg[15] != '=') {
// Invalid parameter, ignore
return SC_PAUSE_ON_EXIT_FALSE;
}
const char *value = &arg[16];
if (!strcmp(value, "true")) {
return SC_PAUSE_ON_EXIT_TRUE;
}
if (!strcmp(value, "if-error")) {
return SC_PAUSE_ON_EXIT_IF_ERROR;
}
// Set to false, inclusing when the value is invalid
return SC_PAUSE_ON_EXIT_FALSE;
}
}
return false;
}
bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
struct sc_getopt_adapter adapter;
@ -2203,5 +2277,11 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
sc_getopt_adapter_destroy(&adapter);
if (!ret && args->pause_on_exit == SC_PAUSE_ON_EXIT_FALSE) {
// Check if "--pause-on-exit" is present in the arguments list, because
// it must be taken into account even if command line parsing failed
args->pause_on_exit = sc_get_pause_on_exit(argc, argv);
}
return ret;
}

View File

@ -7,10 +7,17 @@
#include "options.h"
enum sc_pause_on_exit {
SC_PAUSE_ON_EXIT_TRUE,
SC_PAUSE_ON_EXIT_FALSE,
SC_PAUSE_ON_EXIT_IF_ERROR,
};
struct scrcpy_cli_args {
struct scrcpy_options opts;
bool help;
bool version;
enum sc_pause_on_exit pause_on_exit;
};
void

View File

@ -39,26 +39,32 @@ main_scrcpy(int argc, char *argv[]) {
.opts = scrcpy_options_default,
.help = false,
.version = false,
.pause_on_exit = SC_PAUSE_ON_EXIT_FALSE,
};
#ifndef NDEBUG
args.opts.log_level = SC_LOG_LEVEL_DEBUG;
#endif
enum scrcpy_exit_code ret;
if (!scrcpy_parse_args(&args, argc, argv)) {
return SCRCPY_EXIT_FAILURE;
ret = SCRCPY_EXIT_FAILURE;
goto end;
}
sc_set_log_level(args.opts.log_level);
if (args.help) {
scrcpy_print_usage(argv[0]);
return SCRCPY_EXIT_SUCCESS;
ret = SCRCPY_EXIT_SUCCESS;
goto end;
}
if (args.version) {
scrcpy_print_version();
return SCRCPY_EXIT_SUCCESS;
ret = SCRCPY_EXIT_SUCCESS;
goto end;
}
#ifdef SCRCPY_LAVF_REQUIRES_REGISTER_ALL
@ -72,18 +78,26 @@ main_scrcpy(int argc, char *argv[]) {
#endif
if (!net_init()) {
return SCRCPY_EXIT_FAILURE;
ret = SCRCPY_EXIT_FAILURE;
goto end;
}
sc_log_configure();
#ifdef HAVE_USB
enum scrcpy_exit_code ret = args.opts.otg ? scrcpy_otg(&args.opts)
: scrcpy(&args.opts);
ret = args.opts.otg ? scrcpy_otg(&args.opts) : scrcpy(&args.opts);
#else
enum scrcpy_exit_code ret = scrcpy(&args.opts);
ret = scrcpy(&args.opts);
#endif
end:
if (args.pause_on_exit == SC_PAUSE_ON_EXIT_TRUE ||
(args.pause_on_exit == SC_PAUSE_ON_EXIT_IF_ERROR &&
ret != SCRCPY_EXIT_SUCCESS)) {
printf("Press Enter to continue...\n");
getchar();
}
return ret;
}