UNPKG

@jsxc/jsxc

Version:

Real-time XMPP chat application with video calls, file transfer and encrypted communication

116 lines (85 loc) 3.72 kB
import Log from '../util/Log'; import Translation from '../util/Translation'; import { VideoDialog } from './VideoDialog'; import JingleMediaSession from '@src/JingleMediaSession'; export default class VideoWindow { private videoElement: JQuery; private wrapperElement: JQuery; constructor(private videoDialog: VideoDialog, private session: JingleMediaSession) { this.registerHooks(); this.initWrapper(); let remoteStreams = this.session.getRemoteStreams(); if (remoteStreams.length > 0) { this.wrapperElement.removeClass('jsxc-establishing'); this.wrapperElement.addClass('jsxc-ice-connected'); this.addStream(remoteStreams[0]); } } private registerHooks() { //@TODO remaining events: hold, resume, mute, unmute this.session.on('change:connectionState', this.onIceConnectionStateChanged); this.session.on('peerStreamAdded', this.addStream); this.session.on('peerStreamRemoved', this.removeStream); this.session.on('ringing', this.callRinging); this.session.on('accepted', this.callAccepted); } private initWrapper() { this.wrapperElement = $('<div>'); this.wrapperElement.addClass('jsxc-video-wrapper jsxc-establishing'); this.wrapperElement.attr('data-sid', this.session.getId()); this.videoDialog.addContainer(this.wrapperElement); } private onIceConnectionStateChanged = (state: string) => { Log.debug('connection state for ' + this.session.getId(), state); if (state === 'connected') { this.wrapperElement.removeClass('jsxc-establishing'); this.wrapperElement.addClass('jsxc-ice-connected'); let remoteStreams = this.session.getRemoteStreams(); if (remoteStreams.length > 0) { this.addStream(remoteStreams[0]); } } else if (state === 'failed') { Log.warn('ICE connection failed'); this.session.end('failed-transport'); } else if (state === 'interrupted') { this.videoDialog.setStatus(Translation.t('Connection_interrupted')); } }; private callAccepted = () => { this.wrapperElement.removeClass('jsxc-ringing'); this.videoDialog.clearStatus(); }; private callRinging = () => { this.videoDialog.setStatus('ringing...', 0); this.wrapperElement.removeClass('jsxc-establishing'); this.wrapperElement.addClass('jsxc-ringing'); }; private addStream = (stream: MediaStream) => { if (this.videoElement) { return; } //@REVIEW can a session contain multiple streams? Log.debug('Remote stream for session ' + this.session.getId() + ' added.'); let isVideoDevice = stream.getVideoTracks().length > 0; let isAudioDevice = stream.getAudioTracks().length > 0; this.videoDialog.setStatus(isVideoDevice ? 'Use remote video device.' : 'No remote video device'); this.videoDialog.setStatus(isAudioDevice ? 'Use remote audio device.' : 'No remote audio device'); this.videoElement = $('<video autoplay playsinline></video>'); this.videoElement.appendTo(this.wrapperElement); VideoDialog.attachMediaStream(this.videoElement, stream); if (isVideoDevice) { this.wrapperElement.addClass('jsxc-video-available'); } if (isAudioDevice) { this.wrapperElement.addClass('jsxc-audio-available'); } }; private removeStream = () => { Log.debug('Remote stream for ' + this.session.getId() + ' removed.'); VideoDialog.detachMediaStream(this.videoElement); if (this.videoElement) { this.videoElement.remove(); this.videoElement = undefined; } }; }