import { Publisher, StreamManager } from 'openvidu-browser'; import { VideoType } from './video-type.model'; /** * @internal */ export enum OpenViduRole { MODERATOR = 'MODERATOR', PUBLISHER = 'PUBLISHER' } export interface StreamModel { /** * Whether the stream is available or not */ connected: boolean; /** * The stream type.{@link VideoType} */ type: VideoType; /** * The streamManager object from openvidu-browser library.{@link https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/StreamManager.html} */ streamManager: StreamManager; /** * Whether the stream is enlarged or not */ videoEnlarged: boolean; /** * Unique identifier of the stream */ connectionId: string; /** * The participant object */ participant?: ParticipantAbstractModel; } export interface ParticipantProperties { /** * Whether the participant is local or not */ local: boolean; /** * The participant nickname */ nickname: string; /** * Unique identifier of the participant */ id?: string; /** * The participant color profile */ colorProfile?: string; /** * Whether the participant is muted forcibly or not */ isMutedForcibly?: boolean; } export abstract class ParticipantAbstractModel { streams: Map = new Map(); id: string; local: boolean; nickname: string; colorProfile: string; isMutedForcibly: boolean; constructor(props: ParticipantProperties, model?: StreamModel) { this.id = props.id ? props.id : Math.random().toString(32).replace('.','_'); this.local = props.local; this.nickname = props.nickname; this.colorProfile = !!props.colorProfile ? props.colorProfile : `hsl(${Math.random() * 360}, 100%, 80%)`; this.isMutedForcibly = typeof props.isMutedForcibly === 'boolean' ? props.isMutedForcibly : false; let streamModel: StreamModel = { connected: model ? model.connected : true, type: model ? model.type : VideoType.CAMERA, streamManager: model ? model.streamManager : null, videoEnlarged: model ? model.videoEnlarged : false, connectionId: model ? model.connectionId : null, participant: this }; this.streams.set(streamModel.type, streamModel); } /** * @internal */ addConnection(streamModel: StreamModel) { streamModel.participant = this; this.streams.set(streamModel.type, streamModel); } /** * @internal */ hasAudioActive(): boolean { const cameraConnection = this.getCameraConnection(); const screenConnection = this.getScreenConnection(); if (cameraConnection.connected) { return this.isCameraAudioActive(); } else if (screenConnection.connected) { return this.isScreenAudioActive(); } return false; } /** * @internal */ private isCameraAudioActive(): boolean { const cameraConnection = this.getCameraConnection(); if (cameraConnection?.connected) { return cameraConnection.streamManager?.stream?.audioActive; } return false; } /** * @internal */ public isCameraVideoActive(): boolean { const cameraConnection = this.getCameraConnection(); return cameraConnection?.connected && cameraConnection?.streamManager?.stream?.videoActive; } /** * @internal */ isScreenAudioActive(): boolean { const screenConnection = this.getScreenConnection(); if (screenConnection?.connected) { return screenConnection?.streamManager?.stream?.audioActive; } return false; } /** * @internal */ hasConnectionType(type: VideoType): boolean { return this.streams.has(type); } /** * @internal */ public getCameraConnection(): StreamModel { return this.streams.get(VideoType.CAMERA); } /** * @internal */ public getScreenConnection(): StreamModel { return this.streams.get(VideoType.SCREEN); } /** * @internal */ getConnectionTypesActive(): VideoType[] { let connType = []; if (this.isCameraActive()) connType.push(VideoType.CAMERA); if (this.isScreenActive()) connType.push(VideoType.SCREEN); return connType; } /** * @internal */ setCameraConnectionId(connectionId: string) { this.getCameraConnection().connectionId = connectionId; } /** * @internal */ setScreenConnectionId(connectionId: string) { this.getScreenConnection().connectionId = connectionId; } /** * @internal */ removeConnection(connectionId: string): StreamModel { const removeStream = this.getConnectionById(connectionId); this.streams.delete(removeStream.type); return removeStream; } /** * @internal */ hasConnectionId(connectionId: string): boolean { return Array.from(this.streams.values()).some((conn) => conn.connectionId === connectionId); } /** * @internal */ getConnectionById(connectionId: string): StreamModel { return Array.from(this.streams.values()).find((conn) => conn.connectionId === connectionId); } /** * @internal */ getAvailableConnections(): StreamModel[] { return Array.from(this.streams.values()).filter((conn) => conn.connected); } /** * @internal */ isLocal(): boolean { return this.local; // return Array.from(this.streams.values()).every((conn) => conn.local); } /** * @internal */ setNickname(nickname: string) { this.nickname = nickname; } /** * @internal */ getNickname() { return this.nickname; } /** * @internal */ setCameraPublisher(publisher: Publisher | undefined) { const cameraConnection = this.getCameraConnection(); if (cameraConnection) cameraConnection.streamManager = publisher; } /** * @internal */ setScreenPublisher(publisher: Publisher) { const screenConnection = this.getScreenConnection(); if (screenConnection) screenConnection.streamManager = publisher; } /** * @internal */ setPublisher(connType: VideoType, publisher: StreamManager) { const connection = this.streams.get(connType); if (connection) { connection.streamManager = publisher; } } /** * @internal */ isCameraActive(): boolean { return this.getCameraConnection()?.connected; } /** * @internal */ enableCamera() { const cameraConnection = this.getCameraConnection(); if (cameraConnection) cameraConnection.connected = true; } /** * @internal */ disableCamera() { const cameraConnection = this.getCameraConnection(); if (cameraConnection) cameraConnection.connected = false; } /** * @internal */ isScreenActive(): boolean { return this.getScreenConnection()?.connected; } /** * @internal */ enableScreen() { const screenConnection = this.getScreenConnection(); if (screenConnection) screenConnection.connected = true; } /** * @internal */ disableScreen() { const screenConnection = this.getScreenConnection(); if (screenConnection) screenConnection.connected = false; } /** * @internal */ setAllVideoEnlarged(enlarged: boolean) { this.streams.forEach((conn) => (conn.videoEnlarged = enlarged)); } /** * @internal */ setCameraEnlarged(enlarged: boolean) { this.streams.get(VideoType.CAMERA).videoEnlarged = enlarged; } /** * @internal */ setScreenEnlarged(enlarged: boolean) { this.streams.get(VideoType.SCREEN).videoEnlarged = enlarged; } /** * @internal */ toggleVideoEnlarged(connectionId: string) { this.streams.forEach((conn) => { if (conn.connectionId === connectionId) { conn.videoEnlarged = !conn.videoEnlarged; } }); } /** * @internal */ someHasVideoEnlarged(): boolean { return Array.from(this.streams.values()).some((conn) => conn.videoEnlarged); } /** * @internal */ setMutedForcibly(muted: boolean) { this.isMutedForcibly = muted; } /** * @internal */ getRole(): OpenViduRole { return this.streams.get(VideoType.CAMERA)?.streamManager?.stream?.connection?.role; } } /** * @internal */ export class ParticipantModel extends ParticipantAbstractModel {}