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