@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
@@ -1,19 +1,35 @@
1
- import { StructDeserializeStream, TransformStream } from '@yume-chan/stream-extra';
2
- import Struct from '@yume-chan/struct';
3
-
4
- import { AndroidKeyEventAction, ScrcpyControlMessageType } from '../../control/index.js';
5
- import type { ScrcpyBackOrScreenOnControlMessage1_18 } from '../1_18.js';
6
- import type { ScrcpyInjectScrollControlMessage1_22 } from '../1_22.js';
7
- import { toScrcpyOptionValue, type ScrcpyOptions, type ScrcpyVideoStreamPacket } from '../types.js';
8
- import { CodecOptions } from './codec-options.js';
9
- import { parse_sequence_parameter_set } from './sps.js';
1
+ import {
2
+ StructDeserializeStream,
3
+ TransformStream,
4
+ } from "@yume-chan/stream-extra";
5
+ import Struct from "@yume-chan/struct";
6
+
7
+ import type {
8
+ ScrcpyBackOrScreenOnControlMessage,
9
+ ScrcpySetClipboardControlMessage,
10
+ } from "../../control/index.js";
11
+ import {
12
+ AndroidKeyEventAction,
13
+ ScrcpyControlMessageType,
14
+ } from "../../control/index.js";
15
+ import type { ScrcpyOptions, ScrcpyVideoStreamPacket } from "../types.js";
16
+ import { toScrcpyOptionValue } from "../types.js";
17
+
18
+ import { CodecOptions } from "./codec-options.js";
19
+ import {
20
+ parseH264Configuration,
21
+ parseSequenceParameterSet,
22
+ removeH264Emulation,
23
+ } from "./h264-configuration.js";
24
+ import type { ScrcpyScrollController } from "./scroll.js";
25
+ import { ScrcpyScrollController1_16 } from "./scroll.js";
10
26
 
11
27
  export enum ScrcpyLogLevel {
12
- Verbose = 'verbose',
13
- Debug = 'debug',
14
- Info = 'info',
15
- Warn = 'warn',
16
- Error = 'error',
28
+ Verbose = "verbose",
29
+ Debug = "debug",
30
+ Info = "info",
31
+ Warn = "warn",
32
+ Error = "error",
17
33
  }
18
34
 
19
35
  export enum ScrcpyVideoOrientation {
@@ -50,6 +66,14 @@ export interface ScrcpyOptionsInit1_16 {
50
66
  */
51
67
  lockVideoOrientation: ScrcpyVideoOrientation;
52
68
 
69
+ /**
70
+ * Use ADB forward tunnel instead of reverse tunnel.
71
+ *
72
+ * This option is mainly used for working around the bug that on Android <9,
73
+ * ADB daemon can't create reverse tunnels if connected wirelessly (ADB over WiFi).
74
+ *
75
+ * When using `AdbScrcpyClient`, it can detect this situation and enable this option automatically.
76
+ */
53
77
  tunnelForward: boolean;
54
78
 
55
79
  crop: string;
@@ -83,40 +107,44 @@ export interface ScrcpyOptionsInit1_16 {
83
107
  encoderName: string;
84
108
  }
85
109
 
86
- export const VideoPacket =
87
- new Struct()
88
- .uint64('pts')
89
- .uint32('size')
90
- .uint8Array('data', { lengthField: 'size' });
110
+ export const VideoPacket = new Struct()
111
+ .uint64("pts")
112
+ .uint32("size")
113
+ .uint8Array("data", { lengthField: "size" });
91
114
 
92
115
  export const NO_PTS = BigInt(1) << BigInt(63);
93
116
 
94
- export const ScrcpyBackOrScreenOnControlMessage1_16 =
95
- new Struct()
96
- .uint8('type', ScrcpyControlMessageType.BackOrScreenOn as const);
97
-
98
- export const ScrcpyInjectScrollControlMessage1_16 =
99
- new Struct()
100
- .uint8('type', ScrcpyControlMessageType.InjectScroll as const)
101
- .uint32('pointerX')
102
- .uint32('pointerY')
103
- .uint16('screenWidth')
104
- .uint16('screenHeight')
105
- .int32('scrollX')
106
- .int32('scrollY');
107
-
108
- export class ScrcpyOptions1_16<T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsInit1_16>
109
- implements ScrcpyOptions<T> {
117
+ export const ScrcpyBackOrScreenOnControlMessage1_16 = new Struct().uint8(
118
+ "type",
119
+ ScrcpyControlMessageType.BackOrScreenOn as const
120
+ );
121
+
122
+ export const ScrcpySetClipboardControlMessage1_15 = new Struct()
123
+ .uint8("type", ScrcpyControlMessageType.SetClipboard as const)
124
+ .uint32("length")
125
+ .string("content", { lengthField: "length" });
126
+
127
+ export type ScrcpySetClipboardControlMessage1_15 =
128
+ (typeof ScrcpySetClipboardControlMessage1_15)["TInit"];
129
+
130
+ export class ScrcpyOptions1_16<
131
+ T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsInit1_16
132
+ > implements ScrcpyOptions<T>
133
+ {
110
134
  public value: Partial<T>;
111
135
 
112
136
  public constructor(value: Partial<ScrcpyOptionsInit1_16>) {
113
- if (new.target === ScrcpyOptions1_16 &&
114
- value.logLevel === ScrcpyLogLevel.Verbose) {
137
+ if (
138
+ new.target === ScrcpyOptions1_16 &&
139
+ value.logLevel === ScrcpyLogLevel.Verbose
140
+ ) {
115
141
  value.logLevel = ScrcpyLogLevel.Debug;
116
142
  }
117
143
 
118
- if (new.target === ScrcpyOptions1_16 &&
119
- value.lockVideoOrientation === ScrcpyVideoOrientation.Initial) {
144
+ if (
145
+ new.target === ScrcpyOptions1_16 &&
146
+ value.lockVideoOrientation === ScrcpyVideoOrientation.Initial
147
+ ) {
120
148
  value.lockVideoOrientation = ScrcpyVideoOrientation.Unlocked;
121
149
  }
122
150
 
@@ -125,20 +153,20 @@ export class ScrcpyOptions1_16<T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsIn
125
153
 
126
154
  protected getArgumentOrder(): (keyof T)[] {
127
155
  return [
128
- 'logLevel',
129
- 'maxSize',
130
- 'bitRate',
131
- 'maxFps',
132
- 'lockVideoOrientation',
133
- 'tunnelForward',
134
- 'crop',
135
- 'sendFrameMeta',
136
- 'control',
137
- 'displayId',
138
- 'showTouches',
139
- 'stayAwake',
140
- 'codecOptions',
141
- 'encoderName',
156
+ "logLevel",
157
+ "maxSize",
158
+ "bitRate",
159
+ "maxFps",
160
+ "lockVideoOrientation",
161
+ "tunnelForward",
162
+ "crop",
163
+ "sendFrameMeta",
164
+ "control",
165
+ "displayId",
166
+ "showTouches",
167
+ "stayAwake",
168
+ "codecOptions",
169
+ "encoderName",
142
170
  ];
143
171
  }
144
172
 
@@ -150,37 +178,38 @@ export class ScrcpyOptions1_16<T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsIn
150
178
  maxFps: 0,
151
179
  lockVideoOrientation: ScrcpyVideoOrientation.Unlocked,
152
180
  tunnelForward: false,
153
- crop: '-',
181
+ crop: "-",
154
182
  sendFrameMeta: true,
155
183
  control: true,
156
184
  displayId: 0,
157
185
  showTouches: false,
158
186
  stayAwake: false,
159
187
  codecOptions: new CodecOptions({}),
160
- encoderName: '-',
188
+ encoderName: "-",
161
189
  } as T;
162
190
  }
163
191
 
164
192
  public formatServerArguments(): string[] {
165
193
  const defaults = this.getDefaultValue();
166
- return this.getArgumentOrder()
167
- .map(
168
- key =>
169
- toScrcpyOptionValue(this.value[key] || defaults[key], '-')
170
- );
194
+ return this.getArgumentOrder().map((key) =>
195
+ toScrcpyOptionValue(this.value[key] || defaults[key], "-")
196
+ );
171
197
  }
172
198
 
173
199
  public getOutputEncoderNameRegex(): RegExp {
174
200
  return /\s+scrcpy --encoder-name '(.*?)'/;
175
201
  }
176
202
 
177
- public createVideoStreamTransformer(): TransformStream<Uint8Array, ScrcpyVideoStreamPacket> {
203
+ public createVideoStreamTransformer(): TransformStream<
204
+ Uint8Array,
205
+ ScrcpyVideoStreamPacket
206
+ > {
178
207
  // Optimized path for video frames only
179
208
  if (this.value.sendFrameMeta === false) {
180
209
  return new TransformStream({
181
210
  transform(chunk, controller) {
182
211
  controller.enqueue({
183
- type: 'frame',
212
+ type: "frame",
184
213
  data: chunk,
185
214
  });
186
215
  },
@@ -189,74 +218,91 @@ export class ScrcpyOptions1_16<T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsIn
189
218
 
190
219
  let header: Uint8Array | undefined;
191
220
 
192
- let deserializeStream = new StructDeserializeStream(VideoPacket);
221
+ const deserializeStream = new StructDeserializeStream(VideoPacket);
193
222
  return {
194
223
  writable: deserializeStream.writable,
195
- readable: deserializeStream.readable.pipeThrough(new TransformStream({
196
- transform(packet, controller) {
197
- if (packet.pts === NO_PTS) {
198
- const sequenceParameterSet = parse_sequence_parameter_set(packet.data.slice().buffer);
199
-
200
- const {
201
- profile_idc: profileIndex,
202
- constraint_set: constraintSet,
203
- level_idc: levelIndex,
204
- pic_width_in_mbs_minus1,
205
- pic_height_in_map_units_minus1,
206
- frame_mbs_only_flag,
207
- frame_crop_left_offset,
208
- frame_crop_right_offset,
209
- frame_crop_top_offset,
210
- frame_crop_bottom_offset,
211
- } = sequenceParameterSet;
212
-
213
- const encodedWidth = (pic_width_in_mbs_minus1 + 1) * 16;
214
- const encodedHeight = (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag) * 16;
215
- const cropLeft = frame_crop_left_offset * 2;
216
- const cropRight = frame_crop_right_offset * 2;
217
- const cropTop = frame_crop_top_offset * 2;
218
- const cropBottom = frame_crop_bottom_offset * 2;
219
-
220
- const croppedWidth = encodedWidth - cropLeft - cropRight;
221
- const croppedHeight = encodedHeight - cropTop - cropBottom;
222
-
223
- header = packet.data;
224
+ readable: deserializeStream.readable.pipeThrough(
225
+ new TransformStream({
226
+ transform(packet, controller) {
227
+ if (packet.pts === NO_PTS) {
228
+ const {
229
+ sequenceParameterSet,
230
+ pictureParameterSet,
231
+ } = parseH264Configuration(packet.data);
232
+
233
+ const {
234
+ profile_idc: profileIndex,
235
+ constraint_set: constraintSet,
236
+ level_idc: levelIndex,
237
+ pic_width_in_mbs_minus1,
238
+ pic_height_in_map_units_minus1,
239
+ frame_mbs_only_flag,
240
+ frame_crop_left_offset,
241
+ frame_crop_right_offset,
242
+ frame_crop_top_offset,
243
+ frame_crop_bottom_offset,
244
+ } = parseSequenceParameterSet(
245
+ removeH264Emulation(sequenceParameterSet)
246
+ );
247
+
248
+ const encodedWidth =
249
+ (pic_width_in_mbs_minus1 + 1) * 16;
250
+ const encodedHeight =
251
+ (pic_height_in_map_units_minus1 + 1) *
252
+ (2 - frame_mbs_only_flag) *
253
+ 16;
254
+ const cropLeft = frame_crop_left_offset * 2;
255
+ const cropRight = frame_crop_right_offset * 2;
256
+ const cropTop = frame_crop_top_offset * 2;
257
+ const cropBottom = frame_crop_bottom_offset * 2;
258
+
259
+ const croppedWidth =
260
+ encodedWidth - cropLeft - cropRight;
261
+ const croppedHeight =
262
+ encodedHeight - cropTop - cropBottom;
263
+
264
+ header = packet.data;
265
+ controller.enqueue({
266
+ type: "configuration",
267
+ pictureParameterSet,
268
+ sequenceParameterSet,
269
+ data: {
270
+ profileIndex,
271
+ constraintSet,
272
+ levelIndex,
273
+ encodedWidth,
274
+ encodedHeight,
275
+ cropLeft,
276
+ cropRight,
277
+ cropTop,
278
+ cropBottom,
279
+ croppedWidth,
280
+ croppedHeight,
281
+ },
282
+ });
283
+ return;
284
+ }
285
+
286
+ let frameData: Uint8Array;
287
+ if (header) {
288
+ frameData = new Uint8Array(
289
+ header.byteLength + packet.data.byteLength
290
+ );
291
+ frameData.set(header);
292
+ frameData.set(packet.data, header.byteLength);
293
+ header = undefined;
294
+ } else {
295
+ frameData = packet.data;
296
+ }
297
+
224
298
  controller.enqueue({
225
- type: 'configuration',
226
- data: {
227
- profileIndex,
228
- constraintSet,
229
- levelIndex,
230
- encodedWidth,
231
- encodedHeight,
232
- cropLeft,
233
- cropRight,
234
- cropTop,
235
- cropBottom,
236
- croppedWidth,
237
- croppedHeight,
238
- }
299
+ type: "frame",
300
+ pts: packet.pts,
301
+ data: frameData,
239
302
  });
240
- return;
241
- }
242
-
243
- let frameData: Uint8Array;
244
- if (header) {
245
- frameData = new Uint8Array(header.byteLength + packet.data.byteLength);
246
- frameData.set(header);
247
- frameData.set(packet.data, header.byteLength);
248
- header = undefined;
249
- } else {
250
- frameData = packet.data;
251
- }
252
-
253
- controller.enqueue({
254
- type: 'frame',
255
- pts: packet.pts,
256
- data: frameData,
257
- });
258
- }
259
- }))
303
+ },
304
+ })
305
+ ),
260
306
  };
261
307
  }
262
308
 
@@ -277,7 +323,7 @@ export class ScrcpyOptions1_16<T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsIn
277
323
  }
278
324
 
279
325
  public serializeBackOrScreenOnControlMessage(
280
- message: ScrcpyBackOrScreenOnControlMessage1_18,
326
+ message: ScrcpyBackOrScreenOnControlMessage
281
327
  ) {
282
328
  if (message.action === AndroidKeyEventAction.Down) {
283
329
  return ScrcpyBackOrScreenOnControlMessage1_16.serialize(message);
@@ -286,9 +332,13 @@ export class ScrcpyOptions1_16<T extends ScrcpyOptionsInit1_16 = ScrcpyOptionsIn
286
332
  return undefined;
287
333
  }
288
334
 
289
- public serializeInjectScrollControlMessage(
290
- message: ScrcpyInjectScrollControlMessage1_22,
335
+ public serializeSetClipboardControlMessage(
336
+ message: ScrcpySetClipboardControlMessage
291
337
  ): Uint8Array {
292
- return ScrcpyInjectScrollControlMessage1_16.serialize(message);
338
+ return ScrcpySetClipboardControlMessage1_15.serialize(message);
339
+ }
340
+
341
+ public getScrollController(): ScrcpyScrollController {
342
+ return new ScrcpyScrollController1_16();
293
343
  }
294
344
  }
@@ -0,0 +1,74 @@
1
+ import Struct from "@yume-chan/struct";
2
+
3
+ import type { ScrcpyInjectScrollControlMessage } from "../../control/index.js";
4
+ import { ScrcpyControlMessageType } from "../../control/index.js";
5
+
6
+ export interface ScrcpyScrollController {
7
+ serializeScrollMessage(
8
+ message: ScrcpyInjectScrollControlMessage
9
+ ): Uint8Array | undefined;
10
+ }
11
+
12
+ export const ScrcpyInjectScrollControlMessage1_16 = new Struct()
13
+ .uint8("type", ScrcpyControlMessageType.InjectScroll as const)
14
+ .uint32("pointerX")
15
+ .uint32("pointerY")
16
+ .uint16("screenWidth")
17
+ .uint16("screenHeight")
18
+ .int32("scrollX")
19
+ .int32("scrollY");
20
+
21
+ /**
22
+ * Old version of Scrcpy server only supports integer values for scroll.
23
+ *
24
+ * Accumulate scroll values and send scroll message when accumulated value
25
+ * reaches 1 or -1.
26
+ */
27
+ export class ScrcpyScrollController1_16 implements ScrcpyScrollController {
28
+ private accumulatedX = 0;
29
+ private accumulatedY = 0;
30
+
31
+ protected processMessage(
32
+ message: ScrcpyInjectScrollControlMessage
33
+ ): ScrcpyInjectScrollControlMessage | undefined {
34
+ this.accumulatedX += message.scrollX;
35
+ this.accumulatedY += message.scrollY;
36
+
37
+ let scrollX = 0;
38
+ let scrollY = 0;
39
+ if (this.accumulatedX >= 1) {
40
+ scrollX = 1;
41
+ this.accumulatedX = 0;
42
+ } else if (this.accumulatedX <= -1) {
43
+ scrollX = -1;
44
+ this.accumulatedX = 0;
45
+ }
46
+
47
+ if (this.accumulatedY >= 1) {
48
+ scrollY = 1;
49
+ this.accumulatedY = 0;
50
+ } else if (this.accumulatedY <= -1) {
51
+ scrollY = -1;
52
+ this.accumulatedY = 0;
53
+ }
54
+
55
+ if (scrollX === 0 && scrollY === 0) {
56
+ return undefined;
57
+ }
58
+
59
+ message.scrollX = scrollX;
60
+ message.scrollY = scrollY;
61
+ return message;
62
+ }
63
+
64
+ public serializeScrollMessage(
65
+ message: ScrcpyInjectScrollControlMessage
66
+ ): Uint8Array | undefined {
67
+ const processed = this.processMessage(message);
68
+ if (!processed) {
69
+ return undefined;
70
+ }
71
+
72
+ return ScrcpyInjectScrollControlMessage1_16.serialize(processed);
73
+ }
74
+ }
@@ -1,27 +1,37 @@
1
- import Struct, { placeholder } from '@yume-chan/struct';
1
+ import Struct, { placeholder } from "@yume-chan/struct";
2
2
 
3
- import { AndroidKeyEventAction, ScrcpyControlMessageType } from '../control/index.js';
4
- import { ScrcpyBackOrScreenOnControlMessage1_16, ScrcpyOptions1_16, type ScrcpyOptionsInit1_16 } from './1_16/options.js';
3
+ import type {
4
+ AndroidKeyEventAction,
5
+ ScrcpyBackOrScreenOnControlMessage,
6
+ } from "../control/index.js";
7
+ import { ScrcpyControlMessageType } from "../control/index.js";
8
+
9
+ import type { ScrcpyOptionsInit1_16 } from "./1_16/options.js";
10
+ import {
11
+ ScrcpyBackOrScreenOnControlMessage1_16,
12
+ ScrcpyOptions1_16,
13
+ } from "./1_16/options.js";
5
14
 
6
15
  export interface ScrcpyOptionsInit1_18 extends ScrcpyOptionsInit1_16 {
7
16
  powerOffOnClose: boolean;
8
17
  }
9
18
 
10
- export const ScrcpyBackOrScreenOnControlMessage1_18 =
11
- new Struct()
12
- .fields(ScrcpyBackOrScreenOnControlMessage1_16)
13
- .uint8('action', placeholder<AndroidKeyEventAction>());
19
+ export const ScrcpyBackOrScreenOnControlMessage1_18 = new Struct()
20
+ .fields(ScrcpyBackOrScreenOnControlMessage1_16)
21
+ .uint8("action", placeholder<AndroidKeyEventAction>());
14
22
 
15
- export type ScrcpyBackOrScreenOnControlMessage1_18 = typeof ScrcpyBackOrScreenOnControlMessage1_18['TInit'];
23
+ export type ScrcpyBackOrScreenOnControlMessage1_18 =
24
+ (typeof ScrcpyBackOrScreenOnControlMessage1_18)["TInit"];
16
25
 
17
- export class ScrcpyOptions1_18<T extends ScrcpyOptionsInit1_18 = ScrcpyOptionsInit1_18>
18
- extends ScrcpyOptions1_16<T> {
26
+ export class ScrcpyOptions1_18<
27
+ T extends ScrcpyOptionsInit1_18 = ScrcpyOptionsInit1_18
28
+ > extends ScrcpyOptions1_16<T> {
19
29
  constructor(value: Partial<ScrcpyOptionsInit1_18>) {
20
30
  super(value);
21
31
  }
22
32
 
23
33
  protected override getArgumentOrder(): (keyof T)[] {
24
- return super.getArgumentOrder().concat(['powerOffOnClose']);
34
+ return super.getArgumentOrder().concat(["powerOffOnClose"]);
25
35
  }
26
36
 
27
37
  public override getDefaultValue(): T {
@@ -56,7 +66,7 @@ export class ScrcpyOptions1_18<T extends ScrcpyOptionsInit1_18 = ScrcpyOptionsIn
56
66
  }
57
67
 
58
68
  public override serializeBackOrScreenOnControlMessage(
59
- message: ScrcpyBackOrScreenOnControlMessage1_18,
69
+ message: ScrcpyBackOrScreenOnControlMessage
60
70
  ) {
61
71
  return ScrcpyBackOrScreenOnControlMessage1_18.serialize(message);
62
72
  }
@@ -1,18 +1,35 @@
1
1
  // cspell: ignore autosync
2
2
 
3
- import { ScrcpyOptions1_18, type ScrcpyOptionsInit1_18 } from './1_18.js';
4
- import { toScrcpyOptionValue } from './types.js';
3
+ import Struct from "@yume-chan/struct";
4
+
5
+ import type { ScrcpySetClipboardControlMessage } from "../control/index.js";
6
+ import { ScrcpyControlMessageType } from "../control/index.js";
7
+
8
+ import type { ScrcpyOptionsInit1_18 } from "./1_18.js";
9
+ import { ScrcpyOptions1_18 } from "./1_18.js";
10
+ import { toScrcpyOptionValue } from "./types.js";
5
11
 
6
12
  export interface ScrcpyOptionsInit1_21 extends ScrcpyOptionsInit1_18 {
7
13
  clipboardAutosync?: boolean;
8
14
  }
9
15
 
10
16
  function toSnakeCase(input: string): string {
11
- return input.replace(/([A-Z])/g, '_$1').toLowerCase();
17
+ return input.replace(/([A-Z])/g, "_$1").toLowerCase();
12
18
  }
13
19
 
14
- export class ScrcpyOptions1_21<T extends ScrcpyOptionsInit1_21 = ScrcpyOptionsInit1_21>
15
- extends ScrcpyOptions1_18<T> {
20
+ export const ScrcpySetClipboardControlMessage1_21 = new Struct()
21
+ .uint8("type", ScrcpyControlMessageType.SetClipboard as const)
22
+ .uint64("sequence")
23
+ .int8("paste")
24
+ .uint32("length")
25
+ .string("content", { lengthField: "length" });
26
+
27
+ export type ScrcpySetClipboardControlMessage1_21 =
28
+ (typeof ScrcpySetClipboardControlMessage1_21)["TInit"];
29
+
30
+ export class ScrcpyOptions1_21<
31
+ T extends ScrcpyOptionsInit1_21 = ScrcpyOptionsInit1_21
32
+ > extends ScrcpyOptions1_18<T> {
16
33
  public constructor(init: Partial<ScrcpyOptionsInit1_21>) {
17
34
  super(init);
18
35
  }
@@ -32,13 +49,13 @@ export class ScrcpyOptions1_21<T extends ScrcpyOptionsInit1_21 = ScrcpyOptionsIn
32
49
  ([key, value]) =>
33
50
  [key, toScrcpyOptionValue(value, undefined)] as const
34
51
  )
35
- .filter(
36
- (pair): pair is [string, string] =>
37
- pair[1] !== undefined
38
- )
39
- .map(
40
- ([key, value]) =>
41
- `${toSnakeCase(key)}=${value}`
42
- );
52
+ .filter((pair): pair is [string, string] => pair[1] !== undefined)
53
+ .map(([key, value]) => `${toSnakeCase(key)}=${value}`);
54
+ }
55
+
56
+ public override serializeSetClipboardControlMessage(
57
+ message: ScrcpySetClipboardControlMessage
58
+ ): Uint8Array {
59
+ return ScrcpySetClipboardControlMessage1_21.serialize(message);
43
60
  }
44
61
  }
@@ -0,0 +1,2 @@
1
+ export * from "./options.js";
2
+ export * from "./scroll.js";
@@ -1,7 +1,8 @@
1
- import Struct from '@yume-chan/struct';
1
+ import type { ScrcpyScrollController } from "../1_16/index.js";
2
+ import type { ScrcpyOptionsInit1_21 } from "../1_21.js";
3
+ import { ScrcpyOptions1_21 } from "../1_21.js";
2
4
 
3
- import { ScrcpyInjectScrollControlMessage1_16 } from './1_16/options.js';
4
- import { ScrcpyOptions1_21, type ScrcpyOptionsInit1_21 } from './1_21.js';
5
+ import { ScrcpyScrollController1_22 } from "./scroll.js";
5
6
 
6
7
  export interface ScrcpyOptionsInit1_22 extends ScrcpyOptionsInit1_21 {
7
8
  downsizeOnError: boolean;
@@ -28,16 +29,9 @@ export interface ScrcpyOptionsInit1_22 extends ScrcpyOptionsInit1_21 {
28
29
  rawVideoStream: boolean;
29
30
  }
30
31
 
31
- export const ScrcpyInjectScrollControlMessage1_22 =
32
- new Struct()
33
- .fields(ScrcpyInjectScrollControlMessage1_16)
34
- .int32('buttons');
35
-
36
- export type ScrcpyInjectScrollControlMessage1_22 =
37
- typeof ScrcpyInjectScrollControlMessage1_22['TInit'];
38
-
39
- export class ScrcpyOptions1_22<T extends ScrcpyOptionsInit1_22 = ScrcpyOptionsInit1_22>
40
- extends ScrcpyOptions1_21<T> {
32
+ export class ScrcpyOptions1_22<
33
+ T extends ScrcpyOptionsInit1_22 = ScrcpyOptionsInit1_22
34
+ > extends ScrcpyOptions1_21<T> {
41
35
  public constructor(init: Partial<ScrcpyOptionsInit1_22>) {
42
36
  if (init.rawVideoStream) {
43
37
  // Set implied options for client-side processing
@@ -59,9 +53,7 @@ export class ScrcpyOptions1_22<T extends ScrcpyOptionsInit1_22 = ScrcpyOptionsIn
59
53
  };
60
54
  }
61
55
 
62
- public override serializeInjectScrollControlMessage(
63
- message: ScrcpyInjectScrollControlMessage1_22,
64
- ): Uint8Array {
65
- return ScrcpyInjectScrollControlMessage1_22.serialize(message);
56
+ public override getScrollController(): ScrcpyScrollController {
57
+ return new ScrcpyScrollController1_22();
66
58
  }
67
59
  }
@@ -0,0 +1,26 @@
1
+ import Struct from "@yume-chan/struct";
2
+
3
+ import {
4
+ ScrcpyInjectScrollControlMessage1_16,
5
+ ScrcpyScrollController1_16,
6
+ } from "../1_16/index.js";
7
+
8
+ export const ScrcpyInjectScrollControlMessage1_22 = new Struct()
9
+ .fields(ScrcpyInjectScrollControlMessage1_16)
10
+ .int32("buttons");
11
+
12
+ export type ScrcpyInjectScrollControlMessage1_22 =
13
+ (typeof ScrcpyInjectScrollControlMessage1_22)["TInit"];
14
+
15
+ export class ScrcpyScrollController1_22 extends ScrcpyScrollController1_16 {
16
+ public override serializeScrollMessage(
17
+ message: ScrcpyInjectScrollControlMessage1_22
18
+ ): Uint8Array | undefined {
19
+ const processed = this.processMessage(message);
20
+ if (!processed) {
21
+ return undefined;
22
+ }
23
+
24
+ return ScrcpyInjectScrollControlMessage1_22.serialize(processed);
25
+ }
26
+ }