mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-03 01:39:21 +02:00
feat(scrcpy): support server version 3.2
This commit is contained in:
parent
ab23e4baa3
commit
418971cdbd
12 changed files with 296 additions and 25 deletions
50
libraries/adb-scrcpy/src/3_2.ts
Normal file
50
libraries/adb-scrcpy/src/3_2.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import type { Adb, AdbNoneProtocolSpawner } from "@yume-chan/adb";
|
||||||
|
import type { ScrcpyDisplay, ScrcpyEncoder } from "@yume-chan/scrcpy";
|
||||||
|
import { ScrcpyOptions3_2 } from "@yume-chan/scrcpy";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createConnection,
|
||||||
|
getDisplays,
|
||||||
|
getEncoders,
|
||||||
|
} from "./2_1/impl/index.js";
|
||||||
|
import type { AdbScrcpyClientOptions } from "./client-options.js";
|
||||||
|
import type { AdbScrcpyConnection } from "./connection.js";
|
||||||
|
import type { AdbScrcpyOptions, AdbScrcpyOptionsGetEncoders } from "./types.js";
|
||||||
|
|
||||||
|
export class AdbScrcpyOptions3_2<TVideo extends boolean>
|
||||||
|
extends ScrcpyOptions3_2<TVideo>
|
||||||
|
implements
|
||||||
|
AdbScrcpyOptions<ScrcpyOptions3_2.Init<TVideo>>,
|
||||||
|
AdbScrcpyOptionsGetEncoders
|
||||||
|
{
|
||||||
|
readonly version: string;
|
||||||
|
|
||||||
|
readonly spawner: AdbNoneProtocolSpawner | undefined;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
init: ScrcpyOptions3_2.Init<TVideo>,
|
||||||
|
clientOptions?: AdbScrcpyClientOptions,
|
||||||
|
) {
|
||||||
|
super(init);
|
||||||
|
|
||||||
|
this.version = clientOptions?.version ?? "3.2";
|
||||||
|
this.spawner = clientOptions?.spawner;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEncoders(adb: Adb, path: string): Promise<ScrcpyEncoder[]> {
|
||||||
|
return getEncoders(adb, path, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisplays(adb: Adb, path: string): Promise<ScrcpyDisplay[]> {
|
||||||
|
return getDisplays(adb, path, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
createConnection(adb: Adb): AdbScrcpyConnection {
|
||||||
|
return createConnection(adb, this.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace AdbScrcpyOptions3_2 {
|
||||||
|
export type Init<TVideo extends boolean = boolean> =
|
||||||
|
ScrcpyOptions3_2.Init<TVideo>;
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ export * from "./3_0.js";
|
||||||
export * from "./3_0_1.js";
|
export * from "./3_0_1.js";
|
||||||
export * from "./3_0_2.js";
|
export * from "./3_0_2.js";
|
||||||
export * from "./3_1.js";
|
export * from "./3_1.js";
|
||||||
|
export * from "./3_2.js";
|
||||||
export * from "./client-options.js";
|
export * from "./client-options.js";
|
||||||
export * from "./client.js";
|
export * from "./client.js";
|
||||||
export * from "./connection.js";
|
export * from "./connection.js";
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { AdbScrcpyOptions3_1 } from "./3_1.js";
|
import { AdbScrcpyOptions3_2 } from "./3_2.js";
|
||||||
import type { AdbScrcpyClientOptions } from "./client-options.js";
|
import type { AdbScrcpyClientOptions } from "./client-options.js";
|
||||||
|
|
||||||
export class AdbScrcpyOptionsLatest<
|
export class AdbScrcpyOptionsLatest<
|
||||||
TVideo extends boolean,
|
TVideo extends boolean,
|
||||||
> extends AdbScrcpyOptions3_1<TVideo> {
|
> extends AdbScrcpyOptions3_2<TVideo> {
|
||||||
constructor(
|
constructor(
|
||||||
init: AdbScrcpyOptions3_1.Init<TVideo>,
|
init: AdbScrcpyOptions3_2.Init<TVideo>,
|
||||||
clientOptions?: AdbScrcpyClientOptions,
|
clientOptions?: AdbScrcpyClientOptions,
|
||||||
) {
|
) {
|
||||||
super(init, clientOptions);
|
super(init, clientOptions);
|
||||||
|
@ -14,5 +14,5 @@ export class AdbScrcpyOptionsLatest<
|
||||||
|
|
||||||
export namespace AdbScrcpyOptionsLatest {
|
export namespace AdbScrcpyOptionsLatest {
|
||||||
export type Init<TVideo extends boolean = boolean> =
|
export type Init<TVideo extends boolean = boolean> =
|
||||||
AdbScrcpyOptions3_1.Init<TVideo>;
|
AdbScrcpyOptions3_2.Init<TVideo>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import type { Init } from "./init.js";
|
import type { Init } from "./init.js";
|
||||||
import { VideoOrientation } from "./init.js";
|
import { VideoOrientation } from "./init.js";
|
||||||
|
|
||||||
export const Defaults = /* #__PURE__ */ (() =>
|
export const Defaults = {
|
||||||
({
|
logLevel: "debug",
|
||||||
logLevel: "debug",
|
maxSize: 0,
|
||||||
maxSize: 0,
|
bitRate: 8_000_000,
|
||||||
bitRate: 8_000_000,
|
maxFps: 0,
|
||||||
maxFps: 0,
|
lockVideoOrientation: VideoOrientation.Unlocked,
|
||||||
lockVideoOrientation: VideoOrientation.Unlocked,
|
tunnelForward: false,
|
||||||
tunnelForward: false,
|
crop: undefined,
|
||||||
crop: undefined,
|
sendFrameMeta: true,
|
||||||
sendFrameMeta: true,
|
control: true,
|
||||||
control: true,
|
displayId: 0,
|
||||||
displayId: 0,
|
showTouches: false,
|
||||||
showTouches: false,
|
stayAwake: false,
|
||||||
stayAwake: false,
|
codecOptions: undefined,
|
||||||
codecOptions: undefined,
|
} as const satisfies Required<Init>;
|
||||||
}) as const satisfies Required<Init>)();
|
|
||||||
|
|
8
libraries/scrcpy/src/3_2/impl/defaults.ts
Normal file
8
libraries/scrcpy/src/3_2/impl/defaults.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import type { Init } from "./init.js";
|
||||||
|
import { PrevImpl } from "./prev.js";
|
||||||
|
|
||||||
|
export const Defaults = /* #__PURE__ */ (() =>
|
||||||
|
({
|
||||||
|
...PrevImpl.Defaults,
|
||||||
|
displayImePolicy: undefined,
|
||||||
|
}) as const satisfies Required<Init<true>>)();
|
3
libraries/scrcpy/src/3_2/impl/index.ts
Normal file
3
libraries/scrcpy/src/3_2/impl/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export * from "../../3_1/impl/index.js";
|
||||||
|
export { Defaults } from "./defaults.js";
|
||||||
|
export type { Init } from "./init.js";
|
17
libraries/scrcpy/src/3_2/impl/init.ts
Normal file
17
libraries/scrcpy/src/3_2/impl/init.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type { PrevImpl } from "./prev.js";
|
||||||
|
|
||||||
|
export interface Init<TVideo extends boolean>
|
||||||
|
extends Omit<PrevImpl.Init<TVideo>, "audioSource"> {
|
||||||
|
audioSource?:
|
||||||
|
| PrevImpl.Init<TVideo>["audioSource"]
|
||||||
|
| "mic-unprocessed"
|
||||||
|
| "mic-camcorder"
|
||||||
|
| "mic-voice-recognition"
|
||||||
|
| "mic-voice-communication"
|
||||||
|
| "voice-call"
|
||||||
|
| "voice-call-uplink"
|
||||||
|
| "voice-call-downlink"
|
||||||
|
| "voice-performance";
|
||||||
|
|
||||||
|
displayImePolicy?: "local" | "fallback" | "hide" | undefined;
|
||||||
|
}
|
1
libraries/scrcpy/src/3_2/impl/prev.ts
Normal file
1
libraries/scrcpy/src/3_2/impl/prev.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * as PrevImpl from "../../3_1/impl/index.js";
|
1
libraries/scrcpy/src/3_2/index.ts
Normal file
1
libraries/scrcpy/src/3_2/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from "./options.js";
|
190
libraries/scrcpy/src/3_2/options.ts
Normal file
190
libraries/scrcpy/src/3_2/options.ts
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
import type { MaybePromiseLike } from "@yume-chan/async";
|
||||||
|
import type { ReadableStream, TransformStream } from "@yume-chan/stream-extra";
|
||||||
|
import type { AsyncExactReadable, ExactReadable } from "@yume-chan/struct";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ScrcpyAudioStreamMetadata,
|
||||||
|
ScrcpyControlMessageType,
|
||||||
|
ScrcpyDisplay,
|
||||||
|
ScrcpyEncoder,
|
||||||
|
ScrcpyMediaStreamPacket,
|
||||||
|
ScrcpyOptions,
|
||||||
|
ScrcpyOptionsListEncoders,
|
||||||
|
ScrcpyScrollController,
|
||||||
|
ScrcpyVideoStream,
|
||||||
|
} from "../base/index.js";
|
||||||
|
import type {
|
||||||
|
ScrcpyBackOrScreenOnControlMessage,
|
||||||
|
ScrcpyInjectTouchControlMessage,
|
||||||
|
ScrcpySetClipboardControlMessage,
|
||||||
|
ScrcpyUHidCreateControlMessage,
|
||||||
|
ScrcpyUHidOutputDeviceMessage,
|
||||||
|
} from "../latest.js";
|
||||||
|
|
||||||
|
import type { Init } from "./impl/index.js";
|
||||||
|
import {
|
||||||
|
AckClipboardHandler,
|
||||||
|
ClipboardStream,
|
||||||
|
ControlMessageTypes,
|
||||||
|
createMediaStreamTransformer,
|
||||||
|
createScrollController,
|
||||||
|
Defaults,
|
||||||
|
parseAudioStreamMetadata,
|
||||||
|
parseDisplay,
|
||||||
|
parseEncoder,
|
||||||
|
parseVideoStreamMetadata,
|
||||||
|
serialize,
|
||||||
|
serializeBackOrScreenOnControlMessage,
|
||||||
|
serializeInjectTouchControlMessage,
|
||||||
|
serializeUHidCreateControlMessage,
|
||||||
|
setListDisplays,
|
||||||
|
setListEncoders,
|
||||||
|
UHidOutputStream,
|
||||||
|
} from "./impl/index.js";
|
||||||
|
|
||||||
|
export class ScrcpyOptions3_2<TVideo extends boolean>
|
||||||
|
implements ScrcpyOptions<Init<TVideo>>, ScrcpyOptionsListEncoders
|
||||||
|
{
|
||||||
|
static readonly Defaults = Defaults;
|
||||||
|
|
||||||
|
readonly value: Required<Init<TVideo>>;
|
||||||
|
|
||||||
|
get controlMessageTypes(): readonly ScrcpyControlMessageType[] {
|
||||||
|
return ControlMessageTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clipboard: ClipboardStream | undefined;
|
||||||
|
get clipboard(): ReadableStream<string> | undefined {
|
||||||
|
return this.#clipboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackClipboardHandler: AckClipboardHandler | undefined;
|
||||||
|
|
||||||
|
#uHidOutput: UHidOutputStream | undefined;
|
||||||
|
get uHidOutput():
|
||||||
|
| ReadableStream<ScrcpyUHidOutputDeviceMessage>
|
||||||
|
| undefined {
|
||||||
|
return this.#uHidOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(init: Init<TVideo>) {
|
||||||
|
this.value = { ...Defaults, ...init } as never;
|
||||||
|
|
||||||
|
if (this.value.videoSource === "camera") {
|
||||||
|
this.value.control = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.value.audioDup) {
|
||||||
|
this.value.audioSource = "playback";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.value.control) {
|
||||||
|
if (this.value.clipboardAutosync) {
|
||||||
|
this.#clipboard = new ClipboardStream();
|
||||||
|
this.#ackClipboardHandler = new AckClipboardHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#uHidOutput = new UHidOutputStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize(): string[] {
|
||||||
|
return serialize<Init<boolean>>(this.value, Defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
setListDisplays(): void {
|
||||||
|
setListDisplays(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseDisplay(line: string): ScrcpyDisplay | undefined {
|
||||||
|
return parseDisplay(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
setListEncoders() {
|
||||||
|
setListEncoders(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseEncoder(line: string): ScrcpyEncoder | undefined {
|
||||||
|
return parseEncoder(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseVideoStreamMetadata(
|
||||||
|
stream: ReadableStream<Uint8Array>,
|
||||||
|
): MaybePromiseLike<ScrcpyVideoStream> {
|
||||||
|
return parseVideoStreamMetadata(this.value, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseAudioStreamMetadata(
|
||||||
|
stream: ReadableStream<Uint8Array>,
|
||||||
|
): MaybePromiseLike<ScrcpyAudioStreamMetadata> {
|
||||||
|
return parseAudioStreamMetadata(stream, this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
async parseDeviceMessage(
|
||||||
|
id: number,
|
||||||
|
stream: ExactReadable | AsyncExactReadable,
|
||||||
|
): Promise<void> {
|
||||||
|
if (await this.#clipboard?.parse(id, stream)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await this.#ackClipboardHandler?.parse(id, stream)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("Unknown device message");
|
||||||
|
}
|
||||||
|
|
||||||
|
endDeviceMessageStream(e?: unknown): void {
|
||||||
|
if (e) {
|
||||||
|
this.#clipboard?.error(e);
|
||||||
|
this.#ackClipboardHandler?.error(e);
|
||||||
|
} else {
|
||||||
|
this.#clipboard?.close();
|
||||||
|
this.#ackClipboardHandler?.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createMediaStreamTransformer(): TransformStream<
|
||||||
|
Uint8Array,
|
||||||
|
ScrcpyMediaStreamPacket
|
||||||
|
> {
|
||||||
|
return createMediaStreamTransformer(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeInjectTouchControlMessage(
|
||||||
|
message: ScrcpyInjectTouchControlMessage,
|
||||||
|
): Uint8Array {
|
||||||
|
return serializeInjectTouchControlMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeBackOrScreenOnControlMessage(
|
||||||
|
message: ScrcpyBackOrScreenOnControlMessage,
|
||||||
|
): Uint8Array | undefined {
|
||||||
|
return serializeBackOrScreenOnControlMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeSetClipboardControlMessage(
|
||||||
|
message: ScrcpySetClipboardControlMessage,
|
||||||
|
): Uint8Array | [Uint8Array, Promise<void>] {
|
||||||
|
return this.#ackClipboardHandler!.serializeSetClipboardControlMessage(
|
||||||
|
message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createScrollController(): ScrcpyScrollController {
|
||||||
|
return createScrollController();
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeUHidCreateControlMessage(
|
||||||
|
message: ScrcpyUHidCreateControlMessage,
|
||||||
|
): Uint8Array {
|
||||||
|
return serializeUHidCreateControlMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Init_<TVideo extends boolean> = Init<TVideo>;
|
||||||
|
|
||||||
|
export namespace ScrcpyOptions3_2 {
|
||||||
|
export type Init<TVideo extends boolean = boolean> = Init_<TVideo>;
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ export * from "./3_0/index.js";
|
||||||
export * from "./3_0_1.js";
|
export * from "./3_0_1.js";
|
||||||
export * from "./3_0_2.js";
|
export * from "./3_0_2.js";
|
||||||
export * from "./3_1/index.js";
|
export * from "./3_1/index.js";
|
||||||
|
export * from "./3_2/index.js";
|
||||||
export * from "./android/index.js";
|
export * from "./android/index.js";
|
||||||
export * from "./base/index.js";
|
export * from "./base/index.js";
|
||||||
export * from "./codec/index.js";
|
export * from "./codec/index.js";
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { ScrcpyOptions3_1 } from "./3_1/options.js";
|
import { ScrcpyOptions3_2 } from "./3_2/options.js";
|
||||||
|
|
||||||
export class ScrcpyOptionsLatest<
|
export class ScrcpyOptionsLatest<
|
||||||
TVideo extends boolean,
|
TVideo extends boolean,
|
||||||
> extends ScrcpyOptions3_1<TVideo> {
|
> extends ScrcpyOptions3_2<TVideo> {
|
||||||
constructor(init: ScrcpyOptions3_1.Init<TVideo>) {
|
constructor(init: ScrcpyOptions3_2.Init<TVideo>) {
|
||||||
super(init);
|
super(init);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace ScrcpyOptionsLatest {
|
export namespace ScrcpyOptionsLatest {
|
||||||
export type Init<TVideo extends boolean = boolean> =
|
export type Init<TVideo extends boolean = boolean> =
|
||||||
ScrcpyOptions3_1.Init<TVideo>;
|
ScrcpyOptions3_2.Init<TVideo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -28,4 +28,4 @@ export {
|
||||||
SetClipboardControlMessage as ScrcpySetClipboardControlMessage,
|
SetClipboardControlMessage as ScrcpySetClipboardControlMessage,
|
||||||
UHidCreateControlMessage as ScrcpyUHidCreateControlMessage,
|
UHidCreateControlMessage as ScrcpyUHidCreateControlMessage,
|
||||||
UHidOutputDeviceMessage as ScrcpyUHidOutputDeviceMessage,
|
UHidOutputDeviceMessage as ScrcpyUHidOutputDeviceMessage,
|
||||||
} from "./3_1/impl/index.js";
|
} from "./3_2/impl/index.js";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue