您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. var UI = {};
  2. var VideoLayout = require("./videolayout/VideoLayout.js");
  3. var AudioLevels = require("./audio_levels/AudioLevels.js");
  4. var Prezi = require("./prezi/Prezi.js");
  5. var Etherpad = require("./etherpad/Etherpad.js");
  6. var Chat = require("./side_pannels/chat/Chat.js");
  7. var Toolbar = require("./toolbars/Toolbar");
  8. var ToolbarToggler = require("./toolbars/ToolbarToggler");
  9. var BottomToolbar = require("./toolbars/BottomToolbar");
  10. var ContactList = require("./side_pannels/contactlist/ContactList");
  11. var Avatar = require("./avatar/Avatar");
  12. var EventEmitter = require("events");
  13. var SettingsMenu = require("./side_pannels/settings/SettingsMenu");
  14. var Settings = require("./side_pannels/settings/Settings");
  15. var PanelToggler = require("./side_pannels/SidePanelToggler");
  16. var RoomNameGenerator = require("./welcome_page/RoomnameGenerator");
  17. UI.messageHandler = require("./util/MessageHandler");
  18. var messageHandler = UI.messageHandler;
  19. var Authentication = require("./authentication/Authentication");
  20. var UIUtil = require("./util/UIUtil");
  21. var NicknameHandler = require("./util/NicknameHandler");
  22. var eventEmitter = new EventEmitter();
  23. var roomName = null;
  24. function setupPrezi()
  25. {
  26. $("#reloadPresentationLink").click(function()
  27. {
  28. Prezi.reloadPresentation();
  29. });
  30. }
  31. function setupChat()
  32. {
  33. Chat.init();
  34. $("#toggle_smileys").click(function() {
  35. Chat.toggleSmileys();
  36. });
  37. }
  38. function setupToolbars() {
  39. Toolbar.init(UI);
  40. Toolbar.setupButtonsFromConfig();
  41. BottomToolbar.init();
  42. }
  43. function streamHandler(stream) {
  44. switch (stream.type)
  45. {
  46. case "audio":
  47. VideoLayout.changeLocalAudio(stream);
  48. break;
  49. case "video":
  50. VideoLayout.changeLocalVideo(stream);
  51. break;
  52. case "stream":
  53. VideoLayout.changeLocalStream(stream);
  54. break;
  55. }
  56. }
  57. function onDisposeConference(unload) {
  58. Toolbar.showAuthenticateButton(false);
  59. };
  60. function onDisplayNameChanged(jid, displayName) {
  61. ContactList.onDisplayNameChange(jid, displayName);
  62. SettingsMenu.onDisplayNameChange(jid, displayName);
  63. VideoLayout.onDisplayNameChanged(jid, displayName);
  64. }
  65. function registerListeners() {
  66. RTC.addStreamListener(streamHandler, StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
  67. RTC.addStreamListener(streamHandler, StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED);
  68. RTC.addStreamListener(function (stream) {
  69. VideoLayout.onRemoteStreamAdded(stream);
  70. }, StreamEventTypes.EVENT_TYPE_REMOTE_CREATED);
  71. RTC.addListener(RTCEvents.LASTN_CHANGED, onLastNChanged);
  72. RTC.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (resourceJid) {
  73. VideoLayout.onDominantSpeakerChanged(resourceJid);
  74. });
  75. RTC.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED,
  76. function (lastNEndpoints, endpointsEnteringLastN, stream) {
  77. VideoLayout.onLastNEndpointsChanged(lastNEndpoints,
  78. endpointsEnteringLastN, stream);
  79. });
  80. RTC.addListener(RTCEvents.SIMULCAST_LAYER_CHANGED,
  81. function (endpointSimulcastLayers) {
  82. VideoLayout.onSimulcastLayersChanged(endpointSimulcastLayers);
  83. });
  84. RTC.addListener(RTCEvents.SIMULCAST_LAYER_CHANGING,
  85. function (endpointSimulcastLayers) {
  86. VideoLayout.onSimulcastLayersChanging(endpointSimulcastLayers);
  87. });
  88. VideoLayout.init();
  89. statistics.addAudioLevelListener(function(jid, audioLevel)
  90. {
  91. var resourceJid;
  92. if(jid === statistics.LOCAL_JID)
  93. {
  94. resourceJid = AudioLevels.LOCAL_LEVEL;
  95. if(RTC.localAudio.isMuted())
  96. {
  97. audioLevel = 0;
  98. }
  99. }
  100. else
  101. {
  102. resourceJid = Strophe.getResourceFromJid(jid);
  103. }
  104. AudioLevels.updateAudioLevel(resourceJid, audioLevel,
  105. UI.getLargeVideoState().userResourceJid);
  106. });
  107. desktopsharing.addListener(function () {
  108. ToolbarToggler.showDesktopSharingButton();
  109. }, DesktopSharingEventTypes.INIT);
  110. desktopsharing.addListener(
  111. Toolbar.changeDesktopSharingButtonState,
  112. DesktopSharingEventTypes.SWITCHING_DONE);
  113. xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference);
  114. xmpp.addListener(XMPPEvents.KICKED, function () {
  115. messageHandler.openMessageDialog("Session Terminated",
  116. "Ouch! You have been kicked out of the meet!");
  117. });
  118. xmpp.addListener(XMPPEvents.BRIDGE_DOWN, function () {
  119. messageHandler.showError("Error",
  120. "Jitsi Videobridge is currently unavailable. Please try again later!");
  121. });
  122. xmpp.addListener(XMPPEvents.USER_ID_CHANGED, Avatar.setUserAvatar);
  123. xmpp.addListener(XMPPEvents.CHANGED_STREAMS, function (jid, changedStreams) {
  124. for(stream in changedStreams)
  125. {
  126. // might need to update the direction if participant just went from sendrecv to recvonly
  127. if (stream.type === 'video' || stream.type === 'screen') {
  128. var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>video');
  129. switch (stream.direction) {
  130. case 'sendrecv':
  131. el.show();
  132. break;
  133. case 'recvonly':
  134. el.hide();
  135. // FIXME: Check if we have to change large video
  136. //VideoLayout.updateLargeVideo(el);
  137. break;
  138. }
  139. }
  140. }
  141. });
  142. xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, onDisplayNameChanged);
  143. xmpp.addListener(XMPPEvents.MUC_JOINED, onMucJoined);
  144. xmpp.addListener(XMPPEvents.LOCALROLE_CHANGED, onLocalRoleChange);
  145. xmpp.addListener(XMPPEvents.MUC_ENTER, onMucEntered);
  146. xmpp.addListener(XMPPEvents.MUC_ROLE_CHANGED, onMucRoleChanged);
  147. xmpp.addListener(XMPPEvents.PRESENCE_STATUS, onMucPresenceStatus);
  148. xmpp.addListener(XMPPEvents.SUBJECT_CHANGED, chatSetSubject);
  149. xmpp.addListener(XMPPEvents.MESSAGE_RECEIVED, updateChatConversation);
  150. xmpp.addListener(XMPPEvents.MUC_LEFT, onMucLeft);
  151. xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, onPasswordReqiured);
  152. xmpp.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, chatAddError);
  153. xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad);
  154. connectionquality.addListener(CQEvents.LOCALSTATS_UPDATED,
  155. VideoLayout.updateLocalConnectionStats);
  156. connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED,
  157. VideoLayout.updateConnectionStats);
  158. connectionquality.addListener(CQEvents.STOP,
  159. VideoLayout.onStatsStop);
  160. xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED, onAuthenticationRequired);
  161. }
  162. function bindEvents()
  163. {
  164. /**
  165. * Resizes and repositions videos in full screen mode.
  166. */
  167. $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
  168. function () {
  169. VideoLayout.resizeLargeVideoContainer();
  170. VideoLayout.positionLarge();
  171. }
  172. );
  173. $(window).resize(function () {
  174. VideoLayout.resizeLargeVideoContainer();
  175. VideoLayout.positionLarge();
  176. });
  177. }
  178. UI.start = function () {
  179. document.title = interfaceConfig.APP_NAME;
  180. if(config.enableWelcomePage && window.location.pathname == "/" &&
  181. (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
  182. {
  183. $("#videoconference_page").hide();
  184. var setupWelcomePage = require("./welcome_page/WelcomePage");
  185. setupWelcomePage();
  186. return;
  187. }
  188. if (interfaceConfig.SHOW_JITSI_WATERMARK) {
  189. var leftWatermarkDiv
  190. = $("#largeVideoContainer div[class='watermark leftwatermark']");
  191. leftWatermarkDiv.css({display: 'block'});
  192. leftWatermarkDiv.parent().get(0).href
  193. = interfaceConfig.JITSI_WATERMARK_LINK;
  194. }
  195. if (interfaceConfig.SHOW_BRAND_WATERMARK) {
  196. var rightWatermarkDiv
  197. = $("#largeVideoContainer div[class='watermark rightwatermark']");
  198. rightWatermarkDiv.css({display: 'block'});
  199. rightWatermarkDiv.parent().get(0).href
  200. = interfaceConfig.BRAND_WATERMARK_LINK;
  201. rightWatermarkDiv.get(0).style.backgroundImage
  202. = "url(images/rightwatermark.png)";
  203. }
  204. if (interfaceConfig.SHOW_POWERED_BY) {
  205. $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'});
  206. }
  207. $("#welcome_page").hide();
  208. VideoLayout.resizeLargeVideoContainer();
  209. $("#videospace").mousemove(function () {
  210. return ToolbarToggler.showToolbar();
  211. });
  212. // Set the defaults for prompt dialogs.
  213. jQuery.prompt.setDefaults({persistent: false});
  214. NicknameHandler.init(eventEmitter);
  215. registerListeners();
  216. bindEvents();
  217. setupPrezi();
  218. setupToolbars();
  219. setupChat();
  220. document.title = interfaceConfig.APP_NAME;
  221. $("#downloadlog").click(function (event) {
  222. dump(event.target);
  223. });
  224. if(config.enableWelcomePage && window.location.pathname == "/" &&
  225. (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
  226. {
  227. $("#videoconference_page").hide();
  228. var setupWelcomePage = require("./welcome_page/WelcomePage");
  229. setupWelcomePage();
  230. return;
  231. }
  232. $("#welcome_page").hide();
  233. document.getElementById('largeVideo').volume = 0;
  234. if (!$('#settings').is(':visible')) {
  235. console.log('init');
  236. init();
  237. } else {
  238. loginInfo.onsubmit = function (e) {
  239. if (e.preventDefault) e.preventDefault();
  240. $('#settings').hide();
  241. init();
  242. };
  243. }
  244. toastr.options = {
  245. "closeButton": true,
  246. "debug": false,
  247. "positionClass": "notification-bottom-right",
  248. "onclick": null,
  249. "showDuration": "300",
  250. "hideDuration": "1000",
  251. "timeOut": "2000",
  252. "extendedTimeOut": "1000",
  253. "showEasing": "swing",
  254. "hideEasing": "linear",
  255. "showMethod": "fadeIn",
  256. "hideMethod": "fadeOut",
  257. "reposition": function() {
  258. if(PanelToggler.isVisible()) {
  259. $("#toast-container").addClass("notification-bottom-right-center");
  260. } else {
  261. $("#toast-container").removeClass("notification-bottom-right-center");
  262. }
  263. },
  264. "newestOnTop": false
  265. };
  266. $('#settingsmenu>input').keyup(function(event){
  267. if(event.keyCode === 13) {//enter
  268. SettingsMenu.update();
  269. }
  270. });
  271. $("#updateSettings").click(function () {
  272. SettingsMenu.update();
  273. });
  274. };
  275. UI.toggleSmileys = function () {
  276. Chat.toggleSmileys();
  277. };
  278. function chatAddError(errorMessage, originalText)
  279. {
  280. return Chat.chatAddError(errorMessage, originalText);
  281. };
  282. function chatSetSubject(text)
  283. {
  284. return Chat.chatSetSubject(text);
  285. };
  286. function updateChatConversation(from, displayName, message) {
  287. return Chat.updateChatConversation(from, displayName, message);
  288. };
  289. function onMucJoined(jid, info) {
  290. Toolbar.updateRoomUrl(window.location.href);
  291. document.getElementById('localNick').appendChild(
  292. document.createTextNode(Strophe.getResourceFromJid(jid) + ' (me)')
  293. );
  294. var settings = Settings.getSettings();
  295. // Add myself to the contact list.
  296. ContactList.addContact(jid, settings.email || settings.uid);
  297. // Once we've joined the muc show the toolbar
  298. ToolbarToggler.showToolbar();
  299. // Show authenticate button if needed
  300. Toolbar.showAuthenticateButton(
  301. xmpp.isExternalAuthEnabled() && !xmpp.isModerator());
  302. var displayName = !config.displayJids
  303. ? info.displayName : Strophe.getResourceFromJid(jid);
  304. if (displayName)
  305. onDisplayNameChanged('localVideoContainer', displayName + ' (me)');
  306. }
  307. function initEtherpad(name) {
  308. Etherpad.init(name);
  309. };
  310. function onMucLeft(jid) {
  311. console.log('left.muc', jid);
  312. var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
  313. '>.displayname').html();
  314. messageHandler.notify(displayName || 'Somebody',
  315. 'disconnected',
  316. 'disconnected');
  317. // Need to call this with a slight delay, otherwise the element couldn't be
  318. // found for some reason.
  319. // XXX(gp) it works fine without the timeout for me (with Chrome 38).
  320. window.setTimeout(function () {
  321. var container = document.getElementById(
  322. 'participant_' + Strophe.getResourceFromJid(jid));
  323. if (container) {
  324. ContactList.removeContact(jid);
  325. VideoLayout.removeConnectionIndicator(jid);
  326. // hide here, wait for video to close before removing
  327. $(container).hide();
  328. VideoLayout.resizeThumbnails();
  329. }
  330. }, 10);
  331. VideoLayout.participantLeft(jid);
  332. };
  333. function onLocalRoleChange(jid, info, pres, isModerator, isExternalAuthEnabled)
  334. {
  335. console.info("My role changed, new role: " + info.role);
  336. onModeratorStatusChanged(isModerator);
  337. VideoLayout.showModeratorIndicator();
  338. Toolbar.showAuthenticateButton(
  339. isExternalAuthEnabled && !isModerator);
  340. if (isModerator) {
  341. Authentication.closeAuthenticationWindow();
  342. messageHandler.notify(
  343. 'Me', 'connected', 'Moderator rights granted !');
  344. }
  345. }
  346. function onModeratorStatusChanged(isModerator) {
  347. Toolbar.showSipCallButton(isModerator);
  348. Toolbar.showRecordingButton(
  349. isModerator); //&&
  350. // FIXME:
  351. // Recording visible if
  352. // there are at least 2(+ 1 focus) participants
  353. //Object.keys(connection.emuc.members).length >= 3);
  354. if (isModerator && config.etherpad_base) {
  355. Etherpad.init();
  356. }
  357. };
  358. function onPasswordReqiured(callback) {
  359. // password is required
  360. Toolbar.lockLockButton();
  361. messageHandler.openTwoButtonDialog(null,
  362. '<h2>Password required</h2>' +
  363. '<input id="lockKey" type="text" placeholder="password" autofocus>',
  364. true,
  365. "Ok",
  366. function (e, v, m, f) {},
  367. function (event) {
  368. document.getElementById('lockKey').focus();
  369. },
  370. function (e, v, m, f) {
  371. if (v) {
  372. var lockKey = document.getElementById('lockKey');
  373. if (lockKey.value !== null) {
  374. Toolbar.setSharedKey(lockKey.value);
  375. callback(lockKey.value);
  376. }
  377. }
  378. }
  379. );
  380. }
  381. function onMucEntered(jid, id, displayName) {
  382. messageHandler.notify(displayName || 'Somebody',
  383. 'connected',
  384. 'connected');
  385. // Add Peer's container
  386. VideoLayout.ensurePeerContainerExists(jid,id);
  387. }
  388. function onMucPresenceStatus( jid, info) {
  389. VideoLayout.setPresenceStatus(
  390. 'participant_' + Strophe.getResourceFromJid(jid), info.status);
  391. }
  392. function onMucRoleChanged(role, displayName) {
  393. VideoLayout.showModeratorIndicator();
  394. if (role === 'moderator') {
  395. var displayName = displayName;
  396. if (!displayName) {
  397. displayName = 'Somebody';
  398. }
  399. messageHandler.notify(
  400. displayName,
  401. 'connected',
  402. 'Moderator rights granted to ' + displayName + '!');
  403. }
  404. }
  405. function onAuthenticationRequired(intervalCallback) {
  406. Authentication.openAuthenticationDialog(
  407. roomName, intervalCallback, function () {
  408. Toolbar.authenticateClicked();
  409. });
  410. };
  411. function onLastNChanged(oldValue, newValue) {
  412. if (config.muteLocalVideoIfNotInLastN) {
  413. setVideoMute(!newValue, { 'byUser': false });
  414. }
  415. }
  416. UI.getSettings = function () {
  417. return Settings.getSettings();
  418. };
  419. UI.toggleFilmStrip = function () {
  420. return BottomToolbar.toggleFilmStrip();
  421. };
  422. UI.toggleChat = function () {
  423. return BottomToolbar.toggleChat();
  424. };
  425. UI.toggleContactList = function () {
  426. return BottomToolbar.toggleContactList();
  427. };
  428. UI.setRecordingButtonState = function (state) {
  429. Toolbar.setRecordingButtonState(state);
  430. };
  431. UI.inputDisplayNameHandler = function (value) {
  432. VideoLayout.inputDisplayNameHandler(value);
  433. };
  434. UI.getLargeVideoState = function()
  435. {
  436. return VideoLayout.getLargeVideoState();
  437. };
  438. UI.showLocalAudioIndicator = function (mute) {
  439. VideoLayout.showLocalAudioIndicator(mute);
  440. };
  441. UI.generateRoomName = function() {
  442. if(roomName)
  443. return roomName;
  444. var roomnode = null;
  445. var path = window.location.pathname;
  446. // determinde the room node from the url
  447. // TODO: just the roomnode or the whole bare jid?
  448. if (config.getroomnode && typeof config.getroomnode === 'function') {
  449. // custom function might be responsible for doing the pushstate
  450. roomnode = config.getroomnode(path);
  451. } else {
  452. /* fall back to default strategy
  453. * this is making assumptions about how the URL->room mapping happens.
  454. * It currently assumes deployment at root, with a rewrite like the
  455. * following one (for nginx):
  456. location ~ ^/([a-zA-Z0-9]+)$ {
  457. rewrite ^/(.*)$ / break;
  458. }
  459. */
  460. if (path.length > 1) {
  461. roomnode = path.substr(1).toLowerCase();
  462. } else {
  463. var word = RoomNameGenerator.generateRoomWithoutSeparator();
  464. roomnode = word.toLowerCase();
  465. window.history.pushState('VideoChat',
  466. 'Room: ' + word, window.location.pathname + word);
  467. }
  468. }
  469. roomName = roomnode + '@' + config.hosts.muc;
  470. return roomName;
  471. };
  472. UI.connectionIndicatorShowMore = function(id)
  473. {
  474. return VideoLayout.connectionIndicators[id].showMore();
  475. };
  476. UI.showToolbar = function () {
  477. return ToolbarToggler.showToolbar();
  478. };
  479. UI.dockToolbar = function (isDock) {
  480. return ToolbarToggler.dockToolbar(isDock);
  481. };
  482. UI.getCreadentials = function () {
  483. return {
  484. bosh: document.getElementById('boshURL').value,
  485. password: document.getElementById('password').value,
  486. jid: document.getElementById('jid').value
  487. };
  488. };
  489. UI.disableConnect = function () {
  490. document.getElementById('connect').disabled = true;
  491. };
  492. UI.showLoginPopup = function(callback)
  493. {
  494. console.log('password is required');
  495. UI.messageHandler.openTwoButtonDialog(null,
  496. '<h2>Password required</h2>' +
  497. '<input id="passwordrequired.username" type="text" placeholder="user@domain.net" autofocus>' +
  498. '<input id="passwordrequired.password" type="password" placeholder="user password">',
  499. true,
  500. "Ok",
  501. function (e, v, m, f) {
  502. if (v) {
  503. var username = document.getElementById('passwordrequired.username');
  504. var password = document.getElementById('passwordrequired.password');
  505. if (username.value !== null && password.value != null) {
  506. callback(username.value, password.value);
  507. }
  508. }
  509. },
  510. function (event) {
  511. document.getElementById('passwordrequired.username').focus();
  512. }
  513. );
  514. }
  515. UI.checkForNicknameAndJoin = function () {
  516. Authentication.closeAuthenticationDialog();
  517. Authentication.stopInterval();
  518. var nick = null;
  519. if (config.useNicks) {
  520. nick = window.prompt('Your nickname (optional)');
  521. }
  522. xmpp.joinRoom(roomName, config.useNicks, nick);
  523. }
  524. function dump(elem, filename) {
  525. elem = elem.parentNode;
  526. elem.download = filename || 'meetlog.json';
  527. elem.href = 'data:application/json;charset=utf-8,\n';
  528. var data = xmpp.populateData();
  529. var metadata = {};
  530. metadata.time = new Date();
  531. metadata.url = window.location.href;
  532. metadata.ua = navigator.userAgent;
  533. var log = xmpp.getLogger();
  534. if (log) {
  535. metadata.xmpp = log;
  536. }
  537. data.metadata = metadata;
  538. elem.href += encodeURIComponent(JSON.stringify(data, null, ' '));
  539. return false;
  540. }
  541. UI.getRoomName = function () {
  542. return roomName;
  543. }
  544. /**
  545. * Mutes/unmutes the local video.
  546. *
  547. * @param mute <tt>true</tt> to mute the local video; otherwise, <tt>false</tt>
  548. * @param options an object which specifies optional arguments such as the
  549. * <tt>boolean</tt> key <tt>byUser</tt> with default value <tt>true</tt> which
  550. * specifies whether the method was initiated in response to a user command (in
  551. * contrast to an automatic decision taken by the application logic)
  552. */
  553. function setVideoMute(mute, options) {
  554. xmpp.setVideoMute(
  555. mute,
  556. function (mute) {
  557. var video = $('#video');
  558. var communicativeClass = "icon-camera";
  559. var muteClass = "icon-camera icon-camera-disabled";
  560. if (mute) {
  561. video.removeClass(communicativeClass);
  562. video.addClass(muteClass);
  563. } else {
  564. video.removeClass(muteClass);
  565. video.addClass(communicativeClass);
  566. }
  567. },
  568. options);
  569. }
  570. /**
  571. * Mutes/unmutes the local video.
  572. */
  573. UI.toggleVideo = function () {
  574. UIUtil.buttonClick("#video", "icon-camera icon-camera-disabled");
  575. setVideoMute(!RTC.localVideo.isMuted());
  576. };
  577. /**
  578. * Mutes / unmutes audio for the local participant.
  579. */
  580. UI.toggleAudio = function() {
  581. UI.setAudioMuted(!RTC.localAudio.isMuted());
  582. };
  583. /**
  584. * Sets muted audio state for the local participant.
  585. */
  586. UI.setAudioMuted = function (mute) {
  587. if(!xmpp.setAudioMute(mute, function () {
  588. UI.showLocalAudioIndicator(mute);
  589. UIUtil.buttonClick("#mute", "icon-microphone icon-mic-disabled");
  590. }))
  591. {
  592. // We still click the button.
  593. UIUtil.buttonClick("#mute", "icon-microphone icon-mic-disabled");
  594. return;
  595. }
  596. }
  597. UI.addListener = function (type, listener) {
  598. eventEmitter.on(type, listener);
  599. }
  600. UI.clickOnVideo = function (videoNumber) {
  601. var remoteVideos = $(".videocontainer:not(#mixedstream)");
  602. if (remoteVideos.length > videoNumber) {
  603. remoteVideos[videoNumber].click();
  604. }
  605. }
  606. module.exports = UI;