@yume-chan/scrcpy 0.0.18 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +33 -0
- package/CHANGELOG.md +18 -1
- package/README.md +157 -183
- package/bin/scrcpy-server +0 -0
- package/bin/version.d.ts +1 -1
- package/bin/version.js +1 -1
- package/esm/codec/av1.d.ts +33 -0
- package/esm/codec/av1.d.ts.map +1 -0
- package/esm/codec/av1.js +35 -0
- package/esm/codec/av1.js.map +1 -0
- package/esm/codec/h264.d.ts +78 -0
- package/esm/codec/h264.d.ts.map +1 -0
- package/esm/codec/h264.js +256 -0
- package/esm/codec/h264.js.map +1 -0
- package/esm/codec/h265.d.ts +490 -0
- package/esm/codec/h265.d.ts.map +1 -0
- package/esm/codec/h265.js +1098 -0
- package/esm/codec/h265.js.map +1 -0
- package/esm/codec/index.d.ts +5 -0
- package/esm/codec/index.d.ts.map +1 -0
- package/esm/codec/index.js +5 -0
- package/esm/codec/index.js.map +1 -0
- package/esm/codec/nalu.d.ts +44 -0
- package/esm/codec/nalu.d.ts.map +1 -0
- package/esm/codec/nalu.js +310 -0
- package/esm/codec/nalu.js.map +1 -0
- package/esm/control/back-or-screen-on.d.ts +2 -2
- package/esm/control/back-or-screen-on.d.ts.map +1 -1
- package/esm/control/back-or-screen-on.js +1 -1
- package/esm/control/basic.d.ts +5 -0
- package/esm/control/basic.d.ts.map +1 -0
- package/esm/control/basic.js +3 -0
- package/esm/control/basic.js.map +1 -0
- package/esm/control/hover-helper.d.ts +17 -17
- package/esm/control/hover-helper.d.ts.map +1 -1
- package/esm/control/hover-helper.js +43 -43
- package/esm/control/hover-helper.js.map +1 -1
- package/esm/control/index.d.ts +13 -11
- package/esm/control/index.d.ts.map +1 -1
- package/esm/control/index.js +13 -11
- package/esm/control/index.js.map +1 -1
- package/esm/control/inject-keycode.d.ts +193 -60
- package/esm/control/inject-keycode.d.ts.map +1 -1
- package/esm/control/inject-keycode.js +198 -61
- package/esm/control/inject-keycode.js.map +1 -1
- package/esm/control/inject-scroll.d.ts +2 -2
- package/esm/control/inject-scroll.d.ts.map +1 -1
- package/esm/control/inject-scroll.js +1 -1
- package/esm/control/inject-text.d.ts +7 -8
- package/esm/control/inject-text.d.ts.map +1 -1
- package/esm/control/inject-text.js +5 -6
- package/esm/control/inject-text.js.map +1 -1
- package/esm/control/inject-touch.d.ts +32 -37
- package/esm/control/inject-touch.d.ts.map +1 -1
- package/esm/control/inject-touch.js +35 -62
- package/esm/control/inject-touch.js.map +1 -1
- package/esm/control/rotate-device.d.ts +4 -6
- package/esm/control/rotate-device.d.ts.map +1 -1
- package/esm/control/rotate-device.js +2 -4
- package/esm/control/rotate-device.js.map +1 -1
- package/esm/control/serializer.d.ts +25 -33
- package/esm/control/serializer.d.ts.map +1 -1
- package/esm/control/serializer.js +53 -78
- package/esm/control/serializer.js.map +1 -1
- package/esm/control/set-clipboard.d.ts +2 -2
- package/esm/control/set-clipboard.d.ts.map +1 -1
- package/esm/control/set-clipboard.js +1 -1
- package/esm/control/set-screen-power-mode.d.ts +10 -11
- package/esm/control/set-screen-power-mode.d.ts.map +1 -1
- package/esm/control/set-screen-power-mode.js +10 -11
- package/esm/control/set-screen-power-mode.js.map +1 -1
- package/esm/control/type.d.ts +28 -14
- package/esm/control/type.d.ts.map +1 -1
- package/esm/control/type.js +40 -18
- package/esm/control/type.js.map +1 -1
- package/esm/control/writer.d.ts +28 -0
- package/esm/control/writer.d.ts.map +1 -0
- package/esm/control/writer.js +53 -0
- package/esm/control/writer.js.map +1 -0
- package/esm/device-message/ack-clipboard.d.ts +8 -8
- package/esm/device-message/ack-clipboard.d.ts.map +1 -1
- package/esm/device-message/ack-clipboard.js +5 -5
- package/esm/device-message/clipboard.d.ts +9 -9
- package/esm/device-message/clipboard.d.ts.map +1 -1
- package/esm/device-message/clipboard.js +6 -6
- package/esm/device-message/index.d.ts +4 -4
- package/esm/device-message/index.js +4 -4
- package/esm/device-message/stream.d.ts +7 -7
- package/esm/device-message/stream.d.ts.map +1 -1
- package/esm/device-message/stream.js +34 -19
- package/esm/device-message/stream.js.map +1 -1
- package/esm/device-message/type.d.ts +4 -4
- package/esm/device-message/type.js +6 -6
- package/esm/index.d.ts +4 -5
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -5
- package/esm/index.js.map +1 -1
- package/esm/options/1_16/codec-options.d.ts +19 -19
- package/esm/options/1_16/codec-options.d.ts.map +1 -1
- package/esm/options/1_16/codec-options.js +25 -25
- package/esm/options/1_16/codec-options.js.map +1 -1
- package/esm/options/1_16/float-to-uint16.d.ts +5 -0
- package/esm/options/1_16/float-to-uint16.d.ts.map +1 -0
- package/esm/options/1_16/float-to-uint16.js +27 -0
- package/esm/options/1_16/float-to-uint16.js.map +1 -0
- package/esm/options/1_16/index.d.ts +6 -4
- package/esm/options/1_16/index.d.ts.map +1 -1
- package/esm/options/1_16/index.js +6 -4
- package/esm/options/1_16/index.js.map +1 -1
- package/esm/options/1_16/init.d.ts +66 -0
- package/esm/options/1_16/init.d.ts.map +1 -0
- package/esm/options/1_16/init.js +16 -0
- package/esm/options/1_16/init.js.map +1 -0
- package/esm/options/1_16/message.d.ts +32 -0
- package/esm/options/1_16/message.d.ts.map +1 -0
- package/esm/options/1_16/message.js +37 -0
- package/esm/options/1_16/message.js.map +1 -0
- package/esm/options/1_16/options.d.ts +48 -93
- package/esm/options/1_16/options.d.ts.map +1 -1
- package/esm/options/1_16/options.js +152 -189
- package/esm/options/1_16/options.js.map +1 -1
- package/esm/options/1_16/scroll.d.ts +26 -26
- package/esm/options/1_16/scroll.d.ts.map +1 -1
- package/esm/options/1_16/scroll.js +54 -55
- package/esm/options/1_16/scroll.js.map +1 -1
- package/esm/options/1_17.d.ts +33 -0
- package/esm/options/1_17.d.ts.map +1 -0
- package/esm/options/1_17.js +42 -0
- package/esm/options/1_17.js.map +1 -0
- package/esm/options/1_18.d.ts +59 -19
- package/esm/options/1_18.d.ts.map +1 -1
- package/esm/options/1_18.js +78 -45
- package/esm/options/1_18.js.map +1 -1
- package/esm/options/1_21.d.ts +41 -20
- package/esm/options/1_21.d.ts.map +1 -1
- package/esm/options/1_21.js +51 -36
- package/esm/options/1_21.js.map +1 -1
- package/esm/options/1_22/index.d.ts +3 -2
- package/esm/options/1_22/index.d.ts.map +1 -1
- package/esm/options/1_22/index.js +3 -2
- package/esm/options/1_22/index.js.map +1 -1
- package/esm/options/1_22/init.d.ts +17 -0
- package/esm/options/1_22/init.d.ts.map +1 -0
- package/esm/options/1_22/init.js +2 -0
- package/esm/options/1_22/init.js.map +1 -0
- package/esm/options/1_22/options.d.ts +35 -28
- package/esm/options/1_22/options.d.ts.map +1 -1
- package/esm/options/1_22/options.js +36 -25
- package/esm/options/1_22/options.js.map +1 -1
- package/esm/options/1_22/scroll.d.ts +16 -16
- package/esm/options/1_22/scroll.d.ts.map +1 -1
- package/esm/options/1_22/scroll.js +14 -14
- package/esm/options/1_23.d.ts +36 -11
- package/esm/options/1_23.d.ts.map +1 -1
- package/esm/options/1_23.js +44 -34
- package/esm/options/1_23.js.map +1 -1
- package/esm/options/1_24.d.ts +34 -8
- package/esm/options/1_24.d.ts.map +1 -1
- package/esm/options/1_24.js +22 -12
- package/esm/options/1_24.js.map +1 -1
- package/esm/options/1_25/index.d.ts +2 -2
- package/esm/options/1_25/index.js +2 -2
- package/esm/options/1_25/options.d.ts +10 -5
- package/esm/options/1_25/options.d.ts.map +1 -1
- package/esm/options/1_25/options.js +21 -7
- package/esm/options/1_25/options.js.map +1 -1
- package/esm/options/1_25/scroll.d.ts +19 -18
- package/esm/options/1_25/scroll.d.ts.map +1 -1
- package/esm/options/1_25/scroll.js +33 -32
- package/esm/options/1_25/scroll.js.map +1 -1
- package/esm/options/2_0.d.ts +91 -0
- package/esm/options/2_0.d.ts.map +1 -0
- package/esm/options/2_0.js +244 -0
- package/esm/options/2_0.js.map +1 -0
- package/esm/options/codec.d.ts +52 -0
- package/esm/options/codec.d.ts.map +1 -0
- package/esm/options/codec.js +26 -0
- package/esm/options/codec.js.map +1 -0
- package/esm/options/index.d.ts +12 -8
- package/esm/options/index.d.ts.map +1 -1
- package/esm/options/index.js +12 -8
- package/esm/options/index.js.map +1 -1
- package/esm/options/latest.d.ts +12 -0
- package/esm/options/latest.d.ts.map +1 -0
- package/esm/options/latest.js +8 -0
- package/esm/options/latest.js.map +1 -0
- package/esm/options/types.d.ts +86 -46
- package/esm/options/types.d.ts.map +1 -1
- package/esm/options/types.js +69 -17
- package/esm/options/types.js.map +1 -1
- package/package.json +10 -16
- package/src/codec/av1.ts +33 -0
- package/src/codec/h264.ts +317 -0
- package/src/codec/h265.ts +1375 -0
- package/src/codec/index.ts +4 -0
- package/src/codec/nalu.ts +373 -0
- package/src/control/back-or-screen-on.ts +1 -1
- package/src/control/basic.ts +3 -0
- package/src/control/hover-helper.ts +2 -4
- package/src/control/index.ts +2 -0
- package/src/control/inject-keycode.ts +194 -51
- package/src/control/inject-scroll.ts +1 -1
- package/src/control/inject-text.ts +6 -9
- package/src/control/inject-touch.ts +16 -55
- package/src/control/rotate-device.ts +3 -7
- package/src/control/serializer.ts +49 -105
- package/src/control/set-clipboard.ts +1 -1
- package/src/control/set-screen-power-mode.ts +6 -9
- package/src/control/type.ts +32 -0
- package/src/control/writer.ts +87 -0
- package/src/device-message/ack-clipboard.ts +1 -1
- package/src/device-message/clipboard.ts +1 -1
- package/src/device-message/stream.ts +32 -12
- package/src/index.ts +4 -5
- package/src/options/1_16/codec-options.ts +5 -8
- package/src/options/1_16/float-to-uint16.ts +33 -0
- package/src/options/1_16/index.ts +3 -1
- package/src/options/1_16/init.ts +80 -0
- package/src/options/1_16/message.ts +55 -0
- package/src/options/1_16/options.ts +152 -256
- package/src/options/1_16/scroll.ts +2 -5
- package/src/options/1_17.ts +66 -0
- package/src/options/1_18.ts +106 -42
- package/src/options/1_21.ts +51 -30
- package/src/options/1_22/index.ts +1 -0
- package/src/options/1_22/init.ts +19 -0
- package/src/options/1_22/options.ts +40 -46
- package/src/options/1_22/scroll.ts +2 -2
- package/src/options/1_23.ts +33 -23
- package/src/options/1_24.ts +25 -11
- package/src/options/1_25/options.ts +25 -6
- package/src/options/1_25/scroll.ts +5 -7
- package/src/options/2_0.ts +342 -0
- package/src/options/codec.ts +98 -0
- package/src/options/index.ts +7 -3
- package/src/options/latest.ts +14 -0
- package/src/options/types.ts +158 -48
- package/tsconfig.build.json +9 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/adb/client.d.ts +0 -41
- package/esm/adb/client.d.ts.map +0 -1
- package/esm/adb/client.js +0 -243
- package/esm/adb/client.js.map +0 -1
- package/esm/adb/connection.d.ts +0 -47
- package/esm/adb/connection.d.ts.map +0 -1
- package/esm/adb/connection.js +0 -110
- package/esm/adb/connection.js.map +0 -1
- package/esm/adb/index.d.ts +0 -4
- package/esm/adb/index.d.ts.map +0 -1
- package/esm/adb/index.js +0 -4
- package/esm/adb/index.js.map +0 -1
- package/esm/adb/options/1_16.d.ts +0 -8
- package/esm/adb/options/1_16.d.ts.map +0 -1
- package/esm/adb/options/1_16.js +0 -20
- package/esm/adb/options/1_16.js.map +0 -1
- package/esm/adb/options/1_22.d.ts +0 -8
- package/esm/adb/options/1_22.d.ts.map +0 -1
- package/esm/adb/options/1_22.js +0 -17
- package/esm/adb/options/1_22.js.map +0 -1
- package/esm/adb/options/index.d.ts +0 -4
- package/esm/adb/options/index.d.ts.map +0 -1
- package/esm/adb/options/index.js +0 -4
- package/esm/adb/options/index.js.map +0 -1
- package/esm/adb/options/types.d.ts +0 -24
- package/esm/adb/options/types.d.ts.map +0 -1
- package/esm/adb/options/types.js +0 -37
- package/esm/adb/options/types.js.map +0 -1
- package/esm/codec.d.ts +0 -34
- package/esm/codec.d.ts.map +0 -1
- package/esm/codec.js +0 -37
- package/esm/codec.js.map +0 -1
- package/esm/options/1_16/h264-configuration.d.ts +0 -49
- package/esm/options/1_16/h264-configuration.d.ts.map +0 -1
- package/esm/options/1_16/h264-configuration.js +0 -414
- package/esm/options/1_16/h264-configuration.js.map +0 -1
- package/esm/options/1_16/sps.d.ts +0 -22
- package/esm/options/1_16/sps.d.ts.map +0 -1
- package/esm/options/1_16/sps.js +0 -263
- package/esm/options/1_16/sps.js.map +0 -1
- package/src/adb/client.ts +0 -345
- package/src/adb/connection.ts +0 -192
- package/src/adb/index.ts +0 -3
- package/src/adb/options/1_16.ts +0 -30
- package/src/adb/options/1_22.ts +0 -26
- package/src/adb/options/index.ts +0 -3
- package/src/adb/options/types.ts +0 -75
- package/src/codec.ts +0 -35
- package/src/options/1_16/h264-configuration.ts +0 -485
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
NumberFieldDefinition,
|
|
3
|
-
NumberFieldType,
|
|
4
|
-
placeholder,
|
|
5
|
-
} from "@yume-chan/struct";
|
|
6
|
-
|
|
7
|
-
import { ScrcpyControlMessageType } from "./type.js";
|
|
1
|
+
import type { ScrcpyInjectTouchControlMessage2_0 } from "../options/index.js";
|
|
8
2
|
|
|
9
3
|
// https://developer.android.com/reference/android/view/MotionEvent#constants_1
|
|
10
4
|
export enum AndroidMotionEventAction {
|
|
@@ -23,56 +17,23 @@ export enum AndroidMotionEventAction {
|
|
|
23
17
|
ButtonRelease,
|
|
24
18
|
}
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
export enum AndroidMotionEventButton {
|
|
21
|
+
Primary = 0x01,
|
|
22
|
+
Secondary = 0x02,
|
|
23
|
+
Tertiary = 0x04,
|
|
24
|
+
Back = 0x08,
|
|
25
|
+
Forward = 0x10,
|
|
26
|
+
StylusPrimary = 0x20,
|
|
27
|
+
StylusSecondary = 0x40,
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return max;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return value;
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
31
|
+
export namespace ScrcpyPointerId {
|
|
32
|
+
export const Mouse = -1n;
|
|
33
|
+
export const Finger = -2n;
|
|
34
|
+
export const VirtualMouse = -3n;
|
|
35
|
+
export const VirtualFinger = -4n;
|
|
44
36
|
}
|
|
45
37
|
|
|
46
|
-
export const ScrcpyFloatToUint16NumberType: NumberFieldType = {
|
|
47
|
-
size: 2,
|
|
48
|
-
signed: false,
|
|
49
|
-
deserialize(array, littleEndian) {
|
|
50
|
-
const value = NumberFieldType.Uint16.deserialize(array, littleEndian);
|
|
51
|
-
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/server/src/main/java/com/genymobile/scrcpy/Binary.java#L22
|
|
52
|
-
return value === 0xffff ? 1 : value / 0x10000;
|
|
53
|
-
},
|
|
54
|
-
serialize(dataView, offset, value, littleEndian) {
|
|
55
|
-
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/app/src/util/binary.h#L51
|
|
56
|
-
value = clamp(value, -1, 1);
|
|
57
|
-
value = value === 1 ? 0xffff : value * 0x10000;
|
|
58
|
-
NumberFieldType.Uint16.serialize(dataView, offset, value, littleEndian);
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const ScrcpyFloatToUint16FieldDefinition = new NumberFieldDefinition(
|
|
63
|
-
ScrcpyFloatToUint16NumberType
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
export const ScrcpyInjectTouchControlMessage = new Struct()
|
|
67
|
-
.uint8("type", ScrcpyControlMessageType.InjectTouch as const)
|
|
68
|
-
.uint8("action", placeholder<AndroidMotionEventAction>())
|
|
69
|
-
.uint64("pointerId")
|
|
70
|
-
.uint32("pointerX")
|
|
71
|
-
.uint32("pointerY")
|
|
72
|
-
.uint16("screenWidth")
|
|
73
|
-
.uint16("screenHeight")
|
|
74
|
-
.field("pressure", ScrcpyFloatToUint16FieldDefinition)
|
|
75
|
-
.uint32("buttons");
|
|
76
|
-
|
|
77
38
|
export type ScrcpyInjectTouchControlMessage =
|
|
78
|
-
|
|
39
|
+
ScrcpyInjectTouchControlMessage2_0;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BasicControlMessage } from "./basic.js";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const ScrcpyRotateDeviceControlMessage =
|
|
6
|
-
new Struct()
|
|
7
|
-
.uint8('type', ScrcpyControlMessageType.RotateDevice as const)
|
|
3
|
+
export const ScrcpyRotateDeviceControlMessage = BasicControlMessage;
|
|
8
4
|
|
|
9
5
|
export type ScrcpyRotateDeviceControlMessage =
|
|
10
|
-
typeof ScrcpyRotateDeviceControlMessage[
|
|
6
|
+
(typeof ScrcpyRotateDeviceControlMessage)["TInit"];
|
|
@@ -1,95 +1,58 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "@yume-chan/stream-extra";
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
type ScrcpyOptions,
|
|
8
|
-
type ScrcpyScrollController,
|
|
1
|
+
import type {
|
|
2
|
+
ScrcpyOptions,
|
|
3
|
+
ScrcpyScrollController,
|
|
9
4
|
} from "../options/index.js";
|
|
10
5
|
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "./inject-keycode.js";
|
|
15
|
-
import { type ScrcpyInjectScrollControlMessage } from "./inject-scroll.js";
|
|
6
|
+
import type { AndroidKeyEventAction } from "./inject-keycode.js";
|
|
7
|
+
import { ScrcpyInjectKeyCodeControlMessage } from "./inject-keycode.js";
|
|
8
|
+
import type { ScrcpyInjectScrollControlMessage } from "./inject-scroll.js";
|
|
16
9
|
import { ScrcpyInjectTextControlMessage } from "./inject-text.js";
|
|
17
|
-
import { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
10
|
+
import type { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
18
11
|
import { ScrcpyRotateDeviceControlMessage } from "./rotate-device.js";
|
|
12
|
+
import type { AndroidScreenPowerMode } from "./set-screen-power-mode.js";
|
|
13
|
+
import { ScrcpySetScreenPowerModeControlMessage } from "./set-screen-power-mode.js";
|
|
19
14
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from "./
|
|
23
|
-
import { ScrcpyControlMessageType } from "./type.js";
|
|
15
|
+
ScrcpyControlMessageType,
|
|
16
|
+
ScrcpyControlMessageTypeValue,
|
|
17
|
+
} from "./type.js";
|
|
24
18
|
|
|
25
19
|
export class ScrcpyControlMessageSerializer {
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
options: ScrcpyOptions<object>
|
|
35
|
-
) {
|
|
36
|
-
this.writer = stream.getWriter();
|
|
37
|
-
|
|
38
|
-
this.options = options;
|
|
39
|
-
this.types = options.getControlMessageTypes();
|
|
40
|
-
this.scrollController = options.getScrollController();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public getActualMessageType(type: ScrcpyControlMessageType): number {
|
|
44
|
-
const value = this.types.indexOf(type);
|
|
45
|
-
if (value === -1) {
|
|
46
|
-
throw new Error("Not supported");
|
|
47
|
-
}
|
|
48
|
-
return value;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public addMessageType<T extends { type: ScrcpyControlMessageType }>(
|
|
52
|
-
message: Omit<T, "type">,
|
|
53
|
-
type: T["type"]
|
|
54
|
-
): T {
|
|
55
|
-
(message as T).type = this.getActualMessageType(type);
|
|
56
|
-
return message as T;
|
|
20
|
+
private _options: ScrcpyOptions<object>;
|
|
21
|
+
private _typeValues: ScrcpyControlMessageTypeValue;
|
|
22
|
+
private _scrollController: ScrcpyScrollController;
|
|
23
|
+
|
|
24
|
+
public constructor(options: ScrcpyOptions<object>) {
|
|
25
|
+
this._options = options;
|
|
26
|
+
this._typeValues = new ScrcpyControlMessageTypeValue(options);
|
|
27
|
+
this._scrollController = options.createScrollController();
|
|
57
28
|
}
|
|
58
29
|
|
|
59
30
|
public injectKeyCode(
|
|
60
31
|
message: Omit<ScrcpyInjectKeyCodeControlMessage, "type">
|
|
61
32
|
) {
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
ScrcpyControlMessageType.InjectKeyCode
|
|
67
|
-
)
|
|
33
|
+
return ScrcpyInjectKeyCodeControlMessage.serialize(
|
|
34
|
+
this._typeValues.fillMessageType(
|
|
35
|
+
message,
|
|
36
|
+
ScrcpyControlMessageType.InjectKeyCode
|
|
68
37
|
)
|
|
69
38
|
);
|
|
70
39
|
}
|
|
71
40
|
|
|
72
41
|
public injectText(text: string) {
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
ScrcpyControlMessageType.InjectText
|
|
78
|
-
),
|
|
79
|
-
})
|
|
80
|
-
);
|
|
42
|
+
return ScrcpyInjectTextControlMessage.serialize({
|
|
43
|
+
text,
|
|
44
|
+
type: this._typeValues.get(ScrcpyControlMessageType.InjectText),
|
|
45
|
+
});
|
|
81
46
|
}
|
|
82
47
|
|
|
83
48
|
/**
|
|
84
49
|
* `pressure` is a float value between 0 and 1.
|
|
85
50
|
*/
|
|
86
51
|
public injectTouch(message: Omit<ScrcpyInjectTouchControlMessage, "type">) {
|
|
87
|
-
return this.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
ScrcpyControlMessageType.InjectTouch
|
|
92
|
-
)
|
|
52
|
+
return this._options.serializeInjectTouchControlMessage(
|
|
53
|
+
this._typeValues.fillMessageType(
|
|
54
|
+
message,
|
|
55
|
+
ScrcpyControlMessageType.InjectTouch
|
|
93
56
|
)
|
|
94
57
|
);
|
|
95
58
|
}
|
|
@@ -100,52 +63,33 @@ export class ScrcpyControlMessageSerializer {
|
|
|
100
63
|
public injectScroll(
|
|
101
64
|
message: Omit<ScrcpyInjectScrollControlMessage, "type">
|
|
102
65
|
) {
|
|
103
|
-
|
|
104
|
-
this.
|
|
66
|
+
return this._scrollController.serializeScrollMessage(
|
|
67
|
+
this._typeValues.fillMessageType(
|
|
68
|
+
message,
|
|
69
|
+
ScrcpyControlMessageType.InjectScroll
|
|
70
|
+
)
|
|
105
71
|
);
|
|
106
|
-
|
|
107
|
-
if (!data) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return this.writer.write(data);
|
|
112
72
|
}
|
|
113
73
|
|
|
114
|
-
public
|
|
115
|
-
|
|
74
|
+
public backOrScreenOn(action: AndroidKeyEventAction) {
|
|
75
|
+
return this._options.serializeBackOrScreenOnControlMessage({
|
|
116
76
|
action,
|
|
117
|
-
type: this.
|
|
118
|
-
ScrcpyControlMessageType.BackOrScreenOn
|
|
119
|
-
),
|
|
77
|
+
type: this._typeValues.get(ScrcpyControlMessageType.BackOrScreenOn),
|
|
120
78
|
});
|
|
121
|
-
|
|
122
|
-
if (buffer) {
|
|
123
|
-
return await this.writer.write(buffer);
|
|
124
|
-
}
|
|
125
79
|
}
|
|
126
80
|
|
|
127
81
|
public setScreenPowerMode(mode: AndroidScreenPowerMode) {
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
})
|
|
135
|
-
);
|
|
82
|
+
return ScrcpySetScreenPowerModeControlMessage.serialize({
|
|
83
|
+
mode,
|
|
84
|
+
type: this._typeValues.get(
|
|
85
|
+
ScrcpyControlMessageType.SetScreenPowerMode
|
|
86
|
+
),
|
|
87
|
+
});
|
|
136
88
|
}
|
|
137
89
|
|
|
138
90
|
public rotateDevice() {
|
|
139
|
-
return
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
ScrcpyControlMessageType.RotateDevice
|
|
143
|
-
),
|
|
144
|
-
})
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
public close() {
|
|
149
|
-
return this.writer.close();
|
|
91
|
+
return ScrcpyRotateDeviceControlMessage.serialize({
|
|
92
|
+
type: this._typeValues.get(ScrcpyControlMessageType.RotateDevice),
|
|
93
|
+
});
|
|
150
94
|
}
|
|
151
95
|
}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import Struct, { placeholder } from
|
|
2
|
-
|
|
3
|
-
import { ScrcpyControlMessageType } from './type.js';
|
|
1
|
+
import Struct, { placeholder } from "@yume-chan/struct";
|
|
4
2
|
|
|
5
3
|
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/SurfaceControl.java;l=659;drc=20303e05bf73796124ab70a279cf849b61b97905
|
|
6
4
|
export enum AndroidScreenPowerMode {
|
|
7
5
|
Off = 0,
|
|
8
|
-
Normal = 2
|
|
6
|
+
Normal = 2,
|
|
9
7
|
}
|
|
10
8
|
|
|
11
|
-
export const ScrcpySetScreenPowerModeControlMessage =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.uint8('mode', placeholder<AndroidScreenPowerMode>());
|
|
9
|
+
export const ScrcpySetScreenPowerModeControlMessage = new Struct()
|
|
10
|
+
.uint8("type")
|
|
11
|
+
.uint8("mode", placeholder<AndroidScreenPowerMode>());
|
|
15
12
|
|
|
16
13
|
export type ScrcpySetScreenPowerModeControlMessage =
|
|
17
|
-
typeof ScrcpySetScreenPowerModeControlMessage[
|
|
14
|
+
(typeof ScrcpySetScreenPowerModeControlMessage)["TInit"];
|
package/src/control/type.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// https://github.com/Genymobile/scrcpy/blob/fa5b2a29e983a46b49531def9cf3d80c40c3de37/app/src/control_msg.h#L23
|
|
2
2
|
// For their message bodies, see https://github.com/Genymobile/scrcpy/blob/5c62f3419d252d10cd8c9cbb7c918b358b81f2d0/app/src/control_msg.c#L92
|
|
3
|
+
|
|
4
|
+
import type { ScrcpyOptions } from "../options/index.js";
|
|
5
|
+
|
|
3
6
|
// Their IDs change between versions, so always use `options.getControlMessageTypes()`
|
|
4
7
|
export enum ScrcpyControlMessageType {
|
|
5
8
|
InjectKeyCode,
|
|
@@ -15,3 +18,32 @@ export enum ScrcpyControlMessageType {
|
|
|
15
18
|
SetScreenPowerMode,
|
|
16
19
|
RotateDevice,
|
|
17
20
|
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Scrcpy control message types have different values between versions.
|
|
24
|
+
*
|
|
25
|
+
* This class provides a way to get the actual value for a given type.
|
|
26
|
+
*/
|
|
27
|
+
export class ScrcpyControlMessageTypeValue {
|
|
28
|
+
private types: readonly ScrcpyControlMessageType[];
|
|
29
|
+
|
|
30
|
+
public constructor(options: ScrcpyOptions<object>) {
|
|
31
|
+
this.types = options.controlMessageTypes;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public get(type: ScrcpyControlMessageType): number {
|
|
35
|
+
const value = this.types.indexOf(type);
|
|
36
|
+
if (value === -1) {
|
|
37
|
+
throw new Error("Not supported");
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public fillMessageType<T extends { type: ScrcpyControlMessageType }>(
|
|
43
|
+
message: Omit<T, "type">,
|
|
44
|
+
type: T["type"]
|
|
45
|
+
): T {
|
|
46
|
+
(message as T).type = this.get(type);
|
|
47
|
+
return message as T;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Consumable,
|
|
3
|
+
WritableStreamDefaultWriter,
|
|
4
|
+
} from "@yume-chan/stream-extra";
|
|
5
|
+
import { ConsumableWritableStream } from "@yume-chan/stream-extra";
|
|
6
|
+
|
|
7
|
+
import type { ScrcpyOptions } from "../options/index.js";
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
AndroidKeyEventAction,
|
|
11
|
+
ScrcpyInjectKeyCodeControlMessage,
|
|
12
|
+
} from "./inject-keycode.js";
|
|
13
|
+
import type { ScrcpyInjectScrollControlMessage } from "./inject-scroll.js";
|
|
14
|
+
import type { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
15
|
+
import { ScrcpyControlMessageSerializer } from "./serializer.js";
|
|
16
|
+
import type { AndroidScreenPowerMode } from "./set-screen-power-mode.js";
|
|
17
|
+
|
|
18
|
+
export class ScrcpyControlMessageWriter {
|
|
19
|
+
private _writer: WritableStreamDefaultWriter<Consumable<Uint8Array>>;
|
|
20
|
+
private _serializer: ScrcpyControlMessageSerializer;
|
|
21
|
+
|
|
22
|
+
public constructor(
|
|
23
|
+
writer: WritableStreamDefaultWriter<Consumable<Uint8Array>>,
|
|
24
|
+
options: ScrcpyOptions<object>
|
|
25
|
+
) {
|
|
26
|
+
this._writer = writer;
|
|
27
|
+
this._serializer = new ScrcpyControlMessageSerializer(options);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private async write(message: Uint8Array) {
|
|
31
|
+
await ConsumableWritableStream.write(this._writer, message);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public async injectKeyCode(
|
|
35
|
+
message: Omit<ScrcpyInjectKeyCodeControlMessage, "type">
|
|
36
|
+
) {
|
|
37
|
+
await this.write(this._serializer.injectKeyCode(message));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async injectText(text: string) {
|
|
41
|
+
await this.write(this._serializer.injectText(text));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* `pressure` is a float value between 0 and 1.
|
|
46
|
+
*/
|
|
47
|
+
public async injectTouch(
|
|
48
|
+
message: Omit<ScrcpyInjectTouchControlMessage, "type">
|
|
49
|
+
) {
|
|
50
|
+
await this.write(this._serializer.injectTouch(message));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* `scrollX` and `scrollY` are float values between 0 and 1.
|
|
55
|
+
*/
|
|
56
|
+
public async injectScroll(
|
|
57
|
+
message: Omit<ScrcpyInjectScrollControlMessage, "type">
|
|
58
|
+
) {
|
|
59
|
+
const data = this._serializer.injectScroll(message);
|
|
60
|
+
if (data) {
|
|
61
|
+
await this.write(data);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public async backOrScreenOn(action: AndroidKeyEventAction) {
|
|
66
|
+
const data = this._serializer.backOrScreenOn(action);
|
|
67
|
+
if (data) {
|
|
68
|
+
await this.write(data);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public async setScreenPowerMode(mode: AndroidScreenPowerMode) {
|
|
73
|
+
await this.write(this._serializer.setScreenPowerMode(mode));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public async rotateDevice() {
|
|
77
|
+
await this.write(this._serializer.rotateDevice());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public releaseLock() {
|
|
81
|
+
this._writer.releaseLock();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async close() {
|
|
85
|
+
await this._writer.close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -7,4 +7,4 @@ export const ScrcpyAckClipboardDeviceMessage = new Struct()
|
|
|
7
7
|
.extra({ type: ScrcpyDeviceMessageType.AckClipboard as const });
|
|
8
8
|
|
|
9
9
|
export type ScrcpyAckClipboardDeviceMessage =
|
|
10
|
-
typeof ScrcpyAckClipboardDeviceMessage["TDeserializeResult"];
|
|
10
|
+
(typeof ScrcpyAckClipboardDeviceMessage)["TDeserializeResult"];
|
|
@@ -8,4 +8,4 @@ export const ScrcpyClipboardDeviceMessage = new Struct()
|
|
|
8
8
|
.extra({ type: ScrcpyDeviceMessageType.Clipboard as const });
|
|
9
9
|
|
|
10
10
|
export type ScrcpyClipboardDeviceMessage =
|
|
11
|
-
typeof ScrcpyClipboardDeviceMessage["TDeserializeResult"];
|
|
11
|
+
(typeof ScrcpyClipboardDeviceMessage)["TDeserializeResult"];
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { BufferedTransformStream } from "@yume-chan/stream-extra";
|
|
2
|
+
import {
|
|
3
|
+
ExactReadableEndedError,
|
|
4
|
+
StructEmptyError,
|
|
5
|
+
StructNotEnoughDataError,
|
|
6
|
+
} from "@yume-chan/struct";
|
|
2
7
|
|
|
3
8
|
import { ScrcpyAckClipboardDeviceMessage } from "./ack-clipboard.js";
|
|
4
9
|
import { ScrcpyClipboardDeviceMessage } from "./clipboard.js";
|
|
@@ -11,18 +16,33 @@ export type ScrcpyDeviceMessage =
|
|
|
11
16
|
export class ScrcpyDeviceMessageDeserializeStream extends BufferedTransformStream<ScrcpyDeviceMessage> {
|
|
12
17
|
constructor() {
|
|
13
18
|
super(async (stream) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
try {
|
|
20
|
+
const type = await stream.readExactly(1);
|
|
21
|
+
switch (type[0]) {
|
|
22
|
+
case ScrcpyDeviceMessageType.Clipboard:
|
|
23
|
+
return await ScrcpyClipboardDeviceMessage.deserialize(
|
|
24
|
+
stream
|
|
25
|
+
);
|
|
26
|
+
case ScrcpyDeviceMessageType.AckClipboard:
|
|
27
|
+
return await ScrcpyAckClipboardDeviceMessage.deserialize(
|
|
28
|
+
stream
|
|
29
|
+
);
|
|
30
|
+
default:
|
|
31
|
+
throw new Error("Unsupported control message type");
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
// Can't read the `type` byte
|
|
35
|
+
if (e instanceof ExactReadableEndedError) {
|
|
36
|
+
throw new StructEmptyError();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Can't read struct body,
|
|
40
|
+
// treat as not enough data because `type` byte is already read
|
|
41
|
+
if (e instanceof StructEmptyError) {
|
|
42
|
+
throw new StructNotEnoughDataError();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
throw e;
|
|
26
46
|
}
|
|
27
47
|
});
|
|
28
48
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from './options/index.js';
|
|
1
|
+
export * from "./codec/index.js";
|
|
2
|
+
export * from "./control/index.js";
|
|
3
|
+
export * from "./device-message/index.js";
|
|
4
|
+
export * from "./options/index.js";
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AndroidCodecLevel,
|
|
3
|
-
type AndroidCodecProfile,
|
|
4
|
-
} from "../../codec.js";
|
|
5
|
-
import { type ScrcpyOptionValue } from "../types.js";
|
|
1
|
+
import type { ScrcpyOptionValue } from "../types.js";
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
4
|
* If the option you need is not in this type,
|
|
9
5
|
* please file an issue on GitHub.
|
|
10
6
|
*/
|
|
11
7
|
export interface CodecOptionsInit {
|
|
12
|
-
profile:
|
|
13
|
-
level:
|
|
8
|
+
profile: number;
|
|
9
|
+
level: number;
|
|
14
10
|
|
|
15
11
|
iFrameInterval: number;
|
|
16
12
|
maxBframes: number;
|
|
17
13
|
repeatPreviousFrameAfter: number;
|
|
18
14
|
maxPtsGapToEncoder: number;
|
|
15
|
+
intraRefreshPeriod: number;
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
function toDashCase(input: string) {
|
|
@@ -32,7 +29,7 @@ const CODEC_OPTION_TYPES: Partial<
|
|
|
32
29
|
export class CodecOptions implements ScrcpyOptionValue {
|
|
33
30
|
public value: Partial<CodecOptionsInit>;
|
|
34
31
|
|
|
35
|
-
public constructor(value: Partial<CodecOptionsInit>) {
|
|
32
|
+
public constructor(value: Partial<CodecOptionsInit> = {}) {
|
|
36
33
|
this.value = value;
|
|
37
34
|
}
|
|
38
35
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { NumberFieldDefinition, NumberFieldType } from "@yume-chan/struct";
|
|
2
|
+
|
|
3
|
+
export function clamp(value: number, min: number, max: number): number {
|
|
4
|
+
if (value < min) {
|
|
5
|
+
return min;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (value > max) {
|
|
9
|
+
return max;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ScrcpyFloatToUint16NumberType: NumberFieldType = {
|
|
16
|
+
size: 2,
|
|
17
|
+
signed: false,
|
|
18
|
+
deserialize(array, littleEndian) {
|
|
19
|
+
const value = NumberFieldType.Uint16.deserialize(array, littleEndian);
|
|
20
|
+
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/server/src/main/java/com/genymobile/scrcpy/Binary.java#L22
|
|
21
|
+
return value === 0xffff ? 1 : value / 0x10000;
|
|
22
|
+
},
|
|
23
|
+
serialize(dataView, offset, value, littleEndian) {
|
|
24
|
+
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/app/src/util/binary.h#L51
|
|
25
|
+
value = clamp(value, -1, 1);
|
|
26
|
+
value = value === 1 ? 0xffff : value * 0x10000;
|
|
27
|
+
NumberFieldType.Uint16.serialize(dataView, offset, value, littleEndian);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const ScrcpyFloatToUint16FieldDefinition = new NumberFieldDefinition(
|
|
32
|
+
ScrcpyFloatToUint16NumberType
|
|
33
|
+
);
|