Merge branch 'master' of ssh://stash.freeswitch.org:7999/fs/freeswitch

This commit is contained in:
Steve Underwood 2015-12-05 01:16:24 +08:00
commit 69697ea6ce
34 changed files with 627 additions and 129 deletions

5
debian/bootstrap.sh vendored
View File

@ -1008,7 +1008,6 @@ EOF
print_conf_install () { print_conf_install () {
cat <<EOF cat <<EOF
conf/${conf} /usr/share/freeswitch/conf conf/${conf} /usr/share/freeswitch/conf
/usr/share/freeswitch/fonts
EOF EOF
} }
@ -1345,6 +1344,10 @@ grep -e '^Package:' control | grep -v '^freeswitch-all$' | while xread l; do
m="${l#*: }" m="${l#*: }"
conf_merge freeswitch-all.install $m.install conf_merge freeswitch-all.install $m.install
done done
echo "/usr/share/freeswitch/fonts" >> freeswitch-all.install
echo "/var/lib/freeswitch/images" >> freeswitch-all.install
for x in postinst postrm preinst prerm; do for x in postinst postrm preinst prerm; do
cp -a freeswitch.$x freeswitch-all.$x cp -a freeswitch.$x freeswitch-all.$x
done done

View File

@ -542,17 +542,10 @@
var bestFrameRate = obj.options.videoParams.vertoBestFrameRate; var bestFrameRate = obj.options.videoParams.vertoBestFrameRate;
delete obj.options.videoParams.vertoBestFrameRate; delete obj.options.videoParams.vertoBestFrameRate;
if (window.moz) { video = {
video = obj.options.videoParams; mandatory: obj.options.videoParams,
if (!video.width) video.width = video.minWidth; optional: []
if (!video.height) video.height = video.minHeight; }
if (!video.frameRate) video.frameRate = video.minFrameRate;
} else {
video = {
mandatory: obj.options.videoParams,
optional: []
}
}
var useVideo = obj.options.useVideo; var useVideo = obj.options.useVideo;
@ -1124,13 +1117,6 @@
"maxHeight": h "maxHeight": h
}; };
if (window.moz) {
video = video.mandatory;
if (!video.width) video.width = video.minWidth;
if (!video.height) video.height = video.minHeight;
if (!video.frameRate) video.frameRate = video.minFrameRate;
}
getUserMedia({ getUserMedia({
constraints: { constraints: {
audio: ttl++ == 0, audio: ttl++ == 0,

View File

@ -1697,7 +1697,22 @@
$(vlselect_id).append(new Option("Choose a Layout", "none")); $(vlselect_id).append(new Option("Choose a Layout", "none"));
if (e.data.responseData) { if (e.data.responseData) {
options = e.data.responseData.sort(); var rdata = [];
for (var i in e.data.responseData) {
rdata.push(e.data.responseData[i].name);
}
options = rdata.sort(function(a, b) {
var ga = a.substring(0, 6) == "group:" ? true : false;
var gb = b.substring(0, 6) == "group:" ? true : false;
if ((ga || gb) && ga != gb) {
return ga ? -1 : 1;
}
return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : -1 ) );
});
for (var i in options) { for (var i in options) {
$(vlselect_id).append(new Option(options[i], options[i])); $(vlselect_id).append(new Option(options[i], options[i]));

View File

@ -21,7 +21,6 @@ body {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
width: 160px;
display: inline-block; display: inline-block;
} }
@ -604,12 +603,24 @@ body .modal-body .btn-group .btn.active {
transition-delay:0s; transition-delay:0s;
} }
#incall .dropdown-menu .selected {
background-color: #ccc;
color: white;
}
#incall .dropdown-menu .selected:hover {
background-color: #ccc;
color: white;
cursor: pointer;
}
#incall .video-hover-buttons .btn-group .dropdown-menu { #incall .video-hover-buttons .btn-group .dropdown-menu {
max-height: 200px; max-height: 200px;
overflow: auto; overflow: auto;
} }
#incall .video-hover-buttons .btn-group ul li a:hover { #incall .video-hover-buttons .btn-group ul li a:not(.selected):hover {
background-color: #EEE; background-color: #EEE;
cursor: pointer; cursor: pointer;
} }
@ -850,6 +861,10 @@ body .modal-body .btn-group .btn.active {
padding-right: 360px; padding-right: 360px;
} }
.watcher #wrapper {
padding-right: 0;
}
#wrapper.toggled { #wrapper.toggled {
padding-right: 0; padding-right: 0;
} }
@ -906,13 +921,11 @@ body .modal-body .btn-group .btn.active {
} }
.members-name { .members-name {
width: 160px; width: 140px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.members-number { .members-number {
width: 140px;
font-size: 10px; font-size: 10px;
} }
@ -970,6 +983,7 @@ body .modal-body .btn-group .btn.active {
display: inline-block; display: inline-block;
line-height: 16px; line-height: 16px;
margin-top: -3px; margin-top: -3px;
width: 140px;
} }
.chat-members .chat-members-status i { .chat-members .chat-members-status i {
@ -1018,6 +1032,17 @@ body .modal-body .btn-group .btn.active {
vertical-align: -2px; vertical-align: -2px;
} }
.chat-members .resevartion-menu .icon {
color: #C5C5C5;
}
.chat-members .resevartion-menu .dropdown-menu {
min-width: 0;
}
.chat-members .resevartion-menu .dropdown-menu .selected {
font-weight: bold;
}
/*.chat-messages {*/ /*.chat-messages {*/
/*border-top: 1px solid #E5E5E5;*/ /*border-top: 1px solid #E5E5E5;*/
@ -1545,3 +1570,42 @@ body:-webkit-full-screen #incall .video-footer {
#preview .refresh { #preview .refresh {
margin: 15px 0px 0px 0px; margin: 15px 0px 0px 0px;
} }
.watcher {
padding: 0;
background-color: #333333;
}
.watcher .navbar, .watcher #sidebar-wrapper, .watcher #dialpad {
display: none;
}
.watcher #wrapper.toggled {
padding-right: 0;
}
.watcher #incall .panel {
margin: 0;
}
.watcher #video-tag-wrapper {
background: linear-gradient(to bottom, #272627, #27252A);
background-color: #27252A;
}
.watcher #incall .video-call {
width: 100%;
height: 100%;
padding: 0;
max-width: none;
max-height: none;
}
.watcher #webcam {
max-width: 160.78vh;
margin: auto;
}
.watcher .spinner {
top: 20%;
}

View File

@ -23,12 +23,12 @@
</span> </span>
<!-- FIXME(italo): Put this whole block in a flex box to avoid defining fixed width.--> <!-- FIXME(italo): Put this whole block in a flex box to avoid defining fixed width.-->
<h4 class="chat-members-name"> <h4 class="chat-members-name">
<div class="members-name">{{ member.name }}</div> <div class="ellipsis members-name">{{ member.name }}</div>
<small class="ellipsis members-number">({{ member.number }})</small> <small class="ellipsis members-number">({{ member.number }})</small>
<div class="members-badges"> <div class="members-badges">
<div ng-if="member.status.video.floor" class="label badge-floor" ng-class="{'label-danger': member.status.video.floorLocked, 'label-info': !member.status.video.floorLocked}"><i class="mdi mdi-action-https lock-floor" ng-if="member.status.video.floorLocked"></i> <span>Floor</span></div> <div ng-if="member.status.video.floor" class="label badge-floor" ng-class="{'label-danger': member.status.video.floorLocked, 'label-info': !member.status.video.floorLocked}"><i class="mdi mdi-action-https lock-floor" ng-if="member.status.video.floorLocked"></i> <span>Floor</span></div>
<div ng-if="member.status.video.reservationID == 'presenter'" class="label label-info">Presenter</div> <div class="label label-info text-capitalize">{{ member.status.video.reservationID }}</div>
<div ng-if="member.status.video.screenShare" class="label label-info">Screen Share</div> <div ng-if="member.status.video.screenShare" class="label label-info">Screen Share</div>
</div> </div>
</h4> </h4>
@ -57,12 +57,6 @@
Mute/Unmute Video Mute/Unmute Video
</a> </a>
</li> </li>
<li>
<a href="" ng-click="confPresenter(member.id)">
<span class="mdi-fw mdi-action-picture-in-picture"></span>
Presenter
</a>
</li>
<li> <li>
<a href="" ng-click="confVideoFloor(member.id)"> <a href="" ng-click="confVideoFloor(member.id)">
<span class="mdi-fw mdi-action-aspect-ratio"></span> <span class="mdi-fw mdi-action-aspect-ratio"></span>
@ -99,6 +93,39 @@
Transfer Transfer
</a> </a>
</li> </li>
<li>
<a href="" ng-click="confCanvasIn(member.id)">
<span class="mdi-fw mdi-image-switch-video"></span>
Canvas In
</a>
</li>
<li>
<a href="" ng-click="confCanvasOut(member.id)">
<span class="mdi-fw mdi-action-swap-horiz"></span>
Canvas Out
</a>
</li>
<li>
<a href="" ng-click="confLayer(member.id)">
<span class="mdi-fw mdi-action-view-carousel"></span>
Layer
</a>
</li>
</ul>
</div>
</div>
<div class="pull-right resevartion-menu chat-members-action" ng-show="verto.data.confRole == 'moderator' && resIDs.length > 0">
<div class="btn-group">
<button type="button" class="btn btn-xs dropdown-toggle" data-toggle="dropdown">
<i class="mdi-action-picture-in-picture icon" style="margin-right: 0px;"></i>
</button>
<ul class="dropdown-menu slidedown pull-right">
<li ng-repeat="resID in resIDs">
<a href="" class="text-capitalize" ng-class="{ 'selected': resID == member.status.video.reservationID }" ng-click="confResID(member.id, resID)">
{{ resID }}
</a>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class="centered-block-frame" id="incall"> <div class="centered-block-frame" id="incall">
<div class="col-md-12 centered-block" ng-class="{'video-call': storage.data.videoCall, 'phone-call': !storage.data.videoCall}"> <div class="col-md-12 centered-block" ng-class="storage.data.videoCall || watcher ? 'video-call' : 'phone-call'">
<div class="slide-animate height100" ng-include="callTemplate"></div> <div class="slide-animate height100" ng-include="callTemplate"></div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
<div class="panel panel-default shadow-z-0"> <div class="panel panel-default shadow-z-0">
<div class="video-wrapper"> <div class="video-wrapper">
<div class="video-hover-buttons" ng-show="verto.data.callState == 'active'"> <div class="video-hover-buttons" ng-show="verto.data.callState == 'active' && !watcher">
<div id="moderator-tools" ng-show="verto.data.confRole == 'moderator'"> <div id="moderator-tools" ng-show="verto.data.confRole == 'moderator'">
<button tooltip-placement="bottom" tooltip-title="Play" uib-tooltip="Play" <button tooltip-placement="bottom" tooltip-title="Play" uib-tooltip="Play"
class="btn btn-material-blue-900" ng-click="play()"> class="btn btn-material-blue-900" ng-click="play()">
@ -31,7 +31,7 @@
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li ng-repeat="layout in verto.data.confLayouts"> <li ng-repeat="layout in verto.data.confLayouts">
<a ng-click="confChangeVideoLayout(layout)">{{ layout }}</a> <a ng-click="confChangeVideoLayout(layout)" ng-class="{ 'selected': layout == videoLayout }">{{ layout }}</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -68,6 +68,17 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="btn-group" ng-show="conf.canvasCount > 1">
<button tooltip-placement="bottom" tooltip-title="Popup" uib-tooltips="Popup" type="button" class="btn btn-material-blue-900 dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="mdi-image-filter-none"></i>
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li ng-repeat="canvas in canvases">
<a ng-click="confPopup(canvas.id)">{{ canvas.name }}</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
<div class="video-tag-wrapper" id="video-tag-wrapper" ng-dblclick="goFullscreen()" show-controls> <div class="video-tag-wrapper" id="video-tag-wrapper" ng-dblclick="goFullscreen()" show-controls>
@ -80,13 +91,14 @@
<div class="row"> <div class="row">
<div class="col-md-6 col-xs-6 text-left"> <div class="col-md-6 col-xs-6 text-left">
<div class="video-timer"> <div class="video-timer">
<timer start-time="start_time" autostart="false" interval="1000">{{hhours}}:{{mminutes}}:{{sseconds}}</timer> <span ng-show="watcher" style="font-size: 18px">Room {{ extension }} - Canvas {{ canvasID }}</span>
<timer start-time="start_time" autostart="false" interval="1000" ng-if="!watcher">{{hhours}}:{{mminutes}}:{{sseconds}}</timer>
</div> </div>
</div> </div>
<div class="col-md-6 col-xs-6 text-right"> <div class="col-md-6 col-xs-6 text-right">
<button class="btn btn-danger" ng-click="hangup()"> <button class="btn btn-danger" ng-click="hangup()">
<i class="mdi-communication-call-end"></i> <i class="mdi-communication-call-end"></i>
End Call {{ watcher ? 'Close' : 'End Call' }}
</button> </button>
</div> </div>
</div> </div>

View File

@ -49,6 +49,39 @@
}); });
}); });
$rootScope.$on('changedVideoLayout', function(event, layout) {
$scope.resIDs = getResByLayout(layout);
// remove resIDs param to clear every members resID.
// passing $scope.resIDs results in preserving resIDs compatible
// with the current layout
clearMembersResID($scope.resIDs);
});
$rootScope.$on('conference.canvasInfo', function(event, data) {
$scope.currentLayout = data[0].layoutName;
$scope.resIDs = getResByLayout($scope.currentLayout);
});
function getResByLayout(layout) {
var layoutsData = verto.data.confLayoutsData;
for (var i = 0; i < layoutsData.length; i++) {
if (layoutsData[i].name === layout) {
return layoutsData[i].resIDS;
}
}
}
// @preserve - a array of values to be preserved
function clearMembersResID(preserve) {
$scope.members.forEach(function(member) {
var resID = member.status.video.reservationID;
if (resID && preserve && preserve.indexOf(resID) !== -1) return;
$scope.confResID(member.id, resID);
});
};
function findMemberByUUID(uuid) { function findMemberByUUID(uuid) {
var found = false; var found = false;
for (var idx in $scope.members) { for (var idx in $scope.members) {
@ -98,6 +131,11 @@
}); });
$rootScope.$on('members.del', function(event, uuid) { $rootScope.$on('members.del', function(event, uuid) {
if ($rootScope.watcher && $rootScope.master === uuid) {
verto.hangup();
window.close();
}
$scope.$apply(function() { $scope.$apply(function() {
var memberIdx = findMemberByUUID(uuid); var memberIdx = findMemberByUUID(uuid);
if (memberIdx != -1) { if (memberIdx != -1) {
@ -171,6 +209,11 @@
verto.data.conf.presenter(memberID); verto.data.conf.presenter(memberID);
}; };
$scope.confResID = function(memberID, resID) {
console.log('Set', memberID, 'to', resID);
verto.setResevartionId(memberID, resID);
};
$scope.confVideoFloor = function(memberID) { $scope.confVideoFloor = function(memberID) {
console.log('$scope.confVideoFloor'); console.log('$scope.confVideoFloor');
verto.data.conf.videoFloor(memberID); verto.data.conf.videoFloor(memberID);
@ -191,6 +234,41 @@
}); });
}; };
$scope.confCanvasIn = function(memberID, canvasID) {
if (canvasID) {
verto.setCanvasIn(memberID, canvasID);
return;
}
shortPrompt('Please insert the Canvas Id', function(canvasID) {
console.log(memberID, canvasID);
verto.setCanvasIn(memberID, canvasID);
});
};
$scope.confCanvasOut = function(memberID, canvasID) {
if (canvasID) {
verto.setCanvasOut(memberID, canvasID);
return;
}
shortPrompt('Please insert the Canvas Id', function(canvasID) {
verto.setCanvasOut(memberID, canvasID);
});
};
$scope.confLayer = function(memberID, canvasID) {
if (canvasID) {
verto.setLayer(memberID, canvasID);
return;
}
shortPrompt('Please insert the Layer', function(canvasID) {
verto.setLayer(memberID, canvasID);
});
};
$scope.confResetBanner = function(memberID) { $scope.confResetBanner = function(memberID) {
console.log('$scope.confResetBanner'); console.log('$scope.confResetBanner');
var text = 'reset'; var text = 'reset';
@ -221,6 +299,19 @@
} }
}); });
}; };
function shortPrompt(text, cb) {
prompt({
title: text,
input: true,
label: '',
value: '',
}).then(function(val) {
if (val && cb) {
cb(val);
}
});
}
} }
]); ]);

View File

@ -10,6 +10,15 @@
eventQueue.process(); eventQueue.process();
if ($location.search().autocall) {
$rootScope.dialpadNumber = $location.search().autocall;
delete $location.search().autocall;
call($rootScope.dialpadNumber);
if($rootScope.watcher) {
return;
}
}
$scope.call_history = CallHistory.all(); $scope.call_history = CallHistory.all();
$scope.history_control = CallHistory.all_control(); $scope.history_control = CallHistory.all_control();
$scope.has_history = Object.keys($scope.call_history).length; $scope.has_history = Object.keys($scope.call_history).length;
@ -32,11 +41,6 @@
/** /**
* fill dialpad via querystring [?autocall=\d+] * fill dialpad via querystring [?autocall=\d+]
*/ */
if ($location.search().autocall) {
$rootScope.dialpadNumber = $location.search().autocall;
delete $location.search().autocall;
call($rootScope.dialpadNumber);
}
/** /**
* fill in dialpad via config.json * fill in dialpad via config.json
@ -83,6 +87,13 @@
return false; return false;
} }
if (extension.indexOf('-canvas-') != -1) {
$rootScope.watcher = true;
verto.call($rootScope.dialpadNumber, null, { useCamera: false, useMic: false, caller_id_name: null, userVariables: {}, caller_id_number: null, mirrorInput: false });
$location.path('/incall');
return;
}
storage.data.mutedVideo = false; storage.data.mutedVideo = false;
storage.data.mutedMic = false; storage.data.mutedMic = false;

View File

@ -15,7 +15,6 @@
$scope.dialpadTemplate = ''; $scope.dialpadTemplate = '';
$scope.incall = true; $scope.incall = true;
if (storage.data.videoCall) { if (storage.data.videoCall) {
$scope.callTemplate = 'partials/video_call.html'; $scope.callTemplate = 'partials/video_call.html';
} }
@ -25,6 +24,7 @@
if($scope.chatStatus) { if($scope.chatStatus) {
$scope.openChat(); $scope.openChat();
} }
buildCanvasesData();
}); });
}); });
@ -73,6 +73,8 @@
$scope.confChangeVideoLayout = function(layout) { $scope.confChangeVideoLayout = function(layout) {
verto.data.conf.setVideoLayout(layout); verto.data.conf.setVideoLayout(layout);
$scope.videoLayout = layout;
$rootScope.$emit('changedVideoLayout', layout);
}; };
$scope.confChangeSpeaker = function(speakerId) { $scope.confChangeSpeaker = function(speakerId) {
@ -80,6 +82,24 @@
$rootScope.$emit('changedSpeaker', speakerId); $rootScope.$emit('changedSpeaker', speakerId);
}; };
$scope.confPopup = function(canvas_id) {
var video = document.getElementById('webcam');
var s = window.location.href;
var curCall = verto.data.call.callID;
var extension = verto.data.call.params.remote_caller_id_number;
var width = webcam.offsetWidth;
var height = webcam.offsetHeight + 100;
var x = (screen.width - width)/2
var y = (screen.height - height)/2
s = s.replace(/\#.*/, '');
s += "#/?sessid=random&master=" + curCall + "&watcher=true&extension=" + extension+ "&canvas_id=" + canvas_id;
console.log("opening new window to " + s);
var popup = window.open(s, "canvas_window_" + canvas_id, "toolbar=0,location=0,menubar=0,directories=0,width=" + width + ",height=" + height, + ',left=' + x + ',top=' + y);
popup.moveTo(x, y);
};
$scope.screenshare = function() { $scope.screenshare = function() {
if(verto.data.shareCall) { if(verto.data.shareCall) {
verto.screenshareHangup(); verto.screenshareHangup();
@ -88,6 +108,14 @@
verto.screenshare(storage.data.called_number); verto.screenshare(storage.data.called_number);
}; };
function buildCanvasesData() {
$scope.conf = verto.data.conf.params.laData;
$scope.canvases = [{ id: 1, name: 'Super Canvas' }];
for (var i = 1; i < $scope.conf.canvasCount; i++) {
$scope.canvases.push({ id: i+1, name: 'Canvas ' + (i+1) });
}
}
$scope.muteMic = verto.muteMic; $scope.muteMic = verto.muteMic;
$scope.muteVideo = verto.muteVideo; $scope.muteVideo = verto.muteVideo;

View File

@ -8,6 +8,24 @@
console.debug('Executing MainController.'); console.debug('Executing MainController.');
$rootScope.master = $location.search().master;
if ($location.search().watcher === 'true') {
$rootScope.watcher = true;
angular.element(document.body).addClass('watcher');
var dialpad;
var extension = dialpad = $location.search().extension;
var canvasID = $location.search().canvas_id;
if (dialpad) {
if (canvasID) {
dialpad += '-canvas-' + canvasID;
}
$rootScope.extension = extension;
$rootScope.canvasID = canvasID;
$location.search().autocall = dialpad;
}
}
var myVideo = document.getElementById("webcam"); var myVideo = document.getElementById("webcam");
$scope.verto = verto; $scope.verto = verto;
$scope.storage = storage; $scope.storage = storage;
@ -432,6 +450,11 @@
return; return;
} }
if ($rootScope.watcher) {
window.close();
return;
}
//var hangupCallback = function(v, hangup) { //var hangupCallback = function(v, hangup) {
// if (hangup) { // if (hangup) {
// $location.path('/dialpad'); // $location.path('/dialpad');

View File

@ -32,4 +32,4 @@
} }
}); });
})(); })();

View File

@ -391,7 +391,27 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
if (message.action == 'response') { if (message.action == 'response') {
// This is a response with the video layouts list. // This is a response with the video layouts list.
if (message['conf-command'] == 'list-videoLayouts') { if (message['conf-command'] == 'list-videoLayouts') {
data.confLayouts = message.responseData.sort(); var rdata = [];
for (var i in message.responseData) {
rdata.push(message.responseData[i].name);
}
var options = rdata.sort(function(a, b) {
var ga = a.substring(0, 6) == "group:" ? true : false;
var gb = b.substring(0, 6) == "group:" ? true : false;
if ((ga || gb) && ga != gb) {
return ga ? -1 : 1;
}
return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : -1 ) );
});
data.confLayoutsData = message.responseData;
data.confLayouts = options;
} else if (message['conf-command'] == 'canvasInfo') {
data.canvasInfo = message.responseData;
$rootScope.$emit('conference.canvasInfo', message.responseData);
} else { } else {
$rootScope.$emit('conference.broadcast', message); $rootScope.$emit('conference.broadcast', message);
} }
@ -402,6 +422,7 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
if (data.confRole == "moderator") { if (data.confRole == "moderator") {
console.log('>>> conf.listVideoLayouts();'); console.log('>>> conf.listVideoLayouts();');
conf.listVideoLayouts(); conf.listVideoLayouts();
conf.modCommand('canvasInfo');
} }
data.conf = conf; data.conf = conf;
@ -584,6 +605,11 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
var that = this; var that = this;
function ourBootstrap() { function ourBootstrap() {
var sessid = $location.search().sessid;
if (sessid === 'random') {
sessid = $.verto.genUUID();
$location.search().sessid = sessid;
}
// Checking if we have a failed connection attempt before // Checking if we have a failed connection attempt before
// connecting again. // connecting again.
if (data.instance && !data.instance.rpcClient.socketReady()) { if (data.instance && !data.instance.rpcClient.socketReady()) {
@ -604,6 +630,7 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
googNoiseSuppression: storage.data.googNoiseSuppression || true, googNoiseSuppression: storage.data.googNoiseSuppression || true,
googHighpassFilter: storage.data.googHighpassFilter || true googHighpassFilter: storage.data.googHighpassFilter || true
}, },
sessid: sessid,
iceServers: storage.data.useSTUN iceServers: storage.data.useSTUN
}, callbacks); }, callbacks);
@ -614,6 +641,7 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
jQuery.verto.unloadJobs.push(function() { jQuery.verto.unloadJobs.push(function() {
that.reloaded = true; that.reloaded = true;
}); });
data.instance.deviceParams({ data.instance.deviceParams({
useCamera: storage.data.selectedVideo, useCamera: storage.data.selectedVideo,
useSpeak: storage.data.selectedSpeaker, useSpeak: storage.data.selectedSpeaker,
@ -674,10 +702,10 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
* *
* @param callback * @param callback
*/ */
call: function(destination, callback) { call: function(destination, callback, custom) {
console.debug('Attempting to call destination ' + destination + '.'); console.debug('Attempting to call destination ' + destination + '.');
var call = data.instance.newCall({ var call = data.instance.newCall(angular.extend({
destination_number: destination, destination_number: destination,
caller_id_name: data.name, caller_id_name: data.name,
caller_id_number: data.callerid ? data.callerid : data.email, caller_id_number: data.callerid ? data.callerid : data.email,
@ -694,7 +722,7 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
email : storage.data.email, email : storage.data.email,
avatar: "http://gravatar.com/avatar/" + md5(storage.data.email) + ".png?s=600" avatar: "http://gravatar.com/avatar/" + md5(storage.data.email) + ".png?s=600"
} }
}); }, custom));
data.call = call; data.call = call;
@ -912,6 +940,21 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
sendConferenceChat: function(message) { sendConferenceChat: function(message) {
data.conf.sendChat(message, "message"); data.conf.sendChat(message, "message");
}, },
setCanvasIn: function(memberID, canvasID) {
data.conf.modCommand('vid-canvas', memberID, canvasID);
},
setCanvasOut: function(memberID, canvasID) {
data.conf.modCommand('vid-watching-canvas', memberID, canvasID);
},
setLayer: function(memberID, canvasID) {
data.conf.modCommand('vid-layer', memberID, canvasID);
},
/*
* Method is used to set a member's resevartion Id.
*/
setResevartionId: function(memberID, resID) {
data.conf.modCommand('vid-res-id', memberID, resID);
},
/* /*
* Method is used to send user2user chats. * Method is used to send user2user chats.
* VC does not yet support that. * VC does not yet support that.

View File

@ -47,7 +47,7 @@ function onError(e){onStreamError(self,e);}
var mediaParams=getMediaParams(self);console.log("Audio constraints",mediaParams.audio);console.log("Video constraints",mediaParams.video);if(self.options.useVideo&&self.options.localVideo){getUserMedia({constraints:{audio:false,video:{mandatory:self.options.videoParams,optional:[]},},localVideo:self.options.localVideo,onsuccess:function(e){self.options.localVideoStream=e;console.log("local video ready");},onerror:function(e){console.error("local video error!");}});} var mediaParams=getMediaParams(self);console.log("Audio constraints",mediaParams.audio);console.log("Video constraints",mediaParams.video);if(self.options.useVideo&&self.options.localVideo){getUserMedia({constraints:{audio:false,video:{mandatory:self.options.videoParams,optional:[]},},localVideo:self.options.localVideo,onsuccess:function(e){self.options.localVideoStream=e;console.log("local video ready");},onerror:function(e){console.error("local video error!");}});}
getUserMedia({constraints:{audio:mediaParams.audio,video:mediaParams.video},video:mediaParams.useVideo,onsuccess:onSuccess,onerror:onError});};function getMediaParams(obj){var audio;if(obj.options.useMic&&obj.options.useMic==="none"){console.log("Microphone Disabled");audio=false;}else if(obj.options.videoParams&&obj.options.screenShare){console.error("SCREEN SHARE");audio=false;}else{audio={mandatory:obj.options.audioParams,optional:[]};if(obj.options.useMic!=="any"){audio.optional=[{sourceId:obj.options.useMic}]}} getUserMedia({constraints:{audio:mediaParams.audio,video:mediaParams.video},video:mediaParams.useVideo,onsuccess:onSuccess,onerror:onError});};function getMediaParams(obj){var audio;if(obj.options.useMic&&obj.options.useMic==="none"){console.log("Microphone Disabled");audio=false;}else if(obj.options.videoParams&&obj.options.screenShare){console.error("SCREEN SHARE");audio=false;}else{audio={mandatory:obj.options.audioParams,optional:[]};if(obj.options.useMic!=="any"){audio.optional=[{sourceId:obj.options.useMic}]}}
if(obj.options.useVideo&&obj.options.localVideo){getUserMedia({constraints:{audio:false,video:{mandatory:obj.options.videoParams,optional:[]},},localVideo:obj.options.localVideo,onsuccess:function(e){self.options.localVideoStream=e;console.log("local video ready");},onerror:function(e){console.error("local video error!");}});} if(obj.options.useVideo&&obj.options.localVideo){getUserMedia({constraints:{audio:false,video:{mandatory:obj.options.videoParams,optional:[]},},localVideo:obj.options.localVideo,onsuccess:function(e){self.options.localVideoStream=e;console.log("local video ready");},onerror:function(e){console.error("local video error!");}});}
var video={};var bestFrameRate=obj.options.videoParams.vertoBestFrameRate;delete obj.options.videoParams.vertoBestFrameRate;if(window.moz){video=obj.options.videoParams;if(!video.width)video.width=video.minWidth;if(!video.height)video.height=video.minHeight;if(!video.frameRate)video.frameRate=video.minFrameRate;}else{video={mandatory:obj.options.videoParams,optional:[]}} var video={};var bestFrameRate=obj.options.videoParams.vertoBestFrameRate;delete obj.options.videoParams.vertoBestFrameRate;video={mandatory:obj.options.videoParams,optional:[]}
var useVideo=obj.options.useVideo;if(useVideo&&obj.options.useCamera&&obj.options.useCamera!=="none"){if(!video.optional){video.optional=[];} var useVideo=obj.options.useVideo;if(useVideo&&obj.options.useCamera&&obj.options.useCamera!=="none"){if(!video.optional){video.optional=[];}
if(obj.options.useCamera!=="any"){video.optional.push({sourceId:obj.options.useCamera});} if(obj.options.useCamera!=="any"){video.optional.push({sourceId:obj.options.useCamera});}
if(bestFrameRate&&!window.moz){video.optional.push({minFrameRate:bestFrameRate});}}else{console.log("Camera Disabled");video=false;useVideo=false;} if(bestFrameRate&&!window.moz){video.optional.push({minFrameRate:bestFrameRate});}}else{console.log("Camera Disabled");video=false;useVideo=false;}
@ -93,8 +93,7 @@ return[w,h];}
var resList=[[320,180],[320,240],[640,360],[640,480],[1280,720],[1920,1080]];var resI=0;var ttl=0;var checkRes=function(cam,func){if(resI>=resList.length){var res={'validRes':$.FSRTC.validRes,'bestResSupported':$.FSRTC.bestResSupported()};localStorage.setItem("res_"+cam,$.toJSON(res));if(func)return func(res);return;} var resList=[[320,180],[320,240],[640,360],[640,480],[1280,720],[1920,1080]];var resI=0;var ttl=0;var checkRes=function(cam,func){if(resI>=resList.length){var res={'validRes':$.FSRTC.validRes,'bestResSupported':$.FSRTC.bestResSupported()};localStorage.setItem("res_"+cam,$.toJSON(res));if(func)return func(res);return;}
var video={mandatory:{},optional:[]} var video={mandatory:{},optional:[]}
if(cam){video.optional=[{sourceId:cam}];} if(cam){video.optional=[{sourceId:cam}];}
w=resList[resI][0];h=resList[resI][1];resI++;video.mandatory={"minWidth":w,"minHeight":h,"maxWidth":w,"maxHeight":h};if(window.moz){video=video.mandatory;if(!video.width)video.width=video.minWidth;if(!video.height)video.height=video.minHeight;if(!video.frameRate)video.frameRate=video.minFrameRate;} w=resList[resI][0];h=resList[resI][1];resI++;video.mandatory={"minWidth":w,"minHeight":h,"maxWidth":w,"maxHeight":h};getUserMedia({constraints:{audio:ttl++==0,video:video},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info(w+"x"+h+" supported.");$.FSRTC.validRes.push([w,h]);checkRes(cam,func);},onerror:function(e){console.error(w+"x"+h+" not supported.");checkRes(cam,func);}});}
getUserMedia({constraints:{audio:ttl++==0,video:video},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info(w+"x"+h+" supported.");$.FSRTC.validRes.push([w,h]);checkRes(cam,func);},onerror:function(e){console.error(w+"x"+h+" not supported.");checkRes(cam,func);}});}
$.FSRTC.getValidRes=function(cam,func){var used=[];var cached=localStorage.getItem("res_"+cam);if(cached){var cache=$.parseJSON(cached);if(cache){$.FSRTC.validRes=cache.validRes;console.log("CACHED RES FOR CAM "+cam,cache);}else{console.error("INVALID CACHE");} $.FSRTC.getValidRes=function(cam,func){var used=[];var cached=localStorage.getItem("res_"+cam);if(cached){var cache=$.parseJSON(cached);if(cache){$.FSRTC.validRes=cache.validRes;console.log("CACHED RES FOR CAM "+cam,cache);}else{console.error("INVALID CACHE");}
return func?func(cache):null;} return func?func(cache):null;}
$.FSRTC.validRes=[];resI=0;checkRes(cam,func);} $.FSRTC.validRes=[];resI=0;checkRes(cam,func);}
@ -238,7 +237,9 @@ jq.mouseover(function(e){jq.data({"mouse":true});$("#"+box_id).show();});jq.mous
$("#"+volup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_in",x,"down");});return html;} $("#"+volup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_in",x,"down");});return html;}
var atitle="";var awidth=0;verto.subscribe(confMan.params.laData.chatChannel,{handler:function(v,e){if(typeof(confMan.params.chatCallback)==="function"){confMan.params.chatCallback(v,e);}}});if(confMan.params.laData.role==="moderator"){atitle="Action";awidth=600;if(confMan.params.mainModID){genMainMod($(confMan.params.mainModID));$(confMan.params.displayID).html("Moderator Controls Ready<br><br>");}else{$(confMan.params.mainModID).html("");} var atitle="";var awidth=0;verto.subscribe(confMan.params.laData.chatChannel,{handler:function(v,e){if(typeof(confMan.params.chatCallback)==="function"){confMan.params.chatCallback(v,e);}}});if(confMan.params.laData.role==="moderator"){atitle="Action";awidth=600;if(confMan.params.mainModID){genMainMod($(confMan.params.mainModID));$(confMan.params.displayID).html("Moderator Controls Ready<br><br>");}else{$(confMan.params.mainModID).html("");}
verto.subscribe(confMan.params.laData.modChannel,{handler:function(v,e){if(confMan.params.onBroadcast){confMan.params.onBroadcast(verto,confMan,e.data);} verto.subscribe(confMan.params.laData.modChannel,{handler:function(v,e){if(confMan.params.onBroadcast){confMan.params.onBroadcast(verto,confMan,e.data);}
if(e.data["conf-command"]==="list-videoLayouts"){for(var j=0;j<confMan.canvasCount;j++){var vlselect_id="#confman_vl_select_"+j+"_"+confMan.serno;var vlayout_id="#confman_vid_layout_"+j+"_"+confMan.serno;var x=0;var options;$(vlselect_id).selectmenu({});$(vlselect_id).selectmenu("enable");$(vlselect_id).empty();$(vlselect_id).append(new Option("Choose a Layout","none"));if(e.data.responseData){options=e.data.responseData.sort();for(var i in options){$(vlselect_id).append(new Option(options[i],options[i]));x++;}} if(e.data["conf-command"]==="list-videoLayouts"){for(var j=0;j<confMan.canvasCount;j++){var vlselect_id="#confman_vl_select_"+j+"_"+confMan.serno;var vlayout_id="#confman_vid_layout_"+j+"_"+confMan.serno;var x=0;var options;$(vlselect_id).selectmenu({});$(vlselect_id).selectmenu("enable");$(vlselect_id).empty();$(vlselect_id).append(new Option("Choose a Layout","none"));if(e.data.responseData){var rdata=[];for(var i in e.data.responseData){rdata.push(e.data.responseData[i].name);}
options=rdata.sort(function(a,b){var ga=a.substring(0,6)=="group:"?true:false;var gb=b.substring(0,6)=="group:"?true:false;if((ga||gb)&&ga!=gb){return ga?-1:1;}
return((a==b)?0:((a>b)?1:-1));});for(var i in options){$(vlselect_id).append(new Option(options[i],options[i]));x++;}}
if(x){$(vlselect_id).selectmenu('refresh',true);}else{$(vlayout_id).hide();}}}else{if(!confMan.destroyed&&confMan.params.displayID){$(confMan.params.displayID).html(e.data.response+"<br><br>");if(confMan.lastTimeout){clearTimeout(confMan.lastTimeout);confMan.lastTimeout=0;} if(x){$(vlselect_id).selectmenu('refresh',true);}else{$(vlayout_id).hide();}}}else{if(!confMan.destroyed&&confMan.params.displayID){$(confMan.params.displayID).html(e.data.response+"<br><br>");if(confMan.lastTimeout){clearTimeout(confMan.lastTimeout);confMan.lastTimeout=0;}
confMan.lastTimeout=setTimeout(function(){$(confMan.params.displayID).html(confMan.destroyed?"":"Moderator Controls Ready<br><br>");},4000);}}}});if(confMan.params.hasVid){confMan.modCommand("list-videoLayouts",null,null);}} confMan.lastTimeout=setTimeout(function(){$(confMan.params.displayID).html(confMan.destroyed?"":"Moderator Controls Ready<br><br>");},4000);}}}});if(confMan.params.hasVid){confMan.modCommand("list-videoLayouts",null,null);}}
var row_callback=null;if(confMan.params.laData.role==="moderator"){row_callback=function(nRow,aData,iDisplayIndex,iDisplayIndexFull){if(!aData[5]){var $row=$('td:eq(5)',nRow);genControls($row,aData);if(confMan.params.onLaRow){confMan.params.onLaRow(verto,confMan,$row,aData);}}};} var row_callback=null;if(confMan.params.laData.role==="moderator"){row_callback=function(nRow,aData,iDisplayIndex,iDisplayIndexFull){if(!aData[5]){var $row=$('td:eq(5)',nRow);genControls($row,aData);if(confMan.params.onLaRow){confMan.params.onLaRow(verto,confMan,$row,aData);}}};}
@ -259,15 +260,15 @@ dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,tr
return false;} return false;}
function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}} function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}}
return id;} return id;}
$.verto.dialog.prototype.setAudioDevice=function(sinkId,callback,arg){var dialog=this;var element=dialog.audioStream;if(typeof element.sinkId!=='undefined'){console.info("Dialog: "+dialog.callID+" Setting speaker:",element,find_name(sinkId));element.setSinkId(sinkId).then(function(){console.log("Dialog: "+dialog.callID+' Success, audio output device attached: '+sinkId);if(callback){callback(true,arg);}}).catch(function(error){var errorMessage=error;if(error.name==='SecurityError'){errorMessage="Dialog: "+dialog.callID+' You need to use HTTPS for selecting audio output '+'device: '+error;} $.verto.dialog.prototype.setAudioPlaybackDevice=function(sinkId,callback,arg){var dialog=this;var element=dialog.audioStream;if(typeof element.sinkId!=='undefined'){var devname=find_name(sinkId);console.info("Dialog: "+dialog.callID+" Setting speaker:",element,devname);element.setSinkId(sinkId).then(function(){console.log("Dialog: "+dialog.callID+' Success, audio output device attached: '+sinkId);if(callback){callback(true,devname,arg);}}).catch(function(error){var errorMessage=error;if(error.name==='SecurityError'){errorMessage="Dialog: "+dialog.callID+' You need to use HTTPS for selecting audio output '+'device: '+error;}
if(callback){callback(false,arg);} if(callback){callback(false,null,arg);}
console.error(errorMessage);});}else{console.warn("Dialog: "+dialog.callID+' Browser does not support output device selection.');if(callback){callback(false,arg);}}} console.error(errorMessage);});}else{console.warn("Dialog: "+dialog.callID+' Browser does not support output device selection.');if(callback){callback(false,null,arg);}}}
$.verto.dialog.prototype.setState=function(state){var dialog=this;if(dialog.state==$.verto.enum.state.ringing){dialog.stopRinging();} $.verto.dialog.prototype.setState=function(state){var dialog=this;if(dialog.state==$.verto.enum.state.ringing){dialog.stopRinging();}
if(dialog.state==state||!checkStateChange(dialog.state,state)){console.error("Dialog "+dialog.callID+": INVALID state change from "+dialog.state.name+" to "+state.name);dialog.hangup();return false;} if(dialog.state==state||!checkStateChange(dialog.state,state)){console.error("Dialog "+dialog.callID+": INVALID state change from "+dialog.state.name+" to "+state.name);dialog.hangup();return false;}
console.log("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(!dialog.causeCode){dialog.causeCode=16;} console.log("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(!dialog.causeCode){dialog.causeCode=16;}
if(!dialog.cause){dialog.cause="NORMAL CLEARING";} if(!dialog.cause){dialog.cause="NORMAL CLEARING";}
if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);} if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);}
switch(dialog.state){case $.verto.enum.state.early:case $.verto.enum.state.active:var speaker=dialog.useSpeak;console.info("Using Speaker: ",speaker);if(speaker&&speaker!=="any"){setTimeout(function(){dialog.setAudioDevice(speaker);},500);} switch(dialog.state){case $.verto.enum.state.early:case $.verto.enum.state.active:var speaker=dialog.useSpeak;console.info("Using Speaker: ",speaker);if(speaker&&speaker!=="any"){setTimeout(function(){dialog.setAudioPlaybackDevice(speaker);},500);}
break;case $.verto.enum.state.trying:setTimeout(function(){if(dialog.state==$.verto.enum.state.trying){dialog.setState($.verto.enum.state.hangup);}},30000);break;case $.verto.enum.state.purge:dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.hangup:if(dialog.lastState.val>$.verto.enum.state.requesting.val&&dialog.lastState.val<$.verto.enum.state.hangup.val){dialog.sendMethod("verto.bye",{});} break;case $.verto.enum.state.trying:setTimeout(function(){if(dialog.state==$.verto.enum.state.trying){dialog.setState($.verto.enum.state.hangup);}},30000);break;case $.verto.enum.state.purge:dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.hangup:if(dialog.lastState.val>$.verto.enum.state.requesting.val&&dialog.lastState.val<$.verto.enum.state.hangup.val){dialog.sendMethod("verto.bye",{});}
dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:delete dialog.verto.dialogs[dialog.callID];if(dialog.params.screenShare){dialog.rtc.stopPeer();}else{dialog.rtc.stop();} dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:delete dialog.verto.dialogs[dialog.callID];if(dialog.params.screenShare){dialog.rtc.stopPeer();}else{dialog.rtc.stop();}
break;} break;}

View File

@ -215,7 +215,9 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_LOCAL_VIDEO_PORT_VARIABLE "local_video_port" #define SWITCH_LOCAL_VIDEO_PORT_VARIABLE "local_video_port"
#define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE "hangup_after_bridge" #define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE "hangup_after_bridge"
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE "park_after_bridge" #define SWITCH_PARK_AFTER_BRIDGE_VARIABLE "park_after_bridge"
#define SWITCH_PARK_AFTER_EARLY_BRIDGE_VARIABLE "park_after_early_bridge"
#define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE "transfer_after_bridge" #define SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE "transfer_after_bridge"
#define SWITCH_TRANSFER_AFTER_EARLY_BRIDGE_VARIABLE "transfer_after_early_bridge"
#define SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE "exec_after_bridge_app" #define SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE "exec_after_bridge_app"
#define SWITCH_EXEC_AFTER_BRIDGE_ARG_VARIABLE "exec_after_bridge_arg" #define SWITCH_EXEC_AFTER_BRIDGE_ARG_VARIABLE "exec_after_bridge_arg"
#define SWITCH_MAX_FORWARDS_VARIABLE "max_forwards" #define SWITCH_MAX_FORWARDS_VARIABLE "max_forwards"

View File

@ -848,7 +848,7 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
context->bandwidth = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 0, 0) * 8; context->bandwidth = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 0, 0) * 8;
} }
sane = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 1, 30); sane = switch_calc_bitrate(1920, 1080, 2, 30);
if (context->bandwidth > sane) { if (context->bandwidth > sane) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BITRATE TRUNCATED TO %d\n", sane); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "BITRATE TRUNCATED TO %d\n", sane);

View File

@ -1577,12 +1577,7 @@ switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switc
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (zstr(text)) { if (zstr(text) || !strcasecmp(text, "clear") || (member->video_reservation_id && !strcasecmp(text, member->video_reservation_id))) {
stream->write_function(stream, "-ERR missing arg\n");
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(text, "clear") || (member->video_reservation_id && !strcasecmp(text, member->video_reservation_id))) {
member->video_reservation_id = NULL; member->video_reservation_id = NULL;
stream->write_function(stream, "+OK reservation_id cleared\n"); stream->write_function(stream, "+OK reservation_id cleared\n");
} else { } else {

View File

@ -42,7 +42,7 @@
#include <mod_conference.h> #include <mod_conference.h>
inline switch_bool_t conference_cdr_test_mflag(conference_cdr_node_t *np, member_flag_t mflag) static inline switch_bool_t conference_cdr_test_mflag(conference_cdr_node_t *np, member_flag_t mflag)
{ {
return !!np->mflags[mflag]; return !!np->mflags[mflag];
} }

View File

@ -42,6 +42,21 @@
#include <mod_conference.h> #include <mod_conference.h>
static cJSON *get_canvas_info(mcu_canvas_t *canvas)
{
cJSON *obj = cJSON_CreateObject();
cJSON_AddItemToObject(obj, "canvasID", cJSON_CreateNumber(canvas->canvas_id));
cJSON_AddItemToObject(obj, "totalLayers", cJSON_CreateNumber(canvas->total_layers));
cJSON_AddItemToObject(obj, "layersUsed", cJSON_CreateNumber(canvas->layers_used));
cJSON_AddItemToObject(obj, "layoutFloorID", cJSON_CreateNumber(canvas->layout_floor_id));
if (canvas->vlayout) {
cJSON_AddItemToObject(obj, "layoutName", cJSON_CreateString(canvas->vlayout->name));
}
return obj;
}
void conference_event_mod_channel_handler(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id) void conference_event_mod_channel_handler(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id)
{ {
cJSON *data, *addobj = NULL; cJSON *data, *addobj = NULL;
@ -63,6 +78,7 @@ void conference_event_mod_channel_handler(const char *event_channel, cJSON *json
if ((data = cJSON_GetObjectItem(json, "data"))) { if ((data = cJSON_GetObjectItem(json, "data"))) {
action = cJSON_GetObjectCstr(data, "command"); action = cJSON_GetObjectCstr(data, "command");
if ((jid = cJSON_GetObjectItem(data, "id"))) { if ((jid = cJSON_GetObjectItem(data, "id"))) {
if (jid->valueint) { if (jid->valueint) {
switch_snprintf(cid, sizeof(cid), "%d", jid->valueint); switch_snprintf(cid, sizeof(cid), "%d", jid->valueint);
@ -151,6 +167,68 @@ void conference_event_mod_channel_handler(const char *event_channel, cJSON *json
switch_thread_rwlock_unlock(conference->rwlock); switch_thread_rwlock_unlock(conference->rwlock);
} }
goto end; goto end;
} else if (!strcasecmp(action, "canvasInfo")) {
cJSON *j_member_id;
int member_id = 0;
int i = 0;
cJSON *array = cJSON_CreateArray();
conference_obj_t *conference;
if ((conference = conference_find(conference_name, NULL))) {
if ((j_member_id = cJSON_GetObjectItem(data, "memberID"))) {
if (j_member_id->valueint) {
member_id = j_member_id->valueint;
} else if (j_member_id->valuedouble) {
member_id = (int) j_member_id->valuedouble;
} else if (j_member_id->valuestring) {
member_id = atoi(j_member_id->valuestring);
}
if (member_id < 0) member_id = 0;
}
if (member_id > 0) {
conference_member_t *member;
if ((member = conference_member_get(conference, member_id))) {
mcu_canvas_t *canvas;
if ((canvas = conference_video_get_canvas_locked(member))) {
cJSON *obj;
if ((obj = get_canvas_info(canvas))) {
cJSON_AddItemToObject(obj, "layerID", cJSON_CreateNumber(member->video_layer_id));
cJSON_AddItemToArray(array, obj);
}
conference_video_release_canvas(&canvas);
}
switch_thread_rwlock_unlock(member->rwlock);
}
} else {
switch_mutex_lock(conference->canvas_mutex);
for (i = 0; i <= conference->canvas_count; i++) {
mcu_canvas_t *canvas = conference->canvases[i];
if (canvas) {
cJSON *obj;
if ((obj = get_canvas_info(canvas))) {
cJSON_AddItemToArray(array, obj);
}
}
}
switch_mutex_unlock(conference->canvas_mutex);
}
switch_thread_rwlock_unlock(conference->rwlock);
}
addobj = array;
} else if (!strcasecmp(action, "list-videoLayouts")) { } else if (!strcasecmp(action, "list-videoLayouts")) {
switch_hash_index_t *hi; switch_hash_index_t *hi;
void *val; void *val;
@ -161,17 +239,49 @@ void conference_event_mod_channel_handler(const char *event_channel, cJSON *json
switch_mutex_lock(conference_globals.setup_mutex); switch_mutex_lock(conference_globals.setup_mutex);
if (conference->layout_hash) { if (conference->layout_hash) {
for (hi = switch_core_hash_first(conference->layout_hash); hi; hi = switch_core_hash_next(&hi)) { for (hi = switch_core_hash_first(conference->layout_hash); hi; hi = switch_core_hash_next(&hi)) {
video_layout_t *vlayout;
cJSON *obj = cJSON_CreateObject();
cJSON *resarray = cJSON_CreateArray();
int i;
switch_core_hash_this(hi, &vvar, NULL, &val); switch_core_hash_this(hi, &vvar, NULL, &val);
cJSON_AddItemToArray(array, cJSON_CreateString((char *)vvar)); vlayout = (video_layout_t *)val;
for (i = 0; i < vlayout->layers; i++) {
if (vlayout->images[i].res_id) {
cJSON_AddItemToArray(resarray, cJSON_CreateString((char *)vlayout->images[i].res_id));
}
}
cJSON_AddItemToObject(obj, "type", cJSON_CreateString("layout"));
cJSON_AddItemToObject(obj, "name", cJSON_CreateString((char *)vvar));
cJSON_AddItemToObject(obj, "resIDS", resarray);
cJSON_AddItemToArray(array, obj);
} }
} }
if (conference->layout_group_hash) { if (conference->layout_group_hash) {
for (hi = switch_core_hash_first(conference->layout_group_hash); hi; hi = switch_core_hash_next(&hi)) { for (hi = switch_core_hash_first(conference->layout_group_hash); hi; hi = switch_core_hash_next(&hi)) {
char *name; char *name;
cJSON *obj = cJSON_CreateObject();
cJSON *grouparray = cJSON_CreateArray();
layout_group_t *lg;
video_layout_node_t *vlnode;
switch_core_hash_this(hi, &vvar, NULL, &val); switch_core_hash_this(hi, &vvar, NULL, &val);
lg = (layout_group_t *) val;
name = switch_mprintf("group:%s", (char *)vvar); name = switch_mprintf("group:%s", (char *)vvar);
cJSON_AddItemToArray(array, cJSON_CreateString(name));
for (vlnode = lg->layouts; vlnode; vlnode = vlnode->next) {
cJSON_AddItemToArray(grouparray, cJSON_CreateString(vlnode->vlayout->name));
}
cJSON_AddItemToObject(obj, "type", cJSON_CreateString("layoutGroup"));
cJSON_AddItemToObject(obj, "name", cJSON_CreateString(name));
cJSON_AddItemToObject(obj, "groupLayouts", grouparray);
cJSON_AddItemToArray(array, obj);
free(name); free(name);
} }
} }

View File

@ -1629,7 +1629,13 @@ int conference_member_setup_media(conference_member_t *member, conference_obj_t
switch_mutex_lock(member->audio_out_mutex); switch_mutex_lock(member->audio_out_mutex);
switch_core_session_get_read_impl(member->session, &read_impl); if (!member->orig_read_impl.samples_per_second) {
switch_core_session_get_read_impl(member->session, &member->orig_read_impl);
member->native_rate = read_impl.samples_per_second;
}
read_impl = member->orig_read_impl;
if (switch_core_codec_ready(&member->read_codec)) { if (switch_core_codec_ready(&member->read_codec)) {
switch_core_codec_destroy(&member->read_codec); switch_core_codec_destroy(&member->read_codec);
@ -1645,9 +1651,6 @@ int conference_member_setup_media(conference_member_t *member, conference_obj_t
switch_resample_destroy(&member->read_resampler); switch_resample_destroy(&member->read_resampler);
} }
switch_core_session_get_read_impl(member->session, &member->orig_read_impl);
member->native_rate = read_impl.samples_per_second;
/* Setup a Signed Linear codec for reading audio. */ /* Setup a Signed Linear codec for reading audio. */
if (switch_core_codec_init(&member->read_codec, if (switch_core_codec_init(&member->read_codec,
"L16", "L16",

View File

@ -1921,9 +1921,17 @@ void conference_video_check_auto_bitrate(conference_member_t *member, mcu_layer_
switch_channel_get_name(member->channel), kps); switch_channel_get_name(member->channel), kps);
} else { } else {
int max = 0; int max = 0;
switch_vid_params_t vid_params = { 0 };
switch_core_media_get_vid_params(member->session, &vid_params);
if (w > vid_params.width || h > vid_params.height) {
w = vid_params.width;
h = vid_params.height;
}
if (layer) { if (layer) {
kps = switch_calc_bitrate(w, h, 1, (int)(member->conference->video_fps.fps)); kps = switch_calc_bitrate(w, h, member->conference->video_quality, (int)(member->conference->video_fps.fps));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps to accomodate %dx%d resolution\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps to accomodate %dx%d resolution\n",
switch_channel_get_name(member->channel), kps, layer->screen_w, layer->screen_h); switch_channel_get_name(member->channel), kps, layer->screen_w, layer->screen_h);
} }
@ -2024,7 +2032,8 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
int do_refresh = 0; int do_refresh = 0;
int last_file_count = 0; int last_file_count = 0;
int layout_applied = 0; int layout_applied = 0;
int files_playing = 0;
canvas->video_timer_reset = 1; canvas->video_timer_reset = 1;
packet = switch_core_alloc(conference->pool, SWITCH_RTP_MAX_BUF_LEN); packet = switch_core_alloc(conference->pool, SWITCH_RTP_MAX_BUF_LEN);
@ -2058,9 +2067,8 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
canvas->send_keyframe = 1; canvas->send_keyframe = 1;
} }
if (!conference->playing_video_file) {
switch_core_timer_next(&canvas->timer); switch_core_timer_next(&canvas->timer);
}
now = switch_micro_time_now(); now = switch_micro_time_now();
@ -2080,8 +2088,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
switch_mutex_lock(conference->member_mutex); switch_mutex_lock(conference->member_mutex);
for (imember = conference->members; imember; imember = imember->next) { for (imember = conference->members; imember; imember = imember->next) {
if (imember->channel && switch_channel_ready(imember->channel) && conference_utils_member_test_flag(imember, MFLAG_RUNNING) if (imember->channel && switch_channel_ready(imember->channel) && switch_channel_test_flag(imember->channel, CF_VIDEO) &&
&& imember->canvas_id == canvas->canvas_id) { conference_utils_member_test_flag(imember, MFLAG_RUNNING)
&& imember->canvas_id == canvas->canvas_id && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY) {
canvas_count++; canvas_count++;
} }
} }
@ -2105,11 +2114,13 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (conference->async_fnode && switch_core_file_has_video(&conference->async_fnode->fh)) { if (conference->async_fnode && switch_core_file_has_video(&conference->async_fnode->fh)) {
check_async_file = 1; check_async_file = 1;
file_count++; file_count++;
files_playing = 1;
} }
if (conference->fnode && switch_core_file_has_video(&conference->fnode->fh)) { if (conference->fnode && switch_core_file_has_video(&conference->fnode->fh)) {
check_file = 1; check_file = 1;
file_count++; file_count++;
files_playing = 1;
} }
if (file_count != last_file_count) { if (file_count != last_file_count) {
@ -2211,11 +2222,6 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
continue; continue;
} }
if (conference->playing_video_file) {
switch_core_session_rwunlock(imember->session);
continue;
}
//VIDFLOOR //VIDFLOOR
if (canvas->layout_floor_id > -1 && imember->id == conference->video_floor_holder && if (canvas->layout_floor_id > -1 && imember->id == conference->video_floor_holder &&
imember->video_layer_id != canvas->layout_floor_id) { imember->video_layer_id != canvas->layout_floor_id) {
@ -2226,6 +2232,13 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
layer = NULL; layer = NULL;
if (conference->playing_video_file) {
switch_img_free(&img);
switch_core_session_rwunlock(imember->session);
continue;
}
switch_mutex_lock(canvas->mutex); switch_mutex_lock(canvas->mutex);
@ -2381,7 +2394,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (count_changed) { if (count_changed) {
int total = conference->members_with_video; int total = conference->members_with_video;
int kps;
switch_vid_params_t vid_params = { 0 };
if (!conference_utils_test_flag(conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS)) { if (!conference_utils_test_flag(conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS)) {
total += conference->members_with_avatar; total += conference->members_with_avatar;
} }
@ -2401,6 +2416,13 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
conference_video_init_canvas_layers(conference, imember->canvas, vlayout); conference_video_init_canvas_layers(conference, imember->canvas, vlayout);
} }
} }
if (!switch_channel_test_flag(imember->channel, CF_VIDEO_BITRATE_UNMANAGABLE) &&
conference_utils_test_flag(conference, CFLAG_MANAGE_INBOUND_VIDEO_BITRATE)) {
switch_core_media_get_vid_params(imember->session, &vid_params);
kps = switch_calc_bitrate(vid_params.width, vid_params.height, conference->video_quality, (int)(imember->conference->video_fps.fps));
conference_video_set_incoming_bitrate(imember, kps);
}
} }
if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) { if (switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
@ -2416,18 +2438,28 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
} }
if (check_async_file) { if (check_async_file) {
if (switch_core_file_read_video(&conference->async_fnode->fh, &file_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) { switch_status_t st = switch_core_file_read_video(&conference->async_fnode->fh, &file_frame, SVR_FLUSH);
if (st == SWITCH_STATUS_SUCCESS) {
if ((async_file_img = file_frame.img)) { if ((async_file_img = file_frame.img)) {
switch_img_free(&file_imgs[j]);
file_imgs[j++] = async_file_img; file_imgs[j++] = async_file_img;
} }
} else if (st == SWITCH_STATUS_BREAK) {
j++;
} }
} }
if (check_file) { if (check_file) {
if (switch_core_file_read_video(&conference->fnode->fh, &file_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) { switch_status_t st = switch_core_file_read_video(&conference->fnode->fh, &file_frame, SVR_FLUSH);
if (st == SWITCH_STATUS_SUCCESS) {
if ((normal_file_img = file_frame.img)) { if ((normal_file_img = file_frame.img)) {
switch_img_free(&file_imgs[j]);
file_imgs[j++] = normal_file_img; file_imgs[j++] = normal_file_img;
} }
} else if (st == SWITCH_STATUS_BREAK) {
j++;
} }
} }
@ -2440,13 +2472,15 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
continue; continue;
} }
i = 0; if (files_playing && !file_count) {
while (i < imember->canvas->total_layers) { i = 0;
layer = &imember->canvas->layers[i++]; while (i < imember->canvas->total_layers) {
switch_img_fill(layer->canvas->img, layer->x_pos, layer->y_pos, layer->screen_w, layer->screen_h, &layer->canvas->bgcolor); layer = &imember->canvas->layers[i++];
switch_img_fill(layer->canvas->img, layer->x_pos, layer->y_pos, layer->screen_w, layer->screen_h, &layer->canvas->bgcolor);
}
i = 0;
} }
i = 0;
if (!file_count && imember->canvas->layout_floor_id > -1 && imember->conference->video_floor_holder && if (!file_count && imember->canvas->layout_floor_id > -1 && imember->conference->video_floor_holder &&
imember->id != imember->conference->video_floor_holder) { imember->id != imember->conference->video_floor_holder) {
@ -2477,7 +2511,6 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (file_count && (conference->members_with_video + conference->members_with_avatar == 1)) { if (file_count && (conference->members_with_video + conference->members_with_avatar == 1)) {
floor_layer = NULL; floor_layer = NULL;
continue;
} }
if (!file_count && floor_layer && omember->id == conference->video_floor_holder) { if (!file_count && floor_layer && omember->id == conference->video_floor_holder) {
@ -2539,8 +2572,6 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
conference_video_scale_and_patch(layer, use_img, SWITCH_FALSE); conference_video_scale_and_patch(layer, use_img, SWITCH_FALSE);
} }
} }
conference_video_check_auto_bitrate(omember, layer);
} }
for (j = 0; j < file_count; j++) { for (j = 0; j < file_count; j++) {
@ -2558,8 +2589,11 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
switch_core_session_rwunlock(imember->session); switch_core_session_rwunlock(imember->session);
} }
switch_img_free(&normal_file_img); if (files_playing && !file_count) {
switch_img_free(&async_file_img); switch_img_free(&file_imgs[0]);
switch_img_free(&file_imgs[1]);
files_playing = 0;
}
for (imember = conference->members; imember; imember = imember->next) { for (imember = conference->members; imember; imember = imember->next) {
switch_frame_t *dupframe; switch_frame_t *dupframe;
@ -2595,7 +2629,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
switch_mutex_unlock(conference->member_mutex); switch_mutex_unlock(conference->member_mutex);
} else { } else {
if (conference->async_fnode && (conference->async_fnode->canvas_id == canvas->canvas_id || conference->async_fnode->canvas_id == -1)) { if (conference->async_fnode && (conference->async_fnode->canvas_id == canvas->canvas_id || conference->async_fnode->canvas_id == -1)) {
if (conference->async_fnode->layer_id > -1) { if (conference->async_fnode->layer_id > -1) {
conference_video_patch_fnode(canvas, conference->async_fnode); conference_video_patch_fnode(canvas, conference->async_fnode);
@ -2686,20 +2720,20 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (canvas->play_file) { if (canvas->play_file) {
canvas->send_keyframe = 1; canvas->send_keyframe = 1;
canvas->play_file = 0; canvas->play_file = 0;
canvas->timer.interval = 1;
canvas->timer.samples = 90;
} }
write_img = file_img = write_frame.img; switch_img_free(&file_img);
file_img = write_img = write_frame.img;
switch_core_timer_sync(&canvas->timer); switch_core_timer_sync(&canvas->timer);
timestamp = canvas->timer.samplecount; timestamp = canvas->timer.samplecount;
} else if (file_img) {
write_img = file_img;
} }
} else if (file_img) { } else if (file_img) {
switch_img_free(&file_img); switch_img_free(&file_img);
} }
write_frame.img = write_img; write_frame.img = write_img;
wait_for_canvas(canvas); wait_for_canvas(canvas);
@ -2893,9 +2927,7 @@ void *SWITCH_THREAD_FUNC conference_video_super_muxing_thread_run(switch_thread_
canvas->send_keyframe = 1; canvas->send_keyframe = 1;
} }
if (!conference->playing_video_file) { switch_core_timer_next(&canvas->timer);
switch_core_timer_next(&canvas->timer);
}
now = switch_micro_time_now(); now = switch_micro_time_now();
@ -3446,11 +3478,10 @@ void conference_video_write_frame(conference_obj_t *conference, conference_membe
continue; continue;
} }
if (!isession || !switch_channel_test_flag(imember->channel, CF_VIDEO) ) { if (switch_channel_test_flag(imember->channel, CF_VIDEO) ) {
continue; switch_core_session_request_video_refresh(imember->session);
} }
switch_core_session_request_video_refresh(imember->session);
switch_core_session_rwunlock(isession); switch_core_session_rwunlock(isession);
} }
} }

View File

@ -2410,6 +2410,7 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
char *video_codec_bandwidth = NULL; char *video_codec_bandwidth = NULL;
char *no_video_avatar = NULL; char *no_video_avatar = NULL;
conference_video_mode_t conference_video_mode = CONF_VIDEO_MODE_PASSTHROUGH; conference_video_mode_t conference_video_mode = CONF_VIDEO_MODE_PASSTHROUGH;
int conference_video_quality = 1;
float fps = 15.0f; float fps = 15.0f;
uint32_t max_members = 0; uint32_t max_members = 0;
uint32_t announce_count = 0; uint32_t announce_count = 0;
@ -2721,6 +2722,15 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
terminate_on_silence = val; terminate_on_silence = val;
} else if (!strcasecmp(var, "endconf-grace-time") && !zstr(val)) { } else if (!strcasecmp(var, "endconf-grace-time") && !zstr(val)) {
endconference_grace_time = val; endconference_grace_time = val;
} else if (!strcasecmp(var, "video-quality") && !zstr(val)) {
int tmp = atoi(val);
if (tmp > 0 && tmp < 5) {
conference_video_quality = tmp;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Video quality must be between 1 and 4\n");
}
} else if (!strcasecmp(var, "video-mode") && !zstr(val)) { } else if (!strcasecmp(var, "video-mode") && !zstr(val)) {
if (!strcasecmp(val, "passthrough")) { if (!strcasecmp(val, "passthrough")) {
conference_video_mode = CONF_VIDEO_MODE_PASSTHROUGH; conference_video_mode = CONF_VIDEO_MODE_PASSTHROUGH;
@ -2789,8 +2799,8 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
conference->caller_controls = switch_core_strdup(conference->pool, caller_controls); conference->caller_controls = switch_core_strdup(conference->pool, caller_controls);
conference->moderator_controls = switch_core_strdup(conference->pool, moderator_controls); conference->moderator_controls = switch_core_strdup(conference->pool, moderator_controls);
conference->broadcast_chat_messages = broadcast_chat_messages; conference->broadcast_chat_messages = broadcast_chat_messages;
conference->video_quality = conference_video_quality;
conference->conference_video_mode = conference_video_mode; conference->conference_video_mode = conference_video_mode;
if (!switch_core_has_video() && (conference->conference_video_mode == CONF_VIDEO_MODE_MUX || conference->conference_video_mode == CONF_VIDEO_MODE_TRANSCODE)) { if (!switch_core_has_video() && (conference->conference_video_mode == CONF_VIDEO_MODE_MUX || conference->conference_video_mode == CONF_VIDEO_MODE_TRANSCODE)) {
@ -2864,7 +2874,7 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
if (video_codec_bandwidth) { if (video_codec_bandwidth) {
if (!strcasecmp(video_codec_bandwidth, "auto")) { if (!strcasecmp(video_codec_bandwidth, "auto")) {
conference->video_codec_settings.video.bandwidth = switch_calc_bitrate(canvas_w, canvas_h, 1, (int)conference->video_fps.fps); conference->video_codec_settings.video.bandwidth = switch_calc_bitrate(canvas_w, canvas_h, conference->video_quality, (int)conference->video_fps.fps);
} else { } else {
conference->video_codec_settings.video.bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth); conference->video_codec_settings.video.bandwidth = switch_parse_bandwidth_string(video_codec_bandwidth);
} }

View File

@ -560,6 +560,7 @@ typedef struct conference_obj {
char *video_letterbox_bgcolor; char *video_letterbox_bgcolor;
char *no_video_avatar; char *no_video_avatar;
conference_video_mode_t conference_video_mode; conference_video_mode_t conference_video_mode;
int video_quality;
int members_with_video; int members_with_video;
int members_with_avatar; int members_with_avatar;
switch_codec_settings_t video_codec_settings; switch_codec_settings_t video_codec_settings;

View File

@ -2206,7 +2206,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
var = switch_event_get_header(client->params, "url"); var = switch_event_get_header(client->params, "url");
if (client->record.action) { if (var && client->record.action) {
if (strcmp(var, client->record.action)) { if (strcmp(var, client->record.action)) {
switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "url", client->record.action); switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "url", client->record.action);
httapi_sync(client); httapi_sync(client);

View File

@ -321,7 +321,7 @@ static switch_status_t init_encoder(switch_codec_t *codec)
} }
sane = switch_calc_bitrate(context->codec_settings.video.width, context->codec_settings.video.height, 1, 30); sane = switch_calc_bitrate(1920, 1080, 2, 30);
if (context->bandwidth > sane) { if (context->bandwidth > sane) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_WARNING, "BITRATE TRUNCATED FROM %d TO %d\n", context->bandwidth, sane); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_WARNING, "BITRATE TRUNCATED FROM %d TO %d\n", context->bandwidth, sane);

View File

@ -28,7 +28,7 @@
* Paul D. Tinsley <pdt at jackhammer.org> * Paul D. Tinsley <pdt at jackhammer.org>
* Bret McDanel <trixter AT 0xdecafbad.com> * Bret McDanel <trixter AT 0xdecafbad.com>
* Raymond Chandler <intralanman@freeswitch.org> * Raymond Chandler <intralanman@freeswitch.org>
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com> * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
* *
* *
* mod_sofia.c -- SOFIA SIP Endpoint * mod_sofia.c -- SOFIA SIP Endpoint
@ -1877,14 +1877,21 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (!zstr(msg->string_arg)) { if (!zstr(msg->string_arg)) {
if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) { if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *dest = (char *) msg->string_arg; char *mydest = (char *) msg->string_arg;
char *argv[MAX_REDIR] = { 0 }; char *argv[MAX_REDIR] = { 0 };
char *mydata = NULL, *newdest = NULL; char *mydata = NULL, *newdest = NULL;
int argc = 0, i; int argc = 0, i;
switch_size_t len = 0; switch_size_t len = 0;
switch_call_cause_t sip_redirect_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
char *dest = switch_core_session_strdup(session, mydest);
if ((argc = switch_separate_string(dest, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) {
const char *redirect_cause = argv[1];
sip_redirect_cause = switch_channel_str2cause(redirect_cause);
}
if (strchr(dest, ',')) { if (strchr(dest, ',')) {
mydata = switch_core_session_strdup(session, dest); mydata = dest;
len = strlen(mydata) * 2; len = strlen(mydata) * 2;
newdest = switch_core_session_alloc(session, len); newdest = switch_core_session_alloc(session, len);
@ -1936,7 +1943,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
tech_pvt->respond_phrase = "Moved Temporarily"; tech_pvt->respond_phrase = "Moved Temporarily";
} }
switch_channel_hangup(tech_pvt->channel, sofia_glue_sip_cause_to_freeswitch(tech_pvt->respond_code)); if (sip_redirect_cause == SWITCH_CAUSE_NONE) {
sip_redirect_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
}
switch_channel_hangup(tech_pvt->channel, sip_redirect_cause);
} else { } else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Too late for redirecting, already answered\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Too late for redirecting, already answered\n");

View File

@ -5472,6 +5472,11 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION); sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
} }
if (sofia_test_flag(profile, TFLAG_INB_NOMEDIA) && !sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "inbound-bypass-media implictly enables inbound-late-negotiation\n");
sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
}
if (sofia_test_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE) && !sofia_test_pflag(profile, PFLAG_ALLOW_UPDATE)) { if (sofia_test_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE) && !sofia_test_pflag(profile, PFLAG_ALLOW_UPDATE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "send-display-update=true is set, but we can't comply because allow-update=false\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "send-display-update=true is set, but we can't comply because allow-update=false\n");
sofia_clear_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE); sofia_clear_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE);

View File

@ -25,7 +25,7 @@
//#include "sha1.h" //#include "sha1.h"
#include <openssl/ssl.h> #include <openssl/ssl.h>
#ifdef _MSC_VER #if defined(_MSC_VER) || defined(__APPLE__)
#define __bswap_64(x) \ #define __bswap_64(x) \
x = (x>>56) | \ x = (x>>56) | \
((x<<40) & 0x00FF000000000000) | \ ((x<<40) & 0x00FF000000000000) | \
@ -35,6 +35,8 @@
((x>>24) & 0x0000000000FF0000) | \ ((x>>24) & 0x0000000000FF0000) | \
((x>>40) & 0x000000000000FF00) | \ ((x>>40) & 0x000000000000FF00) | \
(x<<56) (x<<56)
#endif
#ifdef _MSC_VER
#ifndef strncasecmp #ifndef strncasecmp
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#endif #endif

View File

@ -3799,7 +3799,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *
} }
if (switch_core_session_in_thread(channel->session)) { if (switch_core_session_in_thread(channel->session) && !switch_channel_test_flag(channel, CF_PROXY_MODE)) {
const char *delay; const char *delay;
if (switch_channel_test_flag(channel, CF_VIDEO)) { if (switch_channel_test_flag(channel, CF_VIDEO)) {

View File

@ -79,6 +79,7 @@ struct switch_ivr_dmachine {
void *user_data; void *user_data;
switch_mutex_t *mutex; switch_mutex_t *mutex;
switch_status_t last_return; switch_status_t last_return;
uint8_t pinging;
}; };
@ -487,6 +488,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (dmachine->pinging) {
return SWITCH_STATUS_BREAK;
}
dmachine->pinging = 1;
if (zstr(dmachine->digits) && !is_timeout) { if (zstr(dmachine->digits) && !is_timeout) {
r = SWITCH_STATUS_SUCCESS; r = SWITCH_STATUS_SUCCESS;
} else if (dmachine->cur_digit_len > dmachine->max_digit_len) { } else if (dmachine->cur_digit_len > dmachine->max_digit_len) {
@ -579,6 +586,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *
dmachine->last_return = r; dmachine->last_return = r;
dmachine->pinging = 0;
switch_mutex_unlock(dmachine->mutex); switch_mutex_unlock(dmachine->mutex);
return r; return r;
@ -608,6 +617,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_feed(switch_ivr_dmachine_t *
status = istatus; status = istatus;
} }
} else { } else {
switch_mutex_unlock(dmachine->mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "dmachine overflow error!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "dmachine overflow error!\n");
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
} }

View File

@ -1698,6 +1698,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
switch_call_cause_t cause = switch_channel_get_cause(peer_channel); switch_call_cause_t cause = switch_channel_get_cause(peer_channel);
const char *hup = switch_channel_get_variable(caller_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE); const char *hup = switch_channel_get_variable(caller_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE);
int explicit = 0; int explicit = 0;
int answered = 0;
int early = 0;
if (cause == SWITCH_CAUSE_NONE) { if (cause == SWITCH_CAUSE_NONE) {
cause = SWITCH_CAUSE_NORMAL_CLEARING; cause = SWITCH_CAUSE_NORMAL_CLEARING;
@ -1718,16 +1720,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
switch_channel_hangup(caller_channel, cause); switch_channel_hangup(caller_channel, cause);
} }
if ((state != CS_EXECUTE && state != CS_SOFT_EXECUTE && state != CS_PARK && state != CS_ROUTING) || answered = switch_channel_test_flag(peer_channel, CF_ANSWERED);
(switch_channel_test_flag(peer_channel, CF_ANSWERED) && state < CS_HANGUP)) { early = switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA);
if ((state != CS_EXECUTE && state != CS_SOFT_EXECUTE && state != CS_PARK && state != CS_ROUTING) || ((answered || early) && state < CS_HANGUP)) {
if (!switch_channel_test_flag(caller_channel, CF_TRANSFER)) { if (!switch_channel_test_flag(caller_channel, CF_TRANSFER)) {
if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE))) {
if ((answered && switch_true(switch_channel_get_variable(caller_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE))) ||
switch_true(switch_channel_get_variable(caller_channel, SWITCH_PARK_AFTER_EARLY_BRIDGE_VARIABLE))) {
switch_ivr_park_session(session); switch_ivr_park_session(session);
} else if ((var = switch_channel_get_variable(caller_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE))) { } else if ((answered && (var = switch_channel_get_variable(caller_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE))) ||
(var = switch_channel_get_variable(caller_channel, SWITCH_TRANSFER_AFTER_EARLY_BRIDGE_VARIABLE))) {
transfer_after_bridge(session, var); transfer_after_bridge(session, var);
} else { } else if (answered) {
if ((switch_channel_test_flag(peer_channel, CF_ANSWERED) && switch_true(hup))) { if (switch_true(hup)) {
if (switch_channel_test_flag(peer_channel, CF_INTERCEPTED)) { if (switch_channel_test_flag(peer_channel, CF_INTERCEPTED)) {
switch_channel_set_flag(peer_channel, CF_INTERCEPT); switch_channel_set_flag(peer_channel, CF_INTERCEPT);
} }

View File

@ -1863,6 +1863,7 @@ static void *SWITCH_THREAD_FUNC early_thread_run(switch_thread_t *thread, void *
if (!session) continue; if (!session) continue;
if (switch_core_codec_ready((&read_codecs[i]))) { if (switch_core_codec_ready((&read_codecs[i]))) {
switch_core_session_set_read_codec(session, NULL);
switch_core_codec_destroy(&read_codecs[i]); switch_core_codec_destroy(&read_codecs[i]);
} }

View File

@ -1490,12 +1490,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/ */
if (switch_channel_has_dtmf(channel)) { if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, &dtmf);
if (!args->input_callback && !args->buf && !args->dmachine) { if (!args->input_callback && !args->buf && !args->dmachine) {
status = SWITCH_STATUS_BREAK; status = SWITCH_STATUS_BREAK;
done = 1; done = 1;
break; break;
} }
switch_channel_dequeue_dtmf(channel, &dtmf);
if (args->dmachine) { if (args->dmachine) {
char ds[2] = {dtmf.digit, '\0'}; char ds[2] = {dtmf.digit, '\0'};

View File

@ -3259,7 +3259,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
const char *kind = ""; const char *kind = "";
BIO *bio; BIO *bio;
DH *dh; DH *dh;
#ifndef OPENSSL_NO_EC
EC_KEY* ecdh; EC_KEY* ecdh;
#endif
#ifndef HAVE_OPENSSL_DTLS_SRTP #ifndef HAVE_OPENSSL_DTLS_SRTP
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
@ -3367,6 +3369,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
SSL_set_read_ahead(dtls->ssl, 1); SSL_set_read_ahead(dtls->ssl, 1);
//SSL_set_verify(dtls->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), cb_verify_peer); //SSL_set_verify(dtls->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), cb_verify_peer);
#ifndef OPENSSL_NO_EC
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (!ecdh) { if (!ecdh) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
@ -3374,6 +3377,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
SSL_set_options(dtls->ssl, SSL_OP_SINGLE_ECDH_USE); SSL_set_options(dtls->ssl, SSL_OP_SINGLE_ECDH_USE);
SSL_set_tmp_ecdh(dtls->ssl, ecdh); SSL_set_tmp_ecdh(dtls->ssl, ecdh);
EC_KEY_free(ecdh); EC_KEY_free(ecdh);
#endif
SSL_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL); SSL_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL);
SSL_set_app_data(dtls->ssl, dtls); SSL_set_app_data(dtls->ssl, dtls);
@ -6724,6 +6728,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
case RESULT_GOTO_TIMERCHECK: case RESULT_GOTO_TIMERCHECK:
goto timer_check; goto timer_check;
case RESULT_CONTINUE: case RESULT_CONTINUE:
status = SWITCH_STATUS_SUCCESS;
goto result_continue; goto result_continue;
} }