Browse Source

- Clean the Visio widget to fit with the new WebSocket system

- Rewrite the Presence CSS and fix minur issues
- Use the browser cookies to set the daemon SID
- Clean the WebSocket Javascript handler
- Clean old and commented sourcecode
pull/16/head
Jaussoin Timothée 11 years ago
parent
commit
18c36cf587
  1. 2
      app/assets/js/movim_base.js
  2. 24
      app/assets/js/movim_websocket.js
  3. 6
      app/views/visio.tpl
  4. 4
      app/widgets/Ack/ack.tpl
  5. 2
      app/widgets/Bookmark/_bookmark_list.tpl
  6. 9
      app/widgets/Bookmark/bookmark.css
  7. 4
      app/widgets/ContactInfo/contactinfo.css
  8. 1
      app/widgets/ContactSummary/contactsummary.css
  9. 2
      app/widgets/Login/Login.php
  10. 1
      app/widgets/Notification/Notification.php
  11. 23
      app/widgets/Notification/notification.js
  12. 4
      app/widgets/Notifs/notifs.css
  13. 3
      app/widgets/Presence/Presence.php
  14. 4
      app/widgets/Presence/presence.css
  15. 10
      app/widgets/Presence/presence.js
  16. 2
      app/widgets/PubsubSubscriptionConfig/PubsubSubscriptionConfig.php
  17. 2
      app/widgets/Roster/_roster_contact.tpl
  18. 198
      app/widgets/Visio/Visio.php
  19. 3
      app/widgets/Visio/_visio_contact.tpl
  20. 6
      app/widgets/Visio/locales.ini
  21. 80
      app/widgets/Visio/turn.js
  22. 2
      app/widgets/Visio/visio.css
  23. 140
      app/widgets/Visio/visio.js
  24. 8
      app/widgets/Visio/visio.tpl
  25. 25
      app/widgets/Visio/webrtc.js
  26. 17
      app/widgets/VisioExt/VisioExt.php
  27. 111
      app/widgets/VisioExt/visioext.js
  28. 6
      bootstrap.php
  29. 8
      daemon.php
  30. 24
      lib/JingletoSDP.php
  31. 2
      lib/SDPtoJingle.php
  32. 8
      linker.php
  33. 112
      src/Movim/Daemon/Behaviour.php
  34. 5
      system/Event.php
  35. 4
      system/RPC.php
  36. 4
      system/Sessionx.php
  37. 2
      system/widget/WidgetWrapper.php

2
app/assets/js/movim_base.js

@ -60,7 +60,7 @@ function movim_posts_unread(cpt) {
function movim_desktop_notification(title, body, image) {
var notification = new Notification(title, { icon: image, body: body });
notification.onshow = function() { setTimeout(notification.cancel(), 15000); }
//notification.onshow = function() { setTimeout(notification.cancel(), 15000); }
}
/**

24
app/assets/js/movim_websocket.js

@ -29,19 +29,10 @@ MovimWebsocket.prototype.init = function() {
this.connection.onopen = function(e) {
console.log("Connection established!");
if(localStorage.movimSession === undefined) {
this.send(JSON.stringify({'func' : 'ask'}));
} else {
this.register();
}
// And we launch the Javascript
movim_onload();
};
this.connection.onmessage = function(e) {
//console.log(e.data);
var obj = JSON.parse(e.data);
if(obj.id) {
@ -79,7 +70,6 @@ MovimWebsocket.prototype.send = function(widget, func, params) {
MovimWebsocket.prototype.handle = function(json) {
var funcalls = JSON.parse(json);
if(funcalls != null) {
for(h = 0; h < funcalls.length; h++) {
var funcall = funcalls[h];
@ -90,13 +80,27 @@ MovimWebsocket.prototype.handle = function(json) {
} catch(err) {
console.log("Error caught: " + err.toString() + " - " + funcall.func + ":" + JSON.stringify(funcall.params));
}
} else if(funcall.func != null) {
var funcs = funcall.func.split('.');
var called = funcs[0];
if(typeof window[called] == 'object') {
window[funcs[0]][funcs[1]].apply(null, funcall.params);
}
}
}
}
}
MovimWebsocket.prototype.unregister = function() {
//console.log(this);
//if(this.connection != null)
this.connection.unregister();
//websocket.unregister();
}
function remoteUnregister()
{
websocket.unregister();
}
// And we start it

6
app/views/visio.tpl

@ -4,17 +4,19 @@
<head>
<meta name="viewport" content="width=device-width, user-scalable=no";>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<?php
<?php
$this->addCss('css/animations.css');
$this->addCss('css/forms.css');
$this->addCss('css/fonts.css');
$this->addCss('css/style.css');
$this->widget('System');
$this->addScript('movim_hash.js');
$this->addScript('movim_utils.js');
$this->addScript('movim_base.js');
$this->addScript('movim_tpl.js');
$this->addScript('movim_rpc.js');
$this->addScript('movim_websocket.js');
$this->scripts();
$this->addCss('css/font-awesome.css');

4
app/widgets/Ack/ack.tpl

@ -1,7 +1,5 @@
<script type="text/javascript">
function ackRequest(arg) {
var to = arg[0];
var id = arg[1];
function ackRequest(to, id) {
{$ack}
}
</script>

2
app/widgets/Bookmark/_bookmark_list.tpl

@ -2,7 +2,7 @@
<li><h2><i class="fa fa-users"></i> {$c->__('title.conferences')}</h2></li>
{loop="$conferences"}
<li>
<!--<a href="#" onclick="{$c->getMucRemove($value)}" class="button oppose color transparent alone"><i class="fa fa-times oppose"></i></a>-->
<a href="#" onclick="{$c->getMucRemove($value)}" class="cross"><i class="fa fa-times oppose"></i></a>
<a href="#" onclick="{$c->getMucJoin($value)}">{$value->name}</a>
</li>
{/loop}

9
app/widgets/Bookmark/bookmark.css

@ -5,3 +5,12 @@
overflow: hidden;
text-overflow: ellipsis;
}
#bookmarks li .cross {
float: right;
opacity: 0.3;
}
#bookmarks li:hover .cross {
opacity: 1;
}

4
app/widgets/ContactInfo/contactinfo.css

@ -6,3 +6,7 @@
#contactinfo a:first-child {
margin-top: 2em;
}
#contactinfo img {
width: 100%;
}

1
app/widgets/ContactSummary/contactsummary.css

@ -12,7 +12,6 @@
line-height: 1.5em;
}
#contactsummary a.avatar {
width: 92%;
padding-bottom: 92%;

2
app/widgets/Login/Login.php

@ -130,7 +130,7 @@ class Login extends WidgetBase
break;
}
RPC::call('websocket.unregister');
RPC::call('remoteUnregister');
RPC::call('movim_desktop_notification', $title, $warning);
}

1
app/widgets/Notification/Notification.php

@ -56,7 +56,6 @@ class Notification extends WidgetCommon
</div>';
RPC::call('removeDiff', 'notification_widget', $html, $id);
RPC::commit();
}
function onPubsubError($error) {

23
app/widgets/Notification/notification.js

@ -1,21 +1,16 @@
function removeDiff(id, html, id2) {
var wrapper= document.createElement('div');
wrapper.innerHTML = html;
var nodes = wrapper.childNodes;
function removeDiff(id, html, id2) {
target = document.getElementById(id);
if(target) {
target.insertAdjacentHTML('beforeend', html);
var nodes = target.childNodes;
for(i = 0; i < nodes.length; i++) {
var n = nodes[i];
// The notification is already here ?
if(document.getElementById(id2) == null) {
target.appendChild(n);
setTimeout(function() {
n.parentNode.removeChild(n);
},
6000);
}
setTimeout(function() {
n.parentNode.removeChild(n);
},
6000);
}
}
}

4
app/widgets/Notifs/notifs.css

@ -1,7 +1,3 @@
#notifslist, #notifslist a:link, #notifslist a:visited {
color: white;
}
#notifslist {
clear: both;
}

3
app/widgets/Presence/Presence.php

@ -36,14 +36,13 @@ class Presence extends WidgetBase
$this->registerEvent('mypresence', 'onMyPresence');
}
function onMyPresence()
function onMyPresence($packet)
{
$html = $this->preparePresence();
RPC::call('movim_fill', 'presence_widget', $html);
Notification::appendNotification($this->__('status.updated'), 'success');
RPC::call('setPresenceActions');
RPC::call('movim_toggle_class', '#presence_widget', 'unfolded');
RPC::commit();
}
function onPostDisconnect($data)

4
app/widgets/Presence/presence.css

@ -58,16 +58,18 @@
#presence_widget span.status {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
#presence_widget span.status {
font-weight: normal;
font-size: 0.8em;
color: #DDD;
display: block;
}
#presence_widget #list {
width: 15rem;
width: 14.4rem;
background-color: white;
display: none;
z-index: 6;

10
app/widgets/Presence/presence.js

@ -1,21 +1,27 @@
function postStart() {
if(localStorage.postStart == 1) {
Presence_ajaxSetPresence();
Presence_ajaxConfigGet();
Presence_ajaxServerCapsGet();
Presence_ajaxBookmarksGet();
Presence_ajaxSetPresence();
localStorage.postStart = 0;
}
}
function setPresenceActions() {
document.querySelector('#presence_widget textarea.status').onkeypress = function(event) {
var textarea = document.querySelector('#presence_widget textarea.status');
textarea.onkeypress = function(event) {
if(event.keyCode == 13) {
Presence_ajaxSetStatus(this.value);
this.blur();
}
};
textarea.onfocus = function(event) {
movim_textarea_autoheight(this);
};
document.querySelector('#presence_widget #tab').onclick = function(event) {
movim_toggle_class('#presence_widget', 'unfolded');
};

2
app/widgets/PubsubSubscriptionConfig/PubsubSubscriptionConfig.php

@ -97,12 +97,10 @@ class PubsubSubscriptionConfig extends WidgetBase
function onGroupAdded($node) {
Notification::appendNotification($this->__('public_groups.added', $node), 'success');
RPC::commit();
}
function onGroupRemoved($node) {
Notification::appendNotification($this->__('public_groups.removed', $node), 'success');
RPC::commit();
}
function ajaxChangeSubscribed($server, $node, $state, $name) {

2
app/widgets/Roster/_roster_contact.tpl

@ -31,7 +31,7 @@
{if="$value.jingle"}
<div
class="infoicon jingle"
onclick="Popup.close(); Popup.open('{$value.jid}/{$value.ressource}')">
onclick="popup.close(); popup.setJid('{$value.jid}/{$value.ressource}'); popup.open()">
</div>
{/if}

198
app/widgets/Visio/Visio.php

@ -14,6 +14,8 @@
*/
//require_once(APP_PATH . "widgets/ChatExt/ChatExt.php");
use Moxl\Xec\Action\Jingle\SessionInitiate;
use Moxl\Xec\Action\Jingle\SessionTerminate;
class Visio extends WidgetBase
{
@ -25,16 +27,196 @@ class Visio extends WidgetBase
$this->addjs('webrtc.js');
$this->addjs('turn.js');
//$s = Session::start('movim');
//var_dump($s->get('jingleSid'));
$this->registerEvent('jinglesessioninitiate', 'onSessionInitiate');
$this->registerEvent('sessioninitiate_erroritemnotfound', 'onInitiationError');
$this->registerEvent('sessioninitiate_errorunexpectedrequest', 'onInitiationError');
$this->registerEvent('jinglesessionterminate', 'onSessionTerminate');
$this->registerEvent('jinglesessionaccept', 'onSessionAccept');
$this->registerEvent('jingletransportinfo', 'onTransportInfo');
$this->registerEvent('jinglecreationsuccess', 'onCreationSuccess');
}
function onInitiationError() {
RPC::call('sendTerminate');
RPC::call('terminate');
}
function onSessionInitiate($jingle) {
$jts = new \JingletoSDP($jingle);
$sdp = $jts->generate();
$cd = new \Modl\ContactDAO();
$contact = $cd->get(cleanJid((string)$jingle->attributes()->initiator));
if(!isset($contact))
$contact = new Modl\Contact;
if($sdp) {
RPC::call(
'movim_desktop_notification',
$contact->getTrueName(),
$this->__('visio.calling'),
$contact->getPhoto('m'));
//RPC::call('Popup.setJid', (string)$jingle->attributes()->initiator);
RPC::call('onOffer', $sdp);
}
}
function onSessionAccept($jingle) {
$jts = new \JingletoSDP($jingle);
$sdp = $jts->generate();
$sid = $jts->getSessionId();
RPC::call('onAccept', $sdp);
$s = Session::start('movim');
$s->set('jingleSid', $sid);
}
function onTransportInfo($jingle) {
$jts = new \JingletoSDP($jingle);
RPC::call('onCandidate', $jts->generate(), $jts->media);
}
function onSessionTerminate($jingle) {
$message = '';
switch($jingle->reason->children()->getName()) {
case 'success':
$message = $this->__('visio.hung_up');
break;
case 'busy':
$message = $this->__('visio.busy');
break;
case 'decline':
$message = $this->__('visio.declined');
break;
case 'unsupported-transports':
break;
case 'failed-transport':
break;
case 'unsupported-applications':
break;
case 'failed-application':
$message = $this->__('visio.remote_incompatible');
break;
case 'incompatible-parameters':
break;
default:
$message = $this->__('visio.unknown_error');
break;
}
RPC::call('terminate');
RPC::call('movim_fill', 'status', $message);
}
function ajaxSendProposal($proposal) {
$p = json_decode($proposal);
$sd = Sessionx::start();
$stj = new SDPtoJingle(
$p->sdp,
$this->user->getLogin().'/'.$sd->ressource,
$p->jid.'/'.$p->ressource,
'session-initiate');
$r = new SessionInitiate;
$r->setTo($p->jid.'/'.$p->ressource)
->setOffer($stj->generate())
->request();
$sid = $stj->getSessionId();
$s = Session::start('movim');
$s->set('jingleSid', $sid);
}
function ajaxSendAcceptance($proposal) {
$p = json_decode($proposal);
$sd = Sessionx::start();
$stj = new SDPtoJingle(
$p->sdp,
$this->user->getLogin().'/'.$sd->ressource,
$p->jid.'/'.$p->ressource,
'session-accept');
$r = new SessionInitiate;
$r->setTo($p->jid.'/'.$p->ressource)
->setOffer($stj->generate())
->request();
}
function ajaxSendSessionTerminate($jid, $ressource, $reason = null) {
$s = Session::start();
$jingleSid = $s->get("jingleSid");
$r = new SessionTerminate;
$r->setTo($jid.'/'.$ressource);
$r->setJingleSid($jingleSid);
if(isset($reason))
$r->setReason($reason);
$r->request();
}
function ajaxSendCandidate($candidate) {
$p = json_decode($candidate);
$sd = Sessionx::start();
$sdp =
'm='.$p->mid."\n".
$p->sdp;
$stj = new SDPtoJingle(
$sdp,
$this->user->getLogin().'/'.$sd->ressource,
$p->jid.'/'.$p->ressource,
'transport-info');
$r = new SessionInitiate;
$r->setTo($p->jid.'/'.$p->ressource)
->setOffer($stj->generate())
->request();
}
function ajaxGetContact($jid)
{
$cd = new \Modl\ContactDAO();
$contact = $cd->get($jid);
$contactview = $this->tpl();
$contactview->assign('contact', $contact);
RPC::call('movim_fill', 'avatar', $contactview->draw('_visio_contact', true));
}
if(isset($_GET['f'])) {
list($jid, $ressource) = explode('/', htmlentities($_GET['f']));
function display()
{
//if(isset($_GET['f'])) {
// list($jid, $ressource) = explode('/', htmlentities($_GET['f']));
$json = requestURL('https://computeengineondemand.appspot.com/turn?username=93773443&key=4080218913', 1);
$this->view->assign('turn_list' , $json);
$json = requestURL('https://computeengineondemand.appspot.com/turn?username=93773443&key=4080218913', 1);
$this->view->assign('turn_list' , $json);
$cd = new \Modl\ContactDAO();
/* $cd = new \Modl\ContactDAO();
$contact = $cd->get($jid);
if(!$contact)
@ -44,6 +226,6 @@ class Visio extends WidgetBase
$this->view->assign('name' ,$contact->getTrueName());
$this->view->assign('jid' ,$jid);
$this->view->assign('ressource' ,$ressource);
}
}*/
}
}

3
app/widgets/Visio/_visio_contact.tpl

@ -0,0 +1,3 @@
<img src="{$contact->getPhoto('l')}"/>
<span class="name">{$contact->getTrueName()}</span>
<div id="status"></div>

6
app/widgets/Visio/locales.ini

@ -1,3 +1,9 @@
visio.call = 'Call'
visio.hang_up = 'Hang up'
visio.connection= 'Connection'
visio.hung_up = 'Hung up'
visio.busy = 'Your contact is busy'
visio.declined = 'Declined'
visio.remote_incompatible = 'Remote application incompatible'
visio.unknown_error = 'Unknown error'
visio.calling = 'Is calling you'

80
app/widgets/Visio/turn.js

@ -2,58 +2,58 @@ var turnUrl = 'https://computeengineondemand.appspot.com/turn?username=93773443&
var turnDone = false;
function maybeRequestTurn() {
if (turnUrl == '') {
turnDone = true;
}
if (turnUrl == '') {
turnDone = true;
}
for (var i = 0, len = configuration.iceServers.length; i < len; i++) {
if (configuration.iceServers[i].url.substr(0, 5) === 'turn:') {
turnDone = true;
for (var i = 0, len = configuration.iceServers.length; i < len; i++) {
if (configuration.iceServers[i].url.substr(0, 5) === 'turn:') {
turnDone = true;
}
}
}
var currentDomain = document.domain;
if (currentDomain.search('localhost') === -1 &&
currentDomain.search('apprtc') === -1) {
// Not authorized domain. Try with default STUN instead.
turnDone = true;
}
var currentDomain = document.domain;
if (currentDomain.search('localhost') === -1 &&
currentDomain.search('apprtc') === -1) {
// Not authorized domain. Try with default STUN instead.
turnDone = true;
}
// No TURN server. Get one from computeengineondemand.appspot.com.
/*xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = onTurnResult;
xmlhttp.open('GET', turnUrl, true);
xmlhttp.send();*/
// No TURN server. Get one from computeengineondemand.appspot.com.
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = onTurnResult;
xmlhttp.open('GET', turnUrl, true);
xmlhttp.send();
for (i = 0; i < VISIO_TURN_LIST.uris.length; i++) {
/*for (i = 0; i < VISIO_TURN_LIST.uris.length; i++) {
var iceServer = createIceServer(VISIO_TURN_LIST.uris[i],
VISIO_TURN_LIST.username,
VISIO_TURN_LIST.password);
if (iceServer !== null) {
configuration.iceServers.push(iceServer);
}
}
}*/
}
function onTurnResult() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var turnServer = JSON.parse(xmlhttp.responseText);
for (i = 0; i < turnServer.uris.length; i++) {
// Create a turnUri using the polyfill (adapter.js).
var iceServer = createIceServer(turnServer.uris[i],
turnServer.username,
turnServer.password);
if (iceServer !== null) {
configuration.iceServers.push(iceServer);
}
}
} else {
console.log(
'Error: Status '
+ xmlhttp.status
+ ', State '
+ xmlhttp.readyState);
}
// If TURN request failed, continue the call with default STUN.
turnDone = true;
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var turnServer = JSON.parse(xmlhttp.responseText);
for (i = 0; i < turnServer.uris.length; i++) {
// Create a turnUri using the polyfill (adapter.js).
var iceServer = createIceServer(turnServer.uris[i],
turnServer.username,
turnServer.password);
if (iceServer !== null) {
configuration.iceServers.push(iceServer);
}
}
} /*else {
console.log(
'Error: Status '
+ xmlhttp.status
+ ', State '
+ xmlhttp.readyState);
}*/
// If TURN request failed, continue the call with default STUN.
turnDone = true;
}

2
app/widgets/Visio/visio.css

@ -91,7 +91,7 @@ body {
position: absolute;
top: 0;
left: 0;
display: none;
/*display: none;*/
}
#visio #log div {

140
app/widgets/Visio/visio.js

@ -8,6 +8,9 @@ setInterval( notifyOpener, 200 );
self.focus();
VISIO_JID = '';
VISIO_RESSOURCE = '';
/**
* When an error occured
*/
@ -26,14 +29,13 @@ var Visio = {
isVideoMuted: false,
fullScreen: function() {
var elem = document.getElementById("visio");
var toggle = document.querySelector("#toggle-screen i");
if(!document.fullscreenElement
&& !document.mozFullScreenElement
&& !document.webkitFullscreenElement) { // current working methods
toggle.className = toggle.className.replace('expand', 'compress');
if(document.fullscreenElement == null
&& document.mozFullScreenElement == null
&& document.webkitFullscreenElement == null) { // current working methods
toggle.className = toggle.className.replace('fa-expand', 'fa-compress');
if (document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen();
} else if (document.documentElement.mozRequestFullScreen) {
@ -42,7 +44,7 @@ var Visio = {
document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
}
} else {
toggle.className = toggle.className.replace('compress', 'expand');
toggle.className = toggle.className.replace('fa-compress', 'fa-expand');
if (document.cancelFullScreen) {
document.cancelFullScreen();
@ -56,84 +58,89 @@ var Visio = {
log: function(content) {
var date = new Date();
movim_prepend([
movim_prepend(
"log",
"<div>["
+ date.getHours() + ":"+date.getMinutes() + ":"+date.getSeconds() + "] "
+ content +
"</div>"]);
},
/*
* @brief Call a function in the main window
* @param Array, array[0] is the name of the function, then the params
*/
call: function(args) {
if( self.opener && !self.opener.closed ) {
// The popup is open so call it
var func = args[0];
args.shift();
var params = args;
self.opener[func].apply(null, params);
}
"</div>");
},
toggleVideoMute: function() {
videoTracks = localStream.getVideoTracks();
var camera = document.getElementById("toggle-camera");
if (videoTracks.length === 0) {
console.log('No local video available.');
return;
}
videoTracks = localStream.getVideoTracks();
var camera = document.getElementById("toggle-camera");
if (this.isVideoMuted) {
for (i = 0; i < videoTracks.length; i++) {
videoTracks[i].enabled = true;
}
camera.className = camera.className.replace('camera-off', 'camera');
console.log('Video unmuted.');
} else {
for (i = 0; i < videoTracks.length; i++) {
videoTracks[i].enabled = false;
if (videoTracks.length === 0) {
console.log('No local video available.');
return;
}
camera.className = camera.className.replace('camera', 'camera-off');
console.log('Video muted.');
}
if (this.isVideoMuted) {
for (i = 0; i < videoTracks.length; i++) {
videoTracks[i].enabled = true;
}
camera.className = camera.className.replace('camera-off', 'camera');
console.log('Video unmuted.');
} else {
for (i = 0; i < videoTracks.length; i++) {
videoTracks[i].enabled = false;
}
this.isVideoMuted = !this.isVideoMuted;
camera.className = camera.className.replace('camera', 'camera-off');
console.log('Video muted.');
}
this.isVideoMuted = !this.isVideoMuted;
},
toggleAudioMute: function() {
audioTracks = localStream.getAudioTracks();
var micro = document.getElementById("toggle-microphone");
audioTracks = localStream.getAudioTracks();
var micro = document.getElementById("toggle-microphone");
if (audioTracks.length === 0) {
console.log('No local audio available.');
return;
}
if (this.isAudioMuted) {
for (i = 0; i < audioTracks.length; i++) {
audioTracks[i].enabled = true;
if (audioTracks.length === 0) {
console.log('No local audio available.');
return;
}
micro.className = micro.className.replace('microphone-off', 'microphone');
console.log('Video unmuted.');
} else {
for (i = 0; i < audioTracks.length; i++) {
audioTracks[i].enabled = false;
if (this.isAudioMuted) {
for (i = 0; i < audioTracks.length; i++) {
audioTracks[i].enabled = true;
}
micro.className = micro.className.replace('microphone-off', 'microphone');
console.log('Video unmuted.');
} else {
for (i = 0; i < audioTracks.length; i++) {
audioTracks[i].enabled = false;
}
micro.className = micro.className.replace('microphone', 'microphone-off');
console.log('Video muted.');
}
micro.className = micro.className.replace('microphone', 'microphone-off');
console.log('Video muted.');
}
this.isAudioMuted = !this.isAudioMuted;
},
this.isAudioMuted = !this.isAudioMuted;
}
readStack: function() {
if(self.opener.popup.stack != null) {
var stack = self.opener.popup.stack;
if(stack.jid != null) {
jid = stack.jid.split('/');
VISIO_JID = jid[0];
VISIO_RESSOURCE = jid[1];
delete stack.jid;
}
for(var call in stack) {
console.log('Call function ' + call);
window[call].call(null, stack[call]);
delete stack[call];
}
}
}
}
movim_add_onload(function()
@ -144,4 +151,7 @@ movim_add_onload(function()
document.getElementById("toggle-screen").addEventListener('click', function() { Visio.fullScreen(); }, false);
document.getElementById("toggle-camera").addEventListener('click', function() { Visio.toggleVideoMute(); }, false);
document.getElementById("toggle-microphone").addEventListener('click', function() { Visio.toggleAudioMute(); }, false);
Visio.readStack();
Visio_ajaxGetContact(VISIO_JID);
});

8
app/widgets/Visio/visio.tpl

@ -10,9 +10,7 @@
</video>
<div id="avatar">
<img src="{$avatar}"/>
<span class="name">{$name}</span>
<div id="status"></div>
</div>
<div class="menu">
<a id="toggle-microphone" class="button color alone merged right oppose">
@ -22,7 +20,7 @@
</a>
<a id="call" class="button color green">
<i class="fa fa-play"></i> {$c->__('visio.call')}
<i class="fa fa-phone"></i> {$c->__('visio.call')}
</a>
<a id="hang-up" class="button color red icon hang-up">
<i class="fa fa-stop"></i> {$c->__('visio.hang_up')}
@ -32,8 +30,6 @@
</div>
</div>
<script type="text/javascript">
VISIO_JID = '{$jid}';
VISIO_RESSOURCE = '{$ressource}';
VISIO_TURN_LIST = {$turn_list};
</script>
<div id="connection">

25
app/widgets/Visio/webrtc.js

@ -98,13 +98,13 @@ function onIceCandidate(event) {
var msgString = JSON.stringify(candidate);
Visio.call(['VisioExt_ajaxSendCandidate', msgString]);
Visio_ajaxSendCandidate(msgString);
}
}
function sendTerminate(reason) {
Visio.call(['VisioExt_ajaxSendSessionTerminate', VISIO_JID, VISIO_RESSOURCE, reason]);
Visio_ajaxSendSessionTerminate(VISIO_JID, VISIO_RESSOURCE, reason);
}
function sendMessage(msg, accept) {
@ -126,14 +126,14 @@ function sendMessage(msg, accept) {
if(accept) {
Visio.log('Send the acceptance.');
Visio.log('ACCEPTANCE ' + msg.sdp);
Visio.call(['VisioExt_ajaxSendAcceptance', msgString]);
Visio_ajaxSendAcceptance(msgString);
} else {
Visio.log('Send the proposal.');
Visio.log('PROPOSAL ' + msg.sdp);
console.log(msg.sdp);
Visio.call(['VisioExt_ajaxSendProposal', msgString]);
Visio_ajaxSendProposal(msgString);
}
}, 1000);
} else {
@ -142,12 +142,12 @@ function sendMessage(msg, accept) {
if(accept) {
Visio.log('Send the acceptance.');
Visio.log('ACCEPTANCE ' + msg.sdp);
Visio.call(['VisioExt_ajaxSendAcceptance', msgString]);
Visio_ajaxSendAcceptance(msgString);
} else {
Visio.log('Send the proposal.');
Visio.log('PROPOSAL ' + msg.sdp);
Visio.call(['VisioExt_ajaxSendProposal', msgString]);
Visio_ajaxSendProposal(msgString);
}
}
}
@ -171,8 +171,7 @@ function onSetRemoteSessionDescriptionError(error) {
}
function onOffer(offer) {
offer = offer[0];
console.log(offer);
Visio.log('Offer received.');
Visio.log('OFFER ' + offer);
@ -192,9 +191,7 @@ function onOffer(offer) {
}
}
function onAccept(offer) {
offer = offer[0];
function onAccept(offer) {
Visio.log('Accept received.');
Visio.log('ACCEPT ' + offer);
@ -208,14 +205,14 @@ function onAccept(offer) {
}
}
function onCandidate(message) {
function onCandidate(sdp, media) {
var label = {
'audio' : 0,
'video' : 1
};
var candidate = new RTCIceCandidate({sdpMLineIndex: label[message[1]],
candidate: message[0]});
var candidate = new RTCIceCandidate({sdpMLineIndex: label[media],
candidate: sdp});
pc.addIceCandidate(candidate, onRemoteIceCandidateAdded, onRemoteIceCandidateError);
}

17
app/widgets/VisioExt/VisioExt.php

@ -26,11 +26,11 @@ class VisioExt extends WidgetBase
function load() {
$this->addjs('visioext.js');
$this->registerEvent('jinglesessioninitiate', 'onSessionInitiate');
$this->registerEvent('jinglesessionterminate', 'onSessionTerminate');
/*$this->registerEvent('jinglesessionterminate', 'onSessionTerminate');
$this->registerEvent('jinglesessionaccept', 'onSessionAccept');
$this->registerEvent('jingletransportinfo', 'onTransportInfo');
$this->registerEvent('jinglecreationsuccess', 'onCreationSuccess');
$this->registerEvent('jinglecreationsuccess', 'onCreationSuccess');*/
}
function onSessionInitiate($jingle) {
@ -45,15 +45,16 @@ class VisioExt extends WidgetBase
if($sdp) {
RPC::call(
'movim_desktop_notification_arr',
'movim_desktop_notification',
$contact->getTrueName(),
$this->__('visio.calling'),
$contact->getPhoto('m'));
RPC::call('Popup.setJid', (string)$jingle->attributes()->initiator);
RPC::call('Popup.call', 'onOffer', $sdp);
RPC::call('remoteSetJid', (string)$jingle->attributes()->initiator);
RPC::call('remoteCall', 'onOffer', $sdp);
RPC::commit();
}
}
/*
function onSessionAccept($jingle) {
$jts = new \JingletoSDP($jingle);
$sdp = $jts->generate();
@ -186,9 +187,9 @@ class VisioExt extends WidgetBase
$r->setTo($p->jid.'/'.$p->ressource)
->setOffer($stj->generate())
->request();
}
}*/
function build() {
}
}
}

111
app/widgets/VisioExt/visioext.js

@ -1,56 +1,59 @@
var Popup = {
win : null,
jid : null,
setJid: function(jid) {
this.jid = jid;
},
open: function(jid) {
console.log('Popup already opened');
var url = BASE_URI + PAGE_KEY_URI + "visio&f="+jid
this.setJid(jid);
if( !this.win || this.win.closed ) {
console.log('Opening the Popup');
this.win = window.open( url, "win", "height=480,width=640,directories=0,titlebar=0,toolbar=0,location=0,status=0, personalbar=0,menubar=0,resizable=0" );
} else this.win.focus();
},
close: function() {
if(this.win)
this.win.close();
},
focus: function() {
this.win.focus();
},
send: function(args) {
var func = args[0];
args.shift();
var params = args;
console.log('Calling the Popup');
this.win[func](params);
},
hangUp: function(args) {
console.log('Your friend just hung up');
},
call: function(args) {
if( this.win && !this.win.closed ) {
// The popup is open so call it
Popup.send(args);
} else if(this.jid) {
// The popup is closed so open it
console.log('We open the Popup');
this.open(this.jid);
console.log('We wait a little');
this.win.addEventListener('load', function() { Popup.send(args); }, false);
}
/**
* @brief Definition of the MovimWebsocket object
* @param string error
*/
function Popup() {
var stack;
var win;
}
Popup.prototype.init = function() {
this.stack = {};
}
Popup.prototype.open = function() {
console.log('Popup already opened');
var url = BASE_URI + PAGE_KEY_URI + 'visio';
//this.setJid(jid);
console.log(url);
if( !this.win || this.win.closed ) {
console.log('Opening the Popup');
this.win = window.open( url, "win", "height=480,width=640,directories=0,titlebar=0,toolbar=0,location=0,status=0, personalbar=0,menubar=0,resizable=0" );
} else this.win.focus();
}
Popup.prototype.close = function() {
if(this.win) { this.win.close(); }
}
Popup.prototype.focus = function() {
if(this.win) { this.win.focus(); }
}
Popup.prototype.setJid = function(jid) {
this.stack.jid = jid;
}
Popup.prototype.call = function(func, param) {
if(!this.win || this.win.closed ) {
/*if(this.stack == null) {
this.stack = {};
}*/
this.stack[func] = param;
this.open();
}
}
function remoteCall(func, param) {
console.log('HOP');
console.log(popup);
popup.call(func, param);
}
function remoteSetJid(jid) {
popup.setJid(jid);
}
var popup = new Popup;
popup.init();

6
bootstrap.php

@ -295,7 +295,7 @@ class Bootstrap {
Modl\Utils::loadModel('Contact');
Modl\Utils::loadModel('Privacy');
Modl\Utils::loadModel('RosterLink');
Modl\Utils::loadModel('Session');
//Modl\Utils::loadModel('Session');
Modl\Utils::loadModel('Cache');
Modl\Utils::loadModel('Postn');
Modl\Utils::loadModel('Subscription');
@ -353,7 +353,7 @@ class Bootstrap {
$compatible = true;
break;
case 'IE':
if($browser_version > 9.0)
if($browser_version > 10.0)
$compatible = true;
break;
case 'Safari': // Also Chrome-Chromium
@ -361,7 +361,7 @@ class Bootstrap {
$compatible = true;
break;
case 'Opera':
if($browser_version > 9.0)
if($browser_version > 12.1)
$compatible = true;
break;
}

8
daemon.php

@ -6,7 +6,13 @@ use Movim\Daemon\Behaviour;
require dirname(__FILE__) . '/vendor/autoload.php';
$server = new Behaviour;
$argsize = count($argv);
if($argsize == 1) {
echo "Please specify a base uri eg. http://myhost.com/movim/\n";
exit;
}
$server = new Behaviour($argv[1]);
$server = IoServer::factory(
new HttpServer(

24
lib/JingletoSDP.php

@ -10,7 +10,7 @@ class JingletoSDP {
public $media;
private $values = array(
'session_id' => 1,
'session_sdp_id' => 1,
'session_version' => 0,
'nettype' => 'IN',
'addrtype' => 'IP4',
@ -23,25 +23,27 @@ class JingletoSDP {
if(isset($this->jingle->attributes()->sid)) {
$sid = (string)$this->jingle->attributes()->sid;
$sid = substr(base_convert($sid, 30, 10), 0, 6);
//$sid = substr(base_convert($sid, 30, 10), 0, 6);
$s = Session::start('movim');
$s = Session::start();
$s->set('jingleSid', $sid);
$this->values['session_id'] = $sid;
//$this->values['session_id'] = $sid;
}
$this->action = (string)$this->jingle->attributes()->action;
}
function getSessionId(){
$s = Session::start('movim');
if($sid = $s->get('jingleSid')){
$s = Session::start();
/*if($sid = $s->get('jingleSid')){
return $sid;
}
else{
$sessid = $this->jingle->attributes()->sid;
return substr(base_convert($sessid, 30, 10), 0, 6);
}
}*/
return substr(base_convert($s->get('jingleSid'), 30, 10), 0, 6);
}
function generate() {
@ -51,7 +53,7 @@ class JingletoSDP {
} else
$username = '-';
$this->values['session_id'] = $this->getSessionId();
$this->values['session_sdp_id'] = $this->getSessionId();
$sdp_version =
'v=0';
@ -59,7 +61,7 @@ class JingletoSDP {
$sdp_origin =
'o='.
$username.' '.
$this->values['session_id'].' '.
$this->values['session_sdp_id'].' '.
$this->values['session_version'].' '.
$this->values['nettype'].' '.
$this->values['addrtype'].' '.
@ -200,14 +202,14 @@ class JingletoSDP {
break;
case 'source':
/*case 'source':
foreach($payload->children() as $s) {
$sdp_media .=
"\r\na=ssrc:".$payload->attributes()->id.' '.
$s->attributes()->name.':'.
$s->attributes()->value;
}
break;
break;*/
}
// TODO sendrecv ?
}

2
lib/SDPtoJingle.php

@ -49,7 +49,7 @@ class SDPtoJingle {
}
function getSessionId(){
$s = Session::start('movim');
$s = Session::start();
if($sid = $s->get('jingleSid')){
return $sid;
}

8
linker.php

@ -7,16 +7,14 @@ require_once(DOCUMENT_ROOT.'/bootstrap.php');
$bootstrap = new Bootstrap();
$booted = $bootstrap->boot();
set_time_limit(200);
$polling = true;
$loop = React\EventLoop\Factory::create();
$dnsResolverFactory = new React\Dns\Resolver\Factory();
$dns = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$connector = new Ratchet\Client\Factory($loop);
//setcookie('PHPENV', getenv('sid'), time()+3600);
/*
$connector_xmpp = new React\SocketClient\Connector($loop, $dns);
$secure_connector_xmpp = new React\SocketClient\SecureConnector($connector_xmpp, $loop);
@ -81,6 +79,8 @@ React\Promise\all([$connector('ws://127.0.0.1:8080'), $connector('ws://movim.eu:
$obj = new \StdClass;
$obj->func = 'message';
$obj->body = \RPC::commit();
$out = json_encode($obj->body);
$logger->notice("XMPP : Send to LOOP {$out}");
\RPC::clear();
if(!empty($obj->body)) {

112
src/Movim/Daemon/Behaviour.php

@ -7,13 +7,45 @@ use Ratchet\ConnectionInterface;
class Behaviour implements MessageComponentInterface {
protected $sessions = array(); // Store the sessions
protected $process;
protected $baseuri;
public function __construct() {
echo "Movim daemon launched\n";
public function __construct($baseuri) {
echo "Movim daemon launched - Base URI : {$baseuri}\n";
$this->baseuri = $baseuri;
}
public function onOpen(ConnectionInterface $conn) {
echo "{$conn->resourceId} connected\n";
$cookies = $conn->WebSocket->request->getCookies();
if(array_key_exists('PHPSESSID', $cookies)) {
$sid = $cookies['PHPSESSID'];
$this->sessions[$sid][$conn->resourceId] = $conn;
// If a linker doesn't exist for the current session
if(!array_key_exists('linker', $this->sessions[$sid])) {
$loop = \React\EventLoop\Factory::create();
$this->process = new \React\ChildProcess\Process(
'php linker.php',
null,
array(
'sid' => $sid,
'baseuri' => $this->baseuri
)
);
$this->process->start($loop);
}
echo "{$cookies['PHPSESSID']} : {$conn->resourceId} connected\n";
} else {
//var_dump(get_class_methods($conn->WebSocket->request));
//var_dump($conn->WebSocket->request->getBody());
//var_dump($conn->WebSocket->request->getHeaders());
//var_dump($conn->WebSocket->request->getParams());
//var_dump($conn->WebSocket->request->getCookies());
//var_dump($conn->WebSocket->request->getUrl());
//var_dump($conn->WebSocket->request->getState());
//var_dump($conn->WebSocket->request->getHeaderLines());
}
}
public function onMessage(ConnectionInterface $from, $msg) {
@ -33,38 +65,16 @@ class Behaviour implements MessageComponentInterface {
$from->send(json_encode($obj));
break;
// A browser websocket ask to be linked to an existent session
case 'register':
$from->sid = $msg->sid;
case 'unregister':
$cookies = $from->WebSocket->request->getCookies();
if(!array_key_exists($from->sid, $this->sessions)) {
$this->sessions[$from->sid] = array();
}
$this->sessions[$from->sid][$from->resourceId] = $from;
// If a linker doesn't exist for the current session
if(!array_key_exists('linker', $this->sessions[$from->sid])) {
$from->send(json_encode('session linked'));
$loop = \React\EventLoop\Factory::create();
$this->process = new \React\ChildProcess\Process(
'php linker.php',
null,
array(
'sid' => $from->sid,
'baseuri' => $msg->baseuri
)
);
$this->process->start($loop);
if(array_key_exists('PHPSESSID', $cookies)) {
$sid = $cookies['PHPSESSID'];
} else {
$sid = $from->sid;
}
$session_size = count($this->sessions[$from->sid]);
echo "{$from->sid} : {$from->resourceId} registered - session size {$session_size}\n";
break;
case 'unregister':
if(array_key_exists('linker', $this->sessions[$from->sid])) {
if(array_key_exists('linker', $this->sessions[$sid])) {
$this->process->terminate();
}
break;
@ -92,18 +102,26 @@ class Behaviour implements MessageComponentInterface {
// A message is received !
case 'message':
$cookies = $from->WebSocket->request->getCookies();
if(array_key_exists('PHPSESSID', $cookies)) {
$sid = $cookies['PHPSESSID'];
} else {
$sid = $from->sid;
}
// Forbid any incoming messages if the session is not linked to XMPP
if(!array_key_exists('linker', $this->sessions[$from->sid])) {
$from->send(json_encode('linker not connected'));
if(!array_key_exists('linker', $this->sessions[$sid])) {
//$from->send(json_encode('linker not connected'));
return;
}
$msg->body = (string)json_encode($msg->body);
// A message from the linker to the clients
if($from === $this->sessions[$from->sid]['linker']) {
if($from === $this->sessions[$sid]['linker']) {
//echo "{$from->sid} : {$msg->body} got from the linker\n";
foreach($this->sessions[$from->sid] as $key => $client) {
foreach($this->sessions[$sid] as $key => $client) {
if($from !== $client) {
//The sender is not the receiver, send to each client connected
if(isset($msg->body)) {
@ -114,7 +132,7 @@ class Behaviour implements MessageComponentInterface {
// A message from the browser to the linker
} else {
//echo "{$from->sid} : {$msg->body} sent to the linker\n";
$this->sessions[$from->sid]['linker']->send((string)$msg->body);
$this->sessions[$sid]['linker']->send((string)$msg->body);
}
break;
default:
@ -125,11 +143,19 @@ class Behaviour implements MessageComponentInterface {
public function onClose(ConnectionInterface $conn) {
if(count($this->sessions) > 0) {
$session_size = count($this->sessions[$conn->sid]);
$cookies = $conn->WebSocket->request->getCookies();
if(array_key_exists('PHPSESSID', $cookies)) {
$sid = $cookies['PHPSESSID'];
} else {
$sid = $conn->sid;
}
$session_size = count($this->sessions[$sid]);
// The connection is closed, remove it, as we can no longer send it messages
if(array_key_exists('linker', $this->sessions[$conn->sid])
&& $conn->resourceId == $this->sessions[$conn->sid]['linker']->resourceId) {
if(array_key_exists('linker', $this->sessions[$sid])
&& $conn->resourceId == $this->sessions[$sid]['linker']->resourceId) {
$obj = new \StdClass;
$obj->func = 'disconnected';
@ -138,10 +164,10 @@ class Behaviour implements MessageComponentInterface {
echo "{$client->resourceId} disconnected to login\n";
}
echo "{$conn->resourceId} linker disconnected - session size {$session_size}\n";
unset($this->sessions[$conn->sid]);
unset($this->sessions[$sid]);
} else {
echo "{$conn->resourceId} disconnected - session size {$session_size}\n";
unset($this->sessions[$conn->sid][$conn->resourceId]);
unset($this->sessions[$sid][$conn->resourceId]);
}
}
}

5
system/Event.php

@ -4,11 +4,6 @@ class Event
{
function runEvent($type, $event = false)
{
global $polling;
if(!$polling) { // avoids issues while loading pages.
return;
}
$widgets = WidgetWrapper::getInstance(false);
$widgets->iterate('runEvents', array(

4
system/RPC.php

@ -27,11 +27,11 @@ class RPC
$args = func_get_args();
array_shift($args);
$args = array_map(
/*$args = array_map(
function($string) {
return preg_replace("/[\t\r\n]/", '', trim($string));
},
$args);
$args);*/
if(self::filter($funcname, $args)) {
$funcall = array(

4
system/Sessionx.php

@ -44,8 +44,8 @@ class Sessionx {
protected function __construct()
{
if(isset($_COOKIE['MOVIM_SESSION_ID'])) {
self::$_sessionid = $_COOKIE['MOVIM_SESSION_ID'];
if(isset($_COOKIE['PHPSESSID'])) {
self::$_sessionid = $_COOKIE['PHPSESSID'];
} else {
self::$_sessionid = SESSION_ID;
}

2
system/widget/WidgetWrapper.php

@ -92,7 +92,7 @@ class WidgetWrapper
protected function destroy()
{
if($this->register_widgets && count($this->loaded_widgets) > 0) {
$sess = Session::start(APP_NAME);
$sess = Session::start();
$sess->set('loaded_widgets', $this->loaded_widgets);
$this->register_widgets = false;
}

Loading…
Cancel
Save