From 1d713d759850f4b5de8525cfb73c338be8fef94e Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sat, 14 Sep 2024 14:32:32 +0200 Subject: [PATCH] Do not parse --max-fps float in the client Many parsing and formatting C functions like strtof() and asprintf() are locale-dependent. Forcing a C locale just for the conversions in a way that works on all platforms is a mess. In practice, this is not a problem, scrcpy always uses the C locale, because it never calls: setlocale(LC_ALL, ""); But the max-fps option should not depend on the locale configuration anyway. Since the value is parsed by the client in Java anyway, just forward the string value as is. --- app/src/cli.c | 36 +----------------------------------- app/src/options.c | 2 +- app/src/options.h | 2 +- app/src/server.c | 3 ++- app/src/server.h | 2 +- app/src/util/str.c | 19 ------------------- app/src/util/str.h | 8 -------- app/tests/test_cli.c | 2 +- 8 files changed, 7 insertions(+), 67 deletions(-) diff --git a/app/src/cli.c b/app/src/cli.c index e2ae4804..e34987f3 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -1447,26 +1447,6 @@ parse_integers_arg(const char *s, const char sep, size_t max_items, long *out, return count; } -static bool -parse_float_arg(const char *s, float *out, float min, float max, - const char *name) { - float value; - bool ok = sc_str_parse_float(s, &value); - if (!ok) { - LOGE("Could not parse %s: %s", name, s); - return false; - } - - if (value < min || value > max) { - LOGE("Could not parse %s: value (%f) out-of-range (%f; %f)", - name, value, min, max); - return false; - } - - *out = value; - return true; -} - static bool parse_bit_rate(const char *s, uint32_t *bit_rate) { long value; @@ -1493,18 +1473,6 @@ parse_max_size(const char *s, uint16_t *max_size) { return true; } -static bool -parse_max_fps(const char *s, float *max_fps) { - float value; - bool ok = parse_float_arg(s, &value, 0, (float) (1 << 16), "max fps"); - if (!ok) { - return false; - } - - *max_fps = value; - return true; -} - static bool parse_buffering_time(const char *s, sc_tick *tick) { long value; @@ -2252,9 +2220,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], "--keyboard=uhid instead."); return false; case OPT_MAX_FPS: - if (!parse_max_fps(optarg, &opts->max_fps)) { - return false; - } + opts->max_fps = optarg; break; case 'm': if (!parse_max_size(optarg, &opts->max_size)) { diff --git a/app/src/options.c b/app/src/options.c index 6fca6ad5..b876b660 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -48,7 +48,7 @@ const struct scrcpy_options scrcpy_options_default = { .max_size = 0, .video_bit_rate = 0, .audio_bit_rate = 0, - .max_fps = 0, + .max_fps = NULL, .lock_video_orientation = SC_LOCK_VIDEO_ORIENTATION_UNLOCKED, .display_orientation = SC_ORIENTATION_0, .record_orientation = SC_ORIENTATION_0, diff --git a/app/src/options.h b/app/src/options.h index ee0be00a..6e77c175 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -240,7 +240,7 @@ struct scrcpy_options { uint16_t max_size; uint32_t video_bit_rate; uint32_t audio_bit_rate; - float max_fps; + const char *max_fps; // float to be parsed by the server enum sc_lock_video_orientation lock_video_orientation; enum sc_orientation display_orientation; enum sc_orientation record_orientation; diff --git a/app/src/server.c b/app/src/server.c index 320062a4..2dc00144 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -321,7 +321,8 @@ execute_server(struct sc_server *server, ADD_PARAM("max_size=%" PRIu16, params->max_size); } if (params->max_fps) { - ADD_PARAM("max_fps=%f" , params->max_fps); + VALIDATE_STRING(params->max_fps); + ADD_PARAM("max_fps=%s", params->max_fps); } if (params->lock_video_orientation != SC_LOCK_VIDEO_ORIENTATION_UNLOCKED) { ADD_PARAM("lock_video_orientation=%" PRIi8, diff --git a/app/src/server.h b/app/src/server.h index 81e8e05b..d9d42582 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -44,7 +44,7 @@ struct sc_server_params { uint16_t max_size; uint32_t video_bit_rate; uint32_t audio_bit_rate; - float max_fps; + const char *max_fps; // float to be parsed by the server int8_t lock_video_orientation; bool control; uint32_t display_id; diff --git a/app/src/util/str.c b/app/src/util/str.c index 7ca880d7..755369d8 100644 --- a/app/src/util/str.c +++ b/app/src/util/str.c @@ -147,25 +147,6 @@ sc_str_parse_integer_with_suffix(const char *s, long *out) { return true; } -bool -sc_str_parse_float(const char *s, float *out) { - char *endptr; - if (*s == '\0') { - return false; - } - errno = 0; - float value = strtof(s, &endptr); - if (errno == ERANGE) { - return false; - } - if (*endptr != '\0') { - return false; - } - - *out = value; - return true; -} - bool sc_str_list_contains(const char *list, char sep, const char *s) { char *p; diff --git a/app/src/util/str.h b/app/src/util/str.h index 98cb1d74..20da26f0 100644 --- a/app/src/util/str.h +++ b/app/src/util/str.h @@ -66,14 +66,6 @@ sc_str_parse_integers(const char *s, const char sep, size_t max_items, bool sc_str_parse_integer_with_suffix(const char *s, long *out); -/** - * `Parse `s` as a float into `out` - * - * Return true if the conversion succeeded, false otherwise. - */ -bool -sc_str_parse_float(const char *s, float *out); - /** * Search `s` in the list separated by `sep` * diff --git a/app/tests/test_cli.c b/app/tests/test_cli.c index cef8df3e..14765792 100644 --- a/app/tests/test_cli.c +++ b/app/tests/test_cli.c @@ -78,7 +78,7 @@ static void test_options(void) { assert(opts->video_bit_rate == 5000000); assert(!strcmp(opts->crop, "100:200:300:400")); assert(opts->fullscreen); - assert(opts->max_fps == 30); + assert(!strcmp(opts->max_fps, "30")); assert(opts->max_size == 1024); assert(opts->lock_video_orientation == 2); assert(opts->port_range.first == 1234);