/* global $, $iq, config, connection, focusMucJid, messageHandler, Toolbar, Util */ var Moderator = require("./moderator"); var recordingToken = null; var recordingEnabled; /** * Whether to use a jirecon component for recording, or use the videobridge * through COLIBRI. */ var useJirecon; /** * The ID of the jirecon recording session. Jirecon generates it when we * initially start recording, and it needs to be used in subsequent requests * to jirecon. */ var jireconRid = null; /** * The callback to update the recording button. Currently used from colibri * after receiving a pending status. */ var recordingStateChangeCallback = null; function setRecordingToken(token) { recordingToken = token; } function setRecordingJirecon(state, token, callback, connection) { if (state == recordingEnabled){ return; } var iq = $iq({to: config.hosts.jirecon, type: 'set'}) .c('recording', {xmlns: 'http://jitsi.org/protocol/jirecon', action: (state === 'on') ? 'start' : 'stop', mucjid: connection.emuc.roomjid}); if (state === 'off'){ iq.attrs({rid: jireconRid}); } console.log('Start recording'); connection.sendIQ( iq, function (result) { // TODO wait for an IQ with the real status, since this is // provisional? jireconRid = $(result).find('recording').attr('rid'); console.log('Recording ' + ((state === 'on') ? 'started' : 'stopped') + '(jirecon)' + result); recordingEnabled = state; if (state === 'off'){ jireconRid = null; } callback(state); }, function (error) { console.log('Failed to start recording, error: ', error); callback(recordingEnabled); }); } // Sends a COLIBRI message which enables or disables (according to 'state') // the recording on the bridge. Waits for the result IQ and calls 'callback' // with the new recording state, according to the IQ. function setRecordingColibri(state, token, callback, connection) { var elem = $iq({to: connection.emuc.focusMucJid, type: 'set'}); elem.c('conference', { xmlns: 'http://jitsi.org/protocol/colibri' }); elem.c('recording', {state: state, token: token}); connection.sendIQ(elem, function (result) { console.log('Set recording "', state, '". Result:', result); var recordingElem = $(result).find('>conference>recording'); var newState = recordingElem.attr('state'); recordingEnabled = newState; callback(newState); if (newState === 'pending' && !recordingStateChangeCallback) { recordingStateChangeCallback = callback; connection.addHandler(function(iq){ var state = $(iq).find('recording').attr('state'); if (state) recordingStateChangeCallback(state); }, 'http://jitsi.org/protocol/colibri', 'iq', null, null, null); } }, function (error) { console.warn(error); callback(recordingEnabled); } ); } function setRecording(state, token, callback, connection) { if (useJirecon){ setRecordingJirecon(state, token, callback, connection); } else { setRecordingColibri(state, token, callback, connection); } } var Recording = { init: function () { useJirecon = config.hosts && (typeof config.hosts.jirecon != "undefined"); }, toggleRecording: function (tokenEmptyCallback, recordingStateChangeCallback, connection) { if (!Moderator.isModerator()) { console.log( 'non-focus, or conference not yet organized:' + ' not enabling recording'); return; } var self = this; // Jirecon does not (currently) support a token. if (!recordingToken && !useJirecon) { tokenEmptyCallback(function (value) { setRecordingToken(value); self.toggleRecording(tokenEmptyCallback, recordingStateChangeCallback, connection); }); return; } var oldState = recordingEnabled; var newState = (oldState === 'off' || !oldState) ? 'on' : 'off'; setRecording(newState, recordingToken, function (state) { console.log("New recording state: ", state); if (state === oldState) { // FIXME: new focus: // this will not work when moderator changes // during active session. Then it will assume that // recording status has changed to true, but it might have // been already true(and we only received actual status from // the focus). // // SO we start with status null, so that it is initialized // here and will fail only after second click, so if invalid // token was used we have to press the button twice before // current status will be fetched and token will be reset. // // Reliable way would be to return authentication error. // Or status update when moderator connects. // Or we have to stop recording session when current // moderator leaves the room. // Failed to change, reset the token because it might // have been wrong setRecordingToken(null); } recordingStateChangeCallback(state); }, connection ); } }; module.exports = Recording;