2017-01-06 01:18:07 +00:00
|
|
|
/* global APP, JitsiMeetJS, interfaceConfig */
|
2017-01-19 21:13:05 +00:00
|
|
|
const logger = require("jitsi-meet-logger").getLogger(__filename);
|
2016-12-28 00:46:55 +00:00
|
|
|
import {DISCO_REMOTE_CONTROL_FEATURE, REMOTE_CONTROL_EVENT_TYPE, EVENT_TYPES,
|
|
|
|
PERMISSIONS_ACTIONS} from "../../service/remotecontrol/Constants";
|
|
|
|
import RemoteControlParticipant from "./RemoteControlParticipant";
|
2017-01-23 18:07:08 +00:00
|
|
|
import * as JitsiMeetConferenceEvents from '../../ConferenceEvents';
|
2016-12-20 22:15:13 +00:00
|
|
|
|
2016-12-09 23:15:04 +00:00
|
|
|
const ConferenceEvents = JitsiMeetJS.events.conference;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class represents the receiver party for a remote controller session.
|
|
|
|
* It handles "remote-control-event" events and sends them to the
|
|
|
|
* API module. From there the events can be received from wrapper application
|
|
|
|
* and executed.
|
|
|
|
*/
|
2016-12-28 00:46:55 +00:00
|
|
|
export default class Receiver extends RemoteControlParticipant {
|
2016-12-09 23:15:04 +00:00
|
|
|
/**
|
|
|
|
* Creates new instance.
|
|
|
|
* @constructor
|
|
|
|
*/
|
2016-12-20 22:15:13 +00:00
|
|
|
constructor() {
|
2016-12-28 00:46:55 +00:00
|
|
|
super();
|
|
|
|
this.controller = null;
|
|
|
|
this._remoteControlEventsListener
|
|
|
|
= this._onRemoteControlEvent.bind(this);
|
2017-01-06 01:18:07 +00:00
|
|
|
this._userLeftListener = this._onUserLeft.bind(this);
|
2017-01-23 18:07:08 +00:00
|
|
|
this._hangupListener = this._onHangup.bind(this);
|
2016-12-20 22:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enables / Disables the remote control
|
|
|
|
* @param {boolean} enabled the new state.
|
|
|
|
*/
|
|
|
|
enable(enabled) {
|
2017-01-23 21:01:54 +00:00
|
|
|
if(this.enabled === enabled) {
|
|
|
|
return;
|
2017-01-06 01:18:07 +00:00
|
|
|
}
|
2017-01-23 21:01:54 +00:00
|
|
|
this.enabled = enabled;
|
2017-01-06 01:18:07 +00:00
|
|
|
if(enabled === true) {
|
2017-01-19 21:13:05 +00:00
|
|
|
logger.log("Remote control receiver enabled.");
|
2016-12-20 22:15:13 +00:00
|
|
|
// Announce remote control support.
|
|
|
|
APP.connection.addFeature(DISCO_REMOTE_CONTROL_FEATURE, true);
|
|
|
|
APP.conference.addConferenceListener(
|
|
|
|
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
2016-12-28 00:46:55 +00:00
|
|
|
this._remoteControlEventsListener);
|
2017-01-23 18:07:08 +00:00
|
|
|
APP.conference.addListener(JitsiMeetConferenceEvents.BEFORE_HANGUP,
|
|
|
|
this._hangupListener);
|
2017-01-06 01:18:07 +00:00
|
|
|
} else {
|
2017-01-19 21:13:05 +00:00
|
|
|
logger.log("Remote control receiver disabled.");
|
2017-01-06 01:18:07 +00:00
|
|
|
this._stop(true);
|
|
|
|
APP.connection.removeFeature(DISCO_REMOTE_CONTROL_FEATURE);
|
|
|
|
APP.conference.removeConferenceListener(
|
|
|
|
ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
|
|
|
this._remoteControlEventsListener);
|
2017-01-23 18:07:08 +00:00
|
|
|
APP.conference.removeListener(
|
|
|
|
JitsiMeetConferenceEvents.BEFORE_HANGUP,
|
|
|
|
this._hangupListener);
|
2016-12-20 22:15:13 +00:00
|
|
|
}
|
2016-12-09 23:15:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes the listener for ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED
|
2017-01-06 01:18:07 +00:00
|
|
|
* events. Sends stop message to the wrapper application. Optionally
|
|
|
|
* displays dialog for informing the user that remote control session
|
|
|
|
* ended.
|
|
|
|
* @param {boolean} dontShowDialog - if true the dialog won't be displayed.
|
|
|
|
*/
|
|
|
|
_stop(dontShowDialog = false) {
|
|
|
|
if(!this.controller) {
|
|
|
|
return;
|
|
|
|
}
|
2017-01-19 21:13:05 +00:00
|
|
|
logger.log("Remote control receiver stop.");
|
2017-01-06 01:18:07 +00:00
|
|
|
this.controller = null;
|
|
|
|
APP.conference.removeConferenceListener(ConferenceEvents.USER_LEFT,
|
|
|
|
this._userLeftListener);
|
|
|
|
APP.API.sendRemoteControlEvent({
|
|
|
|
type: EVENT_TYPES.stop
|
|
|
|
});
|
|
|
|
if(!dontShowDialog) {
|
|
|
|
APP.UI.messageHandler.openMessageDialog(
|
|
|
|
"dialog.remoteControlTitle",
|
|
|
|
"dialog.remoteControlStopMessage"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calls this._stop() and sends stop message to the controller participant
|
2016-12-09 23:15:04 +00:00
|
|
|
*/
|
|
|
|
stop() {
|
2017-01-06 01:18:07 +00:00
|
|
|
if(!this.controller) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this._sendRemoteControlEvent(this.controller, {
|
2016-12-28 00:46:55 +00:00
|
|
|
type: EVENT_TYPES.stop
|
2017-01-06 01:18:07 +00:00
|
|
|
});
|
|
|
|
this._stop();
|
2016-12-09 23:15:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-18 00:16:18 +00:00
|
|
|
* Listens for data channel EndpointMessage events. Handles only events of
|
|
|
|
* type remote control. Sends "remote-control-event" events to the API
|
|
|
|
* module.
|
2016-12-09 23:15:04 +00:00
|
|
|
* @param {JitsiParticipant} participant the controller participant
|
2017-01-19 23:19:58 +00:00
|
|
|
* @param {Object} event EndpointMessage event from the data channels.
|
|
|
|
* @property {string} type property. The function process only events of
|
|
|
|
* type REMOTE_CONTROL_EVENT_TYPE
|
|
|
|
* @property {RemoteControlEvent} event - the remote control event.
|
2016-12-09 23:15:04 +00:00
|
|
|
*/
|
|
|
|
_onRemoteControlEvent(participant, event) {
|
2016-12-28 00:46:55 +00:00
|
|
|
if(this.enabled && event.type === REMOTE_CONTROL_EVENT_TYPE) {
|
|
|
|
const remoteControlEvent = event.event;
|
|
|
|
if(this.controller === null
|
|
|
|
&& remoteControlEvent.type === EVENT_TYPES.permissions
|
|
|
|
&& remoteControlEvent.action === PERMISSIONS_ACTIONS.request) {
|
|
|
|
remoteControlEvent.userId = participant.getId();
|
|
|
|
remoteControlEvent.userJID = participant.getJid();
|
2017-01-06 01:18:07 +00:00
|
|
|
remoteControlEvent.displayName = participant.getDisplayName()
|
|
|
|
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME;
|
|
|
|
remoteControlEvent.screenSharing
|
|
|
|
= APP.conference.isSharingScreen;
|
2016-12-28 00:46:55 +00:00
|
|
|
} else if(this.controller !== participant.getId()) {
|
|
|
|
return;
|
2017-01-06 01:18:07 +00:00
|
|
|
} else if(remoteControlEvent.type === EVENT_TYPES.stop) {
|
|
|
|
this._stop();
|
|
|
|
return;
|
2016-12-28 00:46:55 +00:00
|
|
|
}
|
|
|
|
APP.API.sendRemoteControlEvent(remoteControlEvent);
|
2017-01-19 21:13:05 +00:00
|
|
|
} else if(event.type === REMOTE_CONTROL_EVENT_TYPE) {
|
2017-01-23 20:58:45 +00:00
|
|
|
logger.log("Remote control event is ignored because remote "
|
2017-01-19 21:13:05 +00:00
|
|
|
+ "control is disabled", event);
|
2016-12-28 00:46:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles remote control permission events received from the API module.
|
|
|
|
* @param {String} userId the user id of the participant related to the
|
|
|
|
* event.
|
|
|
|
* @param {PERMISSIONS_ACTIONS} action the action related to the event.
|
|
|
|
*/
|
|
|
|
_onRemoteControlPermissionsEvent(userId, action) {
|
|
|
|
if(action === PERMISSIONS_ACTIONS.grant) {
|
2017-01-06 01:18:07 +00:00
|
|
|
APP.conference.addConferenceListener(ConferenceEvents.USER_LEFT,
|
|
|
|
this._userLeftListener);
|
2016-12-28 00:46:55 +00:00
|
|
|
this.controller = userId;
|
2017-01-23 20:58:45 +00:00
|
|
|
logger.log("Remote control permissions granted to: " + userId);
|
2017-01-06 01:18:07 +00:00
|
|
|
if(!APP.conference.isSharingScreen) {
|
|
|
|
APP.conference.toggleScreenSharing();
|
|
|
|
APP.conference.screenSharingPromise.then(() => {
|
|
|
|
if(APP.conference.isSharingScreen) {
|
|
|
|
this._sendRemoteControlEvent(userId, {
|
|
|
|
type: EVENT_TYPES.permissions,
|
|
|
|
action: action
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this._sendRemoteControlEvent(userId, {
|
|
|
|
type: EVENT_TYPES.permissions,
|
|
|
|
action: PERMISSIONS_ACTIONS.error
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}).catch(() => {
|
|
|
|
this._sendRemoteControlEvent(userId, {
|
|
|
|
type: EVENT_TYPES.permissions,
|
|
|
|
action: PERMISSIONS_ACTIONS.error
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2016-12-28 00:46:55 +00:00
|
|
|
}
|
|
|
|
this._sendRemoteControlEvent(userId, {
|
|
|
|
type: EVENT_TYPES.permissions,
|
|
|
|
action: action
|
|
|
|
});
|
2016-12-09 23:15:04 +00:00
|
|
|
}
|
2017-01-06 01:18:07 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calls the stop method if the other side have left.
|
|
|
|
* @param {string} id - the user id for the participant that have left
|
|
|
|
*/
|
|
|
|
_onUserLeft(id) {
|
|
|
|
if(this.controller === id) {
|
|
|
|
this._stop();
|
|
|
|
}
|
|
|
|
}
|
2017-01-23 18:07:08 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles hangup events. Disables the receiver.
|
|
|
|
*/
|
|
|
|
_onHangup() {
|
|
|
|
this.enable(false);
|
|
|
|
}
|
2016-12-09 23:15:04 +00:00
|
|
|
}
|