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