@yume-chan/scrcpy 0.0.17 → 0.0.19
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 +39 -3
- package/CHANGELOG.md +22 -4
- package/LICENSE +1 -1
- package/README.md +149 -82
- package/bin/scrcpy-server +0 -0
- package/bin/version.d.ts +1 -1
- package/bin/version.js +1 -1
- package/esm/adb/client.d.ts +40 -39
- package/esm/adb/client.d.ts.map +1 -1
- package/esm/adb/client.js +223 -217
- package/esm/adb/client.js.map +1 -1
- package/esm/adb/connection.d.ts +48 -37
- package/esm/adb/connection.d.ts.map +1 -1
- package/esm/adb/connection.js +121 -101
- package/esm/adb/connection.js.map +1 -1
- package/esm/adb/index.d.ts +3 -3
- package/esm/adb/index.js +3 -3
- package/esm/adb/options/1_16.d.ts +7 -7
- package/esm/adb/options/1_16.d.ts.map +1 -1
- package/esm/adb/options/1_16.js +19 -19
- package/esm/adb/options/1_16.js.map +1 -1
- package/esm/adb/options/1_22.d.ts +7 -7
- package/esm/adb/options/1_22.d.ts.map +1 -1
- package/esm/adb/options/1_22.js +16 -16
- package/esm/adb/options/1_22.js.map +1 -1
- package/esm/adb/options/1_26.d.ts +9 -0
- package/esm/adb/options/1_26.d.ts.map +1 -0
- package/esm/adb/options/1_26.js +11 -0
- package/esm/adb/options/1_26.js.map +1 -0
- package/esm/adb/options/2_0.d.ts +8 -0
- package/esm/adb/options/2_0.d.ts.map +1 -0
- package/esm/adb/options/2_0.js +13 -0
- package/esm/adb/options/2_0.js.map +1 -0
- package/esm/adb/options/index.d.ts +3 -3
- package/esm/adb/options/index.js +3 -3
- package/esm/adb/options/types.d.ts +23 -22
- package/esm/adb/options/types.d.ts.map +1 -1
- package/esm/adb/options/types.js +36 -29
- package/esm/adb/options/types.js.map +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 +98 -0
- package/esm/codec/h264.d.ts.map +1 -0
- package/esm/codec/h264.js +477 -0
- package/esm/codec/h264.js.map +1 -0
- package/esm/codec/h265.d.ts +36 -0
- package/esm/codec/h265.d.ts.map +1 -0
- package/esm/codec/h265.js +38 -0
- package/esm/codec/h265.js.map +1 -0
- package/esm/codec/index.d.ts +4 -0
- package/esm/codec/index.d.ts.map +1 -0
- package/esm/codec/index.js +4 -0
- package/esm/codec/index.js.map +1 -0
- package/esm/codec.d.ts +33 -33
- package/esm/codec.js +36 -36
- package/esm/control/back-or-screen-on.d.ts +3 -0
- package/esm/control/back-or-screen-on.d.ts.map +1 -0
- package/esm/control/back-or-screen-on.js +2 -0
- package/esm/control/back-or-screen-on.js.map +1 -0
- 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 +18 -0
- package/esm/control/hover-helper.d.ts.map +1 -0
- package/esm/control/hover-helper.js +44 -0
- package/esm/control/hover-helper.js.map +1 -0
- package/esm/control/index.d.ts +11 -7
- package/esm/control/index.d.ts.map +1 -1
- package/esm/control/index.js +11 -7
- package/esm/control/index.js.map +1 -1
- package/esm/control/inject-keycode.d.ts +194 -52
- package/esm/control/inject-keycode.d.ts.map +1 -1
- package/esm/control/inject-keycode.js +199 -53
- package/esm/control/inject-keycode.js.map +1 -1
- package/esm/control/inject-scroll.d.ts +3 -0
- package/esm/control/inject-scroll.d.ts.map +1 -0
- package/esm/control/inject-scroll.js +2 -0
- package/esm/control/inject-scroll.js.map +1 -0
- package/esm/control/inject-text.d.ts +8 -8
- package/esm/control/inject-text.d.ts.map +1 -1
- package/esm/control/inject-text.js +6 -6
- package/esm/control/inject-text.js.map +1 -1
- package/esm/control/inject-touch.d.ts +37 -29
- package/esm/control/inject-touch.d.ts.map +1 -1
- package/esm/control/inject-touch.js +62 -29
- package/esm/control/inject-touch.js.map +1 -1
- package/esm/control/rotate-device.d.ts +6 -6
- package/esm/control/rotate-device.d.ts.map +1 -1
- package/esm/control/rotate-device.js +3 -4
- package/esm/control/rotate-device.js.map +1 -1
- package/esm/control/serializer.d.ts +35 -22
- package/esm/control/serializer.d.ts.map +1 -1
- package/esm/control/serializer.js +82 -72
- package/esm/control/serializer.js.map +1 -1
- package/esm/control/set-clipboard.d.ts +3 -0
- package/esm/control/set-clipboard.d.ts.map +1 -0
- package/esm/control/set-clipboard.js +2 -0
- package/esm/control/set-clipboard.js.map +1 -0
- package/esm/control/set-screen-power-mode.d.ts +11 -11
- package/esm/control/set-screen-power-mode.d.ts.map +1 -1
- package/esm/control/set-screen-power-mode.js +11 -11
- package/esm/control/set-screen-power-mode.js.map +1 -1
- package/esm/control/simple.d.ts +5 -0
- package/esm/control/simple.d.ts.map +1 -0
- package/esm/control/simple.js +3 -0
- package/esm/control/simple.js.map +1 -0
- package/esm/control/type.d.ts +14 -14
- package/esm/control/type.js +18 -18
- package/esm/decoder.d.ts +2 -0
- package/esm/decoder.d.ts.map +1 -0
- package/esm/decoder.js +2 -0
- package/esm/decoder.js.map +1 -0
- package/esm/device-message/ack-clipboard.d.ts +9 -0
- package/esm/device-message/ack-clipboard.d.ts.map +1 -0
- package/esm/device-message/ack-clipboard.js +6 -0
- package/esm/device-message/ack-clipboard.js.map +1 -0
- 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/clipboard.js.map +1 -1
- package/esm/device-message/index.d.ts +4 -3
- package/esm/device-message/index.d.ts.map +1 -1
- package/esm/device-message/index.js +4 -3
- package/esm/device-message/index.js.map +1 -1
- package/esm/device-message/stream.d.ts +7 -6
- package/esm/device-message/stream.d.ts.map +1 -1
- package/esm/device-message/stream.js +19 -15
- 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 +5 -5
- package/esm/index.js +5 -5
- package/esm/options/1.17.d.ts +3 -0
- package/esm/options/1.17.d.ts.map +1 -0
- package/esm/options/1.17.js +2 -0
- package/esm/options/1.17.js.map +1 -0
- package/esm/options/1_16/codec-options.d.ts +20 -18
- package/esm/options/1_16/codec-options.d.ts.map +1 -1
- package/esm/options/1_16/codec-options.js +25 -26
- 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/h264-configuration.d.ts +49 -0
- package/esm/options/1_16/h264-configuration.d.ts.map +1 -0
- package/esm/options/1_16/h264-configuration.js +414 -0
- package/esm/options/1_16/h264-configuration.js.map +1 -0
- package/esm/options/1_16/index.d.ts +4 -3
- package/esm/options/1_16/index.d.ts.map +1 -1
- package/esm/options/1_16/index.js +4 -3
- 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 +102 -96
- package/esm/options/1_16/options.d.ts.map +1 -1
- package/esm/options/1_16/options.js +189 -187
- package/esm/options/1_16/options.js.map +1 -1
- package/esm/options/1_16/scroll.d.ts +28 -0
- package/esm/options/1_16/scroll.d.ts.map +1 -0
- package/esm/options/1_16/scroll.js +56 -0
- package/esm/options/1_16/scroll.js.map +1 -0
- package/esm/options/1_16/sps.d.ts +1 -1
- package/esm/options/1_16/sps.d.ts.map +1 -1
- package/esm/options/1_16/sps.js +25 -17
- package/esm/options/1_16/sps.js.map +1 -1
- package/esm/options/1_17.d.ts +32 -0
- package/esm/options/1_17.d.ts.map +1 -0
- package/esm/options/1_17.js +36 -0
- package/esm/options/1_17.js.map +1 -0
- package/esm/options/1_18.d.ts +21 -19
- package/esm/options/1_18.d.ts.map +1 -1
- package/esm/options/1_18.js +45 -45
- package/esm/options/1_18.js.map +1 -1
- package/esm/options/1_21.d.ts +22 -9
- package/esm/options/1_21.d.ts.map +1 -1
- package/esm/options/1_21.js +36 -25
- package/esm/options/1_21.js.map +1 -1
- package/esm/options/1_22/index.d.ts +3 -0
- package/esm/options/1_22/index.d.ts.map +1 -0
- package/esm/options/1_22/index.js +3 -0
- package/esm/options/1_22/index.js.map +1 -0
- 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.d.ts → 1_22/options.d.ts} +30 -40
- package/esm/options/1_22/options.d.ts.map +1 -0
- package/esm/options/{1_22.js → 1_22/options.js} +26 -30
- package/esm/options/1_22/options.js.map +1 -0
- package/esm/options/1_22/scroll.d.ts +17 -0
- package/esm/options/1_22/scroll.d.ts.map +1 -0
- package/esm/options/1_22/scroll.js +15 -0
- package/esm/options/1_22/scroll.js.map +1 -0
- package/esm/options/1_23.d.ts +12 -11
- package/esm/options/1_23.d.ts.map +1 -1
- package/esm/options/1_23.js +34 -33
- package/esm/options/1_23.js.map +1 -1
- package/esm/options/1_24.d.ts +9 -8
- package/esm/options/1_24.d.ts.map +1 -1
- package/esm/options/1_24.js +12 -12
- package/esm/options/1_24.js.map +1 -1
- package/esm/options/1_25/index.d.ts +3 -0
- package/esm/options/1_25/index.d.ts.map +1 -0
- package/esm/options/1_25/index.js +3 -0
- package/esm/options/1_25/index.js.map +1 -0
- package/esm/options/1_25/options.d.ts +7 -0
- package/esm/options/1_25/options.d.ts.map +1 -0
- package/esm/options/1_25/options.js +8 -0
- package/esm/options/1_25/options.js.map +1 -0
- package/esm/options/1_25/scroll.d.ts +20 -0
- package/esm/options/1_25/scroll.d.ts.map +1 -0
- package/esm/options/1_25/scroll.js +33 -0
- package/esm/options/1_25/scroll.js.map +1 -0
- package/esm/options/1_26.d.ts +57 -0
- package/esm/options/1_26.d.ts.map +1 -0
- package/esm/options/1_26.js +67 -0
- package/esm/options/1_26.js.map +1 -0
- package/esm/options/2.d.ts +57 -0
- package/esm/options/2.d.ts.map +1 -0
- package/esm/options/2.js +67 -0
- package/esm/options/2.js.map +1 -0
- package/esm/options/2_0.d.ts +87 -0
- package/esm/options/2_0.d.ts.map +1 -0
- package/esm/options/2_0.js +175 -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 +8 -7
- package/esm/options/index.d.ts.map +1 -1
- package/esm/options/index.js +8 -7
- 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 +46 -44
- package/esm/options/types.d.ts.map +1 -1
- package/esm/options/types.js +17 -15
- package/esm/options/types.js.map +1 -1
- package/package.json +20 -12
- package/scripts/fetch-server.cjs +19 -9
- package/src/adb/client.ts +184 -147
- package/src/adb/connection.ts +95 -31
- package/src/adb/index.ts +3 -3
- package/src/adb/options/1_16.ts +15 -6
- package/src/adb/options/1_22.ts +12 -6
- package/src/adb/options/index.ts +3 -3
- package/src/adb/options/types.ts +34 -14
- package/src/control/back-or-screen-on.ts +4 -0
- package/src/control/hover-helper.ts +54 -0
- package/src/control/index.ts +11 -7
- package/src/control/inject-keycode.ts +203 -45
- package/src/control/inject-scroll.ts +4 -0
- package/src/control/inject-text.ts +7 -8
- package/src/control/inject-touch.ts +58 -14
- package/src/control/rotate-device.ts +7 -6
- package/src/control/serializer.ts +111 -43
- package/src/control/set-clipboard.ts +4 -0
- package/src/control/set-screen-power-mode.ts +7 -8
- package/src/device-message/ack-clipboard.ts +10 -0
- package/src/device-message/clipboard.ts +8 -8
- package/src/device-message/index.ts +4 -3
- package/src/device-message/stream.ts +17 -7
- package/src/index.ts +5 -5
- package/src/options/1_16/codec-options.ts +16 -11
- package/src/options/1_16/h264-configuration.ts +485 -0
- package/src/options/1_16/index.ts +4 -3
- package/src/options/1_16/options.ts +180 -130
- package/src/options/1_16/scroll.ts +74 -0
- package/src/options/1_18.ts +22 -12
- package/src/options/1_21.ts +30 -13
- package/src/options/1_22/index.ts +2 -0
- package/src/options/{1_22.ts → 1_22/options.ts} +9 -17
- package/src/options/1_22/scroll.ts +26 -0
- package/src/options/1_23.ts +30 -20
- package/src/options/1_24.ts +5 -3
- package/src/options/1_25/index.ts +2 -0
- package/src/options/1_25/options.ts +13 -0
- package/src/options/1_25/scroll.ts +49 -0
- package/src/options/index.ts +8 -7
- package/src/options/types.ts +36 -19
- package/tsconfig.build.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/decoder/index.d.ts +0 -28
- package/esm/decoder/index.d.ts.map +0 -1
- package/esm/decoder/index.js +0 -2
- package/esm/decoder/index.js.map +0 -1
- package/esm/decoder/tinyh264/index.d.ts +0 -20
- package/esm/decoder/tinyh264/index.d.ts.map +0 -1
- package/esm/decoder/tinyh264/index.js +0 -86
- package/esm/decoder/tinyh264/index.js.map +0 -1
- package/esm/decoder/tinyh264/worker.d.ts +0 -2
- package/esm/decoder/tinyh264/worker.d.ts.map +0 -1
- package/esm/decoder/tinyh264/worker.js +0 -3
- package/esm/decoder/tinyh264/worker.js.map +0 -1
- package/esm/decoder/tinyh264/wrapper.d.ts +0 -21
- package/esm/decoder/tinyh264/wrapper.d.ts.map +0 -1
- package/esm/decoder/tinyh264/wrapper.js +0 -74
- package/esm/decoder/tinyh264/wrapper.js.map +0 -1
- package/esm/decoder/types.d.ts +0 -2
- package/esm/decoder/types.d.ts.map +0 -1
- package/esm/decoder/types.js +0 -2
- package/esm/decoder/types.js.map +0 -1
- package/esm/decoder/web-codecs/index.d.ts +0 -22
- package/esm/decoder/web-codecs/index.d.ts.map +0 -1
- package/esm/decoder/web-codecs/index.js +0 -81
- package/esm/decoder/web-codecs/index.js.map +0 -1
- package/esm/options/1_22.d.ts.map +0 -1
- package/esm/options/1_22.js.map +0 -1
- package/src/options/1_16/sps.ts +0 -300
- package/tsconfig.test.tsbuildinfo +0 -1
package/src/adb/client.ts
CHANGED
|
@@ -1,103 +1,114 @@
|
|
|
1
|
-
import { Adb,
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import type { Adb, AdbSubprocessProtocol } from "@yume-chan/adb";
|
|
2
|
+
import {
|
|
3
|
+
AdbReverseNotSupportedError,
|
|
4
|
+
AdbSubprocessNoneProtocol,
|
|
5
|
+
} from "@yume-chan/adb";
|
|
6
|
+
import type {
|
|
7
|
+
Consumable,
|
|
8
|
+
ReadableStream,
|
|
9
|
+
ReadableWritablePair,
|
|
10
|
+
} from "@yume-chan/stream-extra";
|
|
11
|
+
import {
|
|
12
|
+
AbortController,
|
|
13
|
+
DecodeUtf8Stream,
|
|
14
|
+
InspectStream,
|
|
15
|
+
PushReadableStream,
|
|
16
|
+
SplitStringStream,
|
|
17
|
+
WritableStream,
|
|
18
|
+
} from "@yume-chan/stream-extra";
|
|
19
|
+
|
|
20
|
+
import { ScrcpyControlMessageSerializer } from "../control/index.js";
|
|
21
|
+
import type { ScrcpyDeviceMessage } from "../device-message/index.js";
|
|
22
|
+
import { ScrcpyDeviceMessageDeserializeStream } from "../device-message/index.js";
|
|
23
|
+
import type {
|
|
24
|
+
ScrcpyOptionsInit1_16,
|
|
25
|
+
ScrcpyVideoStreamPacket,
|
|
26
|
+
} from "../options/index.js";
|
|
27
|
+
import { DEFAULT_SERVER_PATH } from "../options/index.js";
|
|
28
|
+
|
|
29
|
+
import type { AdbScrcpyConnection } from "./connection.js";
|
|
30
|
+
import type { AdbScrcpyOptions } from "./options/index.js";
|
|
31
|
+
|
|
32
|
+
function arrayToStream<T>(array: T[]): ReadableStream<T> {
|
|
33
|
+
return new PushReadableStream(async (controller) => {
|
|
34
|
+
for (const item of array) {
|
|
35
|
+
await controller.enqueue(item);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
29
38
|
}
|
|
30
39
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.streams = streams;
|
|
42
|
-
this.advance(controller);
|
|
43
|
-
},
|
|
44
|
-
pull: async (controller) => {
|
|
45
|
-
const result = await this.reader.read();
|
|
46
|
-
if (!result.done) {
|
|
47
|
-
controller.enqueue(result.value);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
this.advance(controller);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private advance(controller: ReadableStreamDefaultController<T>) {
|
|
56
|
-
if (this.index < this.streams.length) {
|
|
57
|
-
this.reader = this.streams[this.index]!.getReader();
|
|
58
|
-
this.index += 1;
|
|
59
|
-
} else {
|
|
60
|
-
controller.close();
|
|
40
|
+
function concatStreams<T>(...streams: ReadableStream<T>[]): ReadableStream<T> {
|
|
41
|
+
return new PushReadableStream(async (controller) => {
|
|
42
|
+
for (const stream of streams) {
|
|
43
|
+
await stream.pipeTo(
|
|
44
|
+
new WritableStream({
|
|
45
|
+
async write(chunk) {
|
|
46
|
+
await controller.enqueue(chunk);
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
);
|
|
61
50
|
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class ScrcpyExitedError extends Error {
|
|
55
|
+
public output: string[];
|
|
56
|
+
|
|
57
|
+
public constructor(output: string[]) {
|
|
58
|
+
super("scrcpy server exited prematurely");
|
|
59
|
+
this.output = output;
|
|
62
60
|
}
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
export class AdbScrcpyClient {
|
|
66
|
-
public static pushServer(
|
|
64
|
+
public static async pushServer(
|
|
67
65
|
adb: Adb,
|
|
68
|
-
|
|
66
|
+
file: ReadableStream<Consumable<Uint8Array>>,
|
|
67
|
+
filename = DEFAULT_SERVER_PATH
|
|
69
68
|
) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
69
|
+
const sync = await adb.sync();
|
|
70
|
+
try {
|
|
71
|
+
await sync.write({
|
|
72
|
+
filename,
|
|
73
|
+
file,
|
|
74
|
+
});
|
|
75
|
+
} finally {
|
|
76
|
+
await sync.dispose();
|
|
77
|
+
}
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
public static async start(
|
|
83
81
|
adb: Adb,
|
|
84
82
|
path: string,
|
|
85
83
|
version: string,
|
|
86
|
-
options: AdbScrcpyOptions<
|
|
84
|
+
options: AdbScrcpyOptions<ScrcpyOptionsInit1_16>
|
|
87
85
|
) {
|
|
88
|
-
|
|
86
|
+
let connection: AdbScrcpyConnection | undefined;
|
|
89
87
|
let process: AdbSubprocessProtocol | undefined;
|
|
90
88
|
|
|
91
89
|
try {
|
|
92
|
-
|
|
90
|
+
try {
|
|
91
|
+
connection = options.createConnection(adb);
|
|
92
|
+
await connection.initialize();
|
|
93
|
+
} catch (e) {
|
|
94
|
+
if (e instanceof AdbReverseNotSupportedError) {
|
|
95
|
+
// When reverse tunnel is not supported, try forward tunnel.
|
|
96
|
+
options.value.tunnelForward = true;
|
|
97
|
+
connection = options.createConnection(adb);
|
|
98
|
+
await connection.initialize();
|
|
99
|
+
} else {
|
|
100
|
+
connection = undefined;
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
93
104
|
|
|
94
105
|
process = await adb.subprocess.spawn(
|
|
95
106
|
[
|
|
96
107
|
// cspell: disable-next-line
|
|
97
108
|
`CLASSPATH=${path}`,
|
|
98
|
-
|
|
99
|
-
/* unused */
|
|
100
|
-
|
|
109
|
+
"app_process",
|
|
110
|
+
/* unused */ "/",
|
|
111
|
+
"com.genymobile.scrcpy.Server",
|
|
101
112
|
version,
|
|
102
113
|
...options.formatServerArguments(),
|
|
103
114
|
],
|
|
@@ -110,31 +121,34 @@ export class AdbScrcpyClient {
|
|
|
110
121
|
|
|
111
122
|
const stdout = process.stdout
|
|
112
123
|
.pipeThrough(new DecodeUtf8Stream())
|
|
113
|
-
.pipeThrough(new SplitStringStream(
|
|
124
|
+
.pipeThrough(new SplitStringStream("\n"));
|
|
114
125
|
|
|
115
126
|
// Read stdout, otherwise `process.exit` won't resolve.
|
|
116
127
|
const output: string[] = [];
|
|
117
128
|
const abortController = new AbortController();
|
|
118
129
|
const pipe = stdout
|
|
119
|
-
.pipeTo(
|
|
120
|
-
|
|
121
|
-
|
|
130
|
+
.pipeTo(
|
|
131
|
+
new WritableStream({
|
|
132
|
+
write(chunk) {
|
|
133
|
+
output.push(chunk);
|
|
134
|
+
},
|
|
135
|
+
}),
|
|
136
|
+
{
|
|
137
|
+
signal: abortController.signal,
|
|
138
|
+
preventCancel: true,
|
|
122
139
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
})
|
|
127
|
-
.catch(() => { });
|
|
140
|
+
)
|
|
141
|
+
.catch((e) => {
|
|
142
|
+
void e;
|
|
143
|
+
});
|
|
128
144
|
|
|
129
145
|
const result = await Promise.race([
|
|
130
146
|
process.exit,
|
|
131
147
|
connection.getStreams(),
|
|
132
148
|
]);
|
|
133
149
|
|
|
134
|
-
if (typeof result ===
|
|
135
|
-
|
|
136
|
-
(error as any).output = output;
|
|
137
|
-
throw error;
|
|
150
|
+
if (typeof result === "number") {
|
|
151
|
+
throw new ScrcpyExitedError(output);
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
abortController.abort();
|
|
@@ -144,10 +158,7 @@ export class AdbScrcpyClient {
|
|
|
144
158
|
return new AdbScrcpyClient(
|
|
145
159
|
options,
|
|
146
160
|
process,
|
|
147
|
-
|
|
148
|
-
new ArrayToStream(output),
|
|
149
|
-
stdout,
|
|
150
|
-
),
|
|
161
|
+
concatStreams(arrayToStream(output), stdout),
|
|
151
162
|
videoStream,
|
|
152
163
|
controlStream
|
|
153
164
|
);
|
|
@@ -155,7 +166,7 @@ export class AdbScrcpyClient {
|
|
|
155
166
|
await process?.kill();
|
|
156
167
|
throw e;
|
|
157
168
|
} finally {
|
|
158
|
-
connection
|
|
169
|
+
connection?.dispose();
|
|
159
170
|
}
|
|
160
171
|
}
|
|
161
172
|
|
|
@@ -167,35 +178,34 @@ export class AdbScrcpyClient {
|
|
|
167
178
|
adb: Adb,
|
|
168
179
|
path: string,
|
|
169
180
|
version: string,
|
|
170
|
-
options: AdbScrcpyOptions<
|
|
181
|
+
options: AdbScrcpyOptions<ScrcpyOptionsInit1_16>
|
|
171
182
|
): Promise<string[]> {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
Object.assign(options.value, {
|
|
184
|
+
// Provide an invalid encoder name
|
|
185
|
+
// So the server will return all available encoders
|
|
186
|
+
encoderName: "_",
|
|
187
|
+
// Disable control for faster connection in 1.22+
|
|
188
|
+
control: false,
|
|
189
|
+
sendDeviceMeta: false,
|
|
190
|
+
sendDummyByte: false,
|
|
191
|
+
});
|
|
179
192
|
|
|
180
193
|
// Scrcpy server will open connections, before initializing encoder
|
|
181
194
|
// Thus although an invalid encoder name is given, the start process will success
|
|
182
|
-
const client = await AdbScrcpyClient.start(
|
|
183
|
-
adb,
|
|
184
|
-
path,
|
|
185
|
-
version,
|
|
186
|
-
options
|
|
187
|
-
);
|
|
195
|
+
const client = await AdbScrcpyClient.start(adb, path, version, options);
|
|
188
196
|
|
|
189
197
|
const encoderNameRegex = options.getOutputEncoderNameRegex();
|
|
190
198
|
const encoders: string[] = [];
|
|
191
|
-
await client.stdout.pipeTo(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
await client.stdout.pipeTo(
|
|
200
|
+
new WritableStream({
|
|
201
|
+
write(line) {
|
|
202
|
+
const match = line.match(encoderNameRegex);
|
|
203
|
+
if (match) {
|
|
204
|
+
encoders.push(match[1]!);
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
);
|
|
199
209
|
|
|
200
210
|
return encoders;
|
|
201
211
|
}
|
|
@@ -208,25 +218,25 @@ export class AdbScrcpyClient {
|
|
|
208
218
|
adb: Adb,
|
|
209
219
|
path: string,
|
|
210
220
|
version: string,
|
|
211
|
-
options: AdbScrcpyOptions<
|
|
221
|
+
options: AdbScrcpyOptions<ScrcpyOptionsInit1_16>
|
|
212
222
|
): Promise<number[]> {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
223
|
+
Object.assign(options.value, {
|
|
224
|
+
// Similar to `getEncoders`, pass an invalid option and parse the output
|
|
225
|
+
displayId: -1,
|
|
226
|
+
// Disable control for faster connection in 1.22+
|
|
227
|
+
control: false,
|
|
228
|
+
sendDeviceMeta: false,
|
|
229
|
+
sendDummyByte: false,
|
|
230
|
+
});
|
|
219
231
|
|
|
220
232
|
try {
|
|
221
233
|
// Server will exit before opening connections when an invalid display id was given.
|
|
222
234
|
await AdbScrcpyClient.start(adb, path, version, options);
|
|
223
235
|
} catch (e) {
|
|
224
|
-
if (e instanceof
|
|
225
|
-
const output = (e as any).output as string[];
|
|
226
|
-
|
|
236
|
+
if (e instanceof ScrcpyExitedError) {
|
|
227
237
|
const displayIdRegex = /\s+scrcpy --display (\d+)/;
|
|
228
238
|
const displays: number[] = [];
|
|
229
|
-
for (const line of output) {
|
|
239
|
+
for (const line of e.output) {
|
|
230
240
|
const match = line.match(displayIdRegex);
|
|
231
241
|
if (match) {
|
|
232
242
|
displays.push(Number.parseInt(match[1]!, 10));
|
|
@@ -236,53 +246,80 @@ export class AdbScrcpyClient {
|
|
|
236
246
|
}
|
|
237
247
|
}
|
|
238
248
|
|
|
239
|
-
throw new Error(
|
|
249
|
+
throw new Error("failed to get displays");
|
|
240
250
|
}
|
|
241
251
|
|
|
242
252
|
private process: AdbSubprocessProtocol;
|
|
243
253
|
|
|
244
254
|
private _stdout: ReadableStream<string>;
|
|
245
|
-
public get stdout() {
|
|
255
|
+
public get stdout() {
|
|
256
|
+
return this._stdout;
|
|
257
|
+
}
|
|
246
258
|
|
|
247
|
-
public get exit() {
|
|
259
|
+
public get exit() {
|
|
260
|
+
return this.process.exit;
|
|
261
|
+
}
|
|
248
262
|
|
|
249
263
|
private _screenWidth: number | undefined;
|
|
250
|
-
public get screenWidth() {
|
|
264
|
+
public get screenWidth() {
|
|
265
|
+
return this._screenWidth;
|
|
266
|
+
}
|
|
251
267
|
|
|
252
268
|
private _screenHeight: number | undefined;
|
|
253
|
-
public get screenHeight() {
|
|
269
|
+
public get screenHeight() {
|
|
270
|
+
return this._screenHeight;
|
|
271
|
+
}
|
|
254
272
|
|
|
255
273
|
private _videoStream: ReadableStream<ScrcpyVideoStreamPacket>;
|
|
256
|
-
public get videoStream() {
|
|
274
|
+
public get videoStream() {
|
|
275
|
+
return this._videoStream;
|
|
276
|
+
}
|
|
257
277
|
|
|
258
|
-
private _controlMessageSerializer:
|
|
259
|
-
|
|
278
|
+
private _controlMessageSerializer:
|
|
279
|
+
| ScrcpyControlMessageSerializer
|
|
280
|
+
| undefined;
|
|
281
|
+
public get controlMessageSerializer() {
|
|
282
|
+
return this._controlMessageSerializer;
|
|
283
|
+
}
|
|
260
284
|
|
|
261
|
-
private _deviceMessageStream:
|
|
262
|
-
|
|
285
|
+
private _deviceMessageStream:
|
|
286
|
+
| ReadableStream<ScrcpyDeviceMessage>
|
|
287
|
+
| undefined;
|
|
288
|
+
public get deviceMessageStream() {
|
|
289
|
+
return this._deviceMessageStream;
|
|
290
|
+
}
|
|
263
291
|
|
|
264
292
|
public constructor(
|
|
265
|
-
options: AdbScrcpyOptions<
|
|
293
|
+
options: AdbScrcpyOptions<ScrcpyOptionsInit1_16>,
|
|
266
294
|
process: AdbSubprocessProtocol,
|
|
267
295
|
stdout: ReadableStream<string>,
|
|
268
296
|
videoStream: ReadableStream<Uint8Array>,
|
|
269
|
-
controlStream:
|
|
297
|
+
controlStream:
|
|
298
|
+
| ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
299
|
+
| undefined
|
|
270
300
|
) {
|
|
271
301
|
this.process = process;
|
|
272
302
|
this._stdout = stdout;
|
|
273
303
|
|
|
274
304
|
this._videoStream = videoStream
|
|
275
305
|
.pipeThrough(options.createVideoStreamTransformer())
|
|
276
|
-
.pipeThrough(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
306
|
+
.pipeThrough(
|
|
307
|
+
new InspectStream((packet) => {
|
|
308
|
+
if (packet.type === "configuration") {
|
|
309
|
+
this._screenWidth = packet.data.croppedWidth;
|
|
310
|
+
this._screenHeight = packet.data.croppedHeight;
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
);
|
|
282
314
|
|
|
283
315
|
if (controlStream) {
|
|
284
|
-
this._controlMessageSerializer = new ScrcpyControlMessageSerializer(
|
|
285
|
-
|
|
316
|
+
this._controlMessageSerializer = new ScrcpyControlMessageSerializer(
|
|
317
|
+
controlStream.writable,
|
|
318
|
+
options
|
|
319
|
+
);
|
|
320
|
+
this._deviceMessageStream = controlStream.readable.pipeThrough(
|
|
321
|
+
new ScrcpyDeviceMessageDeserializeStream()
|
|
322
|
+
);
|
|
286
323
|
}
|
|
287
324
|
}
|
|
288
325
|
|
package/src/adb/connection.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import type { Adb } from
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import type {
|
|
1
|
+
import type { Adb } from "@yume-chan/adb";
|
|
2
|
+
import { AdbReverseNotSupportedError } from "@yume-chan/adb";
|
|
3
|
+
import { delay } from "@yume-chan/async";
|
|
4
|
+
import type { Disposable } from "@yume-chan/event";
|
|
5
|
+
import type {
|
|
6
|
+
Consumable,
|
|
7
|
+
ReadableStream,
|
|
8
|
+
ReadableStreamDefaultReader,
|
|
9
|
+
ReadableWritablePair,
|
|
10
|
+
} from "@yume-chan/stream-extra";
|
|
11
|
+
import { TransformStream } from "@yume-chan/stream-extra";
|
|
12
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
6
13
|
|
|
7
14
|
export interface AdbScrcpyConnectionOptions {
|
|
8
15
|
control: boolean;
|
|
@@ -28,20 +35,37 @@ export abstract class AdbScrcpyConnection implements Disposable {
|
|
|
28
35
|
this.options = options;
|
|
29
36
|
}
|
|
30
37
|
|
|
31
|
-
public initialize(): ValueOrPromise<void> {
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
public initialize(): ValueOrPromise<void> {
|
|
39
|
+
// do nothing
|
|
40
|
+
}
|
|
34
41
|
|
|
35
|
-
public
|
|
42
|
+
public abstract getStreams(): ValueOrPromise<
|
|
43
|
+
[
|
|
44
|
+
videoSteam: ReadableStream<Uint8Array>,
|
|
45
|
+
controlStream:
|
|
46
|
+
| ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
47
|
+
| undefined
|
|
48
|
+
]
|
|
49
|
+
>;
|
|
50
|
+
|
|
51
|
+
public dispose(): void {
|
|
52
|
+
// do nothing
|
|
53
|
+
}
|
|
36
54
|
}
|
|
37
55
|
|
|
38
56
|
export class AdbScrcpyForwardConnection extends AdbScrcpyConnection {
|
|
39
|
-
private
|
|
40
|
-
|
|
57
|
+
private _disposed = false;
|
|
58
|
+
|
|
59
|
+
private connect(): Promise<
|
|
60
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
61
|
+
> {
|
|
62
|
+
return this.adb.createSocket("localabstract:scrcpy");
|
|
41
63
|
}
|
|
42
64
|
|
|
43
|
-
private async connectAndRetry(): Promise<
|
|
44
|
-
|
|
65
|
+
private async connectAndRetry(): Promise<
|
|
66
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
67
|
+
> {
|
|
68
|
+
for (let i = 0; !this._disposed && i < 100; i += 1) {
|
|
45
69
|
try {
|
|
46
70
|
return await this.connect();
|
|
47
71
|
} catch (e) {
|
|
@@ -58,17 +82,26 @@ export class AdbScrcpyForwardConnection extends AdbScrcpyConnection {
|
|
|
58
82
|
const { done, value } = await reader.read();
|
|
59
83
|
// server will write a `0` to signal connection success
|
|
60
84
|
if (done || value.byteLength !== 1 || value[0] !== 0) {
|
|
61
|
-
throw new Error(
|
|
85
|
+
throw new Error("Unexpected response from server");
|
|
62
86
|
}
|
|
63
87
|
reader.releaseLock();
|
|
64
88
|
}
|
|
65
89
|
return videoStream;
|
|
66
90
|
}
|
|
67
91
|
|
|
68
|
-
public async getStreams(): Promise<
|
|
92
|
+
public override async getStreams(): Promise<
|
|
93
|
+
[
|
|
94
|
+
videoSteam: ReadableStream<Uint8Array>,
|
|
95
|
+
controlStream:
|
|
96
|
+
| ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
97
|
+
| undefined
|
|
98
|
+
]
|
|
99
|
+
> {
|
|
69
100
|
const videoStream = await this.connectVideoStream();
|
|
70
101
|
|
|
71
|
-
let controlStream:
|
|
102
|
+
let controlStream:
|
|
103
|
+
| ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
104
|
+
| undefined;
|
|
72
105
|
if (this.options.control) {
|
|
73
106
|
controlStream = await this.connectAndRetry();
|
|
74
107
|
}
|
|
@@ -79,45 +112,74 @@ export class AdbScrcpyForwardConnection extends AdbScrcpyConnection {
|
|
|
79
112
|
const { done, value } = await reader.read();
|
|
80
113
|
// 64 bytes device name + 2 bytes video width + 2 bytes video height
|
|
81
114
|
if (done || value.byteLength !== 64 + 2 + 2) {
|
|
82
|
-
throw new Error(
|
|
115
|
+
throw new Error("Unexpected response from server");
|
|
83
116
|
}
|
|
84
117
|
reader.releaseLock();
|
|
85
118
|
}
|
|
86
119
|
|
|
87
120
|
return [videoStream, controlStream];
|
|
88
121
|
}
|
|
122
|
+
|
|
123
|
+
public override dispose(): void {
|
|
124
|
+
super.dispose();
|
|
125
|
+
this._disposed = true;
|
|
126
|
+
}
|
|
89
127
|
}
|
|
90
128
|
|
|
91
129
|
export class AdbScrcpyReverseConnection extends AdbScrcpyConnection {
|
|
92
|
-
private streams!: ReadableStreamDefaultReader<
|
|
130
|
+
private streams!: ReadableStreamDefaultReader<
|
|
131
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
132
|
+
>;
|
|
93
133
|
|
|
94
134
|
private address!: string;
|
|
95
135
|
|
|
96
136
|
public override async initialize(): Promise<void> {
|
|
97
|
-
|
|
98
|
-
|
|
137
|
+
try {
|
|
138
|
+
// try to unbind first
|
|
139
|
+
await this.adb.reverse.remove("localabstract:scrcpy");
|
|
140
|
+
} catch (e) {
|
|
141
|
+
if (e instanceof AdbReverseNotSupportedError) {
|
|
142
|
+
throw e;
|
|
143
|
+
}
|
|
99
144
|
|
|
100
|
-
|
|
145
|
+
// Ignore other errors when unbinding
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const queue = new TransformStream<
|
|
149
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>,
|
|
150
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
151
|
+
>();
|
|
101
152
|
this.streams = queue.readable.getReader();
|
|
102
153
|
const writer = queue.writable.getWriter();
|
|
103
154
|
this.address = await this.adb.reverse.add(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
socket => {
|
|
107
|
-
writer.write(socket);
|
|
155
|
+
"localabstract:scrcpy",
|
|
156
|
+
"tcp:27183",
|
|
157
|
+
(socket) => {
|
|
158
|
+
void writer.write(socket);
|
|
108
159
|
return true;
|
|
109
|
-
}
|
|
160
|
+
}
|
|
110
161
|
);
|
|
111
162
|
}
|
|
112
163
|
|
|
113
|
-
private async accept(): Promise<
|
|
164
|
+
private async accept(): Promise<
|
|
165
|
+
ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
166
|
+
> {
|
|
114
167
|
return (await this.streams.read()).value!;
|
|
115
168
|
}
|
|
116
169
|
|
|
117
|
-
public async getStreams(): Promise<
|
|
170
|
+
public async getStreams(): Promise<
|
|
171
|
+
[
|
|
172
|
+
videoSteam: ReadableStream<Uint8Array>,
|
|
173
|
+
controlStream:
|
|
174
|
+
| ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
175
|
+
| undefined
|
|
176
|
+
]
|
|
177
|
+
> {
|
|
118
178
|
const { readable: videoStream } = await this.accept();
|
|
119
179
|
|
|
120
|
-
let controlStream:
|
|
180
|
+
let controlStream:
|
|
181
|
+
| ReadableWritablePair<Uint8Array, Consumable<Uint8Array>>
|
|
182
|
+
| undefined;
|
|
121
183
|
if (this.options.control) {
|
|
122
184
|
controlStream = await this.accept();
|
|
123
185
|
}
|
|
@@ -128,7 +190,7 @@ export class AdbScrcpyReverseConnection extends AdbScrcpyConnection {
|
|
|
128
190
|
const { done, value } = await reader.read();
|
|
129
191
|
// 64 bytes device name + 2 bytes video width + 2 bytes video height
|
|
130
192
|
if (done || value.byteLength !== 64 + 2 + 2) {
|
|
131
|
-
throw new Error(
|
|
193
|
+
throw new Error("Unexpected response from server");
|
|
132
194
|
}
|
|
133
195
|
reader.releaseLock();
|
|
134
196
|
}
|
|
@@ -140,6 +202,8 @@ export class AdbScrcpyReverseConnection extends AdbScrcpyConnection {
|
|
|
140
202
|
// Don't await this!
|
|
141
203
|
// `reverse.remove`'s response will never arrive
|
|
142
204
|
// before we read all pending data from `videoStream`
|
|
143
|
-
this.adb.reverse.remove(this.address)
|
|
205
|
+
this.adb.reverse.remove(this.address).catch((e) => {
|
|
206
|
+
void e;
|
|
207
|
+
});
|
|
144
208
|
}
|
|
145
209
|
}
|
package/src/adb/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from "./options/index.js";
|
|
2
|
+
export * from "./client.js";
|
|
3
|
+
export * from "./connection.js";
|