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

Commit 6ae7e873 authored by Simon Chan's avatar Simon Chan
Browse files

feat(scrcpy): support `sendFrameMeta: false`

fixes #374
parent 3e3e56df
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -3,6 +3,10 @@ import Head from 'next/head';
import { ExternalLink } from '../components';
import { RouteStackProps } from "../utils";

<!--
cspell: ignore cybojenix
-->

This is a demo for my <ExternalLink href="https://github.com/yume-chan/ya-webadb/">ya-webadb</ExternalLink> project, which can use ADB protocol to control Android phones, directly from Web browsers (or Node.js).

It started because I want to try the <ExternalLink href="https://developer.mozilla.org/en-US/docs/Web/API/USB">WebUSB</ExternalLink> API, and because I have an Android phone. It's not production-ready, and I don't recommend normal users to try it. If you have any questions or suggestions, please file an issue at <ExternalLink href="https://github.com/yume-chan/ya-webadb/issues">here</ExternalLink>.
@@ -10,7 +14,6 @@ It started because I want to try the <ExternalLink href="https://developer.mozil
It was called "ya-webadb" (Yet Another WebADB), because there have already been several similar projects, for example:

* <ExternalLink href="https://github.com/webadb/webadb.js">webadb/webadb.js</ExternalLink>
<!-- cspell: disable-next-line -->
* <ExternalLink href="https://github.com/cybojenix/WebADB">cybojenix/WebADB</ExternalLink>

However, they are all pretty simple and not maintained, so I decided to make my own.
+6 −6
Original line number Diff line number Diff line
@@ -336,7 +336,7 @@ class ScrcpyPageState {
                while (this.rendererContainer.firstChild) {
                    this.rendererContainer.firstChild.remove();
                }
                this.rendererContainer.appendChild(this.decoder.element);
                this.rendererContainer.appendChild(this.decoder.renderer);
            }
        });

@@ -454,19 +454,19 @@ class ScrcpyPageState {
            client.onOutput(action(line => this.log.push(line)));
            client.onClose(this.stop);

            client.onSizeChanged(action((size) => {
                const { croppedWidth, croppedHeight, } = size;
            client.onEncodingChanged(action((encoding) => {
                const { croppedWidth, croppedHeight, } = encoding;

                this.log.push(`[client] Video size changed: ${croppedWidth}x${croppedHeight}`);

                this.width = croppedWidth;
                this.height = croppedHeight;

                decoder.setSize(size);
                decoder.changeEncoding(encoding);
            }));

            client.onVideoData(({ data }) => {
                decoder.feed(data);
            client.onVideoData((data) => {
                decoder.feedData(data);
            });

            client.onClipboardChange(content => {
+39 −12
Original line number Diff line number Diff line
import { StructAsyncDeserializeStream } from '@yume-chan/struct';
import { StructAsyncDeserializeStream, ValueOrPromise } from '@yume-chan/struct';
import { AdbSocket, AdbSocketInfo } from '../socket';
import { AdbSocketStream } from './stream';

export class StreamEndedError extends Error {
    public constructor() {
        super('Stream ended');

        // Fix Error's prototype chain when compiling to ES5
        Object.setPrototypeOf(this, new.target.prototype);
    }
}

export interface Stream {
    /**
     * When the stream is ended (no more data can be read),
     * An `StreamEndedError` should be thrown.
     *
     * @param length A hint of how much data should be read.
     * @returns Data, which can be either more or less than `length`
     * @returns Data, which can be either more or less than `length`.
     */
    read(length: number): ArrayBuffer | Promise<ArrayBuffer>;
    read(length: number): ValueOrPromise<ArrayBuffer>;

    close?(): void;
}
@@ -21,7 +33,13 @@ export class BufferedStream<T extends Stream> {
        this.stream = stream;
    }

    public async read(length: number): Promise<ArrayBuffer> {
    /**
     *
     * @param length
     * @param readToEnd When `true`, allow less data to be returned if the stream has reached its end.
     * @returns
     */
    public async read(length: number, readToEnd: boolean = false): Promise<ArrayBuffer> {
        let array: Uint8Array;
        let index: number;
        if (this.buffer) {
@@ -51,6 +69,7 @@ export class BufferedStream<T extends Stream> {
            index = buffer.byteLength;
        }

        try {
            while (index < length) {
                const left = length - index;

@@ -64,6 +83,14 @@ export class BufferedStream<T extends Stream> {
                array.set(new Uint8Array(buffer), index);
                index += buffer.byteLength;
            }
        }
        catch (e) {
            if (readToEnd && e instanceof StreamEndedError) {
                return array.buffer;
            }

            throw e;
        }

        return array.buffer;
    }
+2 −1
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ import { once } from '@yume-chan/event';
import { ValueOrPromise } from '@yume-chan/struct';
import { AdbSocket, AdbSocketInfo } from '../socket';
import { EventQueue } from '../utils';
import { StreamEndedError } from "./buffered-stream";

export class AdbSocketStream implements AdbSocketInfo {
    private socket: AdbSocket;
@@ -36,7 +37,7 @@ export class AdbSocketStream implements AdbSocketInfo {
        try {
            return await this.queue.dequeue();
        } catch {
            throw new Error('Can not read after AdbSocketStream has been closed');
            throw new StreamEndedError();
        }
    }

+1 −1
Original line number Diff line number Diff line
import { PromiseResolver } from '@yume-chan/async';
import { Event } from './event';

export async function once<T>(event: Event<T>): Promise<T> {
export async function once<T>(event: Event<T, any>): Promise<T> {
    const resolver = new PromiseResolver<T>();
    const dispose = event(resolver.resolve);
    const result = await resolver.promise;
Loading