UNPKG

@jellyfish-dev/react-client-sdk

Version:
135 lines (134 loc) 4.63 kB
import EventEmitter from "events"; import { parseError } from "./types"; export class ScreenShareManager extends EventEmitter { defaultConfig; config; data = { audioMedia: null, videoMedia: null, status: "Not requested", error: null, }; // todo add nested read only getSnapshot() { return this.data; } constructor(defaultConfig) { super(); this.defaultConfig = defaultConfig; } setConfig(config) { this.config = config; } getType(options) { if (options.audio && options.video) return "audiovideo"; if (options.audio) return "audio"; if (options.video) return "video"; return null; } async start(config) { const options = { video: config?.videoTrackConstraints ?? this.config?.videoTrackConstraints ?? this.defaultConfig?.videoTrackConstraints, audio: config?.audioTrackConstraints ?? this.config?.audioTrackConstraints ?? this.defaultConfig?.audioTrackConstraints, }; const type = this.getType(options); if (!type) return; try { const newStream = await navigator.mediaDevices.getDisplayMedia(options); this.data = { error: null, videoMedia: { enabled: true, stream: newStream, track: newStream?.getVideoTracks()[0] ?? null, }, audioMedia: { enabled: true, stream: newStream, track: newStream?.getAudioTracks()[0] ?? null, }, status: "OK", }; this.setupOnEndedCallback(); this.emit("deviceReady", { type: type }, this.data); } catch (error) { const parsedError = parseError(error); this.emit("error", { type, error: parsedError, rawError: error }, this.data); } } setupOnEndedCallback() { if (this.data.videoMedia?.track) { this.data.videoMedia.track.addEventListener("ended", async (event) => await this.onTrackEnded("video", event.target.id)); } if (this.data.audioMedia?.track) { this.data.audioMedia.track.addEventListener("ended", async (event) => await this.onTrackEnded("audio", event.target.id)); } } onTrackEnded = async (type, trackId) => { const mediaType = type === "video" ? "videoMedia" : "audioMedia"; if (trackId === this?.data[mediaType]?.track?.id) { await this.stop("audiovideo"); } }; async stop(type) { if (type === "video") { for (const track of this.data?.videoMedia?.stream?.getTracks() ?? []) { track.stop(); } this.data.videoMedia = null; } else if (type === "audio") { // todo test it for (const track of this.data?.audioMedia?.stream?.getTracks() ?? []) { track.stop(); } this.data.audioMedia = null; } else { for (const track of this.data?.videoMedia?.stream?.getTracks() ?? []) { track.stop(); } this.data.videoMedia = null; for (const track of this.data?.audioMedia?.stream?.getTracks() ?? []) { track.stop(); } this.data.audioMedia = null; } this.emit("deviceStopped", { type }, this.data); } setEnable(type, value) { if (type === "video" && this.data.videoMedia?.track) { this.data.videoMedia.track.enabled = value; this.data.videoMedia.enabled = value; } else if (type === "audio" && this.data.audioMedia?.track) { this.data.audioMedia.track.enabled = value; this.data.audioMedia.enabled = value; } else { if (this.data.videoMedia?.track) { this.data.videoMedia.track.enabled = value; this.data.videoMedia.enabled = value; } if (this.data.audioMedia?.track) { this.data.audioMedia.track.enabled = value; this.data.audioMedia.enabled = value; } } if (value) { this.emit("deviceEnabled", { type }, this.data); } else { this.emit("deviceDisabled", { type }, this.data); } } }