Merge branch 'master' into ff-select-webcam-bug

This commit is contained in:
Anton Georgiev 2019-03-12 13:40:08 -04:00 committed by GitHub
commit 0894788119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
204 changed files with 3278 additions and 2254 deletions

View File

@ -26,7 +26,14 @@ trait CreateGroupChatReqMsgHdlr extends SystemConfiguration {
if (user.role != Roles.MODERATOR_ROLE) {
if (msg.body.access == GroupChatAccess.PRIVATE) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
chatLocked = user.locked && permissions.disablePrivChat
val modMembers = msg.body.users.filter(userId => Users2x.findWithIntId(liveMeeting.users2x, userId) match {
case Some(user) => user.role == Roles.MODERATOR_ROLE
case None => false
})
// don't lock creation of private chats that involve a moderator
if (modMembers.length == 0) {
chatLocked = user.locked && permissions.disablePrivChat
}
} else {
chatLocked = true
}

View File

@ -28,7 +28,14 @@ trait SendGroupChatMessageMsgHdlr {
if (user.role != Roles.MODERATOR_ROLE && user.locked) {
val permissions = MeetingStatus2x.getPermissions(liveMeeting.status)
if (groupChat.access == GroupChatAccess.PRIVATE) {
chatLocked = permissions.disablePrivChat
val modMembers = groupChat.users.filter(cu => Users2x.findWithIntId(liveMeeting.users2x, cu.id) match {
case Some(user) => user.role == Roles.MODERATOR_ROLE
case None => false
})
// don't lock private chats that involve a moderator
if (modMembers.length == 0) {
chatLocked = permissions.disablePrivChat
}
} else {
chatLocked = permissions.disablePubChat
}

View File

@ -131,7 +131,7 @@ class MeetingActor(
meetingExpireIfNoUserJoinedInMs = TimeUtil.minutesToMillis(props.durationProps.meetingExpireIfNoUserJoinedInMinutes),
meetingExpireWhenLastUserLeftInMs = TimeUtil.minutesToMillis(props.durationProps.meetingExpireWhenLastUserLeftInMinutes),
userInactivityInspectTimerInMs = TimeUtil.minutesToMillis(props.durationProps.userInactivityInspectTimerInMinutes),
userInactivityThresholdInMs = TimeUtil.minutesToMillis(props.durationProps.userInactivityInspectTimerInMinutes),
userInactivityThresholdInMs = TimeUtil.minutesToMillis(props.durationProps.userInactivityThresholdInMinutes),
userActivitySignResponseDelayInMs = TimeUtil.minutesToMillis(props.durationProps.userActivitySignResponseDelayInMinutes))
val recordingTracker = new MeetingRecordingTracker(startedOnInMs = 0L, previousDurationInMs = 0L, currentDurationInMs = 0L)
@ -650,8 +650,8 @@ class MeetingActor(
log.info("Check for users who haven't responded to user inactivity warning.")
val users = Users2x.findAll(liveMeeting.users2x)
users foreach { u =>
val respondedOntIme = (lastUserInactivityInspectSentOn - expiryTracker.userInactivityThresholdInMs) < u.lastActivityTime && (lastUserInactivityInspectSentOn + expiryTracker.userActivitySignResponseDelayInMs) > u.lastActivityTime
if (!respondedOntIme) {
val respondedOnTime = (lastUserInactivityInspectSentOn - expiryTracker.userInactivityThresholdInMs) < u.lastActivityTime && (lastUserInactivityInspectSentOn + expiryTracker.userActivitySignResponseDelayInMs) > u.lastActivityTime
if (!respondedOnTime) {
UsersApp.ejectUserFromMeeting(outGW, liveMeeting, u.intId, SystemUser.ID, "User inactive for too long.", EjectReasonCode.USER_INACTIVITY)
Sender.sendDisconnectClientSysMsg(liveMeeting.props.meetingProp.intId, u.intId, SystemUser.ID, EjectReasonCode.USER_INACTIVITY, outGW)
}

View File

@ -314,8 +314,8 @@ public class MeetingService implements MessageListener {
m.getGuestPolicy(), m.getWelcomeMessageTemplate(), m.getWelcomeMessage(), m.getModeratorOnlyMessage(),
m.getDialNumber(), m.getMaxUsers(), m.getMaxInactivityTimeoutMinutes(), m.getWarnMinutesBeforeMax(),
m.getMeetingExpireIfNoUserJoinedInMinutes(), m.getmeetingExpireWhenLastUserLeftInMinutes(),
m.getUserInactivityInspectTimerInMinutes(), m.getUserActivitySignResponseDelayInMinutes(),
m.getUserInactivityThresholdInMinutes(), m.getMuteOnStart(), keepEvents);
m.getUserInactivityInspectTimerInMinutes(), m.getUserInactivityThresholdInMinutes(),
m.getUserActivitySignResponseDelayInMinutes(), m.getMuteOnStart(), keepEvents);
}
private String formatPrettyDate(Long timestamp) {

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FilenameUtils;
@ -121,7 +122,7 @@ public class Pdf2SwfPageConverter implements PageConverter {
log.warn(" --analytics-- data={}", logStr);
File tempPng = null;
String basePresentationame = FilenameUtils.getBaseName(presentation.getName());
String basePresentationame = UUID.randomUUID().toString();
try {
tempPng = File.createTempFile(basePresentationame + "-" + page, ".png");
} catch (IOException ioException) {

View File

@ -5,6 +5,7 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
@ -129,7 +130,7 @@ public class SvgImageCreatorImp implements SvgImageCreator {
log.warn(" --analytics-- data={}", logStr);
File tempPng = null;
String basePresentationame = FilenameUtils.getBaseName(pres.getName());
String basePresentationame = UUID.randomUUID().toString();
try {
tempPng = File.createTempFile(basePresentationame + "-" + i, ".png");
} catch (IOException ioException) {

View File

@ -790,9 +790,9 @@ bbb.shortcutkey.users.makePresenter.function = Make selected person presenter
bbb.shortcutkey.users.kick = 69
bbb.shortcutkey.users.kick.function = Remove selected person from the meeting
bbb.shortcutkey.users.mute = 83
bbb.shortcutkey.users.mute.function = Mute or unmute selected person
bbb.shortcutkey.users.mute.function = Mute selected person
bbb.shortcutkey.users.muteall = 65
bbb.shortcutkey.users.muteall.function = Mute or unmute all users
bbb.shortcutkey.users.muteall.function = Mute all users
bbb.shortcutkey.users.muteAllButPres = 65
bbb.shortcutkey.users.muteAllButPres.function = Mute everyone but the Presenter
bbb.shortcutkey.users.breakoutRooms = 75

View File

@ -217,10 +217,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function refreshListStatus():void {
if (UsersUtil.amIModerator() || UsersUtil.amIPresenter()) return; // Settings only affect viewers.
usersList.enabled = ! LiveMeeting.inst().me.disableMyPrivateChat;
if (LiveMeeting.inst().me.disableMyPrivateChat) {
handler.enableModeratorsFilter();
} else {
handler.disableModeratorsFilter();
}
users = removeMe(handler.users);
}
public function sendSaveEvent():void{

View File

@ -69,6 +69,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.UserStatusChangedEvent;
import org.bigbluebutton.core.model.LiveMeeting;
import org.bigbluebutton.core.model.users.User2x;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.events.UserJoinedEvent;
@ -87,13 +88,13 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.model.ChatOptions;
import org.bigbluebutton.modules.chat.model.GroupChat;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
import org.bigbluebutton.modules.chat.vo.GroupChatUser;
import org.bigbluebutton.modules.polling.events.StartCustomPollEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOGGER:ILogger = getClassLogger(ChatTab);
public var publicChat:Boolean = false;
public var chatWithUserID:String;
public var chatWithUsername:String
public var chatId: String = null;
public var parentWindowId:String = null;
@ -609,7 +610,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
if (publicChat) {
txtMsgArea.enabled = sendBtn.enabled = !LiveMeeting.inst().me.disableMyPublicChat;
} else {
txtMsgArea.enabled = sendBtn.enabled = !LiveMeeting.inst().me.disableMyPrivateChat || LiveMeeting.inst().users.getUser(chatWithUserID).role == Role.MODERATOR;
var chattingWithMod:Boolean = false;
var gc:GroupChat = LiveMeeting.inst().chats.getGroupChat(chatId);
for (var i:int = 0; i < gc.users.length; i++) {
var chatUser:GroupChatUser = gc.users[i] as GroupChatUser;
if (chatUser.id != UsersUtil.getMyUserID()) {
var user:User2x = UsersUtil.getUser(chatUser.id);
if (user && user.role == Role.MODERATOR) {
chattingWithMod = true;
}
}
}
txtMsgArea.enabled = sendBtn.enabled = !LiveMeeting.inst().me.disableMyPrivateChat || chattingWithMod;
}
}

View File

@ -340,7 +340,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
var chatBox:ChatTab = new ChatTab();
chatBox.name = groupChatId;
chatBox.chatWithUserID = groupChatId;
chatBox.parentWindowId = windowId;
chatBox.tabIndexer.startIndex = tabIndexer.startIndex + 10;
chatBox.chatMessages = new ChatConversation(groupChatId);

View File

@ -9,19 +9,27 @@ package org.bigbluebutton.modules.polling.views {
import org.bigbluebutton.modules.present.events.PageLoadedEvent;
import org.bigbluebutton.modules.present.model.Page;
import org.bigbluebutton.modules.present.model.PresentationModel;
import org.bigbluebutton.modules.present.model.PresentationPodManager;
import org.bigbluebutton.util.i18n.ResourceUtil;
public class QuickPollButton extends Button {
private static const LOGGER:ILogger = getClassLogger(QuickPollButton);
private static const LOGGER:ILogger = getClassLogger(QuickPollButton);
private var currentPageId:String;
private var currentPodId:String;
override public function set visible(vsb:Boolean):void {
if (vsb) {
// This button should only be visible when there is a polling at the current slide's text
// var page:Page = PresentationModel.getInstance().getCurrentPage();
// super.visible = page != null ? parseSlideText(page.txtData) : false;
} else {
super.visible = false;
var presentationModel:PresentationModel = PresentationPodManager.getInstance().getPod(PresentationPodManager.DEFAULT_POD_ID);
if (presentationModel != null) {
var page:Page = presentationModel.getCurrentPage();
super.visible = page != null ? parseSlideText(page.txtData) : false;
return;
}
}
super.visible = false;
}
public function QuickPollButton() {
@ -34,7 +42,10 @@ package org.bigbluebutton.modules.polling.views {
}
private function handlePageLoadedEvent(e:PageLoadedEvent):void {
visible = UsersUtil.amIPresenter();
// Only revalidate when it's the default pod that loaded a page
if (e.podId == PresentationPodManager.DEFAULT_POD_ID) {
visible = UsersUtil.amIPresenter();
}
}
private function parseSlideText(text:String):Boolean {

View File

@ -609,9 +609,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
if (this.podId == PresentationPodManager.DEFAULT_POD_ID) { // only allow polling from the default pod
pollStartBtn.visible = showButtons;
quickPollBtn.visible = showButtons;
} else {
pollStartBtn.visible = false;
quickPollBtn.visible = false;
}
quickPollBtn.visible = showButtons;
navigationControls.visible = showButtons;
zoomControls.visible = showButtons;

View File

@ -169,6 +169,9 @@
}
private function kickUser():void{
if (!data.me && !UsersUtil.amIModerator())
return;
if (data.role == Role.VOICE_ONLY ) {
var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.EJECT_USER);
e.userid = data.userId;
@ -185,13 +188,19 @@
}
private function toggleMuteState():void {
if (!data.me && !UsersUtil.amIModerator())
return;
var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.MUTE_USER);
e.userid = data.userId;
e.mute = !data.muted;
e.mute = data.me ? !data.muted : true;
dispatchEvent(e);
}
public function toggleLockState():void {
if (!data.me && !UsersUtil.amIModerator())
return;
var e:LockControlEvent;
if(data.locked) {

View File

@ -6,7 +6,8 @@
horizontalScrollPolicy="off"
creationComplete="onCreationCompleteHandler(event)">
<fx:Declarations>
<mate:Listener type="{BreakoutRoomsReadyEvent.BREAKOUT_ROOMS_READY_EVENT}" method="handleBreakoutRoomsReadyEvent" />
<mate:Listener type="{BreakoutRoomsReadyEvent.BREAKOUT_ROOMS_READY_EVENT}" method="handleBreakoutRoomsReadyEvent" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="handleChangeMyRoleEvent" />
</fx:Declarations>
<fx:Script>
<![CDATA[
@ -19,6 +20,7 @@
import org.bigbluebutton.core.model.LiveMeeting;
import org.bigbluebutton.main.events.BreakoutRoomEvent;
import org.bigbluebutton.main.model.users.BreakoutRoom;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.util.i18n.ResourceUtil;
private var globalDispatch:Dispatcher = new Dispatcher();
@ -40,6 +42,10 @@
breakoutRoomsReady = LiveMeeting.inst().breakoutRooms.breakoutRoomsReady;
}
private function handleChangeMyRoleEvent(event:ChangeMyRole):void {
moderator = UsersUtil.amIModerator();
}
private function dataChangeHandler(event:FlexEvent):void {
if (BreakoutRoom(data).listenStatus == BreakoutRoom.SELF) {
listenBtn.setStyle("icon", getStyle("iconTransferred"));

View File

@ -189,12 +189,15 @@
}
private function roleBtnClicked():void {
if (!data.presenter) {
var e:RoleChangeEvent = new RoleChangeEvent(RoleChangeEvent.ASSIGN_PRESENTER);
e.userid = data.userId;
e.username = data.name;
dispatchEvent(e);
}
if (!data.me && !UsersUtil.amIModerator())
return;
if (!data.presenter) {
var e:RoleChangeEvent = new RoleChangeEvent(RoleChangeEvent.ASSIGN_PRESENTER);
e.userid = data.userId;
e.username = data.name;
dispatchEvent(e);
}
}
private function emojiBtnClicked():void {

View File

@ -697,10 +697,10 @@ $Id: $
}
public function remoteMuteUser():void {
if (amIModerator && usersGrid.selectedIndex != -1) {
if (usersGrid.selectedIndex != -1) {
var selData:BBBUser2x = (usersGrid.selectedItem) as BBBUser2x;
if (selData.inVoiceConf) {
if (selData.inVoiceConf && (selData.me || (UsersUtil.amIModerator() && !selData.muted))) {
var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.MUTE_USER);
e.userid = selData.userId;
e.mute = !selData.muted;

View File

@ -1,17 +1,13 @@
#!/bin/bash -e
# This is a template for apply-config.sh, which if created will be automatically called by
# bbb-conf when you do
# This is a library of functions for apply-config.sh, which, if created, will be automatically called by
# bbb-conf when you run
#
# bbb-conf --restart
# bbb-conf --seitp ...
# bbb-conf --seitp ...
#
# To use this template, copy it to apply-config.sh and make it executable
#
# cp apply-config.template apply-config.sh
# chmod +x apply-config.sh
#
# You can then uncomment some of the built-in configuration options or add your own.
# The purpose of apply-config.sh is to make it easy to apply for your BigBlueButton server that get applied
# before BigBlueButton starts
#
@ -37,6 +33,7 @@ if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
fi
HOST=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
HTML5_CONFIG=/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml
#
@ -45,22 +42,23 @@ HOST=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' |
enableHTML5ClientLog() {
echo " - Enable HTML5 client log to /var/log/nginx/html5-client.log"
HTML5_CONFIG=/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml
yq w -i $HTML5_CONFIG public.clientLog.external.enabled true
yq w -i $HTML5_CONFIG public.clientLog.external.url "$PROTOCOL://$HOST/html5log"
yq w -i $HTML5_CONFIG public.app.askForFeedbackOnLogout true
chown meteor:meteor $HTML5_CONFIG
cat > /etc/bigbluebutton/nginx/html5-client-log.nginx << HERE
location /html5log {
access_log /var/log/nginx/html5-client.log postdata;
echo_read_request_body;
access_log /var/log/nginx/html5-client.log postdata;
echo_read_request_body;
}
HERE
cat > /etc/nginx/conf.d/html5-client-log.conf << HERE
log_format postdata '\$remote_addr [\$time_iso8601] \$request_body';
HERE
# We need nginx-full to enable postdata log_format
# We need nginx-full to enable postdata log_format
if ! dpkg -l | grep -q nginx-full; then
apt-get install -y nginx-full
fi
@ -71,9 +69,33 @@ HERE
#
# You can monitor the live HTML5 client logs with the command
#
# tail -f /var/log/nginx/html5-client.log | sed -u 's/\\x22/"/g' | sed -u 's/\\x5C//g'
# tail -f /var/log/nginx/html5-client.log | sed -u 's/\\x22/"/g' | sed -u 's/\\x5C//g'
}
# Sample commands
#enableHTML5ClientLog
notCalled() {
#
# This function is not called.
# Instead, it gives you the ability to copy the following text and paste it into the shell to create a starting point for
# apply-config.sh.
#
# By creating apply-config.sh manually, it will not be overwritten by any package updates. You can call functions in this
# library for commong BigBlueButton configuration tasks.
## Start Copying HEre
cat > /etc/bigbluebutton/bbb-conf/apply-config.sh << HERE
#!/bin/bash
# Pull in the helper functions for configuring BigBlueButton
source apply-lib.sh
# Put your custom configuration here
enableHTML5ClientLog
HERE
chmod +x /etc/bigbluebutton/bbb-conf/apply-config.sh
## Stop Copying HERE
}

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash
#
# BlueButton open source conferencing system - http://www.bigbluebutton.org/
#
@ -87,12 +87,26 @@ source /etc/bigbluebutton/bigbluebutton-release
# Figure out our environment (Debian vs. CentOS)
#
RED5_DIR=/usr/share/red5
if [ -f /etc/redhat-release ]; then
DISTRIB_ID=centos
SERVLET_LOGS=/usr/share/tomcat/logs
FREESWITCH=freeswitch
TOMCAT_SERVICE=tomcat
REDIS_SERVICE=redis.service
else
. /etc/lsb-release # Get value for DISTRIB_ID
SERVLET_LOGS=$TOMCAT_DIR/logs
FREESWITCH=freeswitch
TOMCAT_SERVICE=tomcat7
REDIS_SERVICE=redis-server
fi
RED5=red5
RED5_DIR=/usr/share/$RED5
SERVLET_CONTAINER=tomcat7
TOMCAT_DIR=/var/lib/$SERVLET_CONTAINER
TOMCAT_DIR=/var/lib/$TOMCAT_SERVICE
LTI_DIR=$TOMCAT_DIR/webapps/lti
if [ -f /usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties ]; then
@ -114,6 +128,7 @@ FREESWITCH_VARS=/opt/freeswitch/conf/vars.xml
FREESWITCH_EXTERNAL=/opt/freeswitch/conf/sip_profiles/external.xml
FREESWITCH_PID=/opt/freeswitch/run/freeswitch.pid
FREESWITCH_EVENT_SOCKET=/opt/freeswitch/conf/autoload_configs/event_socket.conf.xml
FREESWITCH_INIT_D="/etc/init.d/freeswitch"
RECORD_CONFIG=/usr/local/bigbluebutton/core/scripts/bigbluebutton.yml
@ -123,8 +138,11 @@ HTML5_CONFIG=/usr/share/meteor/bundle/programs/server/assets/app/config/settings
KURENTO_CONFIG=/usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml
BBB_WEB_CONFIG=$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties
NGINX_IP=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/server_name/{s/.*server_name[ ]*//;s/;//;p}' | cut -d' ' -f1 | head -n 1)
SIP_CONFIG=/etc/bigbluebutton/nginx/sip.nginx
SIP_NGINX_IP=$(cat $SIP_CONFIG | grep -v '#' | sed -n '/proxy_pass/{s/.*proxy_pass http[s]*:\/\///;s/:.*//;p}' | head -n 1)
NCPU=`nproc --all`
BBB_USER=bigbluebutton
@ -346,7 +364,7 @@ stop_bigbluebutton () {
/etc/init.d/monit stop
/etc/init.d/$RED5 stop
/etc/init.d/${SERVLET_CONTAINER} stop
/etc/init.d/${TOMCAT_SERVICE} stop
/etc/init.d/nginx stop
if [ -a $FREESWITCH_PID ]; then
@ -394,12 +412,14 @@ start_bigbluebutton () {
/etc/bigbluebutton/bbb-conf/apply-config.sh
echo
fi
if grep -q "Failure to connect to CORE_DB sofia_reg_external" /opt/freeswitch/var/log/freeswitch/freeswitch.log; then
if [ -f /opt/freeswitch/var/log/freeswitch/freeswitch.log ]; then
if grep -q "Failure to connect to CORE_DB sofia_reg_external" /opt/freeswitch/var/log/freeswitch/freeswitch.log; then
# See: http://docs.bigbluebutton.org/install/install.html#freeswitch-fails-to-bind-to-ipv4
echo "Clearing the FreeSWITCH database."
rm -rf /opt/freeswitch/var/lib/freeswitch/db/*
fi
fi
fi
# Clear any previous registration errors
if [ -f /usr/share/red5/log/sip.log ]; then
@ -448,7 +468,7 @@ start_bigbluebutton () {
/etc/init.d/nginx start
/etc/init.d/$RED5 start
/etc/init.d/${SERVLET_CONTAINER} start
/etc/init.d/${TOMCAT_SERVICE} start
# monit will start libreoffice and bbb-rap-worker
/etc/init.d/monit start
@ -496,7 +516,6 @@ start_bigbluebutton () {
#
echo -n "Waiting for BigBlueButton to finish starting up (this may take a minute): "
NGINX_IP=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/server_name/{s/.*server_name[ ]*//;s/;//;p}' | cut -d' ' -f1)
check_no_value server_name /etc/nginx/sites-available/bigbluebutton $NGINX_IP
#if ! wget http://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS; then
@ -574,7 +593,7 @@ display_bigbluebutton_status () {
else
/etc/init.d/nginx status
/etc/init.d/$RED5 status
/etc/init.d/${SERVLET_CONTAINER} status
/etc/init.d/${TOMCAT_SERVICE} status
fi
}
@ -871,7 +890,6 @@ check_configuration() {
#
# Check if the IP resolves to a different host
#
NGINX_IP=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/server_name/{s/.*server_name[ ]*//;s/;//;p}' | cut -d' ' -f1)
check_no_value server_name /etc/nginx/sites-available/bigbluebutton $NGINX_IP
if which host > /dev/null 2>&1; then
@ -915,7 +933,6 @@ check_configuration() {
fi
BBB_SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
NGINX_IP=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/server_name/{s/.*server_name[ ]*//;s/;//;p}' | cut -d' ' -f1)
if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.js ]; then
@ -958,7 +975,7 @@ check_configuration() {
fi
fi
PROTOCOL=$(cat /etc/bigbluebutton/nginx/sip.nginx | sed -n '/proxy_pass/{s/.*proxy_pass [ ]*//;s/:.*//;p}')
PROTOCOL=$(cat /etc/bigbluebutton/nginx/sip.nginx | grep -v \# | sed -n '/proxy_pass/{s/.*proxy_pass [ ]*//;s/:.*//;p}' | head -n 1)
if [[ $PROTOCOL == "https" ]]; then
if ! grep wss-binding $FREESWITCH_EXTERNAL > /dev/null; then
echo "# Warning: Websockets is using HTTPS in /etc/bigbluebutton/nginx/sip.nginx"
@ -1027,6 +1044,34 @@ check_configuration() {
echo "#"
fi
fi
GUEST_POLICY=$(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^defaultGuestPolicy/{s/.*=//;p}')
if [ "$GUEST_POLICY" == "ASK_MODERATOR" ]; then
echo
echo "# Warning: defaultGuestPolicy is set to ASK_MODERATOR in"
echo "# $BBB_WEB_CONFIG"
echo "# This is not yet supported yet the HTML5 client."
echo "#"
echo "# To revert it to ALWAYS_ALLOW, see"
echo "#"
echo "# $SUDO sed -i s/^defaultGuestPolicy=.*$/defaultGuestPolicy=ALWAYS_ALLOW/g $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties"
echo "#"
echo
fi
if [ -f $HTML5_CONFIG ]; then
SVG_IMAGES_REQUIRED=$(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^svgImagesRequired/{s/.*=//;p}')
if [ "$SVG_IMAGES_REQUIRED" != "true" ]; then
echo
echo "# Warning: You have the HTML5 client installed but in"
echo "#"
echo "# $BBB_WEB_CONFIG"
echo "#"
echo "# the setting for svgImagesRequired is false. To fix, run the commnad"
echo "#"
echo "# sed -i 's/^svgImagesRequired=.*/svgImagesRequired=true/' $BBB_WEB_CONFIG "
echo "#"
fi
fi
}
@ -1067,14 +1112,14 @@ check_state() {
if ! netstat -ant | grep '8090' > /dev/null; then
print_header
NOT_RUNNING_APPS="${NOT_RUNNING_APPS} ${SERVLET_CONTAINER} or grails"
NOT_RUNNING_APPS="${NOT_RUNNING_APPS} ${TOMCAT_SERVICE} or grails"
else
if ps aux | ps -aef | grep -v grep | grep grails | grep run-app > /dev/null; then
print_header
RUNNING_APPS="${RUNNING_APPS} Grails"
echo "# ${SERVLET_CONTAINER}: noticed you are running grails run-app instead of ${SERVLET_CONTAINER}"
echo "# ${TOMCAT_SERVICE}: noticed you are running grails run-app instead of ${TOMCAT_SERVICE}"
else
RUNNING_APPS="${RUNNING_APPS} ${SERVLET_CONTAINER}"
RUNNING_APPS="${RUNNING_APPS} ${TOMCAT_SERVICE}"
fi
fi
@ -1315,11 +1360,11 @@ check_state() {
check_no_value server_name /etc/nginx/sites-available/bigbluebutton $BBB_WEB
COUNT=0
while [ $COUNT -lt 30 ]; do
while [ $COUNT -lt 80 ]; do
let COUNT=COUNT+1
timeout 1s wget $PROTOCOL://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS
if [ $? -eq 0 ]; then
let COUNT=40
let COUNT=80
else
echo -n "."
sleep 1
@ -1374,7 +1419,6 @@ check_state() {
fi
fi
SIP_NGINX_IP=$(cat /etc/bigbluebutton/nginx/sip.nginx | grep -v '#' | sed -n '/proxy_pass/{s/.*proxy_pass http[s]*:\/\///;s/:.*//;p}')
if [ "$SIP_NGINX_IP" != $IP ]; then
if [ "$SIP_NGINX_IP" != "\$freeswitch_addr" ]; then
echo "# Warning: The setting of $SIP_NGINX_IP for proxy_pass in"
@ -1430,7 +1474,11 @@ check_state() {
BBB_WEB_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
echo "# Warning: The API demos are installed and accessible from:"
echo "#"
echo "# $BBB_WEB_URL/demo/demo1.jsp"
echo "# $BBB_WEB_URL"
echo "#"
echo "# and"
echo "#"
echo "# $BBB_WEB_URL/demo/demo1.jsp"
echo "#"
echo "# These API demos allow anyone to access your server without authentication"
echo "# to create/manage meetings and recordings. They are for testing purposes only."
@ -1580,15 +1628,16 @@ if [ $CHECK ]; then
fi
echo " Memory: $MEM MB"
echo " CPU cores: $NCPU"
echo
echo "$BBB_WEB_CONFIG (bbb-web)"
echo " bigbluebutton.web.serverURL: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')"
echo " defaultGuestPolicy: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^defaultGuestPolicy/{s/.*=//;p}')"
echo " svgImagesRequired: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^svgImagesRequired/{s/.*=//;p}')"
echo
echo "/etc/nginx/sites-available/bigbluebutton (nginx)"
NGINX_IP=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/server_name/{s/.*server_name[ ]*//;s/;//;p}' | cut -d' ' -f1)
echo " server name: $NGINX_IP"
PORT=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/listen/{s/.*listen[ ]*//;s/;//;p}' | grep -v ssl | tr --delete '\n' | sed 's/\[/, \[/g' | sed 's/0$/0\n/g')
@ -1654,7 +1703,7 @@ if [ $CHECK ]; then
if [ -f $SIP_CONFIG ]; then
echo
echo "$SIP_CONFIG (sip.nginx)"
echo " proxy_pass: $(cat $SIP_CONFIG | grep proxy_pass | sed 's/.*proxy_pass //g' | sed 's/;//'g )"
echo " proxy_pass: $SIP_NGINX_IP"
fi
if [ -f $KURENTO_CONFIG ]; then

View File

@ -68,7 +68,9 @@ find /var/freeswitch/meetings/ -name "*.wav" -mtime +$history -delete
#
find /opt/freeswitch/var/log/freeswitch -type f -mtime +$log_history -delete
find /var/log/red5 -type f -mtime +$log_history -delete
find /var/log/tomcat7 -type f -mtime +$log_history -delete
if [ -d /var/log/tomcat7 ]; then
find /var/log/tomcat7 -type f -mtime +$log_history -delete
fi
find /var/log/bigbluebutton -type f -mtime +$log_history -delete
#

View File

@ -1,561 +0,0 @@
(function($){function findLine(sdpLines,prefix,substr){return findLineInRange(sdpLines,0,-1,prefix,substr);}
function findLineInRange(sdpLines,startLine,endLine,prefix,substr){var realEndLine=(endLine!=-1)?endLine:sdpLines.length;for(var i=startLine;i<realEndLine;++i){if(sdpLines[i].indexOf(prefix)===0){if(!substr||sdpLines[i].toLowerCase().indexOf(substr.toLowerCase())!==-1){return i;}}}
return null;}
function getCodecPayloadType(sdpLine){var pattern=new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');var result=sdpLine.match(pattern);return(result&&result.length==2)?result[1]:null;}
function setDefaultCodec(mLine,payload){var elements=mLine.split(' ');var newLine=[];var index=0;for(var i=0;i<elements.length;i++){if(index===3){newLine[index++]=payload;}
if(elements[i]!==payload)newLine[index++]=elements[i];}
return newLine.join(' ');}
$.FSRTC=function(options){this.options=$.extend({useVideo:null,useStereo:false,userData:null,localVideo:null,screenShare:false,useCamera:"any",iceServers:false,videoParams:{},audioParams:{},callbacks:{onICEComplete:function(){},onICE:function(){},onOfferSDP:function(){}},},options);this.audioEnabled=true;this.videoEnabled=true;this.mediaData={SDP:null,profile:{},candidateList:[]};this.constraints={offerToReceiveAudio:this.options.useSpeak==="none"?false:true,offerToReceiveVideo:this.options.useVideo?true:false,};if(self.options.useVideo){self.options.useVideo.style.display='none';}
setCompat();checkCompat();};$.FSRTC.validRes=[];$.FSRTC.prototype.useVideo=function(obj,local){var self=this;if(obj){self.options.useVideo=obj;self.options.localVideo=local;self.constraints.offerToReceiveVideo=true;}else{self.options.useVideo=null;self.options.localVideo=null;self.constraints.offerToReceiveVideo=false;}
if(self.options.useVideo){self.options.useVideo.style.display='none';}};$.FSRTC.prototype.useStereo=function(on){var self=this;self.options.useStereo=on;};$.FSRTC.prototype.stereoHack=function(sdp){var self=this;if(!self.options.useStereo){return sdp;}
var sdpLines=sdp.split('\r\n');var opusIndex=findLine(sdpLines,'a=rtpmap','opus/48000'),opusPayload;if(!opusIndex){return sdp;}else{opusPayload=getCodecPayloadType(sdpLines[opusIndex]);}
var fmtpLineIndex=findLine(sdpLines,'a=fmtp:'+opusPayload.toString());if(fmtpLineIndex===null){sdpLines[opusIndex]=sdpLines[opusIndex]+'\r\na=fmtp:'+opusPayload.toString()+" stereo=1; sprop-stereo=1"}else{sdpLines[fmtpLineIndex]=sdpLines[fmtpLineIndex].concat('; stereo=1; sprop-stereo=1');}
sdp=sdpLines.join('\r\n');return sdp;};function setCompat(){}
function checkCompat(){return true;}
function onStreamError(self,e){console.log('There has been a problem retrieving the streams - did you allow access? Check Device Resolution',e);doCallback(self,"onError",e);}
function onStreamSuccess(self,stream){console.log("Stream Success");doCallback(self,"onStream",stream);}
function onICE(self,candidate){self.mediaData.candidate=candidate;self.mediaData.candidateList.push(self.mediaData.candidate);doCallback(self,"onICE");}
function doCallback(self,func,arg){if(func in self.options.callbacks){self.options.callbacks[func](self,arg);}}
function onICEComplete(self,candidate){console.log("ICE Complete");doCallback(self,"onICEComplete");}
function onChannelError(self,e){console.error("Channel Error",e);doCallback(self,"onError",e);}
function onICESDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("ICE SDP");doCallback(self,"onICESDP");}
function onAnswerSDP(self,sdp){self.answer.SDP=self.stereoHack(sdp.sdp);console.log("ICE ANSWER SDP");doCallback(self,"onAnswerSDP",self.answer.SDP);}
function onMessage(self,msg){console.log("Message");doCallback(self,"onICESDP",msg);}
FSRTCattachMediaStream=function(element,stream){if(typeof element.srcObject!=='undefined'){element.srcObject=stream;}else if(typeof element.src!=='undefined'){element.src=URL.createObjectURL(stream);}else{console.error('Error attaching stream to element.');}}
function onRemoteStream(self,stream){if(self.options.useVideo){self.options.useVideo.style.display='block';}
var element=self.options.useAudio;console.log("REMOTE STREAM",stream,element);FSRTCattachMediaStream(element,stream);self.options.useAudio.play();self.remoteStream=stream;}
function onOfferSDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("Offer SDP");doCallback(self,"onOfferSDP");}
$.FSRTC.prototype.answer=function(sdp,onSuccess,onError){this.peer.addAnswerSDP({type:"answer",sdp:sdp},onSuccess,onError);};$.FSRTC.prototype.stopPeer=function(){if(self.peer){console.log("stopping peer");self.peer.stop();}}
$.FSRTC.prototype.stop=function(){var self=this;if(self.options.useVideo){self.options.useVideo.style.display='none';self.options.useVideo['src']='';}
if(self.localStream){if(typeof self.localStream.stop=='function'){self.localStream.stop();}else{if(self.localStream.active){var tracks=self.localStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}
self.localStream=null;}
if(self.options.localVideo){self.options.localVideo.style.display='none';self.options.localVideo['src']='';}
if(self.options.localVideoStream){if(typeof self.options.localVideoStream.stop=='function'){self.options.localVideoStream.stop();}else{if(self.options.localVideoStream.active){var tracks=self.options.localVideoStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}}
if(self.peer){console.log("stopping peer");self.peer.stop();}};$.FSRTC.prototype.getMute=function(){var self=this;return self.audioEnabled;}
$.FSRTC.prototype.setMute=function(what){var self=this;var audioTracks=self.localStream.getAudioTracks();for(var i=0,len=audioTracks.length;i<len;i++){switch(what){case"on":audioTracks[i].enabled=true;break;case"off":audioTracks[i].enabled=false;break;case"toggle":audioTracks[i].enabled=!audioTracks[i].enabled;default:break;}
self.audioEnabled=audioTracks[i].enabled;}
return!self.audioEnabled;}
$.FSRTC.prototype.getVideoMute=function(){var self=this;return self.videoEnabled;}
$.FSRTC.prototype.setVideoMute=function(what){var self=this;var videoTracks=self.localStream.getVideoTracks();for(var i=0,len=videoTracks.length;i<len;i++){switch(what){case"on":videoTracks[i].enabled=true;break;case"off":videoTracks[i].enabled=false;break;case"toggle":videoTracks[i].enabled=!videoTracks[i].enabled;default:break;}
self.videoEnabled=videoTracks[i].enabled;}
return!self.videoEnabled;}
$.FSRTC.prototype.createAnswer=function(params){var self=this;self.type="answer";self.remoteSDP=params.sdp;console.debug("inbound sdp: ",params.sdp);function onSuccess(stream){self.localStream=stream;self.peer=FSRTCPeerConnection({type:self.type,attachStream:self.localStream,onICE:function(candidate){return onICE(self,candidate);},onICEComplete:function(){return onICEComplete(self);},onRemoteStream:function(stream){return onRemoteStream(self,stream);},onICESDP:function(sdp){return onICESDP(self,sdp);},onChannelError:function(e){return onChannelError(self,e);},constraints:self.constraints,iceServers:self.options.iceServers,offerSDP:{type:"offer",sdp:self.remoteSDP}});onStreamSuccess(self,stream);}
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:{},},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",obj.options.videoParams);audio=false;}else{audio={};if(obj.options.audioParams){audio=obj.options.audioParams;}
if(obj.options.useMic!=="any"){audio.deviceId={exact:obj.options.useMic};}}
if(obj.options.useVideo&&obj.options.localVideo){getUserMedia({constraints:{audio:false,video:obj.options.videoParams},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;var minFrameRate=obj.options.videoParams.minFrameRate||15;delete obj.options.videoParams.vertoBestFrameRate;if(obj.options.screenShare){if(!obj.options.useCamera&&!!navigator.mozGetUserMedia){var dowin=window.confirm("Do you want to share an application window? If not you can share an entire screen.");video={width:{min:obj.options.videoParams.minWidth,max:obj.options.videoParams.maxWidth},height:{min:obj.options.videoParams.minHeight,max:obj.options.videoParams.maxHeight},mediaSource:dowin?"window":"screen"}}else{var opt=[];if(obj.options.useCamera){opt.push({sourceId:obj.options.useCamera});}
if(bestFrameRate){opt.push({minFrameRate:bestFrameRate});opt.push({maxFrameRate:bestFrameRate});}
video={mandatory:obj.options.videoParams,optional:opt};}}else{video={width:{min:obj.options.videoParams.minWidth,max:obj.options.videoParams.maxWidth},height:{min:obj.options.videoParams.minHeight,max:obj.options.videoParams.maxHeight}};var useVideo=obj.options.useVideo;if(useVideo&&obj.options.useCamera&&obj.options.useCamera!=="none"){if(obj.options.useCamera!=="any"){video.deviceId=obj.options.useCamera;}
if(bestFrameRate){video.frameRate={ideal:bestFrameRate,min:minFrameRate,max:30};}}else{console.log("Camera Disabled");video=false;useVideo=false;}}
return{audio:audio,video:video,useVideo:useVideo};}
$.FSRTC.prototype.call=function(profile){checkCompat();var self=this;var screen=false;self.type="offer";if(self.options.videoParams&&self.options.screenShare){screen=true;}
function onSuccess(stream){self.localStream=stream;if(screen){self.constraints.offerToReceiveVideo=false;self.constraints.offerToReceiveAudio=false;self.constraints.offerToSendAudio=false;}
self.peer=FSRTCPeerConnection({type:self.type,attachStream:self.localStream,onICE:function(candidate){return onICE(self,candidate);},onICEComplete:function(){return onICEComplete(self);},onRemoteStream:screen?function(stream){}:function(stream){return onRemoteStream(self,stream);},onOfferSDP:function(sdp){return onOfferSDP(self,sdp);},onICESDP:function(sdp){return onICESDP(self,sdp);},onChannelError:function(e){return onChannelError(self,e);},constraints:self.constraints,iceServers:self.options.iceServers,});onStreamSuccess(self,stream);}
function onError(e){onStreamError(self,e);}
var mediaParams=getMediaParams(self);console.log("Audio constraints",mediaParams.audio);console.log("Video constraints",mediaParams.video);if(mediaParams.audio||mediaParams.video){getUserMedia({constraints:{audio:mediaParams.audio,video:mediaParams.video},video:mediaParams.useVideo,onsuccess:onSuccess,onerror:onError});}else{onSuccess(null);}};function FSRTCPeerConnection(options){var gathering=false,done=false;var config={};var default_ice={urls:['stun:stun.l.google.com:19302']};if(options.iceServers){if(typeof(options.iceServers)==="boolean"){config.iceServers=[default_ice];}else{config.iceServers=options.iceServers;}}
var peer=new window.RTCPeerConnection(config);openOffererChannel();var x=0;function ice_handler(){done=true;gathering=null;if(options.onICEComplete){options.onICEComplete();}
if(options.type=="offer"){options.onICESDP(peer.localDescription);}else{if(!x&&options.onICESDP){options.onICESDP(peer.localDescription);}}}
peer.onicecandidate=function(event){if(done){return;}
if(!gathering){gathering=setTimeout(ice_handler,1000);}
if(event){if(event.candidate){options.onICE(event.candidate);}}else{done=true;if(gathering){clearTimeout(gathering);gathering=null;}
ice_handler();}};if(options.attachStream)peer.addStream(options.attachStream);if(options.attachStreams&&options.attachStream.length){var streams=options.attachStreams;for(var i=0;i<streams.length;i++){peer.addStream(streams[i]);}}
peer.onaddstream=function(event){var remoteMediaStream=event.stream;remoteMediaStream.oninactive=function(){if(options.onRemoteStreamEnded)options.onRemoteStreamEnded(remoteMediaStream);};if(options.onRemoteStream)options.onRemoteStream(remoteMediaStream);};function createOffer(){if(!options.onOfferSDP)return;peer.createOffer(function(sessionDescription){sessionDescription.sdp=serializeSdp(sessionDescription.sdp);peer.setLocalDescription(sessionDescription);options.onOfferSDP(sessionDescription);},onSdpError,options.constraints);}
function createAnswer(){if(options.type!="answer")return;peer.setRemoteDescription(new window.RTCSessionDescription(options.offerSDP),onSdpSuccess,onSdpError);peer.createAnswer(function(sessionDescription){sessionDescription.sdp=serializeSdp(sessionDescription.sdp);peer.setLocalDescription(sessionDescription);if(options.onAnswerSDP){options.onAnswerSDP(sessionDescription);}},onSdpError);}
if((options.onChannelMessage)||!options.onChannelMessage){createOffer();createAnswer();}
function setBandwidth(sdp){sdp=sdp.replace(/b=AS([^\r\n]+\r\n)/g,'');sdp=sdp.replace(/a=mid:data\r\n/g,'a=mid:data\r\nb=AS:1638400\r\n');return sdp;}
function getInteropSDP(sdp){var chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),extractedChars='';function getChars(){extractedChars+=chars[parseInt(Math.random()*40)]||'';if(extractedChars.length<40)getChars();return extractedChars;}
if(options.onAnswerSDP)sdp=sdp.replace(/(a=crypto:0 AES_CM_128_HMAC_SHA1_32)(.*?)(\r\n)/g,'');var inline=getChars()+'\r\n'+(extractedChars='');sdp=sdp.indexOf('a=crypto')==-1?sdp.replace(/c=IN/g,'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:'+inline+'c=IN'):sdp;return sdp;}
function serializeSdp(sdp){return sdp;}
var channel;function openOffererChannel(){if(!options.onChannelMessage)return;_openOffererChannel();return;}
function _openOffererChannel(){channel=peer.createDataChannel(options.channel||'RTCDataChannel',{reliable:false});setChannelEvents();}
function setChannelEvents(){channel.onmessage=function(event){if(options.onChannelMessage)options.onChannelMessage(event);};channel.onopen=function(){if(options.onChannelOpened)options.onChannelOpened(channel);};channel.onclose=function(event){if(options.onChannelClosed)options.onChannelClosed(event);console.warn('WebRTC DataChannel closed',event);};channel.onerror=function(event){if(options.onChannelError)options.onChannelError(event);console.error('WebRTC DataChannel error',event);};}
function openAnswererChannel(){peer.ondatachannel=function(event){channel=event.channel;channel.binaryType='blob';setChannelEvents();};return;}
function useless(){log('Error in fake:true');}
function onSdpSuccess(){}
function onSdpError(e){if(options.onChannelError){options.onChannelError(e);}
console.error('sdp error:',e);}
return{addAnswerSDP:function(sdp,cbSuccess,cbError){peer.setRemoteDescription(new window.RTCSessionDescription(sdp),cbSuccess?cbSuccess:onSdpSuccess,cbError?cbError:onSdpError);},addICE:function(candidate){peer.addIceCandidate(new window.RTCIceCandidate({sdpMLineIndex:candidate.sdpMLineIndex,candidate:candidate.candidate}));},peer:peer,channel:channel,sendData:function(message){if(channel){channel.send(message);}},stop:function(){peer.close();if(options.attachStream){if(typeof options.attachStream.stop=='function'){options.attachStream.stop();}else{options.attachStream.active=false;}}}};}
var video_constraints={};function getUserMedia(options){var n=navigator,media;n.getMedia=n.getUserMedia;n.getMedia(options.constraints||{audio:true,video:video_constraints},streaming,options.onerror||function(e){console.error(e);});function streaming(stream){if(options.localVideo){options.localVideo['src']=window.URL.createObjectURL(stream);options.localVideo.style.display='block';}
if(options.onsuccess){options.onsuccess(stream);}
media=stream;}
return media;}
$.FSRTC.resSupported=function(w,h){for(var i in $.FSRTC.validRes){if($.FSRTC.validRes[i][0]==w&&$.FSRTC.validRes[i][1]==h){return true;}}
return false;}
$.FSRTC.bestResSupported=function(){var w=0,h=0;for(var i in $.FSRTC.validRes){if($.FSRTC.validRes[i][0]>=w&&$.FSRTC.validRes[i][1]>=h){w=$.FSRTC.validRes[i][0];h=$.FSRTC.validRes[i][1];}}
return[w,h];}
var resList=[[160,120],[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={}
if(cam){video.deviceId={exact:cam};}
w=resList[resI][0];h=resList[resI][1];resI++;video={width:{exact:w},height:{exact: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.warn(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");}
return func?func(cache):null;}
$.FSRTC.validRes=[];resI=0;checkRes(cam,func);}
$.FSRTC.checkPerms=function(runtime,check_audio,check_video){getUserMedia({constraints:{audio:check_audio,video:check_video,},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info("media perm init complete");if(runtime){setTimeout(runtime,100,true);}},onerror:function(e){if(check_video&&check_audio){console.error("error, retesting with audio params only");return $.FSRTC.checkPerms(runtime,check_audio,false);}
console.error("media perm init error");if(runtime){runtime(false)}}});}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,loginParams:null,userVariables:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);self.ws_cnt=0;this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.speedTest=function(bytes,cb){var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this.speedCB=cb;this.speedBytes=bytes;socket.send("#SPU "+bytes);var loops=bytes/1024;var rem=bytes%1024;var i;var data=new Array(1024).join(".");for(i=0;i<loops;i++){socket.send("#SPB "+data);}
if(rem){socket.send("#SPB "+data);}
socket.send("#SPE");}};$.JsonRpcClient.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
if(this.options.sessid){params.sessid=this.options.sessid;}
var request={jsonrpc:'2.0',method:method,params:params,id:this._current_id++};if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this._wsCall(socket,request,success_cb,error_cb);return;}
if(this.options.ajaxUrl===null){throw"$.JsonRpcClient.call used with no websocket and no http endpoint.";}
$.ajax({type:'POST',url:this.options.ajaxUrl,data:$.toJSON(request),dataType:'json',cache:false,success:function(data){if('error'in data)error_cb(data.error,this);success_cb(data.result,this);},error:function(jqXHR,textStatus,errorThrown){try{var response=$.parseJSON(jqXHR.responseText);if('console'in window)console.log(response);error_cb(response.error,this);}catch(err){error_cb({error:jqXHR.responseText},this);}}});};$.JsonRpcClient.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
var request={jsonrpc:'2.0',method:method,params:params};var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this._wsCall(socket,request);return;}
if(this.options.ajaxUrl===null){throw"$.JsonRpcClient.notify used with no websocket and no http endpoint.";}
$.ajax({type:'POST',url:this.options.ajaxUrl,data:$.toJSON(request),dataType:'json',cache:false});};$.JsonRpcClient.prototype.batch=function(callback,all_done_cb,error_cb){var batch=new $.JsonRpcClient._batchObject(this,all_done_cb,error_cb);callback(batch);batch._execute();};$.JsonRpcClient.prototype.socketReady=function(){if(this._ws_socket===null||this._ws_socket.readyState>1){return false;}
return true;};$.JsonRpcClient.prototype.closeSocket=function(){var self=this;if(self.socketReady()){self._ws_socket.onclose=function(w){console.log("Closing Socket");};self._ws_socket.close();}};$.JsonRpcClient.prototype.loginData=function(params){var self=this;self.options.login=params.login;self.options.passwd=params.passwd;self.options.loginParams=params.loginParams;self.options.userVariables=params.userVariables;};$.JsonRpcClient.prototype.connectSocket=function(onmessage_cb){var self=this;if(self.to){clearTimeout(self.to);}
if(!self.socketReady()){self.authing=false;if(self._ws_socket){delete self._ws_socket;}
self._ws_socket=new WebSocket(self.options.socketUrl);if(self._ws_socket){self._ws_socket.onmessage=onmessage_cb;self._ws_socket.onclose=function(w){if(!self.ws_sleep){self.ws_sleep=1000;}
if(self.options.onWSClose){self.options.onWSClose(self);}
console.error("Websocket Lost "+self.ws_cnt+" sleep: "+self.ws_sleep+"msec");self.to=setTimeout(function(){console.log("Attempting Reconnection....");self.connectSocket(onmessage_cb);},self.ws_sleep);self.ws_cnt++;if(self.ws_sleep<3000&&(self.ws_cnt%10)===0){self.ws_sleep+=1000;}};self._ws_socket.onopen=function(){if(self.to){clearTimeout(self.to);}
self.ws_sleep=1000;self.ws_cnt=0;if(self.options.onWSConnect){self.options.onWSConnect(self);}
var req;while((req=$.JsonRpcClient.q.pop())){self._ws_socket.send(req);}};}}
return self._ws_socket?true:false;};$.JsonRpcClient.prototype.stopRetrying=function(){if(self.to)
clearTimeout(self.to);}
$.JsonRpcClient.prototype._getSocket=function(onmessage_cb){if(this.options.socketUrl===null||!("WebSocket"in window))return null;this.connectSocket(onmessage_cb);return this._ws_socket;};$.JsonRpcClient.q=[];$.JsonRpcClient.prototype._wsCall=function(socket,request,success_cb,error_cb){var request_json=$.toJSON(request);if(socket.readyState<1){self=this;$.JsonRpcClient.q.push(request_json);}else{socket.send(request_json);}
if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;if(event.data[0]=="#"&&event.data[1]=="S"&&event.data[2]=="P"){if(event.data[3]=="U"){this.up_dur=parseInt(event.data.substring(4));}else if(this.speedCB&&event.data[3]=="D"){this.down_dur=parseInt(event.data.substring(4));var up_kps=(((this.speedBytes*8)/(this.up_dur/1000))/1024).toFixed(0);var down_kps=(((this.speedBytes*8)/(this.down_dur/1000))/1024).toFixed(0);console.info("Speed Test: Up: "+up_kps+" Down: "+down_kps);this.speedCB(event,{upDur:this.up_dur,downDur:this.down_dur,upKPS:up_kps,downKPS:down_kps});this.speedCB=null;}
return;}
try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd,loginParams:self.options.loginParams,userVariables:self.options.userVariables},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
if(self.options.onWSLogin){self.options.onWSLogin(true,self);}},function(e){console.log("error logging in, request id:",response.id);delete self._ws_callbacks[response.id];error_cb(response.error,this);if(self.options.onWSLogin){self.options.onWSLogin(false,self);}});return;}
delete this._ws_callbacks[response.id];error_cb(response.error,this);return;}}}catch(err){console.log("ERROR: "+err);return;}
if(typeof this.options.onmessage==='function'){event.eventData=response;if(!event.eventData){event.eventData={};}
var reply=this.options.onmessage(event);if(reply&&typeof reply==="object"&&event.eventData.id){var msg={jsonrpc:"2.0",id:event.eventData.id,result:reply};var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send($.toJSON(msg));}}}};$.JsonRpcClient._batchObject=function(jsonrpcclient,all_done_cb,error_cb){this._requests=[];this.jsonrpcclient=jsonrpcclient;this.all_done_cb=all_done_cb;this.error_cb=typeof error_cb==='function'?error_cb:function(){};};$.JsonRpcClient._batchObject.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
if(this.options.sessid){params.sessid=this.options.sessid;}
if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
this._requests.push({request:{jsonrpc:'2.0',method:method,params:params,id:this.jsonrpcclient._current_id++},success_cb:success_cb,error_cb:error_cb});};$.JsonRpcClient._batchObject.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
this._requests.push({request:{jsonrpc:'2.0',method:method,params:params}});};$.JsonRpcClient._batchObject.prototype._execute=function(){var self=this;if(this._requests.length===0)return;var batch_request=[];var handlers={};var i=0;var call;var success_cb;var error_cb;var socket=self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);if(socket!==null){for(i=0;i<this._requests.length;i++){call=this._requests[i];success_cb=('success_cb'in call)?call.success_cb:undefined;error_cb=('error_cb'in call)?call.error_cb:undefined;self.jsonrpcclient._wsCall(socket,call.request,success_cb,error_cb);}
if(typeof all_done_cb==='function')all_done_cb(result);return;}
for(i=0;i<this._requests.length;i++){call=this._requests[i];batch_request.push(call.request);if('id'in call.request){handlers[call.request.id]={success_cb:call.success_cb,error_cb:call.error_cb};}}
success_cb=function(data){self._batchCb(data,handlers,self.all_done_cb);};if(self.jsonrpcclient.options.ajaxUrl===null){throw"$.JsonRpcClient.batch used with no websocket and no http endpoint.";}
$.ajax({url:self.jsonrpcclient.options.ajaxUrl,data:$.toJSON(batch_request),dataType:'json',cache:false,type:'POST',error:function(jqXHR,textStatus,errorThrown){self.error_cb(jqXHR,textStatus,errorThrown);},success:success_cb});};$.JsonRpcClient._batchObject.prototype._batchCb=function(result,handlers,all_done_cb){for(var i=0;i<result.length;i++){var response=result[i];if('error'in response){if(response.id===null||!(response.id in handlers)){if('console'in window)console.log(response);}else{handlers[response.id].error_cb(response.error,this);}}else{if(!(response.id in handlers)&&'console'in window){console.log(response);}else{handlers[response.id].success_cb(response.result,this);}}}
if(typeof all_done_cb==='function')all_done_cb(result);};})(jQuery);(function($){var sources=[];var generateGUID=(typeof(window.crypto)!=='undefined'&&typeof(window.crypto.getRandomValues)!=='undefined')?function(){var buf=new Uint16Array(8);window.crypto.getRandomValues(buf);var S4=function(num){var ret=num.toString(16);while(ret.length<4){ret="0"+ret;}
return ret;};return(S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));}:function(){return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){var r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);return v.toString(16);});};$.verto=function(options,callbacks){var verto=this;$.verto.saved.push(verto);verto.options=$.extend({login:null,passwd:null,socketUrl:null,tag:null,localTag:null,videoParams:{},audioParams:{},loginParams:{},deviceParams:{onResCheck:null},userVariables:{},iceServers:false,ringSleep:6000,sessid:null},options);if(verto.options.deviceParams.useCamera){$.FSRTC.getValidRes(verto.options.deviceParams.useCamera,verto.options.deviceParams.onResCheck);}
if(!verto.options.deviceParams.useMic){verto.options.deviceParams.useMic="any";}
if(!verto.options.deviceParams.useSpeak){verto.options.deviceParams.useSpeak="any";}
if(verto.options.sessid){verto.sessid=verto.options.sessid;}else{verto.sessid=localStorage.getItem("verto_session_uuid")||generateGUID();localStorage.setItem("verto_session_uuid",verto.sessid);}
verto.dialogs={};verto.callbacks=callbacks||{};verto.eventSUBS={};verto.rpcClient=new $.JsonRpcClient({login:verto.options.login,passwd:verto.options.passwd,socketUrl:verto.options.socketUrl,loginParams:verto.options.loginParams,userVariables:verto.options.userVariables,sessid:verto.sessid,onmessage:function(e){return verto.handleMessage(e.eventData);},onWSConnect:function(o){o.call('login',{});},onWSLogin:function(success){if(verto.callbacks.onWSLogin){verto.callbacks.onWSLogin(verto,success);}},onWSClose:function(success){if(verto.callbacks.onWSClose){verto.callbacks.onWSClose(verto,success);}
verto.purge();}});var tag=verto.options.tag;if(typeof(tag)==="function"){tag=tag();}
if(verto.options.ringFile&&verto.options.tag){verto.ringer=$("#"+tag);}
verto.rpcClient.call('login',{});};$.verto.prototype.deviceParams=function(obj){var verto=this;for(var i in obj){verto.options.deviceParams[i]=obj[i];}
if(obj.useCamera){$.FSRTC.getValidRes(verto.options.deviceParams.useCamera,obj?obj.onResCheck:undefined);}};$.verto.prototype.videoParams=function(obj){var verto=this;for(var i in obj){verto.options.videoParams[i]=obj[i];}};$.verto.prototype.iceServers=function(obj){var verto=this;verto.options.iceServers=obj;};$.verto.prototype.loginData=function(params){var verto=this;verto.options.login=params.login;verto.options.passwd=params.passwd;verto.rpcClient.loginData(params);};$.verto.prototype.logout=function(msg){var verto=this;verto.rpcClient.closeSocket();if(verto.callbacks.onWSClose){verto.callbacks.onWSClose(verto,false);}
verto.purge();};$.verto.prototype.login=function(msg){var verto=this;verto.logout();verto.rpcClient.call('login',{});};$.verto.prototype.message=function(msg){var verto=this;var err=0;if(!msg.to){console.error("Missing To");err++;}
if(!msg.body){console.error("Missing Body");err++;}
if(err){return false;}
verto.sendMethod("verto.info",{msg:msg});return true;};$.verto.prototype.processReply=function(method,success,e){var verto=this;var i;switch(method){case"verto.subscribe":for(i in e.unauthorizedChannels){drop_bad(verto,e.unauthorizedChannels[i]);}
for(i in e.subscribedChannels){mark_ready(verto,e.subscribedChannels[i]);}
break;case"verto.unsubscribe":break;}};$.verto.prototype.sendMethod=function(method,params){var verto=this;verto.rpcClient.call(method,params,function(e){verto.processReply(method,true,e);},function(e){verto.processReply(method,false,e);});};function do_sub(verto,channel,obj){}
function drop_bad(verto,channel){console.error("drop unauthorized channel: "+channel);delete verto.eventSUBS[channel];}
function mark_ready(verto,channel){for(var j in verto.eventSUBS[channel]){verto.eventSUBS[channel][j].ready=true;console.log("subscribed to channel: "+channel);if(verto.eventSUBS[channel][j].readyHandler){verto.eventSUBS[channel][j].readyHandler(verto,channel);}}}
var SERNO=1;function do_subscribe(verto,channel,subChannels,sparams){var params=sparams||{};var local=params.local;var obj={eventChannel:channel,userData:params.userData,handler:params.handler,ready:false,readyHandler:params.readyHandler,serno:SERNO++};var isnew=false;if(!verto.eventSUBS[channel]){verto.eventSUBS[channel]=[];subChannels.push(channel);isnew=true;}
verto.eventSUBS[channel].push(obj);if(local){obj.ready=true;obj.local=true;}
if(!isnew&&verto.eventSUBS[channel][0].ready){obj.ready=true;if(obj.readyHandler){obj.readyHandler(verto,channel);}}
return{serno:obj.serno,eventChannel:channel};}
$.verto.prototype.subscribe=function(channel,sparams){var verto=this;var r=[];var subChannels=[];var params=sparams||{};if(typeof(channel)==="string"){r.push(do_subscribe(verto,channel,subChannels,params));}else{for(var i in channel){r.push(do_subscribe(verto,channel,subChannels,params));}}
if(subChannels.length){verto.sendMethod("verto.subscribe",{eventChannel:subChannels.length==1?subChannels[0]:subChannels,subParams:params.subParams});}
return r;};$.verto.prototype.unsubscribe=function(handle){var verto=this;var i;if(!handle){for(i in verto.eventSUBS){if(verto.eventSUBS[i]){verto.unsubscribe(verto.eventSUBS[i]);}}}else{var unsubChannels={};var sendChannels=[];var channel;if(typeof(handle)=="string"){delete verto.eventSUBS[handle];unsubChannels[handle]++;}else{for(i in handle){if(typeof(handle[i])=="string"){channel=handle[i];delete verto.eventSUBS[channel];unsubChannels[channel]++;}else{var repl=[];channel=handle[i].eventChannel;for(var j in verto.eventSUBS[channel]){if(verto.eventSUBS[channel][j].serno==handle[i].serno){}else{repl.push(verto.eventSUBS[channel][j]);}}
verto.eventSUBS[channel]=repl;if(verto.eventSUBS[channel].length===0){delete verto.eventSUBS[channel];unsubChannels[channel]++;}}}}
for(var u in unsubChannels){console.log("Sending Unsubscribe for: ",u);sendChannels.push(u);}
if(sendChannels.length){verto.sendMethod("verto.unsubscribe",{eventChannel:sendChannels.length==1?sendChannels[0]:sendChannels});}}};$.verto.prototype.broadcast=function(channel,params){var verto=this;var msg={eventChannel:channel,data:{}};for(var i in params){msg.data[i]=params[i];}
verto.sendMethod("verto.broadcast",msg);};$.verto.prototype.purge=function(callID){var verto=this;var x=0;var i;for(i in verto.dialogs){if(!x){console.log("purging dialogs");}
x++;verto.dialogs[i].setState($.verto.enum.state.purge);}
for(i in verto.eventSUBS){if(verto.eventSUBS[i]){console.log("purging subscription: "+i);delete verto.eventSUBS[i];}}};$.verto.prototype.hangup=function(callID){var verto=this;if(callID){var dialog=verto.dialogs[callID];if(dialog){dialog.hangup();}}else{for(var i in verto.dialogs){verto.dialogs[i].hangup();}}};$.verto.prototype.newCall=function(args,callbacks){var verto=this;if(!verto.rpcClient.socketReady()){console.error("Not Connected...");return;}
var dialog=new $.verto.dialog($.verto.enum.direction.outbound,this,args);dialog.invite();if(callbacks){dialog.callbacks=callbacks;}
return dialog;};$.verto.prototype.handleMessage=function(data){var verto=this;if(!(data&&data.method)){console.error("Invalid Data",data);return;}
if(data.params.callID){var dialog=verto.dialogs[data.params.callID];if(data.method==="verto.attach"&&dialog){delete dialog.verto.dialogs[dialog.callID];dialog.rtc.stop();dialog=null;}
if(dialog){switch(data.method){case'verto.bye':dialog.hangup(data.params);break;case'verto.answer':dialog.handleAnswer(data.params);break;case'verto.media':dialog.handleMedia(data.params);break;case'verto.display':dialog.handleDisplay(data.params);break;case'verto.info':dialog.handleInfo(data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",dialog,data.method);break;}}else{switch(data.method){case'verto.attach':data.params.attach=true;if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.useVideo=true;}
if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);dialog.setState($.verto.enum.state.recovering);break;case'verto.invite':if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.wantVideo=true;}
if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");break;}}
return{method:data.method};}else{switch(data.method){case'verto.punt':verto.purge();verto.logout();break;case'verto.event':var list=null;var key=null;if(data.params){key=data.params.eventChannel;}
if(key){list=verto.eventSUBS[key];if(!list){list=verto.eventSUBS[key.split(".")[0]];}}
if(!list&&key&&key===verto.sessid){if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.pvtEvent,data.params);}}else if(!list&&key&&verto.dialogs[key]){verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent,data.params);}else if(!list){if(!key){key="UNDEFINED";}
console.error("UNSUBBED or invalid EVENT "+key+" IGNORED");}else{for(var i in list){var sub=list[i];if(!sub||!sub.ready){console.error("invalid EVENT for "+key+" IGNORED");}else if(sub.handler){sub.handler(verto,data.params,sub.userData);}else if(verto.callbacks.onEvent){verto.callbacks.onEvent(verto,data.params,sub.userData);}else{console.log("EVENT:",data.params);}}}
break;case"verto.info":if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.info,data.params.msg);}
console.debug("MESSAGE from: "+data.params.msg.from,data.params.msg.body);break;default:console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",data.method);break;}}};var del_array=function(array,name){var r=[];var len=array.length;for(var i=0;i<len;i++){if(array[i]!=name){r.push(array[i]);}}
return r;};var hashArray=function(){var vha=this;var hash={};var array=[];vha.reorder=function(a){array=a;var h=hash;hash={};var len=array.length;for(var i=0;i<len;i++){var key=array[i];if(h[key]){hash[key]=h[key];delete h[key];}}
h=undefined;};vha.clear=function(){hash=undefined;array=undefined;hash={};array=[];};vha.add=function(name,val,insertAt){var redraw=false;if(!hash[name]){if(insertAt===undefined||insertAt<0||insertAt>=array.length){array.push(name);}else{var x=0;var n=[];var len=array.length;for(var i=0;i<len;i++){if(x++==insertAt){n.push(name);}
n.push(array[i]);}
array=undefined;array=n;n=undefined;redraw=true;}}
hash[name]=val;return redraw;};vha.del=function(name){var r=false;if(hash[name]){array=del_array(array,name);delete hash[name];r=true;}else{console.error("can't del nonexistant key "+name);}
return r;};vha.get=function(name){return hash[name];};vha.order=function(){return array;};vha.hash=function(){return hash;};vha.indexOf=function(name){var len=array.length;for(var i=0;i<len;i++){if(array[i]==name){return i;}}};vha.arrayLen=function(){return array.length;};vha.asArray=function(){var r=[];var len=array.length;for(var i=0;i<len;i++){var key=array[i];r.push(hash[key]);}
return r;};vha.each=function(cb){var len=array.length;for(var i=0;i<len;i++){cb(array[i],hash[array[i]]);}};vha.dump=function(html){var str="";vha.each(function(name,val){str+="name: "+name+" val: "+JSON.stringify(val)+(html?"<br>":"\n");});return str;};};$.verto.liveArray=function(verto,context,name,config){var la=this;var lastSerno=0;var binding=null;var user_obj=config.userObj;var local=false;hashArray.call(la);la._add=la.add;la._del=la.del;la._reorder=la.reorder;la._clear=la.clear;la.context=context;la.name=name;la.user_obj=user_obj;la.verto=verto;la.broadcast=function(channel,obj){verto.broadcast(channel,obj);};la.errs=0;la.clear=function(){la._clear();lastSerno=0;if(la.onChange){la.onChange(la,{action:"clear"});}};la.checkSerno=function(serno){if(serno<0){return true;}
if(lastSerno>0&&serno!=(lastSerno+1)){if(la.onErr){la.onErr(la,{lastSerno:lastSerno,serno:serno});}
la.errs++;console.debug(la.errs);if(la.errs<3){la.bootstrap(la.user_obj);}
return false;}else{lastSerno=serno;return true;}};la.reorder=function(serno,a){if(la.checkSerno(serno)){la._reorder(a);if(la.onChange){la.onChange(la,{serno:serno,action:"reorder"});}}};la.init=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){if(la.onChange){la.onChange(la,{serno:serno,action:"init",index:index,key:key,data:val});}}};la.bootObj=function(serno,val){if(la.checkSerno(serno)){for(var i in val){la._add(val[i][0],val[i][1]);}
if(la.onChange){la.onChange(la,{serno:serno,action:"bootObj",data:val,redraw:true});}}};la.add=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){var redraw=la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"add",index:index,key:key,data:val,redraw:redraw});}}};la.modify=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"modify",key:key,data:val,index:index});}}};la.del=function(serno,key,index){if(key===null||key===undefined){key=serno;}
if(la.checkSerno(serno)){if(index===null||index<0||index===undefined){index=la.indexOf(key);}
var ok=la._del(key);if(ok&&la.onChange){la.onChange(la,{serno:serno,action:"del",key:key,index:index});}}};var eventHandler=function(v,e,la){var packet=e.data;if(packet.name!=la.name){return;}
switch(packet.action){case"init":la.init(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"bootObj":la.bootObj(packet.wireSerno,packet.data);break;case"add":la.add(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"modify":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.modify(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);}
break;case"del":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.del(packet.wireSerno,packet.hashKey,packet.arrIndex);}
break;case"clear":la.clear();break;case"reorder":la.reorder(packet.wireSerno,packet.order);break;default:if(la.checkSerno(packet.wireSerno)){if(la.onChange){la.onChange(la,{serno:packet.wireSerno,action:packet.action,data:packet.data});}}
break;}};if(la.context){binding=la.verto.subscribe(la.context,{handler:eventHandler,userData:la,subParams:config.subParams});}
la.destroy=function(){la._clear();la.verto.unsubscribe(binding);};la.sendCommand=function(cmd,obj){var self=la;self.broadcast(self.context,{liveArray:{command:cmd,context:self.context,name:self.name,obj:obj}});};la.bootstrap=function(obj){var self=la;la.sendCommand("bootstrap",obj);};la.changepage=function(obj){var self=la;self.clear();self.broadcast(self.context,{liveArray:{command:"changepage",context:la.context,name:la.name,obj:obj}});};la.heartbeat=function(obj){var self=la;var callback=function(){self.heartbeat.call(self,obj);};self.broadcast(self.context,{liveArray:{command:"heartbeat",context:self.context,name:self.name,obj:obj}});self.hb_pid=setTimeout(callback,30000);};la.bootstrap(la.user_obj);};$.verto.liveTable=function(verto,context,name,jq,config){var dt;var la=new $.verto.liveArray(verto,context,name,{subParams:config.subParams});var lt=this;lt.liveArray=la;lt.dataTable=dt;lt.verto=verto;lt.destroy=function(){if(dt){dt.fnDestroy();}
if(la){la.destroy();}
dt=null;la=null;};la.onErr=function(obj,args){console.error("Error: ",obj,args);};function genRow(data){if(typeof(data[4])==="string"&&data[4].indexOf("{")>-1){var tmp=$.parseJSON(data[4]);data[4]=tmp.oldStatus;data[5]=null;}
return data;}
function genArray(obj){var data=obj.asArray();for(var i in data){data[i]=genRow(data[i]);}
return data;}
la.onChange=function(obj,args){var index=0;var iserr=0;if(!dt){if(!config.aoColumns){if(args.action!="init"){return;}
config.aoColumns=[];for(var i in args.data){config.aoColumns.push({"sTitle":args.data[i]});}}
dt=jq.dataTable(config);}
if(dt&&(args.action=="del"||args.action=="modify")){index=args.index;if(index===undefined&&args.key){index=la.indexOf(args.key);}
if(index===undefined){console.error("INVALID PACKET Missing INDEX\n",args);return;}}
if(config.onChange){config.onChange(obj,args);}
try{switch(args.action){case"bootObj":if(!args.data){console.error("missing data");return;}
dt.fnClearTable();dt.fnAddData(genArray(obj));dt.fnAdjustColumnSizing();break;case"add":if(!args.data){console.error("missing data");return;}
if(args.redraw>-1){dt.fnClearTable();dt.fnAddData(genArray(obj));}else{dt.fnAddData(genRow(args.data));}
dt.fnAdjustColumnSizing();break;case"modify":if(!args.data){return;}
dt.fnUpdate(genRow(args.data),index);dt.fnAdjustColumnSizing();break;case"del":dt.fnDeleteRow(index);dt.fnAdjustColumnSizing();break;case"clear":dt.fnClearTable();break;case"reorder":dt.fnClearTable();dt.fnAddData(genArray(obj));break;case"hide":jq.hide();break;case"show":jq.show();break;}}catch(err){console.error("ERROR: "+err);iserr++;}
if(iserr){obj.errs++;if(obj.errs<3){obj.bootstrap(obj.user_obj);}}else{obj.errs=0;}};la.onChange(la,{action:"init"});};var CONFMAN_SERNO=1;$.verto.conf=function(verto,params){var conf=this;conf.params=$.extend({dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);conf.verto=verto;conf.serno=CONFMAN_SERNO++;createMainModeratorMethods();verto.subscribe(conf.params.laData.modChannel,{handler:function(v,e){if(conf.params.onBroadcast){conf.params.onBroadcast(verto,conf,e.data);}}});verto.subscribe(conf.params.laData.infoChannel,{handler:function(v,e){if(typeof(conf.params.infoCallback)==="function"){conf.params.infoCallback(v,e);}}});verto.subscribe(conf.params.laData.chatChannel,{handler:function(v,e){if(typeof(conf.params.chatCallback)==="function"){conf.params.chatCallback(v,e);}}});};$.verto.conf.prototype.modCommand=function(cmd,id,value){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.conf.prototype.destroy=function(){var conf=this;conf.destroyed=true;conf.params.onBroadcast(conf.verto,conf,'destroy');if(conf.params.laData.modChannel){conf.verto.unsubscribe(conf.params.laData.modChannel);}
if(conf.params.laData.chatChannel){conf.verto.unsubscribe(conf.params.laData.chatChannel);}
if(conf.params.laData.infoChannel){conf.verto.unsubscribe(conf.params.laData.infoChannel);}};function createMainModeratorMethods(){$.verto.conf.prototype.listVideoLayouts=function(){this.modCommand("list-videoLayouts",null,null);};$.verto.conf.prototype.play=function(file){this.modCommand("play",null,file);};$.verto.conf.prototype.stop=function(){this.modCommand("stop",null,"all");};$.verto.conf.prototype.deaf=function(memberID){this.modCommand("deaf",parseInt(memberID));};$.verto.conf.prototype.undeaf=function(memberID){this.modCommand("undeaf",parseInt(memberID));};$.verto.conf.prototype.record=function(file){this.modCommand("recording",null,["start",file]);};$.verto.conf.prototype.stopRecord=function(){this.modCommand("recording",null,["stop","all"]);};$.verto.conf.prototype.snapshot=function(file){if(!this.params.hasVid){throw'Conference has no video';}
this.modCommand("vid-write-png",null,file);};$.verto.conf.prototype.setVideoLayout=function(layout,canvasID){if(!this.params.hasVid){throw'Conference has no video';}
if(canvasID){this.modCommand("vid-layout",null,[layout,canvasID]);}else{this.modCommand("vid-layout",null,layout);}};$.verto.conf.prototype.kick=function(memberID){this.modCommand("kick",parseInt(memberID));};$.verto.conf.prototype.muteMic=function(memberID){this.modCommand("tmute",parseInt(memberID));};$.verto.conf.prototype.muteVideo=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
this.modCommand("tvmute",parseInt(memberID));};$.verto.conf.prototype.presenter=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
this.modCommand("vid-res-id",parseInt(memberID),"presenter");};$.verto.conf.prototype.videoFloor=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
this.modCommand("vid-floor",parseInt(memberID),"force");};$.verto.conf.prototype.banner=function(memberID,text){if(!this.params.hasVid){throw'Conference has no video';}
this.modCommand("vid-banner",parseInt(memberID),escape(text));};$.verto.conf.prototype.volumeDown=function(memberID){this.modCommand("volume_out",parseInt(memberID),"down");};$.verto.conf.prototype.volumeUp=function(memberID){this.modCommand("volume_out",parseInt(memberID),"up");};$.verto.conf.prototype.gainDown=function(memberID){this.modCommand("volume_in",parseInt(memberID),"down");};$.verto.conf.prototype.gainUp=function(memberID){this.modCommand("volume_in",parseInt(memberID),"up");};$.verto.conf.prototype.transfer=function(memberID,exten){this.modCommand("transfer",parseInt(memberID),exten);};$.verto.conf.prototype.sendChat=function(message,type){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};}
$.verto.modfuncs={};$.verto.confMan=function(verto,params){var confMan=this;confMan.params=$.extend({tableID:null,statusID:null,mainModID:null,dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);confMan.verto=verto;confMan.serno=CONFMAN_SERNO++;confMan.canvasCount=confMan.params.laData.canvasCount;function genMainMod(jq){var play_id="play_"+confMan.serno;var stop_id="stop_"+confMan.serno;var recording_id="recording_"+confMan.serno;var snapshot_id="snapshot_"+confMan.serno;var rec_stop_id="recording_stop"+confMan.serno;var div_id="confman_"+confMan.serno;var html="<div id='"+div_id+"'><br>"+"<button class='ctlbtn' id='"+play_id+"'>Play</button>"+"<button class='ctlbtn' id='"+stop_id+"'>Stop</button>"+"<button class='ctlbtn' id='"+recording_id+"'>Record</button>"+"<button class='ctlbtn' id='"+rec_stop_id+"'>Record Stop</button>"+
(confMan.params.hasVid?"<button class='ctlbtn' id='"+snapshot_id+"'>PNG Snapshot</button>":"")+"<br><br></div>";jq.html(html);$.verto.modfuncs.change_video_layout=function(id,canvas_id){var val=$("#"+id+" option:selected").text();if(val!=="none"){confMan.modCommand("vid-layout",null,[val,canvas_id]);}};if(confMan.params.hasVid){for(var j=0;j<confMan.canvasCount;j++){var vlayout_id="confman_vid_layout_"+j+"_"+confMan.serno;var vlselect_id="confman_vl_select_"+j+"_"+confMan.serno;var vlhtml="<div id='"+vlayout_id+"'><br>"+"<b>Video Layout Canvas "+(j+1)+"</b> <select onChange='$.verto.modfuncs.change_video_layout(\""+vlayout_id+"\", \""+(j+1)+"\")' id='"+vlselect_id+"'></select> "+"<br><br></div>";jq.append(vlhtml);}
$("#"+snapshot_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("vid-write-png",null,file);}});}
$("#"+play_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("play",null,file);}});$("#"+stop_id).click(function(){confMan.modCommand("stop",null,"all");});$("#"+recording_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("recording",null,["start",file]);}});$("#"+rec_stop_id).click(function(){confMan.modCommand("recording",null,["stop","all"]);});}
function genControls(jq,rowid){var x=parseInt(rowid);var kick_id="kick_"+x;var canvas_in_next_id="canvas_in_next_"+x;var canvas_in_prev_id="canvas_in_prev_"+x;var canvas_out_next_id="canvas_out_next_"+x;var canvas_out_prev_id="canvas_out_prev_"+x;var canvas_in_set_id="canvas_in_set_"+x;var canvas_out_set_id="canvas_out_set_"+x;var layer_set_id="layer_set_"+x;var layer_next_id="layer_next_"+x;var layer_prev_id="layer_prev_"+x;var tmute_id="tmute_"+x;var tvmute_id="tvmute_"+x;var vbanner_id="vbanner_"+x;var tvpresenter_id="tvpresenter_"+x;var tvfloor_id="tvfloor_"+x;var box_id="box_"+x;var gainup_id="gain_in_up"+x;var gaindn_id="gain_in_dn"+x;var volup_id="vol_in_up"+x;var voldn_id="vol_in_dn"+x;var transfer_id="transfer"+x;var html="<div id='"+box_id+"'>";html+="<b>General Controls</b><hr noshade>";html+="<button class='ctlbtn' id='"+kick_id+"'>Kick</button>"+"<button class='ctlbtn' id='"+tmute_id+"'>Mute</button>"+"<button class='ctlbtn' id='"+gainup_id+"'>Gain -</button>"+"<button class='ctlbtn' id='"+gaindn_id+"'>Gain +</button>"+"<button class='ctlbtn' id='"+voldn_id+"'>Vol -</button>"+"<button class='ctlbtn' id='"+volup_id+"'>Vol +</button>"+"<button class='ctlbtn' id='"+transfer_id+"'>Transfer</button>";if(confMan.params.hasVid){html+="<br><br><b>Video Controls</b><hr noshade>";html+="<button class='ctlbtn' id='"+tvmute_id+"'>VMute</button>"+"<button class='ctlbtn' id='"+tvpresenter_id+"'>Presenter</button>"+"<button class='ctlbtn' id='"+tvfloor_id+"'>Vid Floor</button>"+"<button class='ctlbtn' id='"+vbanner_id+"'>Banner</button>";if(confMan.canvasCount>1){html+="<br><br><b>Canvas Controls</b><hr noshade>"+"<button class='ctlbtn' id='"+canvas_in_set_id+"'>Set Input Canvas</button>"+"<button class='ctlbtn' id='"+canvas_in_prev_id+"'>Prev Input Canvas</button>"+"<button class='ctlbtn' id='"+canvas_in_next_id+"'>Next Input Canvas</button>"+"<br>"+"<button class='ctlbtn' id='"+canvas_out_set_id+"'>Set Watching Canvas</button>"+"<button class='ctlbtn' id='"+canvas_out_prev_id+"'>Prev Watching Canvas</button>"+"<button class='ctlbtn' id='"+canvas_out_next_id+"'>Next Watching Canvas</button>";}
html+="<br>"+"<button class='ctlbtn' id='"+layer_set_id+"'>Set Layer</button>"+"<button class='ctlbtn' id='"+layer_prev_id+"'>Prev Layer</button>"+"<button class='ctlbtn' id='"+layer_next_id+"'>Next Layer</button>"+"</div>";}
jq.html(html);if(!jq.data("mouse")){$("#"+box_id).hide();}
jq.mouseover(function(e){jq.data({"mouse":true});$("#"+box_id).show();});jq.mouseout(function(e){jq.data({"mouse":false});$("#"+box_id).hide();});$("#"+transfer_id).click(function(){var xten=prompt("Enter Extension");if(xten){confMan.modCommand("transfer",x,xten);}});$("#"+kick_id).click(function(){confMan.modCommand("kick",x);});$("#"+layer_set_id).click(function(){var cid=prompt("Please enter layer ID","");if(cid){confMan.modCommand("vid-layer",x,cid);}});$("#"+layer_next_id).click(function(){confMan.modCommand("vid-layer",x,"next");});$("#"+layer_prev_id).click(function(){confMan.modCommand("vid-layer",x,"prev");});$("#"+canvas_in_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-canvas",x,cid);}});$("#"+canvas_out_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-watching-canvas",x,cid);}});$("#"+canvas_in_next_id).click(function(){confMan.modCommand("vid-canvas",x,"next");});$("#"+canvas_in_prev_id).click(function(){confMan.modCommand("vid-canvas",x,"prev");});$("#"+canvas_out_next_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"next");});$("#"+canvas_out_prev_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"prev");});$("#"+tmute_id).click(function(){confMan.modCommand("tmute",x);});if(confMan.params.hasVid){$("#"+tvmute_id).click(function(){confMan.modCommand("tvmute",x);});$("#"+tvpresenter_id).click(function(){confMan.modCommand("vid-res-id",x,"presenter");});$("#"+tvfloor_id).click(function(){confMan.modCommand("vid-floor",x,"force");});$("#"+vbanner_id).click(function(){var text=prompt("Please enter text","");if(text){confMan.modCommand("vid-banner",x,escape(text));}});}
$("#"+gainup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+gaindn_id).click(function(){confMan.modCommand("volume_in",x,"down");});$("#"+volup_id).click(function(){confMan.modCommand("volume_out",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_out",x,"down");});return html;}
var atitle="";var awidth=0;verto.subscribe(confMan.params.laData.infoChannel,{handler:function(v,e){if(typeof(confMan.params.infoCallback)==="function"){confMan.params.infoCallback(v,e);}}});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);}
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;}
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);}}};}
confMan.lt=new $.verto.liveTable(verto,confMan.params.laData.laChannel,confMan.params.laData.laName,$(confMan.params.tableID),{subParams:{callID:confMan.params.dialog?confMan.params.dialog.callID:null},"onChange":function(obj,args){$(confMan.params.statusID).text("Conference Members: "+" ("+obj.arrayLen()+" Total)");if(confMan.params.onLaChange){confMan.params.onLaChange(verto,confMan,$.verto.enum.confEvent.laChange,obj,args);}},"aaData":[],"aoColumns":[{"sTitle":"ID","sWidth":"50"},{"sTitle":"Number","sWidth":"250"},{"sTitle":"Name","sWidth":"250"},{"sTitle":"Codec","sWidth":"100"},{"sTitle":"Status","sWidth":confMan.params.hasVid?"200px":"150px"},{"sTitle":atitle,"sWidth":awidth,}],"bAutoWidth":true,"bDestroy":true,"bSort":false,"bInfo":false,"bFilter":false,"bLengthChange":false,"bPaginate":false,"iDisplayLength":1400,"oLanguage":{"sEmptyTable":"The Conference is Empty....."},"fnRowCallback":row_callback});};$.verto.confMan.prototype.modCommand=function(cmd,id,value){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.confMan.prototype.sendChat=function(message,type){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};$.verto.confMan.prototype.destroy=function(){var confMan=this;confMan.destroyed=true;if(confMan.lt){confMan.lt.destroy();}
if(confMan.params.laData.chatChannel){confMan.verto.unsubscribe(confMan.params.laData.chatChannel);}
if(confMan.params.laData.modChannel){confMan.verto.unsubscribe(confMan.params.laData.modChannel);}
if(confMan.params.mainModID){$(confMan.params.mainModID).html("");}};$.verto.dialog=function(direction,verto,params){var dialog=this;dialog.params=$.extend({useVideo:verto.options.useVideo,useStereo:verto.options.useStereo,screenShare:false,useCamera:false,useMic:verto.options.deviceParams.useMic,useSpeak:verto.options.deviceParams.useSpeak,tag:verto.options.tag,localTag:verto.options.localTag,login:verto.options.login,videoParams:verto.options.videoParams},params);if(!dialog.params.screenShare){dialog.params.useCamera=verto.options.deviceParams.useCamera;}
dialog.verto=verto;dialog.direction=direction;dialog.lastState=null;dialog.state=dialog.lastState=$.verto.enum.state.new;dialog.callbacks=verto.callbacks;dialog.answered=false;dialog.attach=params.attach||false;dialog.screenShare=params.screenShare||false;dialog.useCamera=dialog.params.useCamera;dialog.useMic=dialog.params.useMic;dialog.useSpeak=dialog.params.useSpeak;if(dialog.params.callID){dialog.callID=dialog.params.callID;}else{dialog.callID=dialog.params.callID=generateGUID();}
if(typeof(dialog.params.tag)==="function"){dialog.params.tag=dialog.params.tag();}
if(dialog.params.tag){dialog.audioStream=document.getElementById(dialog.params.tag);if(dialog.params.useVideo){dialog.videoStream=dialog.audioStream;}}
if(dialog.params.localTag){dialog.localVideo=document.getElementById(dialog.params.localTag);}
dialog.verto.dialogs[dialog.callID]=dialog;var RTCcallbacks={};if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.params.display_direction==="outbound"){dialog.params.remote_caller_id_name=dialog.params.caller_id_name;dialog.params.remote_caller_id_number=dialog.params.caller_id_number;}else{dialog.params.remote_caller_id_name=dialog.params.callee_id_name;dialog.params.remote_caller_id_number=dialog.params.callee_id_number;}
if(!dialog.params.remote_caller_id_name){dialog.params.remote_caller_id_name="Nobody";}
if(!dialog.params.remote_caller_id_number){dialog.params.remote_caller_id_number="UNKNOWN";}
RTCcallbacks.onMessage=function(rtc,msg){console.debug(msg);};RTCcallbacks.onAnswerSDP=function(rtc,sdp){console.error("answer sdp",sdp);};}else{dialog.params.remote_caller_id_name="Outbound Call";dialog.params.remote_caller_id_number=dialog.params.destination_number;}
RTCcallbacks.onICESDP=function(rtc){console.log("RECV "+rtc.type+" SDP",rtc.mediaData.SDP);if(dialog.state==$.verto.enum.state.requesting||dialog.state==$.verto.enum.state.answering||dialog.state==$.verto.enum.state.active){location.reload();return;}
if(rtc.type=="offer"){if(dialog.state==$.verto.enum.state.active){dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.attach",{sdp:rtc.mediaData.SDP});}else{dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.invite",{sdp:rtc.mediaData.SDP});}}else{dialog.setState($.verto.enum.state.answering);dialog.sendMethod(dialog.attach?"verto.attach":"verto.answer",{sdp:dialog.rtc.mediaData.SDP});}};RTCcallbacks.onICE=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.candidate);return;}};RTCcallbacks.onStream=function(rtc,stream){if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onGranted==='function'){dialog.verto.options.permissionCallback.onGranted(stream);}
console.log("stream started");};RTCcallbacks.onError=function(e){if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onDenied==='function'){dialog.verto.options.permissionCallback.onDenied();}
console.error("ERROR:",e);dialog.hangup({cause:"Device or Permission Error"});};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,localVideo:dialog.screenShare?null:dialog.localVideo,useVideo:dialog.params.useVideo?dialog.videoStream:null,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:dialog.params.videoParams,audioParams:verto.options.audioParams,iceServers:verto.options.iceServers,screenShare:dialog.screenShare,useCamera:dialog.useCamera,useMic:dialog.useMic,useSpeak:dialog.useSpeak});dialog.rtc.verto=dialog.verto;if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.attach){dialog.answer();}else{dialog.ring();}}};$.verto.dialog.prototype.invite=function(){var dialog=this;dialog.rtc.call();};$.verto.dialog.prototype.sendMethod=function(method,obj){var dialog=this;obj.dialogParams={};for(var i in dialog.params){if(i=="sdp"&&method!="verto.invite"&&method!="verto.attach"){continue;}
if((obj.noDialogParams&&i!="callID")){continue;}
obj.dialogParams[i]=dialog.params[i];}
delete obj.noDialogParams;dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,true,e);},function(e){dialog.processReply(method,false,e);});};function checkStateChange(oldS,newS){if(newS==$.verto.enum.state.purge||$.verto.enum.states[oldS.name][newS.name]){return true;}
return false;}
function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}}
return id;}
$.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,null,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();}
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;}
if(!dialog.cause){dialog.cause="NORMAL CLEARING";}
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"&&speaker!=="none"){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",{});}
dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:if(typeof(dialog.verto.options.tag)==="function"){$('#'+dialog.params.tag).remove();}
delete dialog.verto.dialogs[dialog.callID];if(dialog.params.screenShare){dialog.rtc.stopPeer();}else{dialog.rtc.stop();}
break;}
return true;};$.verto.dialog.prototype.processReply=function(method,success,e){var dialog=this;switch(method){case"verto.answer":case"verto.attach":if(success){dialog.setState($.verto.enum.state.active);}else{dialog.hangup();}
break;case"verto.invite":if(success){dialog.setState($.verto.enum.state.trying);}else{dialog.setState($.verto.enum.state.destroy);}
break;case"verto.bye":dialog.hangup();break;case"verto.modify":if(e.holdState){if(e.holdState=="held"){if(dialog.state!=$.verto.enum.state.held){dialog.setState($.verto.enum.state.held);}}else if(e.holdState=="active"){if(dialog.state!=$.verto.enum.state.active){dialog.setState($.verto.enum.state.active);}}}
if(success){}
break;default:break;}};$.verto.dialog.prototype.hangup=function(params){var dialog=this;if(params){if(params.causeCode){dialog.causeCode=params.causeCode;}
if(params.cause){dialog.cause=params.cause;}}
if(dialog.state.val>=$.verto.enum.state.new.val&&dialog.state.val<$.verto.enum.state.hangup.val){dialog.setState($.verto.enum.state.hangup);}else if(dialog.state.val<$.verto.enum.state.destroy){dialog.setState($.verto.enum.state.destroy);}};$.verto.dialog.prototype.stopRinging=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.stop();}};$.verto.dialog.prototype.indicateRing=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.attr("src",dialog.verto.options.ringFile)[0].play();setTimeout(function(){dialog.stopRinging();if(dialog.state==$.verto.enum.state.ringing){dialog.indicateRing();}},dialog.verto.options.ringSleep);}};$.verto.dialog.prototype.ring=function(){var dialog=this;dialog.setState($.verto.enum.state.ringing);dialog.indicateRing();};$.verto.dialog.prototype.useVideo=function(on){var dialog=this;dialog.params.useVideo=on;if(on){dialog.videoStream=dialog.audioStream;}else{dialog.videoStream=null;}
dialog.rtc.useVideo(dialog.videoStream,dialog.localVideo);};$.verto.dialog.prototype.setMute=function(what){var dialog=this;return dialog.rtc.setMute(what);};$.verto.dialog.prototype.getMute=function(){var dialog=this;return dialog.rtc.getMute();};$.verto.dialog.prototype.setVideoMute=function(what){var dialog=this;return dialog.rtc.setVideoMute(what);};$.verto.dialog.prototype.getVideoMute=function(){var dialog=this;return dialog.rtc.getVideoMute();};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.rtt=function(obj){var dialog=this;var pobj={};if(!obj){return false;}
pobj.code=obj.code;pobj.chars=obj.chars;if(pobj.chars||pobj.code){dialog.sendMethod("verto.info",{txt:obj,noDialogParams:true});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){dialog.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;msg.from=dialog.params.login;if(!msg.to){console.error("Missing To");err++;}
if(!msg.body){console.error("Missing Body");err++;}
if(err){return false;}
dialog.sendMethod("verto.info",{msg:msg});return true;};$.verto.dialog.prototype.answer=function(params){var dialog=this;if(!dialog.answered){if(!params){params={};}
params.sdp=dialog.params.sdp;if(params){if(params.useVideo){dialog.useVideo(true);}
dialog.params.callee_id_name=params.callee_id_name;dialog.params.callee_id_number=params.callee_id_number;if(params.useCamera){dialog.useCamera=params.useCamera;}
if(params.useMic){dialog.useMic=params.useMic;}
if(params.useSpeak){dialog.useSpeak=params.useSpeak;}}
dialog.rtc.createAnswer(params);dialog.answered=true;}};$.verto.dialog.prototype.handleAnswer=function(params){var dialog=this;dialog.gotAnswer=true;if(dialog.state.val>=$.verto.enum.state.active.val){return;}
if(dialog.state.val>=$.verto.enum.state.early.val){dialog.setState($.verto.enum.state.active);}else{if(dialog.gotEarly){console.log("Dialog "+dialog.callID+" Got answer while still establishing early media, delaying...");}else{console.log("Dialog "+dialog.callID+" Answering Channel");dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.active);},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"ANSWER SDP",params.sdp);}}};$.verto.dialog.prototype.cidString=function(enc){var dialog=this;var party=dialog.params.remote_caller_id_name+(enc?" &lt;":" <")+dialog.params.remote_caller_id_number+(enc?"&gt;":">");return party;};$.verto.dialog.prototype.sendMessage=function(msg,params){var dialog=this;if(dialog.callbacks.onMessage){dialog.callbacks.onMessage(dialog.verto,dialog,msg,params);}};$.verto.dialog.prototype.handleInfo=function(params){var dialog=this;dialog.sendMessage($.verto.enum.message.info,params);};$.verto.dialog.prototype.handleDisplay=function(params){var dialog=this;if(params.display_name){dialog.params.remote_caller_id_name=params.display_name;}
if(params.display_number){dialog.params.remote_caller_id_number=params.display_number;}
dialog.sendMessage($.verto.enum.message.display,{});};$.verto.dialog.prototype.handleMedia=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.early.val){return;}
dialog.gotEarly=true;dialog.rtc.answer(params.sdp,function(){console.log("Dialog "+dialog.callID+"Establishing early media");dialog.setState($.verto.enum.state.early);if(dialog.gotAnswer){console.log("Dialog "+dialog.callID+"Answering Channel");dialog.setState($.verto.enum.state.active);}},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"EARLY SDP",params.sdp);};$.verto.ENUM=function(s){var i=0,o={};s.split(" ").map(function(x){o[x]={name:x,val:i++};});return Object.freeze(o);};$.verto.enum={};$.verto.enum.states=Object.freeze({new:{requesting:1,recovering:1,ringing:1,destroy:1,answering:1,hangup:1},requesting:{trying:1,hangup:1,active:1},recovering:{answering:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{answering:1,requesting:1,hangup:1,held:1},held:{hangup:1,active:1},early:{hangup:1,active:1},hangup:{destroy:1},destroy:{},purge:{destroy:1}});$.verto.enum.state=$.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");$.verto.enum.direction=$.verto.ENUM("inbound outbound");$.verto.enum.message=$.verto.ENUM("display info pvtEvent");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$.verto.unloadJobs=[];$(window).bind('beforeunload',function(){for(var f in $.verto.unloadJobs){$.verto.unloadJobs[f]();}
if($.verto.haltClosure)
return $.verto.haltClosure();for(var i in $.verto.saved){var verto=$.verto.saved[i];if(verto){verto.purge();verto.logout();}}
return $.verto.warnOnUnload;});$.verto.videoDevices=[];$.verto.audioInDevices=[];$.verto.audioOutDevices=[];var checkDevices=function(runtime){console.info("enumerating devices");var aud_in=[],aud_out=[],vid=[];var has_video=0,has_audio=0;var Xstream;function gotDevices(deviceInfos){for(var i=0;i!==deviceInfos.length;++i){var deviceInfo=deviceInfos[i];var text="";console.log(deviceInfo);console.log(deviceInfo.kind+": "+deviceInfo.label+" id = "+deviceInfo.deviceId);if(deviceInfo.kind==='audioinput'){text=deviceInfo.label||'microphone '+(aud_in.length+1);aud_in.push({id:deviceInfo.deviceId,kind:"audio_in",label:text});}else if(deviceInfo.kind==='audiooutput'){text=deviceInfo.label||'speaker '+(aud_out.length+1);aud_out.push({id:deviceInfo.deviceId,kind:"audio_out",label:text});}else if(deviceInfo.kind==='videoinput'){text=deviceInfo.label||'camera '+(vid.length+1);vid.push({id:deviceInfo.deviceId,kind:"video",label:text});}else{console.log('Some other kind of source/device: ',deviceInfo);}}
$.verto.videoDevices=vid;$.verto.audioInDevices=aud_in;$.verto.audioOutDevices=aud_out;console.info("Audio IN Devices",$.verto.audioInDevices);console.info("Audio Out Devices",$.verto.audioOutDevices);console.info("Video Devices",$.verto.videoDevices);if(Xstream){Xstream.getTracks().forEach(function(track){track.stop();});}
if(runtime){runtime(true);}}
function handleError(error){console.log('device enumeration error: ',error);if(runtime)runtime(false);}
function checkTypes(devs){for(var i=0;i!==devs.length;++i){if(devs[i].kind==='audioinput'){has_audio++;}else if(devs[i].kind==='videoinput'){has_video++;}}
navigator.getUserMedia({audio:(has_audio>0?true:false),video:(has_video>0?true:false)},function(stream){Xstream=stream;navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);},function(err){console.log("The following error occurred: "+err.name);});}
navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);};$.verto.refreshDevices=function(runtime){checkDevices(runtime);}
$.verto.init=function(obj,runtime){if(!obj){obj={};}
if(!obj.skipPermCheck&&!obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){checkDevices(runtime);},true,true);}else if(obj.skipPermCheck&&!obj.skipDeviceCheck){checkDevices(runtime);}else if(!obj.skipPermCheck&&obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){runtime(status);},true,true);}else{runtime(null);}}
$.verto.genUUID=function(){return generateGUID();}})(jQuery);(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.adapter=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){'use strict';var SDPUtils={};SDPUtils.generateIdentifier=function(){return Math.random().toString(36).substr(2,10);};SDPUtils.localCName=SDPUtils.generateIdentifier();SDPUtils.splitLines=function(blob){return blob.trim().split('\n').map(function(line){return line.trim();});};SDPUtils.splitSections=function(blob){var parts=blob.split('\nm=');return parts.map(function(part,index){return(index>0?'m='+part:part).trim()+'\r\n';});};SDPUtils.matchPrefix=function(blob,prefix){return SDPUtils.splitLines(blob).filter(function(line){return line.indexOf(prefix)===0;});};SDPUtils.parseCandidate=function(line){var parts;if(line.indexOf('a=candidate:')===0){parts=line.substring(12).split(' ');}else{parts=line.substring(10).split(' ');}
var candidate={foundation:parts[0],component:parseInt(parts[1],10),protocol:parts[2].toLowerCase(),priority:parseInt(parts[3],10),ip:parts[4],port:parseInt(parts[5],10),type:parts[7]};for(var i=8;i<parts.length;i+=2){switch(parts[i]){case'raddr':candidate.relatedAddress=parts[i+1];break;case'rport':candidate.relatedPort=parseInt(parts[i+1],10);break;case'tcptype':candidate.tcpType=parts[i+1];break;default:candidate[parts[i]]=parts[i+1];break;}}
return candidate;};SDPUtils.writeCandidate=function(candidate){var sdp=[];sdp.push(candidate.foundation);sdp.push(candidate.component);sdp.push(candidate.protocol.toUpperCase());sdp.push(candidate.priority);sdp.push(candidate.ip);sdp.push(candidate.port);var type=candidate.type;sdp.push('typ');sdp.push(type);if(type!=='host'&&candidate.relatedAddress&&candidate.relatedPort){sdp.push('raddr');sdp.push(candidate.relatedAddress);sdp.push('rport');sdp.push(candidate.relatedPort);}
if(candidate.tcpType&&candidate.protocol.toLowerCase()==='tcp'){sdp.push('tcptype');sdp.push(candidate.tcpType);}
if(candidate.ufrag){sdp.push('ufrag');sdp.push(candidate.ufrag);}
return'candidate:'+sdp.join(' ');};SDPUtils.parseIceOptions=function(line){return line.substr(14).split(' ');}
SDPUtils.parseRtpMap=function(line){var parts=line.substr(9).split(' ');var parsed={payloadType:parseInt(parts.shift(),10)};parts=parts[0].split('/');parsed.name=parts[0];parsed.clockRate=parseInt(parts[1],10);parsed.numChannels=parts.length===3?parseInt(parts[2],10):1;return parsed;};SDPUtils.writeRtpMap=function(codec){var pt=codec.payloadType;if(codec.preferredPayloadType!==undefined){pt=codec.preferredPayloadType;}
return'a=rtpmap:'+pt+' '+codec.name+'/'+codec.clockRate+
(codec.numChannels!==1?'/'+codec.numChannels:'')+'\r\n';};SDPUtils.parseExtmap=function(line){var parts=line.substr(9).split(' ');return{id:parseInt(parts[0],10),direction:parts[0].indexOf('/')>0?parts[0].split('/')[1]:'sendrecv',uri:parts[1]};};SDPUtils.writeExtmap=function(headerExtension){return'a=extmap:'+(headerExtension.id||headerExtension.preferredId)+
(headerExtension.direction&&headerExtension.direction!=='sendrecv'?'/'+headerExtension.direction:'')+' '+headerExtension.uri+'\r\n';};SDPUtils.parseFmtp=function(line){var parsed={};var kv;var parts=line.substr(line.indexOf(' ')+1).split(';');for(var j=0;j<parts.length;j++){kv=parts[j].trim().split('=');parsed[kv[0].trim()]=kv[1];}
return parsed;};SDPUtils.writeFmtp=function(codec){var line='';var pt=codec.payloadType;if(codec.preferredPayloadType!==undefined){pt=codec.preferredPayloadType;}
if(codec.parameters&&Object.keys(codec.parameters).length){var params=[];Object.keys(codec.parameters).forEach(function(param){params.push(param+'='+codec.parameters[param]);});line+='a=fmtp:'+pt+' '+params.join(';')+'\r\n';}
return line;};SDPUtils.parseRtcpFb=function(line){var parts=line.substr(line.indexOf(' ')+1).split(' ');return{type:parts.shift(),parameter:parts.join(' ')};};SDPUtils.writeRtcpFb=function(codec){var lines='';var pt=codec.payloadType;if(codec.preferredPayloadType!==undefined){pt=codec.preferredPayloadType;}
if(codec.rtcpFeedback&&codec.rtcpFeedback.length){codec.rtcpFeedback.forEach(function(fb){lines+='a=rtcp-fb:'+pt+' '+fb.type+
(fb.parameter&&fb.parameter.length?' '+fb.parameter:'')+'\r\n';});}
return lines;};SDPUtils.parseSsrcMedia=function(line){var sp=line.indexOf(' ');var parts={ssrc:parseInt(line.substr(7,sp-7),10)};var colon=line.indexOf(':',sp);if(colon>-1){parts.attribute=line.substr(sp+1,colon-sp-1);parts.value=line.substr(colon+1);}else{parts.attribute=line.substr(sp+1);}
return parts;};SDPUtils.getMid=function(mediaSection){var mid=SDPUtils.matchPrefix(mediaSection,'a=mid:')[0];if(mid){return mid.substr(6);}}
SDPUtils.parseFingerprint=function(line){var parts=line.substr(14).split(' ');return{algorithm:parts[0].toLowerCase(),value:parts[1]};};SDPUtils.getDtlsParameters=function(mediaSection,sessionpart){var lines=SDPUtils.matchPrefix(mediaSection+sessionpart,'a=fingerprint:');return{role:'auto',fingerprints:lines.map(SDPUtils.parseFingerprint)};};SDPUtils.writeDtlsParameters=function(params,setupType){var sdp='a=setup:'+setupType+'\r\n';params.fingerprints.forEach(function(fp){sdp+='a=fingerprint:'+fp.algorithm+' '+fp.value+'\r\n';});return sdp;};SDPUtils.getIceParameters=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);lines=lines.concat(SDPUtils.splitLines(sessionpart));var iceParameters={usernameFragment:lines.filter(function(line){return line.indexOf('a=ice-ufrag:')===0;})[0].substr(12),password:lines.filter(function(line){return line.indexOf('a=ice-pwd:')===0;})[0].substr(10)};return iceParameters;};SDPUtils.writeIceParameters=function(params){return'a=ice-ufrag:'+params.usernameFragment+'\r\n'+'a=ice-pwd:'+params.password+'\r\n';};SDPUtils.parseRtpParameters=function(mediaSection){var description={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]};var lines=SDPUtils.splitLines(mediaSection);var mline=lines[0].split(' ');for(var i=3;i<mline.length;i++){var pt=mline[i];var rtpmapline=SDPUtils.matchPrefix(mediaSection,'a=rtpmap:'+pt+' ')[0];if(rtpmapline){var codec=SDPUtils.parseRtpMap(rtpmapline);var fmtps=SDPUtils.matchPrefix(mediaSection,'a=fmtp:'+pt+' ');codec.parameters=fmtps.length?SDPUtils.parseFmtp(fmtps[0]):{};codec.rtcpFeedback=SDPUtils.matchPrefix(mediaSection,'a=rtcp-fb:'+pt+' ').map(SDPUtils.parseRtcpFb);description.codecs.push(codec);switch(codec.name.toUpperCase()){case'RED':case'ULPFEC':description.fecMechanisms.push(codec.name.toUpperCase());break;default:break;}}}
SDPUtils.matchPrefix(mediaSection,'a=extmap:').forEach(function(line){description.headerExtensions.push(SDPUtils.parseExtmap(line));});return description;};SDPUtils.writeRtpDescription=function(kind,caps){var sdp='';sdp+='m='+kind+' ';sdp+=caps.codecs.length>0?'9':'0';sdp+=' UDP/TLS/RTP/SAVPF ';sdp+=caps.codecs.map(function(codec){if(codec.preferredPayloadType!==undefined){return codec.preferredPayloadType;}
return codec.payloadType;}).join(' ')+'\r\n';sdp+='c=IN IP4 0.0.0.0\r\n';sdp+='a=rtcp:9 IN IP4 0.0.0.0\r\n';caps.codecs.forEach(function(codec){sdp+=SDPUtils.writeRtpMap(codec);sdp+=SDPUtils.writeFmtp(codec);sdp+=SDPUtils.writeRtcpFb(codec);});var maxptime=0;caps.codecs.forEach(function(codec){if(codec.maxptime>maxptime){maxptime=codec.maxptime;}});if(maxptime>0){sdp+='a=maxptime:'+maxptime+'\r\n';}
sdp+='a=rtcp-mux\r\n';caps.headerExtensions.forEach(function(extension){sdp+=SDPUtils.writeExtmap(extension);});return sdp;};SDPUtils.parseRtpEncodingParameters=function(mediaSection){var encodingParameters=[];var description=SDPUtils.parseRtpParameters(mediaSection);var hasRed=description.fecMechanisms.indexOf('RED')!==-1;var hasUlpfec=description.fecMechanisms.indexOf('ULPFEC')!==-1;var ssrcs=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(parts){return parts.attribute==='cname';});var primarySsrc=ssrcs.length>0&&ssrcs[0].ssrc;var secondarySsrc;var flows=SDPUtils.matchPrefix(mediaSection,'a=ssrc-group:FID').map(function(line){var parts=line.split(' ');parts.shift();return parts.map(function(part){return parseInt(part,10);});});if(flows.length>0&&flows[0].length>1&&flows[0][0]===primarySsrc){secondarySsrc=flows[0][1];}
description.codecs.forEach(function(codec){if(codec.name.toUpperCase()==='RTX'&&codec.parameters.apt){var encParam={ssrc:primarySsrc,codecPayloadType:parseInt(codec.parameters.apt,10),rtx:{ssrc:secondarySsrc}};encodingParameters.push(encParam);if(hasRed){encParam=JSON.parse(JSON.stringify(encParam));encParam.fec={ssrc:secondarySsrc,mechanism:hasUlpfec?'red+ulpfec':'red'};encodingParameters.push(encParam);}}});if(encodingParameters.length===0&&primarySsrc){encodingParameters.push({ssrc:primarySsrc});}
var bandwidth=SDPUtils.matchPrefix(mediaSection,'b=');if(bandwidth.length){if(bandwidth[0].indexOf('b=TIAS:')===0){bandwidth=parseInt(bandwidth[0].substr(7),10);}else if(bandwidth[0].indexOf('b=AS:')===0){bandwidth=parseInt(bandwidth[0].substr(5),10)*1000*0.95
-(50*40*8);}else{bandwidth=undefined;}
encodingParameters.forEach(function(params){params.maxBitrate=bandwidth;});}
return encodingParameters;};SDPUtils.parseRtcpParameters=function(mediaSection){var rtcpParameters={};var cname;var remoteSsrc=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(obj){return obj.attribute==='cname';})[0];if(remoteSsrc){rtcpParameters.cname=remoteSsrc.value;rtcpParameters.ssrc=remoteSsrc.ssrc;}
var rsize=SDPUtils.matchPrefix(mediaSection,'a=rtcp-rsize');rtcpParameters.reducedSize=rsize.length>0;rtcpParameters.compound=rsize.length===0;var mux=SDPUtils.matchPrefix(mediaSection,'a=rtcp-mux');rtcpParameters.mux=mux.length>0;return rtcpParameters;};SDPUtils.parseMsid=function(mediaSection){var parts;var spec=SDPUtils.matchPrefix(mediaSection,'a=msid:');if(spec.length===1){parts=spec[0].substr(7).split(' ');return{stream:parts[0],track:parts[1]};}
var planB=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(parts){return parts.attribute==='msid';});if(planB.length>0){parts=planB[0].value.split(' ');return{stream:parts[0],track:parts[1]};}};SDPUtils.generateSessionId=function(){return Math.random().toString().substr(2,21);};SDPUtils.writeSessionBoilerplate=function(sessId){var sessionId;if(sessId){sessionId=sessId;}else{sessionId=SDPUtils.generateSessionId();}
return'v=0\r\n'+'o=thisisadapterortc '+sessionId+' 2 IN IP4 127.0.0.1\r\n'+'s=-\r\n'+'t=0 0\r\n';};SDPUtils.writeMediaSection=function(transceiver,caps,type,stream){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.direction){sdp+='a='+transceiver.direction+'\r\n';}else if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
if(transceiver.rtpSender){var msid='msid:'+stream.id+' '+
transceiver.rtpSender.track.id+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
transceiver.sendEncodingParameters[0].ssrc+' '+
transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
return sdp;};SDPUtils.getDirection=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);for(var i=0;i<lines.length;i++){switch(lines[i]){case'a=sendrecv':case'a=sendonly':case'a=recvonly':case'a=inactive':return lines[i].substr(2);default:}}
if(sessionpart){return SDPUtils.getDirection(sessionpart);}
return'sendrecv';};SDPUtils.getKind=function(mediaSection){var lines=SDPUtils.splitLines(mediaSection);var mline=lines[0].split(' ');return mline[0].substr(2);};SDPUtils.isRejected=function(mediaSection){return mediaSection.split(' ',2)[1]==='0';};module.exports=SDPUtils;},{}],2:[function(require,module,exports){(function(global){'use strict';var adapterFactory=require('./adapter_factory.js');module.exports=adapterFactory({window:global.window});}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./adapter_factory.js":3}],3:[function(require,module,exports){'use strict';module.exports=function(dependencies){var window=dependencies&&dependencies.window;var utils=require('./utils');var logging=utils.log;var browserDetails=utils.detectBrowser(window);var adapter={browserDetails:browserDetails,extractVersion:utils.extractVersion,disableLog:utils.disableLog,disableWarnings:utils.disableWarnings};var chromeShim=require('./chrome/chrome_shim')||null;var edgeShim=require('./edge/edge_shim')||null;var firefoxShim=require('./firefox/firefox_shim')||null;var safariShim=require('./safari/safari_shim')||null;switch(browserDetails.browser){case'chrome':if(!chromeShim||!chromeShim.shimPeerConnection){logging('Chrome shim is not included in this adapter release.');return adapter;}
logging('adapter.js shimming chrome.');adapter.browserShim=chromeShim;chromeShim.shimGetUserMedia(window);chromeShim.shimMediaStream(window);utils.shimCreateObjectURL(window);chromeShim.shimSourceObject(window);chromeShim.shimPeerConnection(window);chromeShim.shimOnTrack(window);chromeShim.shimGetSendersWithDtmf(window);break;case'firefox':if(!firefoxShim||!firefoxShim.shimPeerConnection){logging('Firefox shim is not included in this adapter release.');return adapter;}
logging('adapter.js shimming firefox.');adapter.browserShim=firefoxShim;firefoxShim.shimGetUserMedia(window);utils.shimCreateObjectURL(window);firefoxShim.shimSourceObject(window);firefoxShim.shimPeerConnection(window);firefoxShim.shimOnTrack(window);break;case'edge':if(!edgeShim||!edgeShim.shimPeerConnection){logging('MS edge shim is not included in this adapter release.');return adapter;}
logging('adapter.js shimming edge.');adapter.browserShim=edgeShim;edgeShim.shimGetUserMedia(window);utils.shimCreateObjectURL(window);edgeShim.shimPeerConnection(window);edgeShim.shimReplaceTrack(window);break;case'safari':if(!safariShim){logging('Safari shim is not included in this adapter release.');return adapter;}
logging('adapter.js shimming safari.');adapter.browserShim=safariShim;utils.shimCreateObjectURL(window);safariShim.shimRTCIceServerUrls(window);safariShim.shimCallbacksAPI(window);safariShim.shimLocalStreamsAPI(window);safariShim.shimRemoteStreamsAPI(window);safariShim.shimGetUserMedia(window);break;default:logging('Unsupported browser!');break;}
return adapter;};},{"./chrome/chrome_shim":4,"./edge/edge_shim":6,"./firefox/firefox_shim":9,"./safari/safari_shim":11,"./utils":12}],4:[function(require,module,exports){'use strict';var utils=require('../utils.js');var logging=utils.log;var chromeShim={shimMediaStream:function(window){window.MediaStream=window.MediaStream||window.webkitMediaStream;},shimOnTrack:function(window){if(typeof window==='object'&&window.RTCPeerConnection&&!('ontrack'in
window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'ontrack',{get:function(){return this._ontrack;},set:function(f){var self=this;if(this._ontrack){this.removeEventListener('track',this._ontrack);this.removeEventListener('addstream',this._ontrackpoly);}
this.addEventListener('track',this._ontrack=f);this.addEventListener('addstream',this._ontrackpoly=function(e){e.stream.addEventListener('addtrack',function(te){var receiver;if(window.RTCPeerConnection.prototype.getReceivers){receiver=self.getReceivers().find(function(r){return r.track.id===te.track.id;});}else{receiver={track:te.track};}
var event=new Event('track');event.track=te.track;event.receiver=receiver;event.streams=[e.stream];self.dispatchEvent(event);});e.stream.getTracks().forEach(function(track){var receiver;if(window.RTCPeerConnection.prototype.getReceivers){receiver=self.getReceivers().find(function(r){return r.track.id===track.id;});}else{receiver={track:track};}
var event=new Event('track');event.track=track;event.receiver=receiver;event.streams=[e.stream];this.dispatchEvent(event);}.bind(this));}.bind(this));}});}},shimGetSendersWithDtmf:function(window){if(typeof window==='object'&&window.RTCPeerConnection&&!('getSenders'in window.RTCPeerConnection.prototype)&&'createDTMFSender'in window.RTCPeerConnection.prototype){window.RTCPeerConnection.prototype.getSenders=function(){return this._senders||[];};var origAddStream=window.RTCPeerConnection.prototype.addStream;var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;if(!window.RTCPeerConnection.prototype.addTrack){window.RTCPeerConnection.prototype.addTrack=function(track,stream){var pc=this;if(pc.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
var streams=[].slice.call(arguments,1);if(streams.length!==1||!streams[0].getTracks().find(function(t){return t===track;})){throw new DOMException('The adapter.js addTrack polyfill only supports a single '+' stream which is associated with the specified track.','NotSupportedError');}
pc._senders=pc._senders||[];var alreadyExists=pc._senders.find(function(t){return t.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}
pc._streams=pc._streams||{};var oldStream=pc._streams[stream.id];if(oldStream){oldStream.addTrack(track);pc.removeStream(oldStream);pc.addStream(oldStream);}else{var newStream=new window.MediaStream([track]);pc._streams[stream.id]=newStream;pc.addStream(newStream);}
var sender={track:track,get dtmf(){if(this._dtmf===undefined){if(track.kind==='audio'){this._dtmf=pc.createDTMFSender(track);}else{this._dtmf=null;}}
return this._dtmf;}};pc._senders.push(sender);return sender;};}
window.RTCPeerConnection.prototype.addStream=function(stream){var pc=this;pc._senders=pc._senders||[];origAddStream.apply(pc,[stream]);stream.getTracks().forEach(function(track){pc._senders.push({track:track,get dtmf(){if(this._dtmf===undefined){if(track.kind==='audio'){this._dtmf=pc.createDTMFSender(track);}else{this._dtmf=null;}}
return this._dtmf;}});});};window.RTCPeerConnection.prototype.removeStream=function(stream){var pc=this;pc._senders=pc._senders||[];origRemoveStream.apply(pc,[stream]);stream.getTracks().forEach(function(track){var sender=pc._senders.find(function(s){return s.track===track;});if(sender){pc._senders.splice(pc._senders.indexOf(sender),1);}});};}else if(typeof window==='object'&&window.RTCPeerConnection&&'getSenders'in window.RTCPeerConnection.prototype&&'createDTMFSender'in window.RTCPeerConnection.prototype&&window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;window.RTCPeerConnection.prototype.getSenders=function(){var pc=this;var senders=origGetSenders.apply(pc,[]);senders.forEach(function(sender){sender._pc=pc;});return senders;};Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=this._pc.createDTMFSender(this.track);}else{this._dtmf=null;}}
return this._dtmf;},});}},shimSourceObject:function(window){var URL=window&&window.URL;if(typeof window==='object'){if(window.HTMLMediaElement&&!('srcObject'in window.HTMLMediaElement.prototype)){Object.defineProperty(window.HTMLMediaElement.prototype,'srcObject',{get:function(){return this._srcObject;},set:function(stream){var self=this;this._srcObject=stream;if(this.src){URL.revokeObjectURL(this.src);}
if(!stream){this.src='';return undefined;}
this.src=URL.createObjectURL(stream);stream.addEventListener('addtrack',function(){if(self.src){URL.revokeObjectURL(self.src);}
self.src=URL.createObjectURL(stream);});stream.addEventListener('removetrack',function(){if(self.src){URL.revokeObjectURL(self.src);}
self.src=URL.createObjectURL(stream);});}});}}},shimPeerConnection:function(window){var browserDetails=utils.detectBrowser(window);if(!window.RTCPeerConnection){window.RTCPeerConnection=function(pcConfig,pcConstraints){logging('PeerConnection');if(pcConfig&&pcConfig.iceTransportPolicy){pcConfig.iceTransports=pcConfig.iceTransportPolicy;}
return new window.webkitRTCPeerConnection(pcConfig,pcConstraints);};window.RTCPeerConnection.prototype=window.webkitRTCPeerConnection.prototype;if(window.webkitRTCPeerConnection.generateCertificate){Object.defineProperty(window.RTCPeerConnection,'generateCertificate',{get:function(){return window.webkitRTCPeerConnection.generateCertificate;}});}}else{var OrigPeerConnection=window.RTCPeerConnection;window.RTCPeerConnection=function(pcConfig,pcConstraints){if(pcConfig&&pcConfig.iceServers){var newIceServers=[];for(var i=0;i<pcConfig.iceServers.length;i++){var server=pcConfig.iceServers[i];if(!server.hasOwnProperty('urls')&&server.hasOwnProperty('url')){console.warn('RTCIceServer.url is deprecated! Use urls instead.');server=JSON.parse(JSON.stringify(server));server.urls=server.url;newIceServers.push(server);}else{newIceServers.push(pcConfig.iceServers[i]);}}
pcConfig.iceServers=newIceServers;}
return new OrigPeerConnection(pcConfig,pcConstraints);};window.RTCPeerConnection.prototype=OrigPeerConnection.prototype;Object.defineProperty(window.RTCPeerConnection,'generateCertificate',{get:function(){return OrigPeerConnection.generateCertificate;}});}
var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,successCallback,errorCallback){var self=this;var args=arguments;if(arguments.length>0&&typeof selector==='function'){return origGetStats.apply(this,arguments);}
if(origGetStats.length===0&&(arguments.length===0||typeof arguments[0]!=='function')){return origGetStats.apply(this,[]);}
var fixChromeStats_=function(response){var standardReport={};var reports=response.result();reports.forEach(function(report){var standardStats={id:report.id,timestamp:report.timestamp,type:{localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[report.type]||report.type};report.names().forEach(function(name){standardStats[name]=report.stat(name);});standardReport[standardStats.id]=standardStats;});return standardReport;};var makeMapStats=function(stats){return new Map(Object.keys(stats).map(function(key){return[key,stats[key]];}));};if(arguments.length>=2){var successCallbackWrapper_=function(response){args[1](makeMapStats(fixChromeStats_(response)));};return origGetStats.apply(this,[successCallbackWrapper_,arguments[0]]);}
return new Promise(function(resolve,reject){origGetStats.apply(self,[function(response){resolve(makeMapStats(fixChromeStats_(response)));},reject]);}).then(successCallback,errorCallback);};if(browserDetails.version<51){['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){var args=arguments;var self=this;var promise=new Promise(function(resolve,reject){nativeMethod.apply(self,[args[0],resolve,reject]);});if(args.length<2){return promise;}
return promise.then(function(){args[1].apply(null,[]);},function(err){if(args.length>=3){args[2].apply(null,[err]);}});};});}
if(browserDetails.version<52){['createOffer','createAnswer'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){var self=this;if(arguments.length<1||(arguments.length===1&&typeof arguments[0]==='object')){var opts=arguments.length===1?arguments[0]:undefined;return new Promise(function(resolve,reject){nativeMethod.apply(self,[resolve,reject,opts]);});}
return nativeMethod.apply(this,arguments);};});}
['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new((method==='addIceCandidate')?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
return Promise.resolve();}
return nativeAddIceCandidate.apply(this,arguments);};}};module.exports={shimMediaStream:chromeShim.shimMediaStream,shimOnTrack:chromeShim.shimOnTrack,shimGetSendersWithDtmf:chromeShim.shimGetSendersWithDtmf,shimSourceObject:chromeShim.shimSourceObject,shimPeerConnection:chromeShim.shimPeerConnection,shimGetUserMedia:require('./getusermedia')};},{"../utils.js":12,"./getusermedia":5}],5:[function(require,module,exports){'use strict';var utils=require('../utils.js');var logging=utils.log;module.exports=function(window){var browserDetails=utils.detectBrowser(window);var navigator=window&&window.navigator;var constraintsToChrome_=function(c){if(typeof c!=='object'||c.mandatory||c.optional){return c;}
var cc={};Object.keys(c).forEach(function(key){if(key==='require'||key==='advanced'||key==='mediaSource'){return;}
var r=(typeof c[key]==='object')?c[key]:{ideal:c[key]};if(r.exact!==undefined&&typeof r.exact==='number'){r.min=r.max=r.exact;}
var oldname_=function(prefix,name){if(prefix){return prefix+name.charAt(0).toUpperCase()+name.slice(1);}
return(name==='deviceId')?'sourceId':name;};if(r.ideal!==undefined){cc.optional=cc.optional||[];var oc={};if(typeof r.ideal==='number'){oc[oldname_('min',key)]=r.ideal;cc.optional.push(oc);oc={};oc[oldname_('max',key)]=r.ideal;cc.optional.push(oc);}else{oc[oldname_('',key)]=r.ideal;cc.optional.push(oc);}}
if(r.exact!==undefined&&typeof r.exact!=='number'){cc.mandatory=cc.mandatory||{};cc.mandatory[oldname_('',key)]=r.exact;}else{['min','max'].forEach(function(mix){if(r[mix]!==undefined){cc.mandatory=cc.mandatory||{};cc.mandatory[oldname_(mix,key)]=r[mix];}});}});if(c.advanced){cc.optional=(cc.optional||[]).concat(c.advanced);}
return cc;};var shimConstraints_=function(constraints,func){constraints=JSON.parse(JSON.stringify(constraints));if(constraints&&typeof constraints.audio==='object'){var remap=function(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};constraints=JSON.parse(JSON.stringify(constraints));remap(constraints.audio,'autoGainControl','googAutoGainControl');remap(constraints.audio,'noiseSuppression','googNoiseSuppression');constraints.audio=constraintsToChrome_(constraints.audio);}
if(constraints&&typeof constraints.video==='object'){var face=constraints.video.facingMode;face=face&&((typeof face==='object')?face:{ideal:face});var getSupportedFacingModeLies=browserDetails.version<61;if((face&&(face.exact==='user'||face.exact==='environment'||face.ideal==='user'||face.ideal==='environment'))&&!(navigator.mediaDevices.getSupportedConstraints&&navigator.mediaDevices.getSupportedConstraints().facingMode&&!getSupportedFacingModeLies)){delete constraints.video.facingMode;var matches;if(face.exact==='environment'||face.ideal==='environment'){matches=['back','rear'];}else if(face.exact==='user'||face.ideal==='user'){matches=['front'];}
if(matches){return navigator.mediaDevices.enumerateDevices().then(function(devices){devices=devices.filter(function(d){return d.kind==='videoinput';});var dev=devices.find(function(d){return matches.some(function(match){return d.label.toLowerCase().indexOf(match)!==-1;});});if(!dev&&devices.length&&matches.indexOf('back')!==-1){dev=devices[devices.length-1];}
if(dev){constraints.video.deviceId=face.exact?{exact:dev.deviceId}:{ideal:dev.deviceId};}
constraints.video=constraintsToChrome_(constraints.video);logging('chrome: '+JSON.stringify(constraints));return func(constraints);});}}
constraints.video=constraintsToChrome_(constraints.video);}
logging('chrome: '+JSON.stringify(constraints));return func(constraints);};var shimError_=function(e){return{name:{PermissionDeniedError:'NotAllowedError',InvalidStateError:'NotReadableError',DevicesNotFoundError:'NotFoundError',ConstraintNotSatisfiedError:'OverconstrainedError',TrackStartError:'NotReadableError',MediaDeviceFailedDueToShutdown:'NotReadableError',MediaDeviceKillSwitchOn:'NotReadableError'}[e.name]||e.name,message:e.message,constraint:e.constraintName,toString:function(){return this.name+(this.message&&': ')+this.message;}};};var getUserMedia_=function(constraints,onSuccess,onError){shimConstraints_(constraints,function(c){navigator.webkitGetUserMedia(c,onSuccess,function(e){onError(shimError_(e));});});};navigator.getUserMedia=getUserMedia_;var getUserMediaPromise_=function(constraints){return new Promise(function(resolve,reject){navigator.getUserMedia(constraints,resolve,reject);});};if(!navigator.mediaDevices){navigator.mediaDevices={getUserMedia:getUserMediaPromise_,enumerateDevices:function(){return new Promise(function(resolve){var kinds={audio:'audioinput',video:'videoinput'};return window.MediaStreamTrack.getSources(function(devices){resolve(devices.map(function(device){return{label:device.label,kind:kinds[device.kind],deviceId:device.id,groupId:''};}));});});},getSupportedConstraints:function(){return{deviceId:true,echoCancellation:true,facingMode:true,frameRate:true,height:true,width:true};}};}
if(!navigator.mediaDevices.getUserMedia){navigator.mediaDevices.getUserMedia=function(constraints){return getUserMediaPromise_(constraints);};}else{var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(cs){return shimConstraints_(cs,function(c){return origGetUserMedia(c).then(function(stream){if(c.audio&&!stream.getAudioTracks().length||c.video&&!stream.getVideoTracks().length){stream.getTracks().forEach(function(track){track.stop();});throw new DOMException('','NotFoundError');}
return stream;},function(e){return Promise.reject(shimError_(e));});});};}
if(typeof navigator.mediaDevices.addEventListener==='undefined'){navigator.mediaDevices.addEventListener=function(){logging('Dummy mediaDevices.addEventListener called.');};}
if(typeof navigator.mediaDevices.removeEventListener==='undefined'){navigator.mediaDevices.removeEventListener=function(){logging('Dummy mediaDevices.removeEventListener called.');};}};},{"../utils.js":12}],6:[function(require,module,exports){'use strict';var utils=require('../utils');var shimRTCPeerConnection=require('./rtcpeerconnection_shim');module.exports={shimGetUserMedia:require('./getusermedia'),shimPeerConnection:function(window){var browserDetails=utils.detectBrowser(window);if(window.RTCIceGatherer){if(!window.RTCIceCandidate){window.RTCIceCandidate=function(args){return args;};}
if(!window.RTCSessionDescription){window.RTCSessionDescription=function(args){return args;};}
if(browserDetails.version<15025){var origMSTEnabled=Object.getOwnPropertyDescriptor(window.MediaStreamTrack.prototype,'enabled');Object.defineProperty(window.MediaStreamTrack.prototype,'enabled',{set:function(value){origMSTEnabled.set.call(this,value);var ev=new Event('enabled');ev.enabled=value;this.dispatchEvent(ev);}});}}
window.RTCPeerConnection=shimRTCPeerConnection(window,browserDetails.version);},shimReplaceTrack:function(window){if(window.RTCRtpSender&&!('replaceTrack'in window.RTCRtpSender.prototype)){window.RTCRtpSender.prototype.replaceTrack=window.RTCRtpSender.prototype.setTrack;}}};},{"../utils":12,"./getusermedia":7,"./rtcpeerconnection_shim":8}],7:[function(require,module,exports){'use strict';module.exports=function(window){var navigator=window&&window.navigator;var shimError_=function(e){return{name:{PermissionDeniedError:'NotAllowedError'}[e.name]||e.name,message:e.message,constraint:e.constraint,toString:function(){return this.name;}};};var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){return origGetUserMedia(c).catch(function(e){return Promise.reject(shimError_(e));});};};},{}],8:[function(require,module,exports){'use strict';var SDPUtils=require('sdp');function sortTracks(tracks){var audioTracks=tracks.filter(function(track){return track.kind==='audio';});var videoTracks=tracks.filter(function(track){return track.kind==='video';});tracks=[];while(audioTracks.length||videoTracks.length){if(audioTracks.length){tracks.push(audioTracks.shift());}
if(videoTracks.length){tracks.push(videoTracks.shift());}}
return tracks;}
function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){console.warn('RTCIceServer.url is deprecated! Use urls instead.');}
var isString=typeof urls==='string';if(isString){urls=[urls];}
urls=urls.filter(function(url){var validTurn=url.indexOf('turn:')===0&&url.indexOf('transport=udp')!==-1&&url.indexOf('turn:[')===-1&&!hasTurn;if(validTurn){hasTurn=true;return true;}
return url.indexOf('stun:')===0&&edgeVersion>=14393;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}
return false;});}
function getCommonCapabilities(localCapabilities,remoteCapabilities){var commonCapabilities={codecs:[],headerExtensions:[],fecMechanisms:[]};var findCodecByPayloadType=function(pt,codecs){pt=parseInt(pt,10);for(var i=0;i<codecs.length;i++){if(codecs[i].payloadType===pt||codecs[i].preferredPayloadType===pt){return codecs[i];}}};var rtxCapabilityMatches=function(lRtx,rRtx,lCodecs,rCodecs){var lCodec=findCodecByPayloadType(lRtx.parameters.apt,lCodecs);var rCodec=findCodecByPayloadType(rRtx.parameters.apt,rCodecs);return lCodec&&rCodec&&lCodec.name.toLowerCase()===rCodec.name.toLowerCase();};localCapabilities.codecs.forEach(function(lCodec){for(var i=0;i<remoteCapabilities.codecs.length;i++){var rCodec=remoteCapabilities.codecs[i];if(lCodec.name.toLowerCase()===rCodec.name.toLowerCase()&&lCodec.clockRate===rCodec.clockRate){if(lCodec.name.toLowerCase()==='rtx'&&lCodec.parameters&&rCodec.parameters.apt){if(!rtxCapabilityMatches(lCodec,rCodec,localCapabilities.codecs,remoteCapabilities.codecs)){continue;}}
rCodec=JSON.parse(JSON.stringify(rCodec));rCodec.numChannels=Math.min(lCodec.numChannels,rCodec.numChannels);commonCapabilities.codecs.push(rCodec);rCodec.rtcpFeedback=rCodec.rtcpFeedback.filter(function(fb){for(var j=0;j<lCodec.rtcpFeedback.length;j++){if(lCodec.rtcpFeedback[j].type===fb.type&&lCodec.rtcpFeedback[j].parameter===fb.parameter){return true;}}
return false;});break;}}});localCapabilities.headerExtensions.forEach(function(lHeaderExtension){for(var i=0;i<remoteCapabilities.headerExtensions.length;i++){var rHeaderExtension=remoteCapabilities.headerExtensions[i];if(lHeaderExtension.uri===rHeaderExtension.uri){commonCapabilities.headerExtensions.push(rHeaderExtension);break;}}});return commonCapabilities;}
function isActionAllowedInSignalingState(action,type,signalingState){return{offer:{setLocalDescription:['stable','have-local-offer'],setRemoteDescription:['stable','have-remote-offer']},answer:{setLocalDescription:['have-remote-offer','have-local-pranswer'],setRemoteDescription:['have-local-offer','have-remote-pranswer']}}[type][action].indexOf(signalingState)!==-1;}
module.exports=function(window,edgeVersion){var RTCPeerConnection=function(config){var self=this;var _eventTarget=document.createDocumentFragment();['addEventListener','removeEventListener','dispatchEvent'].forEach(function(method){self[method]=_eventTarget[method].bind(_eventTarget);});this.needNegotiation=false;this.onicecandidate=null;this.onaddstream=null;this.ontrack=null;this.onremovestream=null;this.onsignalingstatechange=null;this.oniceconnectionstatechange=null;this.onicegatheringstatechange=null;this.onnegotiationneeded=null;this.ondatachannel=null;this.canTrickleIceCandidates=null;this.localStreams=[];this.remoteStreams=[];this.getLocalStreams=function(){return self.localStreams;};this.getRemoteStreams=function(){return self.remoteStreams;};this.localDescription=new window.RTCSessionDescription({type:'',sdp:''});this.remoteDescription=new window.RTCSessionDescription({type:'',sdp:''});this.signalingState='stable';this.iceConnectionState='new';this.iceGatheringState='new';this.iceOptions={gatherPolicy:'all',iceServers:[]};if(config&&config.iceTransportPolicy){switch(config.iceTransportPolicy){case'all':case'relay':this.iceOptions.gatherPolicy=config.iceTransportPolicy;break;default:break;}}
this.usingBundle=config&&config.bundlePolicy==='max-bundle';if(config&&config.iceServers){this.iceOptions.iceServers=filterIceServers(config.iceServers,edgeVersion);}
this._config=config||{};this.transceivers=[];this._localIceCandidatesBuffer=[];this._sdpSessionId=SDPUtils.generateSessionId();};RTCPeerConnection.prototype._emitGatheringStateChange=function(){var event=new Event('icegatheringstatechange');this.dispatchEvent(event);if(this.onicegatheringstatechange!==null){this.onicegatheringstatechange(event);}};RTCPeerConnection.prototype._emitBufferedCandidates=function(){var self=this;var sections=SDPUtils.splitSections(self.localDescription.sdp);this._localIceCandidatesBuffer.forEach(function(event){var end=!event.candidate||Object.keys(event.candidate).length===0;if(end){for(var j=1;j<sections.length;j++){if(sections[j].indexOf('\r\na=end-of-candidates\r\n')===-1){sections[j]+='a=end-of-candidates\r\n';}}}else{sections[event.candidate.sdpMLineIndex+1]+='a='+event.candidate.candidate+'\r\n';}
self.localDescription.sdp=sections.join('');self.dispatchEvent(event);if(self.onicecandidate!==null){self.onicecandidate(event);}
if(!event.candidate&&self.iceGatheringState!=='complete'){var complete=self.transceivers.every(function(transceiver){return transceiver.iceGatherer&&transceiver.iceGatherer.state==='completed';});if(complete&&self.iceGatheringStateChange!=='complete'){self.iceGatheringState='complete';self._emitGatheringStateChange();}}});this._localIceCandidatesBuffer=[];};RTCPeerConnection.prototype.getConfiguration=function(){return this._config;};RTCPeerConnection.prototype._createTransceiver=function(kind){var hasBundleTransport=this.transceivers.length>0;var transceiver={track:null,iceGatherer:null,iceTransport:null,dtlsTransport:null,localCapabilities:null,remoteCapabilities:null,rtpSender:null,rtpReceiver:null,kind:kind,mid:null,sendEncodingParameters:null,recvEncodingParameters:null,stream:null,wantReceive:true};if(this.usingBundle&&hasBundleTransport){transceiver.iceTransport=this.transceivers[0].iceTransport;transceiver.dtlsTransport=this.transceivers[0].dtlsTransport;}else{var transports=this._createIceAndDtlsTransports();transceiver.iceTransport=transports.iceTransport;transceiver.dtlsTransport=transports.dtlsTransport;}
this.transceivers.push(transceiver);return transceiver;};RTCPeerConnection.prototype.addTrack=function(track,stream){var transceiver;for(var i=0;i<this.transceivers.length;i++){if(!this.transceivers[i].track&&this.transceivers[i].kind===track.kind){transceiver=this.transceivers[i];}}
if(!transceiver){transceiver=this._createTransceiver(track.kind);}
transceiver.track=track;transceiver.stream=stream;transceiver.rtpSender=new window.RTCRtpSender(track,transceiver.dtlsTransport);this._maybeFireNegotiationNeeded();return transceiver.rtpSender;};RTCPeerConnection.prototype.addStream=function(stream){var self=this;if(edgeVersion>=15025){this.localStreams.push(stream);stream.getTracks().forEach(function(track){self.addTrack(track,stream);});}else{var clonedStream=stream.clone();stream.getTracks().forEach(function(track,idx){var clonedTrack=clonedStream.getTracks()[idx];track.addEventListener('enabled',function(event){clonedTrack.enabled=event.enabled;});});clonedStream.getTracks().forEach(function(track){self.addTrack(track,clonedStream);});this.localStreams.push(clonedStream);}
this._maybeFireNegotiationNeeded();};RTCPeerConnection.prototype.removeStream=function(stream){var idx=this.localStreams.indexOf(stream);if(idx>-1){this.localStreams.splice(idx,1);this._maybeFireNegotiationNeeded();}};RTCPeerConnection.prototype.getSenders=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpSender;}).map(function(transceiver){return transceiver.rtpSender;});};RTCPeerConnection.prototype.getReceivers=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpReceiver;}).map(function(transceiver){return transceiver.rtpReceiver;});};RTCPeerConnection.prototype._createIceGatherer=function(mid,sdpMLineIndex){var self=this;var iceGatherer=new window.RTCIceGatherer(self.iceOptions);iceGatherer.onlocalcandidate=function(evt){var event=new Event('icecandidate');event.candidate={sdpMid:mid,sdpMLineIndex:sdpMLineIndex};var cand=evt.candidate;var end=!cand||Object.keys(cand).length===0;if(end){if(iceGatherer.state===undefined){iceGatherer.state='completed';}}else{cand.component=1;event.candidate.candidate=SDPUtils.writeCandidate(cand);}
var sections=SDPUtils.splitSections(self.localDescription.sdp);if(!end){sections[event.candidate.sdpMLineIndex+1]+='a='+event.candidate.candidate+'\r\n';}else{sections[event.candidate.sdpMLineIndex+1]+='a=end-of-candidates\r\n';}
self.localDescription.sdp=sections.join('');var transceivers=self._pendingOffer?self._pendingOffer:self.transceivers;var complete=transceivers.every(function(transceiver){return transceiver.iceGatherer&&transceiver.iceGatherer.state==='completed';});switch(self.iceGatheringState){case'new':if(!end){self._localIceCandidatesBuffer.push(event);}
if(end&&complete){self._localIceCandidatesBuffer.push(new Event('icecandidate'));}
break;case'gathering':self._emitBufferedCandidates();if(!end){self.dispatchEvent(event);if(self.onicecandidate!==null){self.onicecandidate(event);}}
if(complete){self.dispatchEvent(new Event('icecandidate'));if(self.onicecandidate!==null){self.onicecandidate(new Event('icecandidate'));}
self.iceGatheringState='complete';self._emitGatheringStateChange();}
break;case'complete':break;default:break;}};return iceGatherer;};RTCPeerConnection.prototype._createIceAndDtlsTransports=function(){var self=this;var iceTransport=new window.RTCIceTransport(null);iceTransport.onicestatechange=function(){self._updateConnectionState();};var dtlsTransport=new window.RTCDtlsTransport(iceTransport);dtlsTransport.ondtlsstatechange=function(){self._updateConnectionState();};dtlsTransport.onerror=function(){Object.defineProperty(dtlsTransport,'state',{value:'failed',writable:true});self._updateConnectionState();};return{iceTransport:iceTransport,dtlsTransport:dtlsTransport};};RTCPeerConnection.prototype._disposeIceAndDtlsTransports=function(sdpMLineIndex){var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer){delete iceGatherer.onlocalcandidate;delete this.transceivers[sdpMLineIndex].iceGatherer;}
var iceTransport=this.transceivers[sdpMLineIndex].iceTransport;if(iceTransport){delete iceTransport.onicestatechange;delete this.transceivers[sdpMLineIndex].iceTransport;}
var dtlsTransport=this.transceivers[sdpMLineIndex].dtlsTransport;if(dtlsTransport){delete dtlsTransport.ondtlssttatechange;delete dtlsTransport.onerror;delete this.transceivers[sdpMLineIndex].dtlsTransport;}};RTCPeerConnection.prototype._transceive=function(transceiver,send,recv){var params=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);if(send&&transceiver.rtpSender){params.encodings=transceiver.sendEncodingParameters;params.rtcp={cname:SDPUtils.localCName,compound:transceiver.rtcpParameters.compound};if(transceiver.recvEncodingParameters.length){params.rtcp.ssrc=transceiver.recvEncodingParameters[0].ssrc;}
transceiver.rtpSender.send(params);}
if(recv&&transceiver.rtpReceiver){if(transceiver.kind==='video'&&transceiver.recvEncodingParameters&&edgeVersion<15019){transceiver.recvEncodingParameters.forEach(function(p){delete p.rtx;});}
params.encodings=transceiver.recvEncodingParameters;params.rtcp={cname:transceiver.rtcpParameters.cname,compound:transceiver.rtcpParameters.compound};if(transceiver.sendEncodingParameters.length){params.rtcp.ssrc=transceiver.sendEncodingParameters[0].ssrc;}
transceiver.rtpReceiver.receive(params);}};RTCPeerConnection.prototype.setLocalDescription=function(description){var self=this;if(!isActionAllowedInSignalingState('setLocalDescription',description.type,this.signalingState)){var e=new Error('Can not set local '+description.type+' in state '+this.signalingState);e.name='InvalidStateError';if(arguments.length>2&&typeof arguments[2]==='function'){window.setTimeout(arguments[2],0,e);}
return Promise.reject(e);}
var sections;var sessionpart;if(description.type==='offer'){if(this._pendingOffer){sections=SDPUtils.splitSections(description.sdp);sessionpart=sections.shift();sections.forEach(function(mediaSection,sdpMLineIndex){var caps=SDPUtils.parseRtpParameters(mediaSection);self._pendingOffer[sdpMLineIndex].localCapabilities=caps;});this.transceivers=this._pendingOffer;delete this._pendingOffer;}}else if(description.type==='answer'){sections=SDPUtils.splitSections(self.remoteDescription.sdp);sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;sections.forEach(function(mediaSection,sdpMLineIndex){var transceiver=self.transceivers[sdpMLineIndex];var iceGatherer=transceiver.iceGatherer;var iceTransport=transceiver.iceTransport;var dtlsTransport=transceiver.dtlsTransport;var localCapabilities=transceiver.localCapabilities;var remoteCapabilities=transceiver.remoteCapabilities;var rejected=SDPUtils.isRejected(mediaSection);if(!rejected&&!transceiver.isDatachannel){var remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);var remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);if(isIceLite){remoteDtlsParameters.role='server';}
if(!self.usingBundle||sdpMLineIndex===0){iceTransport.start(iceGatherer,remoteIceParameters,isIceLite?'controlling':'controlled');dtlsTransport.start(remoteDtlsParameters);}
var params=getCommonCapabilities(localCapabilities,remoteCapabilities);self._transceive(transceiver,params.codecs.length>0,false);}});}
this.localDescription={type:description.type,sdp:description.sdp};switch(description.type){case'offer':this._updateSignalingState('have-local-offer');break;case'answer':this._updateSignalingState('stable');break;default:throw new TypeError('unsupported type "'+description.type+'"');}
var hasCallback=arguments.length>1&&typeof arguments[1]==='function';if(hasCallback){var cb=arguments[1];window.setTimeout(function(){cb();if(self.iceGatheringState==='new'){self.iceGatheringState='gathering';self._emitGatheringStateChange();}
self._emitBufferedCandidates();},0);}
var p=Promise.resolve();p.then(function(){if(!hasCallback){if(self.iceGatheringState==='new'){self.iceGatheringState='gathering';self._emitGatheringStateChange();}
window.setTimeout(self._emitBufferedCandidates.bind(self),500);}});return p;};RTCPeerConnection.prototype.setRemoteDescription=function(description){var self=this;if(!isActionAllowedInSignalingState('setRemoteDescription',description.type,this.signalingState)){var e=new Error('Can not set remote '+description.type+' in state '+this.signalingState);e.name='InvalidStateError';if(arguments.length>2&&typeof arguments[2]==='function'){window.setTimeout(arguments[2],0,e);}
return Promise.reject(e);}
var streams={};var receiverList=[];var sections=SDPUtils.splitSections(description.sdp);var sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;var usingBundle=SDPUtils.matchPrefix(sessionpart,'a=group:BUNDLE ').length>0;this.usingBundle=usingBundle;var iceOptions=SDPUtils.matchPrefix(sessionpart,'a=ice-options:')[0];if(iceOptions){this.canTrickleIceCandidates=iceOptions.substr(14).split(' ').indexOf('trickle')>=0;}else{this.canTrickleIceCandidates=false;}
sections.forEach(function(mediaSection,sdpMLineIndex){var lines=SDPUtils.splitLines(mediaSection);var kind=SDPUtils.getKind(mediaSection);var rejected=SDPUtils.isRejected(mediaSection);var protocol=lines[0].substr(2).split(' ')[2];var direction=SDPUtils.getDirection(mediaSection,sessionpart);var remoteMsid=SDPUtils.parseMsid(mediaSection);var mid=SDPUtils.getMid(mediaSection)||SDPUtils.generateIdentifier();if(kind==='application'&&protocol==='DTLS/SCTP'){self.transceivers[sdpMLineIndex]={mid:mid,isDatachannel:true};return;}
var transceiver;var iceGatherer;var iceTransport;var dtlsTransport;var rtpReceiver;var sendEncodingParameters;var recvEncodingParameters;var localCapabilities;var track;var remoteCapabilities=SDPUtils.parseRtpParameters(mediaSection);var remoteIceParameters;var remoteDtlsParameters;if(!rejected){remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);remoteDtlsParameters.role='client';}
recvEncodingParameters=SDPUtils.parseRtpEncodingParameters(mediaSection);var rtcpParameters=SDPUtils.parseRtcpParameters(mediaSection);var isComplete=SDPUtils.matchPrefix(mediaSection,'a=end-of-candidates',sessionpart).length>0;var cands=SDPUtils.matchPrefix(mediaSection,'a=candidate:').map(function(cand){return SDPUtils.parseCandidate(cand);}).filter(function(cand){return cand.component==='1'||cand.component===1;});if((description.type==='offer'||description.type==='answer')&&!rejected&&usingBundle&&sdpMLineIndex>0&&self.transceivers[sdpMLineIndex]){self._disposeIceAndDtlsTransports(sdpMLineIndex);self.transceivers[sdpMLineIndex].iceGatherer=self.transceivers[0].iceGatherer;self.transceivers[sdpMLineIndex].iceTransport=self.transceivers[0].iceTransport;self.transceivers[sdpMLineIndex].dtlsTransport=self.transceivers[0].dtlsTransport;if(self.transceivers[sdpMLineIndex].rtpSender){self.transceivers[sdpMLineIndex].rtpSender.setTransport(self.transceivers[0].dtlsTransport);}
if(self.transceivers[sdpMLineIndex].rtpReceiver){self.transceivers[sdpMLineIndex].rtpReceiver.setTransport(self.transceivers[0].dtlsTransport);}}
if(description.type==='offer'&&!rejected){transceiver=self.transceivers[sdpMLineIndex]||self._createTransceiver(kind);transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=usingBundle&&sdpMLineIndex>0?self.transceivers[0].iceGatherer:self._createIceGatherer(mid,sdpMLineIndex);}
if(isComplete&&(!usingBundle||sdpMLineIndex===0)){transceiver.iceTransport.setRemoteCandidates(cands);}
localCapabilities=window.RTCRtpReceiver.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
sendEncodingParameters=[{ssrc:(2*sdpMLineIndex+2)*1001}];if(direction==='sendrecv'||direction==='sendonly'){rtpReceiver=new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);track=rtpReceiver.track;if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();Object.defineProperty(streams[remoteMsid.stream],'id',{get:function(){return remoteMsid.stream;}});}
Object.defineProperty(track,'id',{get:function(){return remoteMsid.track;}});streams[remoteMsid.stream].addTrack(track);receiverList.push([track,rtpReceiver,streams[remoteMsid.stream]]);}else{if(!streams.default){streams.default=new window.MediaStream();}
streams.default.addTrack(track);receiverList.push([track,rtpReceiver,streams.default]);}}
transceiver.localCapabilities=localCapabilities;transceiver.remoteCapabilities=remoteCapabilities;transceiver.rtpReceiver=rtpReceiver;transceiver.rtcpParameters=rtcpParameters;transceiver.sendEncodingParameters=sendEncodingParameters;transceiver.recvEncodingParameters=recvEncodingParameters;self._transceive(self.transceivers[sdpMLineIndex],false,direction==='sendrecv'||direction==='sendonly');}else if(description.type==='answer'&&!rejected){transceiver=self.transceivers[sdpMLineIndex];iceGatherer=transceiver.iceGatherer;iceTransport=transceiver.iceTransport;dtlsTransport=transceiver.dtlsTransport;rtpReceiver=transceiver.rtpReceiver;sendEncodingParameters=transceiver.sendEncodingParameters;localCapabilities=transceiver.localCapabilities;self.transceivers[sdpMLineIndex].recvEncodingParameters=recvEncodingParameters;self.transceivers[sdpMLineIndex].remoteCapabilities=remoteCapabilities;self.transceivers[sdpMLineIndex].rtcpParameters=rtcpParameters;if((isIceLite||isComplete)&&cands.length){iceTransport.setRemoteCandidates(cands);}
if(!usingBundle||sdpMLineIndex===0){iceTransport.start(iceGatherer,remoteIceParameters,'controlling');dtlsTransport.start(remoteDtlsParameters);}
self._transceive(transceiver,direction==='sendrecv'||direction==='recvonly',direction==='sendrecv'||direction==='sendonly');if(rtpReceiver&&(direction==='sendrecv'||direction==='sendonly')){track=rtpReceiver.track;if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();}
streams[remoteMsid.stream].addTrack(track);receiverList.push([track,rtpReceiver,streams[remoteMsid.stream]]);}else{if(!streams.default){streams.default=new window.MediaStream();}
streams.default.addTrack(track);receiverList.push([track,rtpReceiver,streams.default]);}}else{delete transceiver.rtpReceiver;}}});this.remoteDescription={type:description.type,sdp:description.sdp};switch(description.type){case'offer':this._updateSignalingState('have-remote-offer');break;case'answer':this._updateSignalingState('stable');break;default:throw new TypeError('unsupported type "'+description.type+'"');}
Object.keys(streams).forEach(function(sid){var stream=streams[sid];if(stream.getTracks().length){self.remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;self.dispatchEvent(event);if(self.onaddstream!==null){window.setTimeout(function(){self.onaddstream(event);},0);}
receiverList.forEach(function(item){var track=item[0];var receiver=item[1];if(stream.id!==item[2].id){return;}
var trackEvent=new Event('track');trackEvent.track=track;trackEvent.receiver=receiver;trackEvent.streams=[stream];self.dispatchEvent(trackEvent);if(self.ontrack!==null){window.setTimeout(function(){self.ontrack(trackEvent);},0);}});}});window.setTimeout(function(){if(!(self&&self.transceivers)){return;}
self.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.iceTransport.state==='new'&&transceiver.iceTransport.getRemoteCandidates().length>0){console.warn('Timeout for addRemoteCandidate. Consider sending '+'an end-of-candidates notification');transceiver.iceTransport.addRemoteCandidate({});}});},4000);if(arguments.length>1&&typeof arguments[1]==='function'){window.setTimeout(arguments[1],0);}
return Promise.resolve();};RTCPeerConnection.prototype.close=function(){this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport){transceiver.iceTransport.stop();}
if(transceiver.dtlsTransport){transceiver.dtlsTransport.stop();}
if(transceiver.rtpSender){transceiver.rtpSender.stop();}
if(transceiver.rtpReceiver){transceiver.rtpReceiver.stop();}});this._updateSignalingState('closed');};RTCPeerConnection.prototype._updateSignalingState=function(newState){this.signalingState=newState;var event=new Event('signalingstatechange');this.dispatchEvent(event);if(this.onsignalingstatechange!==null){this.onsignalingstatechange(event);}};RTCPeerConnection.prototype._maybeFireNegotiationNeeded=function(){var self=this;if(this.signalingState!=='stable'||this.needNegotiation===true){return;}
this.needNegotiation=true;window.setTimeout(function(){if(self.needNegotiation===false){return;}
self.needNegotiation=false;var event=new Event('negotiationneeded');self.dispatchEvent(event);if(self.onnegotiationneeded!==null){self.onnegotiationneeded(event);}},0);};RTCPeerConnection.prototype._updateConnectionState=function(){var self=this;var newState;var states={'new':0,closed:0,connecting:0,checking:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){states[transceiver.iceTransport.state]++;states[transceiver.dtlsTransport.state]++;});states.connected+=states.completed;newState='new';if(states.failed>0){newState='failed';}else if(states.connecting>0||states.checking>0){newState='connecting';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0||states.completed>0){newState='connected';}
if(newState!==self.iceConnectionState){self.iceConnectionState=newState;var event=new Event('iceconnectionstatechange');this.dispatchEvent(event);if(this.oniceconnectionstatechange!==null){this.oniceconnectionstatechange(event);}}};RTCPeerConnection.prototype.createOffer=function(){var self=this;if(this._pendingOffer){throw new Error('createOffer called while there is a pending offer.');}
var offerOptions;if(arguments.length===1&&typeof arguments[0]!=='function'){offerOptions=arguments[0];}else if(arguments.length===3){offerOptions=arguments[2];}
var numAudioTracks=this.transceivers.filter(function(t){return t.kind==='audio';}).length;var numVideoTracks=this.transceivers.filter(function(t){return t.kind==='video';}).length;if(offerOptions){if(offerOptions.mandatory||offerOptions.optional){throw new TypeError('Legacy mandatory/optional constraints not supported.');}
if(offerOptions.offerToReceiveAudio!==undefined){if(offerOptions.offerToReceiveAudio===true){numAudioTracks=1;}else if(offerOptions.offerToReceiveAudio===false){numAudioTracks=0;}else{numAudioTracks=offerOptions.offerToReceiveAudio;}}
if(offerOptions.offerToReceiveVideo!==undefined){if(offerOptions.offerToReceiveVideo===true){numVideoTracks=1;}else if(offerOptions.offerToReceiveVideo===false){numVideoTracks=0;}else{numVideoTracks=offerOptions.offerToReceiveVideo;}}}
this.transceivers.forEach(function(transceiver){if(transceiver.kind==='audio'){numAudioTracks--;if(numAudioTracks<0){transceiver.wantReceive=false;}}else if(transceiver.kind==='video'){numVideoTracks--;if(numVideoTracks<0){transceiver.wantReceive=false;}}});while(numAudioTracks>0||numVideoTracks>0){if(numAudioTracks>0){this._createTransceiver('audio');numAudioTracks--;}
if(numVideoTracks>0){this._createTransceiver('video');numVideoTracks--;}}
var transceivers=sortTracks(this.transceivers);var sdp=SDPUtils.writeSessionBoilerplate(this._sdpSessionId);transceivers.forEach(function(transceiver,sdpMLineIndex){var track=transceiver.track;var kind=transceiver.kind;var mid=SDPUtils.generateIdentifier();transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=self.usingBundle&&sdpMLineIndex>0?transceivers[0].iceGatherer:self._createIceGatherer(mid,sdpMLineIndex);}
var localCapabilities=window.RTCRtpSender.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
localCapabilities.codecs.forEach(function(codec){if(codec.name==='H264'&&codec.parameters['level-asymmetry-allowed']===undefined){codec.parameters['level-asymmetry-allowed']='1';}});var sendEncodingParameters=[{ssrc:(2*sdpMLineIndex+1)*1001}];if(track){if(edgeVersion>=15019&&kind==='video'){sendEncodingParameters[0].rtx={ssrc:(2*sdpMLineIndex+1)*1001+1};}}
if(transceiver.wantReceive){transceiver.rtpReceiver=new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);}
transceiver.localCapabilities=localCapabilities;transceiver.sendEncodingParameters=sendEncodingParameters;});if(this._config.bundlePolicy!=='max-compat'){sdp+='a=group:BUNDLE '+transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
sdp+='a=ice-options:trickle\r\n';transceivers.forEach(function(transceiver,sdpMLineIndex){sdp+=SDPUtils.writeMediaSection(transceiver,transceiver.localCapabilities,'offer',transceiver.stream);sdp+='a=rtcp-rsize\r\n';});this._pendingOffer=transceivers;var desc=new window.RTCSessionDescription({type:'offer',sdp:sdp});if(arguments.length&&typeof arguments[0]==='function'){window.setTimeout(arguments[0],0,desc);}
return Promise.resolve(desc);};RTCPeerConnection.prototype.createAnswer=function(){var sdp=SDPUtils.writeSessionBoilerplate(this._sdpSessionId);if(this.usingBundle){sdp+='a=group:BUNDLE '+this.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
this.transceivers.forEach(function(transceiver,sdpMLineIndex){if(transceiver.isDatachannel){sdp+='m=application 0 DTLS/SCTP 5000\r\n'+'c=IN IP4 0.0.0.0\r\n'+'a=mid:'+transceiver.mid+'\r\n';return;}
if(transceiver.stream){var localTrack;if(transceiver.kind==='audio'){localTrack=transceiver.stream.getAudioTracks()[0];}else if(transceiver.kind==='video'){localTrack=transceiver.stream.getVideoTracks()[0];}
if(localTrack){if(edgeVersion>=15019&&transceiver.kind==='video'){transceiver.sendEncodingParameters[0].rtx={ssrc:(2*sdpMLineIndex+2)*1001+1};}}}
var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
sdp+=SDPUtils.writeMediaSection(transceiver,commonCapabilities,'answer',transceiver.stream);if(transceiver.rtcpParameters&&transceiver.rtcpParameters.reducedSize){sdp+='a=rtcp-rsize\r\n';}});var desc=new window.RTCSessionDescription({type:'answer',sdp:sdp});if(arguments.length&&typeof arguments[0]==='function'){window.setTimeout(arguments[0],0,desc);}
return Promise.resolve(desc);};RTCPeerConnection.prototype.addIceCandidate=function(candidate){if(!candidate){for(var j=0;j<this.transceivers.length;j++){this.transceivers[j].iceTransport.addRemoteCandidate({});if(this.usingBundle){return Promise.resolve();}}}else{var mLineIndex=candidate.sdpMLineIndex;if(candidate.sdpMid){for(var i=0;i<this.transceivers.length;i++){if(this.transceivers[i].mid===candidate.sdpMid){mLineIndex=i;break;}}}
var transceiver=this.transceivers[mLineIndex];if(transceiver){var cand=Object.keys(candidate.candidate).length>0?SDPUtils.parseCandidate(candidate.candidate):{};if(cand.protocol==='tcp'&&(cand.port===0||cand.port===9)){return Promise.resolve();}
if(cand.component&&!(cand.component==='1'||cand.component===1)){return Promise.resolve();}
transceiver.iceTransport.addRemoteCandidate(cand);var sections=SDPUtils.splitSections(this.remoteDescription.sdp);sections[mLineIndex+1]+=(cand.type?candidate.candidate.trim():'a=end-of-candidates')+'\r\n';this.remoteDescription.sdp=sections.join('');}}
if(arguments.length>1&&typeof arguments[1]==='function'){window.setTimeout(arguments[1],0);}
return Promise.resolve();};RTCPeerConnection.prototype.getStats=function(){var promises=[];this.transceivers.forEach(function(transceiver){['rtpSender','rtpReceiver','iceGatherer','iceTransport','dtlsTransport'].forEach(function(method){if(transceiver[method]){promises.push(transceiver[method].getStats());}});});var cb=arguments.length>1&&typeof arguments[1]==='function'&&arguments[1];var fixStatsType=function(stat){return{inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[stat.type]||stat.type;};return new Promise(function(resolve){var results=new Map();Promise.all(promises).then(function(res){res.forEach(function(result){Object.keys(result).forEach(function(id){result[id].type=fixStatsType(result[id]);results.set(id,result[id]);});});if(cb){window.setTimeout(cb,0,results);}
resolve(results);});});};return RTCPeerConnection;};},{"sdp":1}],9:[function(require,module,exports){'use strict';var utils=require('../utils');var firefoxShim={shimOnTrack:function(window){if(typeof window==='object'&&window.RTCPeerConnection&&!('ontrack'in
window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'ontrack',{get:function(){return this._ontrack;},set:function(f){if(this._ontrack){this.removeEventListener('track',this._ontrack);this.removeEventListener('addstream',this._ontrackpoly);}
this.addEventListener('track',this._ontrack=f);this.addEventListener('addstream',this._ontrackpoly=function(e){e.stream.getTracks().forEach(function(track){var event=new Event('track');event.track=track;event.receiver={track:track};event.streams=[e.stream];this.dispatchEvent(event);}.bind(this));}.bind(this));}});}},shimSourceObject:function(window){if(typeof window==='object'){if(window.HTMLMediaElement&&!('srcObject'in window.HTMLMediaElement.prototype)){Object.defineProperty(window.HTMLMediaElement.prototype,'srcObject',{get:function(){return this.mozSrcObject;},set:function(stream){this.mozSrcObject=stream;}});}}},shimPeerConnection:function(window){var browserDetails=utils.detectBrowser(window);if(typeof window!=='object'||!(window.RTCPeerConnection||window.mozRTCPeerConnection)){return;}
if(!window.RTCPeerConnection){window.RTCPeerConnection=function(pcConfig,pcConstraints){if(browserDetails.version<38){if(pcConfig&&pcConfig.iceServers){var newIceServers=[];for(var i=0;i<pcConfig.iceServers.length;i++){var server=pcConfig.iceServers[i];if(server.hasOwnProperty('urls')){for(var j=0;j<server.urls.length;j++){var newServer={url:server.urls[j]};if(server.urls[j].indexOf('turn')===0){newServer.username=server.username;newServer.credential=server.credential;}
newIceServers.push(newServer);}}else{newIceServers.push(pcConfig.iceServers[i]);}}
pcConfig.iceServers=newIceServers;}}
return new window.mozRTCPeerConnection(pcConfig,pcConstraints);};window.RTCPeerConnection.prototype=window.mozRTCPeerConnection.prototype;if(window.mozRTCPeerConnection.generateCertificate){Object.defineProperty(window.RTCPeerConnection,'generateCertificate',{get:function(){return window.mozRTCPeerConnection.generateCertificate;}});}
window.RTCSessionDescription=window.mozRTCSessionDescription;window.RTCIceCandidate=window.mozRTCIceCandidate;}
['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new((method==='addIceCandidate')?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
return Promise.resolve();}
return nativeAddIceCandidate.apply(this,arguments);};var makeMapStats=function(stats){var map=new Map();Object.keys(stats).forEach(function(key){map.set(key,stats[key]);map[key]=stats[key];});return map;};var modernStatsTypes={inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'};var nativeGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,onSucc,onErr){return nativeGetStats.apply(this,[selector||null]).then(function(stats){if(browserDetails.version<48){stats=makeMapStats(stats);}
if(browserDetails.version<53&&!onSucc){try{stats.forEach(function(stat){stat.type=modernStatsTypes[stat.type]||stat.type;});}catch(e){if(e.name!=='TypeError'){throw e;}
stats.forEach(function(stat,i){stats.set(i,Object.assign({},stat,{type:modernStatsTypes[stat.type]||stat.type}));});}}
return stats;}).then(onSucc,onErr);};}};module.exports={shimOnTrack:firefoxShim.shimOnTrack,shimSourceObject:firefoxShim.shimSourceObject,shimPeerConnection:firefoxShim.shimPeerConnection,shimGetUserMedia:require('./getusermedia')};},{"../utils":12,"./getusermedia":10}],10:[function(require,module,exports){'use strict';var utils=require('../utils');var logging=utils.log;module.exports=function(window){var browserDetails=utils.detectBrowser(window);var navigator=window&&window.navigator;var MediaStreamTrack=window&&window.MediaStreamTrack;var shimError_=function(e){return{name:{InternalError:'NotReadableError',NotSupportedError:'TypeError',PermissionDeniedError:'NotAllowedError',SecurityError:'NotAllowedError'}[e.name]||e.name,message:{'The operation is insecure.':'The request is not allowed by the '+'user agent or the platform in the current context.'}[e.message]||e.message,constraint:e.constraint,toString:function(){return this.name+(this.message&&': ')+this.message;}};};var getUserMedia_=function(constraints,onSuccess,onError){var constraintsToFF37_=function(c){if(typeof c!=='object'||c.require){return c;}
var require=[];Object.keys(c).forEach(function(key){if(key==='require'||key==='advanced'||key==='mediaSource'){return;}
var r=c[key]=(typeof c[key]==='object')?c[key]:{ideal:c[key]};if(r.min!==undefined||r.max!==undefined||r.exact!==undefined){require.push(key);}
if(r.exact!==undefined){if(typeof r.exact==='number'){r.min=r.max=r.exact;}else{c[key]=r.exact;}
delete r.exact;}
if(r.ideal!==undefined){c.advanced=c.advanced||[];var oc={};if(typeof r.ideal==='number'){oc[key]={min:r.ideal,max:r.ideal};}else{oc[key]=r.ideal;}
c.advanced.push(oc);delete r.ideal;if(!Object.keys(r).length){delete c[key];}}});if(require.length){c.require=require;}
return c;};constraints=JSON.parse(JSON.stringify(constraints));if(browserDetails.version<38){logging('spec: '+JSON.stringify(constraints));if(constraints.audio){constraints.audio=constraintsToFF37_(constraints.audio);}
if(constraints.video){constraints.video=constraintsToFF37_(constraints.video);}
logging('ff37: '+JSON.stringify(constraints));}
return navigator.mozGetUserMedia(constraints,onSuccess,function(e){onError(shimError_(e));});};var getUserMediaPromise_=function(constraints){return new Promise(function(resolve,reject){getUserMedia_(constraints,resolve,reject);});};if(!navigator.mediaDevices){navigator.mediaDevices={getUserMedia:getUserMediaPromise_,addEventListener:function(){},removeEventListener:function(){}};}
navigator.mediaDevices.enumerateDevices=navigator.mediaDevices.enumerateDevices||function(){return new Promise(function(resolve){var infos=[{kind:'audioinput',deviceId:'default',label:'',groupId:''},{kind:'videoinput',deviceId:'default',label:'',groupId:''}];resolve(infos);});};if(browserDetails.version<41){var orgEnumerateDevices=navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);navigator.mediaDevices.enumerateDevices=function(){return orgEnumerateDevices().then(undefined,function(e){if(e.name==='NotFoundError'){return[];}
throw e;});};}
if(browserDetails.version<49){var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){return origGetUserMedia(c).then(function(stream){if(c.audio&&!stream.getAudioTracks().length||c.video&&!stream.getVideoTracks().length){stream.getTracks().forEach(function(track){track.stop();});throw new DOMException('The object can not be found here.','NotFoundError');}
return stream;},function(e){return Promise.reject(shimError_(e));});};}
if(!(browserDetails.version>55&&'autoGainControl'in navigator.mediaDevices.getSupportedConstraints())){var remap=function(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};var nativeGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){if(typeof c==='object'&&typeof c.audio==='object'){c=JSON.parse(JSON.stringify(c));remap(c.audio,'autoGainControl','mozAutoGainControl');remap(c.audio,'noiseSuppression','mozNoiseSuppression');}
return nativeGetUserMedia(c);};if(MediaStreamTrack&&MediaStreamTrack.prototype.getSettings){var nativeGetSettings=MediaStreamTrack.prototype.getSettings;MediaStreamTrack.prototype.getSettings=function(){var obj=nativeGetSettings.apply(this,arguments);remap(obj,'mozAutoGainControl','autoGainControl');remap(obj,'mozNoiseSuppression','noiseSuppression');return obj;};}
if(MediaStreamTrack&&MediaStreamTrack.prototype.applyConstraints){var nativeApplyConstraints=MediaStreamTrack.prototype.applyConstraints;MediaStreamTrack.prototype.applyConstraints=function(c){if(this.kind==='audio'&&typeof c==='object'){c=JSON.parse(JSON.stringify(c));remap(c,'autoGainControl','mozAutoGainControl');remap(c,'noiseSuppression','mozNoiseSuppression');}
return nativeApplyConstraints.apply(this,[c]);};}}
navigator.getUserMedia=function(constraints,onSuccess,onError){if(browserDetails.version<44){return getUserMedia_(constraints,onSuccess,onError);}
console.warn('navigator.getUserMedia has been replaced by '+'navigator.mediaDevices.getUserMedia');navigator.mediaDevices.getUserMedia(constraints).then(onSuccess,onError);};};},{"../utils":12}],11:[function(require,module,exports){'use strict';var utils=require('../utils');var safariShim={shimLocalStreamsAPI:function(window){if(typeof window!=='object'||!window.RTCPeerConnection){return;}
if(!('getLocalStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getLocalStreams=function(){if(!this._localStreams){this._localStreams=[];}
return this._localStreams;};}
if(!('getStreamById'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getStreamById=function(id){var result=null;if(this._localStreams){this._localStreams.forEach(function(stream){if(stream.id===id){result=stream;}});}
if(this._remoteStreams){this._remoteStreams.forEach(function(stream){if(stream.id===id){result=stream;}});}
return result;};}
if(!('addStream'in window.RTCPeerConnection.prototype)){var _addTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addStream=function(stream){if(!this._localStreams){this._localStreams=[];}
if(this._localStreams.indexOf(stream)===-1){this._localStreams.push(stream);}
var self=this;stream.getTracks().forEach(function(track){_addTrack.call(self,track,stream);});};window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(stream){if(!this._localStreams){this._localStreams=[stream];}else if(this._localStreams.indexOf(stream)===-1){this._localStreams.push(stream);}}
_addTrack.call(this,track,stream);};}
if(!('removeStream'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.removeStream=function(stream){if(!this._localStreams){this._localStreams=[];}
var index=this._localStreams.indexOf(stream);if(index===-1){return;}
this._localStreams.splice(index,1);var self=this;var tracks=stream.getTracks();this.getSenders().forEach(function(sender){if(tracks.indexOf(sender.track)!==-1){self.removeTrack(sender);}});};}},shimRemoteStreamsAPI:function(window){if(typeof window!=='object'||!window.RTCPeerConnection){return;}
if(!('getRemoteStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[];};}
if(!('onaddstream'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'onaddstream',{get:function(){return this._onaddstream;},set:function(f){if(this._onaddstream){this.removeEventListener('addstream',this._onaddstream);this.removeEventListener('track',this._onaddstreampoly);}
this.addEventListener('addstream',this._onaddstream=f);this.addEventListener('track',this._onaddstreampoly=function(e){var stream=e.streams[0];if(!this._remoteStreams){this._remoteStreams=[];}
if(this._remoteStreams.indexOf(stream)>=0){return;}
this._remoteStreams.push(stream);var event=new Event('addstream');event.stream=e.streams[0];this.dispatchEvent(event);}.bind(this));}});}},shimCallbacksAPI:function(window){if(typeof window!=='object'||!window.RTCPeerConnection){return;}
var prototype=window.RTCPeerConnection.prototype;var createOffer=prototype.createOffer;var createAnswer=prototype.createAnswer;var setLocalDescription=prototype.setLocalDescription;var setRemoteDescription=prototype.setRemoteDescription;var addIceCandidate=prototype.addIceCandidate;prototype.createOffer=function(successCallback,failureCallback){var options=(arguments.length>=2)?arguments[2]:arguments[0];var promise=createOffer.apply(this,[options]);if(!failureCallback){return promise;}
promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.createAnswer=function(successCallback,failureCallback){var options=(arguments.length>=2)?arguments[2]:arguments[0];var promise=createAnswer.apply(this,[options]);if(!failureCallback){return promise;}
promise.then(successCallback,failureCallback);return Promise.resolve();};var withCallback=function(description,successCallback,failureCallback){var promise=setLocalDescription.apply(this,[description]);if(!failureCallback){return promise;}
promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setLocalDescription=withCallback;withCallback=function(description,successCallback,failureCallback){var promise=setRemoteDescription.apply(this,[description]);if(!failureCallback){return promise;}
promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setRemoteDescription=withCallback;withCallback=function(candidate,successCallback,failureCallback){var promise=addIceCandidate.apply(this,[candidate]);if(!failureCallback){return promise;}
promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.addIceCandidate=withCallback;},shimGetUserMedia:function(window){var navigator=window&&window.navigator;if(!navigator.getUserMedia){if(navigator.webkitGetUserMedia){navigator.getUserMedia=navigator.webkitGetUserMedia.bind(navigator);}else if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){navigator.getUserMedia=function(constraints,cb,errcb){navigator.mediaDevices.getUserMedia(constraints).then(cb,errcb);}.bind(navigator);}}},shimRTCIceServerUrls:function(window){var OrigPeerConnection=window.RTCPeerConnection;window.RTCPeerConnection=function(pcConfig,pcConstraints){if(pcConfig&&pcConfig.iceServers){var newIceServers=[];for(var i=0;i<pcConfig.iceServers.length;i++){var server=pcConfig.iceServers[i];if(!server.hasOwnProperty('urls')&&server.hasOwnProperty('url')){utils.deprecated('RTCIceServer.url','RTCIceServer.urls');server=JSON.parse(JSON.stringify(server));server.urls=server.url;delete server.url;newIceServers.push(server);}else{newIceServers.push(pcConfig.iceServers[i]);}}
pcConfig.iceServers=newIceServers;}
return new OrigPeerConnection(pcConfig,pcConstraints);};window.RTCPeerConnection.prototype=OrigPeerConnection.prototype;Object.defineProperty(window.RTCPeerConnection,'generateCertificate',{get:function(){return OrigPeerConnection.generateCertificate;}});}};module.exports={shimCallbacksAPI:safariShim.shimCallbacksAPI,shimLocalStreamsAPI:safariShim.shimLocalStreamsAPI,shimRemoteStreamsAPI:safariShim.shimRemoteStreamsAPI,shimGetUserMedia:safariShim.shimGetUserMedia,shimRTCIceServerUrls:safariShim.shimRTCIceServerUrls};},{"../utils":12}],12:[function(require,module,exports){'use strict';var logDisabled_=true;var deprecationWarnings_=true;var utils={disableLog:function(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+typeof bool+'. Please use a boolean.');}
logDisabled_=bool;return(bool)?'adapter.js logging disabled':'adapter.js logging enabled';},disableWarnings:function(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+typeof bool+'. Please use a boolean.');}
deprecationWarnings_=!bool;return'adapter.js deprecation warnings '+(bool?'disabled':'enabled');},log:function(){if(typeof window==='object'){if(logDisabled_){return;}
if(typeof console!=='undefined'&&typeof console.log==='function'){console.log.apply(console,arguments);}}},deprecated:function(oldMethod,newMethod){if(!deprecationWarnings_){return;}
console.warn(oldMethod+' is deprecated, please use '+newMethod+' instead.');},extractVersion:function(uastring,expr,pos){var match=uastring.match(expr);return match&&match.length>=pos&&parseInt(match[pos],10);},detectBrowser:function(window){var navigator=window&&window.navigator;var result={};result.browser=null;result.version=null;if(typeof window==='undefined'||!window.navigator){result.browser='Not a browser.';return result;}
if(navigator.mozGetUserMedia){result.browser='firefox';result.version=this.extractVersion(navigator.userAgent,/Firefox\/(\d+)\./,1);}else if(navigator.webkitGetUserMedia){if(window.webkitRTCPeerConnection){result.browser='chrome';result.version=this.extractVersion(navigator.userAgent,/Chrom(e|ium)\/(\d+)\./,2);}else{if(navigator.userAgent.match(/Version\/(\d+).(\d+)/)){result.browser='safari';result.version=this.extractVersion(navigator.userAgent,/AppleWebKit\/(\d+)\./,1);}else{result.browser='Unsupported webkit-based browser '+'with GUM support but no WebRTC support.';return result;}}}else if(navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)){result.browser='edge';result.version=this.extractVersion(navigator.userAgent,/Edge\/(\d+).(\d+)$/,2);}else if(navigator.mediaDevices&&navigator.userAgent.match(/AppleWebKit\/(\d+)\./)){result.browser='safari';result.version=this.extractVersion(navigator.userAgent,/AppleWebKit\/(\d+)\./,1);}else{result.browser='Not a supported browser.';return result;}
return result;},shimCreateObjectURL:function(window){var URL=window&&window.URL;if(!(typeof window==='object'&&window.HTMLMediaElement&&'srcObject'in window.HTMLMediaElement.prototype)){return undefined;}
var nativeCreateObjectURL=URL.createObjectURL.bind(URL);var nativeRevokeObjectURL=URL.revokeObjectURL.bind(URL);var streams=new Map(),newId=0;URL.createObjectURL=function(stream){if('getTracks'in stream){var url='polyblob:'+(++newId);streams.set(url,stream);utils.deprecated('URL.createObjectURL(stream)','elem.srcObject = stream');return url;}
return nativeCreateObjectURL(stream);};URL.revokeObjectURL=function(url){nativeRevokeObjectURL(url);streams.delete(url);};var dsc=Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,'src');Object.defineProperty(window.HTMLMediaElement.prototype,'src',{get:function(){return dsc.get.apply(this);},set:function(url){this.srcObject=streams.get(url)||null;return dsc.set.apply(this,[url]);}});var nativeSetAttribute=window.HTMLMediaElement.prototype.setAttribute;window.HTMLMediaElement.prototype.setAttribute=function(){if(arguments.length===2&&(''+arguments[0]).toLowerCase()==='src'){this.srcObject=streams.get(arguments[1])||null;}
return nativeSetAttribute.apply(this,arguments);};}};module.exports={log:utils.log,deprecated:utils.deprecated,disableLog:utils.disableLog,disableWarnings:utils.disableWarnings,extractVersion:utils.extractVersion,shimCreateObjectURL:utils.shimCreateObjectURL,detectBrowser:utils.detectBrowser.bind(utils)};},{}]},{},[2])(2)});

View File

@ -1,706 +0,0 @@
Verto = function (
tag,
voiceBridge,
conferenceUsername,
userCallback,
onFail = null,
chromeExtension = null,
stunTurnInfo = null,
loadingCallback = null) {
voiceBridge += "-SCREENSHARE";
this.cur_call = null;
this.share_call = null;
this.vertoHandle;
this.vid_width = Math.max(window.screen.width, 1920);
this.vid_height = Math.max(window.screen.height, 1080);
this.outgoingBandwidth = "default";
this.incomingBandwidth = "default";
// this.sessid = $.verto.genUUID();
this.sessid = Math.random().toString();
this.renderTag = 'remote-media';
this.destination_number = voiceBridge;
this.caller_id_name = conferenceUsername;
this.caller_id_number = conferenceUsername;
this.vertoPort = "verto";
this.hostName = window.location.hostname;
this.socketUrl = 'wss://' + this.hostName + '/' + this.vertoPort;
this.login = "bbbuser";
this.password = "secret";
this.useVideo = false;
this.useCamera = false;
this.useMic = false;
this.callWasSuccessful = false;
this.shouldConnect = true;
this.iceServers = stunTurnInfo;
this.userCallback = userCallback;
if (loadingCallback != null) {
this.videoLoadingCallback = Verto.normalizeCallback(loadingCallback);
} else {
this.videoLoadingCallback = function() {};
}
if (chromeExtension != null) {
this.chromeExtension = chromeExtension;
}
if (onFail != null) {
this.onFail = Verto.normalizeCallback(onFail);
} else {
var _this = this;
this.onFail = function () {
_this.logError('Default error handler');
};
}
};
Verto.prototype.logger = function (obj) {
console.log(obj);
};
Verto.prototype.logError = function (obj) {
console.error(obj);
};
Verto.prototype.setRenderTag = function (tag) {
this.renderTag = tag;
};
// receives either a string variable holding the name of an actionscript
// registered callback, or a javascript function object.
// The function will return either the function if it is a javascript Function
// or if it is an actionscript string it will return a javascript Function
// that when invokved will invoke the actionscript registered callback
// and passes along parameters
Verto.normalizeCallback = function (callback) {
if (typeof callback == 'function') {
return callback;
} else {
return function (args) {
document.getElementById('BigBlueButton')[callback](args);
};
}
};
Verto.prototype.onWSLogin = function (v, success) {
this.cur_call = null;
if (success) {
if (!this.shouldConnect) {
return;
}
this.callWasSuccessful = true;
this.mediaCallback();
return;
} else {
// error logging verto into freeswitch
this.logError({ status: 'failed', errorcode: '10XX' });
this.callWasSuccessful = false;
this.onFail();
return;
}
};
Verto.prototype.registerCallbacks = function () {
var callbacks = {
onMessage: function (verto, dialog, msg, data) {
switch (msg) {
case $.verto.enum.message.pvtEvent:
if (data.pvtData) {
switch (data.pvtData.action) {
// This client has joined the live array for the conference.
case "conference-liveArray-join":
initLiveArray(verto, dialog, data);
break;
// This client has left the live array for the conference.
case "conference-liveArray-part":
// Some kind of client-side wrapup...
break;
}
}
break;
}
},
onDialogState: function (d) {},
onWSLogin: this.onWSLogin.bind(this),
onWSClose: function (v, success) {
cur_call = null;
if (this.callWasSuccessful) {
// the connection was dropped in an already established call
this.logError('websocket disconnected');
// WebSocket disconnected
this.logError({ status: 'failed', errorcode: 1001 });
toDisplayDisconnectCallback = false;
} else {
// this callback was triggered and a call was never successfully established
this.logError('websocket connection could not be established');
// Could not make a WebSocket connection
this.logError({ status: 'failed', errorcode: 1002 });
this.onFail();
return;
}
}.bind(this),
};
this.callbacks = callbacks;
};
var initLiveArray = function(verto, dialog, data) {
// Set up addtional configuration specific to the call.
window.vertoConf = new $.verto.conf(verto, {
dialog: dialog,
hasVid: true,
laData: data.pvtData,
// For subscribing to published chat messages.
chatCallback: function(verto, eventObj) {
var from = eventObj.data.fromDisplay || eventObj.data.from || 'Unknown';
var message = eventObj.data.message || '';
},
});
var config = {
subParams: {
callID: dialog ? dialog.callID : null
},
};
// Set up the live array, using the live array data received from FreeSWITCH.
window.liveArray = new $.verto.liveArray(window.vertoHandle, data.pvtData.laChannel, data.pvtData.laName, config);
// Subscribe to live array changes.
window.liveArray.onChange = function(liveArrayObj, args) {
console.log("Call UUID is: " + args.key);
console.log("Call data is: ", args.data);
console.log(liveArrayObj);
console.log(args);
try {
switch (args.action) {
// Initial list of existing conference users.
case "bootObj":
break;
// New user joined conference.
case "add":
break;
// User left conference.
case "del":
break;
// Existing user's state changed (mute/unmute, talking, floor, etc)
case "modify":
break;
}
} catch (err) {
console.error("ERROR: " + err);
}
};
// Called if the live array throws an error.
window.liveArray.onErr = function (obj, args) {
console.error("Error: ", obj, args);
};
};
Verto.prototype.hold = function () {
this.cur_call.toggleHold();
};
Verto.prototype.hangup = function () {
if (this.cur_call) {
// the duration of the call
if (this.cur_call.audioStream) {
this.logger('call ended ' + this.cur_call.audioStream.currentTime);
}
this.cur_call.hangup();
this.cur_call = null;
}
if (this.share_call) {
if (this.share_call.state == $.verto.enum.state.active) {
this.shouldConnect = false;
} else {
this.shouldConnect = true;
}
// the duration of the call
this.logger('call ended ' + this.share_call.audioStream.currentTime);
this.share_call.rtc.localStream.getTracks().forEach(track => track.stop());
this.share_call.hangup();
this.share_call = null;
}
// the user ended the call themself
// if (callPurposefullyEnded === true) {
if (true) {
this.logger({ status: 'ended' });
} else {
// Call ended unexpectedly
this.logError({ status: 'failed', errorcode: 1005 });
}
};
Verto.prototype.mute = function () {
this.cur_call.dtmf('0');
};
Verto.prototype.localmute = function () {
// var muted = cur_call.setMute('toggle');
// if (muted) {
// display('Talking to: ' + cur_call.cidString() + ' [LOCALLY MUTED]');
// } else {
// display('Talking to: ' + cur_call.cidString());
// }
};
Verto.prototype.localvidmute = function () {
// var muted = cur_call.setVideoMute('toggle');
// if (muted) {
// display('Talking to: ' + cur_call.cidString() + ' [VIDEO LOCALLY MUTED]');
// } else {
// display('Talking to: ' + cur_call.cidString());
// }
};
Verto.prototype.vmute = function () {
this.cur_call.dtmf('*0');
};
Verto.prototype.setWatchVideo = function (tag) {
this.mediaCallback = this.docall;
this.useVideo = true;
this.useCamera = 'none';
this.useMic = 'none';
this.create(tag);
};
Verto.prototype.setListenOnly = function (tag) {
this.mediaCallback = this.docall;
this.useVideo = false;
this.useCamera = 'none';
this.useMic = 'none';
this.create(tag);
};
Verto.prototype.setMicrophone = function (tag) {
this.mediaCallback = this.docall;
this.useVideo = false;
this.useCamera = 'none';
this.useMic = 'any';
this.create(tag);
};
Verto.prototype.setScreenShare = function (tag) {
// required for Verto to know we want to use video
// tell Verto we want to share webcam so it knows there will be a video stream
// but instead of a webcam we pass screen constraints
this.useCamera = 'any';
this.useMic = 'none';
this.mediaCallback = this.makeShare;
this.create(tag);
};
Verto.prototype.create = function (tag) {
this.setRenderTag(tag);
this.registerCallbacks();
// fetch ice information from server
if (this.iceServers == null) {
this.configStuns(this.init);
} else {
// already have it. proceed with init
this.init();
}
};
Verto.prototype.docall = function () {
if (this.cur_call) {
this.logger('Quitting: Call already in progress');
return;
}
this.shouldConnect = true;
this.cur_call = window.vertoHandle.newCall({
destination_number: this.destination_number,
caller_id_name: this.caller_id_name,
caller_id_number: this.caller_id_number,
outgoingBandwidth: this.outgoingBandwidth,
incomingBandwidth: this.incomingBandwidth,
useVideo: this.useVideo,
useStereo: true,
useCamera: this.useCamera,
useMic: this.useMic,
useSpeak: 'any',
dedEnc: true,
tag: this.renderTag,
});
this.logger(this.cur_call);
};
Verto.prototype.makeShare = function () {
if (this.share_call) {
this.logError('Quitting: Call already in progress');
return;
}
var screenInfo = null;
if (!!navigator.mozGetUserMedia) {
// no screen parameters for FF, just screenShare: true down below
screenInfo = {};
this.doShare(screenInfo);
} else if (!!window.chrome) {
var _this = this;
if (!_this.chromeExtension) {
_this.logError({
status: 'failed',
message: 'Missing Chrome Extension key',
});
_this.onFail();
return;
}
// bring up Chrome screen picker
getMyScreenConstraints(function (constraints) {
if (constraints == null || constraints == "" || constraints.streamId == null || constraints.streamId == "") {
_this.onFail();
return _this.logError(constraints);
}
screenInfo = {
chromeMediaSource: "desktop",
chromeMediaSourceId: constraints.streamId,
};
_this.logger(screenInfo);
_this.doShare(screenInfo);
}, _this.chromeExtension);
}
};
Verto.prototype.doShare = function (screenConstraints) {
this.shouldConnect = true;
screenConstraints.maxWidth = this.vid_width;
screenConstraints.maxHeight = this.vid_height;
this.share_call = window.vertoHandle.newCall({
destination_number: this.destination_number,
caller_id_name: this.caller_id_name,
caller_id_number: this.caller_id_number,
outgoingBandwidth: "default",
incomingBandwidth: "default",
videoParams: screenConstraints,
useVideo: true,
screenShare: true,
dedEnc: true,
mirrorInput: false,
tag: this.renderTag,
});
var stopSharing = function() {
console.log("stopSharing");
this.share_call.hangup();
this.share_call = null;
};
var _this = this;
// Override onStream callback in $.FSRTC instance
this.share_call.rtc.options.callbacks.onStream = function (rtc, stream) {
_this.videoLoadingCallback();
if (stream) {
var StreamTrack = stream.getVideoTracks()[0];
StreamTrack.addEventListener('ended', stopSharing.bind(_this));
}
};
};
Verto.prototype.init = function () {
this.cur_call = null;
if (!window.vertoHandle) {
window.vertoHandle = new $.verto({
useVideo: true,
login: this.login,
passwd: this.password,
socketUrl: this.socketUrl,
tag: this.renderTag,
ringFile: 'sounds/bell_ring2.wav',
sessid: this.sessid,
videoParams: {
minFrameRate: 15,
vertoBestFrameRate: 30,
},
deviceParams: {
useCamera: false,
useMic: false,
useSpeak: 'none',
},
audioParams: {
googAutoGainControl: false,
googNoiseSuppression: false,
googHighpassFilter: false,
},
iceServers: this.iceServers,
}, this.callbacks);
} else {
this.mediaCallback();
return;
}
};
Verto.prototype.configStuns = function (callback) {
this.logger('Fetching STUN/TURN server info for Verto initialization');
var _this = this;
var stunsConfig = {};
// flash client has api access. html5 user passes array.
// client provided no stuns and cannot make api calls
// use defaults in verto and try making a call
if (BBB.getSessionToken == undefined) {
// uses defaults
this.iceServers = true;
// run init callback
return callback();
}
// TODO: screensharing and audio use this exact same function. Should be
// moved to a shared library for retrieving stun/turn and just pass
// success/fail callbacks
BBB.getSessionToken(function(sessionToken) {
$.ajax({
dataType: 'json',
url: '/bigbluebutton/api/stuns/',
data: {sessionToken},
}).done(function (data) {
_this.logger('ajax request done');
_this.logger(data);
if (data.response && data.response.returncode == 'FAILED') {
_this.logError(data.response.message, { error: true });
_this.logError({ status: 'failed', errorcode: data.response.message });
return;
}
stunsConfig.stunServers = (data.stunServers ? data.stunServers.map(function (data) {
return { url: data.url };
}) : []);
stunsConfig.turnServers = (data.turnServers ? data.turnServers.map(function (data) {
return {
urls: data.url,
username: data.username,
credential: data.password,
};
}) : []);
stunsConfig = stunsConfig.stunServers.concat(stunsConfig.turnServers);
_this.logger('success got stun data, making verto');
_this.iceServers = stunsConfig;
callback.apply(_this);
}).fail(function (data, textStatus, errorThrown) {
_this.logError({ status: 'failed', errorcode: 1009 });
_this.onFail();
return;
});
});
};
// checks whether Google Chrome or Firefox have the WebRTCPeerConnection object
Verto.prototype.isWebRTCAvailable = function () {
return (typeof window.webkitRTCPeerConnection !== 'undefined' ||
typeof window.mozRTCPeerConnection !== 'undefined');
};
this.VertoManager = function () {
this.vertoAudio = null;
this.vertoVideo = null;
this.vertoScreenShare = null;
window.vertoHandle = null;
};
Verto.prototype.logout = function () {
this.exitAudio();
this.exitVideo();
this.exitScreenShare();
window.vertoHandle.logout();
};
VertoManager.prototype.exitAudio = function () {
if (this.vertoAudio != null) {
console.log('Hanging up vertoAudio');
this.vertoAudio.hangup();
}
};
VertoManager.prototype.exitVideo = function () {
if (this.vertoVideo != null) {
console.log('Hanging up vertoVideo');
this.vertoVideo.hangup();
}
};
VertoManager.prototype.exitScreenShare = function () {
if (this.vertoScreenShare != null) {
console.log('Hanging up vertoScreenShare');
this.vertoScreenShare.hangup();
}
};
VertoManager.prototype.joinListenOnly = function (tag) {
this.exitAudio();
if (this.vertoAudio == null) {
var obj = Object.create(Verto.prototype);
Verto.apply(obj, arguments);
this.vertoAudio = obj;
}
this.vertoAudio.setListenOnly(tag);
};
VertoManager.prototype.joinMicrophone = function (tag) {
this.exitAudio();
if (this.vertoAudio == null) {
var obj = Object.create(Verto.prototype);
Verto.apply(obj, arguments);
this.vertoAudio = obj;
}
this.vertoAudio.setMicrophone(tag);
};
VertoManager.prototype.joinWatchVideo = function (tag) {
this.exitVideo();
if (this.vertoVideo == null) {
var obj = Object.create(Verto.prototype);
Verto.apply(obj, arguments);
this.vertoVideo = obj;
}
this.vertoVideo.setWatchVideo(tag);
};
VertoManager.prototype.shareScreen = function (tag) {
this.exitScreenShare();
if (this.vertoScreenShare == null) {
var obj = Object.create(Verto.prototype);
Verto.apply(obj, arguments);
this.vertoScreenShare = obj;
}
this.vertoScreenShare.setScreenShare(tag);
};
window.vertoInitialize = function () {
if (window.vertoManager == null || window.vertoManager == undefined) {
window.vertoManager = new VertoManager();
}
};
window.vertoExitAudio = function () {
window.vertoInitialize();
window.vertoManager.exitAudio();
};
window.vertoExitVideo = function () {
window.vertoInitialize();
window.vertoManager.exitVideo();
};
window.vertoExitScreenShare = function () {
window.vertoInitialize();
window.vertoManager.exitScreenShare();
};
window.vertoJoinListenOnly = function () {
window.vertoInitialize();
window.vertoManager.joinListenOnly.apply(window.vertoManager, arguments);
};
window.vertoJoinMicrophone = function () {
window.vertoInitialize();
window.vertoManager.joinMicrophone.apply(window.vertoManager, arguments);
};
window.vertoWatchVideo = function () {
window.vertoInitialize();
window.vertoManager.joinWatchVideo.apply(window.vertoManager, arguments);
};
window.vertoShareScreen = function () {
window.vertoInitialize();
window.vertoManager.shareScreen.apply(window.vertoManager, arguments);
};
// a function to check whether the browser (Chrome only) is in an isIncognito
// session. Requires 1 mandatory callback that only gets called if the browser
// session is incognito. The callback for not being incognito is optional.
// Attempts to retrieve the chrome filesystem API.
window.checkIfIncognito = function(isIncognito, isNotIncognito = function () {}) {
isIncognito = Verto.normalizeCallback(isIncognito);
isNotIncognito = Verto.normalizeCallback(isNotIncognito);
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
isNotIncognito();
return;
}
fs(window.TEMPORARY, 100, function(){isNotIncognito()}, function(){isIncognito()});
};
window.checkChromeExtInstalled = function (callback, chromeExtensionId) {
callback = Verto.normalizeCallback(callback);
if (typeof chrome === "undefined" || !chrome || !chrome.runtime) {
// No API, so no extension for sure
callback(false);
return;
}
chrome.runtime.sendMessage(
chromeExtensionId,
{ getVersion: true },
function (response) {
if (!response || !response.version) {
// Communication failure - assume that no endpoint exists
callback(false);
return;
}
callback(true);
}
);
}
window.getMyScreenConstraints = function(theCallback, extensionId) {
theCallback = Verto.normalizeCallback(theCallback);
chrome.runtime.sendMessage(extensionId, {
getStream: true,
sources: [
"window",
"screen",
"tab"
]},
function(response) {
console.log(response);
theCallback(response);
});
};

View File

@ -3,7 +3,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 300;
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('fonts/SourceSansPro/SourceSansPro-Light.ttf') format('ttf');
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'),
url('fonts/SourceSansPro/SourceSansPro-Light.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -11,7 +12,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 300;
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('fonts/SourceSansPro/SourceSansPro-Light.ttf') format('ttf');
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'),
url('fonts/SourceSansPro/SourceSansPro-Light.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -19,7 +21,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 300;
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('fonts/SourceSansPro/SourceSansPro-Light.ttf') format('ttf');
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'),
url('fonts/SourceSansPro/SourceSansPro-Light.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -27,7 +30,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/SourceSansPro/SourceSansPro-Regular.ttf') format('ttf');
src: local('Source Sans Pro'), local('SourceSansPro-Regular'),
url('fonts/SourceSansPro/SourceSansPro-Regular.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -35,7 +39,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/SourceSansPro/SourceSansPro-Regular.ttf') format('ttf');
src: local('Source Sans Pro'), local('SourceSansPro-Regular'),
url('fonts/SourceSansPro/SourceSansPro-Regular.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -43,7 +48,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/SourceSansPro/SourceSansPro-Regular.ttf') format('ttf');
src: local('Source Sans Pro'), local('SourceSansPro-Regular'),
url('fonts/SourceSansPro/SourceSansPro-Regular.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -51,7 +57,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('fonts/SourceSansPro/SourceSansPro-Semibold.ttf') format('ttf');
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'),
url('fonts/SourceSansPro/SourceSansPro-Semibold.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -59,7 +66,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('fonts/SourceSansPro/SourceSansPro-Semibold.ttf') format('ttf');
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'),
url('fonts/SourceSansPro/SourceSansPro-Semibold.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -67,7 +75,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('fonts/SourceSansPro/SourceSansPro-Semibold.ttf') format('ttf');
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'),
url('fonts/SourceSansPro/SourceSansPro-Semibold.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -75,7 +84,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('fonts/SourceSansPro/SourceSansPro-Bold.ttf') format('ttf');
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
url('fonts/SourceSansPro/SourceSansPro-Bold.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -83,7 +93,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('fonts/SourceSansPro/SourceSansPro-Bold.ttf') format('ttf');
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
url('fonts/SourceSansPro/SourceSansPro-Bold.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -91,7 +102,8 @@
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('fonts/SourceSansPro/SourceSansPro-Bold.ttf') format('ttf');
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
url('fonts/SourceSansPro/SourceSansPro-Bold.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -99,7 +111,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 300;
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('fonts/SourceSansPro/SourceSansPro-LightItalic.ttf') format('ttf');
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'),
url('fonts/SourceSansPro/SourceSansPro-LightItalic.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -107,7 +120,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 300;
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('fonts/SourceSansPro/SourceSansPro-LightItalic.ttf') format('ttf');
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'),
url('fonts/SourceSansPro/SourceSansPro-LightItalic.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -115,7 +129,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 300;
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('fonts/SourceSansPro/SourceSansPro-LightItalic.ttf') format('ttf');
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'),
url('fonts/SourceSansPro/SourceSansPro-LightItalic.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -123,7 +138,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 400;
src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('fonts/SourceSansPro/SourceSansPro-Italic.ttf') format('ttf');
src: local('Source Sans Pro Italic'), local('SourceSansPro-It'),
url('fonts/SourceSansPro/SourceSansPro-Italic.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -131,7 +147,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 400;
src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('fonts/SourceSansPro/SourceSansPro-Italic.ttf') format('ttf');
src: local('Source Sans Pro Italic'), local('SourceSansPro-It'),
url('fonts/SourceSansPro/SourceSansPro-Italic.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -139,7 +156,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 400;
src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('fonts/SourceSansPro/SourceSansPro-Italic.ttf') format('ttf');
src: local('Source Sans Pro Italic'), local('SourceSansPro-It'),
url('fonts/SourceSansPro/SourceSansPro-Italic.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -147,7 +165,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 600;
src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('fonts/SourceSansPro/SourceSansPro-SemiboldItalic.ttf') format('ttf');
src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'),
url('fonts/SourceSansPro/SourceSansPro-SemiboldItalic.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -155,7 +174,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 600;
src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('fonts/SourceSansPro/SourceSansPro-SemiboldItalic.ttf') format('ttf');
src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'),
url('fonts/SourceSansPro/SourceSansPro-SemiboldItalic.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -163,7 +183,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 600;
src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('fonts/SourceSansPro/SourceSansPro-SemiboldItalic.ttf') format('ttf');
src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'),
url('fonts/SourceSansPro/SourceSansPro-SemiboldItalic.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
/* vietnamese */
@ -171,7 +192,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 700;
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'), url('fonts/SourceSansPro/SourceSansPro-BoldItalic.ttf') format('ttf');
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'),
url('fonts/SourceSansPro/SourceSansPro-BoldItalic.woff') format('woff');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@ -179,7 +201,8 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 700;
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'), url('fonts/SourceSansPro/SourceSansPro-BoldItalic.ttf') format('ttf');
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'),
url('fonts/SourceSansPro/SourceSansPro-BoldItalic.woff') format('woff');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@ -187,6 +210,7 @@
font-family: 'Source Sans Pro';
font-style: italic;
font-weight: 700;
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'), url('fonts/SourceSansPro/SourceSansPro-BoldItalic.ttf') format('ttf');
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'),
url('fonts/SourceSansPro/SourceSansPro-BoldItalic.woff') format('woff');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}

View File

@ -1,5 +1,4 @@
import { check } from 'meteor/check';
import Annotations from '/imports/api/annotations';
const ANNOTATION_TYPE_TEXT = 'text';
const ANNOTATION_TYPE_PENCIL = 'pencil';
@ -83,6 +82,7 @@ function handlePencilUpdate(meetingId, whiteboardId, userId, annotation) {
whiteboardId,
};
let baseModifier;
switch (status) {
case DRAW_START:
// on start we split the points
@ -131,6 +131,8 @@ function handlePencilUpdate(meetingId, whiteboardId, userId, annotation) {
$inc: { version: 1 },
};
break;
default:
break;
}
return { selector: baseSelector, modifier: baseModifier };

View File

@ -8,7 +8,7 @@ export default function addAnnotation(meetingId, whiteboardId, userId, annotatio
check(whiteboardId, String);
check(annotation, Object);
let query = addAnnotationQuery(meetingId, whiteboardId, userId, annotation);
const query = addAnnotationQuery(meetingId, whiteboardId, userId, annotation);
const cb = (err, numChanged) => {
if (err) {
@ -19,8 +19,7 @@ export default function addAnnotation(meetingId, whiteboardId, userId, annotatio
if (insertedId) {
return Logger.info(`Added annotation id=${annotation.id} whiteboard=${whiteboardId}`);
}
return Logger.info(`Upserted annotation id=${annotation.id} whiteboard=${whiteboardId}`);
return true;
};
return Annotations.upsert(query.selector, query.modifier, cb);

View File

@ -10,7 +10,7 @@ function annotations(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing Annotations for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing Annotations for ${meetingId} ${requesterUserId} ${requesterToken}`);
return Annotations.find({ meetingId });
}

View File

@ -1,31 +0,0 @@
import BaseAudioBridge from './base';
export default class VertoBridge extends BaseAudioBridge {
constructor(userData) {
super();
const {
userId,
username,
voiceBridge,
} = userData;
this.voiceBridge = voiceBridge;
this.vertoUsername = `${userId}-bbbID-${username}`;
}
exitAudio(listenOnly) {
window.vertoExitAudio();
}
joinAudio({ isListenOnly }) {
const vertoJoin = isListenOnly ? 'vertoJoinListenOnly' : 'vertoJoinMicrophone';
window[vertoJoin](
'remote-media',
this.voiceBridge,
this.vertoUsername,
null,
);
}
}

View File

@ -7,7 +7,7 @@ function breakouts(credentials, moderator) {
meetingId,
requesterUserId,
} = credentials;
Logger.info(`Publishing Breakouts for ${meetingId} ${requesterUserId}`);
Logger.debug(`Publishing Breakouts for ${meetingId} ${requesterUserId}`);
if (moderator) {
const presenterSelector = {

View File

@ -10,7 +10,7 @@ function captions(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.verbose(`Publishing Captions for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing Captions for ${meetingId} ${requesterUserId} ${requesterToken}`);
return Captions.find({ meetingId });
}

View File

@ -14,7 +14,7 @@ function groupChatMsg(credentials, chatsIds) {
const CHAT_CONFIG = Meteor.settings.public.chat;
const PUBLIC_GROUP_CHAT_ID = CHAT_CONFIG.public_group_id;
Logger.info(`Publishing group-chat-msg for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing group-chat-msg for ${meetingId} ${requesterUserId} ${requesterToken}`);
return GroupChatMsg.find({
$or: [

View File

@ -14,7 +14,7 @@ function groupChat(credentials) {
const CHAT_CONFIG = Meteor.settings.public.chat;
const PUBLIC_CHAT_TYPE = CHAT_CONFIG.type_public;
Logger.info(`Publishing group-chat for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing group-chat for ${meetingId} ${requesterUserId} ${requesterToken}`);
return GroupChat.find({
$or: [

View File

@ -0,0 +1,6 @@
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
const GuestUsers = new Mongo.Collection('guestUsers');
export default GuestUsers;

View File

@ -0,0 +1,6 @@
import RedisPubSub from '/imports/startup/server/redis';
import handleGuestApproved from './handlers/guestApproved';
import handleGuestsWaitingForApproval from './handlers/guestsWaitingForApproval';
RedisPubSub.on('GuestsWaitingForApprovalEvtMsg', handleGuestsWaitingForApproval);
RedisPubSub.on('GuestsWaitingApprovedEvtMsg', handleGuestApproved);

View File

@ -0,0 +1,13 @@
import { check } from 'meteor/check';
import setGuestStatus from '../modifiers/setGuestStatus';
export default function handleGuestsWaitingForApproval({ header, body }, meetingId) {
const { userId } = header;
const { approvedBy, guests } = body;
check(userId, String);
check(meetingId, String);
check(approvedBy, String);
return guests.forEach(guest => setGuestStatus(meetingId, guest.guest, guest.status, approvedBy));
}

View File

@ -0,0 +1,39 @@
import stringHash from 'string-hash';
import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger';
import GuestUsers from '/imports/api/guest-users/';
const COLOR_LIST = [
'#7b1fa2', '#6a1b9a', '#4a148c', '#5e35b1', '#512da8', '#4527a0',
'#311b92', '#3949ab', '#303f9f', '#283593', '#1a237e', '#1976d2', '#1565c0',
'#0d47a1', '#0277bd', '#01579b',
];
export default function handleGuestsWaitingForApproval({ body }, meetingId) {
const { guests } = body;
check(guests, Array);
const cb = (err, numChanged) => {
if (err) {
return Logger.error(`Adding guest user to collection: ${err}`);
}
const { insertedId } = numChanged;
if (insertedId) {
return Logger.info(`Added guest user meeting=${meetingId}`);
}
return Logger.info(`Upserted guest user meeting=${meetingId}`);
};
return guests.map(guest => GuestUsers.upsert({
meetingId,
intId: guest.intId,
}, {
approved: false,
denied: false,
...guest,
meetingId,
loginTime: new Date().getTime(),
color: COLOR_LIST[stringHash(guest.intId) % COLOR_LIST.length],
}, cb));
}

View File

@ -0,0 +1,3 @@
import './eventHandlers';
import './methods';
import './publishers';

View File

@ -0,0 +1,6 @@
import { Meteor } from 'meteor/meteor';
import allowPendingUsers from '/imports/api/guest-users/server/methods/allowPendingUsers';
Meteor.methods({
allowPendingUsers,
});

View File

@ -0,0 +1,32 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import RedisPubSub from '/imports/startup/server/redis';
import Logger from '/imports/startup/server/logger';
const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'GuestsWaitingApprovedMsg';
export default function allowPendingUsers(credentials, guests, status) {
const {
meetingId,
requesterUserId,
requesterToken,
} = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
check(guests, Array);
const mappedGuests = guests.map(guest => ({ status, guest: guest.intId }));
const payload = {
approvedBy: requesterUserId,
guests: mappedGuests,
};
Logger.info(`User=${requesterUserId} ${status} guests ${JSON.stringify(mappedGuests)}`);
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}

View File

@ -0,0 +1,33 @@
import { check } from 'meteor/check';
import GuestUsers from '/imports/api/guest-users';
import Logger from '/imports/startup/server/logger';
const GUEST_STATUS_ALLOW = 'ALLOW';
const GUEST_STATUS_DENY = 'DENY';
export default function setGuestStatus(meetingId, intId, status, approvedBy = null) {
check(meetingId, String);
check(intId, String);
check(status, String);
const selector = {
meetingId,
intId,
};
const modifier = {
$set: {
approved: status === GUEST_STATUS_ALLOW,
denied: status === GUEST_STATUS_DENY,
approvedBy,
},
};
const cb = (err) => {
if (err) {
return Logger.error(`Updating status=${status} user=${intId}: ${err}`);
}
return Logger.info(`Updated status=${status} user=${intId} meeting=${meetingId}`);
};
return GuestUsers.update(selector, modifier, cb);
}

View File

@ -0,0 +1,23 @@
import GuestUsers from '/imports/api/guest-users/';
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger';
function guestUsers(credentials) {
const { meetingId, requesterUserId, requesterToken } = credentials;
check(meetingId, String);
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing Slides for ${meetingId} ${requesterUserId} ${requesterToken}`);
return GuestUsers.find({ meetingId });
}
function publish(...args) {
const boundSlides = guestUsers.bind(this);
return boundSlides(...args);
}
Meteor.publish('guestUser', publish);

View File

@ -22,13 +22,13 @@ const logClient = function (type, log, fullInfo = {}) {
if (typeof log === 'string' || log instanceof String) {
Logger.log({
level: type,
message: `${topic || 'CLIENT'} LOG: ${log}\n`,
message: `${topic || 'CLIENT'} LOG: ${log} `,
meta: logContents,
});
} else {
Logger.log({
level: type,
message: `${topic || 'CLIENT'} LOG: ${JSON.stringify(log)}\n`,
message: `${topic || 'CLIENT'} LOG: ${JSON.stringify(log)} `,
meta: logContents,
});
}

View File

@ -46,7 +46,7 @@ export default function addMeeting(meeting) {
recordProp: Match.ObjectIncluding({
allowStartStopRecording: Boolean,
autoStartRecording: Boolean,
record: Boolean
record: Boolean,
}),
password: {
viewerPass: String,
@ -66,6 +66,8 @@ export default function addMeeting(meeting) {
metadataProp: Object,
});
const newMeeting = meeting;
const selector = {
meetingId,
};
@ -81,10 +83,26 @@ export default function addMeeting(meeting) {
setBy: 'temp',
};
newMeeting.welcomeProp.welcomeMsg = newMeeting.welcomeProp.welcomeMsg.replace(
'href="event:',
'href="',
);
const insertBlankTarget = (s, i) => `${s.substr(0, i)} target="_blank"${s.substr(i)}`;
const linkWithoutTarget = new RegExp('<a href="(.*?)">', 'g');
linkWithoutTarget.test(newMeeting.welcomeProp.welcomeMsg);
if (linkWithoutTarget.lastIndex > 0) {
newMeeting.welcomeProp.welcomeMsg = insertBlankTarget(
newMeeting.welcomeProp.welcomeMsg,
linkWithoutTarget.lastIndex - 1,
);
}
const modifier = {
$set: Object.assign(
{ meetingId },
flat(meeting, { safe: true }),
flat(newMeeting, { safe: true }),
{ lockSettingsProp },
),
};

View File

@ -10,13 +10,15 @@ function meetings(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing meeting =${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing meeting =${meetingId} ${requesterUserId} ${requesterToken}`);
const selector = {
$or: [
{ meetingId },
{ 'meetingProp.isBreakout': true },
{ 'breakoutProps.parentId': meetingId },
{
'meetingProp.isBreakout': true,
'breakoutProps.parentId': meetingId,
},
],
};
@ -35,4 +37,3 @@ function publish(...args) {
}
Meteor.publish('meetings', publish);

View File

@ -27,9 +27,8 @@ export default function userResponded({ body }) {
return Logger.error(`Updating Poll responses: ${err}`);
}
return Logger.info(`Updating Poll response (userId: ${userId},
response: ${answerId},
pollId: ${pollId})`);
return Logger.info(`Updating Poll response (userId: ${userId},`
+ `response: ${answerId}, pollId: ${pollId})`);
};
return Polls.update(selector, modifier, cb);

View File

@ -51,8 +51,8 @@ export default function publishVote(credentials, id, pollAnswerId) { // TODO dis
return Logger.error(`Updating Polls collection: ${err}`);
}
return Logger.info(`Updating Polls collection (meetingId: ${meetingId},
pollId: ${currentPoll.id}!)`);
return Logger.info(`Updating Polls collection (meetingId: ${meetingId}, `
+ `pollId: ${currentPoll.id}!)`);
};
Polls.update(selector, modifier, cb);

View File

@ -20,6 +20,7 @@ export default function addPoll(meetingId, requesterId, poll) {
const userSelector = {
meetingId,
userId: { $ne: requesterId },
clientType: { $ne: 'dial-in-user' },
};
const userIds = Users.find(userSelector)

View File

@ -10,7 +10,7 @@ Meteor.publish('current-poll', (meetingId) => {
meetingId,
};
Logger.info(`Publishing poll for meeting=${meetingId}`);
Logger.debug(`Publishing poll for meeting=${meetingId}`);
return Polls.find(selector);
});
@ -23,7 +23,7 @@ function polls(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing polls =${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing polls =${meetingId} ${requesterUserId} ${requesterToken}`);
const selector = {
meetingId,
@ -39,4 +39,3 @@ function publish(...args) {
}
Meteor.publish('polls', publish);

View File

@ -10,7 +10,7 @@ function presentationPods(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing presentation-pods for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing presentation-pods for ${meetingId} ${requesterUserId} ${requesterToken}`);
return PresentationPods.find({ meetingId });
}

View File

@ -19,7 +19,7 @@ Meteor.publish('presentation-upload-token', (credentials, podId, filename) => {
filename,
};
Logger.info(`Publishing PresentationUploadToken for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing PresentationUploadToken for ${meetingId} ${requesterUserId} ${requesterToken}`);
return PresentationUploadToken.find(selector);
});

View File

@ -82,7 +82,7 @@ export default function handlePresentationConversionUpdate({ body }, meetingId)
return Logger.info(`Updated presentation conversion status=${status} id=${presentationId} meeting=${meetingId}`);
}
return Logger.info(`Upserted presentation conversion status=${status} id=${presentationId} meeting=${meetingId}`);
return Logger.debug(`Upserted presentation conversion status=${status} id=${presentationId} meeting=${meetingId}`);
};
return Presentations.upsert(selector, modifier, cb);

View File

@ -10,7 +10,7 @@ function presentations(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing Presentations for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing Presentations for ${meetingId} ${requesterUserId} ${requesterToken}`);
return Presentations.find({ meetingId });
}

View File

@ -1,7 +1,5 @@
import VertoBridge from './verto';
import KurentoBridge from './kurento';
//const screenshareBridge = new VertoBridge();
const screenshareBridge = new KurentoBridge();
export default screenshareBridge;

View File

@ -1,7 +1,5 @@
import Meetings from '/imports/api/meetings';
// TODO - we currently add "-SCREENSHARE" in the verto_extension.js library
// Therefore we only pass the voiceConf here, not the full screenshareConf
const getConferenceBridge = () => Meetings.findOne().voiceProp.voiceConf;
export default {

View File

@ -1,26 +0,0 @@
import Users from '/imports/api/users';
import Auth from '/imports/ui/services/auth';
import BridgeService from './service';
const createVertoUserName = () => {
const userId = Auth.userID;
const uName = Users.findOne({ userId }).user.name;
return `FreeSWITCH User - ${encodeURIComponent(uName)}`;
};
export default class VertoScreenshareBridge {
vertoWatchVideo() {
window.vertoWatchVideo(
'screenshareVideo',
BridgeService.getConferenceBridge(),
createVertoUserName(),
null,
null,
null,
);
}
vertoExitVideo() {
window.vertoExitVideo();
}
}

View File

@ -9,7 +9,7 @@ function screenshare(credentials) {
check(meetingId, String);
check(requesterUserId, String);
Logger.info(`Publishing Screenshare for ${meetingId} ${requesterUserId}`);
Logger.debug(`Publishing Screenshare for ${meetingId} ${requesterUserId}`);
return Screenshare.find({ meetingId });
}

View File

@ -56,7 +56,7 @@ export default function resizeSlide(meetingId, slide) {
}
if (numChanged) {
return Logger.info(`Resized slide id=${pageId}`);
return Logger.debug(`Resized slide id=${pageId}`);
}
return Logger.info(`No slide found with id=${pageId}`);

View File

@ -10,7 +10,7 @@ function slides(credentials) {
check(requesterUserId, String);
check(requesterToken, String);
Logger.info(`Publishing Slides for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing Slides for ${meetingId} ${requesterUserId} ${requesterToken}`);
return Slides.find({ meetingId });
}

View File

@ -9,7 +9,7 @@ function userSettings(credentials) {
check(meetingId, String);
check(requesterUserId, String);
Logger.info(`Publishing user settings for user=${requesterUserId}`);
Logger.debug(`Publishing user settings for user=${requesterUserId}`);
return UserSettings.find({ meetingId, userId: requesterUserId });
}

View File

@ -5,10 +5,9 @@ import handleValidateAuthToken from './handlers/validateAuthToken';
import handlePresenterAssigned from './handlers/presenterAssigned';
import handleEmojiStatus from './handlers/emojiStatus';
import handleGetUsers from './handlers/getUsers';
import handleGuestsWaitingForApproval from './handlers/guestsWaitingForApproval';
import handleGuestApproved from './handlers/guestApproved';
import handleUserEjected from './handlers/userEjected';
import handleChangeRole from './handlers/changeRole';
import handleUserInactivityInspect from './handlers/userInactivityInspect';
RedisPubSub.on('PresenterAssignedEvtMsg', handlePresenterAssigned);
RedisPubSub.on('UserJoinedMeetingEvtMsg', handleUserJoined);
@ -16,7 +15,6 @@ RedisPubSub.on('UserLeftMeetingEvtMsg', handleRemoveUser);
RedisPubSub.on('ValidateAuthTokenRespMsg', handleValidateAuthToken);
RedisPubSub.on('UserEmojiChangedEvtMsg', handleEmojiStatus);
RedisPubSub.on('SyncGetUsersMeetingRespMsg', handleGetUsers);
RedisPubSub.on('GuestsWaitingForApprovalEvtMsg', handleGuestsWaitingForApproval);
RedisPubSub.on('GuestsWaitingApprovedEvtMsg', handleGuestApproved);
RedisPubSub.on('UserEjectedFromMeetingEvtMsg', handleUserEjected);
RedisPubSub.on('UserRoleChangedEvtMsg', handleChangeRole);
RedisPubSub.on('UserInactivityInspectMsg', handleUserInactivityInspect);

View File

@ -1,29 +0,0 @@
import { check } from 'meteor/check';
import Users from '/imports/api/users';
import setApprovedStatus from '../modifiers/setApprovedStatus';
import userJoin from '../methods/userJoin';
export default function handleGuestsWaitingForApproval({ header, body }, meetingId) {
const { userId } = header;
const { status, approvedBy } = body;
check(userId, String);
check(meetingId, String);
check(status, String);
check(approvedBy, String);
const selector = {
meetingId,
userId,
};
const User = Users.findOne(selector);
const GUEST_STATUS_ALLOW = 'ALLOW';
const approved = GUEST_STATUS_ALLOW === status;
if (User && approved) {
userJoin(meetingId, userId, User.authToken);
}
return setApprovedStatus(meetingId, userId, approved, approvedBy);
}

View File

@ -1,11 +0,0 @@
import { check } from 'meteor/check';
import setApprovedStatus from '../modifiers/setApprovedStatus';
export default function handleGuestsWaitingForApproval({ body }, meetingId) {
const { guests } = body;
check(guests, Array);
return guests.map(guest => setApprovedStatus(meetingId, guest.intId, false));
}

View File

@ -0,0 +1,14 @@
import { check } from 'meteor/check';
import userInactivityInspect from '../modifiers/userInactivityInspect';
export default function handleUserInactivityInspect({ header, body }, meetingId) {
const { userId } = header;
const { responseDelay } = body;
check(userId, String);
check(responseDelay, Match.Integer);
check(meetingId, String);
return userInactivityInspect(userId, responseDelay);
}

View File

@ -41,6 +41,7 @@ export default function handleValidateAuthToken({ body }, meetingId) {
validated: valid,
approved: !waitForApproval,
loginTime: Date.now(),
inactivityCheck: false,
},
};

View File

@ -5,6 +5,7 @@ import assignPresenter from './methods/assignPresenter';
import changeRole from './methods/changeRole';
import removeUser from './methods/removeUser';
import toggleUserLock from './methods/toggleUserLock';
import userActivitySign from './methods/userActivitySign';
Meteor.methods({
setEmojiStatus,
@ -13,4 +14,5 @@ Meteor.methods({
removeUser,
validateAuthToken,
toggleUserLock,
userActivitySign,
});

View File

@ -0,0 +1,36 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import Users from '/imports/api/users';
import RedisPubSub from '/imports/startup/server/redis';
import Logger from '/imports/startup/server/logger';
export default function userActivitySign(credentials) {
const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'UserActivitySignCmdMsg';
const { meetingId, requesterUserId: userId } = credentials;
check(meetingId, String);
check(userId, String);
const payload = {
userId,
};
const selector = {
userId,
};
const modifier = {
$set: {
inactivityCheck: false,
},
};
Users.update(selector, modifier);
Logger.info(`User ${userId} sent a activity sign for meeting ${meetingId}`);
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, userId, payload);
}

View File

@ -9,7 +9,6 @@ import flat from 'flat';
import addVoiceUser from '/imports/api/voice-users/server/modifiers/addVoiceUser';
import changeRole from '/imports/api/users/server/modifiers/changeRole';
import setApprovedStatus from '/imports/api/users/server/modifiers/setApprovedStatus';
const COLOR_LIST = [
'#7b1fa2', '#6a1b9a', '#4a148c', '#5e35b1', '#512da8', '#4527a0',
@ -50,7 +49,6 @@ export default function addUser(meetingId, user) {
const ROLE_VIEWER = USER_CONFIG.role_viewer;
const APP_CONFIG = Meteor.settings.public.app;
const ALLOW_HTML5_MODERATOR = APP_CONFIG.allowHTML5Moderator;
const GUEST_ALWAYS_ACCEPT = 'ALWAYS_ACCEPT';
const Meeting = Meetings.findOne({ meetingId });
// override moderator status of html5 client users, depending on a system flag
@ -58,10 +56,10 @@ export default function addUser(meetingId, user) {
let userRole = user.role;
if (
dummyUser &&
dummyUser.clientType === 'HTML5' &&
userRole === ROLE_MODERATOR &&
!ALLOW_HTML5_MODERATOR
dummyUser
&& dummyUser.clientType === 'HTML5'
&& userRole === ROLE_MODERATOR
&& !ALLOW_HTML5_MODERATOR
) {
userRole = ROLE_VIEWER;
}
@ -82,6 +80,8 @@ export default function addUser(meetingId, user) {
isBreakoutUser: Meeting.meetingProp.isBreakout,
parentId: Meeting.breakoutProps.parentId,
},
inactivityCheck: false,
responseDelay: 0,
},
flat(user),
),
@ -116,10 +116,6 @@ export default function addUser(meetingId, user) {
changeRole(ROLE_MODERATOR, true, userId, meetingId);
}
if (Meeting.usersProp.guestPolicy === GUEST_ALWAYS_ACCEPT) {
setApprovedStatus(meetingId, userId, true);
}
const { insertedId } = numChanged;
if (insertedId) {
return Logger.info(`Added user id=${userId} meeting=${meetingId}`);

View File

@ -1,31 +0,0 @@
import { check } from 'meteor/check';
import Users from '/imports/api/users';
import Logger from '/imports/startup/server/logger';
export default function setApprovedStatus(meetingId, userId, approved = false, approvedBy = null) {
check(meetingId, String);
check(userId, String);
check(approved, Boolean);
const selector = {
meetingId,
userId,
};
const modifier = {
$set: {
approved,
approvedBy,
},
};
const cb = (err) => {
if (err) {
return Logger.error(`Updating approved status user=${userId}: ${err}`);
}
return Logger.info(`Updated approved status user=${userId} approved=${approved} meeting=${meetingId}`);
};
return Users.update(selector, modifier, cb);
}

View File

@ -0,0 +1,34 @@
import { check } from 'meteor/check';
import Logger from '/imports/startup/server/logger';
import Users from '/imports/api/users';
export default function userInactivityInspect(userId, responseDelay) {
check(userId, String);
check(responseDelay, Match.Integer);
const selector = {
userId,
inactivityCheck: false,
};
const modifier = {
$set: {
inactivityCheck: true,
responseDelay,
},
};
const cb = (err, numChanged) => {
if (err) {
return Logger.error(`Inactivity check for user ${userId}: ${err}`);
}
if (numChanged) {
return Logger.info(`Updated user ${userId} with inactivity inspect`);
}
return null;
};
return Users.update(selector, modifier, cb);
}

View File

@ -70,7 +70,7 @@ function users(credentials, isModerator = false) {
},
};
Logger.info(`Publishing Users for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing Users for ${meetingId} ${requesterUserId} ${requesterToken}`);
return Users.find(selector, options);
}

View File

@ -9,7 +9,7 @@ function voiceUser(credentials) {
check(meetingId, String);
check(requesterUserId, String);
Logger.info(`Publishing Voice User for ${meetingId} ${requesterUserId}`);
Logger.debug(`Publishing Voice User for ${meetingId} ${requesterUserId}`);
return VoiceUsers.find({ meetingId });
}

View File

@ -8,7 +8,7 @@ function whiteboardMultiUser(credentials) {
check(meetingId, String);
Logger.info(`Publishing whiteboard-multi-user for ${meetingId} ${requesterUserId} ${requesterToken}`);
Logger.debug(`Publishing whiteboard-multi-user for ${meetingId} ${requesterUserId} ${requesterToken}`);
return WhiteboardMultiUser.find({ meetingId });
}

View File

@ -57,9 +57,14 @@ class Base extends Component {
meetingExist,
animations,
meteorIsConnected,
subscriptionsReady,
} = this.props;
const { loading, meetingExisted } = this.state;
if (!prevProps.subscriptionsReady && subscriptionsReady) {
logger.info({ logCode: 'startup_client_subscriptions_ready' }, 'Subscriptions are ready');
}
if (!prevProps.meetingExist && meetingExist) {
Session.set('isMeetingEnded', false);
}
@ -127,11 +132,6 @@ class Base extends Component {
return (<LoadingScreen>{loading}</LoadingScreen>);
}
// this.props.annotationsHandler.stop();
if (subscriptionsReady) {
logger.info({ logCode: 'startup_client_subscriptions_ready' }, 'Subscriptions are ready');
}
return (<AppContainer {...this.props} baseControls={stateControls} />);
}
@ -159,7 +159,7 @@ Base.defaultProps = defaultProps;
const SUBSCRIPTIONS_NAME = [
'users', 'meetings', 'polls', 'presentations',
'slides', 'captions', 'voiceUsers', 'whiteboard-multi-user', 'screenshare',
'group-chat', 'presentation-pods', 'users-settings',
'group-chat', 'presentation-pods', 'users-settings', 'guestUser',
];
const BaseContainer = withTracker(() => {

View File

@ -13,6 +13,7 @@ import en from 'react-intl/locale-data/en';
import es from 'react-intl/locale-data/es';
import fa from 'react-intl/locale-data/fa';
import fr from 'react-intl/locale-data/fr';
import he from 'react-intl/locale-data/he';
import id from 'react-intl/locale-data/id';
import it from 'react-intl/locale-data/it';
import ja from 'react-intl/locale-data/ja';
@ -34,6 +35,7 @@ addLocaleData([
...es,
...fa,
...fr,
...he,
...id,
...it,
...ja,

View File

@ -30,8 +30,9 @@ WebApp.connectHandlers.use('/locale', (req, res) => {
const usableLocales = AVAILABLE_LOCALES
.map(file => file.replace('.json', ''))
.reduce((locales, locale) =>
(locale.match(browserLocale[0]) ? [...locales, locale] : locales), []);
.reduce((locales, locale) => (locale.match(browserLocale[0])
? [...locales, locale]
: locales), []);
const regionDefault = usableLocales.find(locale => browserLocale[0] === locale);
@ -52,8 +53,8 @@ WebApp.connectHandlers.use('/locale', (req, res) => {
messages = Object.assign(messages, JSON.parse(data));
normalizedLocale = locale;
} catch (e) {
Logger.error(`'Could not process locale ${locale}:${e}`);
// Getting here means the locale is not available on the files.
Logger.warn(`'Could not process locale ${locale}:${e}`);
// Getting here means the locale is not available in the current locale files.
}
});
@ -72,8 +73,7 @@ WebApp.connectHandlers.use('/locales', (req, res) => {
name: Langmap[locale].nativeName,
}));
} catch (e) {
Logger.error(`'Could not process locales error: ${e}`);
// Getting here means the locale is not available on the files.
Logger.warn(`'Could not process locales error: ${e}`);
}
res.setHeader('Content-Type', 'application/json');

View File

@ -1,7 +1,7 @@
import _ from 'lodash';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, intlShape } from 'react-intl';
import { defineMessages, intlShape } from 'react-intl';
import Button from '/imports/ui/components/button/component';
import Dropdown from '/imports/ui/components/dropdown/component';
import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
@ -315,4 +315,4 @@ class ActionsDropdown extends Component {
ActionsDropdown.propTypes = propTypes;
export default withShortcutHelper(withModalMounter(injectIntl(ActionsDropdown)), 'openActions');
export default withShortcutHelper(withModalMounter(ActionsDropdown), 'openActions');

View File

@ -3,6 +3,7 @@ import cx from 'classnames';
import { styles } from './styles.scss';
import DesktopShare from './desktop-share/component';
import ActionsDropdown from './actions-dropdown/component';
import QuickPollDropdown from './quick-poll-dropdown/component';
import AudioControlsContainer from '../audio/audio-controls/container';
import JoinVideoOptionsContainer from '../video-provider/video-button/container';
@ -33,6 +34,9 @@ class ActionsBar extends React.PureComponent {
sendInvitation,
getBreakouts,
handleTakePresenter,
intl,
currentSlidHasContent,
parseCurrentSlideContent,
isSharingVideo,
} = this.props;
@ -68,9 +72,18 @@ class ActionsBar extends React.PureComponent {
sendInvitation,
getBreakouts,
handleTakePresenter,
intl,
isSharingVideo,
}}
/>
<QuickPollDropdown
{...{
currentSlidHasContent,
intl,
isUserPresenter,
parseCurrentSlideContent,
}}
/>
</div>
<div
className={
@ -96,7 +109,7 @@ class ActionsBar extends React.PureComponent {
/>
</div>
<div className={styles.right}>
{ isLayoutSwapped
{isLayoutSwapped
? (
<PresentationOptionsContainer
toggleSwapLayout={toggleSwapLayout}

View File

@ -1,8 +1,10 @@
import React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import { injectIntl } from 'react-intl';
import getFromUserSettings from '/imports/ui/services/users-settings';
import Meetings from '/imports/api/meetings';
import Auth from '/imports/ui/services/auth';
import PresentationService from '/imports/ui/components/presentation/service';
import ActionsBar from './component';
import Service from './service';
import VideoService from '../video-provider/service';
@ -49,6 +51,8 @@ export default withTracker(() => {
getBreakouts: Service.getBreakouts,
getUsersNotAssigned: Service.getUsersNotAssigned,
handleTakePresenter: Service.takePresenterRole,
currentSlidHasContent: PresentationService.currentSlidHasContent(),
parseCurrentSlideContent: PresentationService.parseCurrentSlideContent,
isSharingVideo: Service.isSharingVideo(),
};
})(ActionsBarContainer);
})(injectIntl(ActionsBarContainer));

View File

@ -136,12 +136,13 @@ class BreakoutRoom extends Component {
this.renderTitle = this.renderTitle.bind(this);
this.handleDismiss = this.handleDismiss.bind(this);
this.setInvitationConfig = this.setInvitationConfig.bind(this);
this.blurDurationTime = this.blurDurationTime.bind(this);
this.state = {
numberOfRooms: MIN_BREAKOUT_ROOMS,
seletedId: '',
users: [],
durationTime: 1,
durationTime: 15,
freeJoin: false,
formFillLevel: 1,
roomSelected: 0,
@ -301,6 +302,10 @@ class BreakoutRoom extends Component {
this.setState({ durationTime: Number.parseInt(event.target.value, 10) || '' });
}
blurDurationTime(event) {
this.setState({ durationTime: Number.parseInt(event.target.value, 10) || 1 });
}
changeNumberOfRooms(event) {
this.setState({ numberOfRooms: Number.parseInt(event.target.value, 10) });
}
@ -389,9 +394,10 @@ class BreakoutRoom extends Component {
<input
type="number"
className={styles.duration}
min={MIN_BREAKOUT_ROOMS}
min="1"
value={durationTime}
onChange={this.changeDurationTime}
onBlur={this.blurDurationTime}
aria-label={intl.formatMessage(intlMessages.duration)}
/>
<HoldButton

View File

@ -0,0 +1,107 @@
import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, intlShape } from 'react-intl';
import _ from 'lodash';
import { makeCall } from '/imports/ui/services/api';
import Button from '/imports/ui/components/button/component';
import Dropdown from '/imports/ui/components/dropdown/component';
import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
import DropdownContent from '/imports/ui/components/dropdown/content/component';
import DropdownList from '/imports/ui/components/dropdown/list/component';
import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
import { styles } from '../styles';
const intlMessages = defineMessages({
quickPollLabel: {
id: 'app.poll.quickPollTitle',
description: 'Quick poll button title',
},
trueOptionLabel: {
id: 'app.poll.t',
description: 'Poll true option value',
},
falseOptionLabel: {
id: 'app.poll.f',
description: 'Poll false option value',
},
yesOptionLabel: {
id: 'app.poll.y',
description: 'Poll yes option value',
},
noOptionLabel: {
id: 'app.poll.n',
description: 'Poll no option value',
},
});
const propTypes = {
intl: intlShape.isRequired,
parseCurrentSlideContent: PropTypes.func.isRequired,
isUserPresenter: PropTypes.bool.isRequired,
};
const handleClickQuickPoll = (slideId, poll) => {
const { type } = poll;
Session.set('openPanel', 'poll');
Session.set('forcePollOpen', true);
makeCall('startPoll', type, slideId);
};
const getAvailableQuickPolls = (slideId, parsedSlides) => parsedSlides.map((poll) => {
const { poll: label, type } = poll;
let itemLabel = label;
if (type !== 'YN' && type !== 'TF') {
const { options } = itemLabel;
itemLabel = options.join('/').replace(/[\n.)]/g, '');
}
return (
<DropdownListItem
label={itemLabel}
key={_.uniqueId('quick-poll-item')}
onClick={() => handleClickQuickPoll(slideId, poll)}
/>);
});
const QuickPollDropdown = (props) => {
const { isUserPresenter, intl, parseCurrentSlideContent } = props;
const parsedSlide = parseCurrentSlideContent(
intl.formatMessage(intlMessages.yesOptionLabel),
intl.formatMessage(intlMessages.noOptionLabel),
intl.formatMessage(intlMessages.trueOptionLabel),
intl.formatMessage(intlMessages.falseOptionLabel),
);
const { slideId, quickPollOptions } = parsedSlide;
return isUserPresenter && quickPollOptions && quickPollOptions.length ? (
<Dropdown>
<DropdownTrigger tabIndex={0}>
<Button
aria-label={intl.formatMessage(intlMessages.quickPollLabel)}
circle
className={styles.button}
color="primary"
hideLabel
icon="polling"
label={intl.formatMessage(intlMessages.quickPollLabel)}
onClick={() => null}
size="lg"
/>
</DropdownTrigger>
<DropdownContent placement="top left">
<DropdownList>
{getAvailableQuickPolls(slideId, quickPollOptions)}
</DropdownList>
</DropdownContent>
</Dropdown>
) : null;
};
QuickPollDropdown.propTypes = propTypes;
export default QuickPollDropdown;

View File

@ -26,7 +26,7 @@ const filterUsersNotAssigned = filterBreakoutUsers(currentBreakoutUsers);
const mapUsersToNotAssined = mapFunction => users => users.map(mapFunction);
const flatUsersArray = usersArray => usersArray.reduce((acc, users) => [...acc, users], []);
const flatUsersArray = usersArray => usersArray.reduce((acc, users) => [...acc, ...users], []);
/*
The concept of pipe is simple

View File

@ -0,0 +1,104 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, intlShape } from 'react-intl';
import Button from '/imports/ui/components/button/component';
import Modal from '/imports/ui/components/modal/simple/component';
import { makeCall } from '/imports/ui/services/api';
import { styles } from './styles';
const propTypes = {
intl: intlShape.isRequired,
responseDelay: PropTypes.number.isRequired,
};
const intlMessages = defineMessages({
activityCheckTitle: {
id: 'app.user.activityCheck',
description: 'Title for activity check modal',
},
activityCheckLabel: {
id: 'app.user.activityCheck.label',
description: 'Label for activity check modal',
},
activityCheckButton: {
id: 'app.user.activityCheck.check',
description: 'Check button for activity modal',
},
});
const handleInactivityDismiss = () => makeCall('userActivitySign');
class ActivityCheck extends Component {
constructor(props) {
super(props);
const { responseDelay } = this.props;
this.state = ({
responseDelay,
});
this.stopRemainingTime = this.stopRemainingTime.bind(this);
this.updateRemainingTime = this.updateRemainingTime.bind(this);
}
componentDidMount() {
this.interval = this.updateRemainingTime();
}
componentDidUpdate() {
this.stopRemainingTime();
this.interval = this.updateRemainingTime();
}
componentWillUnmount() {
this.stopRemainingTime();
}
updateRemainingTime() {
const { responseDelay } = this.state;
return setInterval(() => {
const remainingTime = responseDelay - 1;
this.setState({
responseDelay: remainingTime,
});
}, 1000);
}
stopRemainingTime() {
clearInterval(this.interval);
}
render() {
const { intl } = this.props;
const { responseDelay } = this.state;
return (
<Modal
hideBorder
shouldCloseOnOverlayClick={false}
shouldShowCloseButton={false}
>
<div className={styles.activityModalContent}>
<h1>{intl.formatMessage(intlMessages.activityCheckTitle)}</h1>
<p>{intl.formatMessage(intlMessages.activityCheckLabel, { 0: responseDelay })}</p>
<Button
color="primary"
label={intl.formatMessage(intlMessages.activityCheckButton)}
onClick={handleInactivityDismiss}
role="button"
size="lg"
/>
</div>
</Modal>
);
}
}
ActivityCheck.propTypes = propTypes;
export default ActivityCheck;

View File

@ -0,0 +1,7 @@
import React from 'react';
import { injectIntl } from 'react-intl';
import ActivityCheck from './component';
const ActivityCheckContainer = props => <ActivityCheck {...props} />;
export default injectIntl(ActivityCheckContainer);

View File

@ -0,0 +1,18 @@
@import "/imports/ui/stylesheets/variables/_all";
.activityModalContent {
flex-direction: column;
flex-grow: 1;
display: flex;
justify-content: center;
padding: 0;
margin-top: auto;
margin-bottom: auto;
padding: 0.5rem;
text-align: center;
p {
font-size: var(--font-size-large);
margin: 0.5em 0;
}
}

View File

@ -7,11 +7,13 @@ import browser from 'browser-detect';
import PanelManager from '/imports/ui/components/panel-manager/component';
import PollingContainer from '/imports/ui/components/polling/container';
import logger from '/imports/startup/client/logger';
import ActivityCheckContainer from '/imports/ui/components/activity-check/container';
import ToastContainer from '../toast/container';
import ModalContainer from '../modal/container';
import NotificationsBarContainer from '../notifications-bar/container';
import AudioContainer from '../audio/container';
import ChatAlertContainer from '../chat/alert/container';
import WaitingNotifierContainer from '/imports/ui/components/waiting-users/alert/container';
import { styles } from './styles';
const MOBILE_MEDIA = 'only screen and (max-width: 40em)';
@ -192,6 +194,18 @@ class App extends Component {
);
}
renderActivityCheck() {
const { User } = this.props;
const { inactivityCheck, responseDelay } = User;
return (inactivityCheck ? (
<ActivityCheckContainer
inactivityCheck={inactivityCheck}
responseDelay={responseDelay}
/>) : null);
}
render() {
const {
customStyle, customStyleUrl, openPanel,
@ -199,6 +213,7 @@ class App extends Component {
return (
<main className={styles.main}>
{this.renderActivityCheck()}
<NotificationsBarContainer />
<section className={styles.wrapper}>
<div className={openPanel ? styles.content : styles.noPanelContent}>
@ -214,6 +229,7 @@ class App extends Component {
<AudioContainer />
<ToastContainer />
<ChatAlertContainer />
<WaitingNotifierContainer />
{customStyleUrl ? <link rel="stylesheet" type="text/css" href={customStyleUrl} /> : null}
{customStyle ? <link rel="stylesheet" type="text/css" href={`data:text/css;charset=UTF-8,${encodeURIComponent(customStyle)}`} /> : null}
</main>

View File

@ -70,8 +70,11 @@
width: 100%;
height: 50%;
opacity: 0;
transition: opacity calc(var(--enableAnimation) * .3s);
pointer-events: none;
[style~="--enableAnimation:1;"] & {
transition: opacity .3s;
}
}
&:before {

View File

@ -32,19 +32,20 @@
}
&.glow {
animation: pulse calc(var(--enableAnimation) * 1s) infinite ease-in;
border-radius: 50%;
[style~="--enableAnimation:1;"] & {
animation: pulse 1s infinite ease-in;
}
[style~="--enableAnimation:0;"] & span {
content: '';
outline: none !important;
background-clip: padding-box;
box-shadow: 0 0 0 4px rgba(255,255,255,.5);
}
}
}
[style~="--enableAnimation:0;"] .button.glow span {
content: '';
outline: none !important;
background-clip: padding-box;
border: var(--border-size-large) solid transparent;
box-shadow: 0 0 0 var(--border-size) rgba(255,255,255,.5);
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 white;

View File

@ -138,10 +138,13 @@
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis steps(4,end) calc(var(--enableAnimation) * 900ms) infinite;
content: "\2026"; /* ascii code for the ellipsis character */
width: 0;
margin-right: 1.25em;
[style~="--enableAnimation:1;"] & {
animation: ellipsis steps(4,end) 900ms infinite;
}
}
}

View File

@ -10,7 +10,10 @@
i {
color: var(--color-primary);
transition: all calc(var(--enableAnimation) * .2s) ease-in-out;
[style~="--enableAnimation:1;"] & {
transition: all .2s ease-in-out;
}
}
&:hover,

View File

@ -1,5 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Session } from 'meteor/session';
import Button from '/imports/ui/components/button/component';
import { defineMessages, intlShape, injectIntl } from 'react-intl';
import { styles } from './styles';
@ -39,6 +40,14 @@ class EchoTest extends Component {
this.handleNo = props.handleNo.bind(this);
}
componentDidMount() {
Session.set('inEchoTest', true);
}
componentWillUnmount() {
Session.set('inEchoTest', false);
}
render() {
const {
intl,

View File

@ -3,18 +3,20 @@
top: -50px;
left: -20px;
font-size: 20px;
animation: bounce calc(var(--enableAnimation) * 2s) infinite;
display: block;
font-family: 'bbb-icons';
content: "\E906";
position: relative;
[style~="--enableAnimation:1;"] & {
animation: bounce 2s infinite;
}
}
:global(.browser-edge) &:after {
top: -50px;
left: -15.5em;
font-size: 20px;
animation: bounceRotate calc(var(--enableAnimation) * 2s) infinite;
}
}
@ -45,7 +47,10 @@
left: 0;
right: 0;
background-color: rgba(0, 0, 0, .85);
animation: fade-in calc(var(--enableAnimation) * .5s) ease-in;
[style~="--enableAnimation:1;"] & {
animation: fade-in .5s ease-in;
}
}
.hint {

View File

@ -4,7 +4,6 @@ import { defineMessages, injectIntl } from 'react-intl';
import _ from 'lodash';
import Button from '/imports/ui/components/button/component';
import { styles } from './styles';
import Icon from '../icon/component';
import BreakoutRoomContainer from './breakout-remaining-time/container';
const intlMessages = defineMessages({
@ -191,15 +190,22 @@ class BreakoutRoom extends Component {
requestedBreakoutId,
} = this.state;
const roomItems = breakoutRooms.map(item => (
<div className={styles.content} key={`breakoutRoomList-${item.breakoutId}`}>
<span aria-hidden>{intl.formatMessage(intlMessages.breakoutRoom, item.sequence.toString())}</span>
{waiting && requestedBreakoutId === item.breakoutId ? (
const roomItems = breakoutRooms.map(breakout => (
<div className={styles.content} key={`breakoutRoomList-${breakout.breakoutId}`}>
<span aria-hidden>
{intl.formatMessage(intlMessages.breakoutRoom, breakout.sequence.toString())}
<span className={styles.usersAssignedNumberLabel}>
(
{breakout.users.length}
)
</span>
</span>
{waiting && requestedBreakoutId === breakout.breakoutId ? (
<span>
{intl.formatMessage(intlMessages.generatingURL)}
<span className={styles.connectingAnimation} />
</span>
) : this.renderUserActions(item.breakoutId, item.sequence.toString())}
) : this.renderUserActions(breakout.breakoutId, breakout.sequence.toString())}
</div>
));

View File

@ -49,6 +49,7 @@
padding: 0 0 0 .5rem;
}
}
.joinButton,
.button {
flex: 0 1 48%;
@ -81,16 +82,18 @@
color: var(--color-gray);
}
.connectingAnimation{
&:after {
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis steps(4,end) calc(var(--enableAnimation) * 900ms) infinite;
content: "\2026"; /* ascii code for the ellipsis character */
width: 0;
margin-right: 1.25em;
[style~="--enableAnimation:1;"] & {
animation: ellipsis steps(4,end) 900ms infinite;
}
}
}
@ -101,9 +104,12 @@
}
}
.duration {
display: flex;
align-self: center;
margin: .5rem 0 .5rem 0;
}
.usersAssignedNumberLabel {
margin-left: .25rem;
}

View File

@ -115,6 +115,7 @@ export default class Button extends BaseButton {
label,
'aria-label': ariaLabel,
'aria-expanded': ariaExpanded,
tooltipDistance,
} = this.props;
const renderFuncName = circle ? 'renderCircle' : 'renderDefault';
@ -124,6 +125,7 @@ export default class Button extends BaseButton {
return (
<Tooltip
tooltipDistance={tooltipDistance}
title={tooltipLabel}
>
{this[renderFuncName]()}
@ -150,6 +152,7 @@ export default class Button extends BaseButton {
delete remainingProps.circle;
delete remainingProps.block;
delete remainingProps.hideLabel;
delete remainingProps.tooltipDistance;
/* TODO: We can change this and make the button with flexbox to avoid html
changes */
@ -182,6 +185,7 @@ export default class Button extends BaseButton {
delete remainingProps.circle;
delete remainingProps.block;
delete remainingProps.hideLabel;
delete remainingProps.tooltipDistance;
return (
<BaseButton
@ -198,8 +202,10 @@ export default class Button extends BaseButton {
}
renderIcon() {
const iconName = this.props.icon;
const customIcon = this.props.customIcon;
const {
icon: iconName,
customIcon,
} = this.props;
if (iconName) {
return (<Icon className={styles.icon} iconName={iconName} />);

View File

@ -52,7 +52,10 @@
vertical-align: middle;
cursor: pointer;
user-select: none;
transition: all calc(var(--enableAnimation) * .2s) ease-in-out;
[style~="--enableAnimation:1;"] & {
transition: all .2s ease-in-out;
}
&:hover,
&:focus {

View File

@ -96,15 +96,12 @@ export default injectIntl(withTracker(({ intl }) => {
const hasClearMessage = clearMessage.length;
const showWelcomeMsg =
(hasClearMessage && clearMessage[0].timestamp < time) || !hasClearMessage;
const showModeratorMsg =
(user.isModerator)
&& ((hasClearMessage && clearMessage[0].timestamp < moderatorTime) || !hasClearMessage);
const messagesFormated = messagesBeforeWelcomeMsg
.concat(showWelcomeMsg ? welcomeMsg : [])
.concat(welcomeMsg)
.concat(showModeratorMsg ? moderatorMsg : [])
.concat(messagesAfterWelcomeMsg);

View File

@ -26,9 +26,12 @@
border-radius: var(--border-radius) 0 0 var(--border-radius);
color: var(--color-gray-light);
padding: var(--sm-padding-y) var(--sm-padding-x);
transition: all calc(var(--enableAnimation) * .3s);
cursor: pointer;
[style~="--enableAnimation:1;"] & {
transition: all .3s;
}
--bg-faded: rgba(167,179,189,0.25);
&:hover,

View File

@ -1,7 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedTime } from 'react-intl';
import cx from 'classnames';
import _ from 'lodash';
import UserAvatar from '/imports/ui/components/user-avatar/component';
@ -110,21 +109,20 @@ export default class MessageListItem extends Component {
} = this.props;
return (
<div className={cx(styles.item, styles.systemMessage)}>
<div className={styles.content} ref={(ref) => { this.item = ref; }}>
<div className={styles.messages}>
{messages.map(message => (
<div className={styles.messages}>
{messages.map(message => (
message.text !== ''
? (
<Message
className={styles.message}
className={(message.id ? styles.systemMessage : null)}
key={_.uniqueId('id-')}
text={message.text}
time={message.time}
chatAreaId={chatAreaId}
handleReadMessage={handleReadMessage}
/>
))}
</div>
</div>
) : null
))}
</div>
);
}

View File

@ -1,5 +1,10 @@
@import "/imports/ui/stylesheets/variables/_all";
:root {
--systemMessage-background-color: #F9FBFC;
--systemMessage-border-color: #C5CDD4;
}
.item {
font-size: var(--font-size-base);
margin-bottom: var(--line-height-computed);
@ -16,24 +21,11 @@
}
.systemMessage {
padding: var(--line-height-computed) 0;
border-bottom: 1px solid var(--color-gray-lighter);
.item:not(&) + & {
border-top: 1px solid var(--color-gray-lighter);
}
& + & {
margin-top: calc(var(--line-height-computed) * -1);
}
&:last-child {
border-bottom: none;
}
.message {
color: var(--color-gray);
}
background: var(--systemMessage-background-color);
border: 1px solid var(--systemMessage-border-color);
border-radius: var(--border-radius);
font-weight: var(--btn-font-weight);
padding: var(--font-size-base);
}
.avatarWrapper {

View File

@ -20,6 +20,8 @@ const PRIVATE_CHAT_TYPE = CHAT_CONFIG.type_private;
const PUBLIC_CHAT_USER_ID = CHAT_CONFIG.system_userid;
const PUBLIC_CHAT_CLEAR = CHAT_CONFIG.system_messages_keys.chat_clear;
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
const ScrollCollection = new Mongo.Collection(null);
const UnsentMessagesCollection = new Mongo.Collection(null);
@ -135,11 +137,14 @@ const isChatLocked = (receiverID) => {
const user = Users.findOne({ userId: Auth.userID });
if (meeting.lockSettingsProp !== undefined) {
const isPubChatLocked = meeting.lockSettingsProp.disablePubChat;
const isPrivChatLocked = meeting.lockSettingsProp.disablePrivChat;
return mapUser(user).isLocked
&& ((isPublic && isPubChatLocked) || (!isPublic && isPrivChatLocked));
if (mapUser(user).isLocked) {
if (isPublic) {
return meeting.lockSettingsProp.disablePubChat;
}
const receivingUser = Users.findOne({ userId: receiverID });
const receiverIsMod = receivingUser && receivingUser.role === ROLE_MODERATOR;
return !receiverIsMod && meeting.lockSettingsProp.disablePrivChat;
}
}
return false;
@ -241,7 +246,9 @@ const removeFromClosedChatsSession = () => {
const htmlDecode = (input) => {
const e = document.createElement('div');
e.innerHTML = input;
return e.childNodes[0].nodeValue;
const messages = Array.from(e.childNodes);
const message = messages.map(chatMessage => chatMessage.textContent);
return message.join('');
};
// Export the chat as [Hour:Min] user: message

View File

@ -127,8 +127,8 @@
}
.iconRight {
margin-right: calc(var(--indicator-padding-left) * -1);
margin-left: var(--sm-padding-x);
margin-right: 0;
margin-left: 1rem;
font-size: 12px;
line-height: 16px;
}

View File

@ -48,6 +48,6 @@
}
.button {
width: 9rem;
min-width: 9rem;
height: 2rem;
}

Some files were not shown because too many files have changed in this diff Show More