@yume-chan/scrcpy 0.0.23 → 0.0.24

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 (173) hide show
  1. package/CHANGELOG.json +21 -0
  2. package/CHANGELOG.md +11 -1
  3. package/LICENSE +1 -1
  4. package/esm/codec/av1.d.ts +364 -0
  5. package/esm/codec/av1.d.ts.map +1 -1
  6. package/esm/codec/av1.js +591 -0
  7. package/esm/codec/av1.js.map +1 -1
  8. package/esm/codec/nalu.d.ts +0 -9
  9. package/esm/codec/nalu.d.ts.map +1 -1
  10. package/esm/codec/nalu.js +56 -129
  11. package/esm/codec/nalu.js.map +1 -1
  12. package/esm/control/{basic.d.ts → empty.d.ts} +2 -2
  13. package/esm/control/empty.d.ts.map +1 -0
  14. package/esm/control/empty.js +3 -0
  15. package/esm/control/empty.js.map +1 -0
  16. package/esm/control/index.d.ts +1 -1
  17. package/esm/control/index.js +1 -1
  18. package/esm/control/rotate-device.js +2 -2
  19. package/esm/control/serializer.d.ts +2 -0
  20. package/esm/control/serializer.d.ts.map +1 -1
  21. package/esm/control/serializer.js +10 -4
  22. package/esm/control/serializer.js.map +1 -1
  23. package/esm/control/type.js +1 -1
  24. package/esm/control/type.js.map +1 -1
  25. package/esm/control/writer.d.ts +4 -1
  26. package/esm/control/writer.d.ts.map +1 -1
  27. package/esm/control/writer.js +12 -2
  28. package/esm/control/writer.js.map +1 -1
  29. package/esm/index.d.ts +0 -1
  30. package/esm/index.d.ts.map +1 -1
  31. package/esm/index.js +0 -1
  32. package/esm/index.js.map +1 -1
  33. package/esm/options/1_16/float.d.ts +6 -0
  34. package/esm/options/1_16/float.d.ts.map +1 -0
  35. package/esm/options/1_16/{float-to-uint16.js → float.js} +7 -6
  36. package/esm/options/1_16/float.js.map +1 -0
  37. package/esm/options/1_16/index.d.ts +1 -1
  38. package/esm/options/1_16/index.d.ts.map +1 -1
  39. package/esm/options/1_16/index.js +1 -1
  40. package/esm/options/1_16/index.js.map +1 -1
  41. package/esm/options/1_16/message.d.ts +4 -0
  42. package/esm/options/1_16/message.d.ts.map +1 -1
  43. package/esm/options/1_16/message.js +7 -4
  44. package/esm/options/1_16/message.js.map +1 -1
  45. package/esm/options/1_16/options.d.ts +13 -4
  46. package/esm/options/1_16/options.d.ts.map +1 -1
  47. package/esm/options/1_16/options.js +43 -15
  48. package/esm/options/1_16/options.js.map +1 -1
  49. package/esm/options/1_17.d.ts +2 -3
  50. package/esm/options/1_17.d.ts.map +1 -1
  51. package/esm/options/1_17.js +3 -6
  52. package/esm/options/1_17.js.map +1 -1
  53. package/esm/options/1_18.d.ts +2 -3
  54. package/esm/options/1_18.d.ts.map +1 -1
  55. package/esm/options/1_18.js +4 -24
  56. package/esm/options/1_18.js.map +1 -1
  57. package/esm/options/1_21.d.ts +9 -4
  58. package/esm/options/1_21.d.ts.map +1 -1
  59. package/esm/options/1_21.js +30 -7
  60. package/esm/options/1_21.js.map +1 -1
  61. package/esm/options/1_22/options.d.ts +2 -3
  62. package/esm/options/1_22/options.d.ts.map +1 -1
  63. package/esm/options/1_22/options.js +4 -7
  64. package/esm/options/1_22/options.js.map +1 -1
  65. package/esm/options/1_23.d.ts +2 -3
  66. package/esm/options/1_23.d.ts.map +1 -1
  67. package/esm/options/1_23.js +4 -7
  68. package/esm/options/1_23.js.map +1 -1
  69. package/esm/options/1_24.d.ts +2 -3
  70. package/esm/options/1_24.d.ts.map +1 -1
  71. package/esm/options/1_24.js +3 -6
  72. package/esm/options/1_24.js.map +1 -1
  73. package/esm/options/1_25/options.d.ts +2 -3
  74. package/esm/options/1_25/options.d.ts.map +1 -1
  75. package/esm/options/1_25/options.js +3 -6
  76. package/esm/options/1_25/options.js.map +1 -1
  77. package/esm/options/1_25/scroll.d.ts +3 -2
  78. package/esm/options/1_25/scroll.d.ts.map +1 -1
  79. package/esm/options/1_25/scroll.js +8 -7
  80. package/esm/options/1_25/scroll.js.map +1 -1
  81. package/esm/options/2_0.d.ts +10 -8
  82. package/esm/options/2_0.d.ts.map +1 -1
  83. package/esm/options/2_0.js +68 -74
  84. package/esm/options/2_0.js.map +1 -1
  85. package/esm/options/2_1.d.ts +4 -5
  86. package/esm/options/2_1.d.ts.map +1 -1
  87. package/esm/options/2_1.js +3 -6
  88. package/esm/options/2_1.js.map +1 -1
  89. package/esm/options/2_2.d.ts +4 -5
  90. package/esm/options/2_2.d.ts.map +1 -1
  91. package/esm/options/2_2.js +3 -6
  92. package/esm/options/2_2.js.map +1 -1
  93. package/esm/options/2_3.d.ts +59 -0
  94. package/esm/options/2_3.d.ts.map +1 -0
  95. package/esm/options/2_3.js +47 -0
  96. package/esm/options/2_3.js.map +1 -0
  97. package/esm/options/codec.d.ts +1 -0
  98. package/esm/options/codec.d.ts.map +1 -1
  99. package/esm/options/codec.js +1 -0
  100. package/esm/options/codec.js.map +1 -1
  101. package/esm/options/index.d.ts +1 -0
  102. package/esm/options/index.d.ts.map +1 -1
  103. package/esm/options/index.js +1 -0
  104. package/esm/options/index.js.map +1 -1
  105. package/esm/options/latest.d.ts +4 -4
  106. package/esm/options/latest.js +2 -2
  107. package/esm/options/types.d.ts +30 -32
  108. package/esm/options/types.d.ts.map +1 -1
  109. package/esm/options/types.js +77 -26
  110. package/esm/options/types.js.map +1 -1
  111. package/package.json +11 -11
  112. package/src/codec/av1.ts +670 -0
  113. package/src/codec/nalu.ts +67 -154
  114. package/src/control/empty.ts +3 -0
  115. package/src/control/index.ts +1 -1
  116. package/src/control/rotate-device.ts +2 -2
  117. package/src/control/serializer.ts +12 -4
  118. package/src/control/type.ts +1 -1
  119. package/src/control/writer.ts +16 -6
  120. package/src/index.ts +0 -1
  121. package/src/options/1_16/{float-to-uint16.ts → float.ts} +8 -6
  122. package/src/options/1_16/index.ts +1 -1
  123. package/src/options/1_16/message.ts +8 -4
  124. package/src/options/1_16/options.ts +68 -28
  125. package/src/options/1_17.ts +3 -9
  126. package/src/options/1_18.ts +3 -36
  127. package/src/options/1_21.ts +40 -11
  128. package/src/options/1_22/options.ts +4 -10
  129. package/src/options/1_23.ts +4 -10
  130. package/src/options/1_24.ts +3 -9
  131. package/src/options/1_25/options.ts +3 -9
  132. package/src/options/1_25/scroll.ts +10 -11
  133. package/src/options/2_0.ts +87 -92
  134. package/src/options/2_1.ts +3 -9
  135. package/src/options/2_2.ts +3 -9
  136. package/src/options/2_3.ts +70 -0
  137. package/src/options/codec.ts +6 -0
  138. package/src/options/index.ts +1 -0
  139. package/src/options/latest.ts +4 -4
  140. package/src/options/types.ts +89 -98
  141. package/tsconfig.build.tsbuildinfo +1 -1
  142. package/esm/control/basic.d.ts.map +0 -1
  143. package/esm/control/basic.js +0 -3
  144. package/esm/control/basic.js.map +0 -1
  145. package/esm/device-message/ack-clipboard.d.ts +0 -9
  146. package/esm/device-message/ack-clipboard.d.ts.map +0 -1
  147. package/esm/device-message/ack-clipboard.js +0 -6
  148. package/esm/device-message/ack-clipboard.js.map +0 -1
  149. package/esm/device-message/clipboard.d.ts +0 -10
  150. package/esm/device-message/clipboard.d.ts.map +0 -1
  151. package/esm/device-message/clipboard.js +0 -7
  152. package/esm/device-message/clipboard.js.map +0 -1
  153. package/esm/device-message/index.d.ts +0 -5
  154. package/esm/device-message/index.d.ts.map +0 -1
  155. package/esm/device-message/index.js +0 -5
  156. package/esm/device-message/index.js.map +0 -1
  157. package/esm/device-message/stream.d.ts +0 -8
  158. package/esm/device-message/stream.d.ts.map +0 -1
  159. package/esm/device-message/stream.js +0 -35
  160. package/esm/device-message/stream.js.map +0 -1
  161. package/esm/device-message/type.d.ts +0 -5
  162. package/esm/device-message/type.d.ts.map +0 -1
  163. package/esm/device-message/type.js +0 -7
  164. package/esm/device-message/type.js.map +0 -1
  165. package/esm/options/1_16/float-to-uint16.d.ts +0 -5
  166. package/esm/options/1_16/float-to-uint16.d.ts.map +0 -1
  167. package/esm/options/1_16/float-to-uint16.js.map +0 -1
  168. package/src/control/basic.ts +0 -3
  169. package/src/device-message/ack-clipboard.ts +0 -10
  170. package/src/device-message/clipboard.ts +0 -11
  171. package/src/device-message/index.ts +0 -4
  172. package/src/device-message/stream.ts +0 -49
  173. package/src/device-message/type.ts +0 -5
@@ -1,11 +1,19 @@
1
- import type { ReadableStream } from "@yume-chan/stream-extra";
1
+ import {
2
+ getUint16BigEndian,
3
+ getUint32BigEndian,
4
+ } from "@yume-chan/no-data-view";
5
+ import type {
6
+ PushReadableStreamController,
7
+ ReadableStream,
8
+ } from "@yume-chan/stream-extra";
2
9
  import {
3
10
  BufferedReadableStream,
11
+ PushReadableStream,
4
12
  StructDeserializeStream,
5
13
  TransformStream,
6
14
  } from "@yume-chan/stream-extra";
7
15
  import type { AsyncExactReadable, ValueOrPromise } from "@yume-chan/struct";
8
- import { NumberFieldType, decodeUtf8 } from "@yume-chan/struct";
16
+ import { decodeUtf8 } from "@yume-chan/struct";
9
17
 
10
18
  import type {
11
19
  ScrcpyBackOrScreenOnControlMessage,
@@ -20,8 +28,8 @@ import type {
20
28
  ScrcpyVideoStreamMetadata,
21
29
  } from "../codec.js";
22
30
  import { ScrcpyVideoCodecId } from "../codec.js";
23
- import type { ScrcpyDisplay, ScrcpyEncoder, ScrcpyOptions } from "../types.js";
24
- import { toScrcpyOptionValue } from "../types.js";
31
+ import type { ScrcpyDisplay, ScrcpyEncoder } from "../types.js";
32
+ import { ScrcpyOptions, toScrcpyOptionValue } from "../types.js";
25
33
 
26
34
  import { CodecOptions } from "./codec-options.js";
27
35
  import type { ScrcpyOptionsInit1_16 } from "./init.js";
@@ -30,6 +38,7 @@ import {
30
38
  SCRCPY_CONTROL_MESSAGE_TYPES_1_16,
31
39
  SCRCPY_MEDIA_PACKET_FLAG_CONFIG,
32
40
  ScrcpyBackOrScreenOnControlMessage1_16,
41
+ ScrcpyClipboardDeviceMessage,
33
42
  ScrcpyInjectTouchControlMessage1_16,
34
43
  ScrcpyMediaStreamRawPacket,
35
44
  ScrcpySetClipboardControlMessage1_15,
@@ -37,7 +46,7 @@ import {
37
46
  import type { ScrcpyScrollController } from "./scroll.js";
38
47
  import { ScrcpyScrollController1_16 } from "./scroll.js";
39
48
 
40
- export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
49
+ export class ScrcpyOptions1_16 extends ScrcpyOptions<ScrcpyOptionsInit1_16> {
41
50
  static readonly DEFAULTS = {
42
51
  logLevel: ScrcpyLogLevel1_16.Debug,
43
52
  maxSize: 0,
@@ -74,35 +83,50 @@ export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
74
83
  return order.map((key) => toScrcpyOptionValue(options[key], "-"));
75
84
  }
76
85
 
86
+ /**
87
+ * Parse a fixed-length, null-terminated string.
88
+ * @param stream The stream to read from
89
+ * @param maxLength The maximum length of the string, including the null terminator, in bytes
90
+ * @returns The parsed string, without the null terminator
91
+ */
77
92
  static async parseCString(
78
93
  stream: AsyncExactReadable,
79
94
  maxLength: number,
80
95
  ): Promise<string> {
81
- let result = decodeUtf8(await stream.readExactly(maxLength));
82
- result = result.substring(0, result.indexOf("\0"));
83
- return result;
96
+ const buffer = await stream.readExactly(maxLength);
97
+ // If null terminator is not found, `subarray(0, -1)` will remove the last byte
98
+ // But since it's a invalid case, it's fine
99
+ return decodeUtf8(buffer.subarray(0, buffer.indexOf(0)));
84
100
  }
85
101
 
86
102
  static async parseUint16BE(stream: AsyncExactReadable): Promise<number> {
87
- const buffer = await stream.readExactly(NumberFieldType.Uint16.size);
88
- return NumberFieldType.Uint16.deserialize(buffer, false);
103
+ const buffer = await stream.readExactly(2);
104
+ return getUint16BigEndian(buffer, 0);
89
105
  }
90
106
 
91
107
  static async parseUint32BE(stream: AsyncExactReadable): Promise<number> {
92
- const buffer = await stream.readExactly(NumberFieldType.Uint32.size);
93
- return NumberFieldType.Uint32.deserialize(buffer, false);
108
+ const buffer = await stream.readExactly(4);
109
+ return getUint32BigEndian(buffer, 0);
94
110
  }
95
111
 
96
- value: Required<ScrcpyOptionsInit1_16>;
97
-
98
112
  readonly defaults: Required<ScrcpyOptionsInit1_16> =
99
113
  ScrcpyOptions1_16.DEFAULTS;
100
114
 
101
- readonly controlMessageTypes: readonly ScrcpyControlMessageType[] =
102
- SCRCPY_CONTROL_MESSAGE_TYPES_1_16;
115
+ override get controlMessageTypes(): readonly ScrcpyControlMessageType[] {
116
+ return SCRCPY_CONTROL_MESSAGE_TYPES_1_16;
117
+ }
118
+
119
+ #clipboardController!: PushReadableStreamController<string>;
120
+ #clipboard: ReadableStream<string>;
121
+ override get clipboard() {
122
+ return this.#clipboard;
123
+ }
103
124
 
104
125
  constructor(init: ScrcpyOptionsInit1_16) {
105
- this.value = { ...ScrcpyOptions1_16.DEFAULTS, ...init };
126
+ super(undefined, init, ScrcpyOptions1_16.DEFAULTS);
127
+ this.#clipboard = new PushReadableStream<string>((controller) => {
128
+ this.#clipboardController = controller;
129
+ });
106
130
  }
107
131
 
108
132
  serialize(): string[] {
@@ -112,22 +136,22 @@ export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
112
136
  );
113
137
  }
114
138
 
115
- setListEncoders(): void {
139
+ override setListEncoders(): void {
116
140
  throw new Error("Not supported");
117
141
  }
118
142
 
119
- setListDisplays(): void {
143
+ override setListDisplays(): void {
120
144
  // Set to an invalid value
121
145
  // Server will print valid values before crashing
122
146
  // (server will crash before opening sockets)
123
147
  this.value.displayId = -1;
124
148
  }
125
149
 
126
- parseEncoder(): ScrcpyEncoder | undefined {
150
+ override parseEncoder(): ScrcpyEncoder | undefined {
127
151
  throw new Error("Not supported");
128
152
  }
129
153
 
130
- parseDisplay(line: string): ScrcpyDisplay | undefined {
154
+ override parseDisplay(line: string): ScrcpyDisplay | undefined {
131
155
  const match = line.match(/^\s+scrcpy --display (\d+)$/);
132
156
  if (match) {
133
157
  return {
@@ -137,7 +161,7 @@ export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
137
161
  return undefined;
138
162
  }
139
163
 
140
- parseVideoStreamMetadata(
164
+ override parseVideoStreamMetadata(
141
165
  stream: ReadableStream<Uint8Array>,
142
166
  ): ValueOrPromise<ScrcpyVideoStream> {
143
167
  return (async () => {
@@ -155,11 +179,27 @@ export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
155
179
  })();
156
180
  }
157
181
 
158
- parseAudioStreamMetadata(): never {
182
+ override parseAudioStreamMetadata(): never {
159
183
  throw new Error("Not supported");
160
184
  }
161
185
 
162
- createMediaStreamTransformer(): TransformStream<
186
+ override async parseDeviceMessage(
187
+ id: number,
188
+ stream: AsyncExactReadable,
189
+ ): Promise<boolean> {
190
+ switch (id) {
191
+ case 0: {
192
+ const message =
193
+ await ScrcpyClipboardDeviceMessage.deserialize(stream);
194
+ await this.#clipboardController.enqueue(message.content);
195
+ return true;
196
+ }
197
+ default:
198
+ return false;
199
+ }
200
+ }
201
+
202
+ override createMediaStreamTransformer(): TransformStream<
163
203
  Uint8Array,
164
204
  ScrcpyMediaStreamPacket
165
205
  > {
@@ -202,13 +242,13 @@ export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
202
242
  };
203
243
  }
204
244
 
205
- serializeInjectTouchControlMessage(
245
+ override serializeInjectTouchControlMessage(
206
246
  message: ScrcpyInjectTouchControlMessage,
207
247
  ): Uint8Array {
208
248
  return ScrcpyInjectTouchControlMessage1_16.serialize(message);
209
249
  }
210
250
 
211
- serializeBackOrScreenOnControlMessage(
251
+ override serializeBackOrScreenOnControlMessage(
212
252
  message: ScrcpyBackOrScreenOnControlMessage,
213
253
  ) {
214
254
  if (message.action === AndroidKeyEventAction.Down) {
@@ -218,13 +258,13 @@ export class ScrcpyOptions1_16 implements ScrcpyOptions<ScrcpyOptionsInit1_16> {
218
258
  return undefined;
219
259
  }
220
260
 
221
- serializeSetClipboardControlMessage(
261
+ override serializeSetClipboardControlMessage(
222
262
  message: ScrcpySetClipboardControlMessage,
223
263
  ): Uint8Array {
224
264
  return ScrcpySetClipboardControlMessage1_15.serialize(message);
225
265
  }
226
266
 
227
- createScrollController(): ScrcpyScrollController {
267
+ override createScrollController(): ScrcpyScrollController {
228
268
  return new ScrcpyScrollController1_16();
229
269
  }
230
270
  }
@@ -1,16 +1,13 @@
1
1
  import type { ScrcpyOptionsInit1_16 } from "./1_16/index.js";
2
2
  import { ScrcpyOptions1_16 } from "./1_16/index.js";
3
3
  import type { ScrcpyEncoder } from "./types.js";
4
- import { ScrcpyOptionsBase } from "./types.js";
4
+ import { ScrcpyOptions } from "./types.js";
5
5
 
6
6
  export interface ScrcpyOptionsInit1_17 extends ScrcpyOptionsInit1_16 {
7
7
  encoderName?: string | undefined;
8
8
  }
9
9
 
10
- export class ScrcpyOptions1_17 extends ScrcpyOptionsBase<
11
- ScrcpyOptionsInit1_17,
12
- ScrcpyOptions1_16
13
- > {
10
+ export class ScrcpyOptions1_17 extends ScrcpyOptions<ScrcpyOptionsInit1_17> {
14
11
  static readonly DEFAULTS = {
15
12
  ...ScrcpyOptions1_16.DEFAULTS,
16
13
  encoderName: undefined,
@@ -37,10 +34,7 @@ export class ScrcpyOptions1_17 extends ScrcpyOptionsBase<
37
34
  }
38
35
 
39
36
  constructor(init: ScrcpyOptionsInit1_17) {
40
- super(new ScrcpyOptions1_16(init), {
41
- ...ScrcpyOptions1_17.DEFAULTS,
42
- ...init,
43
- });
37
+ super(ScrcpyOptions1_16, init, ScrcpyOptions1_17.DEFAULTS);
44
38
  }
45
39
 
46
40
  override serialize(): string[] {
@@ -9,14 +9,12 @@ import { ScrcpyControlMessageType } from "../control/index.js";
9
9
  import {
10
10
  SCRCPY_CONTROL_MESSAGE_TYPES_1_16,
11
11
  ScrcpyBackOrScreenOnControlMessage1_16,
12
- ScrcpyLogLevel1_16,
13
12
  ScrcpyOptions1_16,
14
- ScrcpyVideoOrientation1_16,
15
13
  } from "./1_16/index.js";
16
14
  import type { ScrcpyOptionsInit1_17 } from "./1_17.js";
17
15
  import { ScrcpyOptions1_17 } from "./1_17.js";
18
16
  import type { ScrcpyEncoder } from "./types.js";
19
- import { ScrcpyOptionsBase } from "./types.js";
17
+ import { ScrcpyOptions } from "./types.js";
20
18
 
21
19
  export enum ScrcpyLogLevel1_18 {
22
20
  Verbose = "verbose",
@@ -59,29 +57,7 @@ SCRCPY_CONTROL_MESSAGE_TYPES_1_18.splice(
59
57
  ScrcpyControlMessageType.ExpandSettingPanel,
60
58
  );
61
59
 
62
- const LOG_LEVEL_MAP = {
63
- [ScrcpyLogLevel1_18.Verbose]: ScrcpyLogLevel1_16.Debug,
64
- [ScrcpyLogLevel1_18.Debug]: ScrcpyLogLevel1_16.Debug,
65
- [ScrcpyLogLevel1_18.Info]: ScrcpyLogLevel1_16.Info,
66
- [ScrcpyLogLevel1_18.Warn]: ScrcpyLogLevel1_16.Warn,
67
- [ScrcpyLogLevel1_18.Error]: ScrcpyLogLevel1_16.Error,
68
- };
69
-
70
- const VIDEO_ORIENTATION_MAP = {
71
- [ScrcpyVideoOrientation1_18.Initial]: ScrcpyVideoOrientation1_16.Unlocked,
72
- [ScrcpyVideoOrientation1_18.Unlocked]: ScrcpyVideoOrientation1_16.Unlocked,
73
- [ScrcpyVideoOrientation1_18.Portrait]: ScrcpyVideoOrientation1_16.Portrait,
74
- [ScrcpyVideoOrientation1_18.Landscape]:
75
- ScrcpyVideoOrientation1_16.Landscape,
76
- [ScrcpyVideoOrientation1_18.PortraitFlipped]:
77
- ScrcpyVideoOrientation1_16.PortraitFlipped,
78
- [ScrcpyVideoOrientation1_18.LandscapeFlipped]:
79
- ScrcpyVideoOrientation1_16.LandscapeFlipped,
80
- };
81
- export class ScrcpyOptions1_18 extends ScrcpyOptionsBase<
82
- ScrcpyOptionsInit1_18,
83
- ScrcpyOptions1_17
84
- > {
60
+ export class ScrcpyOptions1_18 extends ScrcpyOptions<ScrcpyOptionsInit1_18> {
85
61
  static readonly DEFAULTS = {
86
62
  ...ScrcpyOptions1_17.DEFAULTS,
87
63
  logLevel: ScrcpyLogLevel1_18.Debug,
@@ -103,16 +79,7 @@ export class ScrcpyOptions1_18 extends ScrcpyOptionsBase<
103
79
  }
104
80
 
105
81
  constructor(init: ScrcpyOptionsInit1_18) {
106
- const value = { ...ScrcpyOptions1_18.DEFAULTS, ...init };
107
- super(
108
- new ScrcpyOptions1_17({
109
- ...init,
110
- logLevel: LOG_LEVEL_MAP[value.logLevel],
111
- lockVideoOrientation:
112
- VIDEO_ORIENTATION_MAP[value.lockVideoOrientation],
113
- }),
114
- value,
115
- );
82
+ super(ScrcpyOptions1_17, init, ScrcpyOptions1_18.DEFAULTS);
116
83
  }
117
84
 
118
85
  override serialize(): string[] {
@@ -1,12 +1,16 @@
1
1
  // cspell: ignore autosync
2
2
 
3
+ import { PromiseResolver } from "@yume-chan/async";
4
+ import type { AsyncExactReadable } from "@yume-chan/struct";
3
5
  import Struct, { placeholder } from "@yume-chan/struct";
4
6
 
5
7
  import type { ScrcpySetClipboardControlMessage } from "../control/index.js";
6
8
 
7
9
  import type { ScrcpyOptionsInit1_18 } from "./1_18.js";
8
10
  import { ScrcpyOptions1_18 } from "./1_18.js";
9
- import { ScrcpyOptionsBase, toScrcpyOptionValue } from "./types.js";
11
+ import { ScrcpyOptions, toScrcpyOptionValue } from "./types.js";
12
+
13
+ export const ScrcpyAckClipboardDeviceMessage = new Struct().uint64("sequence");
10
14
 
11
15
  export interface ScrcpyOptionsInit1_21 extends ScrcpyOptionsInit1_18 {
12
16
  clipboardAutosync?: boolean;
@@ -26,10 +30,7 @@ export const ScrcpySetClipboardControlMessage1_21 = new Struct()
26
30
  export type ScrcpySetClipboardControlMessage1_21 =
27
31
  (typeof ScrcpySetClipboardControlMessage1_21)["TInit"];
28
32
 
29
- export class ScrcpyOptions1_21 extends ScrcpyOptionsBase<
30
- ScrcpyOptionsInit1_21,
31
- ScrcpyOptions1_18
32
- > {
33
+ export class ScrcpyOptions1_21 extends ScrcpyOptions<ScrcpyOptionsInit1_21> {
33
34
  static readonly DEFAULTS = {
34
35
  ...ScrcpyOptions1_18.DEFAULTS,
35
36
  clipboardAutosync: true,
@@ -64,11 +65,30 @@ export class ScrcpyOptions1_21 extends ScrcpyOptionsBase<
64
65
  return ScrcpyOptions1_21.DEFAULTS;
65
66
  }
66
67
 
68
+ #clipboardAck = new Map<bigint, PromiseResolver<void>>();
69
+
67
70
  constructor(init: ScrcpyOptionsInit1_21) {
68
- super(new ScrcpyOptions1_18(init), {
69
- ...ScrcpyOptions1_21.DEFAULTS,
70
- ...init,
71
- });
71
+ super(ScrcpyOptions1_18, init, ScrcpyOptions1_21.DEFAULTS);
72
+ }
73
+
74
+ override async parseDeviceMessage(
75
+ id: number,
76
+ stream: AsyncExactReadable,
77
+ ): Promise<boolean> {
78
+ switch (id) {
79
+ case 1: {
80
+ const message =
81
+ await ScrcpyAckClipboardDeviceMessage.deserialize(stream);
82
+ const resolver = this.#clipboardAck.get(message.sequence);
83
+ if (resolver) {
84
+ resolver.resolve();
85
+ this.#clipboardAck.delete(message.sequence);
86
+ }
87
+ return true;
88
+ }
89
+ default:
90
+ return await super.parseDeviceMessage(id, stream);
91
+ }
72
92
  }
73
93
 
74
94
  override serialize(): string[] {
@@ -77,7 +97,16 @@ export class ScrcpyOptions1_21 extends ScrcpyOptionsBase<
77
97
 
78
98
  override serializeSetClipboardControlMessage(
79
99
  message: ScrcpySetClipboardControlMessage,
80
- ): Uint8Array {
81
- return ScrcpySetClipboardControlMessage1_21.serialize(message);
100
+ ): Uint8Array | [Uint8Array, Promise<void>] {
101
+ if (message.sequence === 0n) {
102
+ return ScrcpySetClipboardControlMessage1_21.serialize(message);
103
+ }
104
+
105
+ const resolver = new PromiseResolver<void>();
106
+ this.#clipboardAck.set(message.sequence, resolver);
107
+ return [
108
+ ScrcpySetClipboardControlMessage1_21.serialize(message),
109
+ resolver.promise,
110
+ ];
82
111
  }
83
112
  }
@@ -5,15 +5,12 @@ import type { ScrcpyScrollController } from "../1_16/index.js";
5
5
  import { ScrcpyOptions1_21 } from "../1_21.js";
6
6
  import type { ScrcpyVideoStream } from "../codec.js";
7
7
  import { ScrcpyVideoCodecId } from "../codec.js";
8
- import { ScrcpyOptionsBase } from "../types.js";
8
+ import { ScrcpyOptions } from "../types.js";
9
9
 
10
10
  import type { ScrcpyOptionsInit1_22 } from "./init.js";
11
11
  import { ScrcpyScrollController1_22 } from "./scroll.js";
12
12
 
13
- export class ScrcpyOptions1_22 extends ScrcpyOptionsBase<
14
- ScrcpyOptionsInit1_22,
15
- ScrcpyOptions1_21
16
- > {
13
+ export class ScrcpyOptions1_22 extends ScrcpyOptions<ScrcpyOptionsInit1_22> {
17
14
  static readonly DEFAULTS = {
18
15
  ...ScrcpyOptions1_21.DEFAULTS,
19
16
  downsizeOnError: true,
@@ -26,10 +23,7 @@ export class ScrcpyOptions1_22 extends ScrcpyOptionsBase<
26
23
  }
27
24
 
28
25
  constructor(init: ScrcpyOptionsInit1_22) {
29
- super(new ScrcpyOptions1_21(init), {
30
- ...ScrcpyOptions1_22.DEFAULTS,
31
- ...init,
32
- });
26
+ super(ScrcpyOptions1_21, init, ScrcpyOptions1_22.DEFAULTS);
33
27
  }
34
28
 
35
29
  override parseVideoStreamMetadata(
@@ -38,7 +32,7 @@ export class ScrcpyOptions1_22 extends ScrcpyOptionsBase<
38
32
  if (!this.value.sendDeviceMeta) {
39
33
  return { stream, metadata: { codec: ScrcpyVideoCodecId.H264 } };
40
34
  } else {
41
- return this._base.parseVideoStreamMetadata(stream);
35
+ return super.parseVideoStreamMetadata(stream);
42
36
  }
43
37
  }
44
38
 
@@ -4,7 +4,7 @@ import { ScrcpyOptions1_21 } from "./1_21.js";
4
4
  import type { ScrcpyOptionsInit1_22 } from "./1_22/index.js";
5
5
  import { ScrcpyOptions1_22 } from "./1_22/index.js";
6
6
  import type { ScrcpyMediaStreamPacket } from "./codec.js";
7
- import { ScrcpyOptionsBase } from "./types.js";
7
+ import { ScrcpyOptions } from "./types.js";
8
8
 
9
9
  export interface ScrcpyOptionsInit1_23 extends ScrcpyOptionsInit1_22 {
10
10
  cleanup?: boolean;
@@ -12,10 +12,7 @@ export interface ScrcpyOptionsInit1_23 extends ScrcpyOptionsInit1_22 {
12
12
 
13
13
  const KEYFRAME_PTS = 1n << 62n;
14
14
 
15
- export class ScrcpyOptions1_23 extends ScrcpyOptionsBase<
16
- ScrcpyOptionsInit1_23,
17
- ScrcpyOptions1_22
18
- > {
15
+ export class ScrcpyOptions1_23 extends ScrcpyOptions<ScrcpyOptionsInit1_23> {
19
16
  static readonly DEFAULTS = {
20
17
  ...ScrcpyOptions1_22.DEFAULTS,
21
18
  cleanup: true,
@@ -26,10 +23,7 @@ export class ScrcpyOptions1_23 extends ScrcpyOptionsBase<
26
23
  }
27
24
 
28
25
  constructor(init: ScrcpyOptionsInit1_22) {
29
- super(new ScrcpyOptions1_22(init), {
30
- ...ScrcpyOptions1_23.DEFAULTS,
31
- ...init,
32
- });
26
+ super(ScrcpyOptions1_22, init, ScrcpyOptions1_23.DEFAULTS);
33
27
  }
34
28
 
35
29
  override serialize(): string[] {
@@ -40,7 +34,7 @@ export class ScrcpyOptions1_23 extends ScrcpyOptionsBase<
40
34
  Uint8Array,
41
35
  ScrcpyMediaStreamPacket
42
36
  > {
43
- const stream = this._base.createMediaStreamTransformer();
37
+ const stream = super.createMediaStreamTransformer();
44
38
  return {
45
39
  writable: stream.writable,
46
40
  readable: stream.readable.pipeThrough(
@@ -1,16 +1,13 @@
1
1
  import { ScrcpyOptions1_21 } from "./1_21.js";
2
2
  import type { ScrcpyOptionsInit1_23 } from "./1_23.js";
3
3
  import { ScrcpyOptions1_23 } from "./1_23.js";
4
- import { ScrcpyOptionsBase } from "./types.js";
4
+ import { ScrcpyOptions } from "./types.js";
5
5
 
6
6
  export interface ScrcpyOptionsInit1_24 extends ScrcpyOptionsInit1_23 {
7
7
  powerOn?: boolean;
8
8
  }
9
9
 
10
- export class ScrcpyOptions1_24 extends ScrcpyOptionsBase<
11
- ScrcpyOptionsInit1_24,
12
- ScrcpyOptions1_23
13
- > {
10
+ export class ScrcpyOptions1_24 extends ScrcpyOptions<ScrcpyOptionsInit1_24> {
14
11
  static readonly DEFAULTS = {
15
12
  ...ScrcpyOptions1_23.DEFAULTS,
16
13
  powerOn: true,
@@ -21,10 +18,7 @@ export class ScrcpyOptions1_24 extends ScrcpyOptionsBase<
21
18
  }
22
19
 
23
20
  constructor(init: ScrcpyOptionsInit1_24) {
24
- super(new ScrcpyOptions1_23(init), {
25
- ...ScrcpyOptions1_24.DEFAULTS,
26
- ...init,
27
- });
21
+ super(ScrcpyOptions1_23, init, ScrcpyOptions1_24.DEFAULTS);
28
22
  }
29
23
 
30
24
  override serialize(): string[] {
@@ -2,23 +2,17 @@ import type { ScrcpyScrollController } from "../1_16/index.js";
2
2
  import { ScrcpyOptions1_21 } from "../1_21.js";
3
3
  import type { ScrcpyOptionsInit1_24 } from "../1_24.js";
4
4
  import { ScrcpyOptions1_24 } from "../1_24.js";
5
- import { ScrcpyOptionsBase } from "../types.js";
5
+ import { ScrcpyOptions } from "../types.js";
6
6
 
7
7
  import { ScrcpyScrollController1_25 } from "./scroll.js";
8
8
 
9
- export class ScrcpyOptions1_25 extends ScrcpyOptionsBase<
10
- ScrcpyOptionsInit1_24,
11
- ScrcpyOptions1_24
12
- > {
9
+ export class ScrcpyOptions1_25 extends ScrcpyOptions<ScrcpyOptionsInit1_24> {
13
10
  override get defaults(): Required<ScrcpyOptionsInit1_24> {
14
11
  return ScrcpyOptions1_24.DEFAULTS;
15
12
  }
16
13
 
17
14
  constructor(init: ScrcpyOptionsInit1_24) {
18
- super(new ScrcpyOptions1_24(init), {
19
- ...ScrcpyOptions1_24.DEFAULTS,
20
- ...init,
21
- });
15
+ super(ScrcpyOptions1_24, init, ScrcpyOptions1_24.DEFAULTS);
22
16
  }
23
17
 
24
18
  override serialize(): string[] {
@@ -1,18 +1,17 @@
1
- import Struct, {
2
- NumberFieldDefinition,
3
- NumberFieldType,
4
- } from "@yume-chan/struct";
1
+ import { getInt16 } from "@yume-chan/no-data-view";
2
+ import type { NumberFieldVariant } from "@yume-chan/struct";
3
+ import Struct, { NumberFieldDefinition } from "@yume-chan/struct";
5
4
 
6
5
  import type { ScrcpyInjectScrollControlMessage } from "../../control/index.js";
7
6
  import { ScrcpyControlMessageType } from "../../control/index.js";
8
7
  import type { ScrcpyScrollController } from "../1_16/index.js";
9
8
  import { clamp } from "../1_16/index.js";
10
9
 
11
- export const ScrcpyFloatToInt16NumberType: NumberFieldType = {
10
+ export const ScrcpySignedFloatNumberVariant: NumberFieldVariant = {
12
11
  size: 2,
13
12
  signed: true,
14
13
  deserialize(array, littleEndian) {
15
- const value = NumberFieldType.Int16.deserialize(array, littleEndian);
14
+ const value = getInt16(array, 0, littleEndian);
16
15
  // https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/server/src/main/java/com/genymobile/scrcpy/Binary.java#L34
17
16
  return value === 0x7fff ? 1 : value / 0x8000;
18
17
  },
@@ -20,12 +19,12 @@ export const ScrcpyFloatToInt16NumberType: NumberFieldType = {
20
19
  // https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/app/src/util/binary.h#L65
21
20
  value = clamp(value, -1, 1);
22
21
  value = value === 1 ? 0x7fff : value * 0x8000;
23
- NumberFieldType.Int16.serialize(dataView, offset, value, littleEndian);
22
+ dataView.setInt16(offset, value, littleEndian);
24
23
  },
25
24
  };
26
25
 
27
- const ScrcpyFloatToInt16FieldDefinition = new NumberFieldDefinition(
28
- ScrcpyFloatToInt16NumberType,
26
+ const ScrcpySignedFloatFieldDefinition = new NumberFieldDefinition(
27
+ ScrcpySignedFloatNumberVariant,
29
28
  );
30
29
 
31
30
  export const ScrcpyInjectScrollControlMessage1_25 = new Struct()
@@ -34,8 +33,8 @@ export const ScrcpyInjectScrollControlMessage1_25 = new Struct()
34
33
  .uint32("pointerY")
35
34
  .uint16("screenWidth")
36
35
  .uint16("screenHeight")
37
- .field("scrollX", ScrcpyFloatToInt16FieldDefinition)
38
- .field("scrollY", ScrcpyFloatToInt16FieldDefinition)
36
+ .field("scrollX", ScrcpySignedFloatFieldDefinition)
37
+ .field("scrollY", ScrcpySignedFloatFieldDefinition)
39
38
  .int32("buttons");
40
39
 
41
40
  export type ScrcpyInjectScrollControlMessage1_25 =