// TODO(fancycode): Should load through AMD if possible. /* global SimpleWebRTC, OC, OCA: false */ var webrtc; var spreedMappingTable = []; var spreedPeerConnectionTable = []; (function(OCA, OC) { 'use strict'; OCA.SpreedMe = OCA.SpreedMe || {}; /** * @private */ function openEventSource() { // Connect to the messages endpoint and pull for new messages var messageEventSource = new OC.EventSource(OC.generateUrl('/apps/spreed/messages')); var previousUsersInRoom = []; Array.prototype.diff = function(a) { return this.filter(function(i) { return a.indexOf(i) < 0; }); }; messageEventSource.listen('usersInRoom', function(users) { var currentUsersInRoom = []; var webrtc = OCA.SpreedMe.webrtc; var currentUser = webrtc.connection.getSessionid(); users.forEach(function(user) { var sessionId = user['sessionId']; currentUsersInRoom.push(sessionId); spreedMappingTable[sessionId] = user['userId']; if (sessionId && currentUser !== sessionId) { var videoContainer = $(OCA.SpreedMe.videos.getContainerId(sessionId)); if (videoContainer.length === 0) { OCA.SpreedMe.videos.add(sessionId); } } }); var currentUsersNo = currentUsersInRoom.length; if(currentUsersNo === 0) { currentUsersNo = 1; } var appContentElement = $('#app-content'), participantsClass = 'participants-' + currentUsersNo; if (!appContentElement.hasClass(participantsClass) && !appContentElement.hasClass('screensharing')) { appContentElement.attr('class', '').addClass(participantsClass); if (currentUsersNo > 1) { appContentElement.addClass('incall'); } else { appContentElement.removeClass('incall'); } } //Send shared screen to new participants if (webrtc.getLocalScreen()) { var newUsers = currentUsersInRoom.diff(previousUsersInRoom); newUsers.forEach(function(user) { if (user !== currentUser) { var peer = webrtc.webrtc.createPeer({ id: user, type: 'screen', sharemyscreen: true, enableDataChannels: false, receiveMedia: { offerToReceiveAudio: 0, offerToReceiveVideo: 0 }, broadcaster: currentUser, }); webrtc.emit('createdPeer', peer); peer.start(); } }); } var disconnectedUsers = previousUsersInRoom.diff(currentUsersInRoom); disconnectedUsers.forEach(function(user) { console.log('XXX Remove peer', user); OCA.SpreedMe.webrtc.removePeers(user); OCA.SpreedMe.speakers.remove(user, true); OCA.SpreedMe.videos.remove(user); }); previousUsersInRoom = currentUsersInRoom; }); messageEventSource.listen('message', function(message) { message = JSON.parse(message); var peers = self.webrtc.getPeers(message.from, message.roomType); var peer; if (message.type === 'offer') { if (peers.length) { peers.forEach(function(p) { if (p.sid === message.sid) { peer = p; } }); } if (!peer) { peer = self.webrtc.createPeer({ id: message.from, sid: message.sid, type: message.roomType, enableDataChannels: true, sharemyscreen: message.roomType === 'screen' && !message.broadcaster, broadcaster: message.roomType === 'screen' && !message.broadcaster ? self.connection.getSessionid() : null }); OCA.SpreedMe.webrtc.emit('createdPeer', peer); } peer.handleMessage(message); } else if (peers.length) { peers.forEach(function(peer) { if (message.sid) { if (peer.sid === message.sid) { peer.handleMessage(message); } } else { peer.handleMessage(message); } }); } }); messageEventSource.listen('__internal__', function(data) { if (data === 'close') { console.log('signaling connection closed - will reopen'); setTimeout(openEventSource, 0); } }); } function initWebRTC() { 'use strict'; openEventSource(); var nick = OC.getCurrentUser()['displayName']; //Check if there is some nick saved on local storage for guests if (!nick && OCA.SpreedMe.app.guestNick) { nick = OCA.SpreedMe.app.guestNick; } webrtc = new SimpleWebRTC({ localVideoEl: 'localVideo', remoteVideosEl: '', autoRequestMedia: true, debug: false, media: { audio: true, video: { width: { max: 1280 }, height: { max: 720 } } }, autoAdjustMic: false, audioFallback: true, detectSpeakingEvents: true, connection: OCA.SpreedMe.XhrConnection, enableDataChannels: true, nick: nick }); OCA.SpreedMe.webrtc = webrtc; var spreedListofSpeakers = {}; var spreedListofSharedScreens = {}; var latestSpeakerId = null; var unpromotedSpeakerId = null; var latestScreenId = null; var screenSharingActive = false; window.addEventListener('resize', function() { if (screenSharingActive) { $('#screens').children('video').each(function() { $(this).width('100%'); $(this).height($('#screens').height()); }); } }); OCA.SpreedMe.videos = { getContainerId: function(id) { var sanitizedId = id.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&"); return '#container_' + sanitizedId + '_video_incoming'; }, add: function(id) { if (!(typeof id === 'string' || id instanceof String)) { return; } // Indicator for username var userIndicator = document.createElement('div'); userIndicator.className = 'nameIndicator'; // Avatar for username var avatar = document.createElement('div'); avatar.className = 'avatar icon-loading'; var userId = spreedMappingTable[id]; if (userId && userId.length) { $(avatar).avatar(userId, 128); } else { $(avatar).imageplaceholder('?', undefined, 128); $(avatar).css('background-color', '#b9b9b9'); } $(avatar).css('opacity', '0.5'); var avatarContainer = document.createElement('div'); avatarContainer.className = 'avatar-container'; avatarContainer.appendChild(avatar); // Media indicators var mediaIndicator = document.createElement('div'); mediaIndicator.className = 'mediaIndicator'; var muteIndicator = document.createElement('button'); muteIndicator.className = 'muteIndicator icon-audio-off-white audio-on'; muteIndicator.disabled = true; var screenSharingIndicator = document.createElement('button'); screenSharingIndicator.className = 'screensharingIndicator icon-screen-white screen-off'; screenSharingIndicator.setAttribute('data-original-title', 'Show screen'); var iceFailedIndicator = document.createElement('button'); iceFailedIndicator.className = 'iceFailedIndicator icon-error-white not-failed'; iceFailedIndicator.disabled = true; $(screenSharingIndicator).tooltip({ placement: 'top', trigger: 'hover' }); mediaIndicator.appendChild(muteIndicator); mediaIndicator.appendChild(screenSharingIndicator); mediaIndicator.appendChild(iceFailedIndicator); // Generic container var container = document.createElement('div'); container.className = 'videoContainer'; container.id = 'container_' + id + '_video_incoming'; container.appendChild(avatarContainer); container.appendChild(userIndicator); container.appendChild(mediaIndicator); $(container).prependTo($('#videos')); return container; }, remove: function(id) { if (!(typeof id === 'string' || id instanceof String)) { return; } $(OCA.SpreedMe.videos.getContainerId(id)).remove(); }, addPeer: function(peer) { var newContainer = $(OCA.SpreedMe.videos.getContainerId(peer.id)); if (newContainer.length === 0) { newContainer = $(OCA.SpreedMe.videos.add(peer.id)); } // Initialize ice restart counter for peer spreedPeerConnectionTable[peer.id] = 0; peer.pc.on('iceConnectionStateChange', function () { var avatar = $(newContainer).find('.avatar'); var mediaIndicator = $(newContainer).find('.mediaIndicator'); avatar.removeClass('icon-loading'); mediaIndicator.find('.iceFailedIndicator').addClass('not-failed'); switch (peer.pc.iceConnectionState) { case 'checking': avatar.addClass('icon-loading'); console.log('Connecting to peer...'); break; case 'connected': case 'completed': // on caller side console.log('Connection established.'); avatar.css('opacity', '1'); // Send the current information about the video and microphone state if (!OCA.SpreedMe.webrtc.webrtc.isVideoEnabled()) { OCA.SpreedMe.webrtc.emit('videoOff'); } else { OCA.SpreedMe.webrtc.emit('videoOn'); } if (!OCA.SpreedMe.webrtc.webrtc.isAudioEnabled()) { OCA.SpreedMe.webrtc.emit('audioOff'); } else { OCA.SpreedMe.webrtc.emit('audioOn'); } if (!OC.getCurrentUser()['uid']) { // If we are a guest, send updated nick if it is different from the one we initialize SimpleWebRTC (OCA.SpreedMe.app.guestNick) var currentGuestNick = localStorage.getItem("nick"); if (OCA.SpreedMe.app.guestNick !== currentGuestNick) { if (!currentGuestNick) { currentGuestNick = t('spreed', 'Guest'); } OCA.SpreedMe.webrtc.sendDirectlyToAll('nickChanged', currentGuestNick); } } // Reset ice restart counter for peer if (spreedPeerConnectionTable[peer.id] > 0) { spreedPeerConnectionTable[peer.id] = 0; } break; case 'disconnected': console.log('Disconnected.'); // If the peer is still disconnected after 5 seconds we try ICE restart. setTimeout(function() { if(peer.pc.iceConnectionState === 'disconnected') { avatar.addClass('icon-loading'); if (spreedPeerConnectionTable[peer.id] < 5) { if (peer.pc.pc.peerconnection.localDescription.type === 'offer' && peer.pc.pc.peerconnection.signalingState === 'stable') { spreedPeerConnectionTable[peer.id] ++; console.log('ICE restart.'); peer.icerestart(); } } } }, 5000); break; case 'failed': console.log('Connection failed.'); if (spreedPeerConnectionTable[peer.id] < 5) { avatar.addClass('icon-loading'); if (peer.pc.pc.peerconnection.localDescription.type === 'offer' && peer.pc.pc.peerconnection.signalingState === 'stable') { spreedPeerConnectionTable[peer.id] ++; console.log('ICE restart.'); peer.icerestart(); } } else { console.log('ICE failed after 5 tries.'); mediaIndicator.children().hide(); mediaIndicator.find('.iceFailedIndicator').removeClass('not-failed').show(); } break; case 'closed': console.log('Connection closed.'); break; } if (latestSpeakerId === peer.id) { OCA.SpreedMe.speakers.updateVideoContainerDummy(peer.id); } }); peer.pc.on('PeerConnectionTrace', function (event) { console.log('trace', event); }); } }; OCA.SpreedMe.speakers = { switchVideoToId: function(id) { if (screenSharingActive || latestSpeakerId === id) { return; } var newContainer = $(OCA.SpreedMe.videos.getContainerId(id)); if(newContainer.find('video').length === 0) { console.warn('promote: no video found for ID', id); return; } if (latestSpeakerId !== null) { // move old video to new location var oldContainer = $(OCA.SpreedMe.videos.getContainerId(latestSpeakerId)); oldContainer.removeClass('promoted'); } newContainer.addClass('promoted'); OCA.SpreedMe.speakers.updateVideoContainerDummy(id); latestSpeakerId = id; }, unpromoteLatestSpeaker: function() { if (latestSpeakerId) { var oldContainer = $(OCA.SpreedMe.videos.getContainerId(latestSpeakerId)); oldContainer.removeClass('promoted'); unpromotedSpeakerId = latestSpeakerId; latestSpeakerId = null; $('.videoContainer-dummy').remove(); } }, updateVideoContainerDummy: function(id) { var newContainer = $(OCA.SpreedMe.videos.getContainerId(id)); $('.videoContainer-dummy').remove(); newContainer.after( $('
') .addClass('videoContainer videoContainer-dummy') .append(newContainer.find('.nameIndicator').clone()) .append(newContainer.find('.mediaIndicator').clone()) .append(newContainer.find('.speakingIndicator').clone()) ); }, add: function(id, notPromote) { if (!(typeof id === 'string' || id instanceof String)) { return; } if (notPromote) { spreedListofSpeakers[id] = 1; return; } spreedListofSpeakers[id] = (new Date()).getTime(); // set speaking class $(OCA.SpreedMe.videos.getContainerId(id)).addClass('speaking'); if (latestSpeakerId === id) { return; } OCA.SpreedMe.speakers.switchVideoToId(id); }, remove: function(id, enforce) { if (!(typeof id === 'string' || id instanceof String)) { return; } if (enforce) { delete spreedListofSpeakers[id]; } // remove speaking class $(OCA.SpreedMe.videos.getContainerId(id)).removeClass('speaking'); if (latestSpeakerId !== id) { return; } var mostRecentTime = 0, mostRecentId = null; for (var currentId in spreedListofSpeakers) { // skip loop if the property is from prototype if (!spreedListofSpeakers.hasOwnProperty(currentId)) { continue; } // skip non-string ids if (!(typeof currentId === 'string' || currentId instanceof String)) { continue; } var currentTime = spreedListofSpeakers[currentId]; if (currentTime > mostRecentTime && $(OCA.SpreedMe.videos.getContainerId(currentId)).length > 0) { mostRecentTime = currentTime; mostRecentId = currentId; } } if (mostRecentId !== null) { OCA.SpreedMe.speakers.switchVideoToId(mostRecentId); } else if (enforce === true) { // if there is no mostRecentId is available there is no user left in call // remove the remaining dummy container then too $('.videoContainer-dummy').remove(); } } }; OCA.SpreedMe.sharedScreens = { getContainerId: function(id) { var currentUser = OCA.SpreedMe.webrtc.connection.getSessionid(); if (currentUser === id) { return '#localScreenContainer'; } else { var sanitizedId = id.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&"); return '#container_' + sanitizedId + '_screen_incoming'; } }, switchScreenToId: function(id) { var selectedScreen = $(OCA.SpreedMe.sharedScreens.getContainerId(id)); if(selectedScreen.find('video').length === 0) { console.warn('promote: no screen video found for ID', id); return; } if(latestScreenId === id) { return; } var screenContainerId = null; for (var currentId in spreedListofSharedScreens) { // skip loop if the property is from prototype if (!spreedListofSharedScreens.hasOwnProperty(currentId)) { continue; } // skip non-string ids if (!(typeof currentId === 'string' || currentId instanceof String)) { continue; } screenContainerId = OCA.SpreedMe.sharedScreens.getContainerId(currentId); if (currentId === id) { $(screenContainerId).removeClass('hidden'); } else { $(screenContainerId).addClass('hidden'); } } // Add screen visible icon to video container $('#videos').find('.screensharingIndicator').removeClass('screen-visible'); $(OCA.SpreedMe.videos.getContainerId(id)).find('.screensharingIndicator').addClass('screen-visible'); latestScreenId = id; }, add: function(id) { if (!(typeof id === 'string' || id instanceof String)) { return; } spreedListofSharedScreens[id] = (new Date()).getTime(); var currentUser = OCA.SpreedMe.webrtc.connection.getSessionid(); if (currentUser !== id) { var screensharingIndicator = $(OCA.SpreedMe.videos.getContainerId(id)).find('.screensharingIndicator'); screensharingIndicator.removeClass('screen-off'); screensharingIndicator.addClass('screen-on'); screensharingIndicator.click(function() { if (!this.classList.contains('screen-visible')) { OCA.SpreedMe.sharedScreens.switchScreenToId(id); } $(this).tooltip('hide'); }); } OCA.SpreedMe.sharedScreens.switchScreenToId(id); }, remove: function(id) { if (!(typeof id === 'string' || id instanceof String)) { return; } delete spreedListofSharedScreens[id]; var screensharingIndicator = $(OCA.SpreedMe.videos.getContainerId(id)).find('.screensharingIndicator'); screensharingIndicator.addClass('screen-off'); screensharingIndicator.removeClass('screen-on'); var mostRecentTime = 0, mostRecentId = null; for (var currentId in spreedListofSharedScreens) { // skip loop if the property is from prototype if (!spreedListofSharedScreens.hasOwnProperty(currentId)) { continue; } // skip non-string ids if (!(typeof currentId === 'string' || currentId instanceof String)) { continue; } var currentTime = spreedListofSharedScreens[currentId]; if (currentTime > mostRecentTime) { mostRecentTime = currentTime; mostRecentId = currentId; } } if (mostRecentId !== null) { OCA.SpreedMe.sharedScreens.switchScreenToId(mostRecentId); } } }; OCA.SpreedMe.webrtc.on('createdPeer', function (peer) { console.log('PEER CREATED', peer); if (peer.type === 'video') { OCA.SpreedMe.videos.addPeer(peer); } }); OCA.SpreedMe.webrtc.on('localMediaStarted', function (configuration) { OCA.SpreedMe.app.startSpreed(configuration); }); OCA.SpreedMe.webrtc.on('localMediaError', function(error) { console.log('Access to microphone & camera failed', error); var message, messageAdditional; if (error.name === "NotAllowedError") { if (error.message && error.message.indexOf("Only secure origins") !== -1) { message = t('spreed', 'Access to microphone & camera is only possible with HTTPS'); messageAdditional = t('spreed', 'Please adjust your configuration'); } else { message = t('spreed', 'Access to microphone & camera was denied'); $('#emptycontent p').hide(); } } else if(!OCA.SpreedMe.webrtc.capabilities.support) { console.log('WebRTC not supported'); message = t('spreed', 'WebRTC is not supported in your browser'); messageAdditional = t('spreed', 'Please use a different browser like Firefox or Chrome'); } else { message = t('spreed', 'Error while accessing microphone & camera'); console.log('Error while accessing microphone & camera: ', error.message || error.name); } OCA.SpreedMe.app.setEmptyContentMessage( 'icon-video-off', message, messageAdditional ); // Hide rooms sidebar $('#app-navigation').hide(); }); if(!OCA.SpreedMe.webrtc.capabilities.support) { console.log('WebRTC not supported'); var message, messageAdditional; message = t('spreed', 'WebRTC is not supported in your browser :-/'); messageAdditional = t('spreed', 'Please use a different browser like Firefox or Chrome'); OCA.SpreedMe.app.setEmptyContentMessage( 'icon-video-off', message, messageAdditional ); } OCA.SpreedMe.webrtc.on('joinedRoom', function(name) { $('#app-content').removeClass('icon-loading'); $('.videoView').removeClass('hidden'); OCA.SpreedMe.app.syncAndSetActiveRoom(name); }); OCA.SpreedMe.webrtc.on('channelMessage', function (peer, label, data) { if(label === 'speaking') { OCA.SpreedMe.speakers.add(peer.id); } else if(label === 'stoppedSpeaking') { OCA.SpreedMe.speakers.remove(peer.id); } else if(label === 'audioOn') { OCA.SpreedMe.webrtc.emit('unmute', {id: peer.id, name:'audio'}); } else if(label === 'audioOff') { OCA.SpreedMe.webrtc.emit('mute', {id: peer.id, name:'audio'}); } else if(label === 'videoOn') { OCA.SpreedMe.webrtc.emit('unmute', {id: peer.id, name:'video'}); } else if(label === 'videoOff') { OCA.SpreedMe.webrtc.emit('mute', {id: peer.id, name:'video'}); } else if (label === 'nickChanged') { OCA.SpreedMe.webrtc.emit('nick', {id: peer.id, name:data.type}); } }); OCA.SpreedMe.webrtc.on('videoAdded', function(video, peer) { console.log('VIDEO ADDED', peer); if (peer.type === 'screen') { OCA.SpreedMe.webrtc.emit('screenAdded', video, peer); return; } var videoContainer = $(OCA.SpreedMe.videos.getContainerId(peer.id)); if (videoContainer.length) { var userId = spreedMappingTable[peer.id]; var nameIndicator = videoContainer.find('.nameIndicator'); var avatar = videoContainer.find('.avatar'); if (userId.length) { avatar.avatar(userId, 128); nameIndicator.text(peer.nick); } else if (peer.nick) { avatar.imageplaceholder(peer.nick, undefined, 128); nameIndicator.text(peer.nick); } else { avatar.imageplaceholder('?', undefined, 128); avatar.css('background-color', '#b9b9b9'); nameIndicator.text(t('spreed', 'Guest')); } $(videoContainer).prepend(video); video.oncontextmenu = function() { return false; }; } var otherSpeakerPromoted = false; for (var key in spreedListofSpeakers) { if (spreedListofSpeakers.hasOwnProperty(key) && spreedListofSpeakers[key] > 1) { otherSpeakerPromoted = true; break; } } if (!otherSpeakerPromoted) { OCA.SpreedMe.speakers.add(peer.id); } else { OCA.SpreedMe.speakers.add(peer.id, true); } }); OCA.SpreedMe.webrtc.on('speaking', function(){ OCA.SpreedMe.webrtc.sendDirectlyToAll('speaking'); $('#localVideoContainer').addClass('speaking'); }); OCA.SpreedMe.webrtc.on('stoppedSpeaking', function(){ OCA.SpreedMe.webrtc.sendDirectlyToAll('stoppedSpeaking'); $('#localVideoContainer').removeClass('speaking'); }); // a peer was removed OCA.SpreedMe.webrtc.on('videoRemoved', function(video, peer) { if (peer) { if (peer.type === 'video') { // a removed peer can't speak anymore ;) OCA.SpreedMe.speakers.remove(peer.id, true); var videoContainer = document.getElementById('container_' + OCA.SpreedMe.webrtc.getDomId(peer)); var el = document.getElementById(OCA.SpreedMe.webrtc.getDomId(peer)); if (videoContainer && el) { videoContainer.removeChild(el); } } else if (peer.type === 'screen') { var remotes = document.getElementById('screens'); var screenContainer = document.getElementById('container_' + OCA.SpreedMe.webrtc.getDomId(peer)); if (remotes && screenContainer) { remotes.removeChild(screenContainer); } OCA.SpreedMe.sharedScreens.remove(peer.id); } } else if (video.id === 'localScreen') { // SimpleWebRTC notifies about stopped screensharing through // the generic "videoRemoved" API, but the stream must be // handled differently. OCA.SpreedMe.webrtc.emit('localScreenStopped'); var screens = document.getElementById('screens'); var localScreenContainer = document.getElementById('localScreenContainer'); if (screens && localScreenContainer) { screens.removeChild(localScreenContainer); } OCA.SpreedMe.sharedScreens.remove(OCA.SpreedMe.webrtc.connection.getSessionid()); } // Check if there are still some screens if (!document.getElementById('screens').hasChildNodes()) { screenSharingActive = false; $('#app-content').removeClass('screensharing'); if (unpromotedSpeakerId) { OCA.SpreedMe.speakers.switchVideoToId(unpromotedSpeakerId); unpromotedSpeakerId = null; } } }); // Send the audio on and off events via data channel OCA.SpreedMe.webrtc.on('audioOn', function() { OCA.SpreedMe.webrtc.sendDirectlyToAll('audioOn'); }); OCA.SpreedMe.webrtc.on('audioOff', function() { OCA.SpreedMe.webrtc.sendDirectlyToAll('audioOff'); }); OCA.SpreedMe.webrtc.on('videoOn', function() { OCA.SpreedMe.webrtc.sendDirectlyToAll('videoOn'); }); OCA.SpreedMe.webrtc.on('videoOff', function() { OCA.SpreedMe.webrtc.sendDirectlyToAll('videoOff'); }); OCA.SpreedMe.webrtc.on('screenAdded', function(video, peer) { OCA.SpreedMe.speakers.unpromoteLatestSpeaker(); screenSharingActive = true; $('#app-content').attr('class', '').addClass('screensharing'); var screens = document.getElementById('screens'); if (screens) { // Indicator for username var userIndicator = document.createElement('div'); userIndicator.className = 'nameIndicator'; if (peer) { if (peer.nick) { userIndicator.textContent = t('spreed', "{participantName}'s screen", {participantName: peer.nick}); } else { userIndicator.textContent = t('spreed', "Guest's screen"); } } else { userIndicator.textContent = t('spreed', 'Your screen'); } // Generic container var container = document.createElement('div'); container.className = 'screenContainer'; container.id = peer ? 'container_' + OCA.SpreedMe.webrtc.getDomId(peer) : 'localScreenContainer'; container.appendChild(video); container.appendChild(userIndicator); video.oncontextmenu = function() { return false; }; $(container).prependTo($('#screens')); if (peer) { OCA.SpreedMe.sharedScreens.add(peer.id); } else { OCA.SpreedMe.sharedScreens.add(OCA.SpreedMe.webrtc.connection.getSessionid()); } } }); // Local screen added. OCA.SpreedMe.webrtc.on('localScreenAdded', function(video) { OCA.SpreedMe.webrtc.emit('screenAdded', video, null); }); // Peer changed nick OCA.SpreedMe.webrtc.on('nick', function(data) { // Video var video = document.getElementById('container_' + OCA.SpreedMe.webrtc.getDomId({ id: data.id, type: 'video', broadcaster: false })); var videoNameIndicator = $(video).find('.nameIndicator'); var videoAvatar = $(video).find('.avatar'); //Screen var screen = document.getElementById('container_' + OCA.SpreedMe.webrtc.getDomId({ id: data.id, type: 'screen', broadcaster: false })); var screenNameIndicator = $(screen).find('.nameIndicator'); if (data.name.length === 0) { videoNameIndicator.text(t('spreed', 'Guest')); videoAvatar.imageplaceholder('?', undefined, 128); videoAvatar.css('background-color', '#b9b9b9'); screenNameIndicator.text(t('spreed', "Guest's screen")); } else { videoNameIndicator.text(data.name); videoAvatar.imageplaceholder(data.name, undefined, 128); screenNameIndicator.text(t('spreed', "{participantName}'s screen", {participantName: data.name})); } if (latestSpeakerId === data.id) { OCA.SpreedMe.speakers.updateVideoContainerDummy(data.id); } }); // Peer is muted OCA.SpreedMe.webrtc.on('mute', function(data) { var el = document.getElementById('container_' + OCA.SpreedMe.webrtc.getDomId({ id: data.id, type: 'video', broadcaster: false })); var $el = $(el); if (data.name === 'video') { var avatarContainer = $el.find('.avatar-container'); avatarContainer.removeClass('hidden'); avatarContainer.show(); $el.find('video').hide(); } else { var muteIndicator = $el.find('.muteIndicator'); muteIndicator.removeClass('audio-on'); muteIndicator.addClass('audio-off'); $el.removeClass('speaking'); } if (latestSpeakerId === data.id) { OCA.SpreedMe.speakers.updateVideoContainerDummy(data.id); } }); // Peer is umuted OCA.SpreedMe.webrtc.on('unmute', function(data) { var el = document.getElementById('container_' + OCA.SpreedMe.webrtc.getDomId({ id: data.id, type: 'video', broadcaster: false })); var $el = $(el); if (data.name === 'video') { $el.find('.avatar-container').hide(); $el.find('video').show(); } else { var muteIndicator = $el.find('.muteIndicator'); muteIndicator.removeClass('audio-off'); muteIndicator.addClass('audio-on'); } if (latestSpeakerId === data.id) { OCA.SpreedMe.speakers.updateVideoContainerDummy(data.id); } }); OCA.SpreedMe.webrtc.on('localStream', function() { if(!OCA.SpreedMe.app.videoWasEnabledAtLeastOnce) { OCA.SpreedMe.app.videoWasEnabledAtLeastOnce = true; } if (!OCA.SpreedMe.app.videoDisabled) { OCA.SpreedMe.app.enableVideo(); } }); } OCA.SpreedMe.initWebRTC = initWebRTC; })(OCA, OC);