Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/data/bash-completion/scrcpy
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ _scrcpy() {
--camera-fps=
--camera-high-speed
--camera-size=
--camera-zoom-step=
--camera-torch
--capture-orientation=
--crop=
-d --select-usb
Expand Down Expand Up @@ -197,6 +199,8 @@ _scrcpy() {
|--camera-id \
|--camera-fps \
|--camera-size \
|--camera-zoom-step \
|--camera-torch \
|--crop \
|--display-id \
|--max-fps \
Expand Down
2 changes: 2 additions & 0 deletions app/data/zsh-completion/_scrcpy
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ arguments=(
'--camera-facing=[Select the device camera by its facing direction]:facing:(front back external)'
'--camera-fps=[Specify the camera capture frame rate]'
'--camera-size=[Specify an explicit camera capture size]'
'--camera-zoom-step=[Specify the camera zoom step value]'
'--camera-torch[Turns the torch on when starting the camera]'
'--capture-orientation=[Set the capture video orientation]:orientation:(0 90 180 270 flip0 flip90 flip180 flip270 @0 @90 @180 @270 @flip0 @flip90 @flip180 @flip270)'
'--crop=[\[width\:height\:x\:y\] Crop the device screen on the server]'
{-d,--select-usb}'[Use USB device]'
Expand Down
1 change: 1 addition & 0 deletions app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ src = [
'src/hid/hid_gamepad.c',
'src/hid/hid_keyboard.c',
'src/hid/hid_mouse.c',
'src/im/camera.c',
'src/trait/frame_source.c',
'src/trait/packet_source.c',
'src/uhid/gamepad_uhid.c',
Expand Down
10 changes: 10 additions & 0 deletions app/scrcpy.1
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ The available camera ids can be listed by \fB\-\-list\-cameras\fR.
.BI "\-\-camera\-size " width\fRx\fIheight
Specify an explicit camera capture size.

.TP
.BI \-\-camera\-torch
Turns the torch on when starting the camera.

.TP
.BI "\-\-camera\-zoom\-step " step
Specify the camera zoom step value.

Default is 0.025.

.TP
.BI "\-\-capture\-orientation " value
Possible values are 0, 90, 180, 270, flip0, flip90, flip180 and flip270, possibly prefixed by '@'.
Expand Down
36 changes: 31 additions & 5 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ enum {
OPT_CAMERA_AR,
OPT_CAMERA_FPS,
OPT_CAMERA_HIGH_SPEED,
OPT_CAMERA_ZOOM_STEP,
OPT_CAMERA_TORCH,
OPT_DISPLAY_ORIENTATION,
OPT_RECORD_ORIENTATION,
OPT_ORIENTATION,
Expand Down Expand Up @@ -563,6 +565,17 @@ static const struct sc_option options[] = {
.text = "Limit the frame rate of screen capture (officially supported "
"since Android 10, but may work on earlier versions).",
},
{
.longopt_id = OPT_CAMERA_ZOOM_STEP,
.longopt = "camera-zoom-step",
.argdesc = "value",
.text = "Specify the camera zoom step value.",
},
{
.longopt_id = OPT_CAMERA_TORCH,
.longopt = "camera-torch",
.text = "Turns the torch on when starting the camera.",
},
{
.longopt_id = OPT_MOUSE,
.longopt = "mouse",
Expand Down Expand Up @@ -1142,6 +1155,18 @@ static const struct sc_shortcut shortcuts[] = {
.shortcuts = { "Right-click (when screen is off)" },
.text = "Power on",
},
{
.shortcuts = { "MOD+q" },
.text = "Camera toggle torch",
},
{
.shortcuts = { "MOD+1" },
.text = "Camera zoom in",
},
{
.shortcuts = { "MOD+2" },
.text = "Camera zoom out",
},
{
.shortcuts = { "MOD+o" },
.text = "Turn device screen off (keep mirroring)",
Expand Down Expand Up @@ -2420,6 +2445,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case OPT_MAX_FPS:
opts->max_fps = optarg;
break;
case OPT_CAMERA_ZOOM_STEP:
opts->camera_zoom_step = optarg;
break;
case OPT_CAMERA_TORCH:
opts->camera_torch = true;
break;
case 'm':
if (!parse_max_size(optarg, &opts->max_size)) {
return false;
Expand Down Expand Up @@ -3104,11 +3135,6 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
LOGE("--camera-high-speed requires an explicit --camera-fps value");
return false;
}

if (opts->control) {
LOGI("Camera video source: control disabled");
opts->control = false;
}
} else if (opts->camera_id
|| opts->camera_ar
|| opts->camera_facing != SC_CAMERA_FACING_ANY
Expand Down
12 changes: 12 additions & 0 deletions app/src/control_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) {
case SC_CONTROL_MSG_TYPE_COLLAPSE_PANELS:
case SC_CONTROL_MSG_TYPE_ROTATE_DEVICE:
case SC_CONTROL_MSG_TYPE_OPEN_HARD_KEYBOARD_SETTINGS:
case SC_CONTROL_MSG_TYPE_CAMERA_TOGGLE_TORCH:
case SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_IN:
case SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_OUT:
case SC_CONTROL_MSG_TYPE_RESET_VIDEO:
// no additional data
return 1;
Expand Down Expand Up @@ -318,6 +321,15 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
case SC_CONTROL_MSG_TYPE_RESET_VIDEO:
LOG_CMSG("reset video");
break;
case SC_CONTROL_MSG_TYPE_CAMERA_TOGGLE_TORCH:
LOG_CMSG("toggle camera torch");
break;
case SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_IN:
LOG_CMSG("camera zoom in");
break;
case SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_OUT:
LOG_CMSG("camera zoom out");
break;
default:
LOG_CMSG("unknown type: %u", (unsigned) msg->type);
break;
Expand Down
3 changes: 3 additions & 0 deletions app/src/control_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ enum sc_control_msg_type {
SC_CONTROL_MSG_TYPE_OPEN_HARD_KEYBOARD_SETTINGS,
SC_CONTROL_MSG_TYPE_START_APP,
SC_CONTROL_MSG_TYPE_RESET_VIDEO,
SC_CONTROL_MSG_TYPE_CAMERA_TOGGLE_TORCH,
SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_IN,
SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_OUT,
};

enum sc_copy_key {
Expand Down
193 changes: 193 additions & 0 deletions app/src/im/camera.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#include "input_manager.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <SDL2/SDL.h>

#include "android/input.h"
#include "android/keycodes.h"
#include "input_events.h"
#include "screen.h"
#include "shortcut_mod.h"
#include "util/log.h"
#include "camera.h"

static void
camera_toggle_torch(struct sc_input_manager *im) {
assert(im->controller);

struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_CAMERA_TOGGLE_TORCH;

if (!sc_controller_push_msg(im->controller, &msg)) {
LOGW("Could not request camera toggle torch");
}
}

static void
camera_zoom_in(struct sc_input_manager *im) {
assert(im->controller);

struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_IN;

if (!sc_controller_push_msg(im->controller, &msg)) {
LOGW("Could not request camera zoom in");
}
}

static void
camera_zoom_out(struct sc_input_manager *im) {
assert(im->controller);

struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_CAMERA_ZOOM_OUT;

if (!sc_controller_push_msg(im->controller, &msg)) {
LOGW("Could not request camera zoom out");
}
}

static void
reset_video(struct sc_input_manager *im) {
assert(im->controller);

struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_RESET_VIDEO;

if (!sc_controller_push_msg(im->controller, &msg)) {
LOGW("Could not request reset video");
}
}

static void
apply_orientation_transform(struct sc_input_manager *im,
enum sc_orientation transform) {
struct sc_screen *screen = im->screen;
enum sc_orientation new_orientation =
sc_orientation_apply(screen->orientation, transform);
sc_screen_set_orientation(screen, new_orientation);
}

static void
sc_input_manager_process_key_camera(struct sc_input_manager *im,
const SDL_KeyboardEvent *event) {
bool control = im->controller;
bool paused = im->screen->paused;
bool video = im->screen->video;

SDL_Keycode sdl_keycode = event->keysym.sym;
uint16_t mod = event->keysym.mod;
bool down = event->type == SDL_KEYDOWN;
bool shift = event->keysym.mod & KMOD_SHIFT;
bool repeat = event->repeat;

uint16_t mods = im->sdl_shortcut_mods;
bool is_shortcut = sc_shortcut_mods_is_shortcut_mod(mods, mod)
|| sc_shortcut_mods_is_shortcut_key(mods, sdl_keycode);

if (down && !repeat) {
if (sdl_keycode == im->last_keycode && mod == im->last_mod) {
++im->key_repeat;
} else {
im->key_repeat = 0;
im->last_keycode = sdl_keycode;
im->last_mod = mod;
}
}

if (is_shortcut) {
switch (sdl_keycode) {
// Camera
case SDLK_1:
if (control && video && !shift && down) {
camera_zoom_in(im);
}
return;
case SDLK_2:
if (control && video && !shift && down) {
camera_zoom_out(im);
}
return;
case SDLK_q:
if (control && video && !shift && !repeat && down) {
camera_toggle_torch(im);
}
return;
// Window
case SDLK_f:
if (video && !shift && !repeat && down) {
sc_screen_toggle_fullscreen(im->screen);
}
return;
case SDLK_w:
if (video && !shift && !repeat && down) {
sc_screen_resize_to_fit(im->screen);
}
return;
case SDLK_g:
if (video && !shift && !repeat && down) {
sc_screen_resize_to_pixel_perfect(im->screen);
}
return;
case SDLK_DOWN:
if (shift) {
if (video && !repeat && down) {
apply_orientation_transform(im,
SC_ORIENTATION_FLIP_180);
}
}
return;
case SDLK_UP:
if (shift) {
if (video && !repeat && down) {
apply_orientation_transform(im,
SC_ORIENTATION_FLIP_180);
}
}
return;
case SDLK_LEFT:
if (video && !repeat && down) {
if (shift) {
apply_orientation_transform(im,
SC_ORIENTATION_FLIP_0);
} else {
apply_orientation_transform(im,
SC_ORIENTATION_270);
}
}
return;
case SDLK_RIGHT:
if (video && !repeat && down) {
if (shift) {
apply_orientation_transform(im,
SC_ORIENTATION_FLIP_0);
} else {
apply_orientation_transform(im,
SC_ORIENTATION_90);
}
}
return;
// Video
case SDLK_r:
if (control && !repeat && down && !paused) {
if (shift) {
reset_video(im);
}
}
return;
}
}
}

void
sc_input_manager_handle_event_camera(struct sc_input_manager *im,
const SDL_Event *event) {
switch (event->type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
sc_input_manager_process_key_camera(im, &event->key);
break;
}
}
11 changes: 11 additions & 0 deletions app/src/im/camera.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef SC_CAMERA_H
#define SC_CAMERA_H

#include "input_manager.h"

#include <SDL2/SDL_events.h>

void sc_input_manager_handle_event_camera(struct sc_input_manager *im,
const SDL_Event *event);

#endif
2 changes: 2 additions & 0 deletions app/src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const struct scrcpy_options scrcpy_options_default = {
.video_bit_rate = 0,
.audio_bit_rate = 0,
.max_fps = NULL,
.camera_zoom_step = NULL,
.camera_torch = false,
.capture_orientation = SC_ORIENTATION_0,
.capture_orientation_lock = SC_ORIENTATION_UNLOCKED,
.display_orientation = SC_ORIENTATION_0,
Expand Down
2 changes: 2 additions & 0 deletions app/src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ struct scrcpy_options {
uint32_t audio_bit_rate;
const char *max_fps; // float to be parsed by the server
const char *angle; // float to be parsed by the server
const char *camera_zoom_step; // float to be parsed by the server
enum sc_orientation capture_orientation;
enum sc_orientation_lock capture_orientation_lock;
enum sc_orientation display_orientation;
Expand Down Expand Up @@ -314,6 +315,7 @@ struct scrcpy_options {
bool require_audio;
bool kill_adb_on_close;
bool camera_high_speed;
bool camera_torch;
#define SC_OPTION_LIST_ENCODERS 0x1
#define SC_OPTION_LIST_DISPLAYS 0x2
#define SC_OPTION_LIST_CAMERAS 0x4
Expand Down
Loading