mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-02 12:52:28 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2b43843b7 | ||
|
|
2f03a0a7fe | ||
|
|
4c2f0d3600 | ||
|
|
a8a0945d73 | ||
|
|
a7048fba06 | ||
|
|
7b35dd89bb | ||
|
|
3561204bb5 | ||
|
|
ee50d07dc3 | ||
|
|
9ec4bc91fc | ||
|
|
88071e5258 | ||
|
|
e79d476d89 | ||
|
|
0fe4999beb | ||
|
|
ae96b9f365 | ||
|
|
922d0bd512 | ||
|
|
9a7bc4ebab | ||
|
|
2081757ba1 | ||
|
|
e9c9fc5e69 | ||
|
|
562761196d | ||
|
|
420514b921 | ||
|
|
eb63b24a9a | ||
|
|
c8bbded994 | ||
|
|
2a2702c13a | ||
|
|
5fc868ee96 | ||
|
|
502eab7278 | ||
|
|
332aafbe20 | ||
|
|
d5258e6197 | ||
|
|
9cc9e6132c | ||
|
|
f60c1d9751 | ||
|
|
5d32318d93 | ||
|
|
fee8482bae | ||
|
|
f2b5cdbfb8 | ||
|
|
60afe2d202 | ||
|
|
18f03e296b | ||
|
|
5cd9db1b6a | ||
|
|
f83404a99e | ||
|
|
7c1ba9242b | ||
|
|
bfcc587047 | ||
|
|
e90d8f5531 | ||
|
|
59033aab28 | ||
|
|
7f1eb617c3 | ||
|
|
fd7e8c9162 | ||
|
|
51e886142b | ||
|
|
dcc206b2b4 | ||
|
|
da75e17ff5 | ||
|
|
de30ce0f5c | ||
|
|
fc6f5717cb |
33
app.js
33
app.js
@@ -16,6 +16,7 @@ var APP =
|
||||
this.settings = require("./modules/settings/Settings");
|
||||
this.DTMF = require("./modules/DTMF/DTMF");
|
||||
this.members = require("./modules/members/MemberList");
|
||||
this.configFetch = require("./modules/config/HttpConfigFetch");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,10 +31,38 @@ function init() {
|
||||
APP.members.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have HTTP endpoint for getting confgi.json configured we're going to
|
||||
* read it and override properties from config.js and interfaceConfig.js.
|
||||
* If there is no endpoint we'll just continue with initialization.
|
||||
* Keep in mind that if the endpoint has been configured and we fail to obtain
|
||||
* the config for any reason then the conference won't start and error message
|
||||
* will be displayed to the user.
|
||||
*/
|
||||
function obtainConfigAndInit() {
|
||||
if (config.configLocation) {
|
||||
APP.configFetch.obtainConfig(
|
||||
config.configLocation, APP.UI.getRoomNode(),
|
||||
// Get config result callback
|
||||
function(success, error) {
|
||||
if (success) {
|
||||
init();
|
||||
} else {
|
||||
// Show obtain config error,
|
||||
// pass the error object for report
|
||||
APP.UI.messageHandler.openReportDialog(
|
||||
null, "dialog.connectError", error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
var URLProcessor = require("./modules/URLProcessor/URLProcessor");
|
||||
var URLProcessor = require("./modules/config/URLProcessor");
|
||||
URLProcessor.setConfigParametersFromUrl();
|
||||
APP.init();
|
||||
|
||||
@@ -42,7 +71,7 @@ $(document).ready(function () {
|
||||
if(APP.API.isEnabled())
|
||||
APP.API.init();
|
||||
|
||||
APP.UI.start(init);
|
||||
APP.UI.start(obtainConfigAndInit);
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var config = {
|
||||
// configLocation: './config.json', // see ./modules/HttpConfigFetch.js
|
||||
hosts: {
|
||||
domain: 'jitsi-meet.example.com',
|
||||
//anonymousdomain: 'guest.example.com',
|
||||
|
||||
36
css/main.css
36
css/main.css
@@ -38,17 +38,30 @@ html, body{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#toolbar a.button::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 40px;
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
background: #373737;
|
||||
}
|
||||
|
||||
#toolbar a.button:last-child::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: #FFFFFF;
|
||||
top: 0px;
|
||||
padding: 10px 0px;
|
||||
top: 0;
|
||||
padding: 10px 0;
|
||||
width: 38px;
|
||||
cursor: pointer;
|
||||
font-size: 11pt;
|
||||
text-align: center;
|
||||
text-shadow: 0px 1px 0px rgba(255,255,255,.3), 0px -1px 0px rgba(0,0,0,.6);
|
||||
text-shadow: 0 1px 0 rgba(255,255,255,.3), 0 -1px 0 rgba(0,0,0,.6);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@@ -61,13 +74,13 @@ html, body{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#chatButton, #chatBottomButton, #contactListButton, #numberOfParticipants {
|
||||
#toolbar_button_chat, #chatBottomButton, #contactListButton, #numberOfParticipants {
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
-moz-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
}
|
||||
/*#ffde00*/
|
||||
#chatButton.active, #contactListButton.glowing, #chatBottomButton.glowing {
|
||||
#toolbar_button_chat.active, #contactListButton.glowing, #chatBottomButton.glowing {
|
||||
-webkit-text-shadow: -1px 0 10px #00ccff,
|
||||
0 1px 10px #00ccff,
|
||||
1px 0 10px #00ccff,
|
||||
@@ -82,6 +95,11 @@ html, body{
|
||||
0 -1px 10px #00ccff;
|
||||
}
|
||||
|
||||
#toolbar_button_hangup {
|
||||
color: #ff0000;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
#numberOfParticipants {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -100,13 +118,13 @@ html, body{
|
||||
color: #00ccff;
|
||||
}
|
||||
|
||||
#recordButton {
|
||||
#toolbar_button_record {
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
-moz-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
}
|
||||
/*#ffde00*/
|
||||
#recordButton.active {
|
||||
#toolbar_button_record.active {
|
||||
-webkit-text-shadow: -1px 0 10px #00ccff,
|
||||
0 1px 10px #00ccff,
|
||||
1px 0 10px #00ccff,
|
||||
@@ -155,6 +173,8 @@ a.bottomToolbarButton:hover {
|
||||
}
|
||||
|
||||
input[type='text'], input[type='password'], textarea {
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
padding: 5px;
|
||||
|
||||
@@ -101,12 +101,14 @@
|
||||
}
|
||||
|
||||
#largeVideo,
|
||||
#largeVideoWrapper,
|
||||
#largeVideoContainer {
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#largeVideo
|
||||
#largeVideo,
|
||||
#largeVideoWrapper
|
||||
{
|
||||
object-fit: cover;
|
||||
}
|
||||
@@ -116,6 +118,9 @@
|
||||
#localVideoWrapper>video,
|
||||
#localVideoWrapper>object,
|
||||
#localVideoWrapper,
|
||||
#largeVideoWrapper,
|
||||
#largeVideoWrapper>video,
|
||||
#largeVideoWrapper>object,
|
||||
.videocontainer>video,
|
||||
.videocontainer>object {
|
||||
position: absolute;
|
||||
@@ -135,7 +140,7 @@
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#etherpadButton {
|
||||
#toolbar_button_etherpad {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,11 @@ constructor.
|
||||
```
|
||||
If you don't specify room the user will enter in new conference with random room name.
|
||||
|
||||
You can enable the "film strip only" mode(only the small videos are visible) by setting 6th parameter to ```true```:
|
||||
You can overwrite options set in config.js and interface_config.js. For example, to enable the film-strip-only interface mode and disable simulcast, you can use:
|
||||
```javascript
|
||||
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement, true);
|
||||
var configOverwrite = {enableSimulcast: false};
|
||||
var interfaceConfigOverwrite = {filmStripOnly: true};
|
||||
var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement, true, configOverwrite, interfaceConfigOverwrite);
|
||||
```
|
||||
|
||||
Controlling embedded Jitsi Meet Conference
|
||||
@@ -171,4 +173,4 @@ You can remove the embedded Jitsi Meet Conference with the following code:
|
||||
api.dispose()
|
||||
```
|
||||
|
||||
It is a good practice to remove the conference before the page is unloaded.
|
||||
It is a good practice to remove the conference before the page is unloaded.
|
||||
|
||||
@@ -28,10 +28,10 @@ var JitsiMeetExternalAPI = (function()
|
||||
* @constructor
|
||||
*/
|
||||
function JitsiMeetExternalAPI(domain, room_name, width, height, parentNode,
|
||||
filmStripOnly) {
|
||||
if(!width || width < MIN_WIDTH)
|
||||
configOverwrite, interfaceConfigOverwrite) {
|
||||
if((!width || width < MIN_WIDTH) && !filmStripOnly)
|
||||
width = MIN_WIDTH;
|
||||
if(!height || height < MIN_HEIGHT)
|
||||
if((!height || height < MIN_HEIGHT) && !filmStripOnly)
|
||||
height = MIN_HEIGHT;
|
||||
|
||||
this.parentNode = null;
|
||||
@@ -45,15 +45,34 @@ var JitsiMeetExternalAPI = (function()
|
||||
this.iframeHolder =
|
||||
this.parentNode.appendChild(document.createElement("div"));
|
||||
this.iframeHolder.id = "jitsiConference" + JitsiMeetExternalAPI.id;
|
||||
this.iframeHolder.style.width = width + "px";
|
||||
this.iframeHolder.style.height = height + "px";
|
||||
if(width)
|
||||
this.iframeHolder.style.width = width + "px";
|
||||
if(height)
|
||||
this.iframeHolder.style.height = height + "px";
|
||||
this.frameName = "jitsiConferenceFrame" + JitsiMeetExternalAPI.id;
|
||||
this.url = "//" + domain + "/";
|
||||
if(room_name)
|
||||
this.url += room_name;
|
||||
this.url += "#external=true";
|
||||
if(filmStripOnly)
|
||||
this.url += "&interfaceConfig.filmStripOnly=true";
|
||||
|
||||
var key;
|
||||
if (configOverwrite) {
|
||||
for (key in configOverwrite) {
|
||||
if (!configOverwrite.hasOwnProperty(key) ||
|
||||
typeof key !== 'string')
|
||||
continue;
|
||||
this.url += "&config." + key + "=" + configOverwrite[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (interfaceConfigOverwrite) {
|
||||
for (key in interfaceConfigOverwrite) {
|
||||
if (!interfaceConfigOverwrite.hasOwnProperty(key) ||
|
||||
typeof key !== 'string')
|
||||
continue;
|
||||
this.url += "&interfaceConfig." + key + "=" + interfaceConfigOverwrite[key];
|
||||
}
|
||||
}
|
||||
|
||||
JitsiMeetExternalAPI.id++;
|
||||
|
||||
|
||||
98
index.html
98
index.html
@@ -11,8 +11,6 @@
|
||||
<meta itemprop="image" content="/images/jitsilogo.png"/>
|
||||
<script src="https://api.callstats.io/static/callstats.min.js"></script>
|
||||
<script src="libs/jquery-2.1.1.min.js"></script>
|
||||
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/1.5.0/sha.js"></script>
|
||||
<script src="config.js?v=12"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||
<script src="libs/strophe/strophe.min.js?v=2"></script>
|
||||
<script src="libs/strophe/strophe.disco.min.js?v=1"></script>
|
||||
@@ -22,12 +20,12 @@
|
||||
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
|
||||
<script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
|
||||
<script src="interface_config.js?v=5"></script>
|
||||
<script src="libs/app.bundle.js?v=126"></script>
|
||||
<script src="libs/app.bundle.js?v=130"></script>
|
||||
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
|
||||
<link rel="stylesheet" href="css/font.css?v=7"/>
|
||||
<link rel="stylesheet" href="css/toastr.css?v=1">
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=30"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=19" id="videolayout_default"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=31"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=20" id="videolayout_default"/>
|
||||
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
|
||||
<link rel="stylesheet" href="css/modaldialog.css?v=3">
|
||||
@@ -133,9 +131,7 @@
|
||||
</div>
|
||||
<span id="toolbar">
|
||||
<span id="authentication" class="authentication" style="display: none">
|
||||
<a class="button" id="toolbar_button_authentication" >
|
||||
<i id="authButton" class="icon-avatar"></i>
|
||||
</a>
|
||||
<a class="button icon-avatar" id="toolbar_button_authentication" data-i18n="[content]toolbar.authenticate"></a>
|
||||
<ul class="loginmenu">
|
||||
<span class="loginmenuPadding"></span>
|
||||
<li id="toolbar_auth_identity" class="identity"></li>
|
||||
@@ -146,79 +142,23 @@
|
||||
<a class="authButton" data-i18n="toolbar.logout"></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="header_button_separator"></div>
|
||||
</span>
|
||||
<a class="button" id="toolbar_button_mute" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="mutePopover" data-i18n="[content]toolbar.mute" content="Mute / Unmute">
|
||||
<i id="mute" class="icon-microphone"></i>
|
||||
<a class="button icon-microphone" id="toolbar_button_mute" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="mutePopover" data-i18n="[content]toolbar.mute" content="Mute / Unmute"></a>
|
||||
<a class="button icon-camera" id="toolbar_button_camera" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" data-i18n="[content]toolbar.videomute" content="Start / stop camera"></a>
|
||||
<a class="button icon-recEnable" id="toolbar_button_record" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.record" content="Record" style="display: none"></a>
|
||||
<a class="button icon-security" id="toolbar_button_security" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.lock" content="Lock / unlock room"></a>
|
||||
<a class="button icon-link" id="toolbar_button_link" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.invite" content="Invite others"></a>
|
||||
<a class="button icon-chat" id="toolbar_button_chat" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="bottom" data-i18n="[content]toolbar.chat" content="Open / close chat">
|
||||
<span id="unreadMessages"></span>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_camera" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" data-i18n="[content]toolbar.videomute" content="Start / stop camera">
|
||||
<i id="video" class="icon-camera"></i>
|
||||
</a>
|
||||
<span id="recording" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_record" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.record" content="Record">
|
||||
<i id="recordButton" class="icon-recEnable"></i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_security" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.lock" content="Lock / unlock room">
|
||||
<i id="lockIcon" class="icon-security"></i>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_link" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.invite" content="Invite others">
|
||||
<i class="icon-link"></i>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<span class="toolbar_span">
|
||||
<a class="button" id="toolbar_button_chat" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="bottom" data-i18n="[content]toolbar.chat" content="Open / close chat">
|
||||
<i id="chatButton" class="icon-chat">
|
||||
<span id="unreadMessages"></span>
|
||||
</i>
|
||||
</a>
|
||||
</span>
|
||||
<span id="prezi_button">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_prezi" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.prezi" content="Share Prezi">
|
||||
<i class="icon-prezi"></i>
|
||||
</a>
|
||||
</span>
|
||||
<span id="etherpadButton">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_etherpad" data-container="body" data-toggle="popover" data-placement="bottom" content="Shared document" data-i18n="[content]toolbar.etherpad">
|
||||
<i class="icon-share-doc"></i>
|
||||
</a>
|
||||
</span>
|
||||
<span id="desktopsharing" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_desktopsharing" data-container="body" data-toggle="popover" data-placement="bottom" content="Share screen" data-i18n="[content]toolbar.sharescreen">
|
||||
<i class="icon-share-desktop"></i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_fullScreen" data-container="body" data-toggle="popover" data-placement="bottom" content="Enter / Exit Full Screen" data-i18n="[content]toolbar.fullscreen">
|
||||
<i id="fullScreen" class="icon-full-screen"></i>
|
||||
</a>
|
||||
<span id="sipCallButton" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_sip" data-container="body" data-toggle="popover" data-placement="bottom" content="Call SIP number" data-i18n="[content]toolbar.sip">
|
||||
<i class="icon-telephone"></i></a>
|
||||
</span>
|
||||
<span id="dialPadButton" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_dialpad" data-container="body" data-toggle="popover" data-placement="bottom" content="Open dialpad" data-i18n="[content]toolbar.dialpad">
|
||||
<i class="icon-dialpad"></i></a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" id="toolbar_button_settings" data-container="body" data-toggle="popover" data-placement="bottom" content="Settings" data-i18n="[content]toolbar.Settings">
|
||||
<i id="settingsButton" class="icon-settings"></i>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<span id="hangup">
|
||||
<a class="button" id="toolbar_button_hangup" data-container="body" data-toggle="popover" data-placement="bottom" content="Hang Up" data-i18n="[content]toolbar.hangup">
|
||||
<i class="icon-hangup" style="color:#ff0000;font-size: 1.4em;"></i>
|
||||
</a>
|
||||
</span>
|
||||
<a class="button icon-prezi" id="toolbar_button_prezi" data-container="body" data-toggle="popover" data-placement="bottom" data-i18n="[content]toolbar.prezi" content="Share Prezi"></a>
|
||||
<a class="button icon-share-doc" id="toolbar_button_etherpad" data-container="body" data-toggle="popover" data-placement="bottom" content="Shared document" data-i18n="[content]toolbar.etherpad"></a>
|
||||
<a class="button icon-share-desktop" id="toolbar_button_desktopsharing" data-container="body" data-toggle="popover" data-placement="bottom" content="Share screen" data-i18n="[content]toolbar.sharescreen" style="display: none"></a>
|
||||
<a class="button icon-full-screen" id="toolbar_button_fullScreen" data-container="body" data-toggle="popover" data-placement="bottom" content="Enter / Exit Full Screen" data-i18n="[content]toolbar.fullscreen"></a>
|
||||
<a class="button icon-telephone" id="toolbar_button_sip" data-container="body" data-toggle="popover" data-placement="bottom" content="Call SIP number" data-i18n="[content]toolbar.sip" style="display: none"></a>
|
||||
<a class="button icon-dialpad" id="toolbar_button_dialpad" data-container="body" data-toggle="popover" data-placement="bottom" content="Open dialpad" data-i18n="[content]toolbar.dialpad" style="display: none"></a>
|
||||
<a class="button icon-settings" id="toolbar_button_settings" data-container="body" data-toggle="popover" data-placement="bottom" content="Settings" data-i18n="[content]toolbar.Settings"></a>
|
||||
<a class="button icon-hangup" id="toolbar_button_hangup" data-container="body" data-toggle="popover" data-placement="bottom" content="Hang Up" data-i18n="[content]toolbar.hangup"></a>
|
||||
</span>
|
||||
</div>
|
||||
<div id="subject"></div>
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
"de": "Deutsch",
|
||||
"tr": "Türkisch",
|
||||
"it": "Italienisch",
|
||||
"fr": "Französisch"
|
||||
"fr": "Französisch",
|
||||
"sl": "Slowenisch"
|
||||
}
|
||||
9
lang/languages-sl.json
Normal file
9
lang/languages-sl.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"en": "Angleščina",
|
||||
"bg": "Bolgarščina",
|
||||
"de": "Nemščina",
|
||||
"tr": "Turščina",
|
||||
"it": "Italjanščina",
|
||||
"fr": "Francoščina",
|
||||
"sl": ""
|
||||
}
|
||||
@@ -4,5 +4,6 @@
|
||||
"de": "German",
|
||||
"tr": "Turkish",
|
||||
"it": "Italian",
|
||||
"fr": "French"
|
||||
"fr": "French",
|
||||
"sl": "Slovenian"
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@
|
||||
"connection": {
|
||||
"ERROR": "Fehler",
|
||||
"CONNECTING": "Verbindung wird hergestellt",
|
||||
"RECONNECTING": "Es ist ein Netzwerkproblem aufgetreten. Verbinde...",
|
||||
"CONNFAIL": "Verbindungsaufbau gescheitert",
|
||||
"AUTHENTICATING": "Anmeldung läuft",
|
||||
"AUTHFAIL": "Authentifizierung fehlgeschlagen",
|
||||
@@ -233,5 +234,10 @@
|
||||
"DISCONNECTED": "Getrennt",
|
||||
"DISCONNECTING": "Verbindung wird getrennt",
|
||||
"ATTACHED": "Angehängt"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "Wird aufgezeichnet",
|
||||
"pending": "Die Aufzeichnung wird gestartet sobald ein weiterer Teilnehmer beitritt",
|
||||
"on": "Aufzeichnung wurde gestartet"
|
||||
}
|
||||
}
|
||||
249
lang/main-sl.json
Normal file
249
lang/main-sl.json
Normal file
@@ -0,0 +1,249 @@
|
||||
{
|
||||
"contactlist": "STIKI",
|
||||
"connectionsettings": "Nastavitve povezave",
|
||||
"poweredby": "poganja",
|
||||
"downloadlogs": "Shrani zapis",
|
||||
"roomUrlDefaultMsg": "Ustvarjanje vaše konference ...",
|
||||
"participant": "Udeleženec",
|
||||
"me": "jaz",
|
||||
"speaker": "Govornik",
|
||||
"defaultNickname": "npr. __name__",
|
||||
"defaultPreziLink": "npr. __url__",
|
||||
"welcomepage": {
|
||||
"go": "POJDI",
|
||||
"roomname": "Vpišite ime sobe",
|
||||
"disable": "Prihodnjič ne prikaži te strani",
|
||||
"feature1": {
|
||||
"title": "Enostavna uporaba",
|
||||
"content": "Nič ni treba namestiti. __app__ deluje direktno v vašem brskalniku. Enostavno sporočite ostalim udeležencem URL svoje konference in začnite."
|
||||
},
|
||||
"feature2": {
|
||||
"title": "Ozka pasovna širina",
|
||||
"content": "Video konferenca z več udeleženci s samo 128Kbps. Deljenje zaslona in samo avdio konference so možne že z veliko nižjo pasovno širino."
|
||||
},
|
||||
"feature3": {
|
||||
"title": "Odprta koda",
|
||||
"content": "__app__ je objavljen po licenci MIT. Pod pogoji te licence lahko prosto snamete, uporabljate, spreminjate in delite."
|
||||
},
|
||||
"feature4": {
|
||||
"title": "Neomejeno število uporabnikov",
|
||||
"content": "Nobene umetne omejitve števila uporabnikov ali udeležencev konference. Zmogljivost strežnika in pasovna širina sta edini omejitvi."
|
||||
},
|
||||
"feature5": {
|
||||
"title": "Skupna raba zaslona",
|
||||
"content": "Skupna raba zaslona z drugimi je zelo enostavna. __app__ je idealna rešitev za spletne predstavitve, predavanja in tehnično podporo."
|
||||
},
|
||||
"feature6": {
|
||||
"title": "Varne sobe",
|
||||
"content": "Rabite zasebnost? Konferenčne sobe __app__ so lahko zaklenjene z geslom, da preprečite dostop neželenim gostom ter prekinitve."
|
||||
},
|
||||
"feature7": {
|
||||
"title": "Skupna raba zapiskov",
|
||||
"content": "__app__ vsebuje Etherpad, realnočasovni skupinski urejevalnik besedil, ki je idealen za pisanje zapisnikov sestankov, člankov in še mnogo drugega."
|
||||
},
|
||||
"feature8": {
|
||||
"title": "Statistika uporabe",
|
||||
"content": "Spoznajte svoje uporabnike z enostavno integracijo v Piwik, Google Analytics ter druge sisteme za nadzor uporabe in statistiko."
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"mute": "Utišaj / Povrni glasnost",
|
||||
"videomute": "Zaženi / Ustavi kamero",
|
||||
"authenticate": "Overi",
|
||||
"record": "Snemaj",
|
||||
"lock": "Zakleni / Odkleni sobo",
|
||||
"invite": "Povabite ostale",
|
||||
"chat": "Odpri / zapri klepetalnico",
|
||||
"prezi": "Skupna raba Prezi",
|
||||
"etherpad": "Dokument v skupni rabi",
|
||||
"sharescreen": "Zaslon v souporabi",
|
||||
"fullscreen": "Vklopi / Izklopi celozaslonski način",
|
||||
"sip": "Pokliči številko SIP",
|
||||
"Settings": "Nastavitve",
|
||||
"hangup": "Odloži",
|
||||
"login": "Prijava",
|
||||
"logout": "Odjava",
|
||||
"dialpad": "Pokaži številčnico"
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Odpri / zapri klepetalnico",
|
||||
"filmstrip": "Pokaži / Skrij filmski trak",
|
||||
"contactlist": "Odpri / Zapri stike"
|
||||
},
|
||||
"chat": {
|
||||
"nickname": {
|
||||
"title": "Vpišite vzdevek v spodnje polje",
|
||||
"popover": "Izberite vzdevek"
|
||||
},
|
||||
"messagebox": "Vnesite besedilo ..."
|
||||
},
|
||||
"settings": {
|
||||
"title": "NASTAVITVE",
|
||||
"update": "Posodobi",
|
||||
"name": "Ime",
|
||||
"startAudioMuted": "začni brez zvoka",
|
||||
"startVideoMuted": "začni brez slike"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Kliknite, da spremenite<br/>svoje ime",
|
||||
"moderator": "Lastnik<br/>konference",
|
||||
"videomute": "Udeleženec je<br/>izključil kamero.",
|
||||
"mute": "Udeleženec je utišan",
|
||||
"kick": "Izženi",
|
||||
"muted": "Utišan",
|
||||
"domute": "Utišaj"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Bitna hitrost:",
|
||||
"packetloss": "Izgubljeni paketi:",
|
||||
"resolution": "Ločljivost:",
|
||||
"less": "Pokaži manj",
|
||||
"more": "Pokaži več",
|
||||
"address": "Naslov:",
|
||||
"remoteport_plural_5": "Oddaljena vrata:",
|
||||
"remoteport": "Oddaljena vrata:",
|
||||
"remoteport_plural_2": "Oddaljena vrata:",
|
||||
"remoteport_plural_3": "Oddaljena vrata:",
|
||||
"localport_plural_5": "Krajevna vrata:",
|
||||
"localport": "Krajevna vrata:",
|
||||
"localport_plural_2": "Krajevna vrata:",
|
||||
"localport_plural_3": "Krajevna vrata:",
|
||||
"localaddress_plural_5": "Krajevni naslov:",
|
||||
"localaddress": "Krajevna naslova:",
|
||||
"localaddress_plural_2": "Krajevni naslovi:",
|
||||
"localaddress_plural_3": "Krajevni naslov:",
|
||||
"remoteaddress_plural_5": "Oddaljeni naslov:",
|
||||
"remoteaddress": "Oddaljena naslova:",
|
||||
"remoteaddress_plural_2": "Oddaljeni naslovi:",
|
||||
"remoteaddress_plural_3": "Oddaljeni naslovi:",
|
||||
"transport": "Prenos:",
|
||||
"bandwidth": "Ocenjena pasovna širina:",
|
||||
"na": "Ko se konferenca začne se vrnite sem za informacije o povezavi"
|
||||
},
|
||||
"notify": {
|
||||
"disconnected": "odklopjeno",
|
||||
"moderator": "Dodeljene moderatorske pravice!",
|
||||
"connected": "povezano",
|
||||
"somebody": "Nekdo",
|
||||
"me": "Jaz",
|
||||
"focus": "Fokus na konferenco",
|
||||
"focusFail": "__component__ ni na razpolago - ponovni poskus čez __ms__ sec",
|
||||
"grantedTo": "Moderatorske pravice dodeljene uporabniku __to__!",
|
||||
"grantedToUnknown": "Moderatorske pravice dodeljene uporabniku $t(somebody)!",
|
||||
"muted": "Pogovor ste začeli utišano.",
|
||||
"mutedTitle": "Utišani ste!"
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Ojej! Izgnali so vas iz srečanja!",
|
||||
"popupError": "Vaš brskalnik ne dovoli pojavnih oken iz te spletne strani. Omogočite prosim pojavna okna v varnostnih nastavitvah svojega brskalnika in ponovno poskusite.",
|
||||
"passwordError": "Ta pogovor je zaščiten z geslom. Samo lastnik konference lahko nastavi geslo.",
|
||||
"passwordError2": "Ta pogovor ni zaščiten z geslom. Samo lastnik konference lahko nastavi geslo.",
|
||||
"joinError": "Ups! Ni se bilo mogoče pridružiti konferenci. Mogoče je kakšna težava z varnostnimi nastavitvami. Pišite prosim administratorju storitve.",
|
||||
"connectError": "Ups! Nekaj je narobe in se ni bilo mogoče povezati s konferenco.",
|
||||
"connectErrorWithMsg": "Ups! Nekaj je narobe in se ni bilo mogoče povezati s konferenco: __msg__",
|
||||
"connecting": "Povezovanje",
|
||||
"error": "Napaka",
|
||||
"detectext": "Napaka pri zaznavanju razširitve za skupno uporabo namizja.",
|
||||
"failtoinstall": "Razširitve za skupno uporabo namizja ni bilo mogoče namestiti",
|
||||
"failedpermissions": "Ni bilo mogoče pridobiti dovoljenja za uporabo lokalnega mikrofona ali kamere.",
|
||||
"bridgeUnavailable": "Jitsi Videobridge trenutno ni na razpolago. Prosim poskusite kasneje!",
|
||||
"lockTitle": "Zaklepanje ni uspelo",
|
||||
"lockMessage": "Konference ni bilo mogoče zakleniti.",
|
||||
"warning": "Opozorilo",
|
||||
"passwordNotSupported": "Trenutno ni mogoče zakleniti sobe z geslom.",
|
||||
"sorry": "Oprostite",
|
||||
"internalError": "Notranja napaka [setRemoteDescription]",
|
||||
"unableToSwitch": "Ni mogoče preklopiti video pretoka.",
|
||||
"SLDFailure": "Ups! Nekaj je narobe in zvoka se ne da utišati! (Napaka SLD)",
|
||||
"SRDFailure": "Ups! Nekaj je narobe in slike ni mogoče ustaviti! (Napaka SRD)",
|
||||
"oops": "Ups!",
|
||||
"defaultError": "Prišlo je do neke napake",
|
||||
"passwordRequired": "Potrebno je geslo",
|
||||
"Ok": "V redu",
|
||||
"removePreziTitle": "Odstrani Prezi",
|
||||
"removePreziMsg": "Ali res želite odstraniti Prezi?",
|
||||
"sharePreziTitle": "Dajte Prezi v skupno rabo",
|
||||
"sharePreziMsg": "Drug uporabnik je že dal Prezi v skupno rabo. Ta konferenca podpira samo en Prezi naenkrat.",
|
||||
"Remove": "Odstrani",
|
||||
"WaitingForHost": "Čakanje na gostitelja ...",
|
||||
"WaitForHostMsg": "Ta konferenca <b>__room__ </b> se še ni začela. V primeru, da ste vi gostitelj se prosim overite. Drugače počakajte prosim na prihod gostitelja.",
|
||||
"IamHost": "Jaz sem gostitelj",
|
||||
"Cancel": "Prekliči",
|
||||
"retry": "Poskusi ponovno",
|
||||
"logoutTitle": "Odjava",
|
||||
"logoutQuestion": "Ali se res želite odjaviti in prekiniti konferenco?",
|
||||
"sessTerminated": "Seja je končana",
|
||||
"hungUp": "Prekinili ste klic",
|
||||
"joinAgain": "Ponovno se pridruži",
|
||||
"Share": "Souporaba",
|
||||
"preziLinkError": "Prosim, pravilno vpišite povezavo Prezi.",
|
||||
"Save": "Shrani",
|
||||
"recordingToken": "Vnesite žeton za registracijo",
|
||||
"Dial": "Pokliči",
|
||||
"sipMsg": "Vnesite številko SIP",
|
||||
"passwordCheck": "Ali res želite odstraniti geslo?",
|
||||
"passwordMsg": "Nastavite geslo za zaklepanje sobe",
|
||||
"Invite": "Povabi",
|
||||
"shareLink": "To povezavo pošljite vsem, ki jih želite povabiti",
|
||||
"settings1": "Nastavite svojo konferenco",
|
||||
"settings2": "Utišaj udeležence ob pristopu",
|
||||
"settings3": "Zahtevaj vzdevke<br/><br/>Nastavi geslo za zaklep sobe:",
|
||||
"yourPassword": "vaše geslo",
|
||||
"Back": "Nazaj",
|
||||
"serviceUnavailable": "Storitev ni na voljo",
|
||||
"gracefulShutdown": "Storitev trenutno ni na voljo zaradi vzdrževanja. Poskusite ponovno kasneje.",
|
||||
"Yes": "Da",
|
||||
"reservationError": "Napaka v sistemu rezervacije",
|
||||
"reservationErrorMsg": "Koda napake: __code__, sporočilo: __msg__",
|
||||
"password": "geslo",
|
||||
"userPassword": "uporabniško geslo",
|
||||
"token": "žeton",
|
||||
"displayNameRequired": "Vpišite svoje ime:"
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
"Ta konferenca je zaklenjena z geslom. Uporabite sledeči PIN ko se pridružite:",
|
||||
"",
|
||||
"",
|
||||
"__sharedKey__",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"subject": "Povabilo na __appName__ (__conferenceName__)",
|
||||
"body": [
|
||||
"Pozdravljeni,",
|
||||
"želim vas povabiti na ravnokar pripravljeno konferenco __appName__.",
|
||||
"",
|
||||
"",
|
||||
"Prosim, kliknite na sledečo povezavo, da se pridružite konferenci.",
|
||||
"",
|
||||
"",
|
||||
"__roomUrl__",
|
||||
"",
|
||||
"",
|
||||
"__sharedKeyText__",
|
||||
" Opomba: __appName__ trenutno nudi podporo samo za __supportedBrowsers__, uporabiti morate enega izmed teh brskalnikov.",
|
||||
"",
|
||||
"",
|
||||
"Se slišimo čez trenutek!"
|
||||
],
|
||||
"and": "in"
|
||||
},
|
||||
"connection": {
|
||||
"ERROR": "Napaka",
|
||||
"CONNECTING": "Povezovanje",
|
||||
"RECONNECTING": "Prišlo je do omrežne napake. Ponovni poskus ...",
|
||||
"CONNFAIL": "Povezovanje je spodletelo",
|
||||
"AUTHENTICATING": "Overjanje",
|
||||
"AUTHFAIL": "Overitev je spodletela",
|
||||
"CONNECTED": "Povezano",
|
||||
"DISCONNECTED": "Ni povezave",
|
||||
"DISCONNECTING": "Prekinjanje povezave",
|
||||
"ATTACHED": "Priključeno"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "Trenutno poteka snemanje!",
|
||||
"pending": "Snemanje se bo začelo takoj, ko se bo pridružil drugi udeleženec",
|
||||
"on": "Snemanje se je začelo"
|
||||
}
|
||||
}
|
||||
8828
libs/app.bundle.js
8828
libs/app.bundle.js
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,8 @@ var currentBrowser;
|
||||
|
||||
var browserVersion;
|
||||
|
||||
var isAndroid;
|
||||
|
||||
var RTCBrowserType = {
|
||||
|
||||
RTC_BROWSER_CHROME: "rtc_browser.chrome",
|
||||
@@ -55,6 +57,13 @@ var RTCBrowserType = {
|
||||
|
||||
usesUnifiedPlan: function() {
|
||||
return RTCBrowserType.isFirefox();
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the browser is running on an android device.
|
||||
*/
|
||||
isAndroid: function() {
|
||||
return isAndroid;
|
||||
}
|
||||
|
||||
// Add version getters for other browsers when needed
|
||||
@@ -157,5 +166,6 @@ function detectBrowser() {
|
||||
}
|
||||
|
||||
browserVersion = detectBrowser();
|
||||
isAndroid = navigator.userAgent.indexOf('Android') != -1;
|
||||
|
||||
module.exports = RTCBrowserType;
|
||||
@@ -22,7 +22,8 @@ function getPreviousResolution(resolution) {
|
||||
return resName;
|
||||
}
|
||||
|
||||
function setResolutionConstraints(constraints, resolution, isAndroid) {
|
||||
function setResolutionConstraints(constraints, resolution) {
|
||||
var isAndroid = RTCBrowserType.isAndroid();
|
||||
|
||||
if (Resolutions[resolution]) {
|
||||
constraints.video.mandatory.minWidth = Resolutions[resolution].width;
|
||||
@@ -44,8 +45,7 @@ function setResolutionConstraints(constraints, resolution, isAndroid) {
|
||||
constraints.video.mandatory.minHeight;
|
||||
}
|
||||
|
||||
function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid)
|
||||
{
|
||||
function getConstraints(um, resolution, bandwidth, fps, desktopStream) {
|
||||
var constraints = {audio: false, video: false};
|
||||
|
||||
if (um.indexOf('video') >= 0) {
|
||||
@@ -54,7 +54,7 @@ function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid
|
||||
|
||||
constraints.video.optional.push({ googLeakyBucket: true });
|
||||
|
||||
setResolutionConstraints(constraints, resolution, isAndroid);
|
||||
setResolutionConstraints(constraints, resolution);
|
||||
}
|
||||
if (um.indexOf('audio') >= 0) {
|
||||
if (!RTCBrowserType.isFirefox()) {
|
||||
@@ -131,6 +131,15 @@ function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid
|
||||
constraints.video.mandatory.minFrameRate = fps;
|
||||
}
|
||||
|
||||
// we turn audio for both audio and video tracks, the fake audio & video seems to work
|
||||
// only when enabled in one getUserMedia call, we cannot get fake audio separate by fake video
|
||||
// this later can be a problem with some of the tests
|
||||
if(RTCBrowserType.isFirefox() && config.firefox_fake_device)
|
||||
{
|
||||
constraints.audio = true;
|
||||
constraints.fake = true;
|
||||
}
|
||||
|
||||
return constraints;
|
||||
}
|
||||
|
||||
@@ -209,7 +218,7 @@ function RTCUtils(RTCService, onTemasysPluginReady)
|
||||
};
|
||||
// DTLS should now be enabled by default but..
|
||||
this.pc_constraints = {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]};
|
||||
if (navigator.userAgent.indexOf('Android') != -1) {
|
||||
if (RTCBrowserType.isAndroid()) {
|
||||
this.pc_constraints = {}; // disable DTLS on Android
|
||||
}
|
||||
if (!webkitMediaStream.prototype.getVideoTracks) {
|
||||
@@ -286,11 +295,9 @@ RTCUtils.prototype.getUserMediaWithConstraints = function(
|
||||
um, success_callback, failure_callback, resolution,bandwidth, fps,
|
||||
desktopStream) {
|
||||
currentResolution = resolution;
|
||||
// Check if we are running on Android device
|
||||
var isAndroid = navigator.userAgent.indexOf('Android') != -1;
|
||||
|
||||
var constraints = getConstraints(
|
||||
um, resolution, bandwidth, fps, desktopStream, isAndroid);
|
||||
um, resolution, bandwidth, fps, desktopStream);
|
||||
|
||||
console.info("Get media constraints", constraints);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*! adapterjs - custom version from - 2015-08-12 */
|
||||
/*! adapterjs - custom version from - 2015-08-19 */
|
||||
|
||||
// Adapter's interface.
|
||||
var AdapterJS = AdapterJS || {};
|
||||
@@ -17,7 +17,7 @@ AdapterJS.options = AdapterJS.options || {};
|
||||
// AdapterJS.options.hidePluginInstallPrompt = true;
|
||||
|
||||
// AdapterJS version
|
||||
AdapterJS.VERSION = '0.11.1';
|
||||
AdapterJS.VERSION = '0.12.0';
|
||||
|
||||
// This function will be called when the WebRTC API is ready to be used
|
||||
// Whether it is the native implementation (Chrome, Firefox, Opera) or
|
||||
@@ -72,6 +72,12 @@ else if(!!navigator.platform.match(/^Win/i)) {
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1kkS4FN';
|
||||
}
|
||||
|
||||
AdapterJS.WebRTCPlugin.TAGS = {
|
||||
NONE : 'none',
|
||||
AUDIO : 'audio',
|
||||
VIDEO : 'video'
|
||||
};
|
||||
|
||||
// Unique identifier of each opened page
|
||||
AdapterJS.WebRTCPlugin.pageId = Math.random().toString(36).slice(2);
|
||||
|
||||
@@ -341,23 +347,23 @@ AdapterJS.renderNotificationBar = function (text, buttonText, buttonLink, openNe
|
||||
event.cancelBubble = true;
|
||||
} catch(error) { }
|
||||
|
||||
var pluginInstallInterval = setInterval(function(){
|
||||
if(! isIE) {
|
||||
navigator.plugins.refresh(false);
|
||||
}
|
||||
AdapterJS.WebRTCPlugin.isPluginInstalled(
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.prefix,
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.plugName,
|
||||
function() {
|
||||
clearInterval(pluginInstallInterval);
|
||||
AdapterJS.WebRTCPlugin.defineWebRTCInterface()
|
||||
},
|
||||
function() { //Does nothing because not used here
|
||||
});
|
||||
} , 500);
|
||||
var pluginInstallInterval = setInterval(function(){
|
||||
if(! isIE) {
|
||||
navigator.plugins.refresh(false);
|
||||
}
|
||||
AdapterJS.WebRTCPlugin.isPluginInstalled(
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.prefix,
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.plugName,
|
||||
function() { // plugin now installed
|
||||
clearInterval(pluginInstallInterval);
|
||||
AdapterJS.WebRTCPlugin.defineWebRTCInterface();
|
||||
},
|
||||
function() {
|
||||
// still no plugin detected, nothing to do
|
||||
});
|
||||
} , 500);
|
||||
});
|
||||
|
||||
}else {
|
||||
} else {
|
||||
c.document.close();
|
||||
}
|
||||
AdapterJS.addEvent(c.document, 'click', function() {
|
||||
@@ -726,6 +732,28 @@ if (navigator.mozGetUserMedia) {
|
||||
return to;
|
||||
};
|
||||
|
||||
AdapterJS.maybeThroughWebRTCReady();
|
||||
} else if (navigator.mediaDevices && navigator.userAgent.match(
|
||||
/Edge\/(\d+).(\d+)$/)) {
|
||||
webrtcDetectedBrowser = 'edge';
|
||||
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
|
||||
|
||||
// the minimum version still supported by adapter.
|
||||
webrtcMinimumVersion = 12;
|
||||
|
||||
getUserMedia = navigator.getUserMedia;
|
||||
|
||||
attachMediaStream = function(element, stream) {
|
||||
element.srcObject = stream;
|
||||
return element;
|
||||
};
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.srcObject = from.srcObject;
|
||||
return to;
|
||||
};
|
||||
|
||||
AdapterJS.maybeThroughWebRTCReady();
|
||||
} else { // TRY TO USE PLUGIN
|
||||
// IE 9 is not offering an implementation of console.log until you open a console
|
||||
@@ -809,8 +837,8 @@ if (navigator.mozGetUserMedia) {
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.pluginId + '" /> ' +
|
||||
'<param name="windowless" value="false" /> ' +
|
||||
'<param name="pageId" value="' + AdapterJS.WebRTCPlugin.pageId + '" /> ' +
|
||||
'<param name="onload" value="' + AdapterJS.WebRTCPlugin.pluginInfo.onload +
|
||||
'" />' +
|
||||
'<param name="onload" value="' + AdapterJS.WebRTCPlugin.pluginInfo.onload + '" />' +
|
||||
'<param name="tag" value="' + AdapterJS.WebRTCPlugin.TAGS.NONE + '" />' +
|
||||
// uncomment to be able to use virtual cams
|
||||
(AdapterJS.options.getAllCams ? '<param name="forceGetAllCams" value="True" />':'') +
|
||||
|
||||
@@ -844,7 +872,8 @@ if (navigator.mozGetUserMedia) {
|
||||
AdapterJS.WebRTCPlugin.pluginInfo.pluginId + '">' +
|
||||
'<param name="windowless" value="false" /> ' +
|
||||
(AdapterJS.options.getAllCams ? '<param name="forceGetAllCams" value="True" />':'') +
|
||||
'<param name="pageId" value="' + AdapterJS.WebRTCPlugin.pageId + '">';
|
||||
'<param name="pageId" value="' + AdapterJS.WebRTCPlugin.pageId + '">' +
|
||||
'<param name="tag" value="' + AdapterJS.WebRTCPlugin.TAGS.NONE + '" />';
|
||||
document.body.appendChild(AdapterJS.WebRTCPlugin.plugin);
|
||||
}
|
||||
|
||||
@@ -877,9 +906,10 @@ if (navigator.mozGetUserMedia) {
|
||||
AdapterJS.WebRTCPlugin.defineWebRTCInterface = function () {
|
||||
if (AdapterJS.WebRTCPlugin.pluginState ===
|
||||
AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
|
||||
console.error("WebRTC interface has been defined already");
|
||||
console.error("AdapterJS - WebRTC interface has already been defined");
|
||||
return;
|
||||
}
|
||||
|
||||
AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING;
|
||||
|
||||
AdapterJS.isDefined = function (variable) {
|
||||
@@ -971,78 +1001,89 @@ if (navigator.mozGetUserMedia) {
|
||||
streamId = '';
|
||||
}
|
||||
else {
|
||||
stream.enableSoundTracks(true);
|
||||
stream.enableSoundTracks(true); // TODO: remove on 0.12.0
|
||||
streamId = stream.id;
|
||||
}
|
||||
|
||||
if (element.nodeName.toLowerCase() !== 'audio') {
|
||||
var elementId = element.id.length === 0 ? Math.random().toString(36).slice(2) : element.id;
|
||||
if (!element.isWebRTCPlugin || !element.isWebRTCPlugin()) {
|
||||
var frag = document.createDocumentFragment();
|
||||
var temp = document.createElement('div');
|
||||
var classHTML = '';
|
||||
if (element.className) {
|
||||
classHTML = 'class="' + element.className + '" ';
|
||||
} else if (element.attributes && element.attributes['class']) {
|
||||
classHTML = 'class="' + element.attributes['class'].value + '" ';
|
||||
var elementId = element.id.length === 0 ? Math.random().toString(36).slice(2) : element.id;
|
||||
var nodeName = element.nodeName.toLowerCase();
|
||||
if (nodeName !== 'object') { // not a plugin <object> tag yet
|
||||
var tag;
|
||||
switch(nodeName) {
|
||||
case 'audio':
|
||||
tag = AdapterJS.WebRTCPlugin.TAGS.AUDIO;
|
||||
break;
|
||||
case 'video':
|
||||
tag = AdapterJS.WebRTCPlugin.TAGS.VIDEO;
|
||||
break;
|
||||
default:
|
||||
tag = AdapterJS.WebRTCPlugin.TAGS.NONE;
|
||||
}
|
||||
|
||||
temp.innerHTML = '<object id="' + elementId + '" ' + classHTML +
|
||||
'type="' + AdapterJS.WebRTCPlugin.pluginInfo.type + '">' +
|
||||
'<param name="pluginId" value="' + elementId + '" /> ' +
|
||||
'<param name="pageId" value="' + AdapterJS.WebRTCPlugin.pageId + '" /> ' +
|
||||
'<param name="windowless" value="true" /> ' +
|
||||
'<param name="streamId" value="' + streamId + '" /> ' +
|
||||
'</object>';
|
||||
while (temp.firstChild) {
|
||||
frag.appendChild(temp.firstChild);
|
||||
}
|
||||
var frag = document.createDocumentFragment();
|
||||
var temp = document.createElement('div');
|
||||
var classHTML = '';
|
||||
if (element.className) {
|
||||
classHTML = 'class="' + element.className + '" ';
|
||||
} else if (element.attributes && element.attributes['class']) {
|
||||
classHTML = 'class="' + element.attributes['class'].value + '" ';
|
||||
}
|
||||
|
||||
var height = '';
|
||||
var width = '';
|
||||
if (element.getBoundingClientRect) {
|
||||
var rectObject = element.getBoundingClientRect();
|
||||
width = rectObject.width + 'px';
|
||||
height = rectObject.height + 'px';
|
||||
}
|
||||
else if (element.width) {
|
||||
width = element.width;
|
||||
height = element.height;
|
||||
} else {
|
||||
// TODO: What scenario could bring us here?
|
||||
}
|
||||
temp.innerHTML = '<object id="' + elementId + '" ' + classHTML +
|
||||
'type="' + AdapterJS.WebRTCPlugin.pluginInfo.type + '">' +
|
||||
'<param name="pluginId" value="' + elementId + '" /> ' +
|
||||
'<param name="pageId" value="' + AdapterJS.WebRTCPlugin.pageId + '" /> ' +
|
||||
'<param name="windowless" value="true" /> ' +
|
||||
'<param name="streamId" value="' + streamId + '" /> ' +
|
||||
'<param name="tag" value="' + tag + '" /> ' +
|
||||
'</object>';
|
||||
while (temp.firstChild) {
|
||||
frag.appendChild(temp.firstChild);
|
||||
}
|
||||
|
||||
element.parentNode.insertBefore(frag, element);
|
||||
frag = document.getElementById(elementId);
|
||||
frag.width = width;
|
||||
frag.height = height;
|
||||
element.parentNode.removeChild(element);
|
||||
var height = '';
|
||||
var width = '';
|
||||
if (element.getBoundingClientRect) {
|
||||
var rectObject = element.getBoundingClientRect();
|
||||
width = rectObject.width + 'px';
|
||||
height = rectObject.height + 'px';
|
||||
}
|
||||
else if (element.width) {
|
||||
width = element.width;
|
||||
height = element.height;
|
||||
} else {
|
||||
var children = element.children;
|
||||
for (var i = 0; i !== children.length; ++i) {
|
||||
if (children[i].name === 'streamId') {
|
||||
children[i].value = streamId;
|
||||
break;
|
||||
}
|
||||
// TODO: What scenario could bring us here?
|
||||
}
|
||||
|
||||
element.parentNode.insertBefore(frag, element);
|
||||
frag = document.getElementById(elementId);
|
||||
frag.width = width;
|
||||
frag.height = height;
|
||||
element.parentNode.removeChild(element);
|
||||
} else { // already an <object> tag, just change the stream id
|
||||
var children = element.children;
|
||||
for (var i = 0; i !== children.length; ++i) {
|
||||
if (children[i].name === 'streamId') {
|
||||
children[i].value = streamId;
|
||||
break;
|
||||
}
|
||||
element.setStreamId(streamId);
|
||||
}
|
||||
var newElement = document.getElementById(elementId);
|
||||
newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {};
|
||||
if (isIE) { // on IE the event needs to be plugged manually
|
||||
newElement.attachEvent('onplaying', newElement.onplaying);
|
||||
newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
|
||||
newElement._TemOnClick = function (id) {
|
||||
var arg = {
|
||||
srcElement : document.getElementById(id)
|
||||
};
|
||||
newElement.onclick(arg);
|
||||
};
|
||||
}
|
||||
return newElement;
|
||||
} else {
|
||||
return element;
|
||||
element.setStreamId(streamId);
|
||||
}
|
||||
var newElement = document.getElementById(elementId);
|
||||
newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {};
|
||||
newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
|
||||
if (isIE) { // on IE the event needs to be plugged manually
|
||||
newElement.attachEvent('onplaying', newElement.onplaying);
|
||||
newElement._TemOnClick = function (id) {
|
||||
var arg = {
|
||||
srcElement : document.getElementById(id)
|
||||
};
|
||||
newElement.onclick(arg);
|
||||
};
|
||||
}
|
||||
|
||||
return newElement;
|
||||
};
|
||||
|
||||
reattachMediaStream = function (to, from) {
|
||||
@@ -1120,211 +1161,3 @@ if (navigator.mozGetUserMedia) {
|
||||
AdapterJS.WebRTCPlugin.defineWebRTCInterface,
|
||||
AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var baseGetUserMedia = null;
|
||||
|
||||
AdapterJS.TEXT.EXTENSION = {
|
||||
REQUIRE_INSTALLATION_FF: 'To enable screensharing you need to install the Skylink WebRTC tools Firefox Add-on.',
|
||||
REQUIRE_INSTALLATION_CHROME: 'To enable screensharing you need to install the Skylink WebRTC tools Chrome Extension.',
|
||||
REQUIRE_REFRESH: 'Please refresh this page after the Skylink WebRTC tools extension has been installed.',
|
||||
BUTTON_FF: 'Install Now',
|
||||
BUTTON_CHROME: 'Go to Chrome Web Store'
|
||||
};
|
||||
|
||||
var clone = function(obj) {
|
||||
if (null == obj || "object" != typeof obj) return obj;
|
||||
var copy = obj.constructor();
|
||||
for (var attr in obj) {
|
||||
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
|
||||
}
|
||||
return copy;
|
||||
};
|
||||
|
||||
if (window.navigator.mozGetUserMedia) {
|
||||
baseGetUserMedia = window.navigator.getUserMedia;
|
||||
|
||||
navigator.getUserMedia = function (constraints, successCb, failureCb) {
|
||||
|
||||
if (constraints && constraints.video && !!constraints.video.mediaSource) {
|
||||
// intercepting screensharing requests
|
||||
|
||||
if (constraints.video.mediaSource !== 'screen' && constraints.video.mediaSource !== 'window') {
|
||||
throw new Error('Only "screen" and "window" option is available as mediaSource');
|
||||
}
|
||||
|
||||
var updatedConstraints = clone(constraints);
|
||||
|
||||
//constraints.video.mediaSource = constraints.video.mediaSource;
|
||||
updatedConstraints.video.mozMediaSource = updatedConstraints.video.mediaSource;
|
||||
|
||||
// so generally, it requires for document.readyState to be completed before the getUserMedia could be invoked.
|
||||
// strange but this works anyway
|
||||
var checkIfReady = setInterval(function () {
|
||||
if (document.readyState === 'complete') {
|
||||
clearInterval(checkIfReady);
|
||||
|
||||
baseGetUserMedia(updatedConstraints, successCb, function (error) {
|
||||
if (error.name === 'PermissionDeniedError' && window.parent.location.protocol === 'https:') {
|
||||
AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION.REQUIRE_INSTALLATION_FF,
|
||||
AdapterJS.TEXT.EXTENSION.BUTTON_FF,
|
||||
'http://skylink.io/screensharing/ff_addon.php?domain=' + window.location.hostname, false, true);
|
||||
//window.location.href = 'http://skylink.io/screensharing/ff_addon.php?domain=' + window.location.hostname;
|
||||
} else {
|
||||
failureCb(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1);
|
||||
|
||||
} else { // regular GetUserMediaRequest
|
||||
baseGetUserMedia(constraints, successCb, failureCb);
|
||||
}
|
||||
};
|
||||
|
||||
getUserMedia = navigator.getUserMedia;
|
||||
|
||||
} else if (window.navigator.webkitGetUserMedia) {
|
||||
baseGetUserMedia = window.navigator.getUserMedia;
|
||||
|
||||
navigator.getUserMedia = function (constraints, successCb, failureCb) {
|
||||
|
||||
if (constraints && constraints.video && !!constraints.video.mediaSource) {
|
||||
if (window.webrtcDetectedBrowser !== 'chrome') {
|
||||
throw new Error('Current browser does not support screensharing');
|
||||
}
|
||||
|
||||
// would be fine since no methods
|
||||
var updatedConstraints = clone(constraints);
|
||||
|
||||
var chromeCallback = function(error, sourceId) {
|
||||
if(!error) {
|
||||
updatedConstraints.video.mandatory = updatedConstraints.video.mandatory || {};
|
||||
updatedConstraints.video.mandatory.chromeMediaSource = 'desktop';
|
||||
updatedConstraints.video.mandatory.maxWidth = window.screen.width > 1920 ? window.screen.width : 1920;
|
||||
updatedConstraints.video.mandatory.maxHeight = window.screen.height > 1080 ? window.screen.height : 1080;
|
||||
|
||||
if (sourceId) {
|
||||
updatedConstraints.video.mandatory.chromeMediaSourceId = sourceId;
|
||||
}
|
||||
|
||||
delete updatedConstraints.video.mediaSource;
|
||||
|
||||
baseGetUserMedia(updatedConstraints, successCb, failureCb);
|
||||
|
||||
} else {
|
||||
if (error === 'permission-denied') {
|
||||
throw new Error('Permission denied for screen retrieval');
|
||||
} else {
|
||||
throw new Error('Failed retrieving selected screen');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var onIFrameCallback = function (event) {
|
||||
if (!event.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.chromeMediaSourceId) {
|
||||
if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
|
||||
chromeCallback('permission-denied');
|
||||
} else {
|
||||
chromeCallback(null, event.data.chromeMediaSourceId);
|
||||
}
|
||||
}
|
||||
|
||||
if (event.data.chromeExtensionStatus) {
|
||||
if (event.data.chromeExtensionStatus === 'not-installed') {
|
||||
AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION.REQUIRE_INSTALLATION_CHROME,
|
||||
AdapterJS.TEXT.EXTENSION.BUTTON_CHROME,
|
||||
event.data.data, true, true);
|
||||
} else {
|
||||
chromeCallback(event.data.chromeExtensionStatus, null);
|
||||
}
|
||||
}
|
||||
|
||||
// this event listener is no more needed
|
||||
window.removeEventListener('message', onIFrameCallback);
|
||||
};
|
||||
|
||||
window.addEventListener('message', onIFrameCallback);
|
||||
|
||||
postFrameMessage({
|
||||
captureSourceId: true
|
||||
});
|
||||
|
||||
} else {
|
||||
baseGetUserMedia(constraints, successCb, failureCb);
|
||||
}
|
||||
};
|
||||
|
||||
getUserMedia = navigator.getUserMedia;
|
||||
|
||||
} else {
|
||||
baseGetUserMedia = window.navigator.getUserMedia;
|
||||
|
||||
navigator.getUserMedia = function (constraints, successCb, failureCb) {
|
||||
if (constraints && constraints.video && !!constraints.video.mediaSource) {
|
||||
// would be fine since no methods
|
||||
var updatedConstraints = clone(constraints);
|
||||
|
||||
// wait for plugin to be ready
|
||||
AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
|
||||
// check if screensharing feature is available
|
||||
if (!!AdapterJS.WebRTCPlugin.plugin.HasScreensharingFeature &&
|
||||
!!AdapterJS.WebRTCPlugin.plugin.isScreensharingAvailable) {
|
||||
|
||||
|
||||
// set the constraints
|
||||
updatedConstraints.video.optional = updatedConstraints.video.optional || [];
|
||||
updatedConstraints.video.optional.push({
|
||||
sourceId: AdapterJS.WebRTCPlugin.plugin.screensharingKey || 'Screensharing'
|
||||
});
|
||||
|
||||
delete updatedConstraints.video.mediaSource;
|
||||
} else {
|
||||
throw new Error('Your WebRTC plugin does not support screensharing');
|
||||
}
|
||||
baseGetUserMedia(updatedConstraints, successCb, failureCb);
|
||||
});
|
||||
} else {
|
||||
baseGetUserMedia(constraints, successCb, failureCb);
|
||||
}
|
||||
};
|
||||
|
||||
getUserMedia = window.navigator.getUserMedia;
|
||||
}
|
||||
|
||||
if (window.webrtcDetectedBrowser === 'chrome') {
|
||||
var iframe = document.createElement('iframe');
|
||||
|
||||
iframe.onload = function() {
|
||||
iframe.isLoaded = true;
|
||||
};
|
||||
|
||||
iframe.src = 'https://cdn.temasys.com.sg/skylink/extensions/detectRTC.html';
|
||||
//'https://temasys-cdn.s3.amazonaws.com/skylink/extensions/detection-script-dev/detectRTC.html';
|
||||
iframe.style.display = 'none';
|
||||
|
||||
(document.body || document.documentElement).appendChild(iframe);
|
||||
|
||||
var postFrameMessage = function (object) {
|
||||
object = object || {};
|
||||
|
||||
if (!iframe.isLoaded) {
|
||||
setTimeout(function () {
|
||||
iframe.contentWindow.postMessage(object, '*');
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
iframe.contentWindow.postMessage(object, '*');
|
||||
};
|
||||
}
|
||||
})();
|
||||
@@ -33,6 +33,7 @@ var UIEvents = require("../../service/UI/UIEvents");
|
||||
var MemberEvents = require("../../service/members/Events");
|
||||
|
||||
var eventEmitter = new EventEmitter();
|
||||
var roomNode = null;
|
||||
var roomName = null;
|
||||
|
||||
|
||||
@@ -260,14 +261,17 @@ function registerListeners() {
|
||||
APP.xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad);
|
||||
APP.xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED,
|
||||
onAuthenticationRequired);
|
||||
APP.xmpp.addListener(XMPPEvents.VIDEO_TYPE, onPeerVideoTypeChanged);
|
||||
APP.xmpp.addListener(XMPPEvents.PARTICIPANT_VIDEO_TYPE_CHANGED,
|
||||
onPeerVideoTypeChanged);
|
||||
APP.xmpp.addListener(XMPPEvents.DEVICE_AVAILABLE,
|
||||
function (resource, devices) {
|
||||
VideoLayout.setDeviceAvailabilityIcons(resource, devices);
|
||||
});
|
||||
|
||||
APP.xmpp.addListener(XMPPEvents.AUDIO_MUTED, VideoLayout.onAudioMute);
|
||||
APP.xmpp.addListener(XMPPEvents.VIDEO_MUTED, VideoLayout.onVideoMute);
|
||||
APP.xmpp.addListener(XMPPEvents.PARTICIPANT_AUDIO_MUTED,
|
||||
VideoLayout.onAudioMute);
|
||||
APP.xmpp.addListener(XMPPEvents.PARTICIPANT_VIDEO_MUTED,
|
||||
VideoLayout.onVideoMute);
|
||||
APP.xmpp.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS, function (doMuteAudio) {
|
||||
UI.setAudioMuted(doMuteAudio);
|
||||
});
|
||||
@@ -681,17 +685,16 @@ UI.getLargeVideoResource = function () {
|
||||
return VideoLayout.getLargeVideoResource();
|
||||
};
|
||||
|
||||
UI.generateRoomName = function() {
|
||||
if(roomName)
|
||||
return roomName;
|
||||
var roomnode = null;
|
||||
UI.getRoomNode = function () {
|
||||
if (roomNode)
|
||||
return roomNode;
|
||||
var path = window.location.pathname;
|
||||
|
||||
// determinde the room node from the url
|
||||
// TODO: just the roomnode or the whole bare jid?
|
||||
if (config.getroomnode && typeof config.getroomnode === 'function') {
|
||||
// custom function might be responsible for doing the pushstate
|
||||
roomnode = config.getroomnode(path);
|
||||
roomNode = config.getroomnode(path);
|
||||
} else {
|
||||
/* fall back to default strategy
|
||||
* this is making assumptions about how the URL->room mapping happens.
|
||||
@@ -702,17 +705,22 @@ UI.generateRoomName = function() {
|
||||
}
|
||||
*/
|
||||
if (path.length > 1) {
|
||||
roomnode = path.substr(1).toLowerCase();
|
||||
roomNode = path.substr(1).toLowerCase();
|
||||
} else {
|
||||
var word = RoomNameGenerator.generateRoomWithoutSeparator();
|
||||
roomnode = word.toLowerCase();
|
||||
|
||||
roomNode = word.toLowerCase();
|
||||
window.history.pushState('VideoChat',
|
||||
'Room: ' + word, window.location.pathname + word);
|
||||
'Room: ' + word, window.location.pathname + word);
|
||||
}
|
||||
}
|
||||
return roomNode;
|
||||
};
|
||||
|
||||
roomName = roomnode + '@' + config.hosts.muc;
|
||||
UI.generateRoomName = function () {
|
||||
if (roomName)
|
||||
return roomName;
|
||||
var roomNode = UI.getRoomNode();
|
||||
roomName = roomNode + '@' + config.hosts.muc;
|
||||
return roomName;
|
||||
};
|
||||
|
||||
@@ -821,10 +829,10 @@ UI.setAudioMuted = function (mute, earlyMute) {
|
||||
if (!audioMute(mute, function () {
|
||||
VideoLayout.showLocalAudioIndicator(mute);
|
||||
|
||||
UIUtil.buttonClick("#mute", "icon-microphone icon-mic-disabled");
|
||||
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
|
||||
})) {
|
||||
// We still click the button.
|
||||
UIUtil.buttonClick("#mute", "icon-microphone icon-mic-disabled");
|
||||
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -851,7 +859,7 @@ UI.dockToolbar = function (isDock) {
|
||||
};
|
||||
|
||||
UI.setVideoMuteButtonsState = function (mute) {
|
||||
var video = $('#video');
|
||||
var video = $('#toolbar_button_camera');
|
||||
var communicativeClass = "icon-camera";
|
||||
var muteClass = "icon-camera icon-camera-disabled";
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ function resize() {
|
||||
* Creates the Etherpad button and adds it to the toolbar.
|
||||
*/
|
||||
function enableEtherpadButton() {
|
||||
if (!$('#etherpadButton').is(":visible"))
|
||||
$('#etherpadButton').css({display: 'inline-block'});
|
||||
if (!$('#toolbar_button_etherpad').is(":visible"))
|
||||
$('#toolbar_button_etherpad').css({display: 'inline-block'});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ var PanelToggler = (function(my) {
|
||||
var buttons = {
|
||||
'#chatspace': '#chatBottomButton',
|
||||
'#contactlist': '#contactListButton',
|
||||
'#settingsmenu': '#settingsButton'
|
||||
'#settingsmenu': '#toolbar_button_settings'
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ function setVisualNotification(show) {
|
||||
var unreadMsgBottomElement
|
||||
= document.getElementById('bottomUnreadMessages');
|
||||
|
||||
var glower = $('#chatButton');
|
||||
var glower = $('#toolbar_button_chat');
|
||||
var bottomGlower = $('#chatBottomButton');
|
||||
|
||||
if (unreadMessages) {
|
||||
@@ -29,7 +29,7 @@ function setVisualNotification(show) {
|
||||
ToolbarToggler.dockToolbar(true);
|
||||
|
||||
var chatButtonElement
|
||||
= document.getElementById('chatButton').parentNode;
|
||||
= document.getElementById('toolbar_button_chat');
|
||||
var leftIndent = (UIUtil.getTextWidth(chatButtonElement) -
|
||||
UIUtil.getTextWidth(unreadMsgElement)) / 2;
|
||||
var topIndent = (UIUtil.getTextHeight(chatButtonElement) -
|
||||
|
||||
@@ -47,7 +47,7 @@ var buttonHandlers = {
|
||||
return APP.desktopsharing.toggleScreenSharing();
|
||||
},
|
||||
"toolbar_button_fullScreen": function() {
|
||||
UIUtil.buttonClick("#fullScreen", "icon-full-screen icon-exit-full-screen");
|
||||
UIUtil.buttonClick("#toolbar_button_fullScreen", "icon-full-screen icon-exit-full-screen");
|
||||
return Toolbar.toggleFullScreen();
|
||||
},
|
||||
"toolbar_button_sip": function () {
|
||||
@@ -340,7 +340,7 @@ var Toolbar = (function (my) {
|
||||
*/
|
||||
my.setupButtonsFromConfig = function () {
|
||||
if (config.disablePrezi) {
|
||||
$("#prezi_button").css({display: "none"});
|
||||
$("#toolbar_button_prezi").css({display: "none"});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -515,15 +515,15 @@ var Toolbar = (function (my) {
|
||||
* Unlocks the lock button state.
|
||||
*/
|
||||
my.unlockLockButton = function () {
|
||||
if ($("#lockIcon").hasClass("icon-security-locked"))
|
||||
UIUtil.buttonClick("#lockIcon", "icon-security icon-security-locked");
|
||||
if ($("#toolbar_button_security").hasClass("icon-security-locked"))
|
||||
UIUtil.buttonClick("#toolbar_button_security", "icon-security icon-security-locked");
|
||||
};
|
||||
/**
|
||||
* Updates the lock button state to locked.
|
||||
*/
|
||||
my.lockLockButton = function () {
|
||||
if ($("#lockIcon").hasClass("icon-security"))
|
||||
UIUtil.buttonClick("#lockIcon", "icon-security icon-security-locked");
|
||||
if ($("#toolbar_button_security").hasClass("icon-security"))
|
||||
UIUtil.buttonClick("#toolbar_button_security", "icon-security icon-security-locked");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -546,16 +546,16 @@ var Toolbar = (function (my) {
|
||||
}
|
||||
|
||||
if (show) {
|
||||
$('#recording').css({display: "inline"});
|
||||
$('#toolbar_button_record').css({display: "inline-block"});
|
||||
}
|
||||
else {
|
||||
$('#recording').css({display: "none"});
|
||||
$('#toolbar_button_record').css({display: "none"});
|
||||
}
|
||||
};
|
||||
|
||||
// Sets the state of the recording button
|
||||
my.setRecordingButtonState = function (recordingState) {
|
||||
var selector = $('#recordButton');
|
||||
var selector = $('#toolbar_button_record');
|
||||
|
||||
if (recordingState === 'on') {
|
||||
selector.removeClass("icon-recEnable");
|
||||
@@ -605,18 +605,18 @@ var Toolbar = (function (my) {
|
||||
// Shows or hides SIP calls button
|
||||
my.showSipCallButton = function (show) {
|
||||
if (APP.xmpp.isSipGatewayEnabled() && show) {
|
||||
$('#sipCallButton').css({display: "inline-block"});
|
||||
$('#toolbar_button_sip').css({display: "inline-block"});
|
||||
} else {
|
||||
$('#sipCallButton').css({display: "none"});
|
||||
$('#toolbar_button_sip').css({display: "none"});
|
||||
}
|
||||
};
|
||||
|
||||
// Shows or hides the dialpad button
|
||||
my.showDialPadButton = function (show) {
|
||||
if (show) {
|
||||
$('#dialPadButton').css({display: "inline-block"});
|
||||
$('#toolbar_button_dialpad').css({display: "inline-block"});
|
||||
} else {
|
||||
$('#dialPadButton').css({display: "none"});
|
||||
$('#toolbar_button_dialpad').css({display: "none"});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -664,7 +664,7 @@ var Toolbar = (function (my) {
|
||||
* @param active the state of the desktop streaming.
|
||||
*/
|
||||
my.changeDesktopSharingButtonState = function (active) {
|
||||
var button = $("#desktopsharing > a");
|
||||
var button = $("#toolbar_button_desktopsharing");
|
||||
if (active) {
|
||||
button.addClass("glow");
|
||||
} else {
|
||||
|
||||
@@ -6,9 +6,9 @@ var toolbarTimeoutObject,
|
||||
|
||||
function showDesktopSharingButton() {
|
||||
if (APP.desktopsharing.isDesktopSharingEnabled()) {
|
||||
$('#desktopsharing').css({display: "inline"});
|
||||
$('#toolbar_button_desktopsharing').css({display: "inline-block"});
|
||||
} else {
|
||||
$('#desktopsharing').css({display: "none"});
|
||||
$('#toolbar_button_desktopsharing').css({display: "none"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ function getContainerByState(state)
|
||||
switch (state)
|
||||
{
|
||||
case "video":
|
||||
selector = "#largeVideo";
|
||||
selector = "#largeVideoWrapper";
|
||||
break;
|
||||
case "etherpad":
|
||||
selector = "#etherpad>iframe";
|
||||
@@ -267,7 +267,7 @@ function changeVideo(isVisible) {
|
||||
if (isVisible) {
|
||||
LargeVideo.VideoLayout.largeVideoUpdated(currentSmallVideo);
|
||||
|
||||
$('#largeVideo').fadeIn(300);
|
||||
$('#largeVideoWrapper').fadeTo(300, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,9 @@ function createLargeVideoHTML()
|
||||
'<img id="activeSpeakerAvatar" src=""/>' +
|
||||
'<canvas id="activeSpeakerAudioLevel"></canvas>' +
|
||||
'</div>' +
|
||||
'<video id="largeVideo" autoplay oncontextmenu="return false;"></video>' +
|
||||
'<div id="largeVideoWrapper">' +
|
||||
'<video id="largeVideo" autoplay oncontextmenu="return false;"></video>' +
|
||||
'</div id="largeVideoWrapper">' +
|
||||
'<span id="videoConnectionMessage"></span>';
|
||||
html += '</div>';
|
||||
$(html).prependTo("#videospace");
|
||||
@@ -351,7 +353,7 @@ var LargeVideo = {
|
||||
* @return <tt>true</tt> if visible, <tt>false</tt> - otherwise
|
||||
*/
|
||||
isLargeVideoVisible: function() {
|
||||
return $('#largeVideo').is(':visible');
|
||||
return $('#largeVideoWrapper').is(':visible');
|
||||
},
|
||||
/**
|
||||
* Returns <tt>true</tt> if the user is currently displayed on large video.
|
||||
@@ -369,6 +371,11 @@ var LargeVideo = {
|
||||
var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid);
|
||||
console.log('hover in ' + resourceJid + ', video: ', newSmallVideo);
|
||||
|
||||
if (!newSmallVideo) {
|
||||
console.error("Small video not found for: " + resourceJid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!LargeVideo.isCurrentlyOnLarge(resourceJid) || forceUpdate) {
|
||||
$('#activeSpeaker').css('visibility', 'hidden');
|
||||
|
||||
@@ -386,13 +393,17 @@ var LargeVideo = {
|
||||
// or null.
|
||||
this.eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, resourceJid);
|
||||
}
|
||||
if (RTCBrowserType.isSafari()) {
|
||||
// FIXME In Safari fadeOut works only for the first time
|
||||
changeVideo(this.isLargeVideoVisible());
|
||||
} else {
|
||||
$('#largeVideo').fadeOut(300,
|
||||
changeVideo.bind($('#largeVideo'), this.isLargeVideoVisible()));
|
||||
}
|
||||
// We are doing fadeOut/fadeIn animations on parent div which wraps
|
||||
// largeVideo, because when Temasys plugin is in use it replaces
|
||||
// <video> elements with plugin <object> tag. In Safari jQuery is
|
||||
// unable to store values on this plugin object which breaks all
|
||||
// animation effects performed on it directly.
|
||||
//
|
||||
// If for any reason large video was hidden before calling fadeOut
|
||||
// changeVideo will never be called, so we call show() in chain just
|
||||
// to be sure
|
||||
$('#largeVideoWrapper').show().fadeTo(300, 0,
|
||||
changeVideo.bind($('#largeVideo'), this.isLargeVideoVisible()));
|
||||
} else {
|
||||
if (currentSmallVideo) {
|
||||
currentSmallVideo.showAvatar();
|
||||
@@ -408,13 +419,13 @@ var LargeVideo = {
|
||||
if(!isEnabled)
|
||||
return;
|
||||
if (isVisible) {
|
||||
$('#largeVideo').css({visibility: 'visible'});
|
||||
$('#largeVideoWrapper').css({visibility: 'visible'});
|
||||
$('.watermark').css({visibility: 'visible'});
|
||||
if(currentSmallVideo)
|
||||
currentSmallVideo.enableDominantSpeaker(true);
|
||||
}
|
||||
else {
|
||||
$('#largeVideo').css({visibility: 'hidden'});
|
||||
$('#largeVideoWrapper').css({visibility: 'hidden'});
|
||||
$('#activeSpeaker').css('visibility', 'hidden');
|
||||
$('.watermark').css({visibility: 'hidden'});
|
||||
if(currentSmallVideo)
|
||||
@@ -430,7 +441,7 @@ var LargeVideo = {
|
||||
getVideoSize = isDesktop ? getDesktopVideoSize : getCameraVideoSize;
|
||||
getVideoPosition = isDesktop ? getDesktopVideoPosition
|
||||
: getCameraVideoPosition;
|
||||
this.position(null, null);
|
||||
this.position(null, null, null, null, true);
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -464,7 +475,7 @@ var LargeVideo = {
|
||||
var horizontalIndent = videoPosition[0];
|
||||
var verticalIndent = videoPosition[1];
|
||||
|
||||
positionVideo($('#largeVideo'),
|
||||
positionVideo($('#largeVideoWrapper'),
|
||||
largeVideoWidth,
|
||||
largeVideoHeight,
|
||||
horizontalIndent, verticalIndent, animate);
|
||||
@@ -522,10 +533,11 @@ var LargeVideo = {
|
||||
}
|
||||
},
|
||||
showAvatar: function (resourceJid, show) {
|
||||
if(!isEnabled)
|
||||
if (!isEnabled)
|
||||
return;
|
||||
if(this.getResourceJid() === resourceJid && state === "video") {
|
||||
$("#largeVideo").css("visibility", show ? "hidden" : "visible");
|
||||
if (this.getResourceJid() === resourceJid && state === "video") {
|
||||
$("#largeVideoWrapper")
|
||||
.css("visibility", show ? "hidden" : "visible");
|
||||
$('#activeSpeaker').css("visibility", show ? "visible" : "hidden");
|
||||
return true;
|
||||
}
|
||||
@@ -632,7 +644,7 @@ var LargeVideo = {
|
||||
document.body.style.background = 'black';
|
||||
ToolbarToggler.dockToolbar(false);//fix that
|
||||
});
|
||||
$('#largeVideo').fadeIn(300, function () {
|
||||
$('#largeVideoWrapper').fadeIn(300, function () {
|
||||
self.setLargeVideoVisible(true);
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -9,6 +9,7 @@ var RTCBrowserType = require("../../RTC/RTCBrowserType");
|
||||
function LocalVideo(VideoLayout) {
|
||||
this.videoSpanId = "localVideoContainer";
|
||||
this.container = $("#localVideoContainer").get(0);
|
||||
this.bindHoverHandler();
|
||||
this.VideoLayout = VideoLayout;
|
||||
this.flipX = true;
|
||||
this.isLocal = true;
|
||||
@@ -165,7 +166,7 @@ LocalVideo.prototype.changeVideo = function (stream, isMuted) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
self.VideoLayout.handleVideoThumbClicked(
|
||||
false,
|
||||
true,
|
||||
APP.xmpp.myResource());
|
||||
}
|
||||
|
||||
@@ -173,19 +174,6 @@ LocalVideo.prototype.changeVideo = function (stream, isMuted) {
|
||||
localVideoContainerSelector.off('click');
|
||||
localVideoContainerSelector.on('click', localVideoClick);
|
||||
|
||||
// Add hover handler
|
||||
localVideoContainerSelector.hover(
|
||||
function() {
|
||||
self.showDisplayName(true);
|
||||
},
|
||||
function() {
|
||||
if (!LargeVideo.isLargeVideoVisible() ||
|
||||
!LargeVideo.isCurrentlyOnLarge(self.getResourceJid())) {
|
||||
self.showDisplayName(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if(isMuted) {
|
||||
APP.UI.setVideoMute(true);
|
||||
return;
|
||||
|
||||
@@ -20,6 +20,7 @@ function RemoteVideo(peerJid, VideoLayout) {
|
||||
nickfield.className = "nick";
|
||||
nickfield.appendChild(document.createTextNode(this.resourceJid));
|
||||
this.container.appendChild(nickfield);
|
||||
this.bindHoverHandler();
|
||||
this.flipX = false;
|
||||
this.isLocal = false;
|
||||
}
|
||||
@@ -191,7 +192,7 @@ RemoteVideo.prototype.waitForPlayback = function (sel, stream) {
|
||||
APP.RTC.attachMediaStream(sel, stream);
|
||||
}
|
||||
if (RTCBrowserType.isTemasysPluginUsed()) {
|
||||
sel = self.VideoLayout.getPeerVideoSel(resourceJid);
|
||||
sel = self.selectVideoElement();
|
||||
}
|
||||
self.VideoLayout.videoactive(sel, resourceJid);
|
||||
sel[0].onplaying = null;
|
||||
@@ -233,9 +234,6 @@ RemoteVideo.prototype.addRemoteStreamElement = function (sid, stream, thessrc) {
|
||||
|
||||
};
|
||||
|
||||
// Name of video element name is different for IE/Safari
|
||||
var videoElem = APP.RTC.getVideoElementName();
|
||||
|
||||
// Add click handler.
|
||||
var onClickHandler = function (event) {
|
||||
|
||||
@@ -255,21 +253,6 @@ RemoteVideo.prototype.addRemoteStreamElement = function (sid, stream, thessrc) {
|
||||
if (RTCBrowserType.isTemasysPluginUsed())
|
||||
sel = $('#' + newElementId);
|
||||
sel[0].onclick = onClickHandler;
|
||||
|
||||
//FIXME
|
||||
// Add hover handler
|
||||
$(this.container).hover(
|
||||
function() {
|
||||
self.showDisplayName(true);
|
||||
},
|
||||
function() {
|
||||
// If the video has been "pinned" by the user we want to
|
||||
// keep the display name on place.
|
||||
if (!LargeVideo.isLargeVideoVisible() ||
|
||||
!LargeVideo.isCurrentlyOnLarge(self.getResourceJid()))
|
||||
self.showDisplayName(false);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,6 +120,26 @@ SmallVideo.createStreamElement = function (sid, stream) {
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configures hoverIn/hoverOut handlers.
|
||||
*/
|
||||
SmallVideo.prototype.bindHoverHandler = function () {
|
||||
// Add hover handler
|
||||
var self = this;
|
||||
$(this.container).hover(
|
||||
function () {
|
||||
self.showDisplayName(true);
|
||||
},
|
||||
function () {
|
||||
// If the video has been "pinned" by the user we want to
|
||||
// keep the display name on place.
|
||||
if (!LargeVideo.isLargeVideoVisible() ||
|
||||
!LargeVideo.isCurrentlyOnLarge(self.getResourceJid()))
|
||||
self.showDisplayName(false);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the data for the indicator
|
||||
* @param id the id of the indicator
|
||||
@@ -284,10 +304,20 @@ SmallVideo.prototype.createModeratorIndicatorElement = function () {
|
||||
APP.translation.translateElement($('#' + this.videoSpanId + ' .focusindicator'));
|
||||
};
|
||||
|
||||
SmallVideo.prototype.selectVideoElement = function () {
|
||||
var videoElem = APP.RTC.getVideoElementName();
|
||||
if (!RTCBrowserType.isTemasysPluginUsed()) {
|
||||
return $('#' + this.videoSpanId).find(videoElem);
|
||||
} else {
|
||||
return $('#' + this.videoSpanId +
|
||||
(this.isLocal ? '>>' : '>') +
|
||||
videoElem + '>param[value="video"]').parent();
|
||||
}
|
||||
};
|
||||
|
||||
SmallVideo.prototype.getSrc = function () {
|
||||
var videoElement = APP.RTC.getVideoElementName();
|
||||
return APP.RTC.getVideoSrc(
|
||||
$('#' + this.videoSpanId).find(videoElement).get(0));
|
||||
var videoElement = this.selectVideoElement().get(0);
|
||||
return APP.RTC.getVideoSrc(videoElement);
|
||||
};
|
||||
|
||||
SmallVideo.prototype.focus = function(isFocused) {
|
||||
@@ -299,8 +329,7 @@ SmallVideo.prototype.focus = function(isFocused) {
|
||||
};
|
||||
|
||||
SmallVideo.prototype.hasVideo = function () {
|
||||
return $("#" + this.videoSpanId).find(
|
||||
APP.RTC.getVideoElementName()).length !== 0;
|
||||
return this.selectVideoElement().length !== 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -320,8 +349,8 @@ SmallVideo.prototype.showAvatar = function (show) {
|
||||
}
|
||||
|
||||
var resourceJid = this.getResourceJid();
|
||||
var videoElem = APP.RTC.getVideoElementName();
|
||||
var video = $('#' + this.videoSpanId).find(videoElem);
|
||||
var video = this.selectVideoElement();
|
||||
|
||||
var avatar = $('#avatar_' + resourceJid);
|
||||
|
||||
if (show === undefined || show === null) {
|
||||
|
||||
@@ -68,6 +68,16 @@ var VideoLayout = (function (my) {
|
||||
localAudio.autoplay = true;
|
||||
localAudio.volume = 0;
|
||||
}
|
||||
// Now when Temasys plugin is converting also <audio> elements to
|
||||
// plugin's <object>s, in current layout it will capture click events
|
||||
// before it reaches the local video object. We hide it here in order
|
||||
// to prevent that.
|
||||
if (RTCBrowserType.isIExplorer()) {
|
||||
// The issue is not present on Safari. Also if we hide it in Safari
|
||||
// then the local audio track will have 'enabled' flag set to false
|
||||
// which will result in audio mute issues
|
||||
$('#localAudio').hide();
|
||||
}
|
||||
};
|
||||
|
||||
my.changeLocalVideo = function(stream, isMuted) {
|
||||
@@ -135,21 +145,21 @@ var VideoLayout = (function (my) {
|
||||
}
|
||||
};
|
||||
|
||||
my.electLastVisibleVideo = function() {
|
||||
my.electLastVisibleVideo = function () {
|
||||
// pick the last visible video in the row
|
||||
// if nobody else is left, this picks the local video
|
||||
var jid;
|
||||
var videoElem = RTC.getVideoElementName();
|
||||
var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>' + videoElem);
|
||||
if (pick.length && APP.RTC.getVideoSrc(pick[0])) {
|
||||
jid = VideoLayout.getPeerContainerResourceJid(pick[0].parentNode);
|
||||
var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last');
|
||||
if (pick.length) {
|
||||
jid = VideoLayout.getPeerContainerResourceJid(pick[0]);
|
||||
} else {
|
||||
console.info("Last visible video no longer exists");
|
||||
pick = $('#remoteVideos>span[id!="mixedstream"]>' + videoElem);
|
||||
if (pick.length && APP.RTC.getVideoSrc(pick[0])) {
|
||||
jid = VideoLayout.getPeerContainerResourceJid(pick[0].parentNode);
|
||||
} else {
|
||||
// Try local video
|
||||
pick = $('#remoteVideos>span[id!="mixedstream"]');
|
||||
if (pick.length) {
|
||||
jid = VideoLayout.getPeerContainerResourceJid(pick[0]);
|
||||
}
|
||||
if (!jid) {
|
||||
// Go with local video
|
||||
console.info("Fallback to local video...");
|
||||
jid = APP.xmpp.myResource();
|
||||
}
|
||||
@@ -457,15 +467,14 @@ var VideoLayout = (function (my) {
|
||||
* DOM element
|
||||
*/
|
||||
my.getPeerContainerResourceJid = function (containerElement) {
|
||||
if (localVideoThumbnail.container === containerElement) {
|
||||
return localVideoThumbnail.getResourceJid();
|
||||
}
|
||||
|
||||
var i = containerElement.id.indexOf('participant_');
|
||||
|
||||
if (i >= 0)
|
||||
return containerElement.id.substring(i + 12);
|
||||
};
|
||||
|
||||
my.getPeerVideoSel = function (peerResourceJid) {
|
||||
return $('#participant_' + peerResourceJid +
|
||||
'>' + APP.RTC.getVideoElementName());
|
||||
return containerElement.id.substring(i + 12);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -482,9 +491,9 @@ var VideoLayout = (function (my) {
|
||||
}
|
||||
|
||||
var resource = Strophe.getResourceFromJid(jid);
|
||||
var videoSel = VideoLayout.getPeerVideoSel(resource);
|
||||
if (videoSel.length > 0) {
|
||||
var videoThumb = videoSel[0];
|
||||
var remoteVideo = remoteVideos[resource];
|
||||
if (remoteVideo && remoteVideo.selectVideoElement().length) {
|
||||
var videoThumb = remoteVideo.selectVideoElement()[0];
|
||||
// It is not always the case that a videoThumb exists (if there is
|
||||
// no actual video).
|
||||
if (RTC.getVideoSrc(videoThumb)) {
|
||||
@@ -543,9 +552,10 @@ var VideoLayout = (function (my) {
|
||||
var resource = Strophe.getResourceFromJid(jid);
|
||||
|
||||
VideoLayout.ensurePeerContainerExists(jid);
|
||||
remoteVideos[resource].showVideoIndicator(value);
|
||||
var remoteVideo = remoteVideos[resource];
|
||||
remoteVideo.showVideoIndicator(value);
|
||||
|
||||
var el = VideoLayout.getPeerVideoSel(resource);
|
||||
var el = remoteVideo.selectVideoElement();
|
||||
if (!value)
|
||||
el.show();
|
||||
else
|
||||
@@ -577,18 +587,19 @@ var VideoLayout = (function (my) {
|
||||
if (resourceJid === APP.xmpp.myResource())
|
||||
return;
|
||||
|
||||
var remoteVideo = remoteVideos[resourceJid];
|
||||
var members = APP.xmpp.getMembers();
|
||||
// Update the current dominant speaker.
|
||||
if (resourceJid !== currentDominantSpeaker) {
|
||||
var currentJID = APP.xmpp.findJidFromResource(currentDominantSpeaker);
|
||||
var newJID = APP.xmpp.findJidFromResource(resourceJid);
|
||||
if(currentDominantSpeaker && (!members || !members[currentJID] ||
|
||||
!members[currentJID].displayName) && remoteVideos[resourceJid]) {
|
||||
remoteVideos[resourceJid].setDisplayName(null);
|
||||
if (currentDominantSpeaker && (!members || !members[currentJID] ||
|
||||
!members[currentJID].displayName) && remoteVideo) {
|
||||
remoteVideo.setDisplayName(null);
|
||||
}
|
||||
if(resourceJid && (!members || !members[newJID] ||
|
||||
!members[newJID].displayName) && remoteVideos[resourceJid]) {
|
||||
remoteVideos[resourceJid].setDisplayName(null,
|
||||
if (resourceJid && (!members || !members[newJID] ||
|
||||
!members[newJID].displayName) && remoteVideo) {
|
||||
remoteVideo.setDisplayName(null,
|
||||
interfaceConfig.DEFAULT_DOMINANT_SPEAKER_DISPLAY_NAME);
|
||||
}
|
||||
currentDominantSpeaker = resourceJid;
|
||||
@@ -596,8 +607,11 @@ var VideoLayout = (function (my) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!remoteVideo)
|
||||
return;
|
||||
|
||||
// Obtain container for new dominant speaker.
|
||||
var videoSel = VideoLayout.getPeerVideoSel(resourceJid);
|
||||
var videoSel = remoteVideo.selectVideoElement();
|
||||
|
||||
// Local video will not have container found, but that's ok
|
||||
// since we don't want to switch to local video.
|
||||
@@ -667,13 +681,19 @@ var VideoLayout = (function (my) {
|
||||
lastNEndpoints.indexOf(resourceJid) < 0 &&
|
||||
localLastNSet.indexOf(resourceJid) < 0) {
|
||||
console.log("Remove from last N", resourceJid);
|
||||
remoteVideos[resourceJid].showPeerContainer('hide');
|
||||
if (remoteVideos[resourceJid])
|
||||
remoteVideos[resourceJid].showPeerContainer('hide');
|
||||
else if (APP.xmpp.myResource() !== resourceJid)
|
||||
console.error("No remote video for: " + resourceJid);
|
||||
isReceived = false;
|
||||
} else if (resourceJid &&
|
||||
$('#participant_' + resourceJid).is(':visible') &&
|
||||
lastNEndpoints.indexOf(resourceJid) < 0 &&
|
||||
localLastNSet.indexOf(resourceJid) >= 0) {
|
||||
remoteVideos[resourceJid].showPeerContainer('avatar');
|
||||
if (remoteVideos[resourceJid])
|
||||
remoteVideos[resourceJid].showPeerContainer('avatar');
|
||||
else if (APP.xmpp.myResource() !== resourceJid)
|
||||
console.error("No remote video for: " + resourceJid);
|
||||
isReceived = false;
|
||||
}
|
||||
|
||||
@@ -696,14 +716,15 @@ var VideoLayout = (function (my) {
|
||||
endpointsEnteringLastN.forEach(function (resourceJid) {
|
||||
|
||||
var isVisible = $('#participant_' + resourceJid).is(':visible');
|
||||
remoteVideos[resourceJid].showPeerContainer('show');
|
||||
var remoteVideo = remoteVideos[resourceJid];
|
||||
remoteVideo.showPeerContainer('show');
|
||||
if (!isVisible) {
|
||||
console.log("Add to last N", resourceJid);
|
||||
|
||||
var jid = APP.xmpp.findJidFromResource(resourceJid);
|
||||
var mediaStream =
|
||||
APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
|
||||
var sel = VideoLayout.getPeerVideoSel(resourceJid);
|
||||
var sel = remoteVideo.selectVideoElement();
|
||||
|
||||
APP.RTC.attachMediaStream(sel, mediaStream.stream);
|
||||
if (lastNPickupJid == mediaStream.peerjid) {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/* global $, $iq, config, interfaceConfig */
|
||||
var params = {};
|
||||
function getConfigParamsFromUrl() {
|
||||
if(!location.hash)
|
||||
return {};
|
||||
var hash = location.hash.substr(1);
|
||||
var result = {};
|
||||
hash.split("&").forEach(function(part) {
|
||||
var item = part.split("=");
|
||||
result[item[0]] = JSON.parse(
|
||||
decodeURIComponent(item[1]).replace(/\\&/, "&"));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
params = getConfigParamsFromUrl();
|
||||
|
||||
var URLProcessor = {
|
||||
setConfigParametersFromUrl: function () {
|
||||
for(var key in params) {
|
||||
if(typeof key !== "string")
|
||||
continue;
|
||||
|
||||
var confObj = null, confKey;
|
||||
if (key.indexOf("config.") === 0) {
|
||||
confObj = config;
|
||||
confKey = key.substr("config.".length);
|
||||
} else if (key.indexOf("interfaceConfig.") === 0) {
|
||||
confObj = interfaceConfig;
|
||||
confKey = key.substr("interfaceConfig.".length);
|
||||
}
|
||||
|
||||
if (!confObj)
|
||||
continue;
|
||||
|
||||
var value = params[key];
|
||||
if (confObj[confKey] && typeof confObj[confKey] !== typeof value)
|
||||
{
|
||||
console.warn("The type of " + key +
|
||||
" is wrong. That parameter won't be updated in config.js.");
|
||||
continue;
|
||||
}
|
||||
|
||||
confObj[confKey] = value;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = URLProcessor;
|
||||
55
modules/config/HttpConfigFetch.js
Normal file
55
modules/config/HttpConfigFetch.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/* global $, $iq, config, interfaceConfig */
|
||||
|
||||
var configUtil = require('./Util');
|
||||
|
||||
var HttpConfig = {
|
||||
/**
|
||||
* Sends HTTP POST request to specified <tt>endpoint</tt>. In request
|
||||
* the name of the room is included in JSON format:
|
||||
* {
|
||||
* "rooomName": "someroom12345"
|
||||
* }
|
||||
* @param endpoint the name of HTTP endpoint to which HTTP POST request will
|
||||
* be sent.
|
||||
* @param roomName the name of the conference room for which config will be
|
||||
* requested.
|
||||
* @param complete
|
||||
*/
|
||||
obtainConfig: function (endpoint, roomName, complete) {
|
||||
console.info(
|
||||
"Send config request to " + endpoint + " for room: " + roomName);
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
var error = null;
|
||||
request.onreadystatechange = function (aEvt) {
|
||||
if (request.readyState == 4) {
|
||||
var status = request.status;
|
||||
if (status === 200) {
|
||||
try {
|
||||
var data = JSON.parse(request.responseText);
|
||||
configUtil.overrideConfigJSON(
|
||||
config, interfaceConfig, data);
|
||||
complete(true);
|
||||
return;
|
||||
} catch (exception) {
|
||||
console.error("Parse config error: ", exception);
|
||||
error = exception;
|
||||
}
|
||||
} else {
|
||||
console.error("Get config error: ", request, status);
|
||||
error = "Get config response status: " + status;
|
||||
}
|
||||
complete(false, error);
|
||||
}
|
||||
};
|
||||
|
||||
request.open("POST", endpoint, true);
|
||||
|
||||
request.setRequestHeader(
|
||||
"Content-Type", "application/json;charset=UTF-8");
|
||||
|
||||
request.send({ "roomName": roomName });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = HttpConfig;
|
||||
65
modules/config/URLProcessor.js
Normal file
65
modules/config/URLProcessor.js
Normal file
@@ -0,0 +1,65 @@
|
||||
/* global $, $iq, config, interfaceConfig */
|
||||
var configUtils = require('./Util');
|
||||
var params = {};
|
||||
function getConfigParamsFromUrl() {
|
||||
if (!location.hash)
|
||||
return {};
|
||||
var hash = location.hash.substr(1);
|
||||
var result = {};
|
||||
hash.split("&").forEach(function (part) {
|
||||
var item = part.split("=");
|
||||
result[item[0]] = JSON.parse(
|
||||
decodeURIComponent(item[1]).replace(/\\&/, "&"));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
params = getConfigParamsFromUrl();
|
||||
|
||||
var URLProcessor = {
|
||||
setConfigParametersFromUrl: function () {
|
||||
// Convert 'params' to JSON object
|
||||
// We have:
|
||||
// {
|
||||
// "config.disableAudioLevels": false,
|
||||
// "config.channelLastN": -1,
|
||||
// "interfaceConfig.APP_NAME": "Jitsi Meet"
|
||||
// }
|
||||
// We want to have:
|
||||
// {
|
||||
// "config": {
|
||||
// "disableAudioLevels": false,
|
||||
// "channelLastN": -1
|
||||
// },
|
||||
// interfaceConfig: {
|
||||
// APP_NAME: "Jitsi Meet"
|
||||
// }
|
||||
// }
|
||||
var configJSON = {
|
||||
config: {},
|
||||
interfaceConfig: {}
|
||||
};
|
||||
for (var key in params) {
|
||||
if (typeof key !== "string") {
|
||||
console.warn("Invalid config key: ", key);
|
||||
continue;
|
||||
}
|
||||
var confObj = null, confKey;
|
||||
if (key.indexOf("config.") === 0) {
|
||||
confObj = configJSON.config;
|
||||
confKey = key.substr("config.".length);
|
||||
} else if (key.indexOf("interfaceConfig.") === 0) {
|
||||
confObj = configJSON.interfaceConfig;
|
||||
confKey = key.substr("interfaceConfig.".length);
|
||||
}
|
||||
|
||||
if (!confObj)
|
||||
continue;
|
||||
|
||||
confObj[confKey] = params[key];
|
||||
}
|
||||
configUtils.overrideConfigJSON(config, interfaceConfig, configJSON);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = URLProcessor;
|
||||
49
modules/config/Util.js
Normal file
49
modules/config/Util.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/* global $ */
|
||||
var ConfigUtil = {
|
||||
/**
|
||||
* Method overrides JSON properties in <tt>config</tt> and
|
||||
* <tt>interfaceConfig</tt> Objects with the values from <tt>newConfig</tt>
|
||||
* @param config the config object for which we'll be overriding properties
|
||||
* @param interfaceConfig the interfaceConfig object for which we'll be
|
||||
* overriding properties.
|
||||
* @param newConfig object containing configuration properties. Destination
|
||||
* object is selected based on root property name:
|
||||
* {
|
||||
* config: {
|
||||
* // config.js properties to be
|
||||
* },
|
||||
* interfaceConfig: {
|
||||
* // interfaceConfig.js properties here
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
overrideConfigJSON: function (config, interfaceConfig, newConfig) {
|
||||
for (var configRoot in newConfig) {
|
||||
|
||||
var confObj = null;
|
||||
if (configRoot == "config") {
|
||||
confObj = config;
|
||||
} else if (configRoot == "interfaceConfig") {
|
||||
confObj = interfaceConfig;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var key in newConfig[configRoot]) {
|
||||
var value = newConfig[configRoot][key];
|
||||
if (confObj[key] && typeof confObj[key] !== typeof value)
|
||||
{
|
||||
console.warn(
|
||||
"The type of " + key +
|
||||
" is wrong. That parameter won't be updated in: ",
|
||||
confObj);
|
||||
continue;
|
||||
}
|
||||
console.info("Overriding " + key + " with: " + value);
|
||||
confObj[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ConfigUtil;
|
||||
@@ -1,4 +1,6 @@
|
||||
/* global config, $, APP, Strophe, callstats */
|
||||
var jsSHA = require('jssha');
|
||||
var io = require('socket.io-client');
|
||||
var callStats = null;
|
||||
|
||||
function initCallback (err, msg) {
|
||||
@@ -11,7 +13,7 @@ var CallStats = {
|
||||
if(!config.callStatsID || !config.callStatsSecret || callStats !== null)
|
||||
return;
|
||||
|
||||
callStats = new callstats($,io,jsSHA);
|
||||
callStats = new callstats($, io, jsSHA);
|
||||
|
||||
this.session = jingleSession;
|
||||
this.peerconnection = jingleSession.peerconnection.peerconnection;
|
||||
|
||||
@@ -4,7 +4,7 @@ var RTCBrowserType = require("../RTC/RTCBrowserType");
|
||||
|
||||
/* Whether we support the browser we are running into for logging statistics */
|
||||
var browserSupported = RTCBrowserType.isChrome() ||
|
||||
RTCBrowserType.isOpera();
|
||||
RTCBrowserType.isOpera() || RTCBrowserType.isFirefox();
|
||||
/**
|
||||
* Calculates packet lost percent using the number of lost packets and the
|
||||
* number of all packet.
|
||||
@@ -296,7 +296,8 @@ StatsCollector.prototype.start = function ()
|
||||
);
|
||||
}
|
||||
|
||||
if (config.logStats && browserSupported) {
|
||||
// Logging statistics does not support firefox
|
||||
if (config.logStats && (browserSupported && !RTCBrowserType.isFirefox())) {
|
||||
this.gatherStatsIntervalId = setInterval(
|
||||
function () {
|
||||
self.peerconnection.getStats(
|
||||
|
||||
@@ -1355,10 +1355,11 @@ JingleSessionPC.prototype.setLocalDescription = function () {
|
||||
}
|
||||
|
||||
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
||||
// TODO: is this hack (along with the XMPPEvent-s used only for it) still needed
|
||||
// now that we announce an SSRC for receive-only streams?
|
||||
function sendKeyframe(pc) {
|
||||
console.log('sendkeyframe', pc.iceConnectionState);
|
||||
if (pc.iceConnectionState !== 'connected') return; // safe...
|
||||
var self = this;
|
||||
pc.setRemoteDescription(
|
||||
pc.remoteDescription,
|
||||
function () {
|
||||
@@ -1431,6 +1432,8 @@ JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
|
||||
|
||||
var isVideo = data.stream.getVideoTracks().length > 0;
|
||||
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
||||
// TODO: is this hack still needed now that we announce an SSRC for
|
||||
// receive-only streams?
|
||||
if (isVideo &&
|
||||
data.peerjid && this.peerjid === data.peerjid &&
|
||||
data.stream.getVideoTracks().length === 0 &&
|
||||
|
||||
@@ -35,7 +35,7 @@ var externalAuthEnabled = false;
|
||||
// Sip gateway can be enabled by configuring Jigasi host in config.js or
|
||||
// it will be enabled automatically if focus detects the component through
|
||||
// service discovery.
|
||||
var sipGatewayEnabled = config.hosts.call_control !== undefined;
|
||||
var sipGatewayEnabled;
|
||||
|
||||
var eventEmitter = null;
|
||||
|
||||
@@ -65,6 +65,9 @@ var Moderator = {
|
||||
this.xmppService = xmpp;
|
||||
eventEmitter = emitter;
|
||||
|
||||
sipGatewayEnabled =
|
||||
config.hosts && config.hosts.call_control !== undefined;
|
||||
|
||||
// Message listener that talks to POPUP window
|
||||
function listener(event) {
|
||||
if (event.data && event.data.sessionId) {
|
||||
|
||||
@@ -10,7 +10,7 @@ var recordingEnabled;
|
||||
* Whether to use a jirecon component for recording, or use the videobridge
|
||||
* through COLIBRI.
|
||||
*/
|
||||
var useJirecon = (typeof config.hosts.jirecon != "undefined");
|
||||
var useJirecon;
|
||||
|
||||
/**
|
||||
* The ID of the jirecon recording session. Jirecon generates it when we
|
||||
@@ -109,6 +109,10 @@ function setRecording(state, token, callback, connection) {
|
||||
}
|
||||
|
||||
var Recording = {
|
||||
init: function () {
|
||||
useJirecon = config.hosts &&
|
||||
(typeof config.hosts.jirecon != "undefined");
|
||||
},
|
||||
toggleRecording: function (tokenEmptyCallback, recordingStateChangeCallback, connection) {
|
||||
if (!Moderator.isModerator()) {
|
||||
console.log(
|
||||
|
||||
@@ -111,10 +111,11 @@ module.exports = function(XMPP, eventEmitter) {
|
||||
}
|
||||
}
|
||||
|
||||
var url;
|
||||
// Parse prezi tag.
|
||||
var presentation = $(pres).find('>prezi');
|
||||
if (presentation.length) {
|
||||
var url = presentation.attr('url');
|
||||
url = presentation.attr('url');
|
||||
var current = presentation.find('>current').text();
|
||||
|
||||
console.log('presentation info received from', from, url);
|
||||
@@ -129,7 +130,7 @@ module.exports = function(XMPP, eventEmitter) {
|
||||
}
|
||||
}
|
||||
else if (this.preziMap[from] != null) {
|
||||
var url = this.preziMap[from];
|
||||
url = this.preziMap[from];
|
||||
delete this.preziMap[from];
|
||||
$(document).trigger('presentationremoved.muc', [from, url]);
|
||||
}
|
||||
@@ -137,22 +138,22 @@ module.exports = function(XMPP, eventEmitter) {
|
||||
// Parse audio info tag.
|
||||
var audioMuted = $(pres).find('>audiomuted');
|
||||
if (audioMuted.length) {
|
||||
eventEmitter.emit(XMPPEvents.AUDIO_MUTED,
|
||||
eventEmitter.emit(XMPPEvents.PARTICIPANT_AUDIO_MUTED,
|
||||
from, (audioMuted.text() === "true"));
|
||||
}
|
||||
|
||||
// Parse video info tag.
|
||||
var videoMuted = $(pres).find('>videomuted');
|
||||
if (videoMuted.length) {
|
||||
eventEmitter.emit(XMPPEvents.VIDEO_MUTED,
|
||||
eventEmitter.emit(XMPPEvents.PARTICIPANT_VIDEO_MUTED,
|
||||
from, (videoMuted.text() === "true"));
|
||||
}
|
||||
|
||||
var startMuted = $(pres).find('>startmuted');
|
||||
if (startMuted.length)
|
||||
{
|
||||
if (startMuted.length && Moderator.isPeerModerator(from)) {
|
||||
eventEmitter.emit(XMPPEvents.START_MUTED_SETTING_CHANGED,
|
||||
startMuted.attr("audio") === "true", startMuted.attr("video") === "true");
|
||||
startMuted.attr("audio") === "true",
|
||||
startMuted.attr("video") === "true");
|
||||
}
|
||||
|
||||
var devices = $(pres).find('>devices');
|
||||
@@ -179,7 +180,7 @@ module.exports = function(XMPP, eventEmitter) {
|
||||
{
|
||||
if (videoType.text().length)
|
||||
{
|
||||
eventEmitter.emit(XMPPEvents.VIDEO_TYPE,
|
||||
eventEmitter.emit(XMPPEvents.PARTICIPANT_VIDEO_TYPE_CHANGED,
|
||||
Strophe.getResourceFromJid(from), videoType.text());
|
||||
}
|
||||
}
|
||||
@@ -216,7 +217,7 @@ module.exports = function(XMPP, eventEmitter) {
|
||||
}
|
||||
|
||||
var nicktag = $(pres).find('>nick[xmlns="http://jabber.org/protocol/nick"]');
|
||||
member.displayName = (nicktag.length > 0 ? nicktag.html() : null);
|
||||
member.displayName = (nicktag.length > 0 ? nicktag.text() : null);
|
||||
|
||||
if (from == this.myroomjid) {
|
||||
if (member.affiliation == 'owner') this.isOwner = true;
|
||||
|
||||
@@ -270,6 +270,7 @@ var XMPP = {
|
||||
initStrophePlugins();
|
||||
registerListeners();
|
||||
Moderator.init(this, eventEmitter);
|
||||
Recording.init();
|
||||
var configDomain = config.hosts.anonymousdomain || config.hosts.domain;
|
||||
// Force authenticated domain if room is appended with '?login=true'
|
||||
if (config.hosts.anonymousdomain &&
|
||||
|
||||
@@ -14,15 +14,18 @@
|
||||
],
|
||||
"author": "",
|
||||
"readmeFilename": "README.md",
|
||||
"//": "Callstats.io does not work with recent versions of jsSHA (2.0.1 in particular)",
|
||||
"dependencies": {
|
||||
"events": "*",
|
||||
"pako": "*",
|
||||
"i18next-client": "1.7.7",
|
||||
"sdp-interop": "0.1.4",
|
||||
"sdp-transform": "1.4.0",
|
||||
"sdp-transform": "1.4.1",
|
||||
"sdp-simulcast": "0.1.0",
|
||||
"async": "0.9.0",
|
||||
"retry": "0.6.1"
|
||||
"retry": "0.6.1",
|
||||
"jssha": "1.5.0",
|
||||
"socket.io-client": "1.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
},
|
||||
|
||||
@@ -1,47 +1,85 @@
|
||||
var XMPPEvents = {
|
||||
// Designates an event indicating that the connection to the XMPP server
|
||||
// failed.
|
||||
CONNECTION_FAILED: "xmpp.connection.failed",
|
||||
// Indicates an interrupted connection event.
|
||||
// Designates an event indicating that the media (ICE) connection was
|
||||
// interrupted. This should go to the RTC module.
|
||||
CONNECTION_INTERRUPTED: "xmpp.connection.interrupted",
|
||||
// Indicates a restored connection event.
|
||||
// Designates an event indicating that the media (ICE) connection was
|
||||
// restored. This should go to the RTC module.
|
||||
CONNECTION_RESTORED: "xmpp.connection.restored",
|
||||
CONFERENCE_CREATED: "xmpp.conferenceCreated.jingle",
|
||||
// Designates an event indicating that an offer (e.g. Jingle
|
||||
// session-initiate) was received.
|
||||
CALL_INCOMING: "xmpp.callincoming.jingle",
|
||||
DISPOSE_CONFERENCE: "xmpp.dispose_conference",
|
||||
GRACEFUL_SHUTDOWN: "xmpp.graceful_shutdown",
|
||||
// Designates an event indicating that we were kicked from the XMPP MUC.
|
||||
KICKED: "xmpp.kicked",
|
||||
BRIDGE_DOWN: "xmpp.bridge_down",
|
||||
// Designates an event indicating that the userID for a specific JID has
|
||||
// changed.
|
||||
USER_ID_CHANGED: "xmpp.user_id_changed",
|
||||
// We joined the MUC
|
||||
// Designates an event indicating that we have joined the XMPP MUC.
|
||||
MUC_JOINED: "xmpp.muc_joined",
|
||||
// A member joined the MUC
|
||||
// Designates an event indicating that a participant joined the XMPP MUC.
|
||||
MUC_MEMBER_JOINED: "xmpp.muc_member_joined",
|
||||
// A member left the MUC
|
||||
// Designates an event indicating that a participant left the XMPP MUC.
|
||||
MUC_MEMBER_LEFT: "xmpp.muc_member_left",
|
||||
// Designates an event indicating that the MUC role of a participant has
|
||||
// changed.
|
||||
MUC_ROLE_CHANGED: "xmpp.muc_role_changed",
|
||||
// Designates an event indicating that the XMPP MUC was destroyed.
|
||||
MUC_DESTROYED: "xmpp.muc_destroyed",
|
||||
// Designates an event indicating that the display name of a participant
|
||||
// has changed.
|
||||
DISPLAY_NAME_CHANGED: "xmpp.display_name_changed",
|
||||
// Designates an event indicating that we received statistics from a
|
||||
// participant in the MUC.
|
||||
REMOTE_STATS: "xmpp.remote_stats",
|
||||
// Designates an event indicating that our role in the XMPP MUC has changed.
|
||||
LOCAL_ROLE_CHANGED: "xmpp.localrole_changed",
|
||||
PRESENCE_STATUS: "xmpp.presence_status",
|
||||
RESERVATION_ERROR: "xmpp.room_reservation_error",
|
||||
// Designates an event indicating that the subject of the XMPP MUC has
|
||||
// changed.
|
||||
SUBJECT_CHANGED: "xmpp.subject_changed",
|
||||
// Designates an event indicating that an XMPP message in the MUC was
|
||||
// received.
|
||||
MESSAGE_RECEIVED: "xmpp.message_received",
|
||||
// Designates an event indicating that we sent an XMPP message to the MUC.
|
||||
SENDING_CHAT_MESSAGE: "xmpp.sending_chat_message",
|
||||
// Designates an event indicating that the video type (e.g. 'camera' or
|
||||
// 'screen') for a participant has changed.
|
||||
PARTICIPANT_VIDEO_TYPE_CHANGED: "xmpp.video_type",
|
||||
// Designates an event indicating that a participant in the XMPP MUC has
|
||||
// advertised that they have audio muted (or unmuted).
|
||||
PARTICIPANT_AUDIO_MUTED: "xmpp.audio_muted",
|
||||
// Designates an event indicating that a participant in the XMPP MUC has
|
||||
// advertised that they have video muted (or unmuted).
|
||||
PARTICIPANT_VIDEO_MUTED: "xmpp.video_muted",
|
||||
// Designates an event indicating that the focus has asked us to mute our
|
||||
// audio.
|
||||
AUDIO_MUTED_BY_FOCUS: "xmpp.audio_muted_by_focus",
|
||||
// Designates an event indicating that a moderator in the room changed the
|
||||
// "start muted" settings for the conference.
|
||||
START_MUTED_SETTING_CHANGED: "xmpp.start_muted_setting_changed",
|
||||
// Designates an event indicating that we should join the conference with
|
||||
// audio and/or video muted.
|
||||
START_MUTED_FROM_FOCUS: "xmpp.start_muted_from_focus",
|
||||
|
||||
|
||||
PEERCONNECTION_READY: "xmpp.peerconnection_ready",
|
||||
CONFERENCE_SETUP_FAILED: "xmpp.conference_setup_failed",
|
||||
PASSWORD_REQUIRED: "xmpp.password_required",
|
||||
AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
|
||||
CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
|
||||
ETHERPAD: "xmpp.etherpad",
|
||||
DEVICE_AVAILABLE: "xmpp.device_available",
|
||||
VIDEO_TYPE: "xmpp.video_type",
|
||||
PEERCONNECTION_READY: "xmpp.peerconnection_ready",
|
||||
CONFERENCE_SETUP_FAILED: "xmpp.conference_setup_failed",
|
||||
AUDIO_MUTED: "xmpp.audio_muted",
|
||||
VIDEO_MUTED: "xmpp.video_muted",
|
||||
AUDIO_MUTED_BY_FOCUS: "xmpp.audio_muted_by_focus",
|
||||
START_MUTED_SETTING_CHANGED: "xmpp.start_muted_setting_changed",
|
||||
START_MUTED_FROM_FOCUS: "xmpp.start_muted_from_focus",
|
||||
BRIDGE_DOWN: "xmpp.bridge_down",
|
||||
PRESENCE_STATUS: "xmpp.presence_status",
|
||||
RESERVATION_ERROR: "xmpp.room_reservation_error",
|
||||
DISPOSE_CONFERENCE: "xmpp.dispose_conference",
|
||||
GRACEFUL_SHUTDOWN: "xmpp.graceful_shutdown",
|
||||
// TODO: only used in a hack, should probably be removed.
|
||||
SET_LOCAL_DESCRIPTION_ERROR: 'xmpp.set_local_description_error',
|
||||
// TODO: only used in a hack, should probably be removed.
|
||||
SET_REMOTE_DESCRIPTION_ERROR: 'xmpp.set_remote_description_error',
|
||||
// TODO: only used in a hack, should probably be removed.
|
||||
CREATE_ANSWER_ERROR: 'xmpp.create_answer_error',
|
||||
JINGLE_FATAL_ERROR: 'xmpp.jingle_fatal_error',
|
||||
PROMPT_FOR_LOGIN: 'xmpp.prompt_for_login',
|
||||
|
||||
Reference in New Issue
Block a user