UNPKG

infobip-rtc

Version:

Infobip RTC JavaScript SDK - Infobip WebRTC API Implementation

148 lines 6.58 kB
import HangupStatusFactory from "../util/HangupStatusFactory"; import { CallStatus } from "../CallStatus"; import { DefaultApplicationCall } from "./DefaultApplicationCall"; import { WsAction } from "../ws/WsAction"; import { DeclineType } from "../DeclineType"; import HangupReasonFactory from "./util/HangupReasonFactory"; import { ApplicationCallOptions } from "../options/ApplicationCallOptions"; import { START_VIDEO_FILTER_ERROR_DESCRIPTION } from '../options/filters/video/DefaultVideoFilterManager'; export class DefaultIncomingApplicationCall extends DefaultApplicationCall { constructor(eventEmitter, gateway, logger, rtcConfig, device, caller, callsConfigurationId, remoteOffer, currentUserIdentity, token, apiUrl, callId) { super(eventEmitter, gateway, logger, rtcConfig, device, callsConfigurationId, null, currentUserIdentity, token, apiUrl, callId); this.caller = caller; this.remoteOffer = remoteOffer; this.callStatus = CallStatus.RINGING; } from() { return this.caller.identity; } fromDisplayName() { return this.caller.displayName; } accept(options) { if (this.callStatus !== CallStatus.RINGING) { return; } this.callStatus = CallStatus.CONNECTING; this.applicationCallOptions = options || ApplicationCallOptions.builder().build(); this.localAudio = { active: this.applicationCallOptions.audio }; this.localCameraVideo = { active: this.applicationCallOptions.video }; if (this.applicationCallOptions.dataChannel) { this.createDataChannel(); } if (this.applicationCallOptions.audioOptions?.detectTalkingWhileMuted) { this.createAudioStreamEnergyMonitor(); } this.createAudioPeerConnection(); let deviceId = this.applicationCallOptions.videoOptions?.deviceId; if (deviceId) { this.setVideoInputDevice(deviceId); } this.negotiateAudio(this.applicationCallOptions); } async negotiateAudio(options) { let mediaStream; try { let audio = options.audio || options.audioOptions?.detectTalkingWhileMuted; mediaStream = await this.getLocalMediaStream(audio, options.video, options.videoOptions?.cameraOrientation, options.videoOptions?.cameraVideoFrameRate); if (this.isFinished()) { this.logger.warn(`Call is no longer connecting, aborting audio negotiation`, this.callId); this.stopAllTracks(mediaStream); return; } if (options.video && mediaStream.getVideoTracks().length > 0) { let videoStream = new MediaStream([mediaStream.getVideoTracks()[0]]); await this.setLocalVideoStream(videoStream); } let audioStream = audio ? new MediaStream([mediaStream.getAudioTracks()[0]]) : new MediaStream(); this.setLocalAudioStream(audioStream); await this.setRemoteDescription(); if (this.isFinished()) { this.logger.warn(`Call is no longer connecting, aborting audio negotiation`, this.callId); return; } this.setRemoteCandidates(); this.addTracksToPc(); let answer = await this.audioPC.peerConnection.createAnswer(); answer = await this.setLocalDescription(this.audioPC.peerConnection, answer); if (this.isFinished()) { this.logger.warn(`Call is no longer connecting, aborting audio negotiation`, this.callId); return; } this.sendAnswer(answer, options); } catch (error) { if (mediaStream) { this.stopAllTracks(mediaStream); } this.handleIncomingCallFlowError(error); } } decline(options) { if (this.callStatus !== CallStatus.RINGING) { return; } this.callStatus = CallStatus.FINISHED; this.declineCall(DeclineType.BUSY, 'Busy Here', options?.declineOnAllDevices); } async setRemoteDescription() { return await this.audioPC.peerConnection.setRemoteDescription(this.remoteOffer); } addTracksToPc() { let audioStream = this.emptyAudioStream ? this.emptyAudioStream.stream() : this.localAudioStream; audioStream.getTracks().forEach((track) => this.audioPC.peerConnection.addTrack(track, this.localAudioStream)); this.localAudio.transceiver = this.audioPC.peerConnection.getTransceivers() .find(transceiver => transceiver.receiver.track.kind === 'audio'); } sendAnswer(answer, options) { this.gateway.send({ action: WsAction.APP_CALL_ACCEPT, callId: this.callId, description: answer, media: { audio: { muted: !this.localAudio.active, }, video: { camera: this.localCameraVideo.active } }, autoReconnect: options.autoReconnect }); } handleIncomingCallFlowError(error) { this.logger.error(`Call flow error occurred: ${error} ${error?.stack}`, this.callId); const errorCode = HangupStatusFactory.getApplicationHangupStatus(error); if (this.isAcceptRetriableError(errorCode)) { this.rollbackAccept(); this.emitErrorEvent(errorCode); return; } let reason = HangupReasonFactory.getHangupReason(error); this.declineCall(DeclineType.ERROR, reason); this.eventEmitter.emit('call-error', { status: errorCode }); } isAcceptRetriableError(errorCode) { return errorCode?.description === START_VIDEO_FILTER_ERROR_DESCRIPTION; } rollbackAccept() { this.callStatus = CallStatus.RINGING; this.applicationCallOptions = null; this.localAudio = { active: false }; this.localCameraVideo = { active: false }; this.dataChannelCleanup(); this.audioStreamEnergyMonitorCleanup(); this.audioCleanup(); } declineCall(declineType, reason, declineOnAllDevices = false) { let message = { action: WsAction.APP_CALL_DECLINE, callId: this.callId, declineType: declineType, reason: reason, declineOnAllDevices: declineOnAllDevices }; this.gateway.send(message); } } //# sourceMappingURL=DefaultIncomingApplicationCall.js.map