Send device name on the socket
Make the server send the device name along with the width and height, so that the client may use it as the window title.
This commit is contained in:
parent
9d141a7f50
commit
39fd6ce518
6 changed files with 42 additions and 20 deletions
|
@ -14,6 +14,7 @@
|
||||||
#include "lockutil.h"
|
#include "lockutil.h"
|
||||||
#include "netutil.h"
|
#include "netutil.h"
|
||||||
|
|
||||||
|
#define DEVICE_NAME_FIELD_LENGTH 64
|
||||||
#define SOCKET_NAME "scrcpy"
|
#define SOCKET_NAME "scrcpy"
|
||||||
#define DISPLAY_MARGINS 96
|
#define DISPLAY_MARGINS 96
|
||||||
#define MIN(X,Y) (X) < (Y) ? (X) : (Y)
|
#define MIN(X,Y) (X) < (Y) ? (X) : (Y)
|
||||||
|
@ -58,13 +59,18 @@ static void stop_server(process_t server) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool read_initial_device_size(TCPsocket socket, struct size *size) {
|
// name must be at least DEVICE_NAME_FIELD_LENGTH bytes
|
||||||
unsigned char buf[4];
|
SDL_bool read_initial_device_info(TCPsocket socket, char *device_name, struct size *size) {
|
||||||
|
unsigned char buf[DEVICE_NAME_FIELD_LENGTH + 4];
|
||||||
if (SDLNet_TCP_Recv(socket, buf, sizeof(buf)) <= 0) {
|
if (SDLNet_TCP_Recv(socket, buf, sizeof(buf)) <= 0) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
size->width = (buf[0] << 8) | buf[1];
|
buf[DEVICE_NAME_FIELD_LENGTH - 1] = '\0'; // in case the client sends garbage
|
||||||
size->height = (buf[2] << 8) | buf[3];
|
// scrcpy is safe here, since name contains at least DEVICE_NAME_FIELD_LENGTH bytes
|
||||||
|
// and strlen(buf) < DEVICE_NAME_FIELD_LENGTH
|
||||||
|
strcpy(device_name, (char *) buf);
|
||||||
|
size->width = (buf[DEVICE_NAME_FIELD_LENGTH] << 8) | buf[DEVICE_NAME_FIELD_LENGTH + 1];
|
||||||
|
size->height = (buf[DEVICE_NAME_FIELD_LENGTH + 2] << 8) | buf[DEVICE_NAME_FIELD_LENGTH + 3];
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,11 +258,12 @@ int show_screen(const char *serial, Uint16 local_port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct size frame_size;
|
struct size frame_size;
|
||||||
|
char device_name[DEVICE_NAME_FIELD_LENGTH];
|
||||||
|
|
||||||
// screenrecord does not send frames when the screen content does not change
|
// screenrecord does not send frames when the screen content does not change
|
||||||
// therefore, we transmit the screen size before the video stream, to be able
|
// therefore, we transmit the screen size before the video stream, to be able
|
||||||
// to init the window immediately
|
// to init the window immediately
|
||||||
if (!read_initial_device_size(device_socket, &frame_size)) {
|
if (!read_initial_device_info(device_socket, device_name, &frame_size)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not retrieve initial screen size");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not retrieve initial screen size");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
SDLNet_TCP_Close(device_socket);
|
SDLNet_TCP_Close(device_socket);
|
||||||
|
@ -297,7 +304,7 @@ int show_screen(const char *serial, Uint16 local_port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct size window_size = get_initial_optimal_size(frame_size);
|
struct size window_size = get_initial_optimal_size(frame_size);
|
||||||
SDL_Window *window = SDL_CreateWindow("scrcpy", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
SDL_Window *window = SDL_CreateWindow(device_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||||
window_size.width, window_size.height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
window_size.width, window_size.height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||||
if (!window) {
|
if (!window) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Could not create window: %s", SDL_GetError());
|
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Could not create window: %s", SDL_GetError());
|
||||||
|
|
|
@ -18,10 +18,10 @@ ANDROID_JAR := $(ANDROID_HOME)/platforms/android-26/android.jar
|
||||||
AIDL_SRC := android/view/IRotationWatcher.aidl
|
AIDL_SRC := android/view/IRotationWatcher.aidl
|
||||||
SRC := com/genymobile/scrcpy/ScrCpyServer.java \
|
SRC := com/genymobile/scrcpy/ScrCpyServer.java \
|
||||||
com/genymobile/scrcpy/DesktopConnection.java \
|
com/genymobile/scrcpy/DesktopConnection.java \
|
||||||
|
com/genymobile/scrcpy/DeviceUtil.java \
|
||||||
com/genymobile/scrcpy/ScreenInfo.java \
|
com/genymobile/scrcpy/ScreenInfo.java \
|
||||||
com/genymobile/scrcpy/ScreenStreamer.java \
|
com/genymobile/scrcpy/ScreenStreamer.java \
|
||||||
com/genymobile/scrcpy/ScreenStreamerSession.java \
|
com/genymobile/scrcpy/ScreenStreamerSession.java \
|
||||||
com/genymobile/scrcpy/ScreenUtil.java \
|
|
||||||
|
|
||||||
JAR := scrcpy-server.jar
|
JAR := scrcpy-server.jar
|
||||||
MAIN := com.genymobile.scrcpy.ScrCpyServer
|
MAIN := com.genymobile.scrcpy.ScrCpyServer
|
||||||
|
|
|
@ -5,9 +5,12 @@ import android.net.LocalSocketAddress;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public class DesktopConnection implements Closeable {
|
public class DesktopConnection implements Closeable {
|
||||||
|
|
||||||
|
private static final int DEVICE_NAME_FIELD_LENGTH = 64;
|
||||||
|
|
||||||
private static final String SOCKET_NAME = "scrcpy";
|
private static final String SOCKET_NAME = "scrcpy";
|
||||||
|
|
||||||
private final LocalSocket socket;
|
private final LocalSocket socket;
|
||||||
|
@ -22,9 +25,9 @@ public class DesktopConnection implements Closeable {
|
||||||
return localSocket;
|
return localSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DesktopConnection open(int width, int height) throws IOException {
|
public static DesktopConnection open(String deviceName, int width, int height) throws IOException {
|
||||||
LocalSocket socket = connect(SOCKET_NAME);
|
LocalSocket socket = connect(SOCKET_NAME);
|
||||||
send(socket, width, height);
|
send(socket, deviceName, width, height);
|
||||||
return new DesktopConnection(socket);
|
return new DesktopConnection(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,15 +37,21 @@ public class DesktopConnection implements Closeable {
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void send(LocalSocket socket, int width, int height) throws IOException {
|
private static void send(LocalSocket socket, String deviceName, int width, int height) throws IOException {
|
||||||
assert width < 0x10000 : "width may not be stored on 16 bits";
|
assert width < 0x10000 : "width may not be stored on 16 bits";
|
||||||
assert height < 0x10000 : "height may not be stored on 16 bits";
|
assert height < 0x10000 : "height may not be stored on 16 bits";
|
||||||
byte[] buffer = new byte[4];
|
byte[] buffer = new byte[DEVICE_NAME_FIELD_LENGTH + 4];
|
||||||
buffer[0] = (byte) (width >> 8);
|
|
||||||
buffer[1] = (byte) width;
|
byte[] deviceNameBytes = deviceName.getBytes(StandardCharsets.UTF_8);
|
||||||
buffer[2] = (byte) (height >> 8);
|
int len = Math.min(DEVICE_NAME_FIELD_LENGTH - 1, deviceNameBytes.length);
|
||||||
buffer[3] = (byte) height;
|
System.arraycopy(deviceNameBytes, 0, buffer, 0, len);
|
||||||
socket.getOutputStream().write(buffer, 0, 4);
|
// byte[] are always 0-initialized in java, no need to set '\0' explicitly
|
||||||
|
|
||||||
|
buffer[DEVICE_NAME_FIELD_LENGTH] = (byte) (width >> 8);
|
||||||
|
buffer[DEVICE_NAME_FIELD_LENGTH + 1] = (byte) width;
|
||||||
|
buffer[DEVICE_NAME_FIELD_LENGTH + 2] = (byte) (height >> 8);
|
||||||
|
buffer[DEVICE_NAME_FIELD_LENGTH + 3] = (byte) height;
|
||||||
|
socket.getOutputStream().write(buffer, 0, buffer.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendVideoStream(byte[] videoStreamBuffer, int len) throws IOException {
|
public void sendVideoStream(byte[] videoStreamBuffer, int len) throws IOException {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package com.genymobile.scrcpy;
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IInterface;
|
import android.os.IInterface;
|
||||||
import android.view.IRotationWatcher;
|
import android.view.IRotationWatcher;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class ScreenUtil {
|
public class DeviceUtil {
|
||||||
|
|
||||||
private static final ServiceManager serviceManager = new ServiceManager();
|
private static final ServiceManager serviceManager = new ServiceManager();
|
||||||
|
|
||||||
|
@ -18,6 +19,10 @@ public class ScreenUtil {
|
||||||
serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher);
|
serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getDeviceName() {
|
||||||
|
return Build.MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
private static class ServiceManager {
|
private static class ServiceManager {
|
||||||
private Method getServiceMethod;
|
private Method getServiceMethod;
|
||||||
|
|
|
@ -5,10 +5,11 @@ import java.io.IOException;
|
||||||
public class ScrCpyServer {
|
public class ScrCpyServer {
|
||||||
|
|
||||||
public static void scrcpy() throws IOException {
|
public static void scrcpy() throws IOException {
|
||||||
ScreenInfo initialScreenInfo = ScreenUtil.getScreenInfo();
|
String deviceName = DeviceUtil.getDeviceName();
|
||||||
|
ScreenInfo initialScreenInfo = DeviceUtil.getScreenInfo();
|
||||||
int width = initialScreenInfo.getLogicalWidth();
|
int width = initialScreenInfo.getLogicalWidth();
|
||||||
int height = initialScreenInfo.getLogicalHeight();
|
int height = initialScreenInfo.getLogicalHeight();
|
||||||
try (DesktopConnection connection = DesktopConnection.open(width, height)) {
|
try (DesktopConnection connection = DesktopConnection.open(deviceName, width, height)) {
|
||||||
try {
|
try {
|
||||||
new ScreenStreamer(connection).streamScreen();
|
new ScreenStreamer(connection).streamScreen();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class ScreenStreamer {
|
||||||
|
|
||||||
public ScreenStreamer(DesktopConnection connection) {
|
public ScreenStreamer(DesktopConnection connection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
ScreenUtil.registerRotationWatcher(new IRotationWatcher.Stub() {
|
DeviceUtil.registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onRotationChanged(int rotation) throws RemoteException {
|
public void onRotationChanged(int rotation) throws RemoteException {
|
||||||
reset();
|
reset();
|
||||||
|
|
Loading…
Reference in a new issue