@yume-chan/scrcpy 0.0.15 → 0.0.17

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 (214) hide show
  1. package/CHANGELOG.json +33 -0
  2. package/CHANGELOG.md +18 -1
  3. package/LICENSE +21 -21
  4. package/README.md +327 -89
  5. package/esm/adb/client.d.ts +40 -0
  6. package/esm/adb/client.d.ts.map +1 -0
  7. package/esm/adb/client.js +218 -0
  8. package/esm/adb/client.js.map +1 -0
  9. package/esm/adb/connection.d.ts +38 -0
  10. package/esm/adb/connection.d.ts.map +1 -0
  11. package/esm/{connection.js → adb/connection.js} +20 -24
  12. package/esm/adb/connection.js.map +1 -0
  13. package/esm/adb/index.d.ts +4 -0
  14. package/esm/adb/index.d.ts.map +1 -0
  15. package/esm/adb/index.js +4 -0
  16. package/esm/adb/index.js.map +1 -0
  17. package/esm/adb/options/1_16.d.ts +8 -0
  18. package/esm/adb/options/1_16.d.ts.map +1 -0
  19. package/esm/adb/options/1_16.js +20 -0
  20. package/esm/adb/options/1_16.js.map +1 -0
  21. package/esm/adb/options/1_22.d.ts +8 -0
  22. package/esm/adb/options/1_22.d.ts.map +1 -0
  23. package/esm/adb/options/1_22.js +17 -0
  24. package/esm/adb/options/1_22.js.map +1 -0
  25. package/esm/adb/options/index.d.ts +4 -0
  26. package/esm/adb/options/index.d.ts.map +1 -0
  27. package/esm/adb/options/index.js +4 -0
  28. package/esm/adb/options/index.js.map +1 -0
  29. package/esm/adb/options/types.d.ts +23 -0
  30. package/esm/adb/options/types.d.ts.map +1 -0
  31. package/esm/adb/options/types.js +30 -0
  32. package/esm/adb/options/types.js.map +1 -0
  33. package/esm/codec.js +2 -2
  34. package/esm/codec.js.map +1 -1
  35. package/esm/control/index.d.ts +8 -0
  36. package/esm/control/index.d.ts.map +1 -0
  37. package/esm/control/index.js +8 -0
  38. package/esm/control/index.js.map +1 -0
  39. package/esm/control/inject-keycode.d.ts +53 -0
  40. package/esm/control/inject-keycode.d.ts.map +1 -0
  41. package/esm/control/inject-keycode.js +54 -0
  42. package/esm/control/inject-keycode.js.map +1 -0
  43. package/esm/control/inject-text.d.ts +9 -0
  44. package/esm/control/inject-text.d.ts.map +1 -0
  45. package/esm/control/inject-text.js +7 -0
  46. package/esm/control/inject-text.js.map +1 -0
  47. package/esm/control/inject-touch.d.ts +30 -0
  48. package/esm/control/inject-touch.d.ts.map +1 -0
  49. package/esm/control/inject-touch.js +30 -0
  50. package/esm/control/inject-touch.js.map +1 -0
  51. package/esm/control/rotate-device.d.ts +7 -0
  52. package/esm/control/rotate-device.d.ts.map +1 -0
  53. package/esm/control/rotate-device.js +5 -0
  54. package/esm/control/rotate-device.js.map +1 -0
  55. package/esm/control/serializer.d.ts +23 -0
  56. package/esm/control/serializer.d.ts.map +1 -0
  57. package/esm/control/serializer.js +73 -0
  58. package/esm/control/serializer.js.map +1 -0
  59. package/esm/control/set-screen-power-mode.d.ts +12 -0
  60. package/esm/control/set-screen-power-mode.d.ts.map +1 -0
  61. package/esm/control/set-screen-power-mode.js +12 -0
  62. package/esm/control/set-screen-power-mode.js.map +1 -0
  63. package/esm/control/type.d.ts +15 -0
  64. package/esm/control/type.d.ts.map +1 -0
  65. package/esm/control/type.js +19 -0
  66. package/esm/control/type.js.map +1 -0
  67. package/esm/decoder/index.d.ts +27 -3
  68. package/esm/decoder/index.d.ts.map +1 -1
  69. package/esm/decoder/index.js +1 -3
  70. package/esm/decoder/index.js.map +1 -1
  71. package/esm/decoder/tinyh264/index.d.ts +5 -5
  72. package/esm/decoder/tinyh264/index.d.ts.map +1 -1
  73. package/esm/decoder/tinyh264/index.js +4 -4
  74. package/esm/decoder/tinyh264/index.js.map +1 -1
  75. package/esm/decoder/tinyh264/worker.js.map +1 -1
  76. package/esm/decoder/tinyh264/wrapper.d.ts.map +1 -1
  77. package/esm/decoder/tinyh264/wrapper.js +14 -8
  78. package/esm/decoder/tinyh264/wrapper.js.map +1 -1
  79. package/esm/decoder/types.d.ts +1 -27
  80. package/esm/decoder/types.d.ts.map +1 -1
  81. package/esm/decoder/web-codecs/index.d.ts +4 -4
  82. package/esm/decoder/web-codecs/index.d.ts.map +1 -1
  83. package/esm/decoder/web-codecs/index.js +1 -1
  84. package/esm/decoder/web-codecs/index.js.map +1 -1
  85. package/esm/device-message/clipboard.d.ts +10 -0
  86. package/esm/device-message/clipboard.d.ts.map +1 -0
  87. package/esm/device-message/clipboard.js +7 -0
  88. package/esm/device-message/clipboard.js.map +1 -0
  89. package/esm/device-message/index.d.ts +4 -0
  90. package/esm/device-message/index.d.ts.map +1 -0
  91. package/esm/device-message/index.js +4 -0
  92. package/esm/device-message/index.js.map +1 -0
  93. package/esm/device-message/stream.d.ts +7 -0
  94. package/esm/device-message/stream.d.ts.map +1 -0
  95. package/esm/device-message/stream.js +16 -0
  96. package/esm/device-message/stream.js.map +1 -0
  97. package/esm/device-message/type.d.ts +5 -0
  98. package/esm/device-message/type.d.ts.map +1 -0
  99. package/esm/device-message/type.js +7 -0
  100. package/esm/device-message/type.js.map +1 -0
  101. package/esm/index.d.ts +3 -6
  102. package/esm/index.d.ts.map +1 -1
  103. package/esm/index.js +3 -6
  104. package/esm/index.js.map +1 -1
  105. package/esm/options/1_16/codec-options.d.ts +19 -0
  106. package/esm/options/1_16/codec-options.d.ts.map +1 -0
  107. package/esm/options/1_16/codec-options.js +27 -0
  108. package/esm/options/1_16/codec-options.js.map +1 -0
  109. package/esm/options/1_16/index.d.ts +3 -107
  110. package/esm/options/1_16/index.d.ts.map +1 -1
  111. package/esm/options/1_16/index.js +3 -216
  112. package/esm/options/1_16/index.js.map +1 -1
  113. package/esm/options/1_16/options.d.ts +97 -0
  114. package/esm/options/1_16/options.d.ts.map +1 -0
  115. package/esm/options/1_16/options.js +188 -0
  116. package/esm/options/1_16/options.js.map +1 -0
  117. package/esm/options/1_18.d.ts +8 -8
  118. package/esm/options/1_18.d.ts.map +1 -1
  119. package/esm/options/1_18.js +6 -6
  120. package/esm/options/1_18.js.map +1 -1
  121. package/esm/options/1_21.d.ts +1 -1
  122. package/esm/options/1_21.d.ts.map +1 -1
  123. package/esm/options/1_21.js +1 -1
  124. package/esm/options/1_21.js.map +1 -1
  125. package/esm/options/1_22.d.ts +5 -8
  126. package/esm/options/1_22.d.ts.map +1 -1
  127. package/esm/options/1_22.js +4 -17
  128. package/esm/options/1_22.js.map +1 -1
  129. package/esm/options/1_23.d.ts +4 -4
  130. package/esm/options/1_23.d.ts.map +1 -1
  131. package/esm/options/1_23.js +1 -1
  132. package/esm/options/1_23.js.map +1 -1
  133. package/esm/options/1_24.d.ts +1 -1
  134. package/esm/options/1_24.d.ts.map +1 -1
  135. package/esm/options/1_24.js.map +1 -1
  136. package/esm/options/index.d.ts +1 -1
  137. package/esm/options/index.d.ts.map +1 -1
  138. package/esm/options/index.js +1 -1
  139. package/esm/options/index.js.map +1 -1
  140. package/esm/options/types.d.ts +45 -0
  141. package/esm/options/types.d.ts.map +1 -0
  142. package/esm/options/{common.js → types.js} +1 -1
  143. package/esm/options/types.js.map +1 -0
  144. package/package.json +24 -24
  145. package/scrcpy.LICENSE +203 -203
  146. package/scripts/fetch-server.cjs +28 -28
  147. package/src/adb/client.ts +292 -0
  148. package/src/{connection.ts → adb/connection.ts} +145 -148
  149. package/src/adb/index.ts +3 -0
  150. package/src/adb/options/1_16.ts +23 -0
  151. package/src/adb/options/1_22.ts +20 -0
  152. package/src/adb/options/index.ts +3 -0
  153. package/src/adb/options/types.ts +55 -0
  154. package/src/codec.ts +35 -35
  155. package/src/control/index.ts +7 -0
  156. package/src/control/inject-keycode.ts +59 -0
  157. package/src/control/inject-text.ts +12 -0
  158. package/src/control/inject-touch.ts +34 -0
  159. package/src/control/rotate-device.ts +10 -0
  160. package/src/control/serializer.ts +86 -0
  161. package/src/control/set-screen-power-mode.ts +17 -0
  162. package/src/control/type.ts +17 -0
  163. package/src/device-message/clipboard.ts +11 -0
  164. package/src/device-message/index.ts +3 -0
  165. package/src/device-message/stream.ts +19 -0
  166. package/src/device-message/type.ts +5 -0
  167. package/src/index.ts +5 -8
  168. package/src/options/1_16/codec-options.ts +48 -0
  169. package/src/options/1_16/index.ts +3 -330
  170. package/src/options/1_16/options.ts +294 -0
  171. package/src/options/1_16/sps.ts +300 -300
  172. package/src/options/1_18.ts +63 -61
  173. package/src/options/1_21.ts +44 -34
  174. package/src/options/1_22.ts +67 -78
  175. package/src/options/1_23.ts +7 -5
  176. package/src/options/1_24.ts +3 -2
  177. package/src/options/index.ts +7 -7
  178. package/src/options/{common.ts → types.ts} +85 -66
  179. package/tsconfig.build.json +3 -0
  180. package/tsconfig.build.tsbuildinfo +1 -0
  181. package/tsconfig.test.tsbuildinfo +1 -0
  182. package/esm/client.d.ts +0 -48
  183. package/esm/client.d.ts.map +0 -1
  184. package/esm/client.js +0 -341
  185. package/esm/client.js.map +0 -1
  186. package/esm/connection.d.ts +0 -37
  187. package/esm/connection.d.ts.map +0 -1
  188. package/esm/connection.js.map +0 -1
  189. package/esm/message.d.ts +0 -97
  190. package/esm/message.d.ts.map +0 -1
  191. package/esm/message.js +0 -97
  192. package/esm/message.js.map +0 -1
  193. package/esm/options/common.d.ts +0 -34
  194. package/esm/options/common.d.ts.map +0 -1
  195. package/esm/options/common.js.map +0 -1
  196. package/esm/push-server.d.ts +0 -6
  197. package/esm/push-server.d.ts.map +0 -1
  198. package/esm/push-server.js +0 -16
  199. package/esm/push-server.js.map +0 -1
  200. package/esm/utils.d.ts +0 -2
  201. package/esm/utils.d.ts.map +0 -1
  202. package/esm/utils.js +0 -6
  203. package/esm/utils.js.map +0 -1
  204. package/src/client.ts +0 -435
  205. package/src/decoder/index.ts +0 -3
  206. package/src/decoder/tinyh264/index.ts +0 -112
  207. package/src/decoder/tinyh264/types.d.ts +0 -137
  208. package/src/decoder/tinyh264/worker.ts +0 -2
  209. package/src/decoder/tinyh264/wrapper.ts +0 -89
  210. package/src/decoder/types.ts +0 -35
  211. package/src/decoder/web-codecs/index.ts +0 -99
  212. package/src/message.ts +0 -112
  213. package/src/push-server.ts +0 -24
  214. package/src/utils.ts +0 -5
@@ -0,0 +1,55 @@
1
+ import type { Adb } from '@yume-chan/adb';
2
+ import type { TransformStream } from '@yume-chan/stream-extra';
3
+
4
+ import type { ScrcpyControlMessageType } from '../../control/index.js';
5
+ import type { ScrcpyBackOrScreenOnControlMessage1_18, ScrcpyInjectScrollControlMessage1_22, ScrcpyOptions, ScrcpyVideoStreamPacket } from '../../options/index.js';
6
+ import type { AdbScrcpyConnection } from '../connection.js';
7
+
8
+ export interface AdbScrcpyOptions<T> extends ScrcpyOptions<T> {
9
+ createConnection(adb: Adb): AdbScrcpyConnection;
10
+ }
11
+
12
+ export abstract class AdbScrcpyOptionsBase<T> implements ScrcpyOptions<T> {
13
+ private raw: ScrcpyOptions<T>;
14
+
15
+ public get value(): Partial<T> { return this.raw.value; }
16
+ public set value(value: Partial<T>) { this.raw.value = value; }
17
+
18
+ public constructor(raw: ScrcpyOptions<T>) {
19
+ this.raw = raw;
20
+ }
21
+
22
+ public getDefaultValue(): T {
23
+ return this.raw.getDefaultValue();
24
+ }
25
+
26
+ public formatServerArguments(): string[] {
27
+ return this.raw.formatServerArguments();
28
+ }
29
+
30
+ public getOutputEncoderNameRegex(): RegExp {
31
+ return this.raw.getOutputEncoderNameRegex();
32
+ }
33
+
34
+ public createVideoStreamTransformer(): TransformStream<Uint8Array, ScrcpyVideoStreamPacket> {
35
+ return this.raw.createVideoStreamTransformer();
36
+ }
37
+
38
+ public getControlMessageTypes(): ScrcpyControlMessageType[] {
39
+ return this.raw.getControlMessageTypes();
40
+ }
41
+
42
+ public serializeBackOrScreenOnControlMessage(
43
+ message: ScrcpyBackOrScreenOnControlMessage1_18,
44
+ ): Uint8Array | undefined {
45
+ return this.raw.serializeBackOrScreenOnControlMessage(message);
46
+ }
47
+
48
+ public serializeInjectScrollControlMessage(
49
+ message: ScrcpyInjectScrollControlMessage1_22,
50
+ ): Uint8Array {
51
+ return this.raw.serializeInjectScrollControlMessage(message);
52
+ }
53
+
54
+ public abstract createConnection(adb: Adb): AdbScrcpyConnection;
55
+ }
package/src/codec.ts CHANGED
@@ -1,35 +1,35 @@
1
- // From https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel
2
- export enum AndroidCodecProfile {
3
- Baseline = 0x01,
4
- Main = 0x02,
5
- Extended = 0x04,
6
- High = 0x08,
7
- High10 = 0x10,
8
- High422 = 0x20,
9
- High444 = 0x40,
10
- ConstrainedBaseline = 0x10000,
11
- ConstrainedHigh = 0x80000,
12
- }
13
-
14
- export enum AndroidCodecLevel {
15
- Level1 = 0x01,
16
- Level1b = 0x02,
17
- Level11 = 0x04,
18
- Level12 = 0x08,
19
- Level13 = 0x10,
20
- Level2 = 0x20,
21
- Level21 = 0x40,
22
- Level22 = 0x80,
23
- Level3 = 0x100,
24
- Level31 = 0x200,
25
- Level32 = 0x400,
26
- Level4 = 0x800,
27
- Level41 = 0x1000,
28
- Level42 = 0x2000,
29
- Level5 = 0x4000,
30
- Level51 = 0x8000,
31
- Level52 = 0x10000,
32
- Level6 = 0x20000,
33
- Level61 = 0x40000,
34
- Level62 = 0x80000,
35
- }
1
+ // From https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel
2
+ export enum AndroidCodecProfile {
3
+ Baseline = 0x01,
4
+ Main = 0x02,
5
+ Extended = 0x04,
6
+ High = 0x08,
7
+ High10 = 0x10,
8
+ High422 = 0x20,
9
+ High444 = 0x40,
10
+ ConstrainedBaseline = 0x10000,
11
+ ConstrainedHigh = 0x80000,
12
+ }
13
+
14
+ export enum AndroidCodecLevel {
15
+ Level1 = 0x01,
16
+ Level1b = 0x02,
17
+ Level11 = 0x04,
18
+ Level12 = 0x08,
19
+ Level13 = 0x10,
20
+ Level2 = 0x20,
21
+ Level21 = 0x40,
22
+ Level22 = 0x80,
23
+ Level3 = 0x100,
24
+ Level31 = 0x200,
25
+ Level32 = 0x400,
26
+ Level4 = 0x800,
27
+ Level41 = 0x1000,
28
+ Level42 = 0x2000,
29
+ Level5 = 0x4000,
30
+ Level51 = 0x8000,
31
+ Level52 = 0x10000,
32
+ Level6 = 0x20000,
33
+ Level61 = 0x40000,
34
+ Level62 = 0x80000,
35
+ }
@@ -0,0 +1,7 @@
1
+ export * from './inject-keycode.js';
2
+ export * from './inject-text.js';
3
+ export * from './inject-touch.js';
4
+ export * from './rotate-device.js';
5
+ export * from './serializer.js';
6
+ export * from './set-screen-power-mode.js';
7
+ export * from './type.js';
@@ -0,0 +1,59 @@
1
+ import Struct, { placeholder } from '@yume-chan/struct';
2
+
3
+ import { ScrcpyControlMessageType } from './type.js';
4
+
5
+ export enum AndroidKeyEventAction {
6
+ Down = 0,
7
+ Up = 1,
8
+ }
9
+
10
+ // https://github.com/Genymobile/scrcpy/blob/cabb102a04153f9c237b18257d3269a058558c63/app/src/android/keycodes.h#L26
11
+ export enum AndroidKeyCode {
12
+ Home = 3,
13
+ Back = 4,
14
+ VolumeUp = 24,
15
+ VolumeDown,
16
+ A = 29,
17
+ B,
18
+ C,
19
+ D,
20
+ E,
21
+ F,
22
+ G,
23
+ H,
24
+ I,
25
+ J,
26
+ K,
27
+ L,
28
+ M,
29
+ N,
30
+ O,
31
+ P,
32
+ Q,
33
+ R,
34
+ S,
35
+ T,
36
+ U,
37
+ V,
38
+ W,
39
+ X,
40
+ Y,
41
+ Z,
42
+ Tab = 61,
43
+ Space,
44
+ Enter = 66,
45
+ Delete,
46
+ VolumeMute = 164,
47
+ AppSwitch = 187,
48
+ }
49
+
50
+ export const ScrcpyInjectKeyCodeControlMessage =
51
+ new Struct()
52
+ .uint8('type', ScrcpyControlMessageType.InjectKeyCode as const)
53
+ .uint8('action', placeholder<AndroidKeyEventAction>())
54
+ .uint32('keyCode')
55
+ .uint32('repeat')
56
+ .uint32('metaState');
57
+
58
+ export type ScrcpyInjectKeyCodeControlMessage =
59
+ typeof ScrcpyInjectKeyCodeControlMessage['TInit'];
@@ -0,0 +1,12 @@
1
+ import Struct from '@yume-chan/struct';
2
+
3
+ import { ScrcpyControlMessageType } from './type.js';
4
+
5
+ export const ScrcpyInjectTextControlMessage =
6
+ new Struct()
7
+ .uint8('type', ScrcpyControlMessageType.InjectText as const)
8
+ .uint32('length')
9
+ .string('text', { lengthField: 'length' });
10
+
11
+ export type ScrcpyInjectTextControlMessage =
12
+ typeof ScrcpyInjectTextControlMessage['TInit'];
@@ -0,0 +1,34 @@
1
+ import Struct, { placeholder } from '@yume-chan/struct';
2
+ import { ScrcpyControlMessageType } from './type.js';
3
+
4
+ // https://developer.android.com/reference/android/view/MotionEvent#constants_1
5
+ export enum AndroidMotionEventAction {
6
+ Down,
7
+ Up,
8
+ Move,
9
+ Cancel,
10
+ Outside,
11
+ PointerDown,
12
+ PointerUp,
13
+ HoverMove,
14
+ Scroll,
15
+ HoverEnter,
16
+ HoverExit,
17
+ ButtonPress,
18
+ ButtonRelease,
19
+ }
20
+
21
+ export const ScrcpyInjectTouchControlMessage =
22
+ new Struct()
23
+ .uint8('type', ScrcpyControlMessageType.InjectTouch as const)
24
+ .uint8('action', placeholder<AndroidMotionEventAction>())
25
+ .uint64('pointerId')
26
+ .uint32('pointerX')
27
+ .uint32('pointerY')
28
+ .uint16('screenWidth')
29
+ .uint16('screenHeight')
30
+ .uint16('pressure')
31
+ .uint32('buttons');
32
+
33
+ export type ScrcpyInjectTouchControlMessage =
34
+ typeof ScrcpyInjectTouchControlMessage['TInit'];
@@ -0,0 +1,10 @@
1
+ import Struct from '@yume-chan/struct';
2
+
3
+ import { ScrcpyControlMessageType } from './type.js';
4
+
5
+ export const ScrcpyRotateDeviceControlMessage =
6
+ new Struct()
7
+ .uint8('type', ScrcpyControlMessageType.RotateDevice as const)
8
+
9
+ export type ScrcpyRotateDeviceControlMessage =
10
+ typeof ScrcpyRotateDeviceControlMessage['TInit'];
@@ -0,0 +1,86 @@
1
+ import type { WritableStream, WritableStreamDefaultWriter } from '@yume-chan/stream-extra';
2
+
3
+ import type { ScrcpyInjectScrollControlMessage1_22, ScrcpyOptions } from '../options/index.js';
4
+ import { AndroidKeyEventAction, ScrcpyInjectKeyCodeControlMessage } from './inject-keycode.js';
5
+ import { ScrcpyInjectTextControlMessage } from './inject-text.js';
6
+ import { ScrcpyInjectTouchControlMessage } from './inject-touch.js';
7
+ import { ScrcpyRotateDeviceControlMessage } from './rotate-device.js';
8
+ import { AndroidScreenPowerMode, ScrcpySetScreenPowerModeControlMessage } from './set-screen-power-mode.js';
9
+ import { ScrcpyControlMessageType } from './type.js';
10
+
11
+ export class ScrcpyControlMessageSerializer {
12
+ private options: ScrcpyOptions<any>;
13
+ /** Control message type values for current version of server */
14
+ private types: ScrcpyControlMessageType[];
15
+ private writer: WritableStreamDefaultWriter<Uint8Array>;
16
+
17
+ public constructor(stream: WritableStream<Uint8Array>, options: ScrcpyOptions<any>) {
18
+ this.options = options;
19
+ this.types = options.getControlMessageTypes();
20
+ this.writer = stream.getWriter();
21
+ }
22
+
23
+ public getTypeValue(type: ScrcpyControlMessageType): number {
24
+ const value = this.types.indexOf(type);
25
+ if (value === -1) {
26
+ throw new Error('Not supported');
27
+ }
28
+ return value;
29
+ }
30
+
31
+ public injectKeyCode(message: Omit<ScrcpyInjectKeyCodeControlMessage, 'type'>) {
32
+ return this.writer.write(ScrcpyInjectKeyCodeControlMessage.serialize({
33
+ ...message,
34
+ type: this.getTypeValue(ScrcpyControlMessageType.InjectKeyCode),
35
+ }));
36
+ }
37
+
38
+ public injectText(text: string) {
39
+ return this.writer.write(ScrcpyInjectTextControlMessage.serialize({
40
+ text,
41
+ type: this.getTypeValue(ScrcpyControlMessageType.InjectText),
42
+ }));
43
+ }
44
+
45
+ public injectTouch(message: Omit<ScrcpyInjectTouchControlMessage, 'type'>) {
46
+ return this.writer.write(ScrcpyInjectTouchControlMessage.serialize({
47
+ ...message,
48
+ type: this.getTypeValue(ScrcpyControlMessageType.InjectTouch),
49
+ }));
50
+ }
51
+
52
+ public injectScroll(message: Omit<ScrcpyInjectScrollControlMessage1_22, 'type'>) {
53
+ return this.writer.write(this.options.serializeInjectScrollControlMessage({
54
+ ...message,
55
+ type: this.getTypeValue(ScrcpyControlMessageType.InjectScroll),
56
+ }));
57
+ }
58
+
59
+ public async backOrScreenOn(action: AndroidKeyEventAction) {
60
+ const buffer = this.options.serializeBackOrScreenOnControlMessage({
61
+ action,
62
+ type: this.getTypeValue(ScrcpyControlMessageType.BackOrScreenOn),
63
+ });
64
+
65
+ if (buffer) {
66
+ return await this.writer.write(buffer);
67
+ }
68
+ }
69
+
70
+ public setScreenPowerMode(mode: AndroidScreenPowerMode) {
71
+ return this.writer.write(ScrcpySetScreenPowerModeControlMessage.serialize({
72
+ mode,
73
+ type: this.getTypeValue(ScrcpyControlMessageType.SetScreenPowerMode),
74
+ }));
75
+ }
76
+
77
+ public rotateDevice() {
78
+ return this.writer.write(ScrcpyRotateDeviceControlMessage.serialize({
79
+ type: this.getTypeValue(ScrcpyControlMessageType.RotateDevice),
80
+ }));
81
+ }
82
+
83
+ public close() {
84
+ return this.writer.close();
85
+ }
86
+ };
@@ -0,0 +1,17 @@
1
+ import Struct, { placeholder } from '@yume-chan/struct';
2
+
3
+ import { ScrcpyControlMessageType } from './type.js';
4
+
5
+ // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/SurfaceControl.java;l=659;drc=20303e05bf73796124ab70a279cf849b61b97905
6
+ export enum AndroidScreenPowerMode {
7
+ Off = 0,
8
+ Normal = 2
9
+ }
10
+
11
+ export const ScrcpySetScreenPowerModeControlMessage =
12
+ new Struct()
13
+ .uint8('type', ScrcpyControlMessageType.SetScreenPowerMode as const)
14
+ .uint8('mode', placeholder<AndroidScreenPowerMode>());
15
+
16
+ export type ScrcpySetScreenPowerModeControlMessage =
17
+ typeof ScrcpySetScreenPowerModeControlMessage['TInit'];
@@ -0,0 +1,17 @@
1
+ // https://github.com/Genymobile/scrcpy/blob/fa5b2a29e983a46b49531def9cf3d80c40c3de37/app/src/control_msg.h#L23
2
+ // For their message bodies, see https://github.com/Genymobile/scrcpy/blob/5c62f3419d252d10cd8c9cbb7c918b358b81f2d0/app/src/control_msg.c#L92
3
+ // Their IDs change between versions, so always use `options.getControlMessageTypes()`
4
+ export enum ScrcpyControlMessageType {
5
+ InjectKeyCode,
6
+ InjectText,
7
+ InjectTouch,
8
+ InjectScroll,
9
+ BackOrScreenOn,
10
+ ExpandNotificationPanel,
11
+ ExpandSettingPanel,
12
+ CollapseNotificationPanel,
13
+ GetClipboard,
14
+ SetClipboard,
15
+ SetScreenPowerMode,
16
+ RotateDevice,
17
+ }
@@ -0,0 +1,11 @@
1
+ import Struct from '@yume-chan/struct';
2
+ import { ScrcpyDeviceMessageType } from './type.js';
3
+
4
+ export const ScrcpyClipboardDeviceMessage =
5
+ new Struct()
6
+ .uint32('length')
7
+ .string('content', { lengthField: 'length' })
8
+ .extra({ type: ScrcpyDeviceMessageType.Clipboard as const });
9
+
10
+ export type ScrcpyClipboardDeviceMessage =
11
+ typeof ScrcpyClipboardDeviceMessage['TDeserializeResult'];
@@ -0,0 +1,3 @@
1
+ export * from './clipboard.js';
2
+ export * from './stream.js';
3
+ export * from './type.js';
@@ -0,0 +1,19 @@
1
+ import { BufferedTransformStream } from '@yume-chan/stream-extra';
2
+ import { ScrcpyClipboardDeviceMessage } from './clipboard.js';
3
+
4
+ export type ScrcpyDeviceMessage =
5
+ | ScrcpyClipboardDeviceMessage;
6
+
7
+ export class ScrcpyDeviceMessageDeserializeStream extends BufferedTransformStream<ScrcpyDeviceMessage> {
8
+ constructor() {
9
+ super(async (stream) => {
10
+ const type = await stream.read(1);
11
+ switch (type[0]) {
12
+ case 0:
13
+ return await ScrcpyClipboardDeviceMessage.deserialize(stream);
14
+ default:
15
+ throw new Error('unknown control message type');
16
+ }
17
+ })
18
+ }
19
+ }
@@ -0,0 +1,5 @@
1
+ // https://github.com/Genymobile/scrcpy/blob/41abe021e2a73efd4899b0efcd0b9eef9ec68c9b/server/src/main/java/com/genymobile/scrcpy/DeviceMessage.java#L5
2
+ export enum ScrcpyDeviceMessageType {
3
+ Clipboard,
4
+ AckClipboard,
5
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,5 @@
1
- export * from './client.js';
2
- export * from './codec.js';
3
- export * from './connection.js';
4
- export * from './decoder/index.js';
5
- export * from './message.js';
6
- export * from './options/index.js';
7
- export * from './push-server.js';
8
- export * from './utils.js';
1
+ export * from './adb/index.js';
2
+ export * from './codec.js';
3
+ export * from './control/index.js';
4
+ export * from './device-message/index.js';
5
+ export * from './options/index.js';
@@ -0,0 +1,48 @@
1
+ import type { AndroidCodecLevel, AndroidCodecProfile } from '../../codec.js';
2
+ import type { ScrcpyOptionValue } from '../types.js';
3
+
4
+ /**
5
+ * If the option you need is not in this type,
6
+ * please file an issue on GitHub.
7
+ */
8
+ export interface CodecOptionsInit {
9
+ profile: AndroidCodecProfile;
10
+ level: AndroidCodecLevel;
11
+
12
+ iFrameInterval: number;
13
+ repeatPreviousFrameAfter: number;
14
+ maxPtsGapToEncoder: number;
15
+ }
16
+
17
+ function toDashCase(input: string) {
18
+ return input.replace(/([A-Z])/g, '-$1').toLowerCase();
19
+ }
20
+
21
+ const CODEC_OPTION_TYPES: Partial<Record<keyof CodecOptionsInit, 'long' | 'float' | 'string'>> = {
22
+ repeatPreviousFrameAfter: 'long',
23
+ maxPtsGapToEncoder: 'long',
24
+ };
25
+
26
+ export class CodecOptions implements ScrcpyOptionValue {
27
+ public value: Partial<CodecOptionsInit>;
28
+
29
+ public constructor(value: Partial<CodecOptionsInit>) {
30
+ this.value = value;
31
+ }
32
+
33
+ public toOptionValue(): string | undefined {
34
+ const entries = Object.entries(this.value)
35
+ .filter(([key, value]) => value !== undefined);
36
+
37
+ if (entries.length === 0) {
38
+ return undefined;
39
+ }
40
+
41
+ return entries
42
+ .map(([key, value]) => {
43
+ const type = CODEC_OPTION_TYPES[key as keyof CodecOptionsInit];
44
+ return `${toDashCase(key)}${type ? `:${type}` : ''}=${value}`;
45
+ })
46
+ .join(',');
47
+ }
48
+ }