@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.
- package/CHANGELOG.json +21 -0
- package/CHANGELOG.md +11 -1
- package/LICENSE +1 -1
- package/esm/codec/av1.d.ts +364 -0
- package/esm/codec/av1.d.ts.map +1 -1
- package/esm/codec/av1.js +591 -0
- package/esm/codec/av1.js.map +1 -1
- package/esm/codec/nalu.d.ts +0 -9
- package/esm/codec/nalu.d.ts.map +1 -1
- package/esm/codec/nalu.js +56 -129
- package/esm/codec/nalu.js.map +1 -1
- package/esm/control/{basic.d.ts → empty.d.ts} +2 -2
- package/esm/control/empty.d.ts.map +1 -0
- package/esm/control/empty.js +3 -0
- package/esm/control/empty.js.map +1 -0
- package/esm/control/index.d.ts +1 -1
- package/esm/control/index.js +1 -1
- package/esm/control/rotate-device.js +2 -2
- package/esm/control/serializer.d.ts +2 -0
- package/esm/control/serializer.d.ts.map +1 -1
- package/esm/control/serializer.js +10 -4
- package/esm/control/serializer.js.map +1 -1
- package/esm/control/type.js +1 -1
- package/esm/control/type.js.map +1 -1
- package/esm/control/writer.d.ts +4 -1
- package/esm/control/writer.d.ts.map +1 -1
- package/esm/control/writer.js +12 -2
- package/esm/control/writer.js.map +1 -1
- package/esm/index.d.ts +0 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +0 -1
- package/esm/index.js.map +1 -1
- package/esm/options/1_16/float.d.ts +6 -0
- package/esm/options/1_16/float.d.ts.map +1 -0
- package/esm/options/1_16/{float-to-uint16.js → float.js} +7 -6
- package/esm/options/1_16/float.js.map +1 -0
- package/esm/options/1_16/index.d.ts +1 -1
- package/esm/options/1_16/index.d.ts.map +1 -1
- package/esm/options/1_16/index.js +1 -1
- package/esm/options/1_16/index.js.map +1 -1
- package/esm/options/1_16/message.d.ts +4 -0
- package/esm/options/1_16/message.d.ts.map +1 -1
- package/esm/options/1_16/message.js +7 -4
- package/esm/options/1_16/message.js.map +1 -1
- package/esm/options/1_16/options.d.ts +13 -4
- package/esm/options/1_16/options.d.ts.map +1 -1
- package/esm/options/1_16/options.js +43 -15
- package/esm/options/1_16/options.js.map +1 -1
- package/esm/options/1_17.d.ts +2 -3
- package/esm/options/1_17.d.ts.map +1 -1
- package/esm/options/1_17.js +3 -6
- package/esm/options/1_17.js.map +1 -1
- package/esm/options/1_18.d.ts +2 -3
- package/esm/options/1_18.d.ts.map +1 -1
- package/esm/options/1_18.js +4 -24
- package/esm/options/1_18.js.map +1 -1
- package/esm/options/1_21.d.ts +9 -4
- package/esm/options/1_21.d.ts.map +1 -1
- package/esm/options/1_21.js +30 -7
- package/esm/options/1_21.js.map +1 -1
- package/esm/options/1_22/options.d.ts +2 -3
- package/esm/options/1_22/options.d.ts.map +1 -1
- package/esm/options/1_22/options.js +4 -7
- package/esm/options/1_22/options.js.map +1 -1
- package/esm/options/1_23.d.ts +2 -3
- package/esm/options/1_23.d.ts.map +1 -1
- package/esm/options/1_23.js +4 -7
- package/esm/options/1_23.js.map +1 -1
- package/esm/options/1_24.d.ts +2 -3
- package/esm/options/1_24.d.ts.map +1 -1
- package/esm/options/1_24.js +3 -6
- package/esm/options/1_24.js.map +1 -1
- package/esm/options/1_25/options.d.ts +2 -3
- package/esm/options/1_25/options.d.ts.map +1 -1
- package/esm/options/1_25/options.js +3 -6
- package/esm/options/1_25/options.js.map +1 -1
- package/esm/options/1_25/scroll.d.ts +3 -2
- package/esm/options/1_25/scroll.d.ts.map +1 -1
- package/esm/options/1_25/scroll.js +8 -7
- package/esm/options/1_25/scroll.js.map +1 -1
- package/esm/options/2_0.d.ts +10 -8
- package/esm/options/2_0.d.ts.map +1 -1
- package/esm/options/2_0.js +68 -74
- package/esm/options/2_0.js.map +1 -1
- package/esm/options/2_1.d.ts +4 -5
- package/esm/options/2_1.d.ts.map +1 -1
- package/esm/options/2_1.js +3 -6
- package/esm/options/2_1.js.map +1 -1
- package/esm/options/2_2.d.ts +4 -5
- package/esm/options/2_2.d.ts.map +1 -1
- package/esm/options/2_2.js +3 -6
- package/esm/options/2_2.js.map +1 -1
- package/esm/options/2_3.d.ts +59 -0
- package/esm/options/2_3.d.ts.map +1 -0
- package/esm/options/2_3.js +47 -0
- package/esm/options/2_3.js.map +1 -0
- package/esm/options/codec.d.ts +1 -0
- package/esm/options/codec.d.ts.map +1 -1
- package/esm/options/codec.js +1 -0
- package/esm/options/codec.js.map +1 -1
- package/esm/options/index.d.ts +1 -0
- package/esm/options/index.d.ts.map +1 -1
- package/esm/options/index.js +1 -0
- package/esm/options/index.js.map +1 -1
- package/esm/options/latest.d.ts +4 -4
- package/esm/options/latest.js +2 -2
- package/esm/options/types.d.ts +30 -32
- package/esm/options/types.d.ts.map +1 -1
- package/esm/options/types.js +77 -26
- package/esm/options/types.js.map +1 -1
- package/package.json +11 -11
- package/src/codec/av1.ts +670 -0
- package/src/codec/nalu.ts +67 -154
- package/src/control/empty.ts +3 -0
- package/src/control/index.ts +1 -1
- package/src/control/rotate-device.ts +2 -2
- package/src/control/serializer.ts +12 -4
- package/src/control/type.ts +1 -1
- package/src/control/writer.ts +16 -6
- package/src/index.ts +0 -1
- package/src/options/1_16/{float-to-uint16.ts → float.ts} +8 -6
- package/src/options/1_16/index.ts +1 -1
- package/src/options/1_16/message.ts +8 -4
- package/src/options/1_16/options.ts +68 -28
- package/src/options/1_17.ts +3 -9
- package/src/options/1_18.ts +3 -36
- package/src/options/1_21.ts +40 -11
- package/src/options/1_22/options.ts +4 -10
- package/src/options/1_23.ts +4 -10
- package/src/options/1_24.ts +3 -9
- package/src/options/1_25/options.ts +3 -9
- package/src/options/1_25/scroll.ts +10 -11
- package/src/options/2_0.ts +87 -92
- package/src/options/2_1.ts +3 -9
- package/src/options/2_2.ts +3 -9
- package/src/options/2_3.ts +70 -0
- package/src/options/codec.ts +6 -0
- package/src/options/index.ts +1 -0
- package/src/options/latest.ts +4 -4
- package/src/options/types.ts +89 -98
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/control/basic.d.ts.map +0 -1
- package/esm/control/basic.js +0 -3
- package/esm/control/basic.js.map +0 -1
- package/esm/device-message/ack-clipboard.d.ts +0 -9
- package/esm/device-message/ack-clipboard.d.ts.map +0 -1
- package/esm/device-message/ack-clipboard.js +0 -6
- package/esm/device-message/ack-clipboard.js.map +0 -1
- package/esm/device-message/clipboard.d.ts +0 -10
- package/esm/device-message/clipboard.d.ts.map +0 -1
- package/esm/device-message/clipboard.js +0 -7
- package/esm/device-message/clipboard.js.map +0 -1
- package/esm/device-message/index.d.ts +0 -5
- package/esm/device-message/index.d.ts.map +0 -1
- package/esm/device-message/index.js +0 -5
- package/esm/device-message/index.js.map +0 -1
- package/esm/device-message/stream.d.ts +0 -8
- package/esm/device-message/stream.d.ts.map +0 -1
- package/esm/device-message/stream.js +0 -35
- package/esm/device-message/stream.js.map +0 -1
- package/esm/device-message/type.d.ts +0 -5
- package/esm/device-message/type.d.ts.map +0 -1
- package/esm/device-message/type.js +0 -7
- package/esm/device-message/type.js.map +0 -1
- package/esm/options/1_16/float-to-uint16.d.ts +0 -5
- package/esm/options/1_16/float-to-uint16.d.ts.map +0 -1
- package/esm/options/1_16/float-to-uint16.js.map +0 -1
- package/src/control/basic.ts +0 -3
- package/src/device-message/ack-clipboard.ts +0 -10
- package/src/device-message/clipboard.ts +0 -11
- package/src/device-message/index.ts +0 -4
- package/src/device-message/stream.ts +0 -49
- package/src/device-message/type.ts +0 -5
package/src/codec/nalu.ts
CHANGED
|
@@ -91,153 +91,17 @@ export function* annexBSplitNalu(buffer: Uint8Array): Generator<Uint8Array> {
|
|
|
91
91
|
yield buffer.subarray(start, buffer.length);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
/**
|
|
95
|
-
* Remove emulation prevention bytes from a H.264/H.265 NAL Unit.
|
|
96
|
-
*
|
|
97
|
-
* The input is not modified.
|
|
98
|
-
* If the input doesn't contain any emulation prevention bytes,
|
|
99
|
-
* the input is returned as-is.
|
|
100
|
-
* Otherwise, a new `Uint8Array` is created and returned.
|
|
101
|
-
*/
|
|
102
|
-
export function naluRemoveEmulation(buffer: Uint8Array) {
|
|
103
|
-
// output will be created when first emulation prevention byte is found
|
|
104
|
-
let output: Uint8Array | undefined;
|
|
105
|
-
let outputOffset = 0;
|
|
106
|
-
|
|
107
|
-
let zeroCount = 0;
|
|
108
|
-
let inEmulation = false;
|
|
109
|
-
|
|
110
|
-
let i = 0;
|
|
111
|
-
scan: for (; i < buffer.length; i += 1) {
|
|
112
|
-
const byte = buffer[i]!;
|
|
113
|
-
|
|
114
|
-
if (byte === 0x00) {
|
|
115
|
-
zeroCount += 1;
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Current byte is not zero
|
|
120
|
-
const prevZeroCount = zeroCount;
|
|
121
|
-
zeroCount = 0;
|
|
122
|
-
|
|
123
|
-
if (prevZeroCount < 2) {
|
|
124
|
-
// zero or one `0x00`s are acceptable
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (byte === 0x01) {
|
|
129
|
-
// Unexpected start code
|
|
130
|
-
throw new Error("Invalid data");
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (prevZeroCount > 2) {
|
|
134
|
-
// Too much `0x00`s
|
|
135
|
-
throw new Error("Invalid data");
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
switch (byte) {
|
|
139
|
-
case 0x02:
|
|
140
|
-
// Didn't find why, but 7.4.1 NAL unit semantics forbids `0x000002` appearing in NAL units
|
|
141
|
-
throw new Error("Invalid data");
|
|
142
|
-
case 0x03:
|
|
143
|
-
// `0x000003` is the "emulation_prevention_three_byte"
|
|
144
|
-
// `0x00000300`, `0x00000301`, `0x00000302` and `0x00000303` represent
|
|
145
|
-
// `0x000000`, `0x000001`, `0x000002` and `0x000003` respectively
|
|
146
|
-
inEmulation = true;
|
|
147
|
-
|
|
148
|
-
// Create output and copy the data before the emulation prevention byte
|
|
149
|
-
// Output size is unknown, so we use the input size as an upper bound
|
|
150
|
-
output = new Uint8Array(buffer.length - 1);
|
|
151
|
-
output.set(buffer.subarray(0, i));
|
|
152
|
-
outputOffset = i;
|
|
153
|
-
i += 1;
|
|
154
|
-
break scan;
|
|
155
|
-
default:
|
|
156
|
-
// `0x000004` or larger are as-is
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (!output) {
|
|
162
|
-
return buffer;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Continue at the byte after the emulation prevention byte
|
|
166
|
-
for (; i < buffer.length; i += 1) {
|
|
167
|
-
const byte = buffer[i]!;
|
|
168
|
-
|
|
169
|
-
output[outputOffset] = byte;
|
|
170
|
-
outputOffset += 1;
|
|
171
|
-
|
|
172
|
-
if (inEmulation) {
|
|
173
|
-
if (byte > 0x03) {
|
|
174
|
-
// `0x00000304` or larger are invalid
|
|
175
|
-
throw new Error("Invalid data");
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// `00000300000300` results in `0000000000` (both `0x03` are removed)
|
|
179
|
-
// which means the `0x00` after `0x03` also counts
|
|
180
|
-
if (byte === 0x00) {
|
|
181
|
-
zeroCount += 1;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
inEmulation = false;
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (byte === 0x00) {
|
|
189
|
-
zeroCount += 1;
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const prevZeroCount = zeroCount;
|
|
194
|
-
zeroCount = 0;
|
|
195
|
-
|
|
196
|
-
if (prevZeroCount < 2) {
|
|
197
|
-
// zero or one `0x00`s are acceptable
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (byte === 0x01) {
|
|
202
|
-
// Unexpected start code
|
|
203
|
-
throw new Error("Invalid data");
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (prevZeroCount > 2) {
|
|
207
|
-
// Too much `0x00`s
|
|
208
|
-
throw new Error("Invalid data");
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
switch (byte) {
|
|
212
|
-
case 0x02:
|
|
213
|
-
// Didn't find why, but 7.4.1 NAL unit semantics forbids `0x000002` appearing in NAL units
|
|
214
|
-
throw new Error("Invalid data");
|
|
215
|
-
case 0x03:
|
|
216
|
-
// `0x000003` is the "emulation_prevention_three_byte"
|
|
217
|
-
// `0x00000300`, `0x00000301`, `0x00000302` and `0x00000303` represent
|
|
218
|
-
// `0x000000`, `0x000001`, `0x000002` and `0x000003` respectively
|
|
219
|
-
inEmulation = true;
|
|
220
|
-
|
|
221
|
-
// Remove the emulation prevention byte
|
|
222
|
-
outputOffset -= 1;
|
|
223
|
-
break;
|
|
224
|
-
default:
|
|
225
|
-
// `0x000004` or larger are as-is
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return output.subarray(0, outputOffset);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
94
|
export class NaluSodbBitReader {
|
|
234
95
|
readonly #nalu: Uint8Array;
|
|
96
|
+
// logical length is `#byteLength * 8 + (7 - #stopBitIndex)`
|
|
235
97
|
readonly #byteLength: number;
|
|
236
98
|
readonly #stopBitIndex: number;
|
|
237
99
|
|
|
238
100
|
#zeroCount = 0;
|
|
239
|
-
|
|
240
|
-
|
|
101
|
+
|
|
102
|
+
// logical position is `#bytePosition * 8 + (7 - #bitPosition)`
|
|
103
|
+
#bytePosition = 0;
|
|
104
|
+
#bitPosition = 7;
|
|
241
105
|
#byte = 0;
|
|
242
106
|
|
|
243
107
|
get byteLength() {
|
|
@@ -258,14 +122,15 @@ export class NaluSodbBitReader {
|
|
|
258
122
|
|
|
259
123
|
get ended() {
|
|
260
124
|
return (
|
|
261
|
-
this.#bytePosition
|
|
262
|
-
this.#bitPosition
|
|
125
|
+
this.#bytePosition >= this.#byteLength &&
|
|
126
|
+
this.#bitPosition <= this.#stopBitIndex
|
|
263
127
|
);
|
|
264
128
|
}
|
|
265
129
|
|
|
266
130
|
constructor(nalu: Uint8Array) {
|
|
267
131
|
this.#nalu = nalu;
|
|
268
132
|
|
|
133
|
+
// Search for the last bit being `1`, also known as the stop bit
|
|
269
134
|
for (let i = nalu.length - 1; i >= 0; i -= 1) {
|
|
270
135
|
if (this.#nalu[i] === 0) {
|
|
271
136
|
continue;
|
|
@@ -276,7 +141,7 @@ export class NaluSodbBitReader {
|
|
|
276
141
|
if (((byte >> j) & 1) === 1) {
|
|
277
142
|
this.#byteLength = i;
|
|
278
143
|
this.#stopBitIndex = j;
|
|
279
|
-
this.#
|
|
144
|
+
this.#loadByte();
|
|
280
145
|
return;
|
|
281
146
|
}
|
|
282
147
|
}
|
|
@@ -285,15 +150,22 @@ export class NaluSodbBitReader {
|
|
|
285
150
|
throw new Error("Stop bit not found");
|
|
286
151
|
}
|
|
287
152
|
|
|
288
|
-
#
|
|
153
|
+
#loadByte() {
|
|
289
154
|
this.#byte = this.#nalu[this.#bytePosition]!;
|
|
155
|
+
|
|
156
|
+
// If the current sequence is `0x000003`, skip to the next byte.
|
|
157
|
+
// `annexBSplitNalu` had validated the input, so skip the check here
|
|
290
158
|
if (this.#zeroCount === 2 && this.#byte === 3) {
|
|
291
159
|
this.#zeroCount = 0;
|
|
292
160
|
this.#bytePosition += 1;
|
|
293
|
-
|
|
161
|
+
// Call `#loadByte` again, because if the next byte is `0x00`,
|
|
162
|
+
// it need to be counted in `#zeroCount` as well.
|
|
163
|
+
this.#loadByte();
|
|
294
164
|
return;
|
|
295
165
|
}
|
|
296
166
|
|
|
167
|
+
// `0x00000301` becomes `0x000001`, so only the `0x03` byte needs to be skipped
|
|
168
|
+
// All `0x00` bytes are returned as-is
|
|
297
169
|
if (this.#byte === 0) {
|
|
298
170
|
this.#zeroCount += 1;
|
|
299
171
|
} else {
|
|
@@ -302,18 +174,19 @@ export class NaluSodbBitReader {
|
|
|
302
174
|
}
|
|
303
175
|
|
|
304
176
|
next() {
|
|
305
|
-
if (this.#bitPosition === -1) {
|
|
306
|
-
this.#bitPosition = 7;
|
|
307
|
-
this.#bytePosition += 1;
|
|
308
|
-
this.#readByte();
|
|
309
|
-
}
|
|
310
|
-
|
|
311
177
|
if (this.ended) {
|
|
312
178
|
throw new Error("Bit index out of bounds");
|
|
313
179
|
}
|
|
314
180
|
|
|
315
181
|
const value = (this.#byte >> this.#bitPosition) & 1;
|
|
182
|
+
|
|
316
183
|
this.#bitPosition -= 1;
|
|
184
|
+
if (this.#bitPosition < 0) {
|
|
185
|
+
this.#bytePosition += 1;
|
|
186
|
+
this.#bitPosition = 7;
|
|
187
|
+
this.#loadByte();
|
|
188
|
+
}
|
|
189
|
+
|
|
317
190
|
return value;
|
|
318
191
|
}
|
|
319
192
|
|
|
@@ -329,10 +202,50 @@ export class NaluSodbBitReader {
|
|
|
329
202
|
return result;
|
|
330
203
|
}
|
|
331
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Throws an error if the current position is invalid for `skip`.
|
|
207
|
+
*
|
|
208
|
+
* Usually it will throw if `ended` is `true`,
|
|
209
|
+
* except when the bit position is at the stop bit,
|
|
210
|
+
* in which case `ended` will be `true`, but it won't throw.
|
|
211
|
+
* `skip` can skip all remaining bits, and stop at the end position.
|
|
212
|
+
* The next `next` call will throw since there is no more bits to read.
|
|
213
|
+
*/
|
|
214
|
+
#checkSkipPosition() {
|
|
215
|
+
if (
|
|
216
|
+
this.#bytePosition >= this.#byteLength &&
|
|
217
|
+
this.#bitPosition < this.#stopBitIndex
|
|
218
|
+
) {
|
|
219
|
+
throw new Error("Bit index out of bounds");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
332
223
|
skip(length: number) {
|
|
333
|
-
|
|
334
|
-
this
|
|
224
|
+
if (length <= this.#bitPosition + 1) {
|
|
225
|
+
this.#bitPosition -= length;
|
|
226
|
+
this.#checkSkipPosition();
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Because of emulation prevention bytes,
|
|
231
|
+
// we don't know how many bits are left in the NAL,
|
|
232
|
+
// nor how many bits should be skipped.
|
|
233
|
+
// So we need to check each byte.
|
|
234
|
+
|
|
235
|
+
length -= this.#bitPosition + 1;
|
|
236
|
+
this.#bytePosition += 1;
|
|
237
|
+
this.#bitPosition = 7;
|
|
238
|
+
this.#loadByte();
|
|
239
|
+
this.#checkSkipPosition();
|
|
240
|
+
|
|
241
|
+
for (; length >= 8; length -= 8) {
|
|
242
|
+
this.#bytePosition += 1;
|
|
243
|
+
this.#loadByte();
|
|
244
|
+
this.#checkSkipPosition();
|
|
335
245
|
}
|
|
246
|
+
|
|
247
|
+
this.#bitPosition = 7 - length;
|
|
248
|
+
this.#checkSkipPosition();
|
|
336
249
|
}
|
|
337
250
|
|
|
338
251
|
decodeExponentialGolombNumber(): number {
|
package/src/control/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EmptyControlMessage } from "./empty.js";
|
|
2
2
|
|
|
3
|
-
export const ScrcpyRotateDeviceControlMessage =
|
|
3
|
+
export const ScrcpyRotateDeviceControlMessage = EmptyControlMessage;
|
|
4
4
|
|
|
5
5
|
export type ScrcpyRotateDeviceControlMessage =
|
|
6
6
|
(typeof ScrcpyRotateDeviceControlMessage)["TInit"];
|
|
@@ -3,13 +3,14 @@ import type {
|
|
|
3
3
|
ScrcpyScrollController,
|
|
4
4
|
} from "../options/index.js";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { EmptyControlMessage } from "./empty.js";
|
|
7
7
|
import type { AndroidKeyEventAction } from "./inject-keycode.js";
|
|
8
8
|
import { ScrcpyInjectKeyCodeControlMessage } from "./inject-keycode.js";
|
|
9
9
|
import type { ScrcpyInjectScrollControlMessage } from "./inject-scroll.js";
|
|
10
10
|
import { ScrcpyInjectTextControlMessage } from "./inject-text.js";
|
|
11
11
|
import type { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
12
12
|
import { ScrcpyRotateDeviceControlMessage } from "./rotate-device.js";
|
|
13
|
+
import type { ScrcpySetClipboardControlMessage } from "./set-clipboard.js";
|
|
13
14
|
import type { AndroidScreenPowerMode } from "./set-screen-power-mode.js";
|
|
14
15
|
import { ScrcpySetScreenPowerModeControlMessage } from "./set-screen-power-mode.js";
|
|
15
16
|
import {
|
|
@@ -85,7 +86,7 @@ export class ScrcpyControlMessageSerializer {
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
expandNotificationPanel() {
|
|
88
|
-
return
|
|
89
|
+
return EmptyControlMessage.serialize({
|
|
89
90
|
type: this.#typeValues.get(
|
|
90
91
|
ScrcpyControlMessageType.ExpandNotificationPanel,
|
|
91
92
|
),
|
|
@@ -93,7 +94,7 @@ export class ScrcpyControlMessageSerializer {
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
expandSettingPanel() {
|
|
96
|
-
return
|
|
97
|
+
return EmptyControlMessage.serialize({
|
|
97
98
|
type: this.#typeValues.get(
|
|
98
99
|
ScrcpyControlMessageType.ExpandSettingPanel,
|
|
99
100
|
),
|
|
@@ -101,7 +102,7 @@ export class ScrcpyControlMessageSerializer {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
collapseNotificationPanel() {
|
|
104
|
-
return
|
|
105
|
+
return EmptyControlMessage.serialize({
|
|
105
106
|
type: this.#typeValues.get(
|
|
106
107
|
ScrcpyControlMessageType.CollapseNotificationPanel,
|
|
107
108
|
),
|
|
@@ -113,4 +114,11 @@ export class ScrcpyControlMessageSerializer {
|
|
|
113
114
|
type: this.#typeValues.get(ScrcpyControlMessageType.RotateDevice),
|
|
114
115
|
});
|
|
115
116
|
}
|
|
117
|
+
|
|
118
|
+
setClipboard(message: Omit<ScrcpySetClipboardControlMessage, "type">) {
|
|
119
|
+
return this.#options.serializeSetClipboardControlMessage({
|
|
120
|
+
...message,
|
|
121
|
+
type: this.#typeValues.get(ScrcpyControlMessageType.SetClipboard),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
116
124
|
}
|
package/src/control/type.ts
CHANGED
|
@@ -34,7 +34,7 @@ export class ScrcpyControlMessageTypeValue {
|
|
|
34
34
|
get(type: ScrcpyControlMessageType): number {
|
|
35
35
|
const value = this.#types.indexOf(type);
|
|
36
36
|
if (value === -1) {
|
|
37
|
-
throw new
|
|
37
|
+
throw new TypeError("Invalid or unsupported control message type");
|
|
38
38
|
}
|
|
39
39
|
return value;
|
|
40
40
|
}
|
package/src/control/writer.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
WritableStreamDefaultWriter,
|
|
4
|
-
} from "@yume-chan/stream-extra";
|
|
5
|
-
import { ConsumableWritableStream } from "@yume-chan/stream-extra";
|
|
1
|
+
import type { WritableStreamDefaultWriter } from "@yume-chan/stream-extra";
|
|
2
|
+
import { Consumable } from "@yume-chan/stream-extra";
|
|
6
3
|
|
|
7
4
|
import type { ScrcpyOptions } from "../options/index.js";
|
|
8
5
|
|
|
@@ -13,6 +10,7 @@ import type {
|
|
|
13
10
|
import type { ScrcpyInjectScrollControlMessage } from "./inject-scroll.js";
|
|
14
11
|
import type { ScrcpyInjectTouchControlMessage } from "./inject-touch.js";
|
|
15
12
|
import { ScrcpyControlMessageSerializer } from "./serializer.js";
|
|
13
|
+
import type { ScrcpySetClipboardControlMessage } from "./set-clipboard.js";
|
|
16
14
|
import type { AndroidScreenPowerMode } from "./set-screen-power-mode.js";
|
|
17
15
|
|
|
18
16
|
export class ScrcpyControlMessageWriter {
|
|
@@ -28,7 +26,7 @@ export class ScrcpyControlMessageWriter {
|
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
async write(message: Uint8Array) {
|
|
31
|
-
await
|
|
29
|
+
await Consumable.WritableStream.write(this.#writer, message);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
async injectKeyCode(
|
|
@@ -87,6 +85,18 @@ export class ScrcpyControlMessageWriter {
|
|
|
87
85
|
await this.write(this.#serializer.rotateDevice());
|
|
88
86
|
}
|
|
89
87
|
|
|
88
|
+
async setClipboard(
|
|
89
|
+
message: Omit<ScrcpySetClipboardControlMessage, "type">,
|
|
90
|
+
) {
|
|
91
|
+
const result = this.#serializer.setClipboard(message);
|
|
92
|
+
if (result instanceof Uint8Array) {
|
|
93
|
+
await this.write(result);
|
|
94
|
+
} else {
|
|
95
|
+
await this.write(result[0]);
|
|
96
|
+
await result[1];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
90
100
|
releaseLock() {
|
|
91
101
|
this.#writer.releaseLock();
|
|
92
102
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getUint16 } from "@yume-chan/no-data-view";
|
|
2
|
+
import type { NumberFieldVariant } from "@yume-chan/struct";
|
|
3
|
+
import { NumberFieldDefinition } from "@yume-chan/struct";
|
|
2
4
|
|
|
3
5
|
export function clamp(value: number, min: number, max: number): number {
|
|
4
6
|
if (value < min) {
|
|
@@ -12,11 +14,11 @@ export function clamp(value: number, min: number, max: number): number {
|
|
|
12
14
|
return value;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
export const
|
|
17
|
+
export const ScrcpyUnsignedFloatNumberVariant: NumberFieldVariant = {
|
|
16
18
|
size: 2,
|
|
17
19
|
signed: false,
|
|
18
20
|
deserialize(array, littleEndian) {
|
|
19
|
-
const value =
|
|
21
|
+
const value = getUint16(array, 0, littleEndian);
|
|
20
22
|
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/server/src/main/java/com/genymobile/scrcpy/Binary.java#L22
|
|
21
23
|
return value === 0xffff ? 1 : value / 0x10000;
|
|
22
24
|
},
|
|
@@ -24,10 +26,10 @@ export const ScrcpyFloatToUint16NumberType: NumberFieldType = {
|
|
|
24
26
|
// https://github.com/Genymobile/scrcpy/blob/1f138aef41de651668043b32c4effc2d4adbfc44/app/src/util/binary.h#L51
|
|
25
27
|
value = clamp(value, -1, 1);
|
|
26
28
|
value = value === 1 ? 0xffff : value * 0x10000;
|
|
27
|
-
|
|
29
|
+
dataView.setUint16(offset, value, littleEndian);
|
|
28
30
|
},
|
|
29
31
|
};
|
|
30
32
|
|
|
31
|
-
export const
|
|
32
|
-
|
|
33
|
+
export const ScrcpyUnsignedFloatFieldDefinition = new NumberFieldDefinition(
|
|
34
|
+
ScrcpyUnsignedFloatNumberVariant,
|
|
33
35
|
);
|
|
@@ -2,11 +2,11 @@ import Struct, { placeholder } from "@yume-chan/struct";
|
|
|
2
2
|
|
|
3
3
|
import type { AndroidMotionEventAction } from "../../control/index.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
EmptyControlMessage,
|
|
6
6
|
ScrcpyControlMessageType,
|
|
7
7
|
} from "../../control/index.js";
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { ScrcpyUnsignedFloatFieldDefinition } from "./float.js";
|
|
10
10
|
|
|
11
11
|
export const SCRCPY_CONTROL_MESSAGE_TYPES_1_16: readonly ScrcpyControlMessageType[] =
|
|
12
12
|
[
|
|
@@ -38,13 +38,13 @@ export const ScrcpyInjectTouchControlMessage1_16 = new Struct()
|
|
|
38
38
|
.uint32("pointerY")
|
|
39
39
|
.uint16("screenWidth")
|
|
40
40
|
.uint16("screenHeight")
|
|
41
|
-
.field("pressure",
|
|
41
|
+
.field("pressure", ScrcpyUnsignedFloatFieldDefinition)
|
|
42
42
|
.uint32("buttons");
|
|
43
43
|
|
|
44
44
|
export type ScrcpyInjectTouchControlMessage1_16 =
|
|
45
45
|
(typeof ScrcpyInjectTouchControlMessage1_16)["TInit"];
|
|
46
46
|
|
|
47
|
-
export const ScrcpyBackOrScreenOnControlMessage1_16 =
|
|
47
|
+
export const ScrcpyBackOrScreenOnControlMessage1_16 = EmptyControlMessage;
|
|
48
48
|
|
|
49
49
|
export const ScrcpySetClipboardControlMessage1_15 = new Struct()
|
|
50
50
|
.uint8("type")
|
|
@@ -53,3 +53,7 @@ export const ScrcpySetClipboardControlMessage1_15 = new Struct()
|
|
|
53
53
|
|
|
54
54
|
export type ScrcpySetClipboardControlMessage1_15 =
|
|
55
55
|
(typeof ScrcpySetClipboardControlMessage1_15)["TInit"];
|
|
56
|
+
|
|
57
|
+
export const ScrcpyClipboardDeviceMessage = new Struct()
|
|
58
|
+
.uint32("length")
|
|
59
|
+
.string("content", { lengthField: "length" });
|