Commit 5cec4267 authored by Dele Olajide's avatar Dele Olajide Committed by dele

Jitsi Videobridge - Added screen/desktop sharing to ofmeet and candy

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13866 b35dd754-fafc-0310-a699-88a17e54d16e
parent 8f7385bf
......@@ -31,6 +31,29 @@
return results[1] || undefined;
};
function toggleFullScreen()
{
var videoElement = document.getElementById("largeVideo");
if (!document.mozFullScreen && !document.webkitFullScreen)
{
if (videoElement.mozRequestFullScreen) {
videoElement.mozRequestFullScreen();
} else {
videoElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}
} else {
if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else {
document.webkitCancelFullScreen();
}
}
}
$(document).ready(function() {
Candy.init('/http-bind/', {
core: { debug: false, websockets: true},
......@@ -59,11 +82,10 @@
CandyShop.Videobridge.init();
CandyShop.Fastpath.init();
Candy.Core.connect();
// for testing only
// Candy.Core.connect(username + "@" + window.location.hostname, password, username);
if (username)
Candy.Core.connect(username + "@" + window.location.hostname, password, username);
else
Candy.Core.connect();
});
</script>
......@@ -72,7 +94,7 @@
<div class="fade_line"></div>
<div id="candy"></div>
<div class="fade_line"></div>
<video id="largeVideo" autoplay oncontextmenu="return false;"></video>
<video id="largeVideo" onDblClick="toggleFullScreen();" autoplay oncontextmenu="return false;"></video>
<div id="remoteVideos">
<video id="localVideo" autoplay oncontextmenu="return false;" muted/>
</div>
......
......@@ -38,6 +38,13 @@ body{
#mic-control.muted {
background-image: url(mic_muted.png);
}
#screen-control {
background-image: url(desktop_off.png);
}
#screen-control.active {
background-image: url(desktop_on.png);
}
#remoteVideos {
display:block;
......
......@@ -14,6 +14,7 @@ CandyShop.Videobridge = (function(self, Candy, $) {
var room = null;
var previousRoom = null;
var videoOn = false;
var screenShare = false;
self.init = function()
{
......@@ -57,7 +58,8 @@ CandyShop.Videobridge = (function(self, Candy, $) {
var html = "";
html += '<li id="videobridge-control" data-tooltip="add or remove video"></li>';
html += '<li id="webcam-control" data-tooltip="mute/toggle video mute"></li>';
html += '<li id="mic-control" data-tooltip="toggle audio mute"></li>';
html += '<li id="mic-control" data-tooltip="toggle audio mute"></li>';
html += '<li id="screen-control" data-tooltip="toggle desktop screen share"></li>';
$('#chat-toolbar').prepend(html);
......@@ -92,12 +94,29 @@ CandyShop.Videobridge = (function(self, Candy, $) {
}
}
});
});
$('#largeVideo').click(function() {
$("#largeVideo").css("visibility", "hidden");
});
$('#screen-control').click(function() {
var videobridge = Strophe.getNodeFromJid(roomJid);
if (screenShare)
{
var screenDIV = document.getElementById("screenshare");
screenDIV.parentElement.removeChild(screenDIV);
$(this).removeClass('active');
} else {
var url = "../../publish.html?r=" + videobridge + "&screen=true";
//var url = "/ofmeet/publish.html?r=" + videobridge + "&screen=true";
$("body").append("<div id='screenshare'><iframe style='display:none' src='" + url + "'></iframe></div>");
$("#screen").addClass("fa-border");
$(this).addClass('active');
}
screenShare = !screenShare;
});
};
......@@ -186,7 +205,12 @@ CandyShop.Videobridge = (function(self, Candy, $) {
setTimeout(function()
{
if (window.RTC.rayo.pc) window.RTC.rayo.pc.close();
if (window.RTC.rayo.pc)
{
console.log("sendExpireCommand close peer conection");
window.RTC.rayo.pc.close();
window.RTC.rayo.pc = null;
}
}, 2000);
},
......@@ -338,7 +362,7 @@ CandyShop.Videobridge = (function(self, Candy, $) {
window.RTC.rayo.pc.onicecandidate = function(event)
{
//console.log('candidate', event.candidate);
console.log('candidate', event.candidate);
if (!event.candidate)
{
......
......@@ -26,6 +26,8 @@
<a href="http://community.igniterealtime.org/community/support/jitsi_videobridge_plugin" target="_blank"><div id="leftlogo"><nobr>OfMeet</nobr></div></a>
<a href="http://jitsi.org" target="_blank"><div id="rightlogo"></div></a>
<div id="toolbar">
<a class="button" onclick='toggleScreenShare();'><i id="screen" title="share/unshare desktop" class="fa fa-desktop fa-lg"></i></a>
<div class="header_button_separator"></div>
<a class="button" onclick='buttonClick("#mute", "fa fa-microphone fa-lg fa fa-microphone-slash fa-lg");toggleAudio();'><i id="mute" title="Mute / unmute" class="fa fa-microphone fa-lg"></i></a>
<div class="header_button_separator"></div>
<a class="button" onclick='buttonClick("#video", "fa fa-video-camera fa-lg fa fa-video-camera no-fa-video-camera fa-lg");toggleVideo();'><i id="video" title="Start / stop camera" class="fa fa-video-camera fa-lg"></i></a>
......@@ -45,6 +47,7 @@
<div id="remoteVideos">
<video id="localVideo" autoplay oncontextmenu="return false;" muted/>
</div>
<video id="screenVideo" autoplay oncontextmenu="return false;" muted style="display:block"/>
</div>
<div id="chatspace">
<div id="nickname">
......@@ -57,7 +60,6 @@
<div id="ofmeet"><div id="ofmeet-messaging"><div id="ofmeet-log"></div></div></div>
<textarea id="usermsg" class= "animated" placeholder='Enter text...' autofocus></textarea>
</div>
<script>
</script>
</body>
......
......@@ -894,7 +894,7 @@ public class PluginImpl implements Plugin, PropertyEventListener
iq.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
iq.setTo("jitsi-videobridge." + domainName);
String id = nickname + "-" + System.currentTimeMillis();
String id = "answer-" + nickname + "-" + System.currentTimeMillis();
ids.put(id, participant);
iq.setID(id);
......@@ -1004,7 +1004,7 @@ public class PluginImpl implements Plugin, PropertyEventListener
iq.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
iq.setTo("jitsi-videobridge." + domainName);
String id = nickname + "-" + System.currentTimeMillis();
String id = "offer-" + nickname + "-" + System.currentTimeMillis();
ids.put(id, participant);
iq.setID(id);
......@@ -1039,7 +1039,8 @@ public class PluginImpl implements Plugin, PropertyEventListener
iq.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
iq.setTo("jitsi-videobridge." + domainName);
String id = nickname + "-" + System.currentTimeMillis();
String id = "expire-" + nickname + "-" + System.currentTimeMillis();
ids.put(id, participant);
iq.setID(id);
Element conferenceIq = iq.setChildElement("conference", "http://jitsi.org/protocol/colibri");
......@@ -1286,13 +1287,17 @@ public class PluginImpl implements Plugin, PropertyEventListener
Participant participant = ids.remove(id);
String username = participant.getUser().toString();
if (users.containsKey(username) == false)
Log.info("FocusAgent response for user " + participant + " " + focusId + "\n" + conference);
if (id.startsWith("offer-") && users.containsKey(username) == false)
{
addUser(participant, conference);
}
Log.info("FocusAgent response for user " + participant + " " + focusId + "\n" + conference);
broadcastSSRC(participant);
if (id.startsWith("answer-"))
{
broadcastSSRC(participant);
}
} else Log.error("FocusAgent deliver cannot find iq owner " + id + "\n" + packet);
......
......@@ -5,6 +5,6 @@ var config = {
bridge: 'jitsi-videobridge.' + window.location.hostname // FIXME: use XEP-0030
},
useNicks: false,
useWebsockets: false,
useWebsockets: true,
bosh: window.location.protocol + "//" + window.location.host + '/http-bind/' // FIXME: use xep-0156 for that
};
......@@ -3,6 +3,7 @@ var roomjid;
var nickname = null;
var roomUrl = null;
var sharedKey = '';
var screenShare = false;
$(document).ready(function ()
{
......@@ -77,12 +78,17 @@ $(document).ready(function ()
{
console.log('connected');
connection.send($pres());
registerRayoEvents();
doJoin();
if (urlParam("screen"))
if (urlParam("screen"))
{
getConstraints(['screen']);
else
$("#screen").addClass("fa-border");
} else {
getConstraints(['audio', 'video'], '720');
$("#screen").removeClass("fa-border");
}
getUserMedia();
......@@ -113,7 +119,8 @@ $(document).bind('mediaready.rayo', function(event, stream)
document.getElementById('largeVideo').src = document.getElementById('localVideo').src;
console.log("mediaready.rayo");
doJoin();
registerRayoEvents();
});
$(document).bind('mediafailure.rayo', function(error) {
......@@ -180,31 +187,6 @@ $(document).bind('remotestreamadded.rayo', function(event, data, sid)
);
});
function registerRayoEvents()
{
connection.sendIQ($iq({to: connection.domain, type: 'set'}).c('colibri', {xmlns: 'urn:xmpp:rayo:colibri:1', action: 'register'}),
function (res) {
console.log('rayo colibri register set ok');
},
function (err) {
console.log('rayo colibri register got error', err);
}
);
}
function unregisterRayoEvents()
{
connection.sendIQ($iq({to: connection.domain, type: 'set'}).c('colibri', {xmlns: 'urn:xmpp:rayo:colibri:1', action: 'unregister'}),
function (res) {
console.log('rayo colibri unregister set ok');
},
function (err) {
console.log('rayo colibri unregister got error', err);
}
);
}
function setupRTC()
{
......@@ -217,7 +199,7 @@ function setupRTC()
rayo: {
channels: {},
confid: {},
pc: null,
pc: {},
addssrc: {},
localStream: null,
constraints: {audio: false, video: false}
......@@ -244,7 +226,7 @@ function setupRTC()
rayo: {
channels: {},
confid: {},
pc: null,
pc: {},
addssrc: {},
localStream: null,
constraints: {audio: false, video: false}
......@@ -462,7 +444,7 @@ function doJoin() {
}
connection.addHandler(rayoCallback, 'urn:xmpp:rayo:colibri:1');
connection.emuc.doJoin(myroomjid);
connection.emuc.doJoin(myroomjid);
}
function rayoCallback(presence)
......@@ -490,13 +472,12 @@ function rayoCallback(presence)
};
function removeSSRC(from, removesource)
{
console.log("removeSSRC input ssrc ", removesource);
var videobridge = $(removesource).attr('videobridge');
var sdp = new SDP(window.RTC.rayo.pc.remoteDescription.sdp);
var sdp = new SDP(window.RTC.rayo.pc[videobridge].remoteDescription.sdp);
console.log("removeSSRC unmodified SDP", videobridge);
......@@ -521,26 +502,29 @@ function removeSSRC(from, removesource)
//console.log("removeSSRC modified SDP", sdp.raw);
window.RTC.rayo.pc.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}
window.RTC.rayo.pc[videobridge].setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}
), function() {
console.log('modify ok');
console.log('removeSSRC modify ok');
}, function(error) {
console.log('handleSSRC modify failed');
console.log('removeSSRC modify failed');
});
};
function handleAddSSRC(from, addsource)
{
console.log("handleSSRC input ssrc ", addsource);
var videobridge = $(addsource).attr('videobridge');
var sdp = new SDP(window.RTC.rayo.pc.remoteDescription.sdp);
var sdp = new SDP(window.RTC.rayo.pc[videobridge].remoteDescription.sdp);
$(addsource).find('content').each(function()
{
var name = $(this).attr('name');
if (name == "audio") return;
var lines = '';
......@@ -566,10 +550,10 @@ function handleAddSSRC(from, addsource)
window.RTC.rayo.addssrc = true;
window.RTC.rayo.pc.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}
window.RTC.rayo.pc[videobridge].setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}
), function() {
console.log('modify ok', window.RTC.rayo.pc.signalingState);
console.log('handleAddSSRC modify ok', window.RTC.rayo.pc[videobridge].signalingState);
}, function(error) {
console.log('handleSSRC modify failed');
......@@ -667,9 +651,10 @@ function handleOffer (from, offer)
//console.log("bridgeSDP.raw", bridgeSDP.raw);
window.RTC.rayo.pc = new window.RTC.peerconnection(null, {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]});
window.RTC.rayo.pc[videobridge] = new window.RTC.peerconnection(null, {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]});
window.RTC.rayo.pc.onicecandidate = function(event)
window.RTC.rayo.pc[videobridge].onicecandidate = function(event)
{
//console.log('candidate', event.candidate);
......@@ -680,22 +665,22 @@ function handleOffer (from, offer)
}
window.RTC.rayo.pc.onaddstream = function(e)
window.RTC.rayo.pc[videobridge].onaddstream = function(e)
{
console.log("onstream", e, window.RTC.rayo.addssrc);
if (window.RTC.rayo.pc.signalingState == "have-remote-offer")
if (window.RTC.rayo.pc[videobridge].signalingState == "have-remote-offer")
$(document).trigger('remotestreamadded.rayo', [e, nick]);
window.RTC.rayo.pc.createAnswer(function(desc)
window.RTC.rayo.pc[videobridge].createAnswer(function(desc)
{
if (!window.RTC.rayo.addssrc)
window.RTC.rayo.pc.setLocalDescription(desc);
window.RTC.rayo.pc[videobridge].setLocalDescription(desc);
});
};
window.RTC.rayo.pc.addStream(window.RTC.rayo.localStream);
window.RTC.rayo.pc.setRemoteDescription(new RTCSessionDescription({type: "offer", sdp : bridgeSDP.raw}));
window.RTC.rayo.pc[videobridge].addStream(window.RTC.rayo.localStream);
window.RTC.rayo.pc[videobridge].setRemoteDescription(new RTCSessionDescription({type: "offer", sdp : bridgeSDP.raw}));
showToolbar();
updateRoomUrl(window.location.href);
......@@ -706,9 +691,9 @@ function sendAnswer(from, videobridge, confid, channelId)
{
console.log("sendAnswer");
var remoteSDP = new SDP(window.RTC.rayo.pc.localDescription.sdp);
var remoteSDP = new SDP(window.RTC.rayo.pc[videobridge].localDescription.sdp);
//console.log("remoteSDP ", window.RTC.rayo.pc.localDescription.sdp);
//console.log("remoteSDP ", window.RTC.rayo.pc[videobridge].localDescription.sdp);
var change = $iq({to: from, type: 'set'});
change.c('colibri', {xmlns: 'urn:xmpp:rayo:colibri:1', videobridge: videobridge});
......@@ -718,7 +703,6 @@ function sendAnswer(from, videobridge, confid, channelId)
{
if (remoteSDP.media[channel])
{
var indx =
change.c('content', {name: remoteSDP.media[channel].indexOf('m=audio') > -1 ? 'audio' : 'video'});
change.c('channel', {id: remoteSDP.media[channel].indexOf('m=audio') > -1 ? channelId[0] : channelId[1]});
......@@ -793,7 +777,7 @@ function sendAnswer(from, videobridge, confid, channelId)
connection.sendIQ(change,
function (res) {
console.log('rayo colibri answer set ok', window.RTC.rayo.pc.signalingState);
console.log('rayo colibri answer set ok', window.RTC.rayo.pc[videobridge].signalingState);
},
function (err) {
......@@ -821,6 +805,56 @@ function toggleAudio()
}
}
function registerRayoEvents()
{
connection.sendIQ($iq({to: connection.domain, type: 'set'}).c('colibri', {xmlns: 'urn:xmpp:rayo:colibri:1', action: 'offer', muc: roomjid}),
function (res) {
console.log('rayo colibri register set ok');
},
function (err) {
console.log('rayo colibri register got error', err);
}
);
}
function unregisterRayoEvents()
{
window.RTC.rayo.localStream.stop();
connection.sendIQ($iq({to: connection.domain, type: 'set'}).c('colibri', {xmlns: 'urn:xmpp:rayo:colibri:1', action: 'expire', muc: roomjid}),
function (res) {
console.log('rayo colibri unregister set ok');
},
function (err) {
console.log('rayo colibri unregister got error', err);
}
);
}
function toggleScreenShare()
{
console.log('toggleScreenShare', window.RTC.rayo.constraints);
var videobridge = Strophe.getNodeFromJid(roomjid);
if (screenShare)
{
var screenDIV = document.getElementById("screenshare");
screenDIV.parentElement.removeChild(screenDIV);
$("#screen").removeClass("fa-border");
} else {
var url = "publish.html?r=" + videobridge + "&screen=true";
$("body").append("<div id='screenshare'><iframe style='display:none' src='" + url + "'></iframe></div>");
$("#screen").addClass("fa-border");
}
screenShare = !screenShare;
}
function updateChatConversation(nick, message)
{
var timestamp = new Date();
......
This diff is collapsed.
<html>
<head>
<title>Openfire Meet</title>
<script src="js/jquery.min.js"></script>
<script src="js/md5.js"></script>
<script src="js/base64.js"></script>
<script src="js/strophe.js"></script>
<script src="js/muc.js"></script>
<script src="js/config.js"></script>
<script src="js/webrtc.sdp.js"></script>
<script src="js/strophe-openfire.js"></script>
<script src="js/publish.js"></script>
<link rel="shortcut icon" href="favicon.ico"/>
</head>
<body>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment