diff --git a/app/meson.build b/app/meson.build index 1f50209e98..75a2fd7101 100644 --- a/app/meson.build +++ b/app/meson.build @@ -99,9 +99,6 @@ foreach f : check_functions endif endforeach -# expose the build type -conf.set('NDEBUG', get_option('buildtype') != 'debug') - # the version, updated on release conf.set_quoted('SCRCPY_VERSION', meson.project_version()) diff --git a/app/src/cli.c b/app/src/cli.c index fbdef07fb4..acbd280b67 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -667,6 +667,7 @@ guess_record_format(const char *filename) { #define OPT_FORWARD_ALL_CLICKS 1023 #define OPT_LEGACY_PASTE 1024 #define OPT_ENCODER_NAME 1025 +#define OPT_POWER_OFF_ON_CLOSE 1026 bool scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { @@ -717,6 +718,8 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { {"window-height", required_argument, NULL, OPT_WINDOW_HEIGHT}, {"window-borderless", no_argument, NULL, OPT_WINDOW_BORDERLESS}, + {"power-off-on-close", no_argument, NULL, + OPT_POWER_OFF_ON_CLOSE}, {NULL, 0, NULL, 0 }, }; @@ -885,6 +888,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { case OPT_LEGACY_PASTE: opts->legacy_paste = true; break; + case OPT_POWER_OFF_ON_CLOSE: + opts->power_off_on_close = true; + break; default: // getopt prints the error message on stderr return false; diff --git a/app/src/input_manager.c b/app/src/input_manager.c index fd780ae6c3..20ea05c589 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -286,7 +286,7 @@ rotate_client_right(struct screen *screen) { screen_set_rotation(screen, new_rotation); } -void +static void input_manager_process_text_input(struct input_manager *im, const SDL_TextInputEvent *event) { if (is_shortcut_mod(im, SDL_GetModState())) { @@ -366,7 +366,7 @@ convert_input_key(const SDL_KeyboardEvent *from, struct control_msg *to, return true; } -void +static void input_manager_process_key(struct input_manager *im, const SDL_KeyboardEvent *event) { // control: indicates the state of the command-line option --no-control @@ -551,7 +551,7 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen, return true; } -void +static void input_manager_process_mouse_motion(struct input_manager *im, const SDL_MouseMotionEvent *event) { if (!event->state) { @@ -605,7 +605,7 @@ convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen, return true; } -void +static void input_manager_process_touch(struct input_manager *im, const SDL_TouchFingerEvent *event) { struct control_msg msg; @@ -637,7 +637,7 @@ convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen, return true; } -void +static void input_manager_process_mouse_button(struct input_manager *im, const SDL_MouseButtonEvent *event) { bool control = im->control; @@ -736,7 +736,7 @@ convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen, return true; } -void +static void input_manager_process_mouse_wheel(struct input_manager *im, const SDL_MouseWheelEvent *event) { struct control_msg msg; @@ -746,3 +746,46 @@ input_manager_process_mouse_wheel(struct input_manager *im, } } } + +bool +input_manager_handle_event(struct input_manager *im, SDL_Event *event) { + switch (event->type) { + case SDL_TEXTINPUT: + if (!im->control) { + return true; + } + input_manager_process_text_input(im, &event->text); + return true; + case SDL_KEYDOWN: + case SDL_KEYUP: + // some key events do not interact with the device, so process the + // event even if control is disabled + input_manager_process_key(im, &event->key); + return true; + case SDL_MOUSEMOTION: + if (!im->control) { + break; + } + input_manager_process_mouse_motion(im, &event->motion); + return true; + case SDL_MOUSEWHEEL: + if (!im->control) { + break; + } + input_manager_process_mouse_wheel(im, &event->wheel); + return true; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + // some mouse events do not interact with the device, so process + // the event even if control is disabled + input_manager_process_mouse_button(im, &event->button); + return true; + case SDL_FINGERMOTION: + case SDL_FINGERDOWN: + case SDL_FINGERUP: + input_manager_process_touch(im, &event->tfinger); + return true; + } + + return false; +} diff --git a/app/src/input_manager.h b/app/src/input_manager.h index a23a731d24..6acb354d13 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -40,28 +40,7 @@ void input_manager_init(struct input_manager *im, const struct scrcpy_options *options); -void -input_manager_process_text_input(struct input_manager *im, - const SDL_TextInputEvent *event); - -void -input_manager_process_key(struct input_manager *im, - const SDL_KeyboardEvent *event); - -void -input_manager_process_mouse_motion(struct input_manager *im, - const SDL_MouseMotionEvent *event); - -void -input_manager_process_touch(struct input_manager *im, - const SDL_TouchFingerEvent *event); - -void -input_manager_process_mouse_button(struct input_manager *im, - const SDL_MouseButtonEvent *event); - -void -input_manager_process_mouse_wheel(struct input_manager *im, - const SDL_MouseWheelEvent *event); +bool +input_manager_handle_event(struct input_manager *im, SDL_Event *event); #endif diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 505b5eaf1d..3e9095cb5d 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -30,7 +30,7 @@ #include "util/net.h" static struct server server; -static struct screen screen = SCREEN_INITIALIZER; +static struct screen screen; static struct fps_counter fps_counter; static struct video_buffer video_buffer; static struct stream stream; @@ -173,56 +173,6 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) { case SDL_QUIT: LOGD("User requested to quit"); return EVENT_RESULT_STOPPED_BY_USER; - case EVENT_NEW_FRAME: - if (!screen.has_frame) { - screen.has_frame = true; - // this is the very first frame, show the window - screen_show_window(&screen); - } - if (!screen_update_frame(&screen, &video_buffer)) { - return EVENT_RESULT_CONTINUE; - } - break; - case SDL_WINDOWEVENT: - if (screen.has_frame) { - screen_handle_window_event(&screen, &event->window); - } - break; - case SDL_TEXTINPUT: - if (!options->control) { - break; - } - input_manager_process_text_input(&input_manager, &event->text); - break; - case SDL_KEYDOWN: - case SDL_KEYUP: - // some key events do not interact with the device, so process the - // event even if control is disabled - input_manager_process_key(&input_manager, &event->key); - break; - case SDL_MOUSEMOTION: - if (!options->control) { - break; - } - input_manager_process_mouse_motion(&input_manager, &event->motion); - break; - case SDL_MOUSEWHEEL: - if (!options->control) { - break; - } - input_manager_process_mouse_wheel(&input_manager, &event->wheel); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - // some mouse events do not interact with the device, so process - // the event even if control is disabled - input_manager_process_mouse_button(&input_manager, &event->button); - break; - case SDL_FINGERMOTION: - case SDL_FINGERDOWN: - case SDL_FINGERUP: - input_manager_process_touch(&input_manager, &event->tfinger); - break; case SDL_DROPFILE: { if (!options->control) { break; @@ -244,6 +194,16 @@ handle_event(SDL_Event *event, const struct scrcpy_options *options) { break; } } + + bool consumed = screen_handle_event(&screen, event); + if (consumed) { + goto end; + } + + consumed = input_manager_handle_event(&input_manager, event); + (void) consumed; + +end: return EVENT_RESULT_CONTINUE; } @@ -339,6 +299,7 @@ scrcpy(const struct scrcpy_options *options) { .codec_options = options->codec_options, .encoder_name = options->encoder_name, .force_adb_forward = options->force_adb_forward, + .power_off_on_close = options->power_off_on_close, }; if (!server_start(&server, options->serial, ¶ms)) { goto end; @@ -429,6 +390,8 @@ scrcpy(const struct scrcpy_options *options) { const char *window_title = options->window_title ? options->window_title : device_name; + screen_init(&screen, &video_buffer); + if (!screen_init_rendering(&screen, window_title, frame_size, options->always_on_top, options->window_x, options->window_y, options->window_width, diff --git a/app/src/scrcpy.h b/app/src/scrcpy.h index 2253cc284a..1558cfbb8c 100644 --- a/app/src/scrcpy.h +++ b/app/src/scrcpy.h @@ -82,6 +82,7 @@ struct scrcpy_options { bool forward_key_repeat; bool forward_all_clicks; bool legacy_paste; + bool power_off_on_close; }; #define SCRCPY_OPTIONS_DEFAULT { \ @@ -129,6 +130,7 @@ struct scrcpy_options { .forward_key_repeat = true, \ .forward_all_clicks = false, \ .legacy_paste = false, \ + .power_off_on_close = false, \ } bool diff --git a/app/src/screen.c b/app/src/screen.c index 1136d5478e..1174593dfa 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -4,6 +4,7 @@ #include #include +#include "events.h" #include "icon.xpm" #include "scrcpy.h" #include "tiny_xpm.h" @@ -191,8 +192,9 @@ screen_update_content_rect(struct screen *screen) { } void -screen_init(struct screen *screen) { +screen_init(struct screen *screen, struct video_buffer *vb) { *screen = (struct screen) SCREEN_INITIALIZER; + screen->vb = vb; } static inline SDL_Texture * @@ -270,7 +272,7 @@ screen_init_rendering(struct screen *screen, const char *window_title, SDL_RENDERER_ACCELERATED); if (!screen->renderer) { LOGC("Could not create renderer: %s", SDL_GetError()); - screen_destroy(screen); + SDL_DestroyWindow(screen->window); return false; } @@ -318,6 +320,8 @@ screen_init_rendering(struct screen *screen, const char *window_title, screen->texture = create_texture(screen); if (!screen->texture) { LOGC("Could not create texture: %s", SDL_GetError()); + SDL_DestroyRenderer(screen->renderer); + SDL_DestroyWindow(screen->window); screen_destroy(screen); return false; } @@ -342,12 +346,8 @@ screen_destroy(struct screen *screen) { if (screen->texture) { SDL_DestroyTexture(screen->texture); } - if (screen->renderer) { - SDL_DestroyRenderer(screen->renderer); - } - if (screen->window) { - SDL_DestroyWindow(screen->window); - } + SDL_DestroyRenderer(screen->renderer); + SDL_DestroyWindow(screen->window); } static void @@ -450,9 +450,9 @@ update_texture(struct screen *screen, const AVFrame *frame) { } } -bool -screen_update_frame(struct screen *screen, struct video_buffer *vb) { - const AVFrame *frame = video_buffer_take_rendering_frame(vb); +static bool +screen_update_frame(struct screen *screen) { + const AVFrame *frame = video_buffer_take_rendering_frame(screen->vb); struct size new_frame_size = {frame->width, frame->height}; if (!prepare_for_frame(screen, new_frame_size)) { return false; @@ -544,31 +544,52 @@ screen_resize_to_pixel_perfect(struct screen *screen) { content_size.height); } -void -screen_handle_window_event(struct screen *screen, - const SDL_WindowEvent *event) { - switch (event->event) { - case SDL_WINDOWEVENT_EXPOSED: - screen_render(screen, true); - break; - case SDL_WINDOWEVENT_SIZE_CHANGED: - screen_render(screen, true); - break; - case SDL_WINDOWEVENT_MAXIMIZED: - screen->maximized = true; - break; - case SDL_WINDOWEVENT_RESTORED: - if (screen->fullscreen) { - // On Windows, in maximized+fullscreen, disabling fullscreen - // mode unexpectedly triggers the "restored" then "maximized" - // events, leaving the window in a weird state (maximized - // according to the events, but not maximized visually). - break; +bool +screen_handle_event(struct screen *screen, SDL_Event *event) { + switch (event->type) { + case EVENT_NEW_FRAME: + if (!screen->has_frame) { + screen->has_frame = true; + // this is the very first frame, show the window + screen_show_window(screen); } - screen->maximized = false; - apply_pending_resize(screen); - break; + bool ok = screen_update_frame(screen); + if (!ok) { + LOGW("Frame update failed\n"); + } + return true; + case SDL_WINDOWEVENT: + if (!screen->has_frame) { + // Do nothing + return true; + } + switch (event->window.event) { + case SDL_WINDOWEVENT_EXPOSED: + screen_render(screen, true); + break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + screen_render(screen, true); + break; + case SDL_WINDOWEVENT_MAXIMIZED: + screen->maximized = true; + break; + case SDL_WINDOWEVENT_RESTORED: + if (screen->fullscreen) { + // On Windows, in maximized+fullscreen, disabling + // fullscreen mode unexpectedly triggers the "restored" + // then "maximized" events, leaving the window in a + // weird state (maximized according to the events, but + // not maximized visually). + break; + } + screen->maximized = false; + apply_pending_resize(screen); + break; + } + return true; } + + return false; } struct point diff --git a/app/src/screen.h b/app/src/screen.h index 35d5df5055..171717abae 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -13,6 +13,7 @@ struct video_buffer; struct screen { + struct video_buffer *vb; SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *texture; @@ -37,6 +38,7 @@ struct screen { }; #define SCREEN_INITIALIZER { \ + .vb = NULL, \ .window = NULL, \ .renderer = NULL, \ .texture = NULL, \ @@ -70,7 +72,7 @@ struct screen { // initialize default values void -screen_init(struct screen *screen); +screen_init(struct screen *screen, struct video_buffer *vb); // initialize screen, create window, renderer and texture (window is hidden) // window_x and window_y accept SC_WINDOW_POSITION_UNDEFINED @@ -89,10 +91,6 @@ screen_show_window(struct screen *screen); void screen_destroy(struct screen *screen); -// resize if necessary and write the rendered frame into the texture -bool -screen_update_frame(struct screen *screen, struct video_buffer *vb); - // render the texture to the renderer // // Set the update_content_rect flag if the window or content size may have @@ -116,9 +114,9 @@ screen_resize_to_pixel_perfect(struct screen *screen); void screen_set_rotation(struct screen *screen, unsigned rotation); -// react to window events -void -screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event); +// react to SDL events +bool +screen_handle_event(struct screen *screen, SDL_Event *event); // convert point from window coordinates to frame coordinates // x and y are expressed in pixels diff --git a/app/src/server.c b/app/src/server.c index 096ac18fc3..a0b40f965f 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -293,6 +293,7 @@ execute_server(struct server *server, const struct server_params *params) { params->stay_awake ? "true" : "false", params->codec_options ? params->codec_options : "-", params->encoder_name ? params->encoder_name : "-", + params->power_off_on_close ? "true" : "false", }; #ifdef SERVER_DEBUGGER LOGI("Server debugger waiting for a client on device port " diff --git a/app/src/server.h b/app/src/server.h index 83c528efef..15306e4fde 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -46,6 +46,7 @@ struct server_params { bool show_touches; bool stay_awake; bool force_adb_forward; + bool power_off_on_close; }; // init default values diff --git a/meson.build b/meson.build index 230f8d21ce..c2989ec75e 100644 --- a/meson.build +++ b/meson.build @@ -4,6 +4,7 @@ project('scrcpy', 'c', default_options: [ 'c_std=c11', 'warning_level=2', + 'b_ndebug=if-release', ]) if get_option('compile_app') diff --git a/server/src/main/java/com/genymobile/scrcpy/CleanUp.java b/server/src/main/java/com/genymobile/scrcpy/CleanUp.java index efaa059aa8..2601240931 100644 --- a/server/src/main/java/com/genymobile/scrcpy/CleanUp.java +++ b/server/src/main/java/com/genymobile/scrcpy/CleanUp.java @@ -19,19 +19,25 @@ private CleanUp() { // not instantiable } - public static void configure(boolean disableShowTouches, int restoreStayOn, boolean restoreNormalPowerMode) throws IOException { - boolean needProcess = disableShowTouches || restoreStayOn != -1 || restoreNormalPowerMode; + public static void configure(boolean disableShowTouches, + int restoreStayOn, + boolean restoreNormalPowerMode, + boolean powerOffScreen, int displayId) throws IOException { + boolean needProcess = disableShowTouches || restoreStayOn != -1 || restoreNormalPowerMode || powerOffScreen; if (needProcess) { - startProcess(disableShowTouches, restoreStayOn, restoreNormalPowerMode); + startProcess(disableShowTouches, restoreStayOn, restoreNormalPowerMode, powerOffScreen, displayId); } else { // There is no additional clean up to do when scrcpy dies unlinkSelf(); } } - private static void startProcess(boolean disableShowTouches, int restoreStayOn, boolean restoreNormalPowerMode) throws IOException { + private static void startProcess(boolean disableShowTouches, + int restoreStayOn, + boolean restoreNormalPowerMode, + boolean powerOffScreen, int displayId) throws IOException { String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(disableShowTouches), String.valueOf( - restoreStayOn), String.valueOf(restoreNormalPowerMode)}; + restoreStayOn), String.valueOf(restoreNormalPowerMode), String.valueOf(powerOffScreen), String.valueOf(displayId)}; ProcessBuilder builder = new ProcessBuilder(cmd); builder.environment().put("CLASSPATH", SERVER_PATH); @@ -61,6 +67,8 @@ public static void main(String... args) { boolean disableShowTouches = Boolean.parseBoolean(args[0]); int restoreStayOn = Integer.parseInt(args[1]); boolean restoreNormalPowerMode = Boolean.parseBoolean(args[2]); + boolean powerOffScreen = Boolean.parseBoolean(args[3]); + int displayId = Integer.parseInt(args[4]); if (disableShowTouches || restoreStayOn != -1) { ServiceManager serviceManager = new ServiceManager(); @@ -76,9 +84,12 @@ public static void main(String... args) { } } - if (restoreNormalPowerMode) { - Ln.i("Restoring normal power mode"); - if (Device.isScreenOn()) { + if (Device.isScreenOn()) { + if (powerOffScreen) { + Ln.i("Power off screen"); + Device.powerOffScreen(displayId); + } else if (restoreNormalPowerMode) { + Ln.i("Restoring normal power mode"); Device.setScreenPowerMode(Device.POWER_MODE_NORMAL); } } diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index a8fdf677eb..624c9fa0d3 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -153,13 +153,17 @@ public static String getDeviceName() { return Build.MODEL; } + public static boolean supportsInputEvents(int displayId) { + return displayId == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + } + public boolean supportsInputEvents() { return supportsInputEvents; } - public boolean injectEvent(InputEvent inputEvent, int mode) { - if (!supportsInputEvents()) { - throw new AssertionError("Could not inject input event if !supportsInputEvents()"); + public static boolean injectEvent(InputEvent inputEvent, int mode, int displayId) { + if (!supportsInputEvents(displayId)) { + return false; } if (displayId != 0 && !InputManager.setDisplayId(inputEvent, displayId)) { @@ -169,10 +173,29 @@ public boolean injectEvent(InputEvent inputEvent, int mode) { return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, mode); } + public boolean injectEvent(InputEvent inputEvent, int mode) { + if (!supportsInputEvents()) { + throw new AssertionError("Could not inject input event if !supportsInputEvents()"); + } + + return injectEvent(inputEvent, mode, displayId); + } + + public static boolean injectEventOnDisplay(InputEvent event, int displayId) { + return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, displayId); + } + public boolean injectEvent(InputEvent event) { return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); } + public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) { + long now = SystemClock.uptimeMillis(); + KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, + InputDevice.SOURCE_KEYBOARD); + return injectEventOnDisplay(event, displayId); + } + public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) { long now = SystemClock.uptimeMillis(); KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, @@ -180,6 +203,10 @@ public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState return injectEvent(event); } + public static boolean injectKeycode(int keyCode, int displayId) { + return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId); + } + public boolean injectKeycode(int keyCode) { return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0); } @@ -249,6 +276,13 @@ public static boolean setScreenPowerMode(int mode) { return SurfaceControl.setDisplayPowerMode(d, mode); } + public static boolean powerOffScreen(int displayId) { + if (!isScreenOn()) { + return true; + } + return injectKeycode(KeyEvent.KEYCODE_POWER, displayId); + } + /** * Disable auto-rotation (if enabled), set the screen rotation and re-enable auto-rotation (if it was enabled). */ diff --git a/server/src/main/java/com/genymobile/scrcpy/Options.java b/server/src/main/java/com/genymobile/scrcpy/Options.java index 150d06a83d..cf11df0f19 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Options.java +++ b/server/src/main/java/com/genymobile/scrcpy/Options.java @@ -17,6 +17,7 @@ public class Options { private boolean stayAwake; private String codecOptions; private String encoderName; + private boolean powerOffScreenOnClose; public Ln.Level getLogLevel() { return logLevel; @@ -129,4 +130,12 @@ public String getEncoderName() { public void setEncoderName(String encoderName) { this.encoderName = encoderName; } + + public void setPowerOffScreenOnClose(boolean powerOffScreenOnClose) { + this.powerOffScreenOnClose = powerOffScreenOnClose; + } + + public boolean getPowerOffScreenOnClose() { + return this.powerOffScreenOnClose; + } } diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index f58e38674d..289f6a9f71 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -50,7 +50,7 @@ private static void scrcpy(Options options) throws IOException { } } - CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn, true); + CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn, true, options.getPowerOffScreenOnClose(), options.getDisplayId()); boolean tunnelForward = options.isTunnelForward(); @@ -135,7 +135,7 @@ private static Options createOptions(String... args) { "The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")"); } - final int expectedParameters = 15; + final int expectedParameters = 16; if (args.length != expectedParameters) { throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters"); } @@ -185,6 +185,9 @@ private static Options createOptions(String... args) { String encoderName = "-".equals(args[14]) ? null : args[14]; options.setEncoderName(encoderName); + boolean powerOffScreenOnClose = Boolean.parseBoolean(args[15]); + options.setPowerOffScreenOnClose(powerOffScreenOnClose); + return options; }