Ramble-FE / services / media / media-manager.ts
media-manager.ts
Raw
import { EventEmitter } from "eventemitter3";
import { IPlatformWebRTC } from "../platform";
import { IMediaManager } from "./media.interface";
import { MediaManagerEventMap } from "./media.types";

export class MediaManager extends EventEmitter<MediaManagerEventMap> implements IMediaManager {
    private localStream?: MediaStream;
    private audioMuted: boolean = false;
    private cameraFront: boolean = true;

    constructor(private platform: IPlatformWebRTC) {
        super();
    }

    async initialize(): Promise<void> {
        try {
            this.localStream = await this.platform.getUserMedia();
            this.emit("stream:ready", this.localStream);
        } catch (error) {
            console.error("[MediaManager] Cannot find MediaStream: ", error);
            this.emit("stream:error", new Error(`error: ${error}`));
        }
    }

    getLocalStream(): MediaStream | null {
        return this.localStream || null;
    }

    toggleAudio(): boolean {
        if (!this.localStream) {
            console.warn("[MediaManager] Cannot toggle audio: no local stream");
            return false;
        }

        const audioTrack = this.localStream.getAudioTracks()[0];

        if (audioTrack) {
            audioTrack.enabled = !audioTrack.enabled;
            this.audioMuted = !audioTrack.enabled;
            this.emit("audio:toggled", this.audioMuted);
        }

        return this.audioMuted;
    }

    isMuted(): boolean {
        return this.audioMuted;
    }

    async switchCamera(): Promise<void> {
        if (!this.localStream) {
            return;
        }

        const result = await this.platform.switchCamera(this.localStream);

        if (result) {
            this.cameraFront = !this.cameraFront;

            this.emit("camera:switched", this.cameraFront); 
        }
    }

    isCameraFront(): boolean {
        return this.cameraFront;
    }

    dispose(): void {
        if (this.localStream) {
            this.localStream.getTracks().forEach((track) => track.stop());

            this.localStream = undefined;
            this.audioMuted  = false;
            this.emit("stream:ended");
        }

        this.removeAllListeners();
    }
    
}