diff --git a/app.js b/app.js
index f7ac1bd53..60a306387 100644
--- a/app.js
+++ b/app.js
@@ -8,6 +8,7 @@ var nickname = null;
var sharedKey = '';
var recordingToken ='';
var roomUrl = null;
+var roomName = null;
var ssrc2jid = {};
/**
* The stats collector that process stats data and triggers updates to app.js.
@@ -182,7 +183,9 @@ function doJoin() {
}
}
- roomjid = roomnode + '@' + config.hosts.muc;
+ roomName = roomnode + '@' + config.hosts.muc;
+
+ roomjid = roomName;
if (config.useNicks) {
var nick = window.prompt('Your nickname (optional)');
@@ -631,9 +634,15 @@ $(document).bind('joined.muc', function (event, jid, info) {
focus.setEndpointDisplayName(connection.emuc.myroomjid,
nickname);
}
+ Toolbar.showSipCallButton(true);
Toolbar.showRecordingButton(false);
}
+ if (!focus)
+ {
+ Toolbar.showSipCallButton(false);
+ }
+
if (focus && config.etherpad_base) {
Etherpad.init();
}
@@ -714,6 +723,8 @@ $(document).bind('left.muc', function (event, jid) {
nickname);
}
+ Toolbar.showSipCallButton(true);
+
if (Object.keys(connection.emuc.members).length > 0) {
focus.makeConference(Object.keys(connection.emuc.members));
Toolbar.showRecordingButton(true);
@@ -730,6 +741,7 @@ $(document).bind('left.muc', function (event, jid) {
focus.setEndpointDisplayName(connection.emuc.myroomjid,
nickname);
}
+ Toolbar.showSipCallButton(true);
Toolbar.showRecordingButton(false);
}
if (connection.emuc.getPrezi(jid)) {
@@ -781,7 +793,7 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
VideoLayout.ensurePeerContainerExists(jid);
VideoLayout.setDisplayName(
'participant_' + Strophe.getResourceFromJid(jid),
- info.displayName);
+ info.displayName, info.status);
}
if (focus !== null && info.displayName !== null) {
@@ -1279,3 +1291,32 @@ $(document).bind('fatalError.jingle',
"Your browser version is too old. Please update and try again...");
}
);
+
+function callSipButtonClicked()
+{
+ $.prompt('
Enter SIP number
' +
+ '',
+ {
+ persistent: false,
+ buttons: { "Dial": true, "Cancel": false},
+ defaultButton: 2,
+ loaded: function (event)
+ {
+ document.getElementById('sipNumber').focus();
+ },
+ submit: function (e, v, m, f)
+ {
+ if (v)
+ {
+ var numberInput = document.getElementById('sipNumber');
+ if (numberInput.value)
+ {
+ connection.rayo.dial(
+ numberInput.value, 'fromnumber', roomName);
+ }
+ }
+ }
+ }
+ );
+}
diff --git a/config.js b/config.js
index 1074b03c7..f0fef9c2f 100644
--- a/config.js
+++ b/config.js
@@ -2,7 +2,8 @@ var config = {
hosts: {
domain: 'jitsi-meet.example.com',
muc: 'conference.jitsi-meet.example.com', // FIXME: use XEP-0030
- bridge: 'jitsi-videobridge.jitsi-meet.example.com' // FIXME: use XEP-0030
+ bridge: 'jitsi-videobridge.jitsi-meet.example.com', // FIXME: use XEP-0030
+ //call_control: 'callcontrol.jitsi-meet.example.com'
},
// getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; },
// useStunTurn: true, // use XEP-0215 to fetch STUN and TURN server
@@ -14,6 +15,7 @@ var config = {
minChromeExtVersion: '0.1', // Required version of Chrome extension
enableRtpStats: true, // Enables RTP stats processing
openSctp: true, // Toggle to enable/disable SCTP channels
+ //defaultSipNumber: '20669', //Default SIP number used in call dialog
// channelLastN: -1, // The default value of the channel attribute last-n.
// useRtcpMux: true,
enableRecording: false
diff --git a/css/font.css b/css/font.css
index 43bc19b47..b9ed14b00 100755
--- a/css/font.css
+++ b/css/font.css
@@ -71,6 +71,9 @@
.icon-share-doc:before {
content: "\e605";
}
+.icon-telephone:before {
+ content: "\e611";
+}
.icon-security-locked:before {
content: "\e607";
}
diff --git a/css/videolayout_default.css b/css/videolayout_default.css
index 3a33e0269..229ef6910 100644
--- a/css/videolayout_default.css
+++ b/css/videolayout_default.css
@@ -171,10 +171,31 @@
border-radius:20px;
}
+.videocontainer>span.status {
+ display: inline-block;
+ position: absolute;
+ color: #FFFFFF;
+ background: rgba(0,0,0,.7);
+ text-align: center;
+ text-overflow: ellipsis;
+ width: 70%;
+ height: 15%;
+ left: 15%;
+ bottom: 2%;
+ padding: 5px;
+ font-size: 10pt;
+ overflow: hidden;
+ white-space: nowrap;
+ z-index: 2;
+ border-radius:20px;
+}
+
+#localVideoContainer>span.status:hover,
#localVideoContainer>span.displayname:hover {
cursor: text;
}
+.videocontainer>span.status,
.videocontainer>span.displayname {
pointer-events: none;
}
@@ -187,6 +208,7 @@
pointer-events: auto !important;
}
+.videocontainer>a.status,
.videocontainer>a.displayname {
display: inline-block;
position: absolute;
diff --git a/index.html b/index.html
index 79d91363b..a86efcbd1 100644
--- a/index.html
+++ b/index.html
@@ -20,6 +20,7 @@
+
@@ -96,6 +97,11 @@
+
+
+
+
+
diff --git a/libs/rayo.js b/libs/rayo.js
new file mode 100644
index 000000000..e036c6f9a
--- /dev/null
+++ b/libs/rayo.js
@@ -0,0 +1,94 @@
+/* jshint -W117 */
+Strophe.addConnectionPlugin('rayo',
+ {
+ RAYO_XMLNS: 'urn:xmpp:rayo:1',
+ connection: null,
+ init: function (conn)
+ {
+ this.connection = conn;
+ if (this.connection.disco)
+ {
+ this.connection.disco.addFeature('urn:xmpp:rayo:client:1');
+ }
+
+ this.connection.addHandler(
+ this.onRayo.bind(this), this.RAYO_XMLNS, 'iq', 'set', null, null);
+ },
+ onRayo: function (iq)
+ {
+ console.info("Rayo IQ", iq);
+ },
+ dial: function (to, from, roomName)
+ {
+ var self = this;
+ var req = $iq(
+ {
+ type: 'set',
+ to: config.hosts.call_control
+ }
+ );
+ req.c('dial',
+ {
+ xmlns: this.RAYO_XMLNS,
+ to: to,
+ from: from
+ });
+ req.c('header',
+ {
+ name: 'JvbRoomName',
+ value: roomName
+ });
+
+ this.connection.sendIQ(
+ req,
+ function (result)
+ {
+ console.info('Dial result ', result);
+
+ var resource = $(result).find('ref').attr('uri');
+ this.call_resource = resource.substr('xmpp:'.length);
+ console.info(
+ "Received call resource: " + this.call_resource);
+ },
+ function (error)
+ {
+ console.info('Dial error ', error);
+ }
+ );
+ },
+ hang_up: function ()
+ {
+ if (!this.call_resource)
+ {
+ console.warn("No call in progress");
+ return;
+ }
+
+ var self = this;
+ var req = $iq(
+ {
+ type: 'set',
+ to: this.call_resource
+ }
+ );
+ req.c('hangup',
+ {
+ xmlns: this.RAYO_XMLNS
+ });
+
+ this.connection.sendIQ(
+ req,
+ function (result)
+ {
+ console.info('Hangup result ', result);
+ self.call_resource = null;
+ },
+ function (error)
+ {
+ console.info('Hangup error ', error);
+ self.call_resource = null;
+ }
+ );
+ }
+ }
+);
\ No newline at end of file
diff --git a/toolbar.js b/toolbar.js
index 870dfa47b..c5e79a011 100644
--- a/toolbar.js
+++ b/toolbar.js
@@ -303,5 +303,18 @@ var Toolbar = (function (my) {
$('#recordButton').toggleClass('active');
};
+ // Shows or hides SIP calls button
+ my.showSipCallButton = function (show)
+ {
+ if (config.hosts.call_control && show)
+ {
+ $('#sipCallButton').css({display: "inline"});
+ }
+ else
+ {
+ $('#sipCallButton').css({display: "none"});
+ }
+ };
+
return my;
}(Toolbar || {}));
diff --git a/videolayout.js b/videolayout.js
index 0c94799f3..5665efa3f 100644
--- a/videolayout.js
+++ b/videolayout.js
@@ -323,11 +323,35 @@ var VideoLayout = (function (my) {
/**
* Shows the display name for the given video.
*/
- my.setDisplayName = function(videoSpanId, displayName) {
+ my.setDisplayName = function(videoSpanId, displayName, statusMsg) {
var nameSpan = $('#' + videoSpanId + '>span.displayname');
var defaultLocalDisplayName = "Me";
var defaultRemoteDisplayName = "Speaker";
+ var statusSpan = $('#' + videoSpanId + '>span.status');
+ if (!statusSpan.length)
+ {
+ //Add status span
+ statusSpan = document.createElement('span');
+ statusSpan.className = 'status';
+ statusSpan.id = videoSpanId + '_status';
+ $('#' + videoSpanId)[0].appendChild(statusSpan);
+
+ statusSpan = $('#' + videoSpanId + '>span.status');
+ }
+
+ // Display status
+ if (statusMsg && statusMsg.length)
+ {
+ $('#' + videoSpanId + '_status').text(statusMsg);
+ statusSpan.get(0).setAttribute("style", "display:inline-block;");
+ }
+ else
+ {
+ // Hide
+ statusSpan.get(0).setAttribute("style", "display:none;");
+ }
+
// If we already have a display name for this video.
if (nameSpan.length > 0) {
var nameSpanElement = nameSpan.get(0);