diff --git a/app/src/server.c b/app/src/server.c index 2ea37af6..98f0a188 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -163,7 +163,6 @@ execute_server(struct sc_server *server, cmd[count++] = "/"; // unused cmd[count++] = "com.genymobile.scrcpy.Server"; cmd[count++] = SCRCPY_VERSION; - cmd[count++] = log_level_to_server_string(params->log_level); unsigned dyn_idx = count; // from there, the strings are allocated #define ADD_PARAM(fmt, ...) { \ @@ -175,22 +174,25 @@ execute_server(struct sc_server *server, } #define STRBOOL(v) (v ? "true" : "false") - ADD_PARAM("%" PRIu16, params->max_size); - ADD_PARAM("%" PRIu32, params->bit_rate); - ADD_PARAM("%" PRIu16, params->max_fps); - ADD_PARAM("%" PRIi8, params->lock_video_orientation); - ADD_PARAM("%s", STRBOOL(server->tunnel.forward)); - ADD_PARAM("%s", params->crop ? params->crop : "-"); + ADD_PARAM("log_level=%s", log_level_to_server_string(params->log_level)); + ADD_PARAM("max_size=%" PRIu16, params->max_size); + ADD_PARAM("bit_rate=%" PRIu32, params->bit_rate); + ADD_PARAM("max_fps=%" PRIu16, params->max_fps); + ADD_PARAM("lock_video_orientation=%" PRIi8, params->lock_video_orientation); + ADD_PARAM("tunnel_forward=%s", STRBOOL(server->tunnel.forward)); + ADD_PARAM("crop=%s", params->crop ? params->crop : ""); // always send frame meta (packet boundaries + timestamp) - ADD_PARAM("true"); - ADD_PARAM("%s", STRBOOL(params->control)); - ADD_PARAM("%" PRIu32, params->display_id); - ADD_PARAM("%s", STRBOOL(params->show_touches)); - ADD_PARAM("%s", STRBOOL(params->stay_awake)); - ADD_PARAM("%s", params->codec_options ? params->codec_options : "-"); - ADD_PARAM("%s", params->encoder_name ? params->encoder_name : "-"); - ADD_PARAM("%s", STRBOOL(params->power_off_on_close)); - ADD_PARAM("%s", STRBOOL(params->clipboard_autosync)); + ADD_PARAM("send_frame_meta=true"); + ADD_PARAM("control=%s", STRBOOL(params->control)); + ADD_PARAM("display_id=%" PRIu32, params->display_id); + ADD_PARAM("show_touches=%s", STRBOOL(params->show_touches)); + ADD_PARAM("stay_awake=%s", STRBOOL(params->stay_awake)); + ADD_PARAM("codec_options=%s", + params->codec_options ? params->codec_options : ""); + ADD_PARAM("encoder_name=%s", + params->encoder_name ? params->encoder_name : ""); + ADD_PARAM("power_off_on_close=%s", STRBOOL(params->power_off_on_close)); + ADD_PARAM("clipboard_autosync=%s", STRBOOL(params->clipboard_autosync)); #undef ADD_PARAM #undef STRBOOL diff --git a/server/src/main/java/com/genymobile/scrcpy/CodecOption.java b/server/src/main/java/com/genymobile/scrcpy/CodecOption.java index 1897bda3..12f2a889 100644 --- a/server/src/main/java/com/genymobile/scrcpy/CodecOption.java +++ b/server/src/main/java/com/genymobile/scrcpy/CodecOption.java @@ -21,7 +21,7 @@ public class CodecOption { } public static List parse(String codecOptions) { - if ("-".equals(codecOptions)) { + if (codecOptions.isEmpty()) { return null; } diff --git a/server/src/main/java/com/genymobile/scrcpy/Options.java b/server/src/main/java/com/genymobile/scrcpy/Options.java index 20a579ed..f649d776 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Options.java +++ b/server/src/main/java/com/genymobile/scrcpy/Options.java @@ -5,22 +5,22 @@ import android.graphics.Rect; import java.util.List; public class Options { - private Ln.Level logLevel; + private Ln.Level logLevel = Ln.Level.DEBUG; private int maxSize; - private int bitRate; + private int bitRate = 8000000; private int maxFps; - private int lockedVideoOrientation; + private int lockedVideoOrientation = -1; private boolean tunnelForward; private Rect crop; - private boolean sendFrameMeta; // send PTS so that the client may record properly - private boolean control; + private boolean sendFrameMeta = true; // send PTS so that the client may record properly + private boolean control = true; private int displayId; private boolean showTouches; private boolean stayAwake; private List codecOptions; private String encoderName; private boolean powerOffScreenOnClose; - private boolean clipboardAutosync; + private boolean clipboardAutosync = true; public Ln.Level getLogLevel() { return logLevel; diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index bcdaf6bb..71920627 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -160,67 +160,93 @@ public final class Server { "The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")"); } - final int expectedParameters = 17; - if (args.length != expectedParameters) { - throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters"); - } - Options options = new Options(); - Ln.Level level = Ln.Level.valueOf(args[1].toUpperCase(Locale.ENGLISH)); - options.setLogLevel(level); - - int maxSize = Integer.parseInt(args[2]) & ~7; // multiple of 8 - options.setMaxSize(maxSize); - - int bitRate = Integer.parseInt(args[3]); - options.setBitRate(bitRate); - - int maxFps = Integer.parseInt(args[4]); - options.setMaxFps(maxFps); - - int lockedVideoOrientation = Integer.parseInt(args[5]); - options.setLockedVideoOrientation(lockedVideoOrientation); - - // use "adb forward" instead of "adb tunnel"? (so the server must listen) - boolean tunnelForward = Boolean.parseBoolean(args[6]); - options.setTunnelForward(tunnelForward); - - Rect crop = parseCrop(args[7]); - options.setCrop(crop); - - boolean sendFrameMeta = Boolean.parseBoolean(args[8]); - options.setSendFrameMeta(sendFrameMeta); - - boolean control = Boolean.parseBoolean(args[9]); - options.setControl(control); - - int displayId = Integer.parseInt(args[10]); - options.setDisplayId(displayId); - - boolean showTouches = Boolean.parseBoolean(args[11]); - options.setShowTouches(showTouches); - - boolean stayAwake = Boolean.parseBoolean(args[12]); - options.setStayAwake(stayAwake); - - List codecOptions = CodecOption.parse(args[13]); - options.setCodecOptions(codecOptions); - - String encoderName = "-".equals(args[14]) ? null : args[14]; - options.setEncoderName(encoderName); - - boolean powerOffScreenOnClose = Boolean.parseBoolean(args[15]); - options.setPowerOffScreenOnClose(powerOffScreenOnClose); - - boolean clipboardAutosync = Boolean.parseBoolean(args[16]); - options.setClipboardAutosync(clipboardAutosync); + for (int i = 1; i < args.length; ++i) { + String arg = args[i]; + int equalIndex = arg.indexOf('='); + if (equalIndex == -1) { + throw new IllegalArgumentException("Invalid key=value pair: \"" + arg + "\""); + } + String key = arg.substring(0, equalIndex); + String value = arg.substring(equalIndex + 1); + switch (key) { + case "log_level": + Ln.Level level = Ln.Level.valueOf(value.toUpperCase(Locale.ENGLISH)); + options.setLogLevel(level); + break; + case "max_size": + int maxSize = Integer.parseInt(value) & ~7; // multiple of 8 + options.setMaxSize(maxSize); + break; + case "bit_rate": + int bitRate = Integer.parseInt(value); + options.setBitRate(bitRate); + break; + case "max_fps": + int maxFps = Integer.parseInt(value); + options.setMaxFps(maxFps); + break; + case "lock_video_orientation": + int lockedVideoOrientation = Integer.parseInt(value); + options.setLockedVideoOrientation(lockedVideoOrientation); + break; + case "tunnel_forward": + boolean tunnelForward = Boolean.parseBoolean(value); + options.setTunnelForward(tunnelForward); + break; + case "crop": + Rect crop = parseCrop(value); + options.setCrop(crop); + break; + case "send_frame_meta": + boolean sendFrameMeta = Boolean.parseBoolean(value); + options.setSendFrameMeta(sendFrameMeta); + break; + case "control": + boolean control = Boolean.parseBoolean(value); + options.setControl(control); + break; + case "display_id": + int displayId = Integer.parseInt(value); + options.setDisplayId(displayId); + break; + case "show_touches": + boolean showTouches = Boolean.parseBoolean(value); + options.setShowTouches(showTouches); + break; + case "stay_awake": + boolean stayAwake = Boolean.parseBoolean(value); + options.setStayAwake(stayAwake); + break; + case "codec_options": + List codecOptions = CodecOption.parse(value); + options.setCodecOptions(codecOptions); + break; + case "encoder_name": + if (!value.isEmpty()) { + options.setEncoderName(value); + } + break; + case "power_off_on_close": + boolean powerOffScreenOnClose = Boolean.parseBoolean(value); + options.setPowerOffScreenOnClose(powerOffScreenOnClose); + break; + case "clipboard_autosync": + boolean clipboardAutosync = Boolean.parseBoolean(value); + options.setClipboardAutosync(clipboardAutosync); + break; + default: + Ln.w("Unknown server option: " + key); + break; + } + } return options; } private static Rect parseCrop(String crop) { - if ("-".equals(crop)) { + if (crop.isEmpty()) { return null; } // input format: "width:height:x:y"