diff --git a/conference.js b/conference.js index e48f28814..371d5e868 100644 --- a/conference.js +++ b/conference.js @@ -7,6 +7,8 @@ import AuthHandler from './modules/UI/authentication/AuthHandler'; import ConnectionQuality from './modules/connectionquality/connectionquality'; +import Recorder from './modules/recorder/Recorder'; + import CQEvents from './service/connectionquality/CQEvents'; import UIEvents from './service/UI/UIEvents'; @@ -346,6 +348,9 @@ export default { devices => APP.UI.onAvailableDevicesChanged(devices) ); } + if (config.iAmRecorder) + this.recorder = new Recorder(); + // XXX The API will take care of disconnecting from the XMPP server // (and, thus, leaving the room) on unload. return new Promise((resolve, reject) => { @@ -532,14 +537,14 @@ export default { * @param command {String} the name of the command * @param handler {Function} handler for the command */ - addCommandListener () { + addCommandListener () { room.addCommandListener.apply(room, arguments); }, /** * Removes command. * @param name {String} the name of the command. */ - removeCommand () { + removeCommand () { room.removeCommand.apply(room, arguments); }, /** @@ -547,7 +552,7 @@ export default { * @param name {String} the name of the command. * @param values {Object} with keys and values that will be sent. */ - sendCommand () { + sendCommand () { room.sendCommand.apply(room, arguments); }, /** @@ -555,7 +560,7 @@ export default { * @param name {String} the name of the command. * @param values {Object} with keys and values that will be sent. */ - sendCommandOnce () { + sendCommandOnce () { room.sendCommandOnce.apply(room, arguments); } }, @@ -878,10 +883,6 @@ export default { room.on(ConferenceEvents.RECORDER_STATE_CHANGED, (status, error) => { console.log("Received recorder status change: ", status, error); - if(status == "error") { - console.error(error); - return; - } APP.UI.updateRecordingState(status); }); diff --git a/lang/main.json b/lang/main.json index 0e5233b05..a7561290b 100644 --- a/lang/main.json +++ b/lang/main.json @@ -268,7 +268,8 @@ "on": "Recording", "off": "Recording stopped", "failedToStart": "Recording failed to start", - "buttonTooltip": "Start / stop recording" + "buttonTooltip": "Start / stop recording", + "error": "Recording failed. Please try again." }, "liveStreaming": { @@ -278,6 +279,7 @@ "unavailable": "The live streaming service is currently unavailable. Please try again later.", "failedToStart": "Live streaming failed to start", "buttonTooltip": "Start / stop live stream", - "streamIdRequired": "Please fill in the stream id in order to launch the live streaming." + "streamIdRequired": "Please fill in the stream id in order to launch the live streaming.", + "error": "Live streaming failed. Please try again" } } diff --git a/modules/UI/recording/Recording.js b/modules/UI/recording/Recording.js index 9d1511ab2..1d5f75f3f 100644 --- a/modules/UI/recording/Recording.js +++ b/modules/UI/recording/Recording.js @@ -205,7 +205,8 @@ var Status = { OFF: "off", AVAILABLE: "available", UNAVAILABLE: "unavailable", - PENDING: "pending" + PENDING: "pending", + ERROR: "error" }; /** @@ -248,6 +249,7 @@ var Recording = { this.recordingOffKey = "liveStreaming.off"; this.recordingPendingKey = "liveStreaming.pending"; this.failedToStartKey = "liveStreaming.failedToStart"; + this.recordingErrorKey = "liveStreaming.error"; this.recordingButtonTooltip = "liveStreaming.buttonTooltip"; } else { @@ -256,6 +258,7 @@ var Recording = { this.recordingOffKey = "recording.off"; this.recordingPendingKey = "recording.pending"; this.failedToStartKey = "recording.failedToStart"; + this.recordingErrorKey = "recording.error"; this.recordingButtonTooltip = "recording.buttonTooltip"; } @@ -338,7 +341,6 @@ var Recording = { */ updateRecordingUI (recordingState) { let buttonSelector = $('#toolbar_button_record'); - let labelSelector = $('#recordingLabel'); // TODO: handle recording state=available if (recordingState === Status.ON) { @@ -346,12 +348,10 @@ var Recording = { buttonSelector.removeClass(this.baseClass); buttonSelector.addClass(this.baseClass + " active"); - labelSelector.attr("data-i18n", this.recordingOnKey); - moveToCorner(labelSelector, true, 3000); - labelSelector - .text(APP.translation.translateString(this.recordingOnKey)); - } else if (recordingState === Status.OFF - || recordingState === Status.UNAVAILABLE) { + this._updateStatusLabel(this.recordingOnKey, false); + } + else if (recordingState === Status.OFF + || recordingState === Status.UNAVAILABLE) { // We don't want to do any changes if this is // an availability change. @@ -362,15 +362,13 @@ var Recording = { buttonSelector.removeClass(this.baseClass + " active"); buttonSelector.addClass(this.baseClass); - moveToCorner(labelSelector, false); let messageKey; if (this.currentState === Status.PENDING) messageKey = this.failedToStartKey; else messageKey = this.recordingOffKey; - labelSelector.attr("data-i18n", messageKey); - labelSelector.text(APP.translation.translateString(messageKey)); + this._updateStatusLabel(messageKey, true); setTimeout(function(){ $('#recordingLabel').css({display: "none"}); @@ -381,16 +379,19 @@ var Recording = { buttonSelector.removeClass(this.baseClass + " active"); buttonSelector.addClass(this.baseClass); - moveToCorner(labelSelector, false); - labelSelector - .attr("data-i18n", this.recordingPendingKey); - labelSelector - .text(APP.translation.translateString( - this.recordingPendingKey)); + this._updateStatusLabel(this.recordingPendingKey, true); + } + else if (recordingState === Status.ERROR) { + buttonSelector.removeClass(this.baseClass + " active"); + buttonSelector.addClass(this.baseClass); + + this._updateStatusLabel(this.recordingErrorKey, true); } this.currentState = recordingState; + let labelSelector = $('#recordingLabel'); + // We don't show the label for available state. if (recordingState !== Status.AVAILABLE && !labelSelector.is(":visible")) @@ -404,6 +405,20 @@ var Recording = { this.eventEmitter.emit(UIEvents.RECORDING_TOGGLED, this.predefinedToken); } + }, + /** + * Updates the status label. + * @param textKey the text to show + * @param isCentered indicates if the label should be centered on the window + * or moved to the top right corner. + */ + _updateStatusLabel(textKey, isCentered) { + let labelSelector = $('#recordingLabel'); + + moveToCorner(labelSelector, !isCentered); + + labelSelector.attr("data-i18n", textKey); + labelSelector.text(APP.translation.translateString(textKey)); } }; diff --git a/modules/recorder/Recorder.js b/modules/recorder/Recorder.js new file mode 100644 index 000000000..2bc527c15 --- /dev/null +++ b/modules/recorder/Recorder.js @@ -0,0 +1,41 @@ +/* global APP, $, config */ + +/** + * The (name of the) command which transports the recorder info. + */ +const _USER_INFO_COMMAND = "userinfo"; + +/** + * The Recorder class is meant to take care of recorder related presence + * commands. + */ +class Recorder { + constructor() { + if (config.iAmRecorder) + this._sendRecorderInfo(); + } + + /** + * Sends the information that this is a recorder through the presence. + * @private + */ + _sendRecorderInfo() { + var commands = APP.conference.commands; + + // XXX The "Follow Me" command represents a snapshot of all states + // which are to be followed so don't forget to removeCommand before + // sendCommand! + commands.removeCommand(_USER_INFO_COMMAND); + var self = this; + commands.sendCommand( + _USER_INFO_COMMAND, + { + attributes: { + xmlns: 'http://jitsi.org/jitmeet/userinfo', + robot: true + } + }); + } +} + +export default Recorder; \ No newline at end of file