-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client orientation (resolves #218) #1151
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,12 @@ scrcpy_print_usage(const char *arg0) { | |
" is preserved.\n" | ||
" Default is %d%s.\n" | ||
"\n" | ||
" -o, --orientation value\n" | ||
" Lock client orientation to value. Values are integers in the\n" | ||
" range [0..3]. Natural device orientation is 0 and each\n" | ||
" increment adds 90 degrees.\n" | ||
" Default is %d%s.\n" | ||
"\n" | ||
" -n, --no-control\n" | ||
" Disable device control (mirror the device in read-only).\n" | ||
"\n" | ||
|
@@ -193,6 +199,7 @@ scrcpy_print_usage(const char *arg0) { | |
arg0, | ||
DEFAULT_BIT_RATE, | ||
DEFAULT_MAX_SIZE, DEFAULT_MAX_SIZE ? "" : " (unlimited)", | ||
DEFAULT_ORIENTATION, DEFAULT_ORIENTATION >= 0 ? "" : " (unlocked)", | ||
DEFAULT_LOCAL_PORT); | ||
} | ||
|
||
|
@@ -259,6 +266,19 @@ parse_max_fps(const char *s, uint16_t *max_fps) { | |
return true; | ||
} | ||
|
||
static bool | ||
parse_orientation(const char *s, int8_t *orientation) { | ||
long value; | ||
bool ok = parse_integer_arg(s, &value, false, -1, 3, | ||
"orientation"); | ||
if (!ok) { | ||
return false; | ||
} | ||
|
||
*orientation = (int8_t) value; | ||
return true; | ||
} | ||
|
||
static bool | ||
parse_window_position(const char *s, int16_t *position) { | ||
long value; | ||
|
@@ -351,6 +371,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { | |
{"help", no_argument, NULL, 'h'}, | ||
{"max-fps", required_argument, NULL, OPT_MAX_FPS}, | ||
{"max-size", required_argument, NULL, 'm'}, | ||
{"orientation", required_argument, NULL, 'o'}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since it's an "advanced" option, I'd prefer not to "consume" a short option (letter) for it. I initially assigned a short letter for everything, but since few releases, I assigned only long options to "advanced" features. |
||
{"no-control", no_argument, NULL, 'n'}, | ||
{"no-display", no_argument, NULL, 'N'}, | ||
{"port", required_argument, NULL, 'p'}, | ||
|
@@ -379,7 +400,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { | |
optind = 0; // reset to start from the first argument in tests | ||
|
||
int c; | ||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTv", long_options, | ||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:o:nNp:r:s:StTv", long_options, | ||
NULL)) != -1) { | ||
switch (c) { | ||
case 'b': | ||
|
@@ -417,6 +438,11 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { | |
return false; | ||
} | ||
break; | ||
case 'o': | ||
if(!parse_orientation(optarg, &opts->orientation)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return false; | ||
} | ||
break; | ||
case 'n': | ||
opts->control = false; | ||
break; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,9 +124,11 @@ execute_server(struct server *server, const struct server_params *params) { | |
char max_size_string[6]; | ||
char bit_rate_string[11]; | ||
char max_fps_string[6]; | ||
char orientation_string[4]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
(OK, this value should not be possible here, but then |
||
sprintf(max_size_string, "%"PRIu16, params->max_size); | ||
sprintf(bit_rate_string, "%"PRIu32, params->bit_rate); | ||
sprintf(max_fps_string, "%"PRIu16, params->max_fps); | ||
sprintf(orientation_string, "%"PRIi8, params->orientation); | ||
const char *const cmd[] = { | ||
"shell", | ||
"CLASSPATH=" DEVICE_SERVER_PATH, | ||
|
@@ -142,6 +144,7 @@ execute_server(struct server *server, const struct server_params *params) { | |
max_size_string, | ||
bit_rate_string, | ||
max_fps_string, | ||
orientation_string, | ||
server->tunnel_forward ? "true" : "false", | ||
params->crop ? params->crop : "-", | ||
"true", // always send frame meta (packet boundaries + timestamp) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,13 @@ public class ControlMessageReader { | |
public static final int CLIPBOARD_TEXT_MAX_LENGTH = 4093; | ||
private static final int RAW_BUFFER_SIZE = 1024; | ||
|
||
private static int rotationOffset = 0; | ||
|
||
private final byte[] rawBuffer = new byte[RAW_BUFFER_SIZE]; | ||
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer); | ||
private final byte[] textBuffer = new byte[CLIPBOARD_TEXT_MAX_LENGTH]; | ||
|
||
|
||
public ControlMessageReader() { | ||
// invariant: the buffer is always in "get" mode | ||
buffer.limit(0); | ||
|
@@ -169,7 +172,30 @@ private static Position readPosition(ByteBuffer buffer) { | |
int y = buffer.getInt(); | ||
int screenWidth = toUnsigned(buffer.getShort()); | ||
int screenHeight = toUnsigned(buffer.getShort()); | ||
return new Position(x, y, screenWidth, screenHeight); | ||
return rotatePosition(x, y, screenWidth, screenHeight); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The I suggest to do this in |
||
} | ||
|
||
@SuppressWarnings("SuspiciousNameCombination") | ||
private static Position rotatePosition(int x, int y, int screenWidth, int screenHeight) { | ||
Position position; | ||
switch (rotationOffset) { | ||
case 1: | ||
position = new Position(y, screenWidth - x, screenHeight, screenWidth); | ||
break; | ||
case 2: | ||
position = new Position(screenWidth - x, screenHeight - y, screenWidth, screenHeight); | ||
break; | ||
case 3: | ||
position = new Position(screenHeight - y, x, screenHeight, screenWidth); | ||
break; | ||
default: | ||
position = new Position(x, y, screenWidth, screenHeight); | ||
} | ||
return position; | ||
} | ||
|
||
static void setRotationOffset(int newRotationOffset) { | ||
rotationOffset = newRotationOffset; | ||
} | ||
|
||
@SuppressWarnings("checkstyle:MagicNumber") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,11 +48,11 @@ public synchronized ScreenInfo getScreenInfo() { | |
|
||
private ScreenInfo computeScreenInfo(Rect crop, int maxSize) { | ||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(); | ||
boolean rotated = (displayInfo.getRotation() & 1) != 0; | ||
int rotation = displayInfo.getRotation(); | ||
Size deviceSize = displayInfo.getSize(); | ||
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight()); | ||
if (crop != null) { | ||
if (rotated) { | ||
if (rotation % 2 != 0 ) { // 180s preserve dimensions | ||
// the crop (provided by the user) is expressed in the natural orientation | ||
crop = flipRect(crop); | ||
} | ||
|
@@ -64,7 +64,7 @@ private ScreenInfo computeScreenInfo(Rect crop, int maxSize) { | |
} | ||
|
||
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize); | ||
return new ScreenInfo(contentRect, videoSize, rotated); | ||
return new ScreenInfo(contentRect, videoSize, rotation); | ||
} | ||
|
||
private static String formatCrop(Rect rect) { | ||
|
@@ -192,7 +192,9 @@ public void rotateDevice() { | |
} | ||
} | ||
|
||
@SuppressWarnings("SuspiciousNameCombination") | ||
static Rect flipRect(Rect crop) { | ||
return new Rect(crop.top, crop.left, crop.bottom, crop.right); | ||
crop.set(crop.top, crop.left, crop.bottom, crop.right); | ||
return crop; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? The parameter should not be modified (it could have unexpected side effects). |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ public class Options { | |
private int maxSize; | ||
private int bitRate; | ||
private int maxFps; | ||
private int clientOrientation; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name is confusing: this is not the client orientation, everything is managed by the server.
|
||
private boolean tunnelForward; | ||
private Rect crop; | ||
private boolean sendFrameMeta; // send PTS so that the client may record properly | ||
|
@@ -35,6 +36,14 @@ public void setMaxFps(int maxFps) { | |
this.maxFps = maxFps; | ||
} | ||
|
||
public int getClientOrientation() { | ||
return clientOrientation; | ||
} | ||
|
||
public void setClientOrientation(int clientOrientation) { | ||
this.clientOrientation = clientOrientation; | ||
} | ||
|
||
public boolean isTunnelForward() { | ||
return tunnelForward; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tryed
ctrl+r
C:\scr>scrcpy --orientation 3
scrcpy: unknown option -- orientation
C:\scr>scrcpy --lock-video-orientation 1
scrcpy: unknown option -- lock-video-orientation
but not go in landscape in some apps like this
https://i.imgur.com/lKPzlEg.jpg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you using the
dev
branch? This is not merged intomaster
yet.Cheers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, any guide for build exe for win10 64bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/Genymobile/scrcpy/blob/master/BUILD.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how to fix this error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not related to the pull request. I don't know how to build for windows either. I know you should not be building as root though. Please ask your question in an appropriate thread so people can help you.
PS: You should also checkout the
dev
branch before you run the build since--lock-video-orientation
is what you are after.Thanks