Browse Source

- Merge with edhelas

pull/16/head
Jaussoin Timothée 12 years ago
parent
commit
a29faa581b
  1. 6
      app/assets/js/movim_rpc.js
  2. 3
      app/assets/js/movim_tpl.js
  3. 2
      app/models/cache/CacheDAO.php
  4. 59
      app/models/contact/Contact.php
  5. 15
      app/models/contact/ContactDAO.php
  6. 17
      app/widgets/Avatar/Avatar.php
  7. 5
      app/widgets/Avatar/_avatar_form.tpl
  8. 2
      app/widgets/Avatar/avatar.js
  9. 2
      app/widgets/Chat/Chat.php
  10. 2
      app/widgets/Chat/chat.css
  11. 3
      app/widgets/Explore/Explore.php
  12. 2
      app/widgets/Presence/Presence.php
  13. 165
      app/widgets/Roster/Roster.php
  14. 46
      app/widgets/Roster/_roster_contact.tpl
  15. 6
      app/widgets/Roster/_roster_list.tpl
  16. 169
      app/widgets/Roster/roster.css
  17. 3
      app/widgets/Roster/roster.js
  18. 4
      app/widgets/Roster/roster.tpl
  19. 1
      app/widgets/Visio/visio.css
  20. 76
      app/widgets/Visio/webrtc.js
  21. 24
      app/widgets/VisioExt/VisioExt.php
  22. 3
      app/widgets/VisioExt/visioext.js
  23. 4
      app/widgets/Wall/Wall.php
  24. 2
      bootstrap.php
  25. 260
      lib/JingletoSDP.php
  26. 23
      lib/SDPtoJingle.php
  27. 139
      system/Picture.php
  28. 4
      themes/movim/css/posts.css

6
app/assets/js/movim_rpc.js

@ -104,15 +104,15 @@ function MovimRPC()
if(funcall.func != null) {
var funcs = funcall.func.split('.');
try {
//try {
if(funcs.length == 1)
window[funcs[0]](funcall.params);
else if(funcs.length == 2)
window[funcs[0]][funcs[1]](funcall.params);
}
/*}
catch(err) {
console.log("Error caught: " + err.toString() + " - " +funcall.func);
}
}*/
}
}
}

3
app/assets/js/movim_tpl.js

@ -62,5 +62,6 @@ function movim_fill(params)
function movim_delete(params)
{
target = document.getElementById(params[0]);
target.parentNode.removeChild(target);
if(target)
target.parentNode.removeChild(target);
}

2
app/models/cache/CacheDAO.php

@ -2,7 +2,7 @@
namespace modl;
class CacheDAO extends ModlSQL {
class CacheDAO extends ModlSQL {
function get($session, $key) {
$this->_sql = '
select * from cache

59
app/models/contact/Contact.php

@ -19,7 +19,6 @@ class Contact extends ModlModel {
protected $gender;
protected $marital;
protected $phototype;
protected $photobin;
protected $description;
@ -84,10 +83,6 @@ class Contact extends ModlModel {
{"type":"string", "size":1 },
"marital" :
{"type":"string", "size":20 },
"phototype" :
{"type":"string", "size":128 },
"photobin" :
{"type":"text"},
"description" :
{"type":"text"},
"mood" :
@ -135,7 +130,7 @@ class Contact extends ModlModel {
"loctimestamp" :
{"type":"date", "size":11 }
}';
parent::__construct();
}
@ -161,44 +156,58 @@ class Contact extends ModlModel {
$this->adrpostalcode = (string)$vcard->vCard->ADR->PCODE;
$this->adrcountry = (string)$vcard->vCard->ADR->CTRY;
$this->phototype = (string)$vcard->vCard->PHOTO->TYPE;
$this->photobin = (string)$vcard->vCard->PHOTO->BINVAL;
$this->description = (string)$vcard->vCard->DESC;
}
public function createThumbnails() {
if(isset($this->photobin))
\createThumbnails(strtolower($this->jid), $this->photobin);
$p = new \Picture;
$p->fromBase($this->photobin);
$p->set($this->jid);
if(isset($this->email))
\createEmailPic(strtolower($this->jid), $this->email);
}
public function getPhoto($size = 'l', $jid = false) {
if($size == 'email') {
$str = BASE_URI.'cache/'.strtolower($this->jid).'_email.jpg';
return BASE_URI.'cache/'.strtolower($this->jid).'_email.jpg';
} else {
$jid = strtolower($jid);
if($jid != false && file_exists(CACHE_PATH.$jid.'_'.$size.'.jpg')) {
$str = BASE_URI.'cache/'.strtolower($jid).'_'.$size.'.jpg';
} elseif(
isset($this->photobin)
&& (string)$this->photobin != ''
) {
$str = BASE_URI.'cache/'.strtolower($this->jid).'_'.$size.'.jpg';
if($jid)
$jid = strtolower($jid);
else
$jid = $this->jid;
$sizes = array(
'l' => 200,
'm' => 120,
's' => 50,
'xs' => 28,
'xxs' => 24
);
$p = new \Picture;
if(isset($jid)) {
if($p->get($jid, $sizes[$size])) {
return $p->get($jid, $sizes[$size]);
} else {
$out = base_convert($jid, 32, 8);
if($out == false)
$out[4] = 1;
return BASE_URI.'/themes/movim/img/default'.$out[4].'.svg';
}
} else {
if(isset($this->jid))
$out = base_convert($this->jid, 32, 8);
else
$out = base_convert(md5(openssl_random_pseudo_bytes(5)), 16, 8);
$out = base_convert(md5(openssl_random_pseudo_bytes(5)), 16, 8);
if($out == false)
$out[4] = 1;
$str = BASE_URI.'themes/movim/img/default'.$out[4].'.svg';
return BASE_URI.'/themes/movim/img/default'.$out[4].'.svg';
}
}
return $str;
}
public function setLocation($stanza) {

15
app/models/contact/ContactDAO.php

@ -41,9 +41,6 @@ class ContactDAO extends ModlSQL {
gender = :gender,
marital = :marital,
phototype = :phototype,
photobin = :photobin,
description = :description,
mood = :mood,
@ -91,9 +88,6 @@ class ContactDAO extends ModlSQL {
'gender' => $contact->gender,
'marital' => $contact->marital,
'phototype' => $contact->phototype,
'photobin' => $contact->photobin,
'description' => $contact->description,
// User Mood (contain serialized array) - XEP 0107
@ -152,9 +146,6 @@ class ContactDAO extends ModlSQL {
gender,
marital,
phototype,
photobin,
description,
mood,
@ -199,9 +190,6 @@ class ContactDAO extends ModlSQL {
:gender,
:marital,
:phototype,
:photobin,
:description,
:mood,
@ -250,9 +238,6 @@ class ContactDAO extends ModlSQL {
'gender' => $contact->gender,
'marital' => $contact->marital,
'phototype' => $contact->phototype,
'photobin' => $contact->photobin,
'description' => $contact->description,
// User Mood (contain serialized array) - XEP 0107

17
app/widgets/Avatar/Avatar.php

@ -29,7 +29,8 @@ class Avatar extends WidgetBase
$cd = new \modl\ContactDAO();
$me = $cd->get($this->user->getLogin());
if($me->photobin == "") {
$p = new Picture;
if(!$p->get($this->user->getLogin())) {
$this->view->assign(
'getavatar',
$this->genCallAjax('ajaxGetAvatar')
@ -50,6 +51,11 @@ class Avatar extends WidgetBase
function prepareForm($me) {
$avatarform = $this->tpl();
$p = new Picture;
$p->get($this->user->getLogin());
$avatarform->assign('photobin', $p->toBase());
$avatarform->assign('me', $me);
$avatarform->assign(
'submit',
@ -81,18 +87,23 @@ class Avatar extends WidgetBase
function ajaxAvatarSubmit($avatar)
{
/*
$cd = new \modl\ContactDAO();
$c = $cd->get($this->user->getLogin());
if($c == null)
$c = new modl\Contact();
$c->phototype = $avatar->phototype->value;
//$c->phototype = $avatar->phototype->value;
$c->photobin = $avatar->photobin->value;
$c->createThumbnails();
$cd->set($c);
$cd->set($c);*/
$p = new \Picture;
$p->fromBase((string)$avatar->photobin->value);
$p->set($this->user->getLogin());
$r = new moxl\AvatarSet();
$r->setData($avatar->photobin->value)->request();

5
app/widgets/Avatar/_avatar_form.tpl

@ -3,13 +3,12 @@
<legend>{$c->t('Avatar')}</legend>
<div class="element">
<label for="avatar">{$c->t('Avatar')}</label>
<img id="vCardPhotoPreview" src="data:'.$me->phototype.';base64,{$me->photobin}">
<img id="vCardPhotoPreview" src="data:image/jpeg;base64,{$photobin}">
<br /><span id="picturesize" class="clean"></span><br /><br />
<input type="file" onchange="vCardImageLoad(this.files);">
<input type="hidden" name="phototype" value="{$me->phototype}"/>
<input type="hidden" name="photobin" value="{$me->photobin}"/>
<input type="hidden" name="photobin" value="{$photobin}"/>
</div>
<div class="element" id="camdiv">

2
app/widgets/Avatar/avatar.js

@ -23,7 +23,7 @@ function vCardImageResize(img) {
var base64 = canvas.toDataURL('image/jpeg', 0.9);
var bin = base64.split(",");
document.querySelector('#vCardPhotoPreview').src = base64;
document.querySelector('input[name="phototype"]').value = 'image/jpeg';
//document.querySelector('input[name="phototype"]').value = 'image/jpeg';
document.querySelector('input[name="photobin"]').value = bin[1];
function bytesToSize(bytes) {

2
app/widgets/Chat/Chat.php

@ -364,7 +364,7 @@ class Chat extends WidgetBase
$c = new \modl\Contact();
$html .= '">
<img class="avatar" src="'.$c->getPhoto('xs', $message->jidfrom).'" />
<span class="date">'.date('H:i', strtotime($message->published)).'</span>';

2
app/widgets/Chat/chat.css

@ -173,7 +173,7 @@
background-color: white;
resize: none;
font-size: 1em;
height: 1.3em;
height: 1.5em;
overflow-y: hidden;
}

3
app/widgets/Explore/Explore.php

@ -121,7 +121,8 @@ class Explore extends WidgetCommon {
</header>
<section class="content">'.prepareString($user->description).'</section>
<footer></footer>
</article>
';
}

2
app/widgets/Presence/Presence.php

@ -44,7 +44,7 @@ class Presence extends WidgetBase
{
// We update the cache with our status and presence
$presence = Cache::c('presence');
var_dump($presence);
if($show == "boot") $show = $presence['show'];
Cache::c(
'presence',

165
app/widgets/Roster/Roster.php

@ -46,6 +46,8 @@ class Roster extends WidgetBase
$this->view->assign('toggle_cache', $this->genCallAjax('ajaxToggleCache', "'offlineshown'"));
$this->view->assign('search_contact', $this->genCallAjax('ajaxSearchContact','this.value'));
$this->view->assign('rosterlist', $this->prepareRoster());
}
function onPresence($presence)
@ -55,8 +57,24 @@ class Roster extends WidgetBase
$cd = new \modl\ContactDAO();
$c = $cd->getRosterItem($arr['jid'], true);
$caps = $this->getCaps();
if($c != null) {
$html = $this->prepareContact($c, $this->getCaps());
if($c[0]->groupname == null)
$group = t('Ungrouped');
else
$group = $c[0]->groupname;
RPC::call(
'movim_delete',
$arr['jid'],
$html /* this second parameter is just to bypass the RPC filter)*/);
RPC::call('movim_append', 'group'.$group, $html);
}
//$caps = $this->getCaps();
/*
if($c != null) {
foreach($c as $item) {
$html = $this->prepareRosterElement($item, $caps);
@ -64,7 +82,7 @@ class Roster extends WidgetBase
RPC::call(
'movim_delete',
'roster'.$item->jid.$item->ressource,
$html /* this second parameter is just to bypass the RPC filter*/);
$html this second parameter is just to bypass the RPC filter);
if($item->groupname == null)
$group = t('Ungrouped');
@ -75,14 +93,14 @@ class Roster extends WidgetBase
}
RPC::call('sortRoster');
}
} */
}
function onRoster($jid)
{
$html = $this->prepareRoster();
RPC::call('movim_fill', 'rosterlist', $html);
RPC::call('sortRoster');
//RPC::call('sortRoster');
}
/**
@ -95,6 +113,85 @@ class Roster extends WidgetBase
$r->request();
}
/**
* @brief Generate the HTML for a roster contact
* @param $contact
* @returns
*/
function prepareContact($contact, $caps)
{
$arr = array();
$jid = false;
$presencestxt = getPresencesTxt();
foreach($contact as $c) {
// We add some basic information
$arr[$c->ressource] = $c->toArray();
$arr[$c->ressource]['avatar'] = $c->getPhoto('s');
$arr[$c->ressource]['name'] = $c->getTrueName();
// Some data relative to the presence
if($c->last != null && $c->last > 60)
$arr[$c->ressource]['inactive'] = 'inactive';
else
$arr[$c->ressource]['inactive'] = '';
if($c->value && $c->value < 5) {
$arr[$c->ressource]['presencetxt'] = $presencestxt[$c->value];
} elseif($c->value == 6)
$arr[$c->ressource]['presencetxt'] = 'server_error';
else
$arr[$c->ressource]['presencetxt'] = 'offline';
// An action to open the chat widget
$arr[$c->ressource]['openchat']
= $this->genCallWidget("Chat","ajaxOpenTalk", "'".$c->jid."'");
$jid = $c->jid;
// About the entity capability
if($caps && isset($caps[$c->node.'#'.$c->ver])) {
$cap = $caps[$c->node.'#'.$c->ver];
$arr[$c->ressource]['type'] = $cap->type;
$client = $cap->name;
$client = explode(' ',$client);
$arr[$c->ressource]['client'] = strtolower(reset($client));
// Jingle support
$features = $cap->features;
$features = unserialize($features);
if(array_search('urn:xmpp:jingle:1', $features) !== null) {
if(array_search('urn:xmpp:jingle:apps:rtp:audio', $features) !== null
&& array_search('urn:xmpp:jingle:apps:rtp:video', $features) !== null
&& ( array_search('urn:xmpp:jingle:transports:ice-udp:0', $features)
|| array_search('urn:xmpp:jingle:transports:ice-udp:1', $features))
){
$arr[$c->ressource]['jingle'] = true;
} else {
$arr[$c->ressource]['jingle'] = false;
}
}
}
// Tune
$arr[$c->ressource]['tune'] = false;
if(($c->tuneartist != null && $c->tuneartist != '') ||
($c->tunetitle != null && $c->tunetitle != ''))
$arr[$c->ressource]['tune'] = true;;
}
$contactview = $this->tpl();
$contactview->assign('jid', $jid);
$contactview->assign('contact', $arr);
return $contactview->draw('_roster_contact', true);
}
/**
* @brief Generate the HTML for a roster contact
* @param $contact
@ -272,15 +369,14 @@ class Roster extends WidgetBase
*/
function prepareRoster()
{
$contactdao = new \modl\ContactDAO();
$contacts = $contactdao->getRoster();
$html = '';
$rd = new \modl\RosterLinkDAO();
//$rd = new \modl\RosterLinkDAO();
$capsarr = $this->getCaps();
/*
if(count($contacts) > 0) {
$i = 0;
@ -296,8 +392,57 @@ class Roster extends WidgetBase
'<br /><a class="button color green icon users" href="'.Route::urlize('explore').'">', '</a>').'
</span>';
}
*/
$roster = array();
return $html;
$presencestxt = getPresencesTxt();
$currentjid = false;
$currentarr = array();
foreach($contacts as $c) {
if(!isset($roster[$c->groupname])) {
$roster[$c->groupname] = new stdClass;
$roster[$c->groupname]->contacts = array();
$roster[$c->groupname]->html = '';
if($c->groupname == '')
$roster[$c->groupname]->name = t('Ungrouped');
else
$roster[$c->groupname]->name = $c->groupname;
$roster[$c->groupname]->shown = '';
// get the current showing state of the group and the offline contacts
$state = Cache::c('group'.$name);
if($state == false)
$roster[$c->groupname]->shown = 'groupshown';
$roster[$c->groupname]->toggle =
$this->genCallAjax('ajaxToggleCache', "'group".$c->groupname."'");
}
if($c->jid == $currentjid) {
array_push($currentarr, $c);
$currenthtml = $this->prepareContact($currentarr, $capsarr);
} else {
$currentarr = array();
$currenthtml = '';
array_push($currentarr, $c);
$currenthtml = $this->prepareContact($currentarr, $capsarr);
$roster[$c->groupname]->html .= $currenthtml;
}
$currentjid = $c->jid;
}
$listview = $this->tpl();
$listview->assign('roster', $roster);
return $listview->draw('_roster_list', true);
//return $roster;
//return $html;
}
/**

46
app/widgets/Roster/_roster_contact.tpl

@ -0,0 +1,46 @@
<li id="{$jid}">
<ul class="contact">
{loop="contact"}
<li
title="{$value.jid}{if="$value.status != ''"} - {$value.status}{/if}"
class="{$value.presencetxt} {$value.inactive} {if="$value.client"}client {$value.client}{/if}">
<div
class="chat on"
onclick="{$value.openchat}">
</div>
{if="$value.type == 'handheld'"}
<div class="infoicon mobile"></div>
{/if}
{if="$value.type == 'web'"}
<div class="infoicon web"></div>
{/if}
{if="$value.type == 'bot'"}
<div class="infoicon bot"></div>
{/if}
{if="$value.tune"}
<div class="infoicon tune"></div>
{/if}
{if="$value.jingle"}
<div
class="infoicon jingle"
onclick="Popup.open('{$value.jid}/{$value.ressource}')">
</div>
{/if}
<a href="{$c->route('friend', $value.jid)}">
<img
class="avatar"
src="{$value.avatar}"
/>{$value.name}
<span class="ressource">{$value.ressource}</span>
</a>
</li>
{/loop}
</ul>
</li>

6
app/widgets/Roster/_roster_list.tpl

@ -0,0 +1,6 @@
{loop="roster"}
<div id="group{$value->name}" class="{$value->shown}">
<h1 onclick="{$value->toggle}">{$key}</h1>
{$value->html}
</div>
{/loop}

169
app/widgets/Roster/roster.css

@ -61,7 +61,7 @@
cursor: pointer;
}
#roster ul#rosterlist div li {
#roster ul#rosterlist div ul.contact li {
display: none;
}
@ -74,13 +74,21 @@
height: 100%;
}
#roster ul#rosterlist div.groupshown li:not(.offline):not(.server_error) {
#roster ul#rosterlist div ul.contact li:first-child:not(.offline):not(.server_error) {
display: list-item;
}
#roster ul#rosterlist.offlineshown div.groupshown li {
display: list-item;
}
/*
#roster ul#rosterlist.offlineshown div.groupshown li:not(:first-child),
#roster ul#rosterlist.offlineshown div li:not(:first-child),
#roster ul#rosterlist div.groupshown li:not(:first-child),
#roster ul#rosterlist div li:not(:first-child) {
display: none;
}
* */
/* Show some clients icons, Xabber style */
#roster ul#rosterlist li.client a {
@ -97,6 +105,160 @@
/* The list */
#roster ul#rosterlist h1 {
padding: 1em;
color: #777;
line-height: 1em;
font-size: 1em;
text-shadow: 0px -0.1em 0px rgba(0, 0, 0, 0.5);
}
#roster ul#rosterlist h1 {
padding: 1em;
color: #777;
line-height: 1em;
font-size: 1em;
text-shadow: 0px -0.1em 0px rgba(0, 0, 0, 0.5);
}
#roster ul#rosterlist h1:hover {
cursor: pointer;
}
#roster ul#rosterlist h1:before {
content: "+";
width: 20px;
padding-right: 5px;
display: inline-block;
text-align: center;
}
#roster ul#rosterlist div.groupshown h1:before {
content: "-";
}
#roster ul#rosterlist ul.contact li img {
max-height: 3em;
}
#roster ul#rosterlist ul.contact li img {
float: left;
width: 3em;
height: 3em;
margin-right: 0.5em;
margin-top: -0.5em;
}
#roster ul#rosterlist ul.contact li a {
display: block;
white-space: nowrap;
width: auto;
overflow: hidden;
color: #BBB;
font-size: 1em;
padding-top: 0.5em;
text-overflow: ellipsis;
vertical-align: text-bottom;
text-decoration: none;
text-shadow: 0px -0.1em 0px rgba(0, 0, 0, 0.5);
}
#roster ul#rosterlist ul.contact li a span.ressource {
display: block;
font-size: 0.8em;
color: #777;
}
/* Chat button */
#roster ul#rosterlist ul.contact li .chat {
width: 0.5em;
height: 3em;
float: right;
background-color: #DDD;
transition: width 0.5s ease;
}
#roster ul#rosterlist ul.contact li:hover .chat {
width: 3em;
background-image: url(img/bubbles.svg);
background-size: 1.3em 1.3em;
background-repeat: no-repeat;
background-position: center center;
}
#roster ul#rosterlist ul.contact li .chat.on:hover {
cursor: pointer;
}
#roster ul#rosterlist ul.contact li.online .chat {
background-color: #6FCC43;
}
#roster ul#rosterlist ul.contact li.away .chat {
background-color: #FFE433;
}
#roster ul#rosterlist ul.contact li.dnd .chat {
background-color: #D92727;
}
#roster ul#rosterlist ul.contact li.xa .chat {
background-color: #442178;
}
#roster ul#rosterlist ul.contact li.inactive {
opacity: 0.5;
}
/* Icons */
#roster ul#rosterlist ul.contact li .infoicon {
width: 1.4em;
height: 1.4em;
background-size: 1.3em 1.3em;
background-repeat: no-repeat;
float: right;
margin-top: 0.8em;
margin-right: 0.2em;
}
#roster ul#rosterlist ul.contact li .mobile {
background-image: url('img/mobile.svg');
}
#roster ul#rosterlist ul.contact li .web {
background-image: url('img/earth.svg');
}
#roster ul#rosterlist ul.contact li .bot {
background-image: url('img/robot.png');
}
#roster ul#rosterlist ul.contact li .tune {
background-image: url('img/music.svg');
}
#roster ul#rosterlist ul.contact li .jingle {
background-image: url('img/call.svg');
}
#roster ul#rosterlist ul.contact li .jingle:hover {
cursor: pointer;
}
/*
#roster ul#rosterlist ul.contact li:not(:first-child) {
display: none;
}
#roster ul#rosterlist ul.contact li:first-child {
display: list-item;
}
* */
/*
#roster ul#rosterlist li:nth-child(2n) {
background-color: rgba(255, 255, 255, 0.03);
}
@ -239,7 +401,7 @@
#roster li .jingle:hover {
cursor: pointer;
}
*/
#rostermenu {
position: fixed;
bottom: 0px;
@ -303,3 +465,4 @@
color: white;
padding: 0.5em;
}

3
app/widgets/Roster/roster.js

@ -1,3 +1,4 @@
/*
function sortRoster() {
cleanMulti();
@ -49,7 +50,7 @@ function cleanMulti() {
i++;
}
}
*/
function showRoster(boolOffline) {
if(boolOffline == '1')
document.querySelector('ul#rosterlist').className = 'offlineshown';

4
app/widgets/Roster/roster.tpl

@ -9,9 +9,9 @@
onclick="focusContact();"
placeholder="{$c->t('Search');}"/>
<ul id="rosterlist" class="{$offline_shown}">
{$c->prepareRoster()}
{$rosterlist}
</ul>
<script type="text/javascript">sortRoster();</script>
<script type="text/javascript">//sortRoster();</script>
</div>
<div id="rostermenu" class="menubar">

1
app/widgets/Visio/visio.css

@ -80,7 +80,6 @@ body {
}
#visio #log {
display: none;
color: white;
position: absolute;
top: 0;

76
app/widgets/Visio/webrtc.js

@ -15,13 +15,6 @@ var sdpConstraints = {'mandatory': {
'OfferToReceiveAudio': true,
'OfferToReceiveVideo': true }};
function onIceCandidate(event) {
Visio.log('onIceCandidate');
//Visio.log(event);
//pc.addIceCandidate(event.candidate, onIceCandidateAdded, onDomError);
}
function onIceConnectionStateChanged(event) {
Visio.log('onIceConnectionStateChanged');
Visio.log(event);
@ -33,7 +26,17 @@ function onSignalingStateChanged(event) {
}
function onIceCandidateAdded(event) {
Visio.log('onIceCandateAdded');
Visio.log('onIceCandidateAdded');
Visio.log(event);
}
function onRemoteIceCandidateAdded(event) {
Visio.log('onRemoteIceCandidateAdded');
Visio.log(event);
}
function onRemoteIceCandidateError(event) {
Visio.log('onRemoteIceCandidateError');
Visio.log(event);
}
@ -49,8 +52,8 @@ function onRemoteStreamAdded(event) {
remoteStream = event.stream;
console.log(remoteStream);
console.log(vid);
//console.log(remoteStream);
//console.log(vid);
/*
audioTracks = remoteStream.getAudioTracks();
@ -75,6 +78,25 @@ function onAnswerCreated(offer) {
sendMessage(offer, true);
}
function onIceCandidate(event) {
Visio.log('onIceCandidate');
candidate = {};
/*
if(event.candidate != null) {
candidate.sdp = event.candidate.candidate;
candidate.mid = event.candidate.sdpMid;
candidate.line = event.candidate.sdpMLineIndex;
candidate.jid = VISIO_JID;
candidate.ressource = VISIO_RESSOURCE;
var msgString = JSON.stringify(candidate);
//Visio.call(['VisioExt_ajaxSendCandidate', msgString]);
}
*/
}
function sendMessage(msg, accept) {
offer = {};
offer.sdp = msg.sdp;
@ -93,12 +115,13 @@ function sendMessage(msg, accept) {
if(accept) {
Visio.log('Send the acceptance.');
//Visio.log('ACCEPTANCE ' + msg.sdp);
Visio.log('ACCEPTANCE ' + msg.sdp);
Visio.call(['VisioExt_ajaxSendAcceptance', msgString]);
} else {
Visio.log('Send the proposal.');
//Visio.log('PROPOSAL ' + msg.sdp);
Visio.log('PROPOSAL ' + msg.sdp);
console.log(msg.sdp);
Visio.call(['VisioExt_ajaxSendProposal', msgString]);
}
@ -106,8 +129,6 @@ function sendMessage(msg, accept) {
} else {
var msgString = JSON.stringify(offer);
//console.log(offer);
if(accept) {
Visio.log('Send the acceptance.');
Visio.log('ACCEPTANCE ' + msg.sdp);
@ -115,7 +136,7 @@ function sendMessage(msg, accept) {
} else {
Visio.log('Send the proposal.');
Visio.log('PROPOSAL ' + msg.sdp);
Visio.call(['VisioExt_ajaxSendProposal', msgString]);
}
}
@ -135,7 +156,7 @@ function onSetRemoteSessionDescriptionSuccess() {
function onSetRemoteSessionDescriptionError(error) {
//console.log('gnap');
//console.log(error);
console.log(error);
Visio.log('Failed to set remote session description: ' + error.message);
}
@ -145,24 +166,24 @@ function onOffer(offer) {
Visio.log('Offer received.');
Visio.log('OFFER ' + offer);
//console.log(offer);
console.log(offer);
if(!pc)
init(false);
if(offer != null) {
/*
var message = {};
message.sdp = offer;
message.type = 'offer';
console.log(message);
var desc = new RTCSessionDescription(message);
console.log(desc);
*/
/*
var desc = new RTCSessionDescription();
desc.sdp = offer;
desc.type = 'offer';
*/
pc.setRemoteDescription(desc,
onSetRemoteSessionDescriptionSuccess, onSetRemoteSessionDescriptionError);
}
@ -190,6 +211,19 @@ function onAccept(offer) {
}
}
function onCandidate(message) {
var label = {
'audio' : 0,
'video' : 1
};
var candidate = new RTCIceCandidate({sdpMLineIndex: label[message[1]],
candidate: message[0]});
//console.log(candidate);
pc.addIceCandidate(candidate, onRemoteIceCandidateAdded, onRemoteIceCandidateError);
}
function init(isCaller) {
var configuration = {"iceServers":[{"url": "stun:23.21.150.121:3478"}]};
@ -255,8 +289,6 @@ function init(isCaller) {
}
console.log(pc);
//Visio.log(pc);
}
function terminate() {

24
app/widgets/VisioExt/VisioExt.php

@ -53,11 +53,11 @@ class VisioExt extends WidgetBase
function onTransportInfo($jingle) {
$jts = new \JingletoSDP($jingle);
$sdp = $jts->generate();
RPC::call('Popup.call', 'onCandidate', $jts->generate(), $jts->media);
}
function onSessionTerminate($jingle) {
//call webrtc.js terminate()
RPC::call('Popup.call', 'terminate');
}
@ -109,6 +109,26 @@ class VisioExt extends WidgetBase
->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 moxl\JingleSessionInitiate();
$r->setTo($p->jid.'/'.$p->ressource)
->setOffer($stj->generate())
->request();
}
function build() {
}

3
app/widgets/VisioExt/visioext.js

@ -39,12 +39,13 @@ var Popup = {
},
open: function(jid) {
console.log('Opening the Popup');
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();
},

4
app/widgets/Wall/Wall.php

@ -107,7 +107,7 @@ class Wall extends WidgetCommon
$html .= $htmlmessages;
if(count($pl) > 9)
$html .= '
<div class="post">
<div class="block large">
<div class="older" onclick="'.$this->genCallAjax('ajaxGetFeed', "'".$next."'", "'".$from."'").'; this.parentNode.style.display = \'none\'">'.t('Get older posts').'</div>
</div>';
}
@ -150,7 +150,7 @@ class Wall extends WidgetCommon
<?php
} ?>
</div>
</div>
</div>
<?php
}
}

2
bootstrap.php

@ -115,6 +115,7 @@ class Bootstrap {
define('APP_NAME', 'movim');
define('APP_VERSION', $this->getVersion());
define('BASE_URI', $this->getBaseUri());
define('CACHE_URI', $this->getBaseUri() . 'cache/');
define('THEMES_PATH', DOCUMENT_ROOT . '/themes/');
define('USERS_PATH', DOCUMENT_ROOT . '/users/');
@ -173,6 +174,7 @@ class Bootstrap {
require_once(SYSTEM_PATH . "MovimException.php");
require_once(SYSTEM_PATH . "RPC.php");
require_once(SYSTEM_PATH . "User.php");
require_once(SYSTEM_PATH . "Picture.php");
}
private function loadCommonLibraries() {

260
lib/JingletoSDP.php

@ -3,6 +3,11 @@
class JingletoSDP {
private $sdp = '';
private $jingle;
private $action;
// Only used for ICE Candidate (Jingle transport-info)
public $media;
private $values = array(
'session_id' => 1,
@ -14,6 +19,8 @@ class JingletoSDP {
function __construct($jingle) {
$this->jingle = $jingle;
$this->action = (string)$this->jingle->attributes()->action;
}
function getSessionId(){
@ -62,135 +69,129 @@ class JingletoSDP {
$media_header_last_ip = null;
$sdp_media = '';
/*
if(isset($content->description->crypto)
|| isset($content->transport->fingerprint)) {
$sdp_media .=
"\na=rtcp:1 IN IP4 0.0.0.0";
} else {
$sdp_media .=
"\na=rtcp:1 IN IP4 0.0.0.0";
}
*/
if(isset($content->transport->attributes()->ufrag))
$sdp_media .= "\na=ice-ufrag:".$content->transport->attributes()->ufrag;
if(isset($content->transport->attributes()->pwd))
$sdp_media .= "\na=ice-pwd:".$content->transport->attributes()->pwd;
foreach($content->description->children() as $payload) {
switch($payload->getName()) {
case 'rtp-hdrext':
$sdp_media .=
"\na=extmap:".
$payload->attributes()->id;
if(isset($payload->attributes()->senders))
$sdp_media .= ' '.$payload->attributes()->senders;
$sdp_media .= ' '.$payload->attributes()->uri;
break;
case 'rtcp-mux':
$sdp_media .=
"\na=rtcp-mux";
case 'encryption':
if(isset($payload->crypto)) {
if(isset($content->description)) {
foreach($content->description->children() as $payload) {
switch($payload->getName()) {
case 'rtp-hdrext':
$sdp_media .=
"\na=crypto:".
$payload->crypto->attributes()->tag.' '.
$payload->crypto->attributes()->{'crypto-suite'}.' '.
$payload->crypto->attributes()->{'key-params'};
"\na=extmap:".
$payload->attributes()->id;
if(isset($payload->attributes()->senders))
$sdp_media .= ' '.$payload->attributes()->senders;
// TODO session params ?
}
break;
$sdp_media .= ' '.$payload->attributes()->uri;
break;
case 'rtcp-mux':
$sdp_media .=
"\na=rtcp-mux";
case 'encryption':
if(isset($payload->crypto)) {
$sdp_media .=
"\na=crypto:".
$payload->crypto->attributes()->tag.' '.
$payload->crypto->attributes()->{'crypto-suite'}.' '.
$payload->crypto->attributes()->{'key-params'};
case 'payload-type':
$sdp_media .=
"\na=rtpmap:".
$payload->attributes()->id;
// TODO session params ?
}
break;
case 'payload-type':
$sdp_media .=
"\na=rtpmap:".
$payload->attributes()->id;
array_push($media_header_ids, $payload->attributes()->id);
array_push($media_header_ids, $payload->attributes()->id);
if(isset($payload->attributes()->name)) {
$sdp_media .= ' '.$payload->attributes()->name;
if(isset($payload->attributes()->name)) {
$sdp_media .= ' '.$payload->attributes()->name;
if(isset($payload->attributes()->clockrate)) {
$sdp_media .= '/'.$payload->attributes()->clockrate;
if(isset($payload->attributes()->clockrate)) {
$sdp_media .= '/'.$payload->attributes()->clockrate;
if(isset($payload->attributes()->channels)) {
$sdp_media .= '/'.$payload->attributes()->channels;
if(isset($payload->attributes()->channels)) {
$sdp_media .= '/'.$payload->attributes()->channels;
}
}
}
}
$first_fmtp = true;
$first_fmtp = true;
foreach($payload->children() as $param) {
switch($param->getName()) {
case 'rtcp-fb' :
$sdp_media .=
"\na=rtcp-fb:".
$param->attributes()->id.' '.
$param->attributes()->type;
foreach($payload->children() as $param) {
switch($param->getName()) {
case 'rtcp-fb' :
$sdp_media .=
"\na=rtcp-fb:".
$param->attributes()->id.' '.
$param->attributes()->type;
if(isset($param->attributes()->subtype)) {
$sdp_media .= ' '.$param->attributes()->subtype;
}
if(isset($param->attributes()->subtype)) {
$sdp_media .= ' '.$param->attributes()->subtype;
}
break;
break;
// http://xmpp.org/extensions/xep-0167.html#format
case 'parameter' :
if($first_fmtp) {
$sdp_media .=
"\na=fmtp:".
$payload->attributes()->id.
' ';
} else {
$sdp_media .= '; ';
}
// http://xmpp.org/extensions/xep-0167.html#format
case 'parameter' :
if($first_fmtp) {
$sdp_media .=
"\na=fmtp:".
$payload->attributes()->id.
' ';
} else {
$sdp_media .= '; ';
}
if(isset($param->attributes()->name)) {
$sdp_media .=
$param->attributes()->name.
'=';
}
if(isset($param->attributes()->name)) {
$sdp_media .=
$param->attributes()->name.
'=';
}
$param->attributes()->value;
$sdp_media .=
$param->attributes()->value;
$first_fmtp = false;
break;
}
$first_fmtp = false;
break;
// TODO rtcp_fb_trr_int ?
}
break;
// TODO rtcp_fb_trr_int ?
}
break;
case 'source':
foreach($payload->children() as $s) {
$sdp_media .=
"\na=ssrc:".$payload->attributes()->id.' '.
$s->attributes()->name.':'.
$s->attributes()->value;
}
break;
case 'source':
foreach($payload->children() as $s) {
$sdp_media .=
"\na=ssrc:".$payload->attributes()->id.' '.
$s->attributes()->name.':'.
$s->attributes()->value;
}
break;
}
// TODO sendrecv ?
}
// TODO sendrecv ?
}
if(isset($content->description->attributes()->ptime)) {
if(isset($content->description)
&& isset($content->description->attributes()->ptime)) {
$sdp_media .=
"\na=ptime:".$content->description->attributes()->ptime;
}
if(isset($content->description->attributes()->maxptime)) {
if(isset($content->description)
&& isset($content->description->attributes()->maxptime)) {
$sdp_media .=
"\na=maxptime:".$content->description->attributes()->maxptime;
}
@ -243,6 +244,9 @@ class JingletoSDP {
$sdp_media .=
' raddr '.$payload->attributes()->{'rel-addr'}.
' rport '.$payload->attributes()->{'rel-port'};
if($media_header_first_port == null)
$media_header_first_port = $payload->attributes()->port;
}
if(isset($payload->attributes()->generation)) {
$sdp_media .=
@ -251,43 +255,61 @@ class JingletoSDP {
' id '.$payload->attributes()->id;
}
if($media_header_first_port == null)
$media_header_first_port = $payload->attributes()->port;
$media_header_last_ip = $payload->attributes()->ip;
break;
}
}
$sdp_media_header =
"\nm=".$content->description->attributes()->media.
' '.$media_header_first_port.' ';
if($media_header_first_port == null)
$media_header_first_port = 1;
if(isset($content->transport->sctpmap)) {
$sdp_media_header .= 'DTLS/SCTP';
} elseif(isset($content->description->crypto)
|| isset($content->transport->fingerprint)) {
$sdp_media_header .= 'RTP/SAVPF';
if($media_header_last_ip == null)
$media_header_last_ip = '0.0.0.0';
if(isset($content->description))
$this->media = (string)$content->description->attributes()->media;
else
$this->media = (string)$content->attributes()->name;
if($this->action != 'transport-info') {
$sdp_media_header =
"\nm=".$this->media.
' '.$media_header_first_port.' ';
if(isset($content->transport->sctpmap)) {
$sdp_media_header .= 'DTLS/SCTP';
} elseif(isset($content->description->crypto)
|| isset($content->transport->fingerprint)) {
$sdp_media_header .= 'RTP/SAVPF';
} else {
$sdp_media_header .= 'RTP/AVP';
}
$sdp_media_header = $sdp_media_header.' '.implode(' ', $media_header_ids);
$sdp_medias .=
$sdp_media_header.
"\nc=IN IP4 ".$media_header_last_ip.
$sdp_media;
//"\na=sendrecv";
} else {
$sdp_media_header .= 'RTP/AVPF';
$sdp_medias = $sdp_media;
}
$sdp_media_header = $sdp_media_header.' '.implode(' ', $media_header_ids);
}
$sdp_medias .=
$sdp_media_header.
"\nc=IN IP4 ".$media_header_last_ip.
$sdp_media;
if($this->action != 'transport-info') {
$this->sdp .= "\n".$sdp_version;
$this->sdp .= "\n".$sdp_origin;
$this->sdp .= "\n".$sdp_session_name;
$this->sdp .= "\n".$sdp_timing;
}
$this->sdp .= $sdp_version;
$this->sdp .= "\n".$sdp_origin;
$this->sdp .= "\n".$sdp_session_name;
$this->sdp .= "\n".$sdp_timing;
$this->sdp .= $sdp_medias;
//$this->sdp = (string)$this->jingle->sdp;
return $this->sdp;
return $this->sdp."\n";
}
}

23
lib/SDPtoJingle.php

@ -7,6 +7,8 @@ class SDPtoJingle {
private $content = null;
private $transport = null;
private $action;
// Move the global fingerprint into each medias
private $global_fingerprint = array();
@ -41,6 +43,8 @@ class SDPtoJingle {
$this->jingle->addAttribute('action',$action);
$this->jingle->addAttribute('initiator',$initiator);
$this->jingle->addAttribute('responder',$responder);
$this->action = $action;
}
function getSessionId(){
@ -72,9 +76,11 @@ class SDPtoJingle {
$this->content->addAttribute('name', $matches[1]);
// The description node
$description = $this->content->addChild('description');
$description->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:1");
$description->addAttribute('media', $matches[1]);
if($this->action != 'transport-info') {
$description = $this->content->addChild('description');
$description->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:1");
$description->addAttribute('media', $matches[1]);
}
if(!empty($this->global_fingerprint)) {
$fingerprint = $this->transport->addChild('fingerprint', $this->global_fingerprint['fingerprint']);
@ -107,10 +113,8 @@ class SDPtoJingle {
// http://xmpp.org/extensions/xep-0167.html#format
case 'fmtp':
/*
* This work only if fmtp is added just after
* the correspondant rtpmap
*/
// This work only if fmtp is added just after
// the correspondant rtpmap
if($matches[1] == $payloadtype->attributes()->id) {
$params = explode(';', $matches[2]);
@ -178,7 +182,8 @@ class SDPtoJingle {
$rtphdrext->addAttribute('xmlns', "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0");
$rtphdrext->addAttribute('id', $matches[1]);
$rtphdrext->addAttribute('uri', $matches[4]);
$rtphdrext->addAttribute('senders', $matches[3]);
if(isset($matches[3]) && $matches[3] != '')
$rtphdrext->addAttribute('senders', $matches[3]);
break;
// http://xmpp.org/extensions/inbox/jingle-source.html
@ -291,6 +296,8 @@ class SDPtoJingle {
}
}
}
//$this->jingle->addChild('sdp', $this->sdp);
// We reindent properly the Jingle package
$xml = $this->jingle->asXML();

139
system/Picture.php

@ -0,0 +1,139 @@
<?php
class Picture {
private $_path = CACHE_PATH;
private $_uri = CACHE_URI;
private $_key;
private $_bin = false;
/**
* @desc Load a bin picture from a path
*/
public function fromPath($path) {
$handle = fopen($path, "r");
$this->_bin = fread($handle, filesize($path));
fclose($handle);
}
/**
* @desc Load a bin picture from a base64
*/
public function fromBase($base = false) {
if($base) {
$this->_bin = (string)base64_decode((string)$base);
}
}
/**
* @desc Convert to a base64
*/
public function toBase() {
if($this->_bin)
return base64_encode($this->_bin);
else
return false;
}
/**
* @desc Get a picture of the current size
* @param $key The key of the picture
* @param $size The size requested
* @return The url of the picture
*/
public function get($key, $size = false) {
$this->_key = $key;
$original = $this->_path.md5($this->_key).'.jpg';
// We request the original picture
if($size == false) {
if(file_exists($original)) {
$this->fromPath($original);
return $this->_uri.md5($this->_key).'.jpg';
} else {
return false;
}
// We request a specific size
} else {
if(file_exists($this->_path.md5($this->_key).'_'.$size.'.jpg')) {
$this->fromPath($this->_path.md5($this->_key).'_'.$size.'.jpg');
return $this->_uri.md5($this->_key).'_'.$size.'.jpg';
} else {
if(file_exists($original)) {
$this->fromPath($original);
$this->createThumbnail($size);
return $this->_uri.md5($this->_key).'_'.$size.'.jpg';
} else {
return false;
}
}
}
}
/**
* @desc Save a picture (original size)
* @param $key The key of the picture
*/
public function set($key) {
$this->_key = $key;
$path = $this->_path.md5($this->_key).'.jpg';
// If the file exist we replace it
if(file_exists($path)) {
unlink($path);
// And destroy all the thumbnails
foreach(
glob(
$this->_path.
md5($key).
'*.jpg',
GLOB_NOSORT
) as $path_thumb) {
unlink($path_thumb);
}
}
if($this->_bin) {
$source = imagecreatefromstring($this->_bin);
imagejpeg($source, $path, 95);
imagedestroy($source);
}
}
/**
* @desc Create a thumbnail of the picture and save it
* @param $size The size requested
*/
private function createThumbnail($size) {
$path = $this->_path.md5($this->_key).'_'.$size.'.jpg';
$thumb = imagecreatetruecolor($size, $size);
$white = imagecolorallocate($thumb, 255, 255, 255);
imagefill($thumb, 0, 0, $white);
$source = imagecreatefromstring($this->_bin);
$width = imagesx($source);
$height = imagesy($source);
if($width >= $height) {
// For landscape images
$x_offset = ($width - $height) / 2;
$y_offset = 0;
$square_size = $width - ($x_offset * 2);
} else {
// For portrait and square images
$x_offset = 0;
$y_offset = ($height - $width) / 2;
$square_size = $height - ($y_offset * 2);
}
if($source) {
imagecopyresampled($thumb, $source, 0, 0, $x_offset, $y_offset, $size, $size, $square_size, $square_size);
imagejpeg($thumb, $path, 95);
imagedestroy($thumb);
}
}
}

4
themes/movim/css/posts.css

@ -46,6 +46,10 @@ article footer {
padding-bottom: 1em;
}
article:nth-last-child(-n+2) footer {
border-bottom: none;
}
article footer:after {
content: "";
clear: both;

Loading…
Cancel
Save