Implements support for events for the API. Adds toggleChat and toggleContactList commands. Renames filmStrip to toggleFilmStrip command. Fixes issues with removing the embedded Jitsi Meet.
This commit is contained in:
parent
007564a1e5
commit
a3d0050328
106
api_connector.js
106
api_connector.js
|
@ -21,7 +21,30 @@ var APIConnector = (function () {
|
|||
displayName: VideoLayout.inputDisplayNameHandler,
|
||||
muteAudio: toggleAudio,
|
||||
muteVideo: toggleVideo,
|
||||
filmStrip: BottomToolbar.toggleFilmStrip
|
||||
toggleFilmStrip: BottomToolbar.toggleFilmStrip,
|
||||
toggleChat: BottomToolbar.toggleChat,
|
||||
toggleContactList: BottomToolbar.toggleContactList
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Maps the supported events and their status
|
||||
* (true it the event is enabled and false if it is disabled)
|
||||
* @type {{
|
||||
* incommingMessage: boolean,
|
||||
* outgoingMessage: boolean,
|
||||
* displayNameChange: boolean,
|
||||
* participantJoined: boolean,
|
||||
* participantLeft: boolean
|
||||
* }}
|
||||
*/
|
||||
var events =
|
||||
{
|
||||
incommingMessage: false,
|
||||
outgoingMessage:false,
|
||||
displayNameChange: false,
|
||||
participantJoined: false,
|
||||
participantLeft: false
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -51,7 +74,7 @@ var APIConnector = (function () {
|
|||
{
|
||||
window.attachEvent('onmessage', APIConnector.processMessage);
|
||||
}
|
||||
APIConnector.sendMessage({loaded: true});
|
||||
APIConnector.sendMessage({type: "system", loaded: true});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -72,12 +95,91 @@ var APIConnector = (function () {
|
|||
try {
|
||||
message = JSON.parse(event.data);
|
||||
} catch (e) {}
|
||||
|
||||
if(!message.type)
|
||||
return;
|
||||
switch (message.type)
|
||||
{
|
||||
case "command":
|
||||
APIConnector.processCommand(message);
|
||||
break;
|
||||
case "event":
|
||||
APIConnector.processEvent(message);
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown type of the message");
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes commands from external applicaiton.
|
||||
* @param message the object with the command
|
||||
*/
|
||||
APIConnector.processCommand = function (message)
|
||||
{
|
||||
if(message.action != "execute")
|
||||
{
|
||||
console.error("Unknown action of the message");
|
||||
return;
|
||||
}
|
||||
for(var key in message)
|
||||
{
|
||||
if(commands[key])
|
||||
commands[key].apply(null, message[key]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes events objects from external applications
|
||||
* @param event the event
|
||||
*/
|
||||
APIConnector.processEvent = function (event) {
|
||||
if(!event.action)
|
||||
{
|
||||
console.error("Event with no action is received.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(event.action)
|
||||
{
|
||||
case "add":
|
||||
for(var i = 0; i < event.events.length; i++)
|
||||
{
|
||||
events[event.events[i]] = true;
|
||||
}
|
||||
break;
|
||||
case "remove":
|
||||
for(var i = 0; i < event.events.length; i++)
|
||||
{
|
||||
events[event.events[i]] = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown action for event.");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether the event is enabled ot not.
|
||||
* @param name the name of the event.
|
||||
* @returns {*}
|
||||
*/
|
||||
APIConnector.isEventEnabled = function (name) {
|
||||
return events[name];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends event object to the external application that has been subscribed
|
||||
* for that event.
|
||||
* @param name the name event
|
||||
* @param object data associated with the event
|
||||
*/
|
||||
APIConnector.triggerEvent = function (name, object) {
|
||||
APIConnector.sendMessage({
|
||||
type: "event", action: "result", event: name, result: object});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
10
app.js
10
app.js
|
@ -698,6 +698,11 @@ $(document).bind('entered.muc', function (event, jid, info, pres) {
|
|||
// Add Peer's container
|
||||
VideoLayout.ensurePeerContainerExists(jid);
|
||||
|
||||
if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantJoined"))
|
||||
{
|
||||
APIConnector.triggerEvent("participantJoined",{jid: jid});
|
||||
}
|
||||
|
||||
if (focus !== null) {
|
||||
// FIXME: this should prepare the video
|
||||
if (focus.confid === null) {
|
||||
|
@ -734,6 +739,11 @@ $(document).bind('left.muc', function (event, jid) {
|
|||
}
|
||||
}, 10);
|
||||
|
||||
if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantLeft"))
|
||||
{
|
||||
APIConnector.triggerEvent("participantLeft",{jid: jid});
|
||||
}
|
||||
|
||||
// Unlock large video
|
||||
if (focusedVideoSrc)
|
||||
{
|
||||
|
|
93
doc/api.md
93
doc/api.md
|
@ -33,6 +33,7 @@ Controlling embedded Jitsi Meet Conference
|
|||
=========
|
||||
|
||||
You can control the embedded Jitsi Meet conference using the JitsiMeetExternalAPI object.
|
||||
|
||||
You can send command to Jitsi Meet conference using ```executeCommand```.
|
||||
```
|
||||
api.executeCommand(command, arguments)
|
||||
|
@ -56,10 +57,18 @@ api.executeCommand('muteAudio', [])
|
|||
```
|
||||
api.executeCommand('muteVideo', [])
|
||||
```
|
||||
* **filmStrip** - hides / shows the film strip. No arguments are required.
|
||||
* **toggleFilmStrip** - hides / shows the film strip. No arguments are required.
|
||||
```
|
||||
api.executeCommand('filmStrip', [])
|
||||
```
|
||||
* **toggleChat** - hides / shows the chat. No arguments are required.
|
||||
```
|
||||
api.executeCommand('toggleChat', [])
|
||||
```
|
||||
* **toggleContactList** - hides / shows the contact list. No arguments are required.
|
||||
```
|
||||
api.executeCommand('toggleContactList', [])
|
||||
```
|
||||
|
||||
You can also execute multiple commands using the method ```executeCommands```.
|
||||
```
|
||||
|
@ -72,7 +81,87 @@ commands.
|
|||
api.executeCommands({displayName: ['nickname'], muteAudio: []});
|
||||
```
|
||||
|
||||
You can also remove the embedded Jitsi Meet Conference with the following code:
|
||||
You can add event listeners to the embedded Jitsi Meet using ```addEventListener``` method.
|
||||
```
|
||||
api.addEventListener(event, listener)
|
||||
```
|
||||
The ```event``` parameter is String object with the name of the event.
|
||||
The ```listener``` paramenter is Function object with one argument that will be notified when the event occurs
|
||||
with data related to the event.
|
||||
|
||||
Currently we support the following events:
|
||||
|
||||
* **incommingMessage** - event notifications about incomming
|
||||
messages. The listener will receive object with the following structure:
|
||||
```
|
||||
{
|
||||
"from": from,//JID of the user that sent the message
|
||||
"nick": nick,//the nickname of the user that sent the message
|
||||
"message": txt//the text of the message
|
||||
}
|
||||
```
|
||||
* **outgoingMessage** - event notifications about outgoing
|
||||
messages. The listener will receive object with the following structure:
|
||||
```
|
||||
{
|
||||
"message": txt//the text of the message
|
||||
}
|
||||
```
|
||||
* **displayNameChanged** - event notifications about display name
|
||||
change. The listener will receive object with the following structure:
|
||||
```
|
||||
{
|
||||
jid: jid,//the JID of the participant that changed his display name
|
||||
displayname: displayName //the new display name
|
||||
}
|
||||
```
|
||||
* **participantJoined** - event notifications about new participant.
|
||||
The listener will receive object with the following structure:
|
||||
```
|
||||
{
|
||||
jid: jid //the jid of the participant
|
||||
}
|
||||
```
|
||||
* **participantLeft** - event notifications about participant that left room.
|
||||
The listener will receive object with the following structure:
|
||||
```
|
||||
{
|
||||
jid: jid //the jid of the participant
|
||||
}
|
||||
```
|
||||
|
||||
You can also add multiple event listeners by using ```addEventListeners```.
|
||||
This method requires one argument of type Object. The object argument must
|
||||
have keys with the names of the events and values the listeners of the events.
|
||||
|
||||
```
|
||||
function incommingMessageListener(object)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
function outgoingMessageListener(object)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
api.addEventListeners({
|
||||
incommingMessage: incommingMessageListener,
|
||||
outgoingMessage: outgoingMessageListener})
|
||||
```
|
||||
|
||||
If you want to remove a listener you can use ```removeEventListener``` method with argument the name of the event.
|
||||
```
|
||||
api.removeEventListener("incommingMessage");
|
||||
```
|
||||
|
||||
If you want to remove more than one event you can use ```removeEventListeners``` method with argument
|
||||
array with the names of the events.
|
||||
```
|
||||
api.removeEventListeners(["incommingMessage", "outgoingMessageListener"]);
|
||||
```
|
||||
|
||||
You can remove the embedded Jitsi Meet Conference with the following code:
|
||||
```
|
||||
api.dispose()
|
||||
```
|
||||
|
|
178
external_api.js
178
external_api.js
|
@ -48,7 +48,7 @@ var JitsiMeetExternalAPI = (function()
|
|||
this.iframeHolder.style.width = width + "px";
|
||||
this.iframeHolder.style.height = height + "px";
|
||||
this.frameName = "jitsiConferenceFrame" + JitsiMeetExternalAPI.id;
|
||||
this.url = "https://" + domain + "/";
|
||||
this.url = "http://" + domain + "/";
|
||||
if(room_name)
|
||||
this.url += room_name;
|
||||
this.url += "#external";
|
||||
|
@ -57,12 +57,16 @@ var JitsiMeetExternalAPI = (function()
|
|||
this.frame = document.createElement("iframe");
|
||||
this.frame.src = this.url;
|
||||
this.frame.name = this.frameName;
|
||||
this.frame.id = this.frameName;
|
||||
this.frame.width = "100%";
|
||||
this.frame.height = "100%";
|
||||
this.frame.setAttribute("allowFullScreen","true");
|
||||
this.frame = this.iframeHolder.appendChild(this.frame);
|
||||
|
||||
|
||||
this.frameLoaded = false;
|
||||
this.initialCommands = [];
|
||||
this.eventHandlers = {};
|
||||
this.initListeners();
|
||||
}
|
||||
|
||||
|
@ -108,7 +112,7 @@ var JitsiMeetExternalAPI = (function()
|
|||
var argumentsArray = argumentsList;
|
||||
if(!argumentsArray)
|
||||
argumentsArray = [];
|
||||
var object = {};
|
||||
var object = {type: "command", action: "execute"};
|
||||
object[name] = argumentsArray;
|
||||
this.sendMessage(object);
|
||||
};
|
||||
|
@ -125,9 +129,147 @@ var JitsiMeetExternalAPI = (function()
|
|||
* arguments for the command.
|
||||
*/
|
||||
JitsiMeetExternalAPI.prototype.executeCommands = function (object) {
|
||||
object.type = "command";
|
||||
object.action = "execute";
|
||||
this.sendMessage(object);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds event listeners to Meet Jitsi. The object key should be the name of the
|
||||
* event and value - the listener.
|
||||
* Currently we support the following
|
||||
* events:
|
||||
* incommingMessage - receives event notifications about incomming
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* "from": from,//JID of the user that sent the message
|
||||
* "nick": nick,//the nickname of the user that sent the message
|
||||
* "message": txt//the text of the message
|
||||
* }}
|
||||
* outgoingMessage - receives event notifications about outgoing
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* "message": txt//the text of the message
|
||||
* }}
|
||||
* displayNameChanged - receives event notifications about display name
|
||||
* change. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid,//the JID of the participant that changed his display name
|
||||
* displayname: displayName //the new display name
|
||||
* }}
|
||||
* participantJoined - receives event notifications about new participant.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid //the jid of the participant
|
||||
* }}
|
||||
* participantLeft - receives event notifications about participant that left room.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid //the jid of the participant
|
||||
* }}
|
||||
* @param object
|
||||
*/
|
||||
JitsiMeetExternalAPI.prototype.addEventListeners
|
||||
= function (object)
|
||||
{
|
||||
|
||||
var message = {type: "event", action: "add", events: []};
|
||||
for(var i in object)
|
||||
{
|
||||
message.events.push(i);
|
||||
this.eventHandlers[i] = object[i];
|
||||
}
|
||||
this.sendMessage(message);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds event listeners to Meet Jitsi. Currently we support the following
|
||||
* events:
|
||||
* incommingMessage - receives event notifications about incomming
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* "from": from,//JID of the user that sent the message
|
||||
* "nick": nick,//the nickname of the user that sent the message
|
||||
* "message": txt//the text of the message
|
||||
* }}
|
||||
* outgoingMessage - receives event notifications about outgoing
|
||||
* messages. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* "message": txt//the text of the message
|
||||
* }}
|
||||
* displayNameChanged - receives event notifications about display name
|
||||
* change. The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid,//the JID of the participant that changed his display name
|
||||
* displayname: displayName //the new display name
|
||||
* }}
|
||||
* participantJoined - receives event notifications about new participant.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid //the jid of the participant
|
||||
* }}
|
||||
* participantLeft - receives event notifications about participant that left room.
|
||||
* The listener will receive object with the following structure:
|
||||
* {{
|
||||
* jid: jid //the jid of the participant
|
||||
* }}
|
||||
* @param event the name of the event
|
||||
* @param listener the listener
|
||||
*/
|
||||
JitsiMeetExternalAPI.prototype.addEventListener
|
||||
= function (event, listener)
|
||||
{
|
||||
|
||||
var message = {type: "event", action: "add", events: [event]};
|
||||
this.eventHandlers[event] = listener;
|
||||
this.sendMessage(message);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes event listener.
|
||||
* @param event the name of the event.
|
||||
*/
|
||||
JitsiMeetExternalAPI.prototype.removeEventListener
|
||||
= function (event)
|
||||
{
|
||||
if(!this.eventHandlers[event])
|
||||
{
|
||||
console.error("The event " + event + " is not registered.");
|
||||
return;
|
||||
}
|
||||
var message = {type: "event", action: "remove", events: [event]};
|
||||
delete this.eventHandlers[event];
|
||||
this.sendMessage(message);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes event listeners.
|
||||
* @param events array with the names of the events.
|
||||
*/
|
||||
JitsiMeetExternalAPI.prototype.removeEventListeners
|
||||
= function (events)
|
||||
{
|
||||
var eventsArray = [];
|
||||
for(var i = 0; i < events.length; i++)
|
||||
{
|
||||
var event = events[i];
|
||||
if(!this.eventHandlers[event])
|
||||
{
|
||||
console.error("The event " + event + " is not registered.");
|
||||
continue;
|
||||
}
|
||||
delete this.eventHandlers[event];
|
||||
eventsArray.push(event);
|
||||
}
|
||||
|
||||
if(eventsArray.length > 0)
|
||||
{
|
||||
this.sendMessage(
|
||||
{type: "event", action: "remove", events: eventsArray});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes message events sent from Jitsi Meet
|
||||
* @param event the event
|
||||
|
@ -138,10 +280,33 @@ var JitsiMeetExternalAPI = (function()
|
|||
try {
|
||||
message = JSON.parse(event.data);
|
||||
} catch (e) {}
|
||||
|
||||
if(!message.type) {
|
||||
console.error("Message without type is received.");
|
||||
return;
|
||||
}
|
||||
switch (message.type)
|
||||
{
|
||||
case "system":
|
||||
if(message.loaded)
|
||||
{
|
||||
this.onFrameLoaded();
|
||||
}
|
||||
break;
|
||||
case "event":
|
||||
if(message.action != "result" ||
|
||||
!message.event || !this.eventHandlers[message.event])
|
||||
{
|
||||
console.warn("The received event cannot be parsed.");
|
||||
return;
|
||||
}
|
||||
this.eventHandlers[message.event](message.result);
|
||||
break;
|
||||
default :
|
||||
console.error("Unknown message type.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -191,7 +356,14 @@ var JitsiMeetExternalAPI = (function()
|
|||
window.detachEvent('onmessage',
|
||||
this.eventListener);
|
||||
}
|
||||
this.iframeHolder.parentNode.removeChild(this.iframeHolder);
|
||||
var frame = document.getElementById(this.frameName);
|
||||
if(frame)
|
||||
frame.src = 'about:blank';
|
||||
var self = this;
|
||||
window.setTimeout(function () {
|
||||
self.iframeHolder.removeChild(self.frame);
|
||||
self.iframeHolder.parentNode.removeChild(self.iframeHolder);
|
||||
}, 10);
|
||||
};
|
||||
|
||||
return JitsiMeetExternalAPI;
|
||||
|
|
|
@ -30,11 +30,11 @@
|
|||
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
|
||||
<script src="interface_config.js?v=2"></script>
|
||||
<script src="brand.js?v=1"></script>
|
||||
<script src="muc.js?v=15"></script><!-- simple MUC library -->
|
||||
<script src="muc.js?v=16"></script><!-- simple MUC library -->
|
||||
<script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
|
||||
<script src="desktopsharing.js?v=3"></script><!-- desktop sharing -->
|
||||
<script src="data_channels.js?v=3"></script><!-- data channels -->
|
||||
<script src="app.js?v=18"></script><!-- application logic -->
|
||||
<script src="app.js?v=19"></script><!-- application logic -->
|
||||
<script src="commands.js?v=1"></script><!-- application logic -->
|
||||
<script src="chat.js?v=13"></script><!-- chat logic -->
|
||||
<script src="contact_list.js?v=5"></script><!-- contact list logic -->
|
||||
|
@ -47,7 +47,7 @@
|
|||
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
|
||||
<script src="rtp_sts.js?v=4"></script><!-- RTP stats processing -->
|
||||
<script src="local_sts.js?v=2"></script><!-- Local stats processing -->
|
||||
<script src="videolayout.js?v=22"></script><!-- video ui -->
|
||||
<script src="videolayout.js?v=23"></script><!-- video ui -->
|
||||
<script src="connectionquality.js?v=1"></script>
|
||||
<script src="toolbar.js?v=6"></script><!-- toolbar ui -->
|
||||
<script src="toolbar_toggler.js?v=2"></script>
|
||||
|
@ -60,7 +60,7 @@
|
|||
<script src="tracking.js?v=1"></script><!-- tracking -->
|
||||
<script src="jitsipopover.js?v=3"></script>
|
||||
<script src="message_handler.js?v=1"></script>
|
||||
<script src="api_connector.js?v=1"></script>
|
||||
<script src="api_connector.js?v=2"></script>
|
||||
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="css/font.css?v=5"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=28"/>
|
||||
|
|
11
muc.js
11
muc.js
|
@ -201,6 +201,10 @@ Strophe.addConnectionPlugin('emuc', {
|
|||
msg.c('nick', {xmlns: 'http://jabber.org/protocol/nick'}).t(nickname).up().up();
|
||||
}
|
||||
this.connection.send(msg);
|
||||
if(APIConnector.isEnabled() && APIConnector.isEventEnabled("outgoingMessage"))
|
||||
{
|
||||
APIConnector.triggerEvent("outgoingMessage", {"message": body});
|
||||
}
|
||||
},
|
||||
setSubject: function (subject){
|
||||
var msg = $msg({to: this.roomjid, type: 'groupchat'});
|
||||
|
@ -234,8 +238,13 @@ Strophe.addConnectionPlugin('emuc', {
|
|||
|
||||
if (txt) {
|
||||
console.log('chat', nick, txt);
|
||||
|
||||
Chat.updateChatConversation(from, nick, txt);
|
||||
if(APIConnector.isEnabled() && APIConnector.isEventEnabled("incommingMessage"))
|
||||
{
|
||||
if(from != this.myroomjid)
|
||||
APIConnector.triggerEvent("incommingMessage",
|
||||
{"from": from, "nick": nick, "message": txt});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
|
@ -1274,18 +1274,28 @@ var VideoLayout = (function (my) {
|
|||
*/
|
||||
$(document).bind('displaynamechanged',
|
||||
function (event, jid, displayName, status) {
|
||||
var name = null;
|
||||
if (jid === 'localVideoContainer'
|
||||
|| jid === connection.emuc.myroomjid) {
|
||||
name = nickname;
|
||||
setDisplayName('localVideoContainer',
|
||||
displayName);
|
||||
} else {
|
||||
VideoLayout.ensurePeerContainerExists(jid);
|
||||
|
||||
name = $('#participant_' + Strophe.getResourceFromJid(jid) + "_name").text();
|
||||
setDisplayName(
|
||||
'participant_' + Strophe.getResourceFromJid(jid),
|
||||
displayName,
|
||||
status);
|
||||
}
|
||||
|
||||
if(APIConnector.isEnabled() && APIConnector.isEventEnabled("displayNameChange"))
|
||||
{
|
||||
if(jid === 'localVideoContainer')
|
||||
jid = connection.emuc.myroomjid;
|
||||
if(!name || name != displayName)
|
||||
APIConnector.triggerEvent("displayNameChange",{jid: jid, displayname: displayName});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue