| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 | /* global $, $iq, config, connection, focusMucJid, messageHandler, Moderator,
   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 = (typeof config.hosts.jirecon != "undefined");
/**
 * 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;
function setRecordingToken(token) {
    recordingToken = token;
}
function setRecording(state, token, callback, connection) {
    if (useJirecon){
        setRecordingJirecon(state, token, callback, connection);
    } else {
        setRecordingColibri(state, token, callback, connection);
    }
}
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 ? 'start' : 'stop',
            mucjid: connection.emuc.roomjid});
    if (!state){
        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 ? 'started' : 'stopped') +
                '(jirecon)' + result);
            recordingEnabled = state;
            if (!state){
                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 = ('true' === recordingElem.attr('state'));
            recordingEnabled = newState;
            callback(newState);
        },
        function (error) {
            console.warn(error);
            callback(recordingEnabled);
        }
    );
}
var Recording = {
    toggleRecording: function (tokenEmptyCallback,
                               startingCallback, startedCallback, 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,
                    startingCallback, startedCallback, connection);
            });
            return;
        }
        var oldState = recordingEnabled;
        startingCallback(!oldState);
        setRecording(!oldState,
            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);
                }
                startedCallback(state);
            },
            connection
        );
    }
}
module.exports = Recording;
 |