-
-
diff --git a/interface_config.js b/interface_config.js
deleted file mode 100644
index 0317683e8..000000000
--- a/interface_config.js
+++ /dev/null
@@ -1,23 +0,0 @@
-var interfaceConfig = {
- CANVAS_EXTRA: 104,
- CANVAS_RADIUS: 7,
- SHADOW_COLOR: '#ffffff',
- INITIAL_TOOLBAR_TIMEOUT: 20000,
- TOOLBAR_TIMEOUT: 4000,
- DEFAULT_REMOTE_DISPLAY_NAME: "Fellow Jitster",
- DEFAULT_DOMINANT_SPEAKER_DISPLAY_NAME: "speaker",
- DEFAULT_LOCAL_DISPLAY_NAME: "me",
- SHOW_JITSI_WATERMARK: true,
- JITSI_WATERMARK_LINK: "https://jitsi.org",
- SHOW_BRAND_WATERMARK: false,
- BRAND_WATERMARK_LINK: "",
- SHOW_POWERED_BY: false,
- GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
- APP_NAME: "Jitsi Meet",
- INVITATION_POWERED_BY: true,
- ACTIVE_SPEAKER_AVATAR_SIZE: 100,
- /**
- * Whether to only show the filmstrip (and hide the toolbar).
- */
- filmStripOnly: false
-};
diff --git a/lang/Translation.md b/lang/Translation.md
deleted file mode 100644
index 2911c3412..000000000
--- a/lang/Translation.md
+++ /dev/null
@@ -1,57 +0,0 @@
-Jitsi Meet Translation
-==========================
-Jitsi Meet uses [i18next](http://i18next.com) library for translation.
-i18next uses separate json files for each language.
-
-
-Translating Jitsi Meet
-======================
-The translation of Jitsi Meet is integrated with Pootle. You can translate Jitsi Meet via our Pootle user interface on
-[http://translate.jitsi.org](http://translate.jitsi.org).
-
-**WARNING: Please don't create or edit manually the language files! Please use our Pootle user interface!**
-
-Development
-===========
-If you want to add new functionality for Jitsi Meet and you have texts that need to be translated please use our translation module.
-It is located in modules/translation. You must add key and value in main.json file in English for each translatable text.
-Than you can use the key to get the translated text for the current language.
-
-**WARNING: Please don't change the other language files except main.json! They must be updated and translated via our Pootle user interface!**
-
-You can add translatable text in the HTML:
-
-
-* **via attribute on HTML element** - add **data-i18n** attribute with value the key of the translatable text.
-
-
- ```
- OK
- ```
-
-
- You can also use APP.translation.generateTranslationHTML(key, options) to get this HTML code as Javascript string.
-
-
- ```
- APP.translation.generateTranslationHTML("dialog.OK") // returns OK
- ```
-
- The value in the options parameter will be added in data-i18n-options attribute of the element.
-
- **Note:** If you dynamically add HTML elements don't forget to call APP.translation.translateElement(jquery_selector) to translate the text initially.
-
-* **via Javascript string** - call APP.translation.translateString(key, options). You can use that method to get the translated string in Javascript and then attach it in the HTML.
-
- ```
- APP.translation.translateString("dialog.OK") // returns the value for the key of the current language file. "OK" for example.
- ```
-
-For the available values of ``options`` parameter for the above methods of translation module see [i18next documentation](http://i18next.com/pages/doc_features).
-
-**Note:** It is useful to add attributes in the HTML for persistent HTML elements because when the language is changed the text will be automatically translated.
- Otherwise you should call ``APP.translation.translateString`` and manually change the text every time the language is changed.
-
-
-
-
diff --git a/lang/languages-bg.json b/lang/languages-bg.json
deleted file mode 100644
index cff4ab662..000000000
--- a/lang/languages-bg.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "en": "Английски",
- "bg": "Български",
- "de": "Немски",
- "tr": "Турски",
- "it": "Италиански"
-}
\ No newline at end of file
diff --git a/lang/languages-de.json b/lang/languages-de.json
deleted file mode 100644
index 149a29e5b..000000000
--- a/lang/languages-de.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "en": "Englisch",
- "bg": "Bulgarisch",
- "de": "Deutsch",
- "tr": "Türkisch",
- "it": "Italienisch",
- "fr": "Französisch"
-}
\ No newline at end of file
diff --git a/lang/languages-fr.json b/lang/languages-fr.json
deleted file mode 100644
index f50dd22d2..000000000
--- a/lang/languages-fr.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "en": "Anglais",
- "bg": "Bulgare",
- "de": "Allemand",
- "tr": "Turc",
- "it": "Italien"
-}
\ No newline at end of file
diff --git a/lang/languages-it.json b/lang/languages-it.json
deleted file mode 100644
index a9831eaed..000000000
--- a/lang/languages-it.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "en": "Inglese",
- "bg": "Bulgaro",
- "de": "Tedesco",
- "tr": "Turco",
- "it": "Italiano"
-}
\ No newline at end of file
diff --git a/lang/languages-tr.json b/lang/languages-tr.json
deleted file mode 100644
index 2d089e711..000000000
--- a/lang/languages-tr.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "en": "İngilizce",
- "bg": "Bulgarca",
- "de": "Almanca"
-}
\ No newline at end of file
diff --git a/lang/languages.json b/lang/languages.json
deleted file mode 100644
index b76ea1a15..000000000
--- a/lang/languages.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "en": "English",
- "bg": "Bulgarian",
- "de": "German",
- "tr": "Turkish",
- "it": "Italian",
- "fr": "French"
-}
diff --git a/lang/main-bg.json b/lang/main-bg.json
deleted file mode 100644
index da2cfebab..000000000
--- a/lang/main-bg.json
+++ /dev/null
@@ -1,224 +0,0 @@
-{
- "contactlist": "СПИСЪК С КОНТАКТИ",
- "connectionsettings": "Настройки на връзката",
- "poweredby": "powered by",
- "downloadlogs": "Изтегли логовете",
- "roomUrlDefaultMsg": "Конференцията се създава...",
- "participant": "Участник",
- "me": "аз",
- "speaker": "Говорител",
- "defaultNickname": "например __name__",
- "defaultPreziLink": "например __url__",
- "welcomepage": {
- "go": "Влез",
- "roomname": "Въведете име на стаята",
- "disable": "Не показвай страницата следващия път",
- "feature1": {
- "title": "Лесен за употреба",
- "content": "Не е необходимо да сваляте нищо. _app_ работи директно във вашия браузър. Просто споделете адреса на вашата конференция с другите за да започнете."
- },
- "feature2": {
- "title": "",
- "content": "Видео конференциите могат да работят с по-малко от 128Kbps, а аудио конференциите и конференциите с споделен екран дори с по-малко."
- },
- "feature3": {
- "title": "Отворен код",
- "content": "__app__ е лицензиран под MIT лиценз. Можете свободно да го изтеглите, използвате, променяте и споделяте според тези лицензи."
- },
- "feature4": {
- "title": "Неограничен брой потребители",
- "content": "Няма изкуствени ограничения за броя на потребителите или участниците в конференция. Единствените ограничения са мощността на вашия сървър и качеството на интернет връзката му."
- },
- "feature5": {
- "title": "Споделяне на екрана",
- "content": "Лесно е да споделите екрана си с другите. __app__ е идеален за онлайн презентации, лекции и техническа подръжка."
- },
- "feature6": {
- "title": "Сигурни стаи",
- "content": "Нуждаете се от уединение? _app__ конферентните стай могат да бъдат защитени от парола за да се препазите от нежелани гости или прекъсвания."
- },
- "feature7": {
- "title": "Споделени бележки",
- "content": "__app__ използва Etherpad, с който можете да редактирате текст в реално време заедно."
- },
- "feature8": {
- "title": "Статистики за използване",
- "content": "Научете повече за своите потребители като интегрирате лесно Piwik, Google Analytics и други статистики за изполването."
- }
- },
- "toolbar": {
- "mute": "Включи / Изключи микрофона",
- "videomute": "Спри / пусни камерата",
- "authenticate": "",
- "record": "Запис",
- "lock": "Заключи / отключи стаята",
- "invite": "Поканване на други",
- "chat": "",
- "prezi": "Сподели Prezi",
- "etherpad": "Споделяне на документ",
- "sharescreen": "Споделяне на екрана",
- "fullscreen": "Влез / Излез от Пълен екран",
- "sip": "Обади се на SIP номер",
- "Settings": "Настройки",
- "hangup": "Затвори",
- "login": "Влез",
- "logout": ""
- },
- "bottomtoolbar": {
- "chat": "Отвори / затвори чат",
- "filmstrip": "Покажи / скрий лентата с видеа",
- "contactlist": "Отвори / затвори контакт листа"
- },
- "chat": {
- "nickname": {
- "title": "Въведете име в полето",
- "popover": "Избор на име"
- },
- "messagebox": "Въведете текст..."
- },
- "settings": {
- "title": "НАСТРОЙКИ",
- "update": "Актуализиране",
- "name": "Име"
- },
- "videothumbnail": {
- "editnickname": "Натиснете за да промените името",
- "moderator": "Създателя на конференцията",
- "videomute": "Учасника е спрял камерата си.",
- "mute": "Учасника е с изключен микрофон",
- "kick": "Изгони",
- "muted": "Изключен микрофон",
- "domute": "Изключи микрофона"
- },
- "connectionindicator": {
- "bitrate": "",
- "packetloss": "Загуба на пакети:",
- "resolution": "Резолюция:",
- "less": "Скрий",
- "more": "Покажи",
- "address": "Адрес:",
- "remoteport": "Отдалечен порт:",
- "remoteport_plural": "Отдалечени портове:",
- "localport": "Локален порт:",
- "localport_plural": "Локални портове:",
- "localaddress": "Локален адрес:",
- "localaddress_plural": "Локални адреси:",
- "remoteaddress": "Отдалечен адрес:",
- "remoteaddress_plural": "Отдалечени адреси:",
- "transport": "Транспорт:",
- "bandwidth": "",
- "na": "Върнете се тук за информацията относно вашата връзка, когато започне конференцията"
- },
- "notify": {
- "disconnected": "връзката е прекъсната",
- "moderator": "Придобихте права на модератор!",
- "connected": "свързан",
- "somebody": "Някой",
- "me": "Аз",
- "focus": "Конферентен фокус",
- "focusFail": "__component__ не е на раположения - следващ опит след __ms__ секунди",
- "grantedTo": "Даване на роля модератор на __to__!",
- "grantedToUnknown": "Даване на роля модератор на $t(somebody)!"
- },
- "dialog": {
- "kickMessage": "Бяхте изгонен от срещата!",
- "popupError": "Вашия браузър блокира попъп прозорците от този сайт. Моля позволете попъп прозорците от настройките на браузъра и опитайте пак.",
- "passwordError": "Тази конференция е защитена с парола. Само създателя и може да промени паролата.",
- "passwordError2": "Тази конференция не е защитена с парола. Само създателя и може да сложи парола.",
- "joinError": "Не можете да се присъедините към конференцията. Може би имате проблем с конфигурацията на сифурността. Моля обърнете се към администратора на услугата.",
- "connectError": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията.",
- "connecting": "",
- "error": "",
- "detectext": "Възникна грешка при опит да бъде намерено разширението за споделяне на екран.",
- "failtoinstall": "Неуспешна инсталация на разширението за споделяне на екрана.",
- "failedpermissions": "Неуспешен опит за получаване на права за използване на микрофон и/или камера.",
- "bridgeUnavailable": "Jitsi Videobridge не е наличен. Моля опитайте пак!",
- "lockTitle": "Неуспешно заключване",
- "lockMessage": "Неуспешно заключване на конференцията.",
- "warning": "Внимание",
- "passwordNotSupported": "В момента не поддържаме стаи с пароли.",
- "sorry": "Съжаляваме",
- "internalError": "Вътрешна грешка [setRemoteDescription]",
- "unableToSwitch": "Неуспешен опит за смяна на видеото.",
- "SLDFailure": "Опа! Нещо се обърка и не успяхме да спрем микрофона! (SLD Failure)",
- "SRDFailure": "Опа! Нещо се обърка и не успяхме да спрем камерата! (SRD Failure)",
- "oops": "Опа!",
- "defaultError": "Възникна грешка",
- "passwordRequired": "Изисква се парола",
- "Ok": "ОК",
- "removePreziTitle": "Премахни Prezi",
- "removePreziMsg": "Сигурни ли сте, че искате да премахнете Prezi?",
- "sharePreziTitle": "Сподели Prezi",
- "sharePreziMsg": "Друг участник вече е споделил Prezi. Тази конференция позволява само да се споделя само едно Prezi.",
- "Remove": "Премахване",
- "Stop": "Спиране",
- "AuthMsg": "Нужна е идентификация, за да създадете стая: __room__ Може да се идентифицирате, за да създадете стая или да изчакате някой друг да го направи.",
- "Authenticate": "Идентификация",
- "Cancel": "Отказ",
- "retry": "Повторен опит",
- "logoutTitle": "Изход",
- "logoutQuestion": "Сигурни ли сте, че искате да излезете и да прекъснете конференцията?",
- "sessTerminated": "Сесията е прекъсната.",
- "hungUp": "Вие затворихте обаждането.",
- "joinAgain": "Песъединете се отново",
- "Share": "Споделяне",
- "preziLinkError": "Моля въведете правилен Prezi линк.",
- "Save": "Запазване",
- "recordingToken": "Въведете код за достъп за запис на конференцията",
- "Dial": "Набиране",
- "sipMsg": "Въведете SIP номер",
- "passwordCheck": "Сигурни ли сте, че искате да махнете паролата?",
- "passwordMsg": "Въведете парола, за да заключите стаята",
- "Invite": "Покани",
- "shareLink": "Сподели този линк с всеки, който искаш да поканиш",
- "settings1": "Конфигурирай конференцията",
- "settings2": "Участниците се присъединиха с изключен микрофон.",
- "settings3": "Изисквай имена
Въведете парола за да заключите стаята:",
- "yourPassword": "вашата парола",
- "Back": "Назад",
- "serviceUnavailable": "Услугата не е налична",
- "gracefulShutdown": "Услугата временно не е достъпна поради профилактика. Моля опитайте по-късно.",
- "Yes": "Да",
- "reservationError": "Грешка в системата за резервации",
- "reservationErrorMsg": "Грешка номер: __code__, съобщение: __msg__",
- "password": "парола",
- "userPassword": "потребителска парола",
- "token": "код за достъп"
- },
- "email": {
- "sharedKey": [
- "Тази конференция е защитена с парола. Моля използвайте следния код за да се присъедините:",
- "",
- "",
- "__sharedKey__",
- "",
- ""
- ],
- "subject": "Покана за __appName__ (__conferenceName__)",
- "body": [
- "Здравей, Бих искал да те поканя в една __appName__ конференция, която създадох.",
- "",
- "",
- "Кликни на следния линк за да се присъединиш в конференцията.",
- "",
- "",
- "__sharedKeyText__",
- "__appName__ поддържа __supportedBrowsers__, така че трябва да използваш един от тези браузъри.",
- "",
- "",
- "Ще се видим след секунда!"
- ],
- "and": "и"
- },
- "connection": {
- "ERROR": "Грешка",
- "CONNECTING": "Свързване",
- "CONNFAIL": "Връзката е неуспешна",
- "AUTHENTICATING": "Идентификация",
- "AUTHFAIL": "Неуспешна идентификация",
- "CONNECTED": "Свързан",
- "DISCONNECTED": "Изключен",
- "DISCONNECTING": "Прекъсване на връзката",
- "ATTACHED": "Прикрепен"
- }
-}
\ No newline at end of file
diff --git a/lang/main-de.json b/lang/main-de.json
deleted file mode 100644
index d15d3e06b..000000000
--- a/lang/main-de.json
+++ /dev/null
@@ -1,243 +0,0 @@
-{
- "contactlist": "Kontaktliste",
- "connectionsettings": "Verbindungseinstellungen",
- "poweredby": "Betrieben von",
- "downloadlogs": "Log herunterladen",
- "roomUrlDefaultMsg": "Die Konferenz wird erstellt...",
- "participant": "Teilnehmer",
- "me": "ich",
- "speaker": "Sprecher",
- "defaultNickname": "Bsp.: __name__",
- "defaultPreziLink": "Bsp.: __url__",
- "welcomepage": {
- "go": "Los",
- "roomname": "Raumnamen eingeben",
- "disable": "Diese Seite beim nächsten Betreten nicht mehr anzeigen",
- "feature1": {
- "title": "Einfach zu benutzen",
- "content": "Kein Download nötig. __app__ läuft direkt im Browser. Einfach die Konferenzadresse teilen und los geht's."
- },
- "feature2": {
- "title": "Niedrige Bandbreite",
- "content": "Videokonferenzen mit mehreren Teilnehmen mit weniger als 128Kpbs. Bildschirmfreigaben und Telefonkonferenzen kommen sogar mit noch weniger Bandbreite aus."
- },
- "feature3": {
- "title": "Open Source",
- "content": "__app__ steht unter der MIT Lizenz. __app__ kann gemäss der Lizenz heruntergeladen, verwendet, verändert und weitergegeben werden."
- },
- "feature4": {
- "title": "Unbegrenzte Anzahl Benutzer",
- "content": "Es gibt keine künstliche Beschränkung der Anzahl der Benutzer oder Konferenzteilnehmer. Die Leistung des Servers und die Bandbreite sind die einzigen limitierenden Faktoren."
- },
- "feature5": {
- "title": "Bildschirmfreigabe",
- "content": "Es ist ganz einfach den Bildschirm zu teilen. __app__ ist ideal für Online-Präsentationen, Vorlesungen und Fernwartungsanfragen."
- },
- "feature6": {
- "title": "Sichere Konferenzen",
- "content": "Privatsphäre gewünscht? __app__ Konferenzen können mit einem Passwort geschützt werden um ungebetene Gäste fernzuhalten und Unterbrechungen zu vermeiden."
- },
- "feature7": {
- "title": "Freigegebene Notizen",
- "content": "__app__ verwendent Etherpad, ein Editor zur kollaborativen Bearbeitung von Texten."
- },
- "feature8": {
- "title": "Benutzungsstatistiken",
- "content": "Die Verwendung kann durch die Integration mit Piwik, Google Analytics und anderen Überwachungs- und Statistikprogrammen protokolliert werden."
- }
- },
- "toolbar": {
- "mute": "Stummschaltung aktivieren / deaktivieren",
- "videomute": "Kamera starten / stoppen",
- "authenticate": "Anmelden",
- "record": "Aufnehmen",
- "lock": "Raum schützen / Schutz aufheben",
- "invite": "Andere einladen",
- "chat": "Chat öffnen / schliessen",
- "prezi": "Prezi freigeben",
- "etherpad": "Geteiltes Dokument",
- "sharescreen": "Bildschirm freigeben",
- "fullscreen": "Vollbildmodus aktivieren / deaktivieren",
- "sip": "SIP Nummer anrufen",
- "Settings": "Einstellungen",
- "hangup": "Auflegen",
- "login": "Anmelden",
- "logout": "Abmelden",
- "dialpad": "Tastenblock anzeigen"
- },
- "bottomtoolbar": {
- "chat": "Chat öffnen / schliessen",
- "filmstrip": "Videovorschauen anzeigen / verstecken",
- "contactlist": "Kontaktliste öffnen / schliessen"
- },
- "chat": {
- "nickname": {
- "title": "Nickname im Eingabefeld eingeben",
- "popover": "Einen Namen auswählen"
- },
- "messagebox": "Text eingeben..."
- },
- "settings": {
- "title": "Einstellungen",
- "update": "Aktualisieren",
- "name": "Name",
- "startAudioMuted": "Stumm beitreten",
- "startVideoMuted": "Ohne Video beitreten"
- },
- "videothumbnail": {
- "editnickname": "Klicken um den Anzeigenamen zu bearbeiten",
- "moderator": "Besitzer dieser Konferenz",
- "videomute": "Teilnehmer hat die Kamera pausiert.",
- "mute": "Teilnehmer ist stumm geschaltet",
- "kick": "Hinauswerfen",
- "muted": "Stummgeschaltet",
- "domute": "Stummschalten"
- },
- "connectionindicator": {
- "bitrate": "Bitrate:",
- "packetloss": "Paketverlust:",
- "resolution": "Auflösung:",
- "less": "Weniger anzeigen",
- "more": "Mehr anzeigen",
- "address": "Adresse:",
- "remoteport": "Entfernter Port:",
- "remoteport_plural": "Entfernte Ports:",
- "localport": "Lokaler Port:",
- "localport_plural": "Lokale Ports:",
- "localaddress": "Lokale Adresse:",
- "localaddress_plural": "Lokale Adressen:",
- "remoteaddress": "Entfernte Adresse:",
- "remoteaddress_plural": "Entfernte Adressen:",
- "transport": "Protokoll:",
- "bandwidth": "Geschätzte Bandbreite:",
- "na": "Verbindungsdaten erneut anzeigen wenn die Konferenz begonnen hat"
- },
- "notify": {
- "disconnected": "getrennt",
- "moderator": "Moderatorenrechte vergeben",
- "connected": "verbunden",
- "somebody": "Jemand",
- "me": "Ich",
- "focus": "Konferenz-Organisator",
- "focusFail": "__component__ ist im Moment nicht verfügbar - wiederholen in __ms__ Sekunden",
- "grantedTo": "Moderatorenrechte an __to__ vergeben.",
- "grantedToUnknown": "Moderatorenrechte an $t(somebody) vergeben.",
- "muted": "Der Konferenz wurde stumm beigetreten.",
- "mutedTitle": "Stummschaltung aktiv."
- },
- "dialog": {
- "kickMessage": "Oh! Sie wurden aus der Konferenz ausgeschlossen.",
- "popupError": "Ihr Browser blockiert Popups von dieser Webseite. Bitte erlauben Sie Popups in den Sicherheitseinstellungen und versuchen Sie es erneut.",
- "passwordError": "Diese Konferenz ist mit einem Paswort geschützt. Nur der Besitzer der Konferenz kann ein Passwort vergeben.",
- "passwordError2": "Diese Konferenzt ist nicht mit einem Passwort geschützt. Nur der Besitzer der Konferenz kann ein Passwort vergeben.",
- "joinError": "Oh! Der Konferenz konnte nicht beigetreten werden. Diese könnte ein Problem mit den Sicherheitseinstellungen sein. Bitte kontaktieren Sie den Administrator des Dienstes.",
- "connectError": "Oh! Es hat etwas nicht geklappt und der Konferenz konnte nicht beigetreten werden.",
- "connectErrorWithMsg": "Oh! Es hat etwas nicht geklappt und der Konferenz konnte nicht beigetreten werden: __msg__",
- "connecting": "Verbindung wird hergestellt",
- "error": "Fehler",
- "detectext": "Fehler bei der Erkennung der Bildschirmfreigabeerweiterung.",
- "failtoinstall": "Die Bildschirmfreigabeerweiterung konnte nicht installiert werden.",
- "failedpermissions": "Die Zugriffsberechtigungen auf das Mikrofon und/oder die Kamera konnte nicht eingeholt werden.",
- "bridgeUnavailable": "Die Jitsi Videobridge ist momentan nicht erreichbar. Bitte versuchen Sie es später noch einmal.",
- "lockTitle": "Sperren fehlgeschlagen",
- "lockMessage": "Die Konferenz konnte nicht gesperrt werden.",
- "warning": "Warnung",
- "passwordNotSupported": "Passwörter für Räume werden nicht unterstützt.",
- "sorry": "Entschuldigung",
- "internalError": "Interner Anwendungsfehler [setRemoteDescription]",
- "unableToSwitch": "Der Videodatenstrom kann nicht gewechselt werden.",
- "SLDFailure": "Oh! Die Stummschaltung konnte nicht aktiviert werden. (SLD Fehler)",
- "SRDFailure": "Oh! Das Video konnte nicht gestoppt werden. (SRD Fehler)",
- "oops": "Oh!",
- "defaultError": "Es ist ein Fehler aufgetreten",
- "passwordRequired": "Passwort erforderlich",
- "Ok": "OK",
- "removePreziTitle": "Prezi entfernen",
- "removePreziMsg": "Sind Sie sich sicher dass sie Prezi entfernen möchten?",
- "sharePreziTitle": "Ein Prezi teilen",
- "sharePreziMsg": "Ein anderer Teilnehmer teilt bereits ein Prezi. Diese Konferenz kann nur eine Prezi auf einmal anzeigen.",
- "Remove": "Entfernen",
- "WaitingForHost": "Warten auf den Organisator...",
- "WaitForHostMsg": "Die Konferenz __room__ hat noch nicht begonnen. Wenn Sie der Organisator sind, melden Sie sich bitte an. Anderenfalls warten Sie bitte bis der Organisator beigetreten ist.",
- "IamHost": "Ich bin der Organisator",
- "Cancel": "Abbrechen",
- "retry": "Wiederholen",
- "logoutTitle": "Abmelden",
- "logoutQuestion": "Sind Sie sicher dass Sie sich abmelden und die Konferenz verlassen möchten?",
- "sessTerminated": "Sitzung beendet",
- "hungUp": "Anruf beendet",
- "joinAgain": "Erneut beitreten",
- "Share": "Teilen",
- "preziLinkError": "Bitte einen gültigen Prezi-Link angeben.",
- "Save": "Speichern",
- "recordingToken": "Aufnahme-Token eingeben",
- "Dial": "Wählen",
- "sipMsg": "Geben Sie eine SIP Nummer ein",
- "passwordCheck": "Sind Sie sicher dass Sie das Passwort entfernen möchten?",
- "passwordMsg": "Passwort setzen um den Raum zu schützen",
- "Invite": "Einladen",
- "shareLink": "Teilen Sie diesen Link mit jedem den Sie einladen möchten",
- "settings1": "Konferenz einrichten",
- "settings2": "Teilnehmer treten stummgeschaltet bei",
- "settings3": "Nickname erforderlich
Setzen Sie ein Passwort um den Raum zu schützen:",
- "yourPassword": "Ihr Passwort",
- "Back": "Zurück",
- "serviceUnavailable": "Dienst nicht verfügbar",
- "gracefulShutdown": "Der Dienst steht momentan wegen Wartungsarbeiten nicht zur Verfügung. Bitte versuchen Sie es später noch einmal.",
- "Yes": "Ja",
- "reservationError": "Fehler im Reservationssystem",
- "reservationErrorMsg": "Fehler, Nummer: __code__, Nachricht: __msg__",
- "password": "Passwort",
- "userPassword": "Benutzerpasswort",
- "token": "Token",
- "displayNameRequired": "Geben Sie Ihren Anzeigenamen ein:"
- },
- "email": {
- "sharedKey": [
- "Diese Konferenz ist Passwortgeschützt. Bitte verwenden Sie diese PIN zum Beitreten:",
- "",
- "",
- "__sharedKey__",
- "",
- ""
- ],
- "subject": "Einladung zu einer __appName__ (__conferenceName__)",
- "body": [
- "Hallo!",
- "",
- "",
- "Ich möchte dich zu einer eben erstellten __appName__-Konferenz einladen.",
- "",
- "",
- "Bitte klicke auf den folgenden Link um der Konferenz ebenfalls beizutreten:",
- "",
- "",
- "__roomUrl__",
- "",
- "",
- "__sharedKeyText__",
- " Bitte beachte, dass __appName__ momentan nur mit einem der Browser __supportedBrowsers__ verwendet werden kann.",
- "",
- "",
- "Bis gleich!"
- ],
- "and": "und"
- },
- "connection": {
- "ERROR": "Fehler",
- "CONNECTING": "Verbindung wird hergestellt",
- "RECONNECTING": "Es ist ein Netzwerkproblem aufgetreten. Verbinde...",
- "CONNFAIL": "Verbindungsaufbau gescheitert",
- "AUTHENTICATING": "Anmeldung läuft",
- "AUTHFAIL": "Authentifizierung fehlgeschlagen",
- "CONNECTED": "Verbunden",
- "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"
- }
-}
\ No newline at end of file
diff --git a/lang/main-fr.json b/lang/main-fr.json
deleted file mode 100644
index 8d2d8ff0a..000000000
--- a/lang/main-fr.json
+++ /dev/null
@@ -1,227 +0,0 @@
-{
- "contactlist": "Liste de contacts",
- "connectionsettings": "Paramètres de connexion",
- "poweredby": "propulsé par",
- "downloadlogs": "Téléchargement des logs",
- "roomUrlDefaultMsg": "Votre conférence est en cours de création...",
- "participant": "Participant",
- "me": "moi",
- "speaker": "Haut-parleur",
- "defaultNickname": "ex: __name__",
- "defaultPreziLink": "e.g. __url__",
- "welcomepage": {
- "go": "Créer",
- "roomname": "Saisissez un nom de salle",
- "disable": "Ne pas afficher cette page lors de ma prochaine visite",
- "feature1": {
- "title": "Simple à utiliser",
- "content": "Aucun téléchargement requis. __app__ s'utilise directement depuis votre navigateur. Partager simplement l'URL de votre conférence avec les autres pour commencer."
- },
- "feature2": {
- "title": "Faible bande passante",
- "content": "Les vidéo conférences à plusieurs participants nécessitent moins de 128 kbps. Le partage d'écran et les conférences avec seulement de l'audio sont possibles avec beaucoup moins de débit."
- },
- "feature3": {
- "title": "Open source",
- "content": "__app__ est sous licence MIT. Vous êtes libre de le télécharger, l'utiliser, le modifier et le partager sous cette licence."
- },
- "feature4": {
- "title": "Nombre d'utilisateurs illimité",
- "content": "Il n'y a pas de restrictions artificielles concernant le nombre d'utilisateurs ou de participants à une conférence. La puissance du serveur et la bande passante sont les seuls facteurs limitants."
- },
- "feature5": {
- "title": "Partage d'écan",
- "content": "C'est facile de partager votre écran avec d'autres personnes. __app__ est idéal pour les présentations en ligne, les cours, et les sessions de support technique."
- },
- "feature6": {
- "title": "Salles sécurisées",
- "content": "Besoin de confidentialité? Les salles de conférence __app__ peuvent être sécurisées par un mot de passe pour exclure des invités non désirées, et prévenir des interruptions. "
- },
- "feature7": {
- "title": "Notes partagées",
- "content": "__app__ propose Etherpad, un éditeur de texte collaboratif en temps réel qui est parfait pour les procès-verbaux, l'édition d'articles et plus encore."
- },
- "feature8": {
- "title": "Statistiques d'utilisation",
- "content": "Connaissez mieux vos utilisateurs avec une intégration facile de Piwik, Google Analytics et d'autres systèmes de statistiques et supervision d'utilisation."
- }
- },
- "toolbar": {
- "mute": "Muet / Actif",
- "videomute": "Démarrer / Arrêter la caméra",
- "authenticate": "",
- "record": "Enregistrer",
- "lock": "Verrouiller / déverrouiller la salle",
- "invite": "Inviter des participants",
- "chat": "",
- "prezi": "Partager une présentation Prezi",
- "etherpad": "Partager un document",
- "sharescreen": "Partager mon écran",
- "fullscreen": "Activer / Désactiver le plein écran",
- "sip": "Appeler un numéro SIP",
- "Settings": "Paramètres",
- "hangup": "Raccrocher",
- "login": "Connexion",
- "logout": ""
- },
- "bottomtoolbar": {
- "chat": "Ouvrir / fermer le chat",
- "filmstrip": "Montrer / cacher ma vidéo miniature",
- "contactlist": "Ouvrir / fermer ma liste de contacts"
- },
- "chat": {
- "nickname": {
- "title": "Saisissez un pseudonyme dans le champ ci-dessous",
- "popover": "Choisissez un pseudonyme"
- },
- "messagebox": "Saisissez votre texte..."
- },
- "settings": {
- "title": "PARAMÈTRES",
- "update": "Mise à jour",
- "name": "Nom"
- },
- "videothumbnail": {
- "editnickname": "Cliquez pour modifier votre nom",
- "moderator": "Le propriétaire de cette conférence",
- "videomute": "Un participant a arrêté sa caméra.",
- "mute": "Un participant a coupé son micro",
- "kick": "Exclure",
- "muted": "Coupé",
- "domute": "Couper le son"
- },
- "connectionindicator": {
- "bitrate": "Débit",
- "packetloss": "Perte de paquets:",
- "resolution": "Résolution:",
- "less": "Cacher le détail",
- "more": "Montrer le détail",
- "address": "Adresse:",
- "remoteport": "Port distant:",
- "remoteport_plural": "Ports distants:",
- "localport": "Port local:",
- "localport_plural": "Ports locaux:",
- "localaddress": "Adresse locale:",
- "localaddress_plural": "Adresses locales:",
- "remoteaddress": "Adresse distante:",
- "remoteaddress_plural": "Adresses distantes:",
- "transport": "Transport:",
- "bandwidth": "Bande passante estimée:",
- "na": "Revenez ici pour afficher les informations de connexion une fois la conférence démarrée"
- },
- "notify": {
- "disconnected": "Déconnecté",
- "moderator": "Droits modérateur accordés!",
- "connected": "Connecté",
- "somebody": "Quelqu'un",
- "me": "Moi",
- "focus": "",
- "focusFail": "__component__ n'est pas disponible - réessayez dans __ms__ sec",
- "grantedTo": "Droits modérateur accordés à __to__!",
- "grantedToUnknown": "Droits modérateur accordés à $t(somebody)!"
- },
- "dialog": {
- "kickMessage": "Oups! Vous avez été renvoyé de la réunion!",
- "popupError": "Votre navigateur bloque les popups pour ce site. Activez les popups pour ce site dans vos paramètres de sécurité et réessayez.",
- "passwordError": "Cette conversation est protégée par un mot de passe. Seul le propriétaire de cette conférence peut paramétrer un mot de passe.",
- "passwordError2": "Cette conversation n'est pas protégée par un mot de passe. Seul le propriétaire de cette conférence peut paramétrer un mot de passe.",
- "joinError": "Oups! La conférence ne peut être rejointe. Il y a peut-être un souci avec les paramètres de sécurité. Contactez l'administrateur.",
- "connectError": "Oups! Un problème est survenu et la connexion à la conférence est impossible.",
- "connecting": "",
- "error": "",
- "detectext": "Une erreur est survenue pendant la détection de l'extension de partage d'écran.",
- "failtoinstall": "Échec de l'installation de l'extension de partage d'écran",
- "failedpermissions": "Échec d'obtention des permissions pour utiliser le micro et/ou la caméra local(e)",
- "bridgeUnavailable": "Le pont de visioconférence Jitsi est indisponible pour le moment. Réessayez plus tard!",
- "lockTitle": "Échec du verrouillage",
- "lockMessage": "Impossible de verrouiller la conférence.",
- "warning": "Avertissement",
- "passwordNotSupported": "Les mots de passe de conférence ne sont pas supportés.",
- "sorry": "Désolé",
- "internalError": "Une erreur interne de l'application est survenue [setRemoteDescription]",
- "unableToSwitch": "Impossible de passer le flux vidéo.",
- "SLDFailure": "Oups! Un problème est survenu et le micro n'a pas été coupé! (Échec SLD)",
- "SRDFailure": "Oups! Un problème est survenu et la caméra n'a pas été coupée! (Échec SRD)",
- "oops": "Oups!",
- "defaultError": "Une erreur est survenue",
- "passwordRequired": "Mot de passe requis",
- "Ok": "Ok",
- "removePreziTitle": "Supprimer la présentation Prezi",
- "removePreziMsg": "Voulez-vous vraiment supprimer votre présentation Prezi?",
- "sharePreziTitle": "Partager une présentation Prezi",
- "sharePreziMsg": "Un autre participant partage déjà une présentation Prezi. Cette conférence autorise une seule présentation Prezi à la fois.",
- "Remove": "Supprimer",
- "Stop": "Arrêter",
- "AuthMsg": "L'authentification est requise pour créer la conférence: __room__ Vous pouvez vous authentifier pour créer la conférence ou attendre que quelqu'un le fasse pour vous.",
- "Authenticate": "Authentifiez-vous",
- "Cancel": "Annuler",
- "retry": "Réessayer",
- "logoutTitle": "Déconnexion",
- "logoutQuestion": "Voulez-vous vraiment vous déconnecter et arrêter la conférence?",
- "sessTerminated": "Session terminée",
- "hungUp": "Vous avez raccroché et quitté la conférence",
- "joinAgain": "Rejoignez à nouveau la conférence",
- "Share": "Partager",
- "preziLinkError": "Fournissez s'il vous plaît un lien prezi fonctionnel.",
- "Save": "Sauvegarder",
- "recordingToken": "Saisissez un jeton d'enregistrement",
- "Dial": "Composer",
- "sipMsg": "Saisissez un numéro SIP",
- "passwordCheck": "Voulez-vous vraiment supprimer votre mot de passe?",
- "passwordMsg": "Saisissez un mot de passe pour verrouiller la conférence",
- "Invite": "Inviter",
- "shareLink": "Partagez ce lien avec toutes les personnes que vous voulez inviter",
- "settings1": "Configurez votre conférence",
- "settings2": "Les participants rejoignent la conférence en étant muets.",
- "settings3": "Pseudonymes requis
Saisissez un mot de passe pour verrouiller la conférence:",
- "yourPassword": "Votre mot de passe",
- "Back": "Retour",
- "serviceUnavailable": "Service indisponible",
- "gracefulShutdown": "Le service est actuellement en maintenance. Réessayez plus tard.",
- "Yes": "Oui",
- "reservationError": "Erreur du système de réservation",
- "reservationErrorMsg": "Code d'erreur: __code__, message: __msg__",
- "password": "mot de passe",
- "userPassword": "mot de passe utilisateur",
- "token": "jeton"
- },
- "email": {
- "sharedKey": [
- "Cette conférence est protégée par un mot de passe. Utilisez le code suivant pour la rejoindre:",
- "",
- "",
- "__sharedKey__",
- "",
- ""
- ],
- "subject": "Invitation à la conférence __appName__ : __conferenceName__",
- "body": [
- "Bonjour, je vous invite à la conférence __appName__ que je viens de créer.",
- "",
- "",
- "Cliquez sur le lien suivant pour rejoindre la conférence.",
- "",
- "",
- "__roomUrl__",
- "",
- "",
- "__sharedKeyText__",
- " Notez que __appName__ est actuellement seulement supporté par __supportedBrowsers__, vous devez donc utiliser un de ces navigateurs.",
- "",
- "",
- "À tout de suite dans la conférence!"
- ],
- "and": "et"
- },
- "connection": {
- "ERROR": "Erreur",
- "CONNECTING": "Connexion en cours...",
- "CONNFAIL": "Échec de la Connexion",
- "AUTHENTICATING": "Authentification en cours...",
- "AUTHFAIL": "Échec de l'authentification",
- "CONNECTED": "Connecté",
- "DISCONNECTED": "Déconnecté",
- "DISCONNECTING": "Déconnexion en cours...",
- "ATTACHED": "Attachée"
- }
-}
\ No newline at end of file
diff --git a/lang/main-it.json b/lang/main-it.json
deleted file mode 100644
index ff3b07404..000000000
--- a/lang/main-it.json
+++ /dev/null
@@ -1,227 +0,0 @@
-{
- "contactlist": "LISTA CONTATTI",
- "connectionsettings": "Impostazioni Connessione",
- "poweredby": "powered by",
- "downloadlogs": "Scarica logs",
- "roomUrlDefaultMsg": "La tua conferenza sta per essere creata...",
- "participant": "Partecipante",
- "me": "io",
- "speaker": "Relatore",
- "defaultNickname": "es. __nome__",
- "defaultPreziLink": "es. __url__",
- "welcomepage": {
- "go": "VAI",
- "roomname": "Inserisci Nome Stanza",
- "disable": "Non visualizzare questa pagina la prossima volta",
- "feature1": {
- "title": "Semplice da usare",
- "content": "Nessun download richiesto. __app__ funziona direttamente nel tuo browser. Condividi semplicemente l'URL della tua conferenza con altri per iniziare."
- },
- "feature2": {
- "title": "Poca banda",
- "content": "Conferenze video multi utente funzionano con appena 128Kbps. La condivisione dello schermo ed conferenze solo audio sono possibili con molto meno."
- },
- "feature3": {
- "title": "Open source",
- "content": "__app__ è sotto licenza MIT. Sei libero di scaricarla, usarla, modificarla e condividerla con la medesima licenza."
- },
- "feature4": {
- "title": "Utenti illimitati",
- "content": "Non ci sono restrizioni sul numero di utenti per una conferenza. La potenza del server e la banda a disposizione sono gli unici fattori limitanti."
- },
- "feature5": {
- "title": "Condivisione Schermo",
- "content": "é facile condividere il tuo schermo con altri. __app__ è l'ideale per presentazioni online, letture, e sessioni di supporto tecnico."
- },
- "feature6": {
- "title": "Stanze sicure",
- "content": "Hai bisogno di più privacy? Le conferenze di __app__ possono essere rese sicure con una password per escludere ospiti non desiderati e prevenire interruzioni."
- },
- "feature7": {
- "title": "Note condivise",
- "content": "__app__ utilizza Etherpad, un editor di testo real-time e collaborativo che è ottimo per meeting, scrivere articoli e tanto altro."
- },
- "feature8": {
- "title": "Statistiche di utilizzo",
- "content": "Impara come i tuoi utenti lo utilizzano con la facile integrazione con PiWik, Google Analytics, e altri sistemi di statistica e monitor dell'utilizzo."
- }
- },
- "toolbar": {
- "mute": "Microfono Attiva / Disattiva",
- "videomute": "Abilita / Disabilita video",
- "authenticate": "",
- "record": "Registra",
- "lock": "Blocca / Sblocca Stanza",
- "invite": "Invita altri",
- "chat": "",
- "prezi": "Condividi con Prezi",
- "etherpad": "Documento condiviso",
- "sharescreen": "Condividi schermo",
- "fullscreen": "Entra / Esci da schermo intero",
- "sip": "Chiama numero SIP",
- "Settings": "Impostazioni",
- "hangup": "Termina",
- "login": "Login",
- "logout": ""
- },
- "bottomtoolbar": {
- "chat": "Apri / Chiudi chat",
- "filmstrip": "Mostra / Nascondi miniature",
- "contactlist": "Apri / Chiudi la lista contatti"
- },
- "chat": {
- "nickname": {
- "title": "Scegli un nickname nel box qui sotto",
- "popover": "Scegli un nickname"
- },
- "messagebox": "Inserisci testo..."
- },
- "settings": {
- "title": "IMPOSTAZIONI",
- "update": "Aggiorna",
- "name": "Nome"
- },
- "videothumbnail": {
- "editnickname": "Clicca per modificare il tuo nome visualizzato",
- "moderator": "Il proprietario della conferenza",
- "videomute": "Il partecipante ha fermato il video.",
- "mute": "Il partecipante è in muto",
- "kick": "Espelli",
- "muted": "Audio disattivato",
- "domute": "Disattiva audio"
- },
- "connectionindicator": {
- "bitrate": "Bitrate:",
- "packetloss": "Perdita pacchetti:",
- "resolution": "Risoluzione:",
- "less": "Mostra meno",
- "more": "Mostra di più",
- "address": "Indirizzo:",
- "remoteport": "Porta remota:",
- "remoteport_plural": "Porte remote:",
- "localport": "Porta locale:",
- "localport_plural": "Porte locali:",
- "localaddress": "Indirizzo locale:",
- "localaddress_plural": "Indirizzi locali:",
- "remoteaddress": "Indirizzo remoto:",
- "remoteaddress_plural": "Indirizzi remoti:",
- "transport": "Trasporto:",
- "bandwidth": "Banda stimata:",
- "na": "Ritorna qui per informazioni sulla connessione una volta che la conferenza inizia"
- },
- "notify": {
- "disconnected": "disconnesso",
- "moderator": "Impostati i permessi di moderatore!",
- "connected": "connesso",
- "somebody": "Qualcuno",
- "me": "io",
- "focus": "Focus su conferenza",
- "focusFail": "__component__ non disponibile - riprova in __ms__ sec",
- "grantedTo": "Permessi di moderatore garantiti a __to__!",
- "grantedToUnknown": "Permessi di moderatore garantiti a $t(somebody)!"
- },
- "dialog": {
- "kickMessage": "Accidenti! Sei stato espulso dalla conferenza !",
- "popupError": "Il tuo browser sta bloccando le finestre popup da questo sito. Abilita i popup tra le impostazioni di sicurezza del tuo browser e riprova.",
- "passwordError": "Questa conversazione è protetta da una password. Solo il proprietario della conferenza può impostare una password.",
- "passwordError2": "Questa conversazione non è al momento protetta da una password. Solo il proprietario può impostare la password.",
- "joinError": "Oops! Non puoi entrare nella conferenza. Ci deve essere qualche problema con la configurazione di sicurezza. Contattare l'amministratore di sistema.",
- "connectError": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza.",
- "connecting": "",
- "error": "",
- "detectext": "Errore durante il rilevamento dell'estensione per il desktopsharing.",
- "failtoinstall": "Impossibile installare l'estensione per il desktop sharing",
- "failedpermissions": "Impossibile ottenere i permessi per usare il microfono e/o il video locale.",
- "bridgeUnavailable": "Il Videobridge non è al momento disponibile. Si prega di riprovare più tardi!",
- "lockTitle": "Blocco fallito",
- "lockMessage": "Impossibile bloccare la conferenza.",
- "warning": "Attenzione",
- "passwordNotSupported": "Le password sulla stanza non sono al momento supportate.",
- "sorry": "Spiacente",
- "internalError": "Errore interno dell'applicazione [setRemoteDescription]",
- "unableToSwitch": "Impossibile cambiare lo stream video.",
- "SLDFailure": "Oops! Qualcosa è andato storto e non è possibile silenziare il microfono! (Errore SLD)",
- "SRDFailure": "Oops! Qualcosa è andato storto e non è possibile fermare il video! (Errore SRD)",
- "oops": "Oops!",
- "defaultError": "C'è stato qualche tipo di errore",
- "passwordRequired": "Richiesta password ",
- "Ok": "Ok",
- "removePreziTitle": "Rimuovi Prezi",
- "removePreziMsg": "Sei sicuro di voler rimuovere il tuo Prezi?",
- "sharePreziTitle": "Condividi un Prezi",
- "sharePreziMsg": "Un altro partecipante sta già condividendo un Prezi. Questa conferenza permette un solo Prezi alla volta.",
- "Remove": "Rimuovi",
- "Stop": "Ferma",
- "AuthMsg": "Autenticazione richiesta per creare la stanza: __room__ Puoi autenticarti per creare la stanza o aspettare che qualcun altro lo faccia per te.",
- "Authenticate": "Autenticazione",
- "Cancel": "Annulla",
- "retry": "Riprova",
- "logoutTitle": "Logout",
- "logoutQuestion": "Vuoi disconnetterti e interrompere la conferenza ?",
- "sessTerminated": "Sessione Terminata",
- "hungUp": "Hai terminato la conversazione",
- "joinAgain": "Entra ancora",
- "Share": "Condividi",
- "preziLinkError": "Fornire un link Prezi esatto.",
- "Save": "Salva",
- "recordingToken": "Inserire token di registrazione",
- "Dial": "Componi",
- "sipMsg": "Inserire numero SIP",
- "passwordCheck": "Confermi la rimozione della password?",
- "passwordMsg": "Imposta una password per bloccare la stanza",
- "Invite": "Invita",
- "shareLink": "Condividi questo link con tutte le persone che vuoi invitare",
- "settings1": "Configura la tua conferenza",
- "settings2": "Partecipanti connessi in muto",
- "settings3": "Richiedi nicknames
Imposta una password per bloccare la tua stanza:",
- "yourPassword": "la tua password",
- "Back": "Indietro",
- "serviceUnavailable": "Servizio non disponibile",
- "gracefulShutdown": "Il nostro servizio è al momento spento per manutenzione. Si prega di riprovare più tardi.",
- "Yes": "Sì",
- "reservationError": "Errore di sistema in prenotazione",
- "reservationErrorMsg": "Codice di errore: __code__, messaggio: __msg__",
- "password": "password",
- "userPassword": "password utente",
- "token": "token"
- },
- "email": {
- "sharedKey": [
- "Questa conferenza è protetta da password. Utilizzare il seguente PIN alla connessione:",
- "",
- "",
- "__sharedKey__",
- "",
- ""
- ],
- "subject": "Invito su __appName__ (__conferenceName__)",
- "body": [
- "Ciao, Vorrei invitarti alla conferenza che ho appena creato su __appName__ .",
- "",
- "",
- "Cliccare sul seguente link per entrare nella conferenza.",
- "",
- "",
- "__roomUrl__",
- "",
- "",
- "__sharedKeyText__",
- "NOTA: __appName__ è al momento supportato da questi browsers: __supportedBrowsers__, è necessario utilizzare uno di questi programmi per poter entrare.",
- "",
- "",
- "Ci sentiamo tra un secondo!"
- ],
- "and": "e"
- },
- "connection": {
- "ERROR": "Errore",
- "CONNECTING": "Connessione",
- "CONNFAIL": "Connessione non riuscita",
- "AUTHENTICATING": "Autenticazione",
- "AUTHFAIL": "Autenticazione fallita",
- "CONNECTED": "Connesso",
- "DISCONNECTED": "Disconnesso",
- "DISCONNECTING": "Disconnessione in corso",
- "ATTACHED": "Collegato"
- }
-}
\ No newline at end of file
diff --git a/lang/main-tr.json b/lang/main-tr.json
deleted file mode 100644
index 89a4a7e3b..000000000
--- a/lang/main-tr.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "contactlist": "KİŞİ LİSTESİ",
- "connectionsettings": "Bağlantı Ayarları",
- "poweredby": "Gücünün kaynağı",
- "downloadlogs": "Günlükleri indir",
- "welcomepage": {
- "go": "GİT",
- "roomname": "Oda adı girin",
- "disable": "Sonraki girişimde bu sayfayı gösterme",
- "feature1": {
- "title": "Kullanımı kolay",
- "content": "İndirmeye gerek yok. __app__ tarayıcınızda doğrudan çalışır. Başlamak için görüşme bağlantısını URL diğerleri ile paylaşın."
- },
- "feature2": {
- "title": "Düşük bant genişliği ihtiyacı",
- "content": "Ekran paylaşımı ve sadece ses ile çok katılımcılı video görüşmeleri, 128Kbps bağlantı ile mümkündür."
- },
- "feature3": {
- "title": "Açık kaynak kodlu",
- "content": "__app__ MIT ile lisanslanmıştır. Bu lisansa uygun olarak indirmek, kullanmak, değiştirmek ve paylaşmakta özgürsün."
- },
- "feature4": {
- "title": "Sınırsız sayıda kullanıcı",
- "content": "Kullanıcılar veya konferans katılımcılarının sayısında hiçbir yapay kısıtlama yoktur. Sadece sunucun güç ve bant genişliği, sınırlayıcı unsurdur."
- },
- "feature5": {
- "title": "Ekran paylaşımı",
- "content": "Diğerlerinle ekranınızı kolayca paylaşın. __app__ çevrimiçi sunumlar, dersler ve teknik destek oturumları için idealdir."
- },
- "feature6": {
- "title": "Güvenli odalar",
- "content": "Biraz gizliliğe ihtiyacınız var? __app__ görüşme odaları, istemeyen misafirleri uzak tutmak ve kesinleri önlemek için bir parola ile güvence altına alınabilir."
- },
- "feature7": {
- "title": "Paylaşımlı notlar",
- "content": "__app__ Etherpad içerir, gerçek zamanlı bir ortak çalışma metin düzenleyicisidir. Görüşme tutanakları, makale yazımı ve daha fazlası için biçilmiş kaftandır."
- },
- "feature8": {
- "title": "Kullanım istatistikleri",
- "content": "Piwik, Google Analytics ve diğer kullanım izleme ve istatistik sistemleri ile kolay tümleştirmeyle kullanıcılar hakkında bilgi edinin."
- }
- },
- "toolbar": {
- "mute": "Sessiz / Sesli",
- "videomute": "Kamera başlat / durdur",
- "authenticate": "",
- "record": "Kaydet",
- "lock": "Odayı kilitle / kilit aç",
- "invite": "Arkadaşlarını davet et",
- "chat": "",
- "prezi": "Prezi paylaş",
- "etherpad": "Paylaşımlı belge",
- "sharescreen": "Ekran paylaş",
- "fullscreen": "Tam Ekrana Gir / Çık",
- "sip": "SIP numara ara",
- "Settings": "Ayarlar",
- "hangup": "Kapat",
- "login": "Oturum aç",
- "logout": ""
- },
- "bottomtoolbar": {
- "chat": "Sohbeti aç / kapa",
- "filmstrip": "Kişi listesi aç / kapa",
- "contactlist": "Film şeridini göster / gizle"
- },
- "chat": {
- "nickname": {
- "title": "Aşağıdaki kutuya bir takma ad girin",
- "popover": "Bir takma ad seçin"
- },
- "messagebox": "Metin girin..."
- },
- "settings": {
- "title": "AYARLAR",
- "update": "Güncelle",
- "name": "Ad"
- },
- "videothumbnail": {
- "editnickname": "Görünür adınızı değiştirmek için tıkla",
- "moderator": "Bu görüşmenin sahibi",
- "videomute": "Katılımcı kamera durdurdu.",
- "mute": "Katılımcı sessiz",
- "kick": "Kovuldu",
- "muted": "Sessiz",
- "domute": "Sustur"
- },
- "connectionindicator": {
- "bitrate": "Bit hızı:",
- "packetloss": "Paket kaybı:",
- "resolution": "Çözünürlük:",
- "less": "Daha az göster",
- "more": "Daha fazla göster",
- "address": "Adres:",
- "remoteport": "Uzak port:Uzak portlar:",
- "localport": "Yerel port:Yerel portlar:",
- "localaddress": "Yerel adres:Yerel adresler:",
- "remoteaddress": "Uzak adres:Uzak adresler:",
- "transport": "Transport:",
- "bandwidth": "Tahmini bant genişliği:",
- "na": "Görüşme başladıktan sonra bağlantı bilgileri için buraya gel"
- },
- "notify": {
- "disconnected": "bağlantı kesildi",
- "moderator": "Görüşme yöneticisi hakları verildi!",
- "connected": "bağlandı",
- "somebody": "Birisi",
- "me": "Bana",
- "focus": "Görüşme odağı",
- "focusFail": "__component__ uygun değil - __ms__ saniye içinde tekrar deneyin",
- "grantedTo": "__to__, görüşme yöneticisi hakları verildi!",
- "grantedToUnknown": "$t(somebody), görüşme yöneticisi hakları verildi!"
- },
- "dialog": {
- "kickMessage": "Ahhh! Görüşmeden, kavuldun!",
- "popupError": "Tarayıcınız bu siteden açılır pencereleri engelliyor. Lütfen, tarayıcınızın güvenlik ayarlarında pop-up etkinleştirin ve tekrar deneyin.",
- "passwordError": "Bu görüşme şu anda bir parola ile korunmaktadır. Sadece görüşmenin sahibi bir parola ayarlayabilir.",
- "passwordError2": "Bu görüşme şu anda bir parola ile korunmamaktadır. Sadece görüşmenin sahibi bir parola ayarlayabilir.",
- "joinError": "Amanin boo! Görüşmeye katılamadık. Güvenlik yapılandırması ile ilgili bir sorun olabilir. Hizmet yöneticisi ile bağlantı kurun.",
- "connectError": "Amanin boo! Birşeyler ters gitti ve görüşmeye bağlanamadık.",
- "error": "Hata",
- "detectext": "Ekran paylaşımı eklentisi tespit edilirken hata.",
- "failtoinstall": "Masaüstü paylaşım eklentisi yüklenemedi",
- "failedpermissions": "Yerel mikrofon ve/veya kamerayı kullanmak için izinler alınamadı.",
- "bridgeUnavailable": "Jitsi Videobridge şu anda kullanılamıyor. Daha sonra tekrar deneyiniz!",
- "lockTitle": "Kilitlenemedi",
- "lockMessage": "Görüşme kilitlenemedi.",
- "warning": "Uyarı",
- "passwordNotSupported": "Oda parolaları şu anda desteklenmemekte.",
- "sorry": "Üzgünüz",
- "internalError": "İç uygulama hatası [setRemoteDescription]",
- "unableToSwitch": "Video akışı açılamıyor.",
- "SLDFailure": "Amanin boo! Birşeyler ters gitti ve sessize alamadık! (SLD Başarısız)",
- "SRDFailure": "Amanin boo! Birşeyler ters gitti ve videoyu durduramadık! (SRD Başarısız)",
- "oops": "Amanin boo!",
- "defaultError": "Bir tür hata var",
- "passwordRequired": "Parola gerekli",
- "Ok": "Tamam",
- "removePreziTitle": "Prezi kaldır",
- "removePreziMsg": "Prezi kaldırmak istediğinizden emin misiniz?",
- "sharePreziTitle": "Bir Prezi paylaşın",
- "sharePreziMsg": "Diğer katılımcı hala bir Prezi paylaşıyor.Bu görüşme aynı zamanda sadece bir Prezi izin verir.",
- "Remove": "Kaldır",
- "Stop": "Durdur",
- "AuthMsg": "Oda oluşturmak için kimlik doğrulama gerekli: __room__ Oda oluşturmak için ya kimlik doğrulamalı ya da bunu yapması için bir başkasını beklemelisiniz.",
- "Authenticate": "Kimlik doğrula",
- "Cancel": "İptal",
- "logoutTitle": "Oturum kapat",
- "logoutQuestion": "Oturumu ve görüşmeyi sonlandırmak istediğinizden emin misiniz?",
- "sessTerminated": "Oturum sonlandırıldı",
- "hungUp": "Görüşmeyi bitirdiniz",
- "joinAgain": "Yeniden katıl",
- "Share": "Paylaş",
- "preziLinkError": "Lütfen doğru prezi bağlantısı verin.",
- "Save": "Kaydet",
- "recordingToken": "Kayıt jetonu girin",
- "Dial": "Ara",
- "sipMsg": "SIP numarası gir",
- "passwordCheck": "Parolanızı kaldırmak istediğinizden emin misiniz?",
- "passwordMsg": "Odanızı kilitlemek için bir parola koyun",
- "Invite": "Davet et",
- "shareLink": "Davet etmek istediğiniz herkesle bu bağlantıyı paylaşın",
- "settings1": "Görüşmenizi yapılandır",
- "settings2": "Katılımcılar sessiz katılsın",
- "settings3": "Takma adlar gerekli
Odanızı kitlemek için bir parola ayarlayın:",
- "yourPassword": "parolanız",
- "Back": "Geri",
- "serviceUnavailable": "Hizmet kullanım dışı",
- "gracefulShutdown": "Hizmetimiz bakıp için durduruldu. Daha sonra tekrar deneyiniz.",
- "Yes": "Evet",
- "reservationError": "Rezervasyon sistemi hatası",
- "reservationErrorMsg": "Hata kodu: __code__, mesaj: __msg__"
- }
-}
\ No newline at end of file
diff --git a/lang/main.json b/lang/main.json
deleted file mode 100644
index 29df8de17..000000000
--- a/lang/main.json
+++ /dev/null
@@ -1,250 +0,0 @@
-{
- "contactlist": "CONTACT LIST",
- "connectionsettings": "Connection Settings",
- "poweredby": "powered by",
- "downloadlogs": "Download logs",
- "roomUrlDefaultMsg": "Your conference is currently being created...",
- "participant": "Participant",
- "me": "me",
- "speaker": "Speaker",
- "defaultNickname": "ex. __name__",
- "defaultPreziLink": "e.g. __url__",
- "welcomepage":{
- "go": "GO",
- "roomname": "Enter room name",
- "disable": "Don't show this page next time I enter",
- "feature1": {
- "title": "Simple to use",
- "content": "No downloads required. __app__ works directly within your browser. Simply share your conference URL with others to get started."
- },
- "feature2": {
- "title": "Low bandwidth",
- "content": "Multi-party video conferences work with as little as 128Kbps. Screen-sharing and audio-only conferences are possible with far less."
- },
- "feature3": {
- "title": "Open source",
- "content": "__app__ is licensed under MIT. You are free to download, use, modify, and share them as per these licenses."
- },
- "feature4": {
- "title": "Unlimited users",
- "content": "There are no artificial restrictions on the number of users or conference participants. Server power and bandwidth are the only limiting factors."
- },
- "feature5": {
- "title": "Screen sharing",
- "content": "It's easy to share your screen with others. __app__ is ideal for on-line presentations, lectures, and tech support sessions."
- },
- "feature6": {
- "title": "Secure rooms",
- "content": "Need some privacy? __app__ conference rooms can be secured with a password in order to exclude unwanted guests and prevent interruptions."
- },
- "feature7": {
- "title": "Shared notes",
- "content": "__app__ features Etherpad, a real-time collaborative text editor that's great for meeting minutes, writing articles, and more."
- },
- "feature8": {
- "title": "Usage statistics",
- "content": "Learn about your users through easy integration with Piwik, Google Analytics, and other usage monitoring and statistics systems."
- }
- },
- "toolbar": {
- "mute": "Mute / Unmute",
- "videomute": "Start / stop camera",
- "authenticate": "Authenticate",
- "record": "Record",
- "lock": "Lock / unlock room",
- "invite": "Invite others",
- "chat": "Open / close chat",
- "prezi": "Share Prezi",
- "etherpad": "Shared document",
- "sharescreen": "Share screen",
- "fullscreen": "Enter / Exit Full Screen",
- "sip": "Call SIP number",
- "Settings": "Settings",
- "hangup": "Hang Up",
- "login": "Login",
- "logout": "Logout",
- "dialpad": "Show dialpad"
- },
- "bottomtoolbar": {
- "chat": "Open / close chat",
- "filmstrip": "Show / hide film strip",
- "contactlist": "Open / close contact list"
- },
- "chat":{
- "nickname": {
- "title": "Enter a nickname in the box below",
- "popover": "Choose a nickname"
- },
- "messagebox": "Enter text..."
- },
- "settings":
- {
- "title": "SETTINGS",
- "update": "Update",
- "name": "Name",
- "startAudioMuted": "start without audio",
- "startVideoMuted": "start without video"
- },
- "videothumbnail":
- {
- "editnickname": "Click to edit your display name",
- "moderator": "The owner of this conference",
- "videomute": "Participant has stopped the camera.",
- "mute": "Participant is muted",
- "kick": "Kick out",
- "muted": "Muted",
- "domute": "Mute"
-
- },
- "connectionindicator":
- {
- "bitrate": "Bitrate:",
- "packetloss": "Packet loss:",
- "resolution": "Resolution:",
- "less": "Show less",
- "more": "Show more",
- "address": "Address:",
- "remoteport_plural": "Remote ports:",
- "localport_plural": "Local ports:",
- "remoteport": "Remote port:",
- "localport": "Local port:",
- "localaddress": "Local address:",
- "localaddress_plural": "Local addresses:",
- "remoteaddress": "Remote address:",
- "remoteaddress_plural": "Remote addresses:",
- "transport": "Transport:",
- "bandwidth": "Estimated bandwidth:",
- "na": "Come back here for connection information once the conference starts"
- },
- "notify": {
- "disconnected": "disconnected",
- "moderator": "Moderator rights granted!",
- "connected": "connected",
- "somebody": "Somebody",
- "me": "Me",
- "focus": "Conference focus",
- "focusFail": "__component__ not available - retry in __ms__ sec",
- "grantedTo": "Moderator rights granted to __to__!",
- "grantedToUnknown": "Moderator rights granted to $t(somebody)!",
- "muted": "You have started the conversation muted.",
- "mutedTitle": "You're muted!"
- },
- "dialog": {
- "kickMessage": "Ouch! You have been kicked out of the meet!",
- "popupError": "Your browser is blocking popup windows from this site. Please enable popups in your browser security settings and try again.",
- "passwordError": "This conversation is currently protected by a password. Only the owner of the conference could set a password.",
- "passwordError2": "This conversation isn't currently protected by a password. Only the owner of the conference could set a password.",
- "joinError": "Oops! We couldn't join the conference. There might be some problem with security configuration. Please contact service administrator.",
- "connectError": "Oops! Something went wrong and we couldn't connect to the conference.",
- "connectErrorWithMsg": "Oops! Something went wrong and we couldn't connect to the conference: __msg__",
- "connecting": "Connecting",
- "error": "Error",
- "detectext": "Error when trying to detect desktopsharing extension.",
- "failtoinstall": "Failed to install desktop sharing extension",
- "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
- "bridgeUnavailable": "Jitsi Videobridge is currently unavailable. Please try again later!",
- "lockTitle": "Lock failed",
- "lockMessage": "Failed to lock conference.",
- "warning": "Warning",
- "passwordNotSupported": "Room passwords are currently not supported.",
- "sorry": "Sorry",
- "internalError": "Internal application error [setRemoteDescription]",
- "unableToSwitch": "Unable to switch video stream.",
- "SLDFailure": "Oops! Something went wrong and we failed to mute! (SLD Failure)",
- "SRDFailure": "Oops! Something went wrong and we failed to stop video! (SRD Failure)",
- "oops": "Oops!",
- "defaultError": "There was some kind of error",
- "passwordRequired": "Password required",
- "Ok": "Ok",
- "removePreziTitle": "Remove Prezi",
- "removePreziMsg": "Are you sure you would like to remove your Prezi?",
- "sharePreziTitle": "Share a Prezi",
- "sharePreziMsg": "Another participant is already sharing a Prezi.This conference allows only one Prezi at a time.",
- "Remove": "Remove",
- "WaitingForHost": "Waiting for the host ...",
- "WaitForHostMsg": "The conference __room__ has not yet started. If you are the host then please authenticate. Otherwise, please wait for the host to arrive.",
- "IamHost": "I am the host",
- "Cancel": "Cancel",
- "retry": "Retry",
- "logoutTitle" : "Logout",
- "logoutQuestion" : "Are you sure you want to logout and stop the conference?",
- "sessTerminated": "Session Terminated",
- "hungUp": "You hung up the call",
- "joinAgain": "Join again",
- "Share": "Share",
- "preziLinkError": "Please provide a correct prezi link.",
- "Save": "Save",
- "recordingToken": "Enter recording token",
- "Dial": "Dial",
- "sipMsg": "Enter SIP number",
- "passwordCheck": "Are you sure you would like to remove your password?",
- "Remove": "Remove",
- "passwordMsg": "Set a password to lock your room",
- "Invite": "Invite",
- "shareLink": "Share this link with everyone you want to invite",
- "settings1": "Configure your conference",
- "settings2": "Participants join muted",
- "settings3": "Require nicknames
Set a password to lock your room:",
- "yourPassword": "your password",
- "Back": "Back",
- "serviceUnavailable": "Service unavailable",
- "gracefulShutdown": "Our service is currently down for maintenance. Please try again later.",
- "Yes": "Yes",
- "reservationError": "Reservation system error",
- "reservationErrorMsg": "Error code: __code__, message: __msg__",
- "password": "password",
- "userPassword": "user password",
- "token": "token",
- "displayNameRequired": "Please enter your display name:"
- },
- "email":
- {
- "sharedKey": [
- "This conference is password protected. Please use the following pin when joining:",
- "",
- "",
- "__sharedKey__",
- "",
- ""],
- "subject": "Invitation to a __appName__ (__conferenceName__)",
- "body": [
- "Hey there, I%27d like to invite you to a __appName__ conference I%27ve just set up.",
- "",
- "",
- "Please click on the following link in order to join the conference.",
- "",
- "",
- "__roomUrl__",
- "",
- "",
- "__sharedKeyText__",
- " Note that __appName__ is currently only supported by __supportedBrowsers__, so you need to be using one of these browsers.",
- "",
- "",
- "Talk to you in a sec!"
- ],
- "and": "and"
- },
- "connection":
- {
- "ERROR": "Error",
- "CONNECTING": "Connecting",
- "RECONNECTING": "A network problem occurred. Reconnecting...",
- "CONNFAIL": "Connection failed",
- "AUTHENTICATING": "Authenticating",
- "AUTHFAIL": "Authentication failed",
- "CONNECTED": "Connected",
- "DISCONNECTED": "Disconnected",
- "DISCONNECTING": "Disconnecting",
- "ATTACHED": "Attached",
- "FETCH_SESSION_ID": "Obtaining session-id...",
- "GOT_SESSION_ID": "Obtaining session-id... Done",
- "GET_SESSION_ID_ERROR": "Get session-id error: "
- },
- "recording":
- {
- "toaster": "Currently recording!",
- "pending": "Your recording will start as soon as another participant joins",
- "on": "Recording has been started"
- }
-}
diff --git a/libs/app.bundle.js b/libs/app.bundle.js
deleted file mode 100644
index 7367b804e..000000000
--- a/libs/app.bundle.js
+++ /dev/null
@@ -1,38194 +0,0 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.APP = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) {
- this._events[type].warned = true;
- console.error('(node) warning: possible EventEmitter memory ' +
- 'leak detected. %d listeners added. ' +
- 'Use emitter.setMaxListeners() to increase limit.',
- this._events[type].length);
- if (typeof console.trace === 'function') {
- // not supported in IE 10
- console.trace();
- }
- }
- }
-
- return this;
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.once = function(type, listener) {
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
-
- var fired = false;
-
- function g() {
- this.removeListener(type, g);
-
- if (!fired) {
- fired = true;
- listener.apply(this, arguments);
- }
- }
-
- g.listener = listener;
- this.on(type, g);
-
- return this;
-};
-
-// emits a 'removeListener' event iff the listener was removed
-EventEmitter.prototype.removeListener = function(type, listener) {
- var list, position, length, i;
-
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
-
- if (!this._events || !this._events[type])
- return this;
-
- list = this._events[type];
- length = list.length;
- position = -1;
-
- if (list === listener ||
- (isFunction(list.listener) && list.listener === listener)) {
- delete this._events[type];
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
-
- } else if (isObject(list)) {
- for (i = length; i-- > 0;) {
- if (list[i] === listener ||
- (list[i].listener && list[i].listener === listener)) {
- position = i;
- break;
- }
- }
-
- if (position < 0)
- return this;
-
- if (list.length === 1) {
- list.length = 0;
- delete this._events[type];
- } else {
- list.splice(position, 1);
- }
-
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
- }
-
- return this;
-};
-
-EventEmitter.prototype.removeAllListeners = function(type) {
- var key, listeners;
-
- if (!this._events)
- return this;
-
- // not listening for removeListener, no need to emit
- if (!this._events.removeListener) {
- if (arguments.length === 0)
- this._events = {};
- else if (this._events[type])
- delete this._events[type];
- return this;
- }
-
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- for (key in this._events) {
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = {};
- return this;
- }
-
- listeners = this._events[type];
-
- if (isFunction(listeners)) {
- this.removeListener(type, listeners);
- } else {
- // LIFO order
- while (listeners.length)
- this.removeListener(type, listeners[listeners.length - 1]);
- }
- delete this._events[type];
-
- return this;
-};
-
-EventEmitter.prototype.listeners = function(type) {
- var ret;
- if (!this._events || !this._events[type])
- ret = [];
- else if (isFunction(this._events[type]))
- ret = [this._events[type]];
- else
- ret = this._events[type].slice();
- return ret;
-};
-
-EventEmitter.listenerCount = function(emitter, type) {
- var ret;
- if (!emitter._events || !emitter._events[type])
- ret = 0;
- else if (isFunction(emitter._events[type]))
- ret = 1;
- else
- ret = emitter._events[type].length;
- return ret;
-};
-
-function isFunction(arg) {
- return typeof arg === 'function';
-}
-
-function isNumber(arg) {
- return typeof arg === 'number';
-}
-
-function isObject(arg) {
- return typeof arg === 'object' && arg !== null;
-}
-
-function isUndefined(arg) {
- return arg === void 0;
-}
-
-},{}],2:[function(require,module,exports){
-// shim for using process in browser
-
-var process = module.exports = {};
-var queue = [];
-var draining = false;
-
-function drainQueue() {
- if (draining) {
- return;
- }
- draining = true;
- var currentQueue;
- var len = queue.length;
- while(len) {
- currentQueue = queue;
- queue = [];
- var i = -1;
- while (++i < len) {
- currentQueue[i]();
- }
- len = queue.length;
- }
- draining = false;
-}
-process.nextTick = function (fun) {
- queue.push(fun);
- if (!draining) {
- setTimeout(drainQueue, 0);
- }
-};
-
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-process.version = ''; // empty string to avoid regexp issues
-process.versions = {};
-
-function noop() {}
-
-process.on = noop;
-process.addListener = noop;
-process.once = noop;
-process.off = noop;
-process.removeListener = noop;
-process.removeAllListeners = noop;
-process.emit = noop;
-
-process.binding = function (name) {
- throw new Error('process.binding is not supported');
-};
-
-// TODO(shtylman)
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
-};
-process.umask = function() { return 0; };
-
-},{}],3:[function(require,module,exports){
-/* jshint -W117 */
-/* application specific logic */
-
-var APP =
-{
- init: function () {
- this.UI = require("./modules/UI/UI");
- this.API = require("./modules/API/API");
- this.connectionquality = require("./modules/connectionquality/connectionquality");
- this.statistics = require("./modules/statistics/statistics");
- this.RTC = require("./modules/RTC/RTC");
- this.desktopsharing = require("./modules/desktopsharing/desktopsharing");
- this.xmpp = require("./modules/xmpp/xmpp");
- this.keyboardshortcut = require("./modules/keyboardshortcut/keyboardshortcut");
- this.translation = require("./modules/translation/translation");
- this.settings = require("./modules/settings/Settings");
- this.DTMF = require("./modules/DTMF/DTMF");
- this.members = require("./modules/members/MemberList");
- }
-};
-
-function init() {
-
- APP.desktopsharing.init();
- APP.RTC.start();
- APP.xmpp.start();
- APP.statistics.start();
- APP.connectionquality.init();
- APP.keyboardshortcut.init();
- APP.members.start();
-}
-
-
-$(document).ready(function () {
-
- var URLProcessor = require("./modules/URLProcessor/URLProcessor");
- URLProcessor.setConfigParametersFromUrl();
- APP.init();
-
- APP.translation.init();
-
- if(APP.API.isEnabled())
- APP.API.init();
-
- APP.UI.start(init);
-
-});
-
-$(window).bind('beforeunload', function () {
- if(APP.API.isEnabled())
- APP.API.dispose();
-});
-
-module.exports = APP;
-
-
-},{"./modules/API/API":4,"./modules/DTMF/DTMF":5,"./modules/RTC/RTC":9,"./modules/UI/UI":13,"./modules/URLProcessor/URLProcessor":44,"./modules/connectionquality/connectionquality":45,"./modules/desktopsharing/desktopsharing":46,"./modules/keyboardshortcut/keyboardshortcut":47,"./modules/members/MemberList":48,"./modules/settings/Settings":49,"./modules/statistics/statistics":53,"./modules/translation/translation":54,"./modules/xmpp/xmpp":70}],4:[function(require,module,exports){
-/* global APP */
-/**
- * Implements API class that communicates with external api class
- * and provides interface to access Jitsi Meet features by external
- * applications that embed Jitsi Meet
- */
-
-var XMPPEvents = require("../../service/xmpp/XMPPEvents");
-
-/**
- * List of the available commands.
- * @type {{
- * displayName: inputDisplayNameHandler,
- * toggleAudio: toggleAudio,
- * toggleVideo: toggleVideo,
- * toggleFilmStrip: toggleFilmStrip,
- * toggleChat: toggleChat,
- * toggleContactList: toggleContactList
- * }}
- */
-var commands = {};
-
-function initCommands() {
- commands = {
- displayName: APP.UI.inputDisplayNameHandler,
- toggleAudio: APP.UI.toggleAudio,
- toggleVideo: APP.UI.toggleVideo,
- toggleFilmStrip: APP.UI.toggleFilmStrip,
- toggleChat: APP.UI.toggleChat,
- toggleContactList: APP.UI.toggleContactList
- };
-}
-
-
-/**
- * Maps the supported events and their status
- * (true it the event is enabled and false if it is disabled)
- * @type {{
- * incomingMessage: boolean,
- * outgoingMessage: boolean,
- * displayNameChange: boolean,
- * participantJoined: boolean,
- * participantLeft: boolean
- * }}
- */
-var events = {
- incomingMessage: false,
- outgoingMessage:false,
- displayNameChange: false,
- participantJoined: false,
- participantLeft: false
-};
-
-var displayName = {};
-
-/**
- * Processes commands from external application.
- * @param message the object with the command
- */
-function processCommand(message) {
- if (message.action != "execute") {
- console.error("Unknown action of the message");
- return;
- }
- for (var key in message) {
- if(commands[key])
- commands[key].apply(null, message[key]);
- }
-}
-
-/**
- * Processes events objects from external applications
- * @param event the event
- */
-function processEvent(event) {
- if (!event.action) {
- console.error("Event with no action is received.");
- return;
- }
-
- var i = 0;
- switch(event.action) {
- case "add":
- for (; i < event.events.length; i++) {
- events[event.events[i]] = true;
- }
- break;
- case "remove":
- for (; i < event.events.length; i++) {
- events[event.events[i]] = false;
- }
- break;
- default:
- console.error("Unknown action for event.");
- }
-}
-
-/**
- * Sends message to the external application.
- * @param object
- */
-function sendMessage(object) {
- window.parent.postMessage(JSON.stringify(object), "*");
-}
-
-/**
- * Processes a message event from the external application
- * @param event the message event
- */
-function processMessage(event) {
- var message;
- try {
- message = JSON.parse(event.data);
- } catch (e) {}
-
- if(!message.type)
- return;
- switch (message.type) {
- case "command":
- processCommand(message);
- break;
- case "event":
- processEvent(message);
- break;
- default:
- console.error("Unknown type of the message");
- return;
- }
-}
-
-function setupListeners() {
- APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_JOINED, function (from) {
- API.triggerEvent("participantJoined", {jid: from});
- });
- APP.xmpp.addListener(XMPPEvents.MESSAGE_RECEIVED, function (from, nick, txt, myjid, stamp) {
- if (from != myjid)
- API.triggerEvent("incomingMessage",
- {"from": from, "nick": nick, "message": txt, "stamp": stamp});
- });
- APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, function (jid) {
- API.triggerEvent("participantLeft", {jid: jid});
- });
- APP.xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, function (jid, newDisplayName) {
- var name = displayName[jid];
- if(!name || name != newDisplayName) {
- API.triggerEvent("displayNameChange", {jid: jid, displayname: newDisplayName});
- displayName[jid] = newDisplayName;
- }
- });
- APP.xmpp.addListener(XMPPEvents.SENDING_CHAT_MESSAGE, function (body) {
- APP.API.triggerEvent("outgoingMessage", {"message": body});
- });
-}
-
-var API = {
- /**
- * Check whether the API should be enabled or not.
- * @returns {boolean}
- */
- isEnabled: function () {
- var hash = location.hash;
- if (hash && hash.indexOf("external") > -1 && window.postMessage)
- return true;
- return false;
- },
- /**
- * Initializes the APIConnector. Setups message event listeners that will
- * receive information from external applications that embed Jitsi Meet.
- * It also sends a message to the external application that APIConnector
- * is initialized.
- */
- init: function () {
- initCommands();
- if (window.addEventListener) {
- window.addEventListener('message',
- processMessage, false);
- }
- else {
- window.attachEvent('onmessage', processMessage);
- }
- sendMessage({type: "system", loaded: true});
- setupListeners();
- },
- /**
- * Checks whether the event is enabled ot not.
- * @param name the name of the event.
- * @returns {*}
- */
- isEventEnabled: function (name) {
- return events[name];
- },
-
- /**
- * Sends event object to the external application that has been subscribed
- * for that event.
- * @param name the name event
- * @param object data associated with the event
- */
- triggerEvent: function (name, object) {
- if(this.isEnabled() && this.isEventEnabled(name))
- sendMessage({
- type: "event", action: "result", event: name, result: object});
- },
-
- /**
- * Removes the listeners.
- */
- dispose: function () {
- if(window.removeEventListener) {
- window.removeEventListener("message",
- processMessage, false);
- }
- else {
- window.detachEvent('onmessage', processMessage);
- }
- }
-};
-
-module.exports = API;
-},{"../../service/xmpp/XMPPEvents":166}],5:[function(require,module,exports){
-/* global APP */
-
-/**
- * A module for sending DTMF tones.
- */
-var DTMFSender;
-var initDtmfSender = function() {
- // TODO: This needs to reset this if the peerconnection changes
- // (e.g. the call is re-made)
- if (DTMFSender)
- return;
-
- var localAudio = APP.RTC.localAudio;
- if (localAudio && localAudio.getTracks().length > 0)
- {
- var peerconnection
- = APP.xmpp.getConnection().jingle.activecall.peerconnection;
- if (peerconnection) {
- DTMFSender =
- peerconnection.peerconnection
- .createDTMFSender(localAudio.getTracks()[0]);
- console.log("Initialized DTMFSender");
- }
- else {
- console.log("Failed to initialize DTMFSender: no PeerConnection.");
- }
- }
- else {
- console.log("Failed to initialize DTMFSender: no audio track.");
- }
-};
-
-var DTMF = {
- sendTones: function (tones, duration, pause) {
- if (!DTMFSender)
- initDtmfSender();
-
- if (DTMFSender){
- DTMFSender.insertDTMF(tones,
- (duration || 200),
- (pause || 200));
- }
- }
-};
-
-module.exports = DTMF;
-
-
-},{}],6:[function(require,module,exports){
-/* global config, APP, Strophe */
-
-// cache datachannels to avoid garbage collection
-// https://code.google.com/p/chromium/issues/detail?id=405545
-var RTCEvents = require("../../service/RTC/RTCEvents");
-
-var _dataChannels = [];
-var eventEmitter = null;
-
-
-var DataChannels = {
- /**
- * Callback triggered by PeerConnection when new data channel is opened
- * on the bridge.
- * @param event the event info object.
- */
- onDataChannel: function (event) {
- var dataChannel = event.channel;
-
- dataChannel.onopen = function () {
- console.info("Data channel opened by the Videobridge!", dataChannel);
-
- // Code sample for sending string and/or binary data
- // Sends String message to the bridge
- //dataChannel.send("Hello bridge!");
- // Sends 12 bytes binary message to the bridge
- //dataChannel.send(new ArrayBuffer(12));
-
- eventEmitter.emit(RTCEvents.DATA_CHANNEL_OPEN);
- };
-
- dataChannel.onerror = function (error) {
- console.error("Data Channel Error:", error, dataChannel);
- };
-
- dataChannel.onmessage = function (event) {
- var data = event.data;
- // JSON
- var obj;
-
- try {
- obj = JSON.parse(data);
- }
- catch (e) {
- console.error(
- "Failed to parse data channel message as JSON: ",
- data,
- dataChannel);
- }
- if (('undefined' !== typeof(obj)) && (null !== obj)) {
- var colibriClass = obj.colibriClass;
-
- if ("DominantSpeakerEndpointChangeEvent" === colibriClass) {
- // Endpoint ID from the Videobridge.
- var dominantSpeakerEndpoint = obj.dominantSpeakerEndpoint;
-
- console.info(
- "Data channel new dominant speaker event: ",
- dominantSpeakerEndpoint);
- eventEmitter.emit(RTCEvents.DOMINANTSPEAKER_CHANGED, dominantSpeakerEndpoint);
- }
- else if ("InLastNChangeEvent" === colibriClass) {
- var oldValue = obj.oldValue;
- var newValue = obj.newValue;
- // Make sure that oldValue and newValue are of type boolean.
- var type;
-
- if ((type = typeof oldValue) !== 'boolean') {
- if (type === 'string') {
- oldValue = (oldValue == "true");
- } else {
- oldValue = new Boolean(oldValue).valueOf();
- }
- }
- if ((type = typeof newValue) !== 'boolean') {
- if (type === 'string') {
- newValue = (newValue == "true");
- } else {
- newValue = new Boolean(newValue).valueOf();
- }
- }
-
- eventEmitter.emit(RTCEvents.LASTN_CHANGED, oldValue, newValue);
- }
- else if ("LastNEndpointsChangeEvent" === colibriClass) {
- // The new/latest list of last-n endpoint IDs.
- var lastNEndpoints = obj.lastNEndpoints;
- // The list of endpoint IDs which are entering the list of
- // last-n at this time i.e. were not in the old list of last-n
- // endpoint IDs.
- var endpointsEnteringLastN = obj.endpointsEnteringLastN;
-
- console.log(
- "Data channel new last-n event: ",
- lastNEndpoints, endpointsEnteringLastN, obj);
- eventEmitter.emit(RTCEvents.LASTN_ENDPOINT_CHANGED,
- lastNEndpoints, endpointsEnteringLastN, obj);
- }
- else {
- console.debug("Data channel JSON-formatted message: ", obj);
- }
- }
- };
-
- dataChannel.onclose = function () {
- console.info("The Data Channel closed", dataChannel);
- var idx = _dataChannels.indexOf(dataChannel);
- if (idx > -1)
- _dataChannels = _dataChannels.splice(idx, 1);
- };
- _dataChannels.push(dataChannel);
- },
-
- /**
- * Binds "ondatachannel" event listener to given PeerConnection instance.
- * @param peerConnection WebRTC peer connection instance.
- */
- init: function (peerConnection, emitter) {
- if(!config.openSctp)
- return;
-
- peerConnection.ondatachannel = this.onDataChannel;
- eventEmitter = emitter;
-
- // Sample code for opening new data channel from Jitsi Meet to the bridge.
- // Although it's not a requirement to open separate channels from both bridge
- // and peer as single channel can be used for sending and receiving data.
- // So either channel opened by the bridge or the one opened here is enough
- // for communication with the bridge.
- /*var dataChannelOptions =
- {
- reliable: true
- };
- var dataChannel
- = peerConnection.createDataChannel("myChannel", dataChannelOptions);
-
- // Can be used only when is in open state
- dataChannel.onopen = function ()
- {
- dataChannel.send("My channel !!!");
- };
- dataChannel.onmessage = function (event)
- {
- var msgData = event.data;
- console.info("Got My Data Channel Message:", msgData, dataChannel);
- };*/
- },
- handleSelectedEndpointEvent: onSelectedEndpointChanged,
- handlePinnedEndpointEvent: onPinnedEndpointChanged
-};
-
-function onSelectedEndpointChanged(userResource) {
- console.log('selected endpoint changed: ', userResource);
- if (_dataChannels && _dataChannels.length != 0) {
- _dataChannels.some(function (dataChannel) {
- if (dataChannel.readyState == 'open') {
- console.log('sending selected endpoint changed ' +
- 'notification to the bridge: ', userResource);
- dataChannel.send(JSON.stringify({
- 'colibriClass': 'SelectedEndpointChangedEvent',
- 'selectedEndpoint':
- (!userResource || userResource === null)?
- null : userResource
- }));
-
- return true;
- }
- });
- }
-}
-
-function onPinnedEndpointChanged(userResource) {
- console.log('pinned endpoint changed: ', userResource);
- if (_dataChannels && _dataChannels.length != 0) {
- _dataChannels.some(function (dataChannel) {
- if (dataChannel.readyState == 'open') {
- dataChannel.send(JSON.stringify({
- 'colibriClass': 'PinnedEndpointChangedEvent',
- 'pinnedEndpoint':
- (!userResource || userResource == null)?
- null : userResource
- }));
-
- return true;
- }
- });
- }
-}
-
-module.exports = DataChannels;
-
-
-},{"../../service/RTC/RTCEvents":157}],7:[function(require,module,exports){
-/* global APP */
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
-var RTCEvents = require("../../service/RTC/RTCEvents");
-var RTCBrowserType = require("./RTCBrowserType");
-
-/**
- * This implements 'onended' callback normally fired by WebRTC after the stream
- * is stopped. There is no such behaviour yet in FF, so we have to add it.
- * @param stream original WebRTC stream object to which 'onended' handling
- * will be added.
- */
-function implementOnEndedHandling(stream) {
- var originalStop = stream.stop;
- stream.stop = function () {
- originalStop.apply(stream);
- if (!stream.ended) {
- stream.ended = true;
- stream.onended();
- }
- };
-}
-
-function LocalStream(stream, type, eventEmitter, videoType, isGUMStream) {
- this.stream = stream;
- this.eventEmitter = eventEmitter;
- this.type = type;
- this.videoType = videoType;
- this.isGUMStream = true;
- if(isGUMStream === false)
- this.isGUMStream = isGUMStream;
- var self = this;
- if(type == "audio") {
- this.getTracks = function () {
- return self.stream.getAudioTracks();
- };
- } else {
- this.getTracks = function () {
- return self.stream.getVideoTracks();
- };
- }
-
- this.stream.onended = function () {
- self.streamEnded();
- };
- if (RTCBrowserType.isFirefox()) {
- implementOnEndedHandling(this.stream);
- }
-}
-
-LocalStream.prototype.streamEnded = function () {
- this.eventEmitter.emit(StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, this);
-};
-
-LocalStream.prototype.getOriginalStream = function()
-{
- return this.stream;
-};
-
-LocalStream.prototype.isAudioStream = function () {
- return this.type === "audio";
-};
-
-LocalStream.prototype.setMute = function (mute)
-{
- var isAudio = this.isAudioStream();
- var eventType = isAudio ? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE;
-
- if ((window.location.protocol != "https:" && this.isGUMStream) ||
- (isAudio && this.isGUMStream) || this.videoType === "screen" ||
- // FIXME FF does not support 'removeStream' method used to mute
- RTCBrowserType.isFirefox()) {
-
- var tracks = this.getTracks();
- for (var idx = 0; idx < tracks.length; idx++) {
- tracks[idx].enabled = !mute;
- }
- this.eventEmitter.emit(eventType, mute);
- } else {
- if (mute) {
- APP.xmpp.removeStream(this.stream);
- this.stream.stop();
- this.eventEmitter.emit(eventType, true);
- } else {
- var self = this;
- APP.RTC.rtcUtils.obtainAudioAndVideoPermissions(
- (this.isAudioStream() ? ["audio"] : ["video"]),
- function (stream) {
- if (isAudio) {
- APP.RTC.changeLocalAudio(stream,
- function () {
- self.eventEmitter.emit(eventType, false);
- });
- } else {
- APP.RTC.changeLocalVideo(stream, false,
- function () {
- self.eventEmitter.emit(eventType, false);
- });
- }
- });
- }
- }
-};
-
-LocalStream.prototype.isMuted = function () {
- var tracks = [];
- if (this.isAudioStream()) {
- tracks = this.stream.getAudioTracks();
- } else {
- if (this.stream.ended)
- return true;
- tracks = this.stream.getVideoTracks();
- }
- for (var idx = 0; idx < tracks.length; idx++) {
- if(tracks[idx].enabled)
- return false;
- }
- return true;
-};
-
-LocalStream.prototype.getId = function () {
- return this.stream.getTracks()[0].id;
-};
-
-module.exports = LocalStream;
-
-},{"../../service/RTC/RTCEvents":157,"../../service/RTC/StreamEventTypes.js":159,"./RTCBrowserType":10}],8:[function(require,module,exports){
-var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
-
-/**
- * Creates a MediaStream object for the given data, session id and ssrc.
- * It is a wrapper class for the MediaStream.
- *
- * @param data the data object from which we obtain the stream,
- * the peerjid, etc.
- * @param sid the session id
- * @param ssrc the ssrc corresponding to this MediaStream
- *
- * @constructor
- */
-function MediaStream(data, sid, ssrc, browser, eventEmitter) {
-
- // XXX(gp) to minimize headaches in the future, we should build our
- // abstractions around tracks and not streams. ORTC is track based API.
- // Mozilla expects m-lines to represent media tracks.
- //
- // Practically, what I'm saying is that we should have a MediaTrack class
- // and not a MediaStream class.
- //
- // Also, we should be able to associate multiple SSRCs with a MediaTrack as
- // a track might have an associated RTX and FEC sources.
-
- this.sid = sid;
- this.stream = data.stream;
- this.peerjid = data.peerjid;
- this.videoType = data.videoType;
- this.ssrc = ssrc;
- this.type = (this.stream.getVideoTracks().length > 0)?
- MediaStreamType.VIDEO_TYPE : MediaStreamType.AUDIO_TYPE;
- this.muted = false;
- this.eventEmitter = eventEmitter;
-}
-
-
-MediaStream.prototype.getOriginalStream = function() {
- return this.stream;
-};
-
-MediaStream.prototype.setMute = function (value) {
- this.stream.muted = value;
- this.muted = value;
-};
-
-module.exports = MediaStream;
-
-},{"../../service/RTC/MediaStreamTypes":156}],9:[function(require,module,exports){
-/* global APP */
-var EventEmitter = require("events");
-var RTCBrowserType = require("./RTCBrowserType");
-var RTCUtils = require("./RTCUtils.js");
-var LocalStream = require("./LocalStream.js");
-var DataChannels = require("./DataChannels");
-var MediaStream = require("./MediaStream.js");
-var DesktopSharingEventTypes
- = require("../../service/desktopsharing/DesktopSharingEventTypes");
-var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
-var RTCEvents = require("../../service/RTC/RTCEvents.js");
-var XMPPEvents = require("../../service/xmpp/XMPPEvents");
-var UIEvents = require("../../service/UI/UIEvents");
-
-var eventEmitter = new EventEmitter();
-
-
-function getMediaStreamUsage()
-{
- var result = {
- audio: true,
- video: true
- };
-
- /** There are some issues with the desktop sharing
- * when this property is enabled.
- * WARNING: We must change the implementation to start video/audio if we
- * receive from the focus that the peer is not muted.
-
- var isSecureConnection = window.location.protocol == "https:";
-
- if(config.disableEarlyMediaPermissionRequests || !isSecureConnection)
- {
- result = {
- audio: false,
- video: false
- };
-
- }
- **/
-
- return result;
-}
-
-var RTC = {
- rtcUtils: null,
- devices: {
- audio: true,
- video: true
- },
- localStreams: [],
- remoteStreams: {},
- localAudio: null,
- localVideo: null,
- addStreamListener: function (listener, eventType) {
- eventEmitter.on(eventType, listener);
- },
- addListener: function (type, listener) {
- eventEmitter.on(type, listener);
- },
- removeStreamListener: function (listener, eventType) {
- if(!(eventType instanceof StreamEventTypes))
- throw "Illegal argument";
-
- eventEmitter.removeListener(eventType, listener);
- },
- createLocalStream: function (stream, type, change, videoType, isMuted, isGUMStream) {
-
- var localStream = new LocalStream(stream, type, eventEmitter, videoType, isGUMStream);
- //in firefox we have only one stream object
- if(this.localStreams.length == 0 ||
- this.localStreams[0].getOriginalStream() != stream)
- this.localStreams.push(localStream);
- if(isMuted === true)
- localStream.setMute(true);
-
- if(type == "audio") {
- this.localAudio = localStream;
- } else {
- this.localVideo = localStream;
- }
- var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED;
- if(change)
- eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED;
-
- eventEmitter.emit(eventType, localStream, isMuted);
- return localStream;
- },
- removeLocalStream: function (stream) {
- for(var i = 0; i < this.localStreams.length; i++) {
- if(this.localStreams[i].getOriginalStream() === stream) {
- delete this.localStreams[i];
- return;
- }
- }
- },
- createRemoteStream: function (data, sid, thessrc) {
- var remoteStream = new MediaStream(data, sid, thessrc,
- RTCBrowserType.getBrowserType(), eventEmitter);
- var jid = data.peerjid || APP.xmpp.myJid();
- if(!this.remoteStreams[jid]) {
- this.remoteStreams[jid] = {};
- }
- this.remoteStreams[jid][remoteStream.type]= remoteStream;
- eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED, remoteStream);
- return remoteStream;
- },
- getPCConstraints: function () {
- return this.rtcUtils.pc_constraints;
- },
- getUserMediaWithConstraints:function(um, success_callback,
- failure_callback, resolution,
- bandwidth, fps, desktopStream)
- {
- return this.rtcUtils.getUserMediaWithConstraints(um, success_callback,
- failure_callback, resolution, bandwidth, fps, desktopStream);
- },
- attachMediaStream: function (elSelector, stream) {
- this.rtcUtils.attachMediaStream(elSelector, stream);
- },
- getStreamID: function (stream) {
- return this.rtcUtils.getStreamID(stream);
- },
- getVideoSrc: function (element) {
- return this.rtcUtils.getVideoSrc(element);
- },
- setVideoSrc: function (element, src) {
- this.rtcUtils.setVideoSrc(element, src);
- },
- getVideoElementName: function () {
- return RTCBrowserType.isTemasysPluginUsed() ? 'object' : 'video';
- },
- dispose: function() {
- if (this.rtcUtils) {
- this.rtcUtils = null;
- }
- },
- stop: function () {
- this.dispose();
- },
- start: function () {
- var self = this;
- APP.desktopsharing.addListener(
- function (stream, isUsingScreenStream, callback) {
- self.changeLocalVideo(stream, isUsingScreenStream, callback);
- }, DesktopSharingEventTypes.NEW_STREAM_CREATED);
- APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function(event) {
- DataChannels.init(event.peerconnection, eventEmitter);
- });
- APP.UI.addListener(UIEvents.SELECTED_ENDPOINT,
- DataChannels.handleSelectedEndpointEvent);
- APP.UI.addListener(UIEvents.PINNED_ENDPOINT,
- DataChannels.handlePinnedEndpointEvent);
-
- // In case of IE we continue from 'onReady' callback
- // passed to RTCUtils constructor. It will be invoked by Temasys plugin
- // once it is initialized.
- var onReady = function () {
- eventEmitter.emit(RTCEvents.RTC_READY, true);
- self.rtcUtils.obtainAudioAndVideoPermissions(
- null, null, getMediaStreamUsage());
- };
-
- this.rtcUtils = new RTCUtils(this, onReady);
-
- // Call onReady() if Temasys plugin is not used
- if (!RTCBrowserType.isTemasysPluginUsed()) {
- onReady();
- }
- },
- muteRemoteVideoStream: function (jid, value) {
- var stream;
-
- if(this.remoteStreams[jid] &&
- this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
- stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
- }
-
- if(!stream)
- return true;
-
- if (value != stream.muted) {
- stream.setMute(value);
- return true;
- }
- return false;
- },
- switchVideoStreams: function (new_stream) {
- this.localVideo.stream = new_stream;
-
- this.localStreams = [];
-
- //in firefox we have only one stream object
- if (this.localAudio.getOriginalStream() != new_stream)
- this.localStreams.push(this.localAudio);
- this.localStreams.push(this.localVideo);
- },
- changeLocalVideo: function (stream, isUsingScreenStream, callback) {
- var oldStream = this.localVideo.getOriginalStream();
- var type = (isUsingScreenStream ? "screen" : "camera");
- var localCallback = callback;
- if(this.localVideo.isMuted() && this.localVideo.videoType !== type) {
- localCallback = function() {
- APP.xmpp.setVideoMute(false, function(mute) {
- eventEmitter.emit(RTCEvents.VIDEO_MUTE, mute);
- });
-
- callback();
- };
- }
- // FIXME: Workaround for FF/IE/Safari
- if (stream && stream.videoStream) {
- stream = stream.videoStream;
- }
- var videoStream = this.rtcUtils.createStream(stream, true);
- this.localVideo = this.createLocalStream(videoStream, "video", true, type);
- // Stop the stream to trigger onended event for old stream
- oldStream.stop();
-
- this.switchVideoStreams(videoStream, oldStream);
-
- APP.xmpp.switchStreams(videoStream, oldStream,localCallback);
- },
- changeLocalAudio: function (stream, callback) {
- var oldStream = this.localAudio.getOriginalStream();
- var newStream = this.rtcUtils.createStream(stream);
- this.localAudio = this.createLocalStream(newStream, "audio", true);
- // Stop the stream to trigger onended event for old stream
- oldStream.stop();
- APP.xmpp.switchStreams(newStream, oldStream, callback, true);
- },
- isVideoMuted: function (jid) {
- if (jid === APP.xmpp.myJid()) {
- var localVideo = APP.RTC.localVideo;
- return (!localVideo || localVideo.isMuted());
- } else {
- if (!APP.RTC.remoteStreams[jid] ||
- !APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
- return null;
- }
- return APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted;
- }
- },
- setVideoMute: function (mute, callback, options) {
- if (!this.localVideo)
- return;
-
- if (mute == APP.RTC.localVideo.isMuted())
- {
- APP.xmpp.sendVideoInfoPresence(mute);
- if (callback)
- callback(mute);
- }
- else
- {
- APP.RTC.localVideo.setMute(mute);
- APP.xmpp.setVideoMute(
- mute,
- callback,
- options);
- }
- },
- setDeviceAvailability: function (devices) {
- if(!devices)
- return;
- if(devices.audio === true || devices.audio === false)
- this.devices.audio = devices.audio;
- if(devices.video === true || devices.video === false)
- this.devices.video = devices.video;
- eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, this.devices);
- }
-};
-
-module.exports = RTC;
-
-},{"../../service/RTC/MediaStreamTypes":156,"../../service/RTC/RTCEvents.js":157,"../../service/RTC/StreamEventTypes.js":159,"../../service/UI/UIEvents":160,"../../service/desktopsharing/DesktopSharingEventTypes":163,"../../service/xmpp/XMPPEvents":166,"./DataChannels":6,"./LocalStream.js":7,"./MediaStream.js":8,"./RTCBrowserType":10,"./RTCUtils.js":11,"events":1}],10:[function(require,module,exports){
-
-var currentBrowser;
-
-var browserVersion;
-
-var RTCBrowserType = {
-
- RTC_BROWSER_CHROME: "rtc_browser.chrome",
-
- RTC_BROWSER_OPERA: "rtc_browser.opera",
-
- RTC_BROWSER_FIREFOX: "rtc_browser.firefox",
-
- RTC_BROWSER_IEXPLORER: "rtc_browser.iexplorer",
-
- RTC_BROWSER_SAFARI: "rtc_browser.safari",
-
- getBrowserType: function () {
- return currentBrowser;
- },
-
- isChrome: function () {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_CHROME;
- },
-
- isOpera: function () {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_OPERA;
- },
- isFirefox: function () {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_FIREFOX;
- },
-
- isIExplorer: function () {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_IEXPLORER;
- },
-
- isSafari: function () {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_SAFARI;
- },
- isTemasysPluginUsed: function () {
- return RTCBrowserType.isIExplorer() || RTCBrowserType.isSafari();
- },
- getFirefoxVersion: function () {
- return RTCBrowserType.isFirefox() ? browserVersion : null;
- },
-
- getChromeVersion: function () {
- return RTCBrowserType.isChrome() ? browserVersion : null;
- },
-
- usesPlanB: function() {
- return RTCBrowserType.isChrome() || RTCBrowserType.isOpera() ||
- RTCBrowserType.isTemasysPluginUsed();
- },
-
- usesUnifiedPlan: function() {
- return RTCBrowserType.isFirefox();
- }
-
- // Add version getters for other browsers when needed
-};
-
-// detectOpera() must be called before detectChrome() !!!
-// otherwise Opera wil be detected as Chrome
-function detectChrome() {
- if (navigator.webkitGetUserMedia) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_CHROME;
- var userAgent = navigator.userAgent.toLowerCase();
- // We can assume that user agent is chrome, because it's
- // enforced when 'ext' streaming method is set
- var ver = parseInt(userAgent.match(/chrome\/(\d+)\./)[1], 10);
- console.log("This appears to be Chrome, ver: " + ver);
- return ver;
- }
- return null;
-}
-
-function detectOpera() {
- var userAgent = navigator.userAgent;
- if (userAgent.match(/Opera|OPR/)) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_OPERA;
- var version = userAgent.match(/(Opera|OPR) ?\/?(\d+)\.?/)[2];
- console.info("This appears to be Opera, ver: " + version);
- return version;
- }
- return null;
-}
-
-function detectFirefox() {
- if (navigator.mozGetUserMedia) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_FIREFOX;
- var version = parseInt(
- navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
- console.log('This appears to be Firefox, ver: ' + version);
- return version;
- }
- return null;
-}
-
-function detectSafari() {
- if ((/^((?!chrome).)*safari/i.test(navigator.userAgent))) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;
- console.info("This appears to be Safari");
- // FIXME detect Safari version when needed
- return 1;
- }
- return null;
-}
-
-function detectIE() {
- var version;
- var ua = window.navigator.userAgent;
-
- var msie = ua.indexOf('MSIE ');
- if (msie > 0) {
- // IE 10 or older => return version number
- version = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
- }
-
- var trident = ua.indexOf('Trident/');
- if (!version && trident > 0) {
- // IE 11 => return version number
- var rv = ua.indexOf('rv:');
- version = parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
- }
-
- var edge = ua.indexOf('Edge/');
- if (!version && edge > 0) {
- // IE 12 => return version number
- version = parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
- }
-
- if (version) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_IEXPLORER;
- console.info("This appears to be IExplorer, ver: " + version);
- }
- return version;
-}
-
-function detectBrowser() {
- var version;
- var detectors = [
- detectOpera,
- detectChrome,
- detectFirefox,
- detectIE,
- detectSafari
- ];
- // Try all browser detectors
- for (var i = 0; i < detectors.length; i++) {
- version = detectors[i]();
- if (version)
- return version;
- }
- console.error("Failed to detect browser type");
- return undefined;
-}
-
-browserVersion = detectBrowser();
-
-module.exports = RTCBrowserType;
-},{}],11:[function(require,module,exports){
-/* global config, require, attachMediaStream, getUserMedia */
-var RTCBrowserType = require("./RTCBrowserType");
-var Resolutions = require("../../service/RTC/Resolutions");
-var AdapterJS = require("./adapter.screenshare");
-var SDPUtil = require("../xmpp/SDPUtil");
-
-var currentResolution = null;
-
-function getPreviousResolution(resolution) {
- if(!Resolutions[resolution])
- return null;
- var order = Resolutions[resolution].order;
- var res = null;
- var resName = null;
- for(var i in Resolutions) {
- var tmp = Resolutions[i];
- if(res == null || (res.order < tmp.order && tmp.order < order)) {
- resName = i;
- res = tmp;
- }
- }
- return resName;
-}
-
-function setResolutionConstraints(constraints, resolution, isAndroid) {
-
- if (Resolutions[resolution]) {
- constraints.video.mandatory.minWidth = Resolutions[resolution].width;
- constraints.video.mandatory.minHeight = Resolutions[resolution].height;
- }
- else if (isAndroid) {
- // FIXME can't remember if the purpose of this was to always request
- // low resolution on Android ? if yes it should be moved up front
- constraints.video.mandatory.minWidth = 320;
- constraints.video.mandatory.minHeight = 240;
- constraints.video.mandatory.maxFrameRate = 15;
- }
-
- if (constraints.video.mandatory.minWidth)
- constraints.video.mandatory.maxWidth =
- constraints.video.mandatory.minWidth;
- if (constraints.video.mandatory.minHeight)
- constraints.video.mandatory.maxHeight =
- constraints.video.mandatory.minHeight;
-}
-
-function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid)
-{
- var constraints = {audio: false, video: false};
-
- if (um.indexOf('video') >= 0) {
- // same behaviour as true
- constraints.video = { mandatory: {}, optional: [] };
-
- constraints.video.optional.push({ googLeakyBucket: true });
-
- setResolutionConstraints(constraints, resolution, isAndroid);
- }
- if (um.indexOf('audio') >= 0) {
- if (!RTCBrowserType.isFirefox()) {
- // same behaviour as true
- constraints.audio = { mandatory: {}, optional: []};
- // if it is good enough for hangouts...
- constraints.audio.optional.push(
- {googEchoCancellation: true},
- {googAutoGainControl: true},
- {googNoiseSupression: true},
- {googHighpassFilter: true},
- {googNoisesuppression2: true},
- {googEchoCancellation2: true},
- {googAutoGainControl2: true}
- );
- } else {
- constraints.audio = true;
- }
- }
- if (um.indexOf('screen') >= 0) {
- if (RTCBrowserType.isChrome()) {
- constraints.video = {
- mandatory: {
- chromeMediaSource: "screen",
- googLeakyBucket: true,
- maxWidth: window.screen.width,
- maxHeight: window.screen.height,
- maxFrameRate: 3
- },
- optional: []
- };
- } else if (RTCBrowserType.isTemasysPluginUsed()) {
- constraints.video = {
- optional: [
- {
- sourceId: AdapterJS.WebRTCPlugin.plugin.screensharingKey
- }
- ]
- };
- } else {
- console.error(
- "'screen' WebRTC media source is supported only in Chrome" +
- " and with Temasys plugin");
- }
- }
- if (um.indexOf('desktop') >= 0) {
- constraints.video = {
- mandatory: {
- chromeMediaSource: "desktop",
- chromeMediaSourceId: desktopStream,
- googLeakyBucket: true,
- maxWidth: window.screen.width,
- maxHeight: window.screen.height,
- maxFrameRate: 3
- },
- optional: []
- };
- }
-
- if (bandwidth) {
- if (!constraints.video) {
- //same behaviour as true
- constraints.video = {mandatory: {}, optional: []};
- }
- constraints.video.optional.push({bandwidth: bandwidth});
- }
- if (fps) {
- // for some cameras it might be necessary to request 30fps
- // so they choose 30fps mjpg over 10fps yuy2
- if (!constraints.video) {
- // same behaviour as true;
- constraints.video = {mandatory: {}, optional: []};
- }
- constraints.video.mandatory.minFrameRate = fps;
- }
-
- return constraints;
-}
-
-
-function RTCUtils(RTCService, onTemasysPluginReady)
-{
- var self = this;
- this.service = RTCService;
- if (RTCBrowserType.isFirefox()) {
- var FFversion = RTCBrowserType.getFirefoxVersion();
- if (FFversion >= 40) {
- this.peerconnection = mozRTCPeerConnection;
- this.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
- this.pc_constraints = {};
- this.attachMediaStream = function (element, stream) {
- // srcObject is being standardized and FF will eventually
- // support that unprefixed. FF also supports the
- // "element.src = URL.createObjectURL(...)" combo, but that
- // will be deprecated in favour of srcObject.
- //
- // https://groups.google.com/forum/#!topic/mozilla.dev.media/pKOiioXonJg
- // https://github.com/webrtc/samples/issues/302
- if(!element[0])
- return;
- element[0].mozSrcObject = stream;
- element[0].play();
- };
- this.getStreamID = function (stream) {
- var id = stream.id;
- if (!id) {
- var tracks = stream.getVideoTracks();
- if (!tracks || tracks.length === 0) {
- tracks = stream.getAudioTracks();
- }
- id = tracks[0].id;
- }
- return SDPUtil.filter_special_chars(id);
- };
- this.getVideoSrc = function (element) {
- if(!element)
- return null;
- return element.mozSrcObject;
- };
- this.setVideoSrc = function (element, src) {
- if(element)
- element.mozSrcObject = src;
- };
- RTCSessionDescription = mozRTCSessionDescription;
- RTCIceCandidate = mozRTCIceCandidate;
- } else {
- console.error(
- "Firefox version too old: " + FFversion + ". Required >= 40.");
- window.location.href = 'unsupported_browser.html';
- return;
- }
-
- } else if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) {
- this.peerconnection = webkitRTCPeerConnection;
- this.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- this.attachMediaStream = function (element, stream) {
- element.attr('src', webkitURL.createObjectURL(stream));
- };
- this.getStreamID = function (stream) {
- // streams from FF endpoints have the characters '{' and '}'
- // that make jQuery choke.
- return SDPUtil.filter_special_chars(stream.id);
- };
- this.getVideoSrc = function (element) {
- if(!element)
- return null;
- return element.getAttribute("src");
- };
- this.setVideoSrc = function (element, src) {
- if(element)
- element.setAttribute("src", src);
- };
- // DTLS should now be enabled by default but..
- this.pc_constraints = {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]};
- if (navigator.userAgent.indexOf('Android') != -1) {
- this.pc_constraints = {}; // disable DTLS on Android
- }
- if (!webkitMediaStream.prototype.getVideoTracks) {
- webkitMediaStream.prototype.getVideoTracks = function () {
- return this.videoTracks;
- };
- }
- if (!webkitMediaStream.prototype.getAudioTracks) {
- webkitMediaStream.prototype.getAudioTracks = function () {
- return this.audioTracks;
- };
- }
- }
- // Detect IE/Safari
- else if (RTCBrowserType.isTemasysPluginUsed()) {
-
- //AdapterJS.WebRTCPlugin.setLogLevel(
- // AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS.VERBOSE);
-
- AdapterJS.webRTCReady(function (isPlugin) {
-
- self.peerconnection = RTCPeerConnection;
- self.getUserMedia = getUserMedia;
- self.attachMediaStream = function (elSel, stream) {
-
- if (stream.id === "dummyAudio" || stream.id === "dummyVideo") {
- return;
- }
-
- attachMediaStream(elSel[0], stream);
- };
- self.getStreamID = function (stream) {
- var id = SDPUtil.filter_special_chars(stream.label);
- return id;
- };
- self.getVideoSrc = function (element) {
- if (!element) {
- console.warn("Attempt to get video SRC of null element");
- return null;
- }
- var children = element.children;
- for (var i = 0; i !== children.length; ++i) {
- if (children[i].name === 'streamId') {
- return children[i].value;
- }
- }
- //console.info(element.id + " SRC: " + src);
- return null;
- };
- self.setVideoSrc = function (element, src) {
- //console.info("Set video src: ", element, src);
- if (!src) {
- console.warn("Not attaching video stream, 'src' is null");
- return;
- }
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- var stream = AdapterJS.WebRTCPlugin.plugin
- .getStreamWithId(AdapterJS.WebRTCPlugin.pageId, src);
- attachMediaStream(element, stream);
- };
-
- onTemasysPluginReady(isPlugin);
- });
- } else {
- try {
- console.log('Browser does not appear to be WebRTC-capable');
- } catch (e) { }
- window.location.href = 'unsupported_browser.html';
- }
-}
-
-
-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);
-
- console.info("Get media constraints", constraints);
-
- var self = this;
-
- try {
- this.getUserMedia(constraints,
- function (stream) {
- console.log('onUserMediaSuccess');
- self.setAvailableDevices(um, true);
- success_callback(stream);
- },
- function (error) {
- self.setAvailableDevices(um, false);
- console.warn('Failed to get access to local media. Error ',
- error, constraints);
- if (failure_callback) {
- failure_callback(error);
- }
- });
- } catch (e) {
- console.error('GUM failed: ', e);
- if(failure_callback) {
- failure_callback(e);
- }
- }
-};
-
-RTCUtils.prototype.setAvailableDevices = function (um, available) {
- var devices = {};
- if(um.indexOf("video") != -1) {
- devices.video = available;
- }
- if(um.indexOf("audio") != -1) {
- devices.audio = available;
- }
- this.service.setDeviceAvailability(devices);
-};
-
-/**
- * We ask for audio and video combined stream in order to get permissions and
- * not to ask twice.
- */
-RTCUtils.prototype.obtainAudioAndVideoPermissions =
- function(devices, callback, usageOptions)
-{
- var self = this;
- // Get AV
-
- var successCallback = function (stream) {
- if(callback)
- callback(stream, usageOptions);
- else
- self.successCallback(stream, usageOptions);
- };
-
- if(!devices)
- devices = ['audio', 'video'];
-
- var newDevices = [];
-
-
- if(usageOptions)
- for(var i = 0; i < devices.length; i++) {
- var device = devices[i];
- if(usageOptions[device] === true)
- newDevices.push(device);
- }
- else
- newDevices = devices;
-
- if(newDevices.length === 0) {
- successCallback();
- return;
- }
-
- if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) {
-
- // With FF/IE we can't split the stream into audio and video because FF
- // doesn't support media stream constructors. So, we need to get the
- // audio stream separately from the video stream using two distinct GUM
- // calls. Not very user friendly :-( but we don't have many other
- // options neither.
- //
- // Note that we pack those 2 streams in a single object and pass it to
- // the successCallback method.
- var obtainVideo = function (audioStream) {
- self.getUserMediaWithConstraints(
- ['video'],
- function (videoStream) {
- return successCallback({
- audioStream: audioStream,
- videoStream: videoStream
- });
- },
- function (error) {
- console.error(
- 'failed to obtain video stream - stop', error);
- self.errorCallback(error);
- },
- config.resolution || '360');
- };
- var obtainAudio = function () {
- self.getUserMediaWithConstraints(
- ['audio'],
- function (audioStream) {
- if (newDevices.indexOf('video') !== -1)
- obtainVideo(audioStream);
- },
- function (error) {
- console.error(
- 'failed to obtain audio stream - stop', error);
- self.errorCallback(error);
- }
- );
- };
- if (newDevices.indexOf('audio') !== -1) {
- obtainAudio();
- } else {
- obtainVideo(null);
- }
- } else {
- this.getUserMediaWithConstraints(
- newDevices,
- function (stream) {
- successCallback(stream);
- },
- function (error) {
- self.errorCallback(error);
- },
- config.resolution || '360');
- }
-};
-
-RTCUtils.prototype.successCallback = function (stream, usageOptions) {
- // If this is FF or IE, the stream parameter is *not* a MediaStream object,
- // it's an object with two properties: audioStream, videoStream.
- if (stream && stream.getAudioTracks && stream.getVideoTracks)
- console.log('got', stream, stream.getAudioTracks().length,
- stream.getVideoTracks().length);
- this.handleLocalStream(stream, usageOptions);
-};
-
-RTCUtils.prototype.errorCallback = function (error) {
- var self = this;
- console.error('failed to obtain audio/video stream - trying audio only', error);
- var resolution = getPreviousResolution(currentResolution);
- if(typeof error == "object" && error.constraintName && error.name
- && (error.name == "ConstraintNotSatisfiedError" ||
- error.name == "OverconstrainedError") &&
- (error.constraintName == "minWidth" || error.constraintName == "maxWidth" ||
- error.constraintName == "minHeight" || error.constraintName == "maxHeight")
- && resolution != null)
- {
- self.getUserMediaWithConstraints(['audio', 'video'],
- function (stream) {
- return self.successCallback(stream);
- }, function (error) {
- return self.errorCallback(error);
- }, resolution);
- }
- else {
- self.getUserMediaWithConstraints(
- ['audio'],
- function (stream) {
- return self.successCallback(stream);
- },
- function (error) {
- console.error('failed to obtain audio/video stream - stop',
- error);
- return self.successCallback(null);
- }
- );
- }
-};
-
-RTCUtils.prototype.handleLocalStream = function(stream, usageOptions) {
- // If this is FF, the stream parameter is *not* a MediaStream object, it's
- // an object with two properties: audioStream, videoStream.
- var audioStream, videoStream;
- if(window.webkitMediaStream)
- {
- audioStream = new webkitMediaStream();
- videoStream = new webkitMediaStream();
- if(stream) {
- var audioTracks = stream.getAudioTracks();
-
- for (var i = 0; i < audioTracks.length; i++) {
- audioStream.addTrack(audioTracks[i]);
- }
-
- var videoTracks = stream.getVideoTracks();
-
- for (i = 0; i < videoTracks.length; i++) {
- videoStream.addTrack(videoTracks[i]);
- }
- }
- }
- else if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed())
- { // Firefox and Temasys plugin
- if (stream && stream.audioStream)
- audioStream = stream.audioStream;
- else
- audioStream = new DummyMediaStream("dummyAudio");
-
- if (stream && stream.videoStream)
- videoStream = stream.videoStream;
- else
- videoStream = new DummyMediaStream("dummyVideo");
- }
-
- var audioMuted = (usageOptions && usageOptions.audio === false),
- videoMuted = (usageOptions && usageOptions.video === false);
-
- var audioGUM = (!usageOptions || usageOptions.audio !== false),
- videoGUM = (!usageOptions || usageOptions.video !== false);
-
-
- this.service.createLocalStream(audioStream, "audio", null, null,
- audioMuted, audioGUM);
-
- this.service.createLocalStream(videoStream, "video", null, 'camera',
- videoMuted, videoGUM);
-};
-
-function DummyMediaStream(id) {
- this.id = id;
- this.label = id;
- this.stop = function() { };
- this.getAudioTracks = function() { return []; };
- this.getVideoTracks = function() { return []; };
-}
-
-RTCUtils.prototype.createStream = function(stream, isVideo) {
- var newStream = null;
- if (window.webkitMediaStream) {
- newStream = new webkitMediaStream();
- if (newStream) {
- var tracks = (isVideo ? stream.getVideoTracks() : stream.getAudioTracks());
-
- for (var i = 0; i < tracks.length; i++) {
- newStream.addTrack(tracks[i]);
- }
- }
-
- }
- else {
- // FIXME: this is duplicated with 'handleLocalStream' !!!
- if (stream) {
- newStream = stream;
- } else {
- newStream =
- new DummyMediaStream(isVideo ? "dummyVideo" : "dummyAudio");
- }
- }
-
- return newStream;
-};
-
-module.exports = RTCUtils;
-
-},{"../../service/RTC/Resolutions":158,"../xmpp/SDPUtil":60,"./RTCBrowserType":10,"./adapter.screenshare":12}],12:[function(require,module,exports){
-/*! adapterjs - custom version from - 2015-08-12 */
-
-// Adapter's interface.
-var AdapterJS = AdapterJS || {};
-
-// Browserify compatibility
-if(typeof exports !== 'undefined') {
- module.exports = AdapterJS;
-}
-
-AdapterJS.options = AdapterJS.options || {};
-
-// uncomment to get virtual webcams
-// AdapterJS.options.getAllCams = true;
-
-// uncomment to prevent the install prompt when the plugin in not yet installed
-// AdapterJS.options.hidePluginInstallPrompt = true;
-
-// AdapterJS version
-AdapterJS.VERSION = '0.11.1';
-
-// This function will be called when the WebRTC API is ready to be used
-// Whether it is the native implementation (Chrome, Firefox, Opera) or
-// the plugin
-// You may Override this function to synchronise the start of your application
-// with the WebRTC API being ready.
-// If you decide not to override use this synchronisation, it may result in
-// an extensive CPU usage on the plugin start (once per tab loaded)
-// Params:
-// - isUsingPlugin: true is the WebRTC plugin is being used, false otherwise
-//
-AdapterJS.onwebrtcready = AdapterJS.onwebrtcready || function(isUsingPlugin) {
- // The WebRTC API is ready.
- // Override me and do whatever you want here
-};
-
-// Sets a callback function to be called when the WebRTC interface is ready.
-// The first argument is the function to callback.\
-// Throws an error if the first argument is not a function
-AdapterJS.webRTCReady = function (callback) {
- if (typeof callback !== 'function') {
- throw new Error('Callback provided is not a function');
- }
-
- if (true === AdapterJS.onwebrtcreadyDone) {
- // All WebRTC interfaces are ready, just call the callback
- callback(null !== AdapterJS.WebRTCPlugin.plugin);
- } else {
- // will be triggered automatically when your browser/plugin is ready.
- AdapterJS.onwebrtcready = callback;
- }
-};
-
-// Plugin namespace
-AdapterJS.WebRTCPlugin = AdapterJS.WebRTCPlugin || {};
-
-// The object to store plugin information
-AdapterJS.WebRTCPlugin.pluginInfo = {
- prefix : 'Tem',
- plugName : 'TemWebRTCPlugin',
- pluginId : 'plugin0',
- type : 'application/x-temwebrtcplugin',
- onload : '__TemWebRTCReady0',
- portalLink : 'http://skylink.io/plugin/',
- downloadLink : null, //set below
- companyName: 'Temasys'
-};
-if(!!navigator.platform.match(/^Mac/i)) {
- AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1n77hco';
-}
-else if(!!navigator.platform.match(/^Win/i)) {
- AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1kkS4FN';
-}
-
-// Unique identifier of each opened page
-AdapterJS.WebRTCPlugin.pageId = Math.random().toString(36).slice(2);
-
-// Use this whenever you want to call the plugin.
-AdapterJS.WebRTCPlugin.plugin = null;
-
-// Set log level for the plugin once it is ready.
-// The different values are
-// This is an asynchronous function that will run when the plugin is ready
-AdapterJS.WebRTCPlugin.setLogLevel = null;
-
-// Defines webrtc's JS interface according to the plugin's implementation.
-// Define plugin Browsers as WebRTC Interface.
-AdapterJS.WebRTCPlugin.defineWebRTCInterface = null;
-
-// This function detects whether or not a plugin is installed.
-// Checks if Not IE (firefox, for example), else if it's IE,
-// we're running IE and do something. If not it is not supported.
-AdapterJS.WebRTCPlugin.isPluginInstalled = null;
-
- // Lets adapter.js wait until the the document is ready before injecting the plugin
-AdapterJS.WebRTCPlugin.pluginInjectionInterval = null;
-
-// Inject the HTML DOM object element into the page.
-AdapterJS.WebRTCPlugin.injectPlugin = null;
-
-// States of readiness that the plugin goes through when
-// being injected and stated
-AdapterJS.WebRTCPlugin.PLUGIN_STATES = {
- NONE : 0, // no plugin use
- INITIALIZING : 1, // Detected need for plugin
- INJECTING : 2, // Injecting plugin
- INJECTED: 3, // Plugin element injected but not usable yet
- READY: 4 // Plugin ready to be used
-};
-
-// Current state of the plugin. You cannot use the plugin before this is
-// equal to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY
-AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.NONE;
-
-// True is AdapterJS.onwebrtcready was already called, false otherwise
-// Used to make sure AdapterJS.onwebrtcready is only called once
-AdapterJS.onwebrtcreadyDone = false;
-
-// Log levels for the plugin.
-// To be set by calling AdapterJS.WebRTCPlugin.setLogLevel
-/*
-Log outputs are prefixed in some cases.
- INFO: Information reported by the plugin.
- ERROR: Errors originating from within the plugin.
- WEBRTC: Error originating from within the libWebRTC library
-*/
-// From the least verbose to the most verbose
-AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS = {
- NONE : 'NONE',
- ERROR : 'ERROR',
- WARNING : 'WARNING',
- INFO: 'INFO',
- VERBOSE: 'VERBOSE',
- SENSITIVE: 'SENSITIVE'
-};
-
-// Does a waiting check before proceeding to load the plugin.
-AdapterJS.WebRTCPlugin.WaitForPluginReady = null;
-
-// This methid will use an interval to wait for the plugin to be ready.
-AdapterJS.WebRTCPlugin.callWhenPluginReady = null;
-
-// !!!! WARNING: DO NOT OVERRIDE THIS FUNCTION. !!!
-// This function will be called when plugin is ready. It sends necessary
-// details to the plugin.
-// The function will wait for the document to be ready and the set the
-// plugin state to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY,
-// indicating that it can start being requested.
-// This function is not in the IE/Safari condition brackets so that
-// TemPluginLoaded function might be called on Chrome/Firefox.
-// This function is the only private function that is not encapsulated to
-// allow the plugin method to be called.
-__TemWebRTCReady0 = function () {
- if (document.readyState === 'complete') {
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;
-
- AdapterJS.maybeThroughWebRTCReady();
- } else {
- AdapterJS.WebRTCPlugin.documentReadyInterval = setInterval(function () {
- if (document.readyState === 'complete') {
- // TODO: update comments, we wait for the document to be ready
- clearInterval(AdapterJS.WebRTCPlugin.documentReadyInterval);
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;
-
- AdapterJS.maybeThroughWebRTCReady();
- }
- }, 100);
- }
-};
-
-AdapterJS.maybeThroughWebRTCReady = function() {
- if (!AdapterJS.onwebrtcreadyDone) {
- AdapterJS.onwebrtcreadyDone = true;
-
- if (typeof(AdapterJS.onwebrtcready) === 'function') {
- AdapterJS.onwebrtcready(AdapterJS.WebRTCPlugin.plugin !== null);
- }
- }
-};
-
-// Text namespace
-AdapterJS.TEXT = {
- PLUGIN: {
- REQUIRE_INSTALLATION: 'This website requires you to install a WebRTC-enabling plugin ' +
- 'to work on this browser.',
- NOT_SUPPORTED: 'Your browser does not support WebRTC.',
- BUTTON: 'Install Now'
- },
- REFRESH: {
- REQUIRE_REFRESH: 'Please refresh page',
- BUTTON: 'Refresh Page'
- }
-};
-
-// The result of ice connection states.
-// - starting: Ice connection is starting.
-// - checking: Ice connection is checking.
-// - connected Ice connection is connected.
-// - completed Ice connection is connected.
-// - done Ice connection has been completed.
-// - disconnected Ice connection has been disconnected.
-// - failed Ice connection has failed.
-// - closed Ice connection is closed.
-AdapterJS._iceConnectionStates = {
- starting : 'starting',
- checking : 'checking',
- connected : 'connected',
- completed : 'connected',
- done : 'completed',
- disconnected : 'disconnected',
- failed : 'failed',
- closed : 'closed'
-};
-
-//The IceConnection states that has been fired for each peer.
-AdapterJS._iceConnectionFiredStates = [];
-
-
-// Check if WebRTC Interface is defined.
-AdapterJS.isDefined = null;
-
-// This function helps to retrieve the webrtc detected browser information.
-// This sets:
-// - webrtcDetectedBrowser: The browser agent name.
-// - webrtcDetectedVersion: The browser version.
-// - webrtcDetectedType: The types of webRTC support.
-// - 'moz': Mozilla implementation of webRTC.
-// - 'webkit': WebKit implementation of webRTC.
-// - 'plugin': Using the plugin implementation.
-AdapterJS.parseWebrtcDetectedBrowser = function () {
- var hasMatch, checkMatch = navigator.userAgent.match(
- /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
- if (/trident/i.test(checkMatch[1])) {
- hasMatch = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || [];
- webrtcDetectedBrowser = 'IE';
- webrtcDetectedVersion = parseInt(hasMatch[1] || '0', 10);
- } else if (checkMatch[1] === 'Chrome') {
- hasMatch = navigator.userAgent.match(/\bOPR\/(\d+)/);
- if (hasMatch !== null) {
- webrtcDetectedBrowser = 'opera';
- webrtcDetectedVersion = parseInt(hasMatch[1], 10);
- }
- }
- if (navigator.userAgent.indexOf('Safari')) {
- if (typeof InstallTrigger !== 'undefined') {
- webrtcDetectedBrowser = 'firefox';
- } else if (/*@cc_on!@*/ false || !!document.documentMode) {
- webrtcDetectedBrowser = 'IE';
- } else if (
- Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
- webrtcDetectedBrowser = 'safari';
- } else if (!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
- webrtcDetectedBrowser = 'opera';
- } else if (!!window.chrome) {
- webrtcDetectedBrowser = 'chrome';
- }
- }
- if (!webrtcDetectedBrowser) {
- webrtcDetectedVersion = checkMatch[1];
- }
- if (!webrtcDetectedVersion) {
- try {
- checkMatch = (checkMatch[2]) ? [checkMatch[1], checkMatch[2]] :
- [navigator.appName, navigator.appVersion, '-?'];
- if ((hasMatch = navigator.userAgent.match(/version\/(\d+)/i)) !== null) {
- checkMatch.splice(1, 1, hasMatch[1]);
- }
- webrtcDetectedVersion = parseInt(checkMatch[1], 10);
- } catch (error) { }
- }
-};
-
-// To fix configuration as some browsers does not support
-// the 'urls' attribute.
-AdapterJS.maybeFixConfiguration = function (pcConfig) {
- if (pcConfig === null) {
- return;
- }
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- if (pcConfig.iceServers[i].hasOwnProperty('urls')) {
- pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;
- delete pcConfig.iceServers[i].urls;
- }
- }
-};
-
-AdapterJS.addEvent = function(elem, evnt, func) {
- if (elem.addEventListener) { // W3C DOM
- elem.addEventListener(evnt, func, false);
- } else if (elem.attachEvent) {// OLD IE DOM
- elem.attachEvent('on'+evnt, func);
- } else { // No much to do
- elem[evnt] = func;
- }
-};
-
-AdapterJS.renderNotificationBar = function (text, buttonText, buttonLink, openNewTab, displayRefreshBar) {
- // only inject once the page is ready
- if (document.readyState !== 'complete') {
- return;
- }
-
- var w = window;
- var i = document.createElement('iframe');
- i.style.position = 'fixed';
- i.style.top = '-41px';
- i.style.left = 0;
- i.style.right = 0;
- i.style.width = '100%';
- i.style.height = '40px';
- i.style.backgroundColor = '#ffffe1';
- i.style.border = 'none';
- i.style.borderBottom = '1px solid #888888';
- i.style.zIndex = '9999999';
- if(typeof i.style.webkitTransition === 'string') {
- i.style.webkitTransition = 'all .5s ease-out';
- } else if(typeof i.style.transition === 'string') {
- i.style.transition = 'all .5s ease-out';
- }
- document.body.appendChild(i);
- c = (i.contentWindow) ? i.contentWindow :
- (i.contentDocument.document) ? i.contentDocument.document : i.contentDocument;
- c.document.open();
- c.document.write('' + text + '');
- if(buttonText && buttonLink) {
- c.document.write('');
- c.document.close();
-
- AdapterJS.addEvent(c.document.getElementById('okay'), 'click', function(e) {
- if (!!displayRefreshBar) {
- AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION ?
- AdapterJS.TEXT.EXTENSION.REQUIRE_REFRESH : AdapterJS.TEXT.REFRESH.REQUIRE_REFRESH,
- AdapterJS.TEXT.REFRESH.BUTTON, 'javascript:location.reload()');
- }
- window.open(buttonLink, !!openNewTab ? '_blank' : '_top');
-
- e.preventDefault();
- try {
- 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);
- });
-
- }else {
- c.document.close();
- }
- AdapterJS.addEvent(c.document, 'click', function() {
- w.document.body.removeChild(i);
- });
- setTimeout(function() {
- if(typeof i.style.webkitTransform === 'string') {
- i.style.webkitTransform = 'translateY(40px)';
- } else if(typeof i.style.transform === 'string') {
- i.style.transform = 'translateY(40px)';
- } else {
- i.style.top = '0px';
- }
- }, 300);
-};
-
-// -----------------------------------------------------------
-// Detected webrtc implementation. Types are:
-// - 'moz': Mozilla implementation of webRTC.
-// - 'webkit': WebKit implementation of webRTC.
-// - 'plugin': Using the plugin implementation.
-webrtcDetectedType = null;
-
-// Detected webrtc datachannel support. Types are:
-// - 'SCTP': SCTP datachannel support.
-// - 'RTP': RTP datachannel support.
-webrtcDetectedDCSupport = null;
-
-// Set the settings for creating DataChannels, MediaStream for
-// Cross-browser compability.
-// - This is only for SCTP based support browsers.
-// the 'urls' attribute.
-checkMediaDataChannelSettings =
- function (peerBrowserAgent, peerBrowserVersion, callback, constraints) {
- if (typeof callback !== 'function') {
- return;
- }
- var beOfferer = true;
- var isLocalFirefox = webrtcDetectedBrowser === 'firefox';
- // Nightly version does not require MozDontOfferDataChannel for interop
- var isLocalFirefoxInterop = webrtcDetectedType === 'moz' && webrtcDetectedVersion > 30;
- var isPeerFirefox = peerBrowserAgent === 'firefox';
- var isPeerFirefoxInterop = peerBrowserAgent === 'firefox' &&
- ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);
-
- // Resends an updated version of constraints for MozDataChannel to work
- // If other userAgent is firefox and user is firefox, remove MozDataChannel
- if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {
- try {
- delete constraints.mandatory.MozDontOfferDataChannel;
- } catch (error) {
- console.error('Failed deleting MozDontOfferDataChannel');
- console.error(error);
- }
- } else if ((isLocalFirefox && !isPeerFirefox)) {
- constraints.mandatory.MozDontOfferDataChannel = true;
- }
- if (!isLocalFirefox) {
- // temporary measure to remove Moz* constraints in non Firefox browsers
- for (var prop in constraints.mandatory) {
- if (constraints.mandatory.hasOwnProperty(prop)) {
- if (prop.indexOf('Moz') !== -1) {
- delete constraints.mandatory[prop];
- }
- }
- }
- }
- // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the
- // interopability of the media stream
- if (isLocalFirefox && !isPeerFirefox && !isLocalFirefoxInterop) {
- beOfferer = false;
- }
- callback(beOfferer, constraints);
-};
-
-// Handles the differences for all browsers ice connection state output.
-// - Tested outcomes are:
-// - Chrome (offerer) : 'checking' > 'completed' > 'completed'
-// - Chrome (answerer) : 'checking' > 'connected'
-// - Firefox (offerer) : 'checking' > 'connected'
-// - Firefox (answerer): 'checking' > 'connected'
-checkIceConnectionState = function (peerId, iceConnectionState, callback) {
- if (typeof callback !== 'function') {
- console.warn('No callback specified in checkIceConnectionState. Aborted.');
- return;
- }
- peerId = (peerId) ? peerId : 'peer';
-
- if (!AdapterJS._iceConnectionFiredStates[peerId] ||
- iceConnectionState === AdapterJS._iceConnectionStates.disconnected ||
- iceConnectionState === AdapterJS._iceConnectionStates.failed ||
- iceConnectionState === AdapterJS._iceConnectionStates.closed) {
- AdapterJS._iceConnectionFiredStates[peerId] = [];
- }
- iceConnectionState = AdapterJS._iceConnectionStates[iceConnectionState];
- if (AdapterJS._iceConnectionFiredStates[peerId].indexOf(iceConnectionState) < 0) {
- AdapterJS._iceConnectionFiredStates[peerId].push(iceConnectionState);
- if (iceConnectionState === AdapterJS._iceConnectionStates.connected) {
- setTimeout(function () {
- AdapterJS._iceConnectionFiredStates[peerId]
- .push(AdapterJS._iceConnectionStates.done);
- callback(AdapterJS._iceConnectionStates.done);
- }, 1000);
- }
- callback(iceConnectionState);
- }
- return;
-};
-
-// Firefox:
-// - Creates iceServer from the url for Firefox.
-// - Create iceServer with stun url.
-// - Create iceServer with turn url.
-// - Ignore the transport parameter from TURN url for FF version <=27.
-// - Return null for createIceServer if transport=tcp.
-// - FF 27 and above supports transport parameters in TURN url,
-// - So passing in the full url to create iceServer.
-// Chrome:
-// - Creates iceServer from the url for Chrome M33 and earlier.
-// - Create iceServer with stun url.
-// - Chrome M28 & above uses below TURN format.
-// Plugin:
-// - Creates Ice Server for Plugin Browsers
-// - If Stun - Create iceServer with stun url.
-// - Else - Create iceServer with turn url
-// - This is a WebRTC Function
-createIceServer = null;
-
-// Firefox:
-// - Creates IceServers for Firefox
-// - Use .url for FireFox.
-// - Multiple Urls support
-// Chrome:
-// - Creates iceServers from the urls for Chrome M34 and above.
-// - .urls is supported since Chrome M34.
-// - Multiple Urls support
-// Plugin:
-// - Creates Ice Servers for Plugin Browsers
-// - Multiple Urls support
-// - This is a WebRTC Function
-createIceServers = null;
-//------------------------------------------------------------
-
-//The RTCPeerConnection object.
-RTCPeerConnection = null;
-
-// Creates RTCSessionDescription object for Plugin Browsers
-RTCSessionDescription = (typeof RTCSessionDescription === 'function') ?
- RTCSessionDescription : null;
-
-// Creates RTCIceCandidate object for Plugin Browsers
-RTCIceCandidate = (typeof RTCIceCandidate === 'function') ?
- RTCIceCandidate : null;
-
-// Get UserMedia (only difference is the prefix).
-// Code from Adam Barth.
-getUserMedia = null;
-
-// Attach a media stream to an element.
-attachMediaStream = null;
-
-// Re-attach a media stream to an element.
-reattachMediaStream = null;
-
-
-// Detected browser agent name. Types are:
-// - 'firefox': Firefox browser.
-// - 'chrome': Chrome browser.
-// - 'opera': Opera browser.
-// - 'safari': Safari browser.
-// - 'IE' - Internet Explorer browser.
-webrtcDetectedBrowser = null;
-
-// Detected browser version.
-webrtcDetectedVersion = null;
-
-// Check for browser types and react accordingly
-if (navigator.mozGetUserMedia) {
- webrtcDetectedBrowser = 'firefox';
- webrtcDetectedVersion = parseInt(navigator
- .userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
- webrtcDetectedType = 'moz';
- webrtcDetectedDCSupport = 'SCTP';
-
- RTCPeerConnection = function (pcConfig, pcConstraints) {
- AdapterJS.maybeFixConfiguration(pcConfig);
- return new mozRTCPeerConnection(pcConfig, pcConstraints);
- };
-
- // The RTCSessionDescription object.
- RTCSessionDescription = mozRTCSessionDescription;
- window.RTCSessionDescription = RTCSessionDescription;
-
- // The RTCIceCandidate object.
- RTCIceCandidate = mozRTCIceCandidate;
- window.RTCIceCandidate = RTCIceCandidate;
-
- window.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
- navigator.getUserMedia = window.getUserMedia;
-
- // Shim for MediaStreamTrack.getSources.
- MediaStreamTrack.getSources = function(successCb) {
- setTimeout(function() {
- var infos = [
- { kind: 'audio', id: 'default', label:'', facing:'' },
- { kind: 'video', id: 'default', label:'', facing:'' }
- ];
- successCb(infos);
- }, 0);
- };
-
- createIceServer = function (url, username, password) {
- var iceServer = null;
- var url_parts = url.split(':');
- if (url_parts[0].indexOf('stun') === 0) {
- iceServer = { url : url };
- } else if (url_parts[0].indexOf('turn') === 0) {
- if (webrtcDetectedVersion < 27) {
- var turn_url_parts = url.split('?');
- if (turn_url_parts.length === 1 ||
- turn_url_parts[1].indexOf('transport=udp') === 0) {
- iceServer = {
- url : turn_url_parts[0],
- credential : password,
- username : username
- };
- }
- } else {
- iceServer = {
- url : url,
- credential : password,
- username : username
- };
- }
- }
- return iceServer;
- };
-
- createIceServers = function (urls, username, password) {
- var iceServers = [];
- for (i = 0; i < urls.length; i++) {
- var iceServer = createIceServer(urls[i], username, password);
- if (iceServer !== null) {
- iceServers.push(iceServer);
- }
- }
- return iceServers;
- };
-
- attachMediaStream = function (element, stream) {
- element.mozSrcObject = stream;
- if (stream !== null)
- element.play();
-
- return element;
- };
-
- reattachMediaStream = function (to, from) {
- to.mozSrcObject = from.mozSrcObject;
- to.play();
- return to;
- };
-
- MediaStreamTrack.getSources = MediaStreamTrack.getSources || function (callback) {
- if (!callback) {
- throw new TypeError('Failed to execute \'getSources\' on \'MediaStreamTrack\'' +
- ': 1 argument required, but only 0 present.');
- }
- return callback([]);
- };
-
- // Fake get{Video,Audio}Tracks
- if (!MediaStream.prototype.getVideoTracks) {
- MediaStream.prototype.getVideoTracks = function () {
- return [];
- };
- }
- if (!MediaStream.prototype.getAudioTracks) {
- MediaStream.prototype.getAudioTracks = function () {
- return [];
- };
- }
-
- AdapterJS.maybeThroughWebRTCReady();
-} else if (navigator.webkitGetUserMedia) {
- webrtcDetectedBrowser = 'chrome';
- webrtcDetectedType = 'webkit';
- webrtcDetectedVersion = parseInt(navigator
- .userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
- // check if browser is opera 20+
- var checkIfOpera = navigator.userAgent.match(/\bOPR\/(\d+)/);
- if (checkIfOpera !== null) {
- webrtcDetectedBrowser = 'opera';
- webrtcDetectedVersion = parseInt(checkIfOpera[1], 10);
- }
- // check browser datachannel support
- if ((webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion >= 31) ||
- (webrtcDetectedBrowser === 'opera' && webrtcDetectedVersion >= 20)) {
- webrtcDetectedDCSupport = 'SCTP';
- } else if (webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion < 30 &&
- webrtcDetectedVersion > 24) {
- webrtcDetectedDCSupport = 'RTP';
- } else {
- webrtcDetectedDCSupport = '';
- }
-
- createIceServer = function (url, username, password) {
- var iceServer = null;
- var url_parts = url.split(':');
- if (url_parts[0].indexOf('stun') === 0) {
- iceServer = { 'url' : url };
- } else if (url_parts[0].indexOf('turn') === 0) {
- iceServer = {
- 'url' : url,
- 'credential' : password,
- 'username' : username
- };
- }
- return iceServer;
- };
-
- createIceServers = function (urls, username, password) {
- var iceServers = [];
- if (webrtcDetectedVersion >= 34) {
- iceServers = {
- 'urls' : urls,
- 'credential' : password,
- 'username' : username
- };
- } else {
- for (i = 0; i < urls.length; i++) {
- var iceServer = createIceServer(urls[i], username, password);
- if (iceServer !== null) {
- iceServers.push(iceServer);
- }
- }
- }
- return iceServers;
- };
-
- RTCPeerConnection = function (pcConfig, pcConstraints) {
- if (webrtcDetectedVersion < 34) {
- AdapterJS.maybeFixConfiguration(pcConfig);
- }
- return new webkitRTCPeerConnection(pcConfig, pcConstraints);
- };
-
- window.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- navigator.getUserMedia = window.getUserMedia;
-
- attachMediaStream = function (element, stream) {
- if (typeof element.srcObject !== 'undefined') {
- element.srcObject = stream;
- } else if (typeof element.mozSrcObject !== 'undefined') {
- element.mozSrcObject = stream;
- } else if (typeof element.src !== 'undefined') {
- element.src = (stream === null ? '' : URL.createObjectURL(stream));
- } else {
- console.log('Error attaching stream to element.');
- }
- return element;
- };
-
- reattachMediaStream = function (to, from) {
- to.src = from.src;
- return to;
- };
-
- AdapterJS.maybeThroughWebRTCReady();
-} else { // TRY TO USE PLUGIN
- // IE 9 is not offering an implementation of console.log until you open a console
- if (typeof console !== 'object' || typeof console.log !== 'function') {
- /* jshint -W020 */
- console = {} || console;
- // Implemented based on console specs from MDN
- // You may override these functions
- console.log = function (arg) {};
- console.info = function (arg) {};
- console.error = function (arg) {};
- console.dir = function (arg) {};
- console.exception = function (arg) {};
- console.trace = function (arg) {};
- console.warn = function (arg) {};
- console.count = function (arg) {};
- console.debug = function (arg) {};
- console.count = function (arg) {};
- console.time = function (arg) {};
- console.timeEnd = function (arg) {};
- console.group = function (arg) {};
- console.groupCollapsed = function (arg) {};
- console.groupEnd = function (arg) {};
- /* jshint +W020 */
- }
- webrtcDetectedType = 'plugin';
- webrtcDetectedDCSupport = 'plugin';
- AdapterJS.parseWebrtcDetectedBrowser();
- isIE = webrtcDetectedBrowser === 'IE';
-
- /* jshint -W035 */
- AdapterJS.WebRTCPlugin.WaitForPluginReady = function() {
- while (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- /* empty because it needs to prevent the function from running. */
- }
- };
- /* jshint +W035 */
-
- AdapterJS.WebRTCPlugin.callWhenPluginReady = function (callback) {
- if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- // Call immediately if possible
- // Once the plugin is set, the code will always take this path
- callback();
- } else {
- // otherwise start a 100ms interval
- var checkPluginReadyState = setInterval(function () {
- if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- clearInterval(checkPluginReadyState);
- callback();
- }
- }, 100);
- }
- };
-
- AdapterJS.WebRTCPlugin.setLogLevel = function(logLevel) {
- AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
- AdapterJS.WebRTCPlugin.plugin.setLogLevel(logLevel);
- });
- };
-
- AdapterJS.WebRTCPlugin.injectPlugin = function () {
- // only inject once the page is ready
- if (document.readyState !== 'complete') {
- return;
- }
-
- // Prevent multiple injections
- if (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING) {
- return;
- }
-
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTING;
-
- if (webrtcDetectedBrowser === 'IE' && webrtcDetectedVersion <= 10) {
- var frag = document.createDocumentFragment();
- AdapterJS.WebRTCPlugin.plugin = document.createElement('div');
- AdapterJS.WebRTCPlugin.plugin.innerHTML = '';
- while (AdapterJS.WebRTCPlugin.plugin.firstChild) {
- frag.appendChild(AdapterJS.WebRTCPlugin.plugin.firstChild);
- }
- document.body.appendChild(frag);
-
- // Need to re-fetch the plugin
- AdapterJS.WebRTCPlugin.plugin =
- document.getElementById(AdapterJS.WebRTCPlugin.pluginInfo.pluginId);
- } else {
- // Load Plugin
- AdapterJS.WebRTCPlugin.plugin = document.createElement('object');
- AdapterJS.WebRTCPlugin.plugin.id =
- AdapterJS.WebRTCPlugin.pluginInfo.pluginId;
- // IE will only start the plugin if it's ACTUALLY visible
- if (isIE) {
- AdapterJS.WebRTCPlugin.plugin.width = '1px';
- AdapterJS.WebRTCPlugin.plugin.height = '1px';
- } else { // The size of the plugin on Safari should be 0x0px
- // so that the autorisation prompt is at the top
- AdapterJS.WebRTCPlugin.plugin.width = '0px';
- AdapterJS.WebRTCPlugin.plugin.height = '0px';
- }
- AdapterJS.WebRTCPlugin.plugin.type = AdapterJS.WebRTCPlugin.pluginInfo.type;
- AdapterJS.WebRTCPlugin.plugin.innerHTML = '' +
- '' +
- ' ' +
- (AdapterJS.options.getAllCams ? '':'') +
- '';
- document.body.appendChild(AdapterJS.WebRTCPlugin.plugin);
- }
-
-
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTED;
- };
-
- AdapterJS.WebRTCPlugin.isPluginInstalled =
- function (comName, plugName, installedCb, notInstalledCb) {
- if (!isIE) {
- var pluginArray = navigator.plugins;
- for (var i = 0; i < pluginArray.length; i++) {
- if (pluginArray[i].name.indexOf(plugName) >= 0) {
- installedCb();
- return;
- }
- }
- notInstalledCb();
- } else {
- try {
- var axo = new ActiveXObject(comName + '.' + plugName);
- } catch (e) {
- notInstalledCb();
- return;
- }
- installedCb();
- }
- };
-
- AdapterJS.WebRTCPlugin.defineWebRTCInterface = function () {
- if (AdapterJS.WebRTCPlugin.pluginState ===
- AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- console.error("WebRTC interface has been defined already");
- return;
- }
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING;
-
- AdapterJS.isDefined = function (variable) {
- return variable !== null && variable !== undefined;
- };
-
- createIceServer = function (url, username, password) {
- var iceServer = null;
- var url_parts = url.split(':');
- if (url_parts[0].indexOf('stun') === 0) {
- iceServer = {
- 'url' : url,
- 'hasCredentials' : false
- };
- } else if (url_parts[0].indexOf('turn') === 0) {
- iceServer = {
- 'url' : url,
- 'hasCredentials' : true,
- 'credential' : password,
- 'username' : username
- };
- }
- return iceServer;
- };
-
- createIceServers = function (urls, username, password) {
- var iceServers = [];
- for (var i = 0; i < urls.length; ++i) {
- iceServers.push(createIceServer(urls[i], username, password));
- }
- return iceServers;
- };
-
- RTCSessionDescription = function (info) {
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- return AdapterJS.WebRTCPlugin.plugin.
- ConstructSessionDescription(info.type, info.sdp);
- };
-
- RTCPeerConnection = function (servers, constraints) {
- var iceServers = null;
- if (servers) {
- iceServers = servers.iceServers;
- for (var i = 0; i < iceServers.length; i++) {
- if (iceServers[i].urls && !iceServers[i].url) {
- iceServers[i].url = iceServers[i].urls;
- }
- iceServers[i].hasCredentials = AdapterJS.
- isDefined(iceServers[i].username) &&
- AdapterJS.isDefined(iceServers[i].credential);
- }
- }
- var mandatory = (constraints && constraints.mandatory) ?
- constraints.mandatory : null;
- var optional = (constraints && constraints.optional) ?
- constraints.optional : null;
-
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- return AdapterJS.WebRTCPlugin.plugin.
- PeerConnection(AdapterJS.WebRTCPlugin.pageId,
- iceServers, mandatory, optional);
- };
-
- MediaStreamTrack = {};
- MediaStreamTrack.getSources = function (callback) {
- AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
- AdapterJS.WebRTCPlugin.plugin.GetSources(callback);
- });
- };
-
- window.getUserMedia = function (constraints, successCallback, failureCallback) {
- constraints.audio = constraints.audio || false;
- constraints.video = constraints.video || false;
-
- AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
- AdapterJS.WebRTCPlugin.plugin.
- getUserMedia(constraints, successCallback, failureCallback);
- });
- };
- window.navigator.getUserMedia = window.getUserMedia;
-
- attachMediaStream = function (element, stream) {
- if (!element || !element.parentNode) {
- return;
- }
-
- var streamId
- if (stream === null) {
- streamId = '';
- }
- else {
- stream.enableSoundTracks(true);
- 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 + '" ';
- }
-
- temp.innerHTML = '';
- while (temp.firstChild) {
- frag.appendChild(temp.firstChild);
- }
-
- 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?
- }
-
- element.parentNode.insertBefore(frag, element);
- frag = document.getElementById(elementId);
- frag.width = width;
- frag.height = height;
- element.parentNode.removeChild(element);
- } else {
- 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;
- }
- };
-
- reattachMediaStream = function (to, from) {
- var stream = null;
- var children = from.children;
- for (var i = 0; i !== children.length; ++i) {
- if (children[i].name === 'streamId') {
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- stream = AdapterJS.WebRTCPlugin.plugin
- .getStreamWithId(AdapterJS.WebRTCPlugin.pageId, children[i].value);
- break;
- }
- }
- if (stream !== null) {
- return attachMediaStream(to, stream);
- } else {
- console.log('Could not find the stream associated with this element');
- }
- };
-
- RTCIceCandidate = function (candidate) {
- if (!candidate.sdpMid) {
- candidate.sdpMid = '';
- }
-
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- return AdapterJS.WebRTCPlugin.plugin.ConstructIceCandidate(
- candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate
- );
- };
-
- // inject plugin
- AdapterJS.addEvent(document, 'readystatechange', AdapterJS.WebRTCPlugin.injectPlugin);
- AdapterJS.WebRTCPlugin.injectPlugin();
- };
-
- // This function will be called if the plugin is needed (browser different
- // from Chrome or Firefox), but the plugin is not installed.
- AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb = AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb ||
- function() {
- AdapterJS.addEvent(document,
- 'readystatechange',
- AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv);
- AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv();
- };
-
- AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv = function () {
- if (AdapterJS.options.hidePluginInstallPrompt) {
- return;
- }
-
- var downloadLink = AdapterJS.WebRTCPlugin.pluginInfo.downloadLink;
- if(downloadLink) { // if download link
- var popupString;
- if (AdapterJS.WebRTCPlugin.pluginInfo.portalLink) { // is portal link
- popupString = 'This website requires you to install the ' +
- ' ' + AdapterJS.WebRTCPlugin.pluginInfo.companyName +
- ' WebRTC Plugin' +
- ' to work on this browser.';
- } else { // no portal link, just print a generic explanation
- popupString = AdapterJS.TEXT.PLUGIN.REQUIRE_INSTALLATION;
- }
-
- AdapterJS.renderNotificationBar(popupString, AdapterJS.TEXT.PLUGIN.BUTTON, downloadLink);
- } else { // no download link, just print a generic explanation
- AdapterJS.renderNotificationBar(AdapterJS.TEXT.PLUGIN.NOT_SUPPORTED);
- }
- };
-
- // Try to detect the plugin and act accordingly
- AdapterJS.WebRTCPlugin.isPluginInstalled(
- AdapterJS.WebRTCPlugin.pluginInfo.prefix,
- AdapterJS.WebRTCPlugin.pluginInfo.plugName,
- 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, '*');
- };
- }
-})();
-},{}],13:[function(require,module,exports){
-/* global Strophe, APP, $, config, interfaceConfig, toastr */
-var UI = {};
-
-var VideoLayout = require("./videolayout/VideoLayout.js");
-var AudioLevels = require("./audio_levels/AudioLevels.js");
-var Prezi = require("./prezi/Prezi.js");
-var Etherpad = require("./etherpad/Etherpad.js");
-var Chat = require("./side_pannels/chat/Chat.js");
-var Toolbar = require("./toolbars/Toolbar");
-var ToolbarToggler = require("./toolbars/ToolbarToggler");
-var BottomToolbar = require("./toolbars/BottomToolbar");
-var ContactList = require("./side_pannels/contactlist/ContactList");
-var Avatar = require("./avatar/Avatar");
-var EventEmitter = require("events");
-var SettingsMenu = require("./side_pannels/settings/SettingsMenu");
-var Settings = require("./../settings/Settings");
-var PanelToggler = require("./side_pannels/SidePanelToggler");
-var RoomNameGenerator = require("./welcome_page/RoomnameGenerator");
-UI.messageHandler = require("./util/MessageHandler");
-var messageHandler = UI.messageHandler;
-var Authentication = require("./authentication/Authentication");
-var UIUtil = require("./util/UIUtil");
-var NicknameHandler = require("./util/NicknameHandler");
-var JitsiPopover = require("./util/JitsiPopover");
-var CQEvents = require("../../service/connectionquality/CQEvents");
-var DesktopSharingEventTypes
- = require("../../service/desktopsharing/DesktopSharingEventTypes");
-var RTCEvents = require("../../service/RTC/RTCEvents");
-var RTCBrowserType = require("../RTC/RTCBrowserType");
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
-var XMPPEvents = require("../../service/xmpp/XMPPEvents");
-var UIEvents = require("../../service/UI/UIEvents");
-var MemberEvents = require("../../service/members/Events");
-
-var eventEmitter = new EventEmitter();
-var roomName = null;
-
-
-function promptDisplayName() {
- var message = '
",
- skin: "black"});
-
- this.emptyIcon = this.connectionIndicatorContainer.appendChild(
- createIcon(["connection", "connection_empty"]));
- this.fullIcon = this.connectionIndicatorContainer.appendChild(
- createIcon(["connection", "connection_full"]));
-};
-
-/**
- * Removes the indicator
- */
-ConnectionIndicator.prototype.remove = function() {
- if (this.connectionIndicatorContainer.parentNode) {
- this.connectionIndicatorContainer.parentNode.removeChild(
- this.connectionIndicatorContainer);
- }
- this.popover.forceHide();
-};
-
-/**
- * Updates the data of the indicator
- * @param percent the percent of connection quality
- * @param object the statistics data.
- */
-ConnectionIndicator.prototype.updateConnectionQuality =
- function (percent, object) {
-
- if (percent === null) {
- this.connectionIndicatorContainer.style.display = "none";
- this.popover.forceHide();
- return;
- } else {
- if(this.connectionIndicatorContainer.style.display == "none") {
- this.connectionIndicatorContainer.style.display = "block";
- this.videoContainer.updateIconPositions();
- }
- }
- this.bandwidth = object.bandwidth;
- this.bitrate = object.bitrate;
- this.packetLoss = object.packetLoss;
- this.transport = object.transport;
- if (object.resolution) {
- this.resolution = object.resolution;
- }
- for (var quality in ConnectionIndicator.connectionQualityValues) {
- if (percent >= quality) {
- this.fullIcon.style.width =
- ConnectionIndicator.connectionQualityValues[quality];
- }
- }
- this.updatePopoverData();
-};
-
-/**
- * Updates the resolution
- * @param resolution the new resolution
- */
-ConnectionIndicator.prototype.updateResolution = function (resolution) {
- this.resolution = resolution;
- this.updatePopoverData();
-};
-
-/**
- * Updates the content of the popover
- */
-ConnectionIndicator.prototype.updatePopoverData = function () {
- this.popover.updateContent(
- "
" + this.generateText() + "
");
- APP.translation.translateElement($(".connection_info"));
-};
-
-/**
- * Hides the popover
- */
-ConnectionIndicator.prototype.hide = function () {
- this.popover.forceHide();
-};
-
-/**
- * Hides the indicator
- */
-ConnectionIndicator.prototype.hideIndicator = function () {
- this.connectionIndicatorContainer.style.display = "none";
- if(this.popover)
- this.popover.forceHide();
-};
-
-module.exports = ConnectionIndicator;
-},{"../util/JitsiPopover":32}],37:[function(require,module,exports){
-/* global $, APP, Strophe, interfaceConfig */
-var Avatar = require("../avatar/Avatar");
-var RTCBrowserType = require("../../RTC/RTCBrowserType");
-var UIUtil = require("../util/UIUtil");
-var UIEvents = require("../../../service/UI/UIEvents");
-var xmpp = require("../../xmpp/xmpp");
-var ToolbarToggler = require("../toolbars/ToolbarToggler");
-
-// FIXME: With Temasys we have to re-select everytime
-//var video = $('#largeVideo');
-
-var currentVideoWidth = null;
-var currentVideoHeight = null;
-// By default we use camera
-var getVideoSize = getCameraVideoSize;
-var getVideoPosition = getCameraVideoPosition;
-/**
- * The small video instance that is displayed in the large video
- * @type {SmallVideo}
- */
-var currentSmallVideo = null;
-/**
- * Indicates whether the large video is enabled.
- * @type {boolean}
- */
-var isEnabled = true;
-/**
- * Current large video state.
- * Possible values - video, prezi or etherpad.
- * @type {string}
- */
-var state = "video";
-
-/**
- * Returns the html element associated with the passed state of large video
- * @param state the state.
- * @returns {JQuery|*|jQuery|HTMLElement} the container.
- */
-function getContainerByState(state)
-{
- var selector = null;
- switch (state)
- {
- case "video":
- selector = "#largeVideo";
- break;
- case "etherpad":
- selector = "#etherpad>iframe";
- break;
- case "prezi":
- selector = "#presentation>iframe";
- break;
- }
- return (selector !== null)? $(selector) : null;
-}
-
-/**
- * Sets the size and position of the given video element.
- *
- * @param video the video element to position
- * @param width the desired video width
- * @param height the desired video height
- * @param horizontalIndent the left and right indent
- * @param verticalIndent the top and bottom indent
- */
-function positionVideo(video,
- width,
- height,
- horizontalIndent,
- verticalIndent,
- animate) {
- if (animate) {
- video.animate({
- width: width,
- height: height,
- top: verticalIndent,
- bottom: verticalIndent,
- left: horizontalIndent,
- right: horizontalIndent
- },
- {
- queue: false,
- duration: 500
- });
- } else {
- video.width(width);
- video.height(height);
- video.css({ top: verticalIndent + 'px',
- bottom: verticalIndent + 'px',
- left: horizontalIndent + 'px',
- right: horizontalIndent + 'px'});
- }
-
-}
-
-/**
- * Returns an array of the video dimensions, so that it keeps it's aspect
- * ratio and fits available area with it's larger dimension. This method
- * ensures that whole video will be visible and can leave empty areas.
- *
- * @return an array with 2 elements, the video width and the video height
- */
-function getDesktopVideoSize(videoWidth,
- videoHeight,
- videoSpaceWidth,
- videoSpaceHeight) {
- if (!videoWidth)
- videoWidth = currentVideoWidth;
- if (!videoHeight)
- videoHeight = currentVideoHeight;
-
- var aspectRatio = videoWidth / videoHeight;
-
- var availableWidth = Math.max(videoWidth, videoSpaceWidth);
- var availableHeight = Math.max(videoHeight, videoSpaceHeight);
-
- videoSpaceHeight -= $('#remoteVideos').outerHeight();
-
- if (availableWidth / aspectRatio >= videoSpaceHeight)
- {
- availableHeight = videoSpaceHeight;
- availableWidth = availableHeight * aspectRatio;
- }
-
- if (availableHeight * aspectRatio >= videoSpaceWidth)
- {
- availableWidth = videoSpaceWidth;
- availableHeight = availableWidth / aspectRatio;
- }
-
- return [availableWidth, availableHeight];
-}
-
-
-/**
- * Returns an array of the video horizontal and vertical indents,
- * so that if fits its parent.
- *
- * @return an array with 2 elements, the horizontal indent and the vertical
- * indent
- */
-function getCameraVideoPosition(videoWidth,
- videoHeight,
- videoSpaceWidth,
- videoSpaceHeight) {
- // Parent height isn't completely calculated when we position the video in
- // full screen mode and this is why we use the screen height in this case.
- // Need to think it further at some point and implement it properly.
- var isFullScreen = document.fullScreen ||
- document.mozFullScreen ||
- document.webkitIsFullScreen;
- if (isFullScreen)
- videoSpaceHeight = window.innerHeight;
-
- var horizontalIndent = (videoSpaceWidth - videoWidth) / 2;
- var verticalIndent = (videoSpaceHeight - videoHeight) / 2;
-
- return [horizontalIndent, verticalIndent];
-}
-
-/**
- * Returns an array of the video horizontal and vertical indents.
- * Centers horizontally and top aligns vertically.
- *
- * @return an array with 2 elements, the horizontal indent and the vertical
- * indent
- */
-function getDesktopVideoPosition(videoWidth,
- videoHeight,
- videoSpaceWidth,
- videoSpaceHeight) {
-
- var horizontalIndent = (videoSpaceWidth - videoWidth) / 2;
-
- var verticalIndent = 0;// Top aligned
-
- return [horizontalIndent, verticalIndent];
-}
-
-
-/**
- * Returns an array of the video dimensions, so that it covers the screen.
- * It leaves no empty areas, but some parts of the video might not be visible.
- *
- * @return an array with 2 elements, the video width and the video height
- */
-function getCameraVideoSize(videoWidth,
- videoHeight,
- videoSpaceWidth,
- videoSpaceHeight) {
- if (!videoWidth)
- videoWidth = currentVideoWidth;
- if (!videoHeight)
- videoHeight = currentVideoHeight;
-
- var aspectRatio = videoWidth / videoHeight;
-
- var availableWidth = Math.max(videoWidth, videoSpaceWidth);
- var availableHeight = Math.max(videoHeight, videoSpaceHeight);
-
- if (availableWidth / aspectRatio < videoSpaceHeight) {
- availableHeight = videoSpaceHeight;
- availableWidth = availableHeight * aspectRatio;
- }
-
- if (availableHeight * aspectRatio < videoSpaceWidth) {
- availableWidth = videoSpaceWidth;
- availableHeight = availableWidth / aspectRatio;
- }
-
- return [availableWidth, availableHeight];
-}
-
-/**
- * Updates the src of the active speaker avatar
- * @param jid of the current active speaker
- */
-function updateActiveSpeakerAvatarSrc() {
- var avatar = $("#activeSpeakerAvatar")[0];
- var jid = currentSmallVideo.peerJid;
- var url = Avatar.getActiveSpeakerUrl(jid);
- if (avatar.src === url)
- return;
- if (jid) {
- avatar.src = url;
- currentSmallVideo.showAvatar();
- }
-}
-
-/**
- * Change the video source of the large video.
- * @param isVisible
- */
-function changeVideo(isVisible) {
-
- if (!currentSmallVideo) {
- console.error("Unable to change large video - no 'currentSmallVideo'");
- return;
- }
-
- updateActiveSpeakerAvatarSrc();
-
- APP.RTC.setVideoSrc($('#largeVideo')[0], currentSmallVideo.getSrc());
-
- var videoTransform = document.getElementById('largeVideo')
- .style.webkitTransform;
-
- var flipX = currentSmallVideo.flipX;
-
- if (flipX && videoTransform !== 'scaleX(-1)') {
- document.getElementById('largeVideo').style.webkitTransform =
- "scaleX(-1)";
- } else if (!flipX && videoTransform === 'scaleX(-1)') {
- document.getElementById('largeVideo').style.webkitTransform =
- "none";
- }
-
- var isDesktop = currentSmallVideo.getVideoType() === 'screen';
- // Change the way we'll be measuring and positioning large video
-
- getVideoSize = isDesktop ? getDesktopVideoSize : getCameraVideoSize;
- getVideoPosition = isDesktop ? getDesktopVideoPosition :
- getCameraVideoPosition;
-
-
- // Only if the large video is currently visible.
- if (isVisible) {
- LargeVideo.VideoLayout.largeVideoUpdated(currentSmallVideo);
-
- $('#largeVideo').fadeIn(300);
- }
-}
-
-/**
- * Creates the html elements for the large video.
- */
-function createLargeVideoHTML()
-{
- var html = '