@yume-chan/scrcpy 0.0.19 → 0.0.21
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 +30 -0
- package/CHANGELOG.md +17 -1
- package/README.md +76 -266
- package/esm/codec/av1.js +2 -2
- package/esm/codec/av1.js.map +1 -1
- package/esm/codec/h264.d.ts +1 -21
- package/esm/codec/h264.d.ts.map +1 -1
- package/esm/codec/h264.js +15 -236
- package/esm/codec/h264.js.map +1 -1
- package/esm/codec/h265.d.ts +454 -0
- package/esm/codec/h265.d.ts.map +1 -1
- package/esm/codec/h265.js +1062 -2
- package/esm/codec/h265.js.map +1 -1
- package/esm/codec/index.d.ts +1 -0
- package/esm/codec/index.d.ts.map +1 -1
- package/esm/codec/index.js +1 -0
- package/esm/codec/index.js.map +1 -1
- package/esm/codec/nalu.d.ts +37 -0
- package/esm/codec/nalu.d.ts.map +1 -0
- package/esm/codec/nalu.js +323 -0
- package/esm/codec/nalu.js.map +1 -0
- package/esm/control/back-or-screen-on.d.ts +1 -1
- package/esm/control/back-or-screen-on.d.ts.map +1 -1
- package/esm/control/hover-helper.d.ts +1 -1
- package/esm/control/hover-helper.d.ts.map +1 -1
- package/esm/control/hover-helper.js +8 -9
- package/esm/control/hover-helper.js.map +1 -1
- package/esm/control/index.d.ts +2 -0
- package/esm/control/index.d.ts.map +1 -1
- package/esm/control/index.js +2 -0
- package/esm/control/index.js.map +1 -1
- package/esm/control/inject-keycode.d.ts +1 -2
- package/esm/control/inject-keycode.d.ts.map +1 -1
- package/esm/control/inject-keycode.js +4 -5
- package/esm/control/inject-keycode.js.map +1 -1
- package/esm/control/inject-text.d.ts +1 -2
- package/esm/control/inject-text.d.ts.map +1 -1
- package/esm/control/inject-text.js +1 -2
- package/esm/control/inject-text.js.map +1 -1
- package/esm/control/inject-touch.d.ts +15 -20
- package/esm/control/inject-touch.d.ts.map +1 -1
- package/esm/control/inject-touch.js +16 -43
- package/esm/control/inject-touch.js.map +1 -1
- package/esm/control/rotate-device.d.ts +2 -4
- package/esm/control/rotate-device.d.ts.map +1 -1
- package/esm/control/rotate-device.js +2 -3
- package/esm/control/rotate-device.js.map +1 -1
- package/esm/control/serializer.d.ts +11 -23
- package/esm/control/serializer.d.ts.map +1 -1
- package/esm/control/serializer.js +23 -52
- package/esm/control/serializer.js.map +1 -1
- package/esm/control/set-screen-power-mode.d.ts +1 -2
- package/esm/control/set-screen-power-mode.d.ts.map +1 -1
- package/esm/control/set-screen-power-mode.js +2 -3
- package/esm/control/set-screen-power-mode.js.map +1 -1
- package/esm/control/type.d.ts +14 -0
- package/esm/control/type.d.ts.map +1 -1
- package/esm/control/type.js +23 -1
- package/esm/control/type.js.map +1 -1
- package/esm/control/writer.d.ts +26 -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/stream.d.ts.map +1 -1
- package/esm/device-message/stream.js +23 -8
- package/esm/device-message/stream.js.map +1 -1
- package/esm/device-message/type.js +1 -1
- package/esm/device-message/type.js.map +1 -1
- package/esm/index.d.ts +1 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -2
- package/esm/index.js.map +1 -1
- package/esm/options/1_16/codec-options.d.ts +2 -3
- package/esm/options/1_16/codec-options.d.ts.map +1 -1
- package/esm/options/1_16/codec-options.js.map +1 -1
- package/esm/options/1_16/index.d.ts +3 -1
- package/esm/options/1_16/index.d.ts.map +1 -1
- package/esm/options/1_16/index.js +3 -1
- package/esm/options/1_16/index.js.map +1 -1
- package/esm/options/1_16/init.js +2 -2
- package/esm/options/1_16/init.js.map +1 -1
- package/esm/options/1_16/options.d.ts +42 -96
- package/esm/options/1_16/options.d.ts.map +1 -1
- package/esm/options/1_16/options.js +104 -142
- package/esm/options/1_16/options.js.map +1 -1
- package/esm/options/1_16/scroll.d.ts +2 -4
- package/esm/options/1_16/scroll.d.ts.map +1 -1
- package/esm/options/1_16/scroll.js +13 -14
- package/esm/options/1_16/scroll.js.map +1 -1
- package/esm/options/1_17.d.ts +1 -0
- package/esm/options/1_17.d.ts.map +1 -1
- package/esm/options/1_17.js +8 -3
- package/esm/options/1_17.js.map +1 -1
- package/esm/options/1_18.d.ts +49 -11
- package/esm/options/1_18.d.ts.map +1 -1
- package/esm/options/1_18.js +64 -32
- package/esm/options/1_18.js.map +1 -1
- package/esm/options/1_21.d.ts +26 -7
- package/esm/options/1_21.d.ts.map +1 -1
- package/esm/options/1_21.js +34 -20
- package/esm/options/1_21.js.map +1 -1
- package/esm/options/1_22/index.d.ts +1 -0
- package/esm/options/1_22/index.d.ts.map +1 -1
- package/esm/options/1_22/index.js +1 -0
- package/esm/options/1_22/index.js.map +1 -1
- package/esm/options/1_22/options.d.ts +32 -26
- package/esm/options/1_22/options.d.ts.map +1 -1
- package/esm/options/1_22/options.js +26 -16
- package/esm/options/1_22/options.js.map +1 -1
- package/esm/options/1_22/scroll.d.ts +1 -1
- package/esm/options/1_22/scroll.d.ts.map +1 -1
- package/esm/options/1_22/scroll.js +1 -1
- package/esm/options/1_22/scroll.js.map +1 -1
- package/esm/options/1_23.d.ts +32 -8
- package/esm/options/1_23.d.ts.map +1 -1
- package/esm/options/1_23.js +23 -14
- package/esm/options/1_23.js.map +1 -1
- package/esm/options/1_24.d.ts +29 -4
- package/esm/options/1_24.d.ts.map +1 -1
- package/esm/options/1_24.js +16 -7
- package/esm/options/1_24.js.map +1 -1
- package/esm/options/1_25/options.d.ts +6 -2
- package/esm/options/1_25/options.d.ts.map +1 -1
- package/esm/options/1_25/options.js +16 -2
- package/esm/options/1_25/options.js.map +1 -1
- package/esm/options/1_25/scroll.d.ts.map +1 -1
- package/esm/options/1_25/scroll.js +2 -1
- package/esm/options/1_25/scroll.js.map +1 -1
- package/esm/options/2_0.d.ts +12 -8
- package/esm/options/2_0.d.ts.map +1 -1
- package/esm/options/2_0.js +82 -15
- package/esm/options/2_0.js.map +1 -1
- package/esm/options/2_1.d.ts +48 -0
- package/esm/options/2_1.d.ts.map +1 -0
- package/esm/options/2_1.js +23 -0
- package/esm/options/2_1.js.map +1 -0
- package/esm/options/codec.d.ts +4 -4
- package/esm/options/codec.d.ts.map +1 -1
- package/esm/options/codec.js +5 -6
- package/esm/options/codec.js.map +1 -1
- package/esm/options/index.d.ts +5 -0
- package/esm/options/index.d.ts.map +1 -1
- package/esm/options/index.js +5 -0
- package/esm/options/index.js.map +1 -1
- package/esm/options/latest.d.ts +4 -5
- package/esm/options/latest.d.ts.map +1 -1
- package/esm/options/latest.js +2 -3
- package/esm/options/latest.js.map +1 -1
- package/esm/options/types.d.ts +74 -33
- package/esm/options/types.d.ts.map +1 -1
- package/esm/options/types.js +62 -0
- package/esm/options/types.js.map +1 -1
- package/package.json +9 -19
- 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 +391 -0
- package/src/control/back-or-screen-on.ts +1 -1
- package/{esm/control/simple.js → src/control/basic.ts} +3 -3
- package/src/control/hover-helper.ts +10 -11
- package/src/control/index.ts +2 -0
- package/src/control/inject-keycode.ts +1 -3
- package/src/control/inject-text.ts +1 -3
- package/src/control/inject-touch.ts +16 -55
- package/src/control/rotate-device.ts +2 -7
- package/src/control/serializer.ts +50 -113
- package/src/control/set-screen-power-mode.ts +1 -3
- package/src/control/type.ts +32 -0
- package/src/control/writer.ts +85 -0
- package/src/device-message/stream.ts +32 -12
- package/src/index.ts +1 -2
- package/src/options/1_16/codec-options.ts +6 -7
- 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 +147 -260
- package/src/options/1_16/scroll.ts +17 -18
- package/src/options/1_17.ts +66 -0
- package/src/options/1_18.ts +103 -39
- package/src/options/1_21.ts +49 -27
- 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 +38 -45
- package/src/options/1_22/scroll.ts +3 -3
- package/src/options/1_23.ts +34 -22
- package/src/options/1_24.ts +23 -11
- package/src/options/1_25/options.ts +22 -4
- package/src/options/1_25/scroll.ts +4 -3
- package/src/options/2_0.ts +342 -0
- package/src/options/2_1.ts +35 -0
- package/src/options/codec.ts +98 -0
- package/src/options/index.ts +5 -0
- package/src/options/latest.ts +12 -0
- package/src/options/types.ts +164 -43
- package/tsconfig.build.json +9 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/bin/scrcpy-server +0 -0
- package/bin/version.d.ts +0 -1
- package/bin/version.js +0 -1
- package/esm/adb/client.d.ts +0 -41
- package/esm/adb/client.d.ts.map +0 -1
- package/esm/adb/client.js +0 -224
- package/esm/adb/client.js.map +0 -1
- package/esm/adb/connection.d.ts +0 -49
- package/esm/adb/connection.d.ts.map +0 -1
- package/esm/adb/connection.js +0 -122
- 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/1_26.d.ts +0 -9
- package/esm/adb/options/1_26.d.ts.map +0 -1
- package/esm/adb/options/1_26.js +0 -11
- package/esm/adb/options/1_26.js.map +0 -1
- package/esm/adb/options/2_0.d.ts +0 -8
- package/esm/adb/options/2_0.d.ts.map +0 -1
- package/esm/adb/options/2_0.js +0 -13
- package/esm/adb/options/2_0.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/control/simple.d.ts +0 -5
- package/esm/control/simple.d.ts.map +0 -1
- package/esm/control/simple.js.map +0 -1
- package/esm/decoder.d.ts +0 -2
- package/esm/decoder.d.ts.map +0 -1
- package/esm/decoder.js +0 -2
- package/esm/decoder.js.map +0 -1
- package/esm/options/1.17.d.ts +0 -3
- package/esm/options/1.17.d.ts.map +0 -1
- package/esm/options/1.17.js +0 -2
- package/esm/options/1.17.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/esm/options/1_26.d.ts +0 -57
- package/esm/options/1_26.d.ts.map +0 -1
- package/esm/options/1_26.js +0 -67
- package/esm/options/1_26.js.map +0 -1
- package/esm/options/2.d.ts +0 -57
- package/esm/options/2.d.ts.map +0 -1
- package/esm/options/2.js +0 -67
- package/esm/options/2.js.map +0 -1
- package/scripts/fetch-server.cjs +0 -38
- package/src/adb/client.ts +0 -329
- package/src/adb/connection.ts +0 -209
- package/src/adb/index.ts +0 -3
- package/src/adb/options/1_16.ts +0 -32
- 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,13 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Consumable,
|
|
3
|
-
WritableStream,
|
|
4
|
-
WritableStreamDefaultWriter,
|
|
5
|
-
} from "@yume-chan/stream-extra";
|
|
6
|
-
import { ConsumableWritableStream } from "@yume-chan/stream-extra";
|
|
7
|
-
|
|
8
1
|
import type {
|
|
9
2
|
ScrcpyOptions,
|
|
10
|
-
ScrcpyOptionsInit1_16,
|
|
11
3
|
ScrcpyScrollController,
|
|
12
4
|
} from "../options/index.js";
|
|
13
5
|
|
|
@@ -15,140 +7,85 @@ import type { AndroidKeyEventAction } from "./inject-keycode.js";
|
|
|
15
7
|
import { ScrcpyInjectKeyCodeControlMessage } from "./inject-keycode.js";
|
|
16
8
|
import type { ScrcpyInjectScrollControlMessage } from "./inject-scroll.js";
|
|
17
9
|
import { ScrcpyInjectTextControlMessage } from "./inject-text.js";
|
|
18
|
-
import { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
10
|
+
import type { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
19
11
|
import { ScrcpyRotateDeviceControlMessage } from "./rotate-device.js";
|
|
20
12
|
import type { AndroidScreenPowerMode } from "./set-screen-power-mode.js";
|
|
21
13
|
import { ScrcpySetScreenPowerModeControlMessage } from "./set-screen-power-mode.js";
|
|
22
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
ScrcpyControlMessageType,
|
|
16
|
+
ScrcpyControlMessageTypeValue,
|
|
17
|
+
} from "./type.js";
|
|
23
18
|
|
|
24
19
|
export class ScrcpyControlMessageSerializer {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
options: ScrcpyOptions<ScrcpyOptionsInit1_16>
|
|
34
|
-
) {
|
|
35
|
-
this.writer = stream.getWriter();
|
|
36
|
-
|
|
37
|
-
this.options = options;
|
|
38
|
-
this.types = options.getControlMessageTypes();
|
|
39
|
-
this.scrollController = options.getScrollController();
|
|
20
|
+
#options: ScrcpyOptions<object>;
|
|
21
|
+
#typeValues: ScrcpyControlMessageTypeValue;
|
|
22
|
+
#scrollController: ScrcpyScrollController;
|
|
23
|
+
|
|
24
|
+
constructor(options: ScrcpyOptions<object>) {
|
|
25
|
+
this.#options = options;
|
|
26
|
+
this.#typeValues = new ScrcpyControlMessageTypeValue(options);
|
|
27
|
+
this.#scrollController = options.createScrollController();
|
|
40
28
|
}
|
|
41
29
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public addMessageType<T extends { type: ScrcpyControlMessageType }>(
|
|
51
|
-
message: Omit<T, "type">,
|
|
52
|
-
type: T["type"]
|
|
53
|
-
): T {
|
|
54
|
-
(message as T).type = this.getActualMessageType(type);
|
|
55
|
-
return message as T;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private async write(data: Uint8Array) {
|
|
59
|
-
await ConsumableWritableStream.write(this.writer, data);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
public injectKeyCode(
|
|
63
|
-
message: Omit<ScrcpyInjectKeyCodeControlMessage, "type">
|
|
64
|
-
) {
|
|
65
|
-
return this.write(
|
|
66
|
-
ScrcpyInjectKeyCodeControlMessage.serialize(
|
|
67
|
-
this.addMessageType(
|
|
68
|
-
message,
|
|
69
|
-
ScrcpyControlMessageType.InjectKeyCode
|
|
70
|
-
)
|
|
71
|
-
)
|
|
30
|
+
injectKeyCode(message: Omit<ScrcpyInjectKeyCodeControlMessage, "type">) {
|
|
31
|
+
return ScrcpyInjectKeyCodeControlMessage.serialize(
|
|
32
|
+
this.#typeValues.fillMessageType(
|
|
33
|
+
message,
|
|
34
|
+
ScrcpyControlMessageType.InjectKeyCode,
|
|
35
|
+
),
|
|
72
36
|
);
|
|
73
37
|
}
|
|
74
38
|
|
|
75
|
-
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
ScrcpyControlMessageType.InjectText
|
|
81
|
-
),
|
|
82
|
-
})
|
|
83
|
-
);
|
|
39
|
+
injectText(text: string) {
|
|
40
|
+
return ScrcpyInjectTextControlMessage.serialize({
|
|
41
|
+
text,
|
|
42
|
+
type: this.#typeValues.get(ScrcpyControlMessageType.InjectText),
|
|
43
|
+
});
|
|
84
44
|
}
|
|
85
45
|
|
|
86
46
|
/**
|
|
87
47
|
* `pressure` is a float value between 0 and 1.
|
|
88
48
|
*/
|
|
89
|
-
|
|
90
|
-
return this.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
)
|
|
96
|
-
)
|
|
49
|
+
injectTouch(message: Omit<ScrcpyInjectTouchControlMessage, "type">) {
|
|
50
|
+
return this.#options.serializeInjectTouchControlMessage(
|
|
51
|
+
this.#typeValues.fillMessageType(
|
|
52
|
+
message,
|
|
53
|
+
ScrcpyControlMessageType.InjectTouch,
|
|
54
|
+
),
|
|
97
55
|
);
|
|
98
56
|
}
|
|
99
57
|
|
|
100
58
|
/**
|
|
101
59
|
* `scrollX` and `scrollY` are float values between 0 and 1.
|
|
102
60
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
61
|
+
injectScroll(message: Omit<ScrcpyInjectScrollControlMessage, "type">) {
|
|
62
|
+
return this.#scrollController.serializeScrollMessage(
|
|
63
|
+
this.#typeValues.fillMessageType(
|
|
64
|
+
message,
|
|
65
|
+
ScrcpyControlMessageType.InjectScroll,
|
|
66
|
+
),
|
|
108
67
|
);
|
|
109
|
-
|
|
110
|
-
if (!data) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return this.write(data);
|
|
115
68
|
}
|
|
116
69
|
|
|
117
|
-
|
|
118
|
-
|
|
70
|
+
backOrScreenOn(action: AndroidKeyEventAction) {
|
|
71
|
+
return this.#options.serializeBackOrScreenOnControlMessage({
|
|
119
72
|
action,
|
|
120
|
-
type: this.
|
|
121
|
-
ScrcpyControlMessageType.BackOrScreenOn
|
|
122
|
-
),
|
|
73
|
+
type: this.#typeValues.get(ScrcpyControlMessageType.BackOrScreenOn),
|
|
123
74
|
});
|
|
124
|
-
|
|
125
|
-
if (buffer) {
|
|
126
|
-
return await this.write(buffer);
|
|
127
|
-
}
|
|
128
75
|
}
|
|
129
76
|
|
|
130
|
-
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
})
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
public rotateDevice() {
|
|
142
|
-
return this.write(
|
|
143
|
-
ScrcpyRotateDeviceControlMessage.serialize({
|
|
144
|
-
type: this.getActualMessageType(
|
|
145
|
-
ScrcpyControlMessageType.RotateDevice
|
|
146
|
-
),
|
|
147
|
-
})
|
|
148
|
-
);
|
|
77
|
+
setScreenPowerMode(mode: AndroidScreenPowerMode) {
|
|
78
|
+
return ScrcpySetScreenPowerModeControlMessage.serialize({
|
|
79
|
+
mode,
|
|
80
|
+
type: this.#typeValues.get(
|
|
81
|
+
ScrcpyControlMessageType.SetScreenPowerMode,
|
|
82
|
+
),
|
|
83
|
+
});
|
|
149
84
|
}
|
|
150
85
|
|
|
151
|
-
|
|
152
|
-
return
|
|
86
|
+
rotateDevice() {
|
|
87
|
+
return ScrcpyRotateDeviceControlMessage.serialize({
|
|
88
|
+
type: this.#typeValues.get(ScrcpyControlMessageType.RotateDevice),
|
|
89
|
+
});
|
|
153
90
|
}
|
|
154
91
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import Struct, { placeholder } from "@yume-chan/struct";
|
|
2
2
|
|
|
3
|
-
import { ScrcpyControlMessageType } from "./type.js";
|
|
4
|
-
|
|
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,
|
|
@@ -9,7 +7,7 @@ export enum AndroidScreenPowerMode {
|
|
|
9
7
|
}
|
|
10
8
|
|
|
11
9
|
export const ScrcpySetScreenPowerModeControlMessage = new Struct()
|
|
12
|
-
.uint8("type"
|
|
10
|
+
.uint8("type")
|
|
13
11
|
.uint8("mode", placeholder<AndroidScreenPowerMode>());
|
|
14
12
|
|
|
15
13
|
export type ScrcpySetScreenPowerModeControlMessage =
|
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
|
+
#types: readonly ScrcpyControlMessageType[];
|
|
29
|
+
|
|
30
|
+
constructor(options: ScrcpyOptions<object>) {
|
|
31
|
+
this.#types = options.controlMessageTypes;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
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
|
+
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,85 @@
|
|
|
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
|
+
#writer: WritableStreamDefaultWriter<Consumable<Uint8Array>>;
|
|
20
|
+
#serializer: ScrcpyControlMessageSerializer;
|
|
21
|
+
|
|
22
|
+
constructor(
|
|
23
|
+
writer: WritableStreamDefaultWriter<Consumable<Uint8Array>>,
|
|
24
|
+
options: ScrcpyOptions<object>,
|
|
25
|
+
) {
|
|
26
|
+
this.#writer = writer;
|
|
27
|
+
this.#serializer = new ScrcpyControlMessageSerializer(options);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async #write(message: Uint8Array) {
|
|
31
|
+
await ConsumableWritableStream.write(this.#writer, message);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async injectKeyCode(
|
|
35
|
+
message: Omit<ScrcpyInjectKeyCodeControlMessage, "type">,
|
|
36
|
+
) {
|
|
37
|
+
await this.#write(this.#serializer.injectKeyCode(message));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
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
|
+
async injectTouch(message: Omit<ScrcpyInjectTouchControlMessage, "type">) {
|
|
48
|
+
await this.#write(this.#serializer.injectTouch(message));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* `scrollX` and `scrollY` are float values between 0 and 1.
|
|
53
|
+
*/
|
|
54
|
+
async injectScroll(
|
|
55
|
+
message: Omit<ScrcpyInjectScrollControlMessage, "type">,
|
|
56
|
+
) {
|
|
57
|
+
const data = this.#serializer.injectScroll(message);
|
|
58
|
+
if (data) {
|
|
59
|
+
await this.#write(data);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async backOrScreenOn(action: AndroidKeyEventAction) {
|
|
64
|
+
const data = this.#serializer.backOrScreenOn(action);
|
|
65
|
+
if (data) {
|
|
66
|
+
await this.#write(data);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async setScreenPowerMode(mode: AndroidScreenPowerMode) {
|
|
71
|
+
await this.#write(this.#serializer.setScreenPowerMode(mode));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async rotateDevice() {
|
|
75
|
+
await this.#write(this.#serializer.rotateDevice());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
releaseLock() {
|
|
79
|
+
this.#writer.releaseLock();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async close() {
|
|
83
|
+
await this.#writer.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -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,4 +1,3 @@
|
|
|
1
|
-
import type { AndroidCodecLevel, AndroidCodecProfile } from "../../codec.js";
|
|
2
1
|
import type { ScrcpyOptionValue } from "../types.js";
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -6,8 +5,8 @@ import type { ScrcpyOptionValue } from "../types.js";
|
|
|
6
5
|
* please file an issue on GitHub.
|
|
7
6
|
*/
|
|
8
7
|
export interface CodecOptionsInit {
|
|
9
|
-
profile:
|
|
10
|
-
level:
|
|
8
|
+
profile: number;
|
|
9
|
+
level: number;
|
|
11
10
|
|
|
12
11
|
iFrameInterval: number;
|
|
13
12
|
maxBframes: number;
|
|
@@ -28,15 +27,15 @@ const CODEC_OPTION_TYPES: Partial<
|
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
export class CodecOptions implements ScrcpyOptionValue {
|
|
31
|
-
|
|
30
|
+
value: Partial<CodecOptionsInit>;
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
constructor(value: Partial<CodecOptionsInit> = {}) {
|
|
34
33
|
this.value = value;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
toOptionValue(): string | undefined {
|
|
38
37
|
const entries = Object.entries(this.value).filter(
|
|
39
|
-
([, value]) => value !== undefined
|
|
38
|
+
([, value]) => value !== undefined,
|
|
40
39
|
);
|
|
41
40
|
|
|
42
41
|
if (entries.length === 0) {
|
|
@@ -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
|
+
);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { CodecOptions } from "./codec-options.js";
|
|
2
|
+
|
|
3
|
+
export enum ScrcpyLogLevel1_16 {
|
|
4
|
+
Debug = "debug",
|
|
5
|
+
Info = "info",
|
|
6
|
+
Warn = "warn",
|
|
7
|
+
Error = "error",
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export enum ScrcpyVideoOrientation1_16 {
|
|
11
|
+
Unlocked = -1,
|
|
12
|
+
Portrait = 0,
|
|
13
|
+
Landscape = 1,
|
|
14
|
+
PortraitFlipped = 2,
|
|
15
|
+
LandscapeFlipped = 3,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ScrcpyOptionsInit1_16 {
|
|
19
|
+
logLevel?: ScrcpyLogLevel1_16;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The maximum value of both width and height.
|
|
23
|
+
*/
|
|
24
|
+
maxSize?: number;
|
|
25
|
+
|
|
26
|
+
bitRate?: number;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 0 for unlimited.
|
|
30
|
+
*
|
|
31
|
+
* @default 0
|
|
32
|
+
*/
|
|
33
|
+
maxFps?: number;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The orientation of the video stream.
|
|
37
|
+
*
|
|
38
|
+
* It will not keep the device screen in specific orientation,
|
|
39
|
+
* only the captured video will in this orientation.
|
|
40
|
+
*/
|
|
41
|
+
lockVideoOrientation?: ScrcpyVideoOrientation1_16;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Use ADB forward tunnel instead of reverse tunnel.
|
|
45
|
+
*
|
|
46
|
+
* This option is mainly used for working around the bug that on Android <9,
|
|
47
|
+
* ADB daemon can't create reverse tunnels if connected wirelessly (ADB over WiFi).
|
|
48
|
+
*
|
|
49
|
+
* When using `AdbScrcpyClient`, it can detect this situation and enable this option automatically.
|
|
50
|
+
*/
|
|
51
|
+
tunnelForward?: boolean;
|
|
52
|
+
|
|
53
|
+
crop?: string | undefined;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Send PTS so that the client may record properly
|
|
57
|
+
*
|
|
58
|
+
* Note: When `sendFrameMeta: false` is specified,
|
|
59
|
+
* the video stream will not contain `configuration` typed packets,
|
|
60
|
+
* which means it can't be decoded by the companion decoders.
|
|
61
|
+
* It's still possible to record the stream into a file,
|
|
62
|
+
* or to decode it with a more tolerant decoder like FFMpeg.
|
|
63
|
+
*
|
|
64
|
+
* @default true
|
|
65
|
+
*/
|
|
66
|
+
sendFrameMeta?: boolean;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @default true
|
|
70
|
+
*/
|
|
71
|
+
control?: boolean;
|
|
72
|
+
|
|
73
|
+
displayId?: number;
|
|
74
|
+
|
|
75
|
+
showTouches?: boolean;
|
|
76
|
+
|
|
77
|
+
stayAwake?: boolean;
|
|
78
|
+
|
|
79
|
+
codecOptions?: CodecOptions;
|
|
80
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import Struct, { placeholder } from "@yume-chan/struct";
|
|
2
|
+
|
|
3
|
+
import type { AndroidMotionEventAction } from "../../control/index.js";
|
|
4
|
+
import {
|
|
5
|
+
BasicControlMessage,
|
|
6
|
+
ScrcpyControlMessageType,
|
|
7
|
+
} from "../../control/index.js";
|
|
8
|
+
|
|
9
|
+
import { ScrcpyFloatToUint16FieldDefinition } from "./float-to-uint16.js";
|
|
10
|
+
|
|
11
|
+
export const SCRCPY_CONTROL_MESSAGE_TYPES_1_16: readonly ScrcpyControlMessageType[] =
|
|
12
|
+
[
|
|
13
|
+
/* 0 */ ScrcpyControlMessageType.InjectKeyCode,
|
|
14
|
+
/* 1 */ ScrcpyControlMessageType.InjectText,
|
|
15
|
+
/* 2 */ ScrcpyControlMessageType.InjectTouch,
|
|
16
|
+
/* 3 */ ScrcpyControlMessageType.InjectScroll,
|
|
17
|
+
/* 4 */ ScrcpyControlMessageType.BackOrScreenOn,
|
|
18
|
+
/* 5 */ ScrcpyControlMessageType.ExpandNotificationPanel,
|
|
19
|
+
/* 6 */ ScrcpyControlMessageType.CollapseNotificationPanel,
|
|
20
|
+
/* 7 */ ScrcpyControlMessageType.GetClipboard,
|
|
21
|
+
/* 8 */ ScrcpyControlMessageType.SetClipboard,
|
|
22
|
+
/* 9 */ ScrcpyControlMessageType.SetScreenPowerMode,
|
|
23
|
+
/* 10 */ ScrcpyControlMessageType.RotateDevice,
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export const ScrcpyMediaStreamRawPacket = new Struct()
|
|
27
|
+
.uint64("pts")
|
|
28
|
+
.uint32("size")
|
|
29
|
+
.uint8Array("data", { lengthField: "size" });
|
|
30
|
+
|
|
31
|
+
export const SCRCPY_MEDIA_PACKET_FLAG_CONFIG = 1n << 63n;
|
|
32
|
+
|
|
33
|
+
export const ScrcpyInjectTouchControlMessage1_16 = new Struct()
|
|
34
|
+
.uint8("type")
|
|
35
|
+
.uint8("action", placeholder<AndroidMotionEventAction>())
|
|
36
|
+
.uint64("pointerId")
|
|
37
|
+
.uint32("pointerX")
|
|
38
|
+
.uint32("pointerY")
|
|
39
|
+
.uint16("screenWidth")
|
|
40
|
+
.uint16("screenHeight")
|
|
41
|
+
.field("pressure", ScrcpyFloatToUint16FieldDefinition)
|
|
42
|
+
.uint32("buttons");
|
|
43
|
+
|
|
44
|
+
export type ScrcpyInjectTouchControlMessage1_16 =
|
|
45
|
+
(typeof ScrcpyInjectTouchControlMessage1_16)["TInit"];
|
|
46
|
+
|
|
47
|
+
export const ScrcpyBackOrScreenOnControlMessage1_16 = BasicControlMessage;
|
|
48
|
+
|
|
49
|
+
export const ScrcpySetClipboardControlMessage1_15 = new Struct()
|
|
50
|
+
.uint8("type")
|
|
51
|
+
.uint32("length")
|
|
52
|
+
.string("content", { lengthField: "length" });
|
|
53
|
+
|
|
54
|
+
export type ScrcpySetClipboardControlMessage1_15 =
|
|
55
|
+
(typeof ScrcpySetClipboardControlMessage1_15)["TInit"];
|