Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit dc1a23b8 authored by Simon Chan's avatar Simon Chan
Browse files

feat(demo): save scrcpy settings to device

fixes #384
parent 4cd4d7a3
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import {
    TooltipHost,
} from "@fluentui/react";
import { makeStyles } from "@griffel/react";
import { AdbSyncError } from "@yume-chan/adb";
import { AdbScrcpyClient, AdbScrcpyOptionsLatest } from "@yume-chan/adb-scrcpy";
import {
    DEFAULT_SERVER_PATH,
@@ -26,6 +27,7 @@ import {
    TinyH264Decoder,
} from "@yume-chan/scrcpy-decoder-tinyh264";
import SCRCPY_SERVER_VERSION from "@yume-chan/scrcpy/bin/version";
import { DecodeUtf8Stream, GatherStringStream } from "@yume-chan/stream-extra";
import {
    autorun,
    computed,
@@ -179,6 +181,18 @@ export interface DecoderDefinition {
    Constructor: ScrcpyVideoDecoderConstructor;
}

const DEFAULT_SETTINGS = {
    maxSize: 1080,
    videoBitRate: 4_000_000,
    videoCodec: "h264",
    lockVideoOrientation: ScrcpyVideoOrientation.Unlocked,
    displayId: 0,
    crop: "",
    powerOn: true,
    audio: true,
    audioCodec: "aac",
} as Settings;

export const SETTING_STATE = makeAutoObservable(
    {
        displays: [] as ScrcpyDisplay[],
@@ -191,17 +205,7 @@ export const SETTING_STATE = makeAutoObservable(
            },
        ] as DecoderDefinition[],

        settings: {
            maxSize: 1080,
            videoBitRate: 4_000_000,
            videoCodec: "h264",
            lockVideoOrientation: ScrcpyVideoOrientation.Unlocked,
            displayId: 0,
            crop: "",
            powerOn: true,
            audio: true,
            audioCodec: "aac",
        } as Settings,
        settings: DEFAULT_SETTINGS,

        clientSettings: {} as ClientSettings,
    },
@@ -212,8 +216,35 @@ export const SETTING_STATE = makeAutoObservable(
    }
);

export const SCRCPY_SETTINGS_FILENAME = "/data/local/tmp/.tango.json";

autorun(() => {
    if (GLOBAL_STATE.adb) {
        (async () => {
            const sync = await GLOBAL_STATE.adb!.sync();
            try {
                const content = new GatherStringStream();
                await sync
                    .read(SCRCPY_SETTINGS_FILENAME)
                    .pipeThrough(new DecodeUtf8Stream())
                    .pipeTo(content);
                const settings = JSON.parse(content.result);
                runInAction(() => {
                    SETTING_STATE.settings = {
                        ...DEFAULT_SETTINGS,
                        ...settings.settings,
                    };
                    SETTING_STATE.clientSettings = settings.clientSettings;
                });
            } catch (e) {
                if (!(e instanceof AdbSyncError)) {
                    throw e;
                }
            } finally {
                await sync.dispose();
            }
        })();

        runInAction(() => {
            SETTING_STATE.encoders = [];
            SETTING_STATE.displays = [];
+27 −2
Original line number Diff line number Diff line
import { ADB_SYNC_MAX_PACKET_SIZE } from "@yume-chan/adb";
import { ADB_SYNC_MAX_PACKET_SIZE, encodeUtf8 } from "@yume-chan/adb";
import { AdbDaemonWebUsbDevice } from "@yume-chan/adb-daemon-webusb";
import { AdbScrcpyClient, AdbScrcpyOptionsLatest } from "@yume-chan/adb-scrcpy";
import {
@@ -43,7 +43,7 @@ import {
    ScrcpyKeyboardInjector,
} from "./input";
import { MatroskaMuxingRecorder, RECORD_STATE } from "./recorder";
import { SETTING_STATE } from "./settings";
import { SCRCPY_SETTINGS_FILENAME, SETTING_STATE } from "./settings";

const NOOP = () => {
    // no-op
@@ -293,6 +293,31 @@ export class ScrcpyPageState {
                })
            );

            const sync = await GLOBAL_STATE.adb!.sync();
            try {
                await sync.write({
                    filename: SCRCPY_SETTINGS_FILENAME,
                    file: new ReadableStream<Consumable<Uint8Array>>({
                        start(controller) {
                            controller.enqueue(
                                new Consumable(
                                    encodeUtf8(
                                        JSON.stringify({
                                            settings: SETTING_STATE.settings,
                                            clientSettings:
                                                SETTING_STATE.clientSettings,
                                        })
                                    )
                                )
                            );
                            controller.close();
                        },
                    }),
                });
            } finally {
                sync.dispose();
            }

            RECORD_STATE.recorder = new MatroskaMuxingRecorder();

            client.videoStream.then(({ stream, metadata }) => {
+3 −1
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@ export enum AdbSyncResponseId {
    Fail = "FAIL",
}

export class AdbSyncError extends Error {}

export const AdbSyncFailResponse = new Struct({ littleEndian: true })
    .uint32("messageLength")
    .string("message", { lengthField: "messageLength" })
    .postDeserialize((object) => {
        throw new Error(object.message);
        throw new AdbSyncError(object.message);
    });

export async function adbSyncReadResponse<T>(