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