зеркало из https://github.com/nextcloud/spreed.git
Import call models
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Родитель
e122cc77fd
Коммит
966d10a038
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* @copyright Copyright (c) 2019, Daniel Calviño Sánchez (danxuliu@gmail.com)
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import CallParticipantModel from './CallParticipantModel'
|
||||
|
||||
export default function CallParticipantCollection() {
|
||||
|
||||
this.callParticipantModels = []
|
||||
|
||||
}
|
||||
|
||||
CallParticipantCollection.prototype = {
|
||||
|
||||
add: function(options) {
|
||||
const callParticipantModel = new CallParticipantModel(options)
|
||||
this.callParticipantModels.push(callParticipantModel)
|
||||
|
||||
return callParticipantModel
|
||||
},
|
||||
|
||||
get: function(peerId) {
|
||||
return this.callParticipantModels.find(function(callParticipantModel) {
|
||||
return callParticipantModel.attributes.peerId === peerId
|
||||
})
|
||||
},
|
||||
|
||||
remove: function(peerId) {
|
||||
const index = this.callParticipantModels.findIndex(function(callParticipantModel) {
|
||||
return callParticipantModel.attributes.peerId === peerId
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.callParticipantModels.splice(index, 1)
|
||||
}
|
||||
},
|
||||
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
*
|
||||
* @copyright Copyright (c) 2019, Daniel Calviño Sánchez (danxuliu@gmail.com)
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
export const ConnectionState = {
|
||||
NEW: 'new',
|
||||
CHECKING: 'checking',
|
||||
CONNECTED: 'connected',
|
||||
COMPLETED: 'completed',
|
||||
DISCONNECTED: 'disconnected',
|
||||
DISCONNECTED_LONG: 'disconnected-long', // Talk specific
|
||||
FAILED: 'failed',
|
||||
FAILED_NO_RESTART: 'failed-no-restart', // Talk specific
|
||||
CLOSED: 'closed',
|
||||
}
|
||||
|
||||
export default function CallParticipantModel(options) {
|
||||
|
||||
this.attributes = {
|
||||
peerId: null,
|
||||
// "undefined" is used for values not known yet; "null" or "false"
|
||||
// are used for known but negative/empty values.
|
||||
userId: undefined,
|
||||
name: undefined,
|
||||
connectionState: ConnectionState.NEW,
|
||||
stream: null,
|
||||
audioAvailable: undefined,
|
||||
speaking: undefined,
|
||||
videoAvailable: undefined,
|
||||
screen: null,
|
||||
}
|
||||
|
||||
this.set('peerId', options.peerId)
|
||||
|
||||
this._webRtc = options.webRtc
|
||||
|
||||
this._handlePeerStreamAddedBound = this._handlePeerStreamAdded.bind(this)
|
||||
this._handlePeerStreamRemovedBound = this._handlePeerStreamRemoved.bind(this)
|
||||
this._handleNickBound = this._handleNick.bind(this)
|
||||
this._handleMuteBound = this._handleMute.bind(this)
|
||||
this._handleUnmuteBound = this._handleUnmute.bind(this)
|
||||
this._handleExtendedIceConnectionStateChangeBound = this._handleExtendedIceConnectionStateChange.bind(this)
|
||||
this._handleChannelMessageBound = this._handleChannelMessage.bind(this)
|
||||
|
||||
this._webRtc.on('peerStreamAdded', this._handlePeerStreamAddedBound)
|
||||
this._webRtc.on('peerStreamRemoved', this._handlePeerStreamRemovedBound)
|
||||
this._webRtc.on('nick', this._handleNickBound)
|
||||
this._webRtc.on('mute', this._handleMuteBound)
|
||||
this._webRtc.on('unmute', this._handleUnmuteBound)
|
||||
this._webRtc.on('channelMessage', this._handleChannelMessageBound)
|
||||
|
||||
}
|
||||
|
||||
CallParticipantModel.prototype = {
|
||||
|
||||
get: function(key) {
|
||||
return this.attributes[key]
|
||||
},
|
||||
|
||||
set: function(key, value) {
|
||||
this.attributes[key] = value
|
||||
},
|
||||
|
||||
_handlePeerStreamAdded: function(peer) {
|
||||
if (this._peer === peer) {
|
||||
this.set('stream', this._peer.stream || null)
|
||||
|
||||
// "peer.nick" is set only for users and when the MCU is not used.
|
||||
if (this._peer.nick !== undefined) {
|
||||
this.set('name', this._peer.nick)
|
||||
}
|
||||
} else if (this._screenPeer === peer) {
|
||||
this.set('screen', this._screenPeer.stream || null)
|
||||
}
|
||||
},
|
||||
|
||||
_handlePeerStreamRemoved: function(peer) {
|
||||
if (this._peer === peer) {
|
||||
this.set('stream', null)
|
||||
this.set('audioAvailable', undefined)
|
||||
this.set('speaking', undefined)
|
||||
this.set('videoAvailable', undefined)
|
||||
} else if (this._screenPeer === peer) {
|
||||
this.set('screen', null)
|
||||
}
|
||||
},
|
||||
|
||||
_handleNick: function(data) {
|
||||
if (!this._peer || this._peer.id !== data.id) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('userId', data.userid || null)
|
||||
this.set('name', data.name || null)
|
||||
},
|
||||
|
||||
_handleMute: function(data) {
|
||||
if (!this._peer || this._peer.id !== data.id) {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.name === 'video') {
|
||||
this.set('videoAvailable', false)
|
||||
} else {
|
||||
this.set('audioAvailable', false)
|
||||
this.set('speaking', false)
|
||||
}
|
||||
},
|
||||
|
||||
_handleUnmute: function(data) {
|
||||
if (!this._peer || this._peer.id !== data.id) {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.name === 'video') {
|
||||
this.set('videoAvailable', true)
|
||||
} else {
|
||||
this.set('audioAvailable', true)
|
||||
}
|
||||
},
|
||||
|
||||
_handleChannelMessage: function(peer, label, data) {
|
||||
if (!this._peer || this._peer.id !== peer.id) {
|
||||
return
|
||||
}
|
||||
|
||||
if (label !== 'status') {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.type === 'speaking') {
|
||||
this.set('speaking', true)
|
||||
} else if (data.type === 'stoppedSpeaking') {
|
||||
this.set('speaking', false)
|
||||
}
|
||||
},
|
||||
|
||||
setPeer: function(peer) {
|
||||
if (peer && this.get('peerId') !== peer.id) {
|
||||
console.warn('Mismatch between stored peer ID and ID of given peer: ', this.get('peerId'), peer.id)
|
||||
}
|
||||
|
||||
if (this._peer) {
|
||||
this._peer.off('extendedIceConnectionStateChange', this._handleExtendedIceConnectionStateChangeBound)
|
||||
}
|
||||
|
||||
this._peer = peer
|
||||
|
||||
// Special case when the participant has no streams.
|
||||
if (!this._peer) {
|
||||
this.set('connectionState', ConnectionState.COMPLETED)
|
||||
this.set('audioAvailable', false)
|
||||
this.set('speaking', false)
|
||||
this.set('videoAvailable', false)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Reset state that depends on the Peer object.
|
||||
this._handleExtendedIceConnectionStateChange(this._peer.pc.iceConnectionState)
|
||||
this._handlePeerStreamAdded(this._peer)
|
||||
|
||||
this._peer.on('extendedIceConnectionStateChange', this._handleExtendedIceConnectionStateChangeBound)
|
||||
},
|
||||
|
||||
_handleExtendedIceConnectionStateChange: function(extendedIceConnectionState) {
|
||||
// Ensure that the name is set, as when the MCU is not used it will
|
||||
// not be set later for registered users without microphone nor
|
||||
// camera.
|
||||
const setNameForUserFromPeerNick = function() {
|
||||
if (this._peer.nick !== undefined) {
|
||||
this.set('name', this._peer.nick)
|
||||
}
|
||||
}.bind(this)
|
||||
|
||||
switch (extendedIceConnectionState) {
|
||||
case 'new':
|
||||
this.set('connectionState', ConnectionState.NEW)
|
||||
this.set('audioAvailable', undefined)
|
||||
this.set('speaking', undefined)
|
||||
this.set('videoAvailable', undefined)
|
||||
break
|
||||
case 'checking':
|
||||
this.set('connectionState', ConnectionState.CHECKING)
|
||||
this.set('audioAvailable', undefined)
|
||||
this.set('speaking', undefined)
|
||||
this.set('videoAvailable', undefined)
|
||||
break
|
||||
case 'connected':
|
||||
this.set('connectionState', ConnectionState.CONNECTED)
|
||||
setNameForUserFromPeerNick()
|
||||
break
|
||||
case 'completed':
|
||||
this.set('connectionState', ConnectionState.COMPLETED)
|
||||
setNameForUserFromPeerNick()
|
||||
break
|
||||
case 'disconnected':
|
||||
this.set('connectionState', ConnectionState.DISCONNECTED)
|
||||
break
|
||||
case 'disconnected-long':
|
||||
this.set('connectionState', ConnectionState.DISCONNECTED_LONG)
|
||||
break
|
||||
case 'failed':
|
||||
this.set('connectionState', ConnectionState.FAILED)
|
||||
break
|
||||
case 'failed-no-restart':
|
||||
this.set('connectionState', ConnectionState.FAILED_NO_RESTART)
|
||||
break
|
||||
case 'closed':
|
||||
this.set('connectionState', ConnectionState.CLOSED)
|
||||
break
|
||||
default:
|
||||
console.error('Unexpected (extended) ICE connection state: ', extendedIceConnectionState)
|
||||
}
|
||||
},
|
||||
|
||||
setScreenPeer: function(screenPeer) {
|
||||
if (this.get('peerId') !== screenPeer.id) {
|
||||
console.warn('Mismatch between stored peer ID and ID of given screen peer: ', this.get('peerId'), screenPeer.id)
|
||||
}
|
||||
|
||||
this._screenPeer = screenPeer
|
||||
|
||||
// Reset state that depends on the screen Peer object.
|
||||
this._handlePeerStreamAdded(this._screenPeer)
|
||||
},
|
||||
|
||||
setUserId: function(userId) {
|
||||
this.set('userId', userId)
|
||||
},
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* @copyright Copyright (c) 2019, Daniel Calviño Sánchez (danxuliu@gmail.com)
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
export default function LocalCallParticipantModel() {
|
||||
|
||||
this.attributes = {
|
||||
peerId: null,
|
||||
guestName: null,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LocalCallParticipantModel.prototype = {
|
||||
|
||||
set: function(key, value) {
|
||||
this.attributes[key] = value
|
||||
},
|
||||
|
||||
setWebRtc: function(webRtc) {
|
||||
this._webRtc = webRtc
|
||||
|
||||
this.set('peerId', this._webRtc.connection.getSessionid())
|
||||
this.set('guestName', null)
|
||||
},
|
||||
|
||||
setGuestName: function(guestName) {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
this.set('guestName', guestName)
|
||||
|
||||
this._webRtc.sendDirectlyToAll('status', 'nickChanged', guestName)
|
||||
},
|
||||
|
||||
}
|
|
@ -0,0 +1,349 @@
|
|||
/**
|
||||
*
|
||||
* @copyright Copyright (c) 2019, Daniel Calviño Sánchez (danxuliu@gmail.com)
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
export default function LocalMediaModel() {
|
||||
|
||||
this.attributes = {
|
||||
localStream: null,
|
||||
audioAvailable: false,
|
||||
audioEnabled: false,
|
||||
speaking: false,
|
||||
speakingWhileMuted: false,
|
||||
currentVolume: -100,
|
||||
volumeThreshold: -100,
|
||||
videoAvailable: false,
|
||||
videoEnabled: false,
|
||||
localScreen: null,
|
||||
}
|
||||
|
||||
this._handlers = []
|
||||
|
||||
this._handleLocalStreamBound = this._handleLocalStream.bind(this)
|
||||
this._handleLocalStreamRequestFailedBound = this._handleLocalStreamRequestFailed.bind(this)
|
||||
this._handleLocalStreamStoppedBound = this._handleLocalStreamStopped.bind(this)
|
||||
this._handleAudioOnBound = this._handleAudioOn.bind(this)
|
||||
this._handleAudioOffBound = this._handleAudioOff.bind(this)
|
||||
this._handleVolumeChangeBound = this._handleVolumeChange.bind(this)
|
||||
this._handleSpeakingBound = this._handleSpeaking.bind(this)
|
||||
this._handleStoppedSpeakingBound = this._handleStoppedSpeaking.bind(this)
|
||||
this._handleSpeakingWhileMutedBound = this._handleSpeakingWhileMuted.bind(this)
|
||||
this._handleStoppedSpeakingWhileMutedBound = this._handleStoppedSpeakingWhileMuted.bind(this)
|
||||
this._handleVideoOnBound = this._handleVideoOn.bind(this)
|
||||
this._handleVideoOffBound = this._handleVideoOff.bind(this)
|
||||
this._handleLocalScreenBound = this._handleLocalScreen.bind(this)
|
||||
this._handleLocalScreenStoppedBound = this._handleLocalScreenStopped.bind(this)
|
||||
|
||||
}
|
||||
|
||||
LocalMediaModel.prototype = {
|
||||
|
||||
get: function(key) {
|
||||
return this.attributes[key]
|
||||
},
|
||||
|
||||
set: function(key, value) {
|
||||
this.attributes[key] = value
|
||||
|
||||
this._trigger('change:' + key, [value])
|
||||
},
|
||||
|
||||
on: function(event, handler) {
|
||||
if (!this._handlers.hasOwnProperty(event)) {
|
||||
this._handlers[event] = [handler]
|
||||
} else {
|
||||
this._handlers[event].push(handler)
|
||||
}
|
||||
},
|
||||
|
||||
_trigger: function(event, args) {
|
||||
let handlers = this._handlers[event]
|
||||
if (!handlers) {
|
||||
return
|
||||
}
|
||||
|
||||
args.unshift(this)
|
||||
|
||||
handlers = handlers.slice(0)
|
||||
for (let i = 0; i < handlers.length; i++) {
|
||||
const handler = handlers[i]
|
||||
handler.apply(handler, args)
|
||||
}
|
||||
},
|
||||
|
||||
getWebRtc: function() {
|
||||
return this._webRtc
|
||||
},
|
||||
|
||||
setWebRtc: function(webRtc) {
|
||||
if (this._webRtc && this._webRtc.webrtc) {
|
||||
this._webRtc.webrtc.off('localStream', this._handleLocalStreamBound)
|
||||
this._webRtc.webrtc.off('localStreamRequestFailed', this._handleLocalStreamRequestFailedBound)
|
||||
this._webRtc.webrtc.off('localStreamStopped', this._handleLocalStreamStoppedBound)
|
||||
this._webRtc.webrtc.off('audioOn', this._handleAudioOnBound)
|
||||
this._webRtc.webrtc.off('audioOff', this._handleAudioOffBound)
|
||||
this._webRtc.webrtc.off('volumeChange', this._handleVolumeChangeBound)
|
||||
this._webRtc.webrtc.off('speaking', this._handleSpeakingBound)
|
||||
this._webRtc.webrtc.off('stoppedSpeaking', this._handleStoppedSpeakingBound)
|
||||
this._webRtc.webrtc.off('speakingWhileMuted', this._handleSpeakingWhileMutedBound)
|
||||
this._webRtc.webrtc.off('stoppedSpeakingWhileMuted', this._handleStoppedSpeakingWhileMutedBound)
|
||||
this._webRtc.webrtc.off('videoOn', this._handleVideoOnBound)
|
||||
this._webRtc.webrtc.off('videoOff', this._handleVideoOffBound)
|
||||
this._webRtc.webrtc.off('localScreen', this._handleLocalScreenBound)
|
||||
this._webRtc.webrtc.off('localScreenStopped', this._handleLocalScreenStoppedBound)
|
||||
}
|
||||
|
||||
this._webRtc = webRtc
|
||||
|
||||
this.set('localStream', null)
|
||||
this.set('audioAvailable', false)
|
||||
this.set('audioEnabled', false)
|
||||
this.set('speaking', false)
|
||||
this.set('speakingWhileMuted', false)
|
||||
this.set('currentVolume', -100)
|
||||
this.set('volumeThreshold', -100)
|
||||
this.set('videoAvailable', false)
|
||||
this.set('videoEnabled', false)
|
||||
this.set('localScreen', null)
|
||||
|
||||
this._webRtc.webrtc.on('localStream', this._handleLocalStreamBound)
|
||||
this._webRtc.webrtc.on('localStreamRequestFailed', this._handleLocalStreamRequestFailedBound)
|
||||
this._webRtc.webrtc.on('localStreamStopped', this._handleLocalStreamStoppedBound)
|
||||
this._webRtc.webrtc.on('audioOn', this._handleAudioOnBound)
|
||||
this._webRtc.webrtc.on('audioOff', this._handleAudioOffBound)
|
||||
this._webRtc.webrtc.on('volumeChange', this._handleVolumeChangeBound)
|
||||
this._webRtc.webrtc.on('speaking', this._handleSpeakingBound)
|
||||
this._webRtc.webrtc.on('stoppedSpeaking', this._handleStoppedSpeakingBound)
|
||||
this._webRtc.webrtc.on('speakingWhileMuted', this._handleSpeakingWhileMutedBound)
|
||||
this._webRtc.webrtc.on('stoppedSpeakingWhileMuted', this._handleStoppedSpeakingWhileMutedBound)
|
||||
this._webRtc.webrtc.on('videoOn', this._handleVideoOnBound)
|
||||
this._webRtc.webrtc.on('videoOff', this._handleVideoOffBound)
|
||||
this._webRtc.webrtc.on('localScreen', this._handleLocalScreenBound)
|
||||
this._webRtc.webrtc.on('localScreenStopped', this._handleLocalScreenStoppedBound)
|
||||
},
|
||||
|
||||
_handleLocalStream: function(configuration, localStream) {
|
||||
// Although there could be several local streams active at the same
|
||||
// time (if the local media is started again before stopping it
|
||||
// first) the methods to control them ("mute", "unmute",
|
||||
// "pauseVideo" and "resumeVideo") act on all the streams, it is not
|
||||
// possible to control them individually. Also all local streams
|
||||
// are transmitted when a Peer is created, but if another local
|
||||
// stream is then added it will not be automatically added to the
|
||||
// Peer. As it is not well supported and there is also no need to
|
||||
// use several local streams for now it is assumed that only one
|
||||
// local stream will be active at the same time.
|
||||
this.set('localStream', localStream)
|
||||
|
||||
this._setInitialMediaState(configuration)
|
||||
},
|
||||
|
||||
_handleLocalStreamRequestFailed: function() {
|
||||
this.set('localStream', null)
|
||||
|
||||
this._setInitialMediaState({ audio: false, video: false })
|
||||
},
|
||||
|
||||
_setInitialMediaState: function(configuration) {
|
||||
if (configuration.audio !== false) {
|
||||
this.set('audioAvailable', true)
|
||||
if (this.get('audioEnabled')) {
|
||||
this.enableAudio()
|
||||
} else {
|
||||
this.disableAudio()
|
||||
}
|
||||
} else {
|
||||
this.set('audioEnabled', false)
|
||||
this.set('audioAvailable', false)
|
||||
}
|
||||
|
||||
if (configuration.video !== false) {
|
||||
this.set('videoAvailable', true)
|
||||
if (this.get('videoEnabled')) {
|
||||
this.enableVideo()
|
||||
} else {
|
||||
this.disableVideo()
|
||||
}
|
||||
} else {
|
||||
this.set('videoEnabled', false)
|
||||
this.set('videoAvailable', false)
|
||||
}
|
||||
},
|
||||
|
||||
_handleLocalStreamStopped: function(localStream) {
|
||||
if (this.get('localStream') !== localStream) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('localStream', null)
|
||||
},
|
||||
|
||||
_handleAudioOn: function() {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('audioEnabled', true)
|
||||
},
|
||||
|
||||
_handleAudioOff: function() {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('audioEnabled', false)
|
||||
},
|
||||
|
||||
_handleVolumeChange: function(currentVolume, volumeThreshold) {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('currentVolume', currentVolume)
|
||||
this.set('volumeThreshold', volumeThreshold)
|
||||
},
|
||||
|
||||
_handleSpeaking: function() {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('speaking', true)
|
||||
},
|
||||
|
||||
_handleStoppedSpeaking: function() {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('speaking', false)
|
||||
},
|
||||
|
||||
_handleSpeakingWhileMuted: function() {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('speakingWhileMuted', true)
|
||||
},
|
||||
|
||||
_handleStoppedSpeakingWhileMuted: function() {
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('speakingWhileMuted', false)
|
||||
},
|
||||
|
||||
_handleVideoOn: function() {
|
||||
if (!this.get('videoAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('videoEnabled', true)
|
||||
},
|
||||
|
||||
_handleVideoOff: function() {
|
||||
if (!this.get('videoAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this.set('videoEnabled', false)
|
||||
},
|
||||
|
||||
_handleLocalScreen: function(screen) {
|
||||
this.set('localScreen', screen)
|
||||
},
|
||||
|
||||
_handleLocalScreenStopped: function() {
|
||||
this.set('localScreen', null)
|
||||
},
|
||||
|
||||
enableAudio: function() {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
if (!this.get('audioAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this._webRtc.unmute()
|
||||
},
|
||||
|
||||
disableAudio: function() {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
if (!this.get('audioAvailable')) {
|
||||
// Ensure that the audio will be disabled once available.
|
||||
this.set('audioEnabled', false)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this._webRtc.mute()
|
||||
},
|
||||
|
||||
enableVideo: function() {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
if (!this.get('videoAvailable')) {
|
||||
return
|
||||
}
|
||||
|
||||
this._webRtc.resumeVideo()
|
||||
},
|
||||
|
||||
disableVideo: function() {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
if (!this.get('videoAvailable')) {
|
||||
// Ensure that the video will be disabled once available.
|
||||
this.set('videoEnabled', false)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this._webRtc.pauseVideo()
|
||||
},
|
||||
|
||||
shareScreen: function(mode, callback) {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
this._webRtc.shareScreen(mode, callback)
|
||||
},
|
||||
|
||||
stopSharingScreen: function() {
|
||||
if (!this._webRtc) {
|
||||
throw new Error('WebRtc not initialized yet')
|
||||
}
|
||||
|
||||
this._webRtc.stopScreenShare()
|
||||
},
|
||||
|
||||
}
|
Загрузка…
Ссылка в новой задаче