From 3cd4c399d4b4e743dd66665c282f7f216317b50a Mon Sep 17 00:00:00 2001 From: Dave Horton Date: Mon, 20 Sep 2021 15:50:00 -0400 Subject: [PATCH] LCC: add support for conf_hold_status to hold/unhold a participant in a conference --- lib/session/call-session.js | 48 ++++++++++++++++++------------------- lib/tasks/conference.js | 18 ++++++++++++++ 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/lib/session/call-session.js b/lib/session/call-session.js index 13e285e2..92d1f886 100644 --- a/lib/session/call-session.js +++ b/lib/session/call-session.js @@ -339,7 +339,7 @@ class CallSession extends Emitter { */ _lccCallStatus(opts) { if (opts.call_status === CallStatus.Completed && this.dlg) { - this.logger.info('CallSession:updateCall hanging up call due to request from api'); + this.logger.info('CallSession:_lccCallStatus hanging up call due to request from api'); this._callerHungup(); } else if (opts.call_status === CallStatus.NoAnswer) { @@ -388,7 +388,7 @@ class CallSession extends Emitter { const {parentLogger} = this.srf.locals; const childLogger = parentLogger.child({callId: this.callId, callSid: sd.callSid}); const t = normalizeJambones(childLogger, childTasks).map((tdata) => makeTask(childLogger, tdata)); - childLogger.info({tasks: listTaskNames(t)}, 'CallSession:updateCall new task list for child call'); + childLogger.info({tasks: listTaskNames(t)}, 'CallSession:_lccCallHook new task list for child call'); const cs = await sd.doAdulting({ logger: childLogger, application: this.application, @@ -400,7 +400,7 @@ class CallSession extends Emitter { } if (tasks) { const t = normalizeJambones(this.logger, tasks).map((tdata) => makeTask(this.logger, tdata)); - this.logger.info({tasks: listTaskNames(t)}, 'CallSession:updateCall new task list'); + this.logger.info({tasks: listTaskNames(t)}, 'CallSession:_lccCallHook new task list'); this.replaceApplication(t); } else { @@ -417,23 +417,34 @@ class CallSession extends Emitter { async _lccListenStatus(opts) { const task = this.currentTask; if (!task || ![TaskName.Dial, TaskName.Listen].includes(task.name)) { - return this.logger.info(`CallSession:updateCall - invalid listen_status in task ${task.name}`); + return this.logger.info(`CallSession:_lccListenStatus - invalid listen_status in task ${task.name}`); } const listenTask = task.name === TaskName.Listen ? task : task.listenTask; if (!listenTask) { - return this.logger.info('CallSession:updateCall - invalid listen_status: Dial does not have a listen'); + return this.logger.info('CallSession:_lccListenStatus - invalid listen_status: Dial does not have a listen'); } listenTask.updateListen(opts.listen_status); } async _lccMuteStatus(callSid, mute) { - // this whole thing requires us to be in a Dial verb + // this whole thing requires us to be in a Dial or Conference verb const task = this.currentTask; - if (!task || TaskName.Dial !== task.name) { - return this.logger.info('CallSession:_lccMute - invalid command as dial is not active'); + if (!task || ![TaskName.Dial, TaskName.Conference].includes(task.name)) { + return this.logger.info('CallSession:_lccMuteStatus - invalid: neither dial nor conference are not active'); } - // now do the whisper - task.mute(callSid, mute).catch((err) => this.logger.error(err, 'CallSession:_lccMute')); + // now do the mute/unmute + task.mute(callSid, mute).catch((err) => this.logger.error(err, 'CallSession:_lccMuteStatus')); + } + + async _lccConfHoldStatus(callSid, hold) { + this.logger.debug(`_lccConfHoldStatus ${hold}`); + const task = this.currentTask; + if (!task || TaskName.Conference !== task.name) { + return this.logger.info('CallSession:_lccConfHoldStatus - invalid command as conference verb is not active'); + } + // now do the mute/unmute, deaf/undeaf + task.mute(callSid, hold).catch((err) => this.logger.error(err, 'CallSession:_lccMuteStatus')); + task.deaf(callSid, hold).catch((err) => this.logger.error(err, 'CallSession:_lccMuteStatus')); } /** @@ -484,20 +495,6 @@ class CallSession extends Emitter { task.whisper(tasks, callSid).catch((err) => this.logger.error(err, 'CallSession:_lccWhisper')); } - /** - * perform live call control -- mute or unmute an endpoint - * @param {array} opts - array of play or say tasks - */ - async _lccMute(callSid, mute) { - - // this whole thing requires us to be in a Dial verb - const task = this.currentTask; - if (!task || TaskName.Dial !== task.name) { - return this.logger.info('CallSession:_lccMute - not possible since we are not in a dial'); - } - - task.mute(callSid, mute).catch((err) => this.logger.error(err, 'CallSession:_lccMute')); - } /** * perform live call control @@ -519,6 +516,9 @@ class CallSession extends Emitter { else if (opts.mute_status) { await this._lccMuteStatus(callSid, opts.mute_status === 'mute'); } + else if (opts.conf_hold_status) { + await this._lccConfHoldStatus(callSid, opts.conf_hold_status === 'hold'); + } // whisper may be the only thing we are asked to do, or it may that // we are doing a whisper after having muted, paused reccording etc.. diff --git a/lib/tasks/conference.js b/lib/tasks/conference.js index 9237df25..be7e2611 100644 --- a/lib/tasks/conference.js +++ b/lib/tasks/conference.js @@ -375,6 +375,24 @@ class Conference extends Task { this.emitter.emit('join', opts); } + async mute(callSid, muted) { + if (this.memberId) { + const prop = muted === true ? 'mute' : 'unmute'; + this.ep.api(`conference ${this.confName} ${prop} ${this.memberId}`) + .catch((err) => this.logger.info({err}, `Error ${prop} participant`)); + return true; + } + } + + async deaf(callSid, deafed) { + if (this.memberId) { + const prop = deafed === true ? 'deaf' : 'undeaf'; + this.ep.api(`conference ${this.confName} ${prop} ${this.memberId}`) + .catch((err) => this.logger.info({err}, `Error ${prop} participant`)); + return true; + } + } + /** * Add ourselves to the waitlist of sessions to be notified once * the conference starts