@yume-chan/scrcpy 2.0.1 → 2.1.1

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 (204) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +5 -2
  3. package/esm/1_15/impl/clipboard-stream.d.ts +2 -1
  4. package/esm/1_15/impl/clipboard-stream.d.ts.map +1 -1
  5. package/esm/1_15/impl/clipboard-stream.js +4 -7
  6. package/esm/1_15/impl/clipboard-stream.js.map +1 -1
  7. package/esm/1_15/impl/defaults.d.ts.map +1 -1
  8. package/esm/1_15/impl/defaults.js +2 -2
  9. package/esm/1_15/impl/defaults.js.map +1 -1
  10. package/esm/1_15/impl/scroll-controller.d.ts.map +1 -1
  11. package/esm/1_15/impl/scroll-controller.js +22 -21
  12. package/esm/1_15/impl/scroll-controller.js.map +1 -1
  13. package/esm/1_15/options.d.ts +2 -3
  14. package/esm/1_15/options.d.ts.map +1 -1
  15. package/esm/1_15/options.js +6 -15
  16. package/esm/1_15/options.js.map +1 -1
  17. package/esm/1_17/options.d.ts +2 -3
  18. package/esm/1_17/options.d.ts.map +1 -1
  19. package/esm/1_17/options.js +6 -15
  20. package/esm/1_17/options.js.map +1 -1
  21. package/esm/1_18/options.d.ts +2 -3
  22. package/esm/1_18/options.d.ts.map +1 -1
  23. package/esm/1_18/options.js +6 -15
  24. package/esm/1_18/options.js.map +1 -1
  25. package/esm/1_21/impl/set-clipboard.d.ts +2 -1
  26. package/esm/1_21/impl/set-clipboard.d.ts.map +1 -1
  27. package/esm/1_21/impl/set-clipboard.js +2 -5
  28. package/esm/1_21/impl/set-clipboard.js.map +1 -1
  29. package/esm/1_21/options.d.ts +2 -3
  30. package/esm/1_21/options.d.ts.map +1 -1
  31. package/esm/1_21/options.js +7 -21
  32. package/esm/1_21/options.js.map +1 -1
  33. package/esm/1_22/options.d.ts +2 -3
  34. package/esm/1_22/options.d.ts.map +1 -1
  35. package/esm/1_22/options.js +7 -21
  36. package/esm/1_22/options.js.map +1 -1
  37. package/esm/1_23/options.d.ts +2 -3
  38. package/esm/1_23/options.d.ts.map +1 -1
  39. package/esm/1_23/options.js +7 -21
  40. package/esm/1_23/options.js.map +1 -1
  41. package/esm/1_24/options.d.ts +2 -3
  42. package/esm/1_24/options.d.ts.map +1 -1
  43. package/esm/1_24/options.js +7 -21
  44. package/esm/1_24/options.js.map +1 -1
  45. package/esm/1_25/options.d.ts +2 -3
  46. package/esm/1_25/options.d.ts.map +1 -1
  47. package/esm/1_25/options.js +7 -21
  48. package/esm/1_25/options.js.map +1 -1
  49. package/esm/2_0/options.d.ts +2 -3
  50. package/esm/2_0/options.d.ts.map +1 -1
  51. package/esm/2_0/options.js +7 -21
  52. package/esm/2_0/options.js.map +1 -1
  53. package/esm/2_1/options.d.ts +2 -3
  54. package/esm/2_1/options.d.ts.map +1 -1
  55. package/esm/2_1/options.js +7 -21
  56. package/esm/2_1/options.js.map +1 -1
  57. package/esm/2_2/options.d.ts +2 -3
  58. package/esm/2_2/options.d.ts.map +1 -1
  59. package/esm/2_2/options.js +7 -21
  60. package/esm/2_2/options.js.map +1 -1
  61. package/esm/2_3/options.d.ts +2 -3
  62. package/esm/2_3/options.d.ts.map +1 -1
  63. package/esm/2_3/options.js +7 -21
  64. package/esm/2_3/options.js.map +1 -1
  65. package/esm/2_4/impl/uhid-output-stream.d.ts +2 -1
  66. package/esm/2_4/impl/uhid-output-stream.d.ts.map +1 -1
  67. package/esm/2_4/impl/uhid-output-stream.js +2 -5
  68. package/esm/2_4/impl/uhid-output-stream.js.map +1 -1
  69. package/esm/2_4/options.d.ts +2 -3
  70. package/esm/2_4/options.d.ts.map +1 -1
  71. package/esm/2_4/options.js +8 -27
  72. package/esm/2_4/options.js.map +1 -1
  73. package/esm/2_6/options.d.ts +2 -3
  74. package/esm/2_6/options.d.ts.map +1 -1
  75. package/esm/2_6/options.js +8 -22
  76. package/esm/2_6/options.js.map +1 -1
  77. package/esm/2_7/impl/serialize-uhid-create.d.ts +2 -2
  78. package/esm/2_7/impl/serialize-uhid-create.d.ts.map +1 -1
  79. package/esm/2_7/impl/serialize-uhid-create.js +3 -4
  80. package/esm/2_7/impl/serialize-uhid-create.js.map +1 -1
  81. package/esm/2_7/options.d.ts +2 -3
  82. package/esm/2_7/options.d.ts.map +1 -1
  83. package/esm/2_7/options.js +8 -22
  84. package/esm/2_7/options.js.map +1 -1
  85. package/esm/3_0/options.d.ts +2 -3
  86. package/esm/3_0/options.d.ts.map +1 -1
  87. package/esm/3_0/options.js +8 -22
  88. package/esm/3_0/options.js.map +1 -1
  89. package/esm/3_1/impl/serialize-uhid-create.d.ts +2 -2
  90. package/esm/3_1/impl/serialize-uhid-create.d.ts.map +1 -1
  91. package/esm/3_1/impl/serialize-uhid-create.js +3 -4
  92. package/esm/3_1/impl/serialize-uhid-create.js.map +1 -1
  93. package/esm/3_1/options.d.ts +2 -3
  94. package/esm/3_1/options.d.ts.map +1 -1
  95. package/esm/3_1/options.js +8 -22
  96. package/esm/3_1/options.js.map +1 -1
  97. package/esm/3_2/impl/defaults.d.ts +57 -0
  98. package/esm/3_2/impl/defaults.d.ts.map +1 -0
  99. package/esm/3_2/impl/defaults.js +6 -0
  100. package/esm/3_2/impl/defaults.js.map +1 -0
  101. package/esm/3_2/impl/index.d.ts +4 -0
  102. package/esm/3_2/impl/index.d.ts.map +1 -0
  103. package/esm/3_2/impl/index.js +3 -0
  104. package/esm/3_2/impl/index.js.map +1 -0
  105. package/esm/3_2/impl/init.d.ts +6 -0
  106. package/esm/3_2/impl/init.d.ts.map +1 -0
  107. package/esm/3_2/impl/init.js +2 -0
  108. package/esm/3_2/impl/init.js.map +1 -0
  109. package/esm/3_2/impl/prev.d.ts +2 -0
  110. package/esm/3_2/impl/prev.d.ts.map +1 -0
  111. package/esm/3_2/impl/prev.js +2 -0
  112. package/esm/3_2/impl/prev.js.map +1 -0
  113. package/esm/3_2/index.d.ts +2 -0
  114. package/esm/3_2/index.d.ts.map +1 -0
  115. package/esm/3_2/index.js +2 -0
  116. package/esm/3_2/index.js.map +1 -0
  117. package/esm/3_2/options.d.ts +90 -0
  118. package/esm/3_2/options.d.ts.map +1 -0
  119. package/esm/3_2/options.js +78 -0
  120. package/esm/3_2/options.js.map +1 -0
  121. package/esm/3_3.d.ts +8 -0
  122. package/esm/3_3.d.ts.map +1 -0
  123. package/esm/3_3.js +7 -0
  124. package/esm/3_3.js.map +1 -0
  125. package/esm/3_3_1/impl/index.d.ts +3 -0
  126. package/esm/3_3_1/impl/index.d.ts.map +1 -0
  127. package/esm/3_3_1/impl/index.js +3 -0
  128. package/esm/3_3_1/impl/index.js.map +1 -0
  129. package/esm/3_3_1/impl/prev.d.ts +2 -0
  130. package/esm/3_3_1/impl/prev.d.ts.map +1 -0
  131. package/esm/3_3_1/impl/prev.js +2 -0
  132. package/esm/3_3_1/impl/prev.js.map +1 -0
  133. package/esm/3_3_1/impl/scroll-controller.d.ts +7 -0
  134. package/esm/3_3_1/impl/scroll-controller.d.ts.map +1 -0
  135. package/esm/3_3_1/impl/scroll-controller.js +15 -0
  136. package/esm/3_3_1/impl/scroll-controller.js.map +1 -0
  137. package/esm/3_3_1/index.d.ts +2 -0
  138. package/esm/3_3_1/index.d.ts.map +1 -0
  139. package/esm/3_3_1/index.js +2 -0
  140. package/esm/3_3_1/index.js.map +1 -0
  141. package/esm/3_3_1/options.d.ts +90 -0
  142. package/esm/3_3_1/options.d.ts.map +1 -0
  143. package/esm/3_3_1/options.js +78 -0
  144. package/esm/3_3_1/options.js.map +1 -0
  145. package/esm/base/device-message.d.ts +10 -1
  146. package/esm/base/device-message.d.ts.map +1 -1
  147. package/esm/base/device-message.js +40 -1
  148. package/esm/base/device-message.js.map +1 -1
  149. package/esm/base/options.d.ts +2 -3
  150. package/esm/base/options.d.ts.map +1 -1
  151. package/esm/control/message-type-map.d.ts +2 -2
  152. package/esm/control/message-type-map.d.ts.map +1 -1
  153. package/esm/control/message-type-map.js.map +1 -1
  154. package/esm/index.d.ts +3 -0
  155. package/esm/index.d.ts.map +1 -1
  156. package/esm/index.js +3 -0
  157. package/esm/index.js.map +1 -1
  158. package/esm/latest.d.ts +5 -5
  159. package/esm/latest.d.ts.map +1 -1
  160. package/esm/latest.js +3 -3
  161. package/esm/latest.js.map +1 -1
  162. package/package.json +9 -9
  163. package/src/1_15/impl/clipboard-stream.ts +5 -7
  164. package/src/1_15/impl/defaults.ts +15 -16
  165. package/src/1_15/impl/scroll-controller.ts +22 -19
  166. package/src/1_15/options.ts +9 -21
  167. package/src/1_17/options.ts +9 -21
  168. package/src/1_18/options.ts +9 -21
  169. package/src/1_21/impl/set-clipboard.ts +2 -5
  170. package/src/1_21/options.ts +13 -28
  171. package/src/1_22/options.ts +13 -28
  172. package/src/1_23/options.ts +13 -28
  173. package/src/1_24/options.ts +13 -28
  174. package/src/1_25/options.ts +13 -28
  175. package/src/2_0/options.ts +13 -28
  176. package/src/2_1/options.ts +13 -28
  177. package/src/2_2/options.ts +13 -28
  178. package/src/2_3/options.ts +13 -28
  179. package/src/2_4/impl/uhid-output-stream.ts +3 -6
  180. package/src/2_4/options.ts +16 -35
  181. package/src/2_6/options.ts +16 -29
  182. package/src/2_7/impl/serialize-uhid-create.ts +9 -11
  183. package/src/2_7/options.ts +16 -29
  184. package/src/3_0/options.ts +16 -29
  185. package/src/3_1/impl/serialize-uhid-create.ts +11 -13
  186. package/src/3_1/options.ts +16 -29
  187. package/src/3_2/impl/defaults.ts +8 -0
  188. package/src/3_2/impl/index.ts +3 -0
  189. package/src/3_2/impl/init.ts +17 -0
  190. package/src/3_2/impl/prev.ts +1 -0
  191. package/src/3_2/index.ts +1 -0
  192. package/src/3_2/options.ts +177 -0
  193. package/src/3_3.ts +14 -0
  194. package/src/3_3_1/impl/index.ts +6 -0
  195. package/src/3_3_1/impl/prev.ts +1 -0
  196. package/src/3_3_1/impl/scroll-controller.ts +21 -0
  197. package/src/3_3_1/index.ts +1 -0
  198. package/src/3_3_1/options.ts +177 -0
  199. package/src/base/device-message.ts +50 -1
  200. package/src/base/options.ts +3 -8
  201. package/src/control/message-type-map.ts +3 -3
  202. package/src/index.ts +3 -0
  203. package/src/latest.ts +5 -5
  204. package/tsconfig.build.tsbuildinfo +1 -1
@@ -34,33 +34,36 @@ export class ScrollController implements ScrcpyScrollController {
34
34
  protected processMessage(
35
35
  message: ScrcpyInjectScrollControlMessage,
36
36
  ): ScrcpyInjectScrollControlMessage | undefined {
37
- this.#accumulatedX += message.scrollX;
38
- this.#accumulatedY += message.scrollY;
37
+ // Ref https://github.com/libsdl-org/SDL/blob/878ea48b607f23e4ec8c12d1395b86ab529e30d0/src/events/SDL_mouse.c#L897-L914
39
38
 
40
- let scrollX = 0;
41
- let scrollY = 0;
42
- if (this.#accumulatedX >= 1) {
43
- scrollX = 1;
44
- this.#accumulatedX = 0;
45
- } else if (this.#accumulatedX <= -1) {
46
- scrollX = -1;
47
- this.#accumulatedX = 0;
39
+ if (message.scrollX) {
40
+ if (Math.sign(message.scrollX) !== Math.sign(this.#accumulatedX)) {
41
+ this.#accumulatedX = message.scrollX;
42
+ } else {
43
+ this.#accumulatedX += message.scrollX;
44
+ }
48
45
  }
49
46
 
50
- if (this.#accumulatedY >= 1) {
51
- scrollY = 1;
52
- this.#accumulatedY = 0;
53
- } else if (this.#accumulatedY <= -1) {
54
- scrollY = -1;
55
- this.#accumulatedY = 0;
47
+ if (message.scrollY) {
48
+ if (Math.sign(message.scrollY) !== Math.sign(this.#accumulatedY)) {
49
+ this.#accumulatedY = message.scrollY;
50
+ } else {
51
+ this.#accumulatedY += message.scrollY;
52
+ }
56
53
  }
57
54
 
58
- if (scrollX === 0 && scrollY === 0) {
55
+ const integerX = this.#accumulatedX | 0;
56
+ this.#accumulatedX -= integerX;
57
+
58
+ const integerY = this.#accumulatedY | 0;
59
+ this.#accumulatedY -= integerY;
60
+
61
+ if (integerX === 0 && integerY === 0) {
59
62
  return undefined;
60
63
  }
61
64
 
62
- message.scrollX = scrollX;
63
- message.scrollY = scrollY;
65
+ message.scrollX = integerX;
66
+ message.scrollY = integerY;
64
67
  return message;
65
68
  }
66
69
 
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -10,6 +9,7 @@ import type {
10
9
  ScrcpyScrollController,
11
10
  ScrcpyVideoStream,
12
11
  } from "../base/index.js";
12
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
13
13
  import type {
14
14
  ScrcpyBackOrScreenOnControlMessage,
15
15
  ScrcpyInjectTouchControlMessage,
@@ -47,11 +47,18 @@ export class ScrcpyOptions1_15 implements ScrcpyOptions<Init> {
47
47
  return this.#clipboard;
48
48
  }
49
49
 
50
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
51
+ get deviceMessageParsers() {
52
+ return this.#deviceMessageParsers;
53
+ }
54
+
50
55
  constructor(init: Init) {
51
56
  this.value = { ...Defaults, ...init };
52
57
 
53
58
  if (this.value.control) {
54
- this.#clipboard = new ClipboardStream();
59
+ this.#clipboard = this.#deviceMessageParsers.add(
60
+ new ClipboardStream(),
61
+ );
55
62
  }
56
63
  }
57
64
 
@@ -73,25 +80,6 @@ export class ScrcpyOptions1_15 implements ScrcpyOptions<Init> {
73
80
  return parseVideoStreamMetadata(stream);
74
81
  }
75
82
 
76
- async parseDeviceMessage(
77
- id: number,
78
- stream: ExactReadable | AsyncExactReadable,
79
- ): Promise<void> {
80
- if (await this.#clipboard!.parse(id, stream)) {
81
- return;
82
- }
83
-
84
- throw new Error("Unknown device message");
85
- }
86
-
87
- endDeviceMessageStream(e?: unknown): void {
88
- if (e) {
89
- this.#clipboard!.error(e);
90
- } else {
91
- this.#clipboard!.close();
92
- }
93
- }
94
-
95
83
  createMediaStreamTransformer(): TransformStream<
96
84
  Uint8Array,
97
85
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -54,11 +54,18 @@ export class ScrcpyOptions1_17
54
54
  return this.#clipboard;
55
55
  }
56
56
 
57
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
58
+ get deviceMessageParsers() {
59
+ return this.#deviceMessageParsers;
60
+ }
61
+
57
62
  constructor(init: Init) {
58
63
  this.value = { ...Defaults, ...init };
59
64
 
60
65
  if (this.value.control) {
61
- this.#clipboard = new ClipboardStream();
66
+ this.#clipboard = this.#deviceMessageParsers.add(
67
+ new ClipboardStream(),
68
+ );
62
69
  }
63
70
  }
64
71
 
@@ -88,25 +95,6 @@ export class ScrcpyOptions1_17
88
95
  return parseVideoStreamMetadata(stream);
89
96
  }
90
97
 
91
- async parseDeviceMessage(
92
- id: number,
93
- stream: ExactReadable | AsyncExactReadable,
94
- ): Promise<void> {
95
- if (await this.#clipboard!.parse(id, stream)) {
96
- return;
97
- }
98
-
99
- throw new Error("Unknown device message");
100
- }
101
-
102
- endDeviceMessageStream(e?: unknown): void {
103
- if (e) {
104
- this.#clipboard!.error(e);
105
- } else {
106
- this.#clipboard!.close();
107
- }
108
- }
109
-
110
98
  createMediaStreamTransformer(): TransformStream<
111
99
  Uint8Array,
112
100
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -54,11 +54,18 @@ export class ScrcpyOptions1_18
54
54
  return this.#clipboard;
55
55
  }
56
56
 
57
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
58
+ get deviceMessageParsers() {
59
+ return this.#deviceMessageParsers;
60
+ }
61
+
57
62
  constructor(init: Init) {
58
63
  this.value = { ...Defaults, ...init };
59
64
 
60
65
  if (this.value.control) {
61
- this.#clipboard = new ClipboardStream();
66
+ this.#clipboard = this.#deviceMessageParsers.add(
67
+ new ClipboardStream(),
68
+ );
62
69
  }
63
70
  }
64
71
 
@@ -88,25 +95,6 @@ export class ScrcpyOptions1_18
88
95
  return parseVideoStreamMetadata(stream);
89
96
  }
90
97
 
91
- async parseDeviceMessage(
92
- id: number,
93
- stream: ExactReadable | AsyncExactReadable,
94
- ): Promise<void> {
95
- if (await this.#clipboard!.parse(id, stream)) {
96
- return;
97
- }
98
-
99
- throw new Error("Unknown device message");
100
- }
101
-
102
- endDeviceMessageStream(e?: unknown): void {
103
- if (e) {
104
- this.#clipboard!.error(e);
105
- } else {
106
- this.#clipboard!.close();
107
- }
108
- }
109
-
110
98
  createMediaStreamTransformer(): TransformStream<
111
99
  Uint8Array,
112
100
  ScrcpyMediaStreamPacket
@@ -29,18 +29,15 @@ export class AckClipboardHandler implements ScrcpyDeviceMessageParser {
29
29
 
30
30
  #closed = false;
31
31
 
32
- async parse(id: number, stream: AsyncExactReadable) {
33
- if (id !== 1) {
34
- return false;
35
- }
32
+ readonly id = 1;
36
33
 
34
+ async parse(_id: number, stream: AsyncExactReadable): Promise<undefined> {
37
35
  const message = await AckClipboardDeviceMessage.deserialize(stream);
38
36
  const resolver = this.#resolvers.get(message.sequence);
39
37
  if (resolver) {
40
38
  resolver.resolve();
41
39
  this.#resolvers.delete(message.sequence);
42
40
  }
43
- return true;
44
41
  }
45
42
 
46
43
  close(): void {
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -55,12 +55,22 @@ export class ScrcpyOptions1_21
55
55
 
56
56
  #ackClipboardHandler: AckClipboardHandler | undefined;
57
57
 
58
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
59
+ get deviceMessageParsers() {
60
+ return this.#deviceMessageParsers;
61
+ }
62
+
58
63
  constructor(init: Init) {
59
64
  this.value = { ...Defaults, ...init };
60
65
 
61
66
  if (this.value.control && this.value.clipboardAutosync) {
62
- this.#clipboard = new ClipboardStream();
63
- this.#ackClipboardHandler = new AckClipboardHandler();
67
+ this.#clipboard = this.#deviceMessageParsers.add(
68
+ new ClipboardStream(),
69
+ );
70
+
71
+ this.#ackClipboardHandler = this.#deviceMessageParsers.add(
72
+ new AckClipboardHandler(),
73
+ );
64
74
  }
65
75
  }
66
76
 
@@ -90,31 +100,6 @@ export class ScrcpyOptions1_21
90
100
  return parseVideoStreamMetadata(stream);
91
101
  }
92
102
 
93
- async parseDeviceMessage(
94
- id: number,
95
- stream: ExactReadable | AsyncExactReadable,
96
- ): Promise<void> {
97
- if (await this.#clipboard?.parse(id, stream)) {
98
- return;
99
- }
100
-
101
- if (await this.#ackClipboardHandler?.parse(id, stream)) {
102
- return;
103
- }
104
-
105
- throw new Error("Unknown device message");
106
- }
107
-
108
- endDeviceMessageStream(e?: unknown): void {
109
- if (e) {
110
- this.#clipboard?.error(e);
111
- this.#ackClipboardHandler?.error(e);
112
- } else {
113
- this.#clipboard?.close();
114
- this.#ackClipboardHandler?.close();
115
- }
116
- }
117
-
118
103
  createMediaStreamTransformer(): TransformStream<
119
104
  Uint8Array,
120
105
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -55,12 +55,22 @@ export class ScrcpyOptions1_22
55
55
 
56
56
  #ackClipboardHandler: AckClipboardHandler | undefined;
57
57
 
58
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
59
+ get deviceMessageParsers() {
60
+ return this.#deviceMessageParsers;
61
+ }
62
+
58
63
  constructor(init: Init) {
59
64
  this.value = { ...Defaults, ...init };
60
65
 
61
66
  if (this.value.control && this.value.clipboardAutosync) {
62
- this.#clipboard = new ClipboardStream();
63
- this.#ackClipboardHandler = new AckClipboardHandler();
67
+ this.#clipboard = this.#deviceMessageParsers.add(
68
+ new ClipboardStream(),
69
+ );
70
+
71
+ this.#ackClipboardHandler = this.#deviceMessageParsers.add(
72
+ new AckClipboardHandler(),
73
+ );
64
74
  }
65
75
  }
66
76
 
@@ -90,31 +100,6 @@ export class ScrcpyOptions1_22
90
100
  return parseVideoStreamMetadata(this.value, stream);
91
101
  }
92
102
 
93
- async parseDeviceMessage(
94
- id: number,
95
- stream: ExactReadable | AsyncExactReadable,
96
- ): Promise<void> {
97
- if (await this.#clipboard?.parse(id, stream)) {
98
- return;
99
- }
100
-
101
- if (await this.#ackClipboardHandler?.parse(id, stream)) {
102
- return;
103
- }
104
-
105
- throw new Error("Unknown device message");
106
- }
107
-
108
- endDeviceMessageStream(e?: unknown): void {
109
- if (e) {
110
- this.#clipboard?.error(e);
111
- this.#ackClipboardHandler?.error(e);
112
- } else {
113
- this.#clipboard?.close();
114
- this.#ackClipboardHandler?.close();
115
- }
116
- }
117
-
118
103
  createMediaStreamTransformer(): TransformStream<
119
104
  Uint8Array,
120
105
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -55,12 +55,22 @@ export class ScrcpyOptions1_23
55
55
 
56
56
  #ackClipboardHandler: AckClipboardHandler | undefined;
57
57
 
58
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
59
+ get deviceMessageParsers() {
60
+ return this.#deviceMessageParsers;
61
+ }
62
+
58
63
  constructor(init: Init) {
59
64
  this.value = { ...Defaults, ...init };
60
65
 
61
66
  if (this.value.control && this.value.clipboardAutosync) {
62
- this.#clipboard = new ClipboardStream();
63
- this.#ackClipboardHandler = new AckClipboardHandler();
67
+ this.#clipboard = this.#deviceMessageParsers.add(
68
+ new ClipboardStream(),
69
+ );
70
+
71
+ this.#ackClipboardHandler = this.#deviceMessageParsers.add(
72
+ new AckClipboardHandler(),
73
+ );
64
74
  }
65
75
  }
66
76
 
@@ -90,31 +100,6 @@ export class ScrcpyOptions1_23
90
100
  return parseVideoStreamMetadata(this.value, stream);
91
101
  }
92
102
 
93
- async parseDeviceMessage(
94
- id: number,
95
- stream: ExactReadable | AsyncExactReadable,
96
- ): Promise<void> {
97
- if (await this.#clipboard?.parse(id, stream)) {
98
- return;
99
- }
100
-
101
- if (await this.#ackClipboardHandler?.parse(id, stream)) {
102
- return;
103
- }
104
-
105
- throw new Error("Unknown device message");
106
- }
107
-
108
- endDeviceMessageStream(e?: unknown): void {
109
- if (e) {
110
- this.#clipboard?.error(e);
111
- this.#ackClipboardHandler?.error(e);
112
- } else {
113
- this.#clipboard?.close();
114
- this.#ackClipboardHandler?.close();
115
- }
116
- }
117
-
118
103
  createMediaStreamTransformer(): TransformStream<
119
104
  Uint8Array,
120
105
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -55,12 +55,22 @@ export class ScrcpyOptions1_24
55
55
 
56
56
  #ackClipboardHandler: AckClipboardHandler | undefined;
57
57
 
58
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
59
+ get deviceMessageParsers() {
60
+ return this.#deviceMessageParsers;
61
+ }
62
+
58
63
  constructor(init: Init) {
59
64
  this.value = { ...Defaults, ...init };
60
65
 
61
66
  if (this.value.control && this.value.clipboardAutosync) {
62
- this.#clipboard = new ClipboardStream();
63
- this.#ackClipboardHandler = new AckClipboardHandler();
67
+ this.#clipboard = this.#deviceMessageParsers.add(
68
+ new ClipboardStream(),
69
+ );
70
+
71
+ this.#ackClipboardHandler = this.#deviceMessageParsers.add(
72
+ new AckClipboardHandler(),
73
+ );
64
74
  }
65
75
  }
66
76
 
@@ -90,31 +100,6 @@ export class ScrcpyOptions1_24
90
100
  return parseVideoStreamMetadata(this.value, stream);
91
101
  }
92
102
 
93
- async parseDeviceMessage(
94
- id: number,
95
- stream: ExactReadable | AsyncExactReadable,
96
- ): Promise<void> {
97
- if (await this.#clipboard?.parse(id, stream)) {
98
- return;
99
- }
100
-
101
- if (await this.#ackClipboardHandler?.parse(id, stream)) {
102
- return;
103
- }
104
-
105
- throw new Error("Unknown device message");
106
- }
107
-
108
- endDeviceMessageStream(e?: unknown): void {
109
- if (e) {
110
- this.#clipboard?.error(e);
111
- this.#ackClipboardHandler?.error(e);
112
- } else {
113
- this.#clipboard?.close();
114
- this.#ackClipboardHandler?.close();
115
- }
116
- }
117
-
118
103
  createMediaStreamTransformer(): TransformStream<
119
104
  Uint8Array,
120
105
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyControlMessageType,
@@ -12,6 +11,7 @@ import type {
12
11
  ScrcpyScrollController,
13
12
  ScrcpyVideoStream,
14
13
  } from "../base/index.js";
14
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
15
15
  import type {
16
16
  ScrcpyBackOrScreenOnControlMessage,
17
17
  ScrcpyInjectTouchControlMessage,
@@ -55,12 +55,22 @@ export class ScrcpyOptions1_25
55
55
 
56
56
  #ackClipboardHandler: AckClipboardHandler | undefined;
57
57
 
58
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
59
+ get deviceMessageParsers() {
60
+ return this.#deviceMessageParsers;
61
+ }
62
+
58
63
  constructor(init: Init) {
59
64
  this.value = { ...Defaults, ...init };
60
65
 
61
66
  if (this.value.control && this.value.clipboardAutosync) {
62
- this.#clipboard = new ClipboardStream();
63
- this.#ackClipboardHandler = new AckClipboardHandler();
67
+ this.#clipboard = this.#deviceMessageParsers.add(
68
+ new ClipboardStream(),
69
+ );
70
+
71
+ this.#ackClipboardHandler = this.#deviceMessageParsers.add(
72
+ new AckClipboardHandler(),
73
+ );
64
74
  }
65
75
  }
66
76
 
@@ -90,31 +100,6 @@ export class ScrcpyOptions1_25
90
100
  return parseVideoStreamMetadata(this.value, stream);
91
101
  }
92
102
 
93
- async parseDeviceMessage(
94
- id: number,
95
- stream: ExactReadable | AsyncExactReadable,
96
- ): Promise<void> {
97
- if (await this.#clipboard?.parse(id, stream)) {
98
- return;
99
- }
100
-
101
- if (await this.#ackClipboardHandler?.parse(id, stream)) {
102
- return;
103
- }
104
-
105
- throw new Error("Unknown device message");
106
- }
107
-
108
- endDeviceMessageStream(e?: unknown): void {
109
- if (e) {
110
- this.#clipboard?.error(e);
111
- this.#ackClipboardHandler?.error(e);
112
- } else {
113
- this.#clipboard?.close();
114
- this.#ackClipboardHandler?.close();
115
- }
116
- }
117
-
118
103
  createMediaStreamTransformer(): TransformStream<
119
104
  Uint8Array,
120
105
  ScrcpyMediaStreamPacket
@@ -1,6 +1,5 @@
1
1
  import type { MaybePromiseLike } from "@yume-chan/async";
2
2
  import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
3
- import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
4
3
 
5
4
  import type {
6
5
  ScrcpyAudioStreamMetadata,
@@ -13,6 +12,7 @@ import type {
13
12
  ScrcpyScrollController,
14
13
  ScrcpyVideoStream,
15
14
  } from "../base/index.js";
15
+ import { ScrcpyDeviceMessageParsers } from "../base/index.js";
16
16
  import type {
17
17
  ScrcpyBackOrScreenOnControlMessage,
18
18
  ScrcpyInjectTouchControlMessage,
@@ -56,12 +56,22 @@ export class ScrcpyOptions2_0
56
56
 
57
57
  #ackClipboardHandler: AckClipboardHandler | undefined;
58
58
 
59
+ #deviceMessageParsers = new ScrcpyDeviceMessageParsers();
60
+ get deviceMessageParsers() {
61
+ return this.#deviceMessageParsers;
62
+ }
63
+
59
64
  constructor(init: Init) {
60
65
  this.value = { ...Defaults, ...init };
61
66
 
62
67
  if (this.value.control && this.value.clipboardAutosync) {
63
- this.#clipboard = new ClipboardStream();
64
- this.#ackClipboardHandler = new AckClipboardHandler();
68
+ this.#clipboard = this.#deviceMessageParsers.add(
69
+ new ClipboardStream(),
70
+ );
71
+
72
+ this.#ackClipboardHandler = this.#deviceMessageParsers.add(
73
+ new AckClipboardHandler(),
74
+ );
65
75
  }
66
76
  }
67
77
 
@@ -97,31 +107,6 @@ export class ScrcpyOptions2_0
97
107
  return parseAudioStreamMetadata(stream, this.value);
98
108
  }
99
109
 
100
- async parseDeviceMessage(
101
- id: number,
102
- stream: ExactReadable | AsyncExactReadable,
103
- ): Promise<void> {
104
- if (await this.#clipboard?.parse(id, stream)) {
105
- return;
106
- }
107
-
108
- if (await this.#ackClipboardHandler?.parse(id, stream)) {
109
- return;
110
- }
111
-
112
- throw new Error("Unknown device message");
113
- }
114
-
115
- endDeviceMessageStream(e?: unknown): void {
116
- if (e) {
117
- this.#clipboard?.error(e);
118
- this.#ackClipboardHandler?.error(e);
119
- } else {
120
- this.#clipboard?.close();
121
- this.#ackClipboardHandler?.close();
122
- }
123
- }
124
-
125
110
  createMediaStreamTransformer(): TransformStream<
126
111
  Uint8Array,
127
112
  ScrcpyMediaStreamPacket