Fixes audio / video mutes
This commit is contained in:
parent
8aad75d9fa
commit
29a85b797a
597
app.js
597
app.js
|
@ -15,35 +15,15 @@ window.toastr = require("toastr");
|
|||
|
||||
import URLProcessor from "./modules/config/URLProcessor";
|
||||
import RoomnameGenerator from './modules/util/RoomnameGenerator';
|
||||
import CQEvents from './service/connectionquality/CQEvents';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
import DSEvents from './service/desktopsharing/DesktopSharingEventTypes';
|
||||
|
||||
import UI from "./modules/UI/UI";
|
||||
import statistics from "./modules/statistics/statistics";
|
||||
import settings from "./modules/settings/Settings";
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
|
||||
import {openConnection} from './modules/connection';
|
||||
import AuthHandler from './modules/AuthHandler';
|
||||
import conference from './conference';
|
||||
|
||||
import createRoomLocker from './modules/RoomLocker';
|
||||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
const ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
const ConferenceErrors = JitsiMeetJS.errors.conference;
|
||||
|
||||
let localVideo, localAudio;
|
||||
|
||||
const Commands = {
|
||||
CONNECTION_QUALITY: "stats",
|
||||
EMAIL: "email",
|
||||
VIDEO_TYPE: "videoType",
|
||||
ETHERPAD: "etherpad",
|
||||
PREZI: "prezi",
|
||||
STOP_PREZI: "stop-prezi"
|
||||
};
|
||||
|
||||
function buildRoomName () {
|
||||
let path = window.location.pathname;
|
||||
|
@ -77,66 +57,12 @@ function buildRoomName () {
|
|||
return roomName;
|
||||
}
|
||||
|
||||
|
||||
const APP = {
|
||||
UI,
|
||||
statistics,
|
||||
settings,
|
||||
|
||||
createLocalTracks (...devices) {
|
||||
return JitsiMeetJS.createLocalTracks({
|
||||
// copy array to avoid mutations inside library
|
||||
devices: devices.slice(0),
|
||||
resolution: config.resolution
|
||||
}).catch(function (err) {
|
||||
console.error('failed to create local tracks', ...devices, err);
|
||||
APP.statistics.onGetUserMediaFailed(err);
|
||||
return [];
|
||||
});
|
||||
},
|
||||
|
||||
init () {
|
||||
let roomName = buildRoomName();
|
||||
this.conference = {
|
||||
roomName,
|
||||
localId: undefined,
|
||||
isModerator: false,
|
||||
membersCount: 0,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
isLocalId (id) {
|
||||
return this.localId === id;
|
||||
},
|
||||
muteAudio (mute) {
|
||||
APP.UI.eventEmitter.emit(UIEvents.AUDIO_MUTED, mute);
|
||||
APP.statistics.onAudioMute(mute);
|
||||
},
|
||||
toggleAudioMuted () {
|
||||
this.muteAudio(!this.audioMuted);
|
||||
},
|
||||
muteVideo (mute) {
|
||||
APP.UI.eventEmitter.emit(UIEvents.VIDEO_MUTED, mute);
|
||||
APP.statistics.onVideoMute(mute);
|
||||
},
|
||||
toggleVideoMuted () {
|
||||
this.muteVideo(!this.videoMuted);
|
||||
},
|
||||
|
||||
// used by torture currently
|
||||
isJoined () {
|
||||
return APP.conference._room
|
||||
&& APP.conference._room.isJoined();
|
||||
},
|
||||
getConnectionState () {
|
||||
return APP.conference._room
|
||||
&& APP.conference._room.getConnectionState();
|
||||
},
|
||||
getMyUserId () {
|
||||
return APP.conference._room
|
||||
&& APP.conference._room.myUserId();
|
||||
}
|
||||
};
|
||||
|
||||
this.conference = conference;
|
||||
this.API = require("./modules/API/API");
|
||||
this.connectionquality =
|
||||
require("./modules/connectionquality/connectionquality");
|
||||
|
@ -149,524 +75,9 @@ const APP = {
|
|||
}
|
||||
};
|
||||
|
||||
function initConference(localTracks, connection) {
|
||||
let options = {
|
||||
openSctp: config.openSctp,
|
||||
disableAudioLevels: config.disableAudioLevels
|
||||
};
|
||||
if(config.enableRecording) {
|
||||
options.recordingType = (config.hosts &&
|
||||
(typeof config.hosts.jirecon != "undefined"))?
|
||||
"jirecon" : "colibri";
|
||||
}
|
||||
let room = connection.initJitsiConference(APP.conference.roomName, options);
|
||||
APP.conference._room = room; // FIXME do not use this
|
||||
|
||||
const addTrack = (track) => {
|
||||
room.addTrack(track);
|
||||
if (track.isAudioTrack()) {
|
||||
return;
|
||||
}
|
||||
|
||||
room.removeCommand(Commands.VIDEO_TYPE);
|
||||
room.sendCommand(Commands.VIDEO_TYPE, {
|
||||
value: track.videoType,
|
||||
attributes: {
|
||||
xmlns: 'http://jitsi.org/jitmeet/video'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
APP.conference.localId = room.myUserId();
|
||||
Object.defineProperty(APP.conference, "membersCount", {
|
||||
get: function () {
|
||||
return room.getParticipants().length; // FIXME maybe +1?
|
||||
}
|
||||
});
|
||||
|
||||
APP.conference.listMembers = function () {
|
||||
return room.getParticipants();
|
||||
};
|
||||
APP.conference.listMembersIds = function () {
|
||||
return room.getParticipants().map(p => p.getId());
|
||||
};
|
||||
|
||||
APP.conference.sipGatewayEnabled = () => {
|
||||
return room.isSIPCallingSupported();
|
||||
};
|
||||
|
||||
function getDisplayName(id) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
return APP.settings.getDisplayName();
|
||||
}
|
||||
|
||||
let participant = room.getParticipantById(id);
|
||||
if (participant && participant.getDisplayName()) {
|
||||
return participant.getDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
// add local streams when joined to the conference
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, function () {
|
||||
localTracks.forEach(function (track) {
|
||||
if(track.isAudioTrack()) {
|
||||
localAudio = track;
|
||||
}
|
||||
else if (track.isVideoTrack()) {
|
||||
localVideo = track;
|
||||
}
|
||||
addTrack(track);
|
||||
APP.UI.addLocalStream(track);
|
||||
});
|
||||
|
||||
APP.UI.updateAuthInfo(room.isAuthEnabled(), room.getAuthLogin());
|
||||
});
|
||||
|
||||
|
||||
room.on(ConferenceEvents.USER_JOINED, function (id, user) {
|
||||
console.log('USER %s connnected', id, user);
|
||||
// FIXME email???
|
||||
APP.UI.addUser(id, user.getDisplayName());
|
||||
});
|
||||
room.on(ConferenceEvents.USER_LEFT, function (id, user) {
|
||||
console.log('USER %s LEFT', id, user);
|
||||
APP.UI.removeUser(id, user.getDisplayName());
|
||||
APP.UI.stopPrezi(id);
|
||||
});
|
||||
|
||||
|
||||
room.on(ConferenceEvents.USER_ROLE_CHANGED, function (id, role) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
console.info(`My role changed, new role: ${role}`);
|
||||
APP.conference.isModerator = room.isModerator();
|
||||
APP.UI.updateLocalRole(room.isModerator());
|
||||
} else {
|
||||
let user = room.getParticipantById(id);
|
||||
if (user) {
|
||||
APP.UI.updateUserRole(user);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let roomLocker = createRoomLocker(room);
|
||||
APP.UI.addListener(UIEvents.ROOM_LOCK_CLICKED, function () {
|
||||
if (room.isModerator()) {
|
||||
let promise = roomLocker.isLocked
|
||||
? roomLocker.askToUnlock()
|
||||
: roomLocker.askToLock();
|
||||
promise.then(function () {
|
||||
APP.UI.markRoomLocked(roomLocker.isLocked);
|
||||
});
|
||||
} else {
|
||||
roomLocker.notifyModeratorRequired();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
room.on(ConferenceEvents.TRACK_ADDED, function (track) {
|
||||
if (track.isLocal()) { // skip local tracks
|
||||
return;
|
||||
}
|
||||
console.log(
|
||||
'REMOTE %s TRACK', track.getType(), track.getParticipantId()
|
||||
);
|
||||
APP.UI.addRemoteStream(track);
|
||||
});
|
||||
room.on(ConferenceEvents.TRACK_REMOVED, function (track) {
|
||||
if (track.isLocal()) { // skip local tracks
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
'REMOTE %s TRACK REMOVED', track.getType(), track.getParticipantId()
|
||||
);
|
||||
|
||||
// FIXME handle
|
||||
});
|
||||
room.on(ConferenceEvents.TRACK_MUTE_CHANGED, function (track) {
|
||||
// FIXME handle mute
|
||||
});
|
||||
room.on(ConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, function (id, lvl) {
|
||||
APP.UI.setAudioLevel(id, lvl);
|
||||
});
|
||||
APP.UI.addListener(UIEvents.AUDIO_MUTED, function (muted) {
|
||||
// FIXME mute or unmute
|
||||
APP.UI.setAudioMuted(muted);
|
||||
APP.conference.audioMuted = muted;
|
||||
});
|
||||
APP.UI.addListener(UIEvents.VIDEO_MUTED, function (muted) {
|
||||
// FIXME mute or unmute
|
||||
APP.UI.setVideoMuted(muted);
|
||||
APP.conference.videoMuted = muted;
|
||||
});
|
||||
|
||||
|
||||
room.on(ConferenceEvents.IN_LAST_N_CHANGED, function (inLastN) {
|
||||
if (config.muteLocalVideoIfNotInLastN) {
|
||||
// TODO mute or unmute if required
|
||||
// mark video on UI
|
||||
// APP.UI.markVideoMuted(true/false);
|
||||
}
|
||||
});
|
||||
room.on(ConferenceEvents.LAST_N_ENDPOINTS_CHANGED, function (ids) {
|
||||
APP.UI.handleLastNEndpoints(ids);
|
||||
});
|
||||
room.on(ConferenceEvents.ACTIVE_SPEAKER_CHANGED, function (id) {
|
||||
APP.UI.markDominantSpiker(id);
|
||||
});
|
||||
|
||||
|
||||
if (!interfaceConfig.filmStripOnly) {
|
||||
room.on(ConferenceEvents.CONNECTION_INTERRUPTED, function () {
|
||||
APP.UI.markVideoInterrupted(true);
|
||||
});
|
||||
room.on(ConferenceEvents.CONNECTION_RESTORED, function () {
|
||||
APP.UI.markVideoInterrupted(false);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.MESSAGE_CREATED, function (message) {
|
||||
room.sendTextMessage(message);
|
||||
});
|
||||
room.on(ConferenceEvents.MESSAGE_RECEIVED, function (id, text, ts) {
|
||||
APP.UI.addMessage(id, getDisplayName(id), text, ts);
|
||||
});
|
||||
}
|
||||
|
||||
APP.connectionquality.addListener(
|
||||
CQEvents.LOCALSTATS_UPDATED,
|
||||
function (percent, stats) {
|
||||
APP.UI.updateLocalStats(percent, stats);
|
||||
|
||||
// send local stats to other users
|
||||
room.sendCommandOnce(Commands.CONNECTION_QUALITY, {
|
||||
children: APP.connectionquality.convertToMUCStats(stats),
|
||||
attributes: {
|
||||
xmlns: 'http://jitsi.org/jitmeet/stats'
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
APP.connectionquality.addListener(CQEvents.STOP, function () {
|
||||
APP.UI.hideStats();
|
||||
room.removeCommand(Commands.CONNECTION_QUALITY);
|
||||
});
|
||||
// listen to remote stats
|
||||
room.addCommandListener(
|
||||
Commands.CONNECTION_QUALITY,
|
||||
function (values, from) {
|
||||
APP.connectionquality.updateRemoteStats(from, values);
|
||||
}
|
||||
);
|
||||
APP.connectionquality.addListener(
|
||||
CQEvents.REMOTESTATS_UPDATED,
|
||||
function (id, percent, stats) {
|
||||
APP.UI.updateRemoteStats(id, percent, stats);
|
||||
}
|
||||
);
|
||||
|
||||
room.addCommandListener(Commands.ETHERPAD, function ({value}) {
|
||||
APP.UI.initEtherpad(value);
|
||||
});
|
||||
|
||||
|
||||
room.addCommandListener(Commands.PREZI, function ({value, attributes}) {
|
||||
APP.UI.showPrezi(attributes.id, value, attributes.slide);
|
||||
});
|
||||
room.addCommandListener(Commands.STOP_PREZI, function ({attributes}) {
|
||||
APP.UI.stopPrezi(attributes.id);
|
||||
});
|
||||
APP.UI.addListener(UIEvents.SHARE_PREZI, function (url, slide) {
|
||||
console.log('Sharing Prezi %s slide %s', url, slide);
|
||||
room.removeCommand(Commands.PREZI);
|
||||
room.sendCommand(Commands.PREZI, {
|
||||
value: url,
|
||||
attributes: {
|
||||
id: room.myUserId(),
|
||||
slide
|
||||
}
|
||||
});
|
||||
});
|
||||
APP.UI.addListener(UIEvents.STOP_SHARING_PREZI, function () {
|
||||
room.removeCommand(Commands.PREZI);
|
||||
room.sendCommandOnce(Commands.STOP_PREZI, {
|
||||
attributes: {
|
||||
id: room.myUserId()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
room.addCommandListener(Commands.VIDEO_TYPE, ({value}, from) => {
|
||||
APP.UI.onPeerVideoTypeChanged(from, value);
|
||||
});
|
||||
|
||||
|
||||
// share email with other users
|
||||
function sendEmail(email) {
|
||||
room.sendCommand(Commands.EMAIL, {
|
||||
value: email,
|
||||
attributes: {
|
||||
id: room.myUserId()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let email = APP.settings.getEmail();
|
||||
email && sendEmail(email);
|
||||
APP.UI.addListener(UIEvents.EMAIL_CHANGED, function (email) {
|
||||
APP.settings.setEmail(email);
|
||||
APP.UI.setUserAvatar(room.myUserId(), email);
|
||||
sendEmail(email);
|
||||
});
|
||||
room.addCommandListener(Commands.EMAIL, function (data) {
|
||||
APP.UI.setUserAvatar(data.attributes.id, data.value);
|
||||
});
|
||||
|
||||
let nick = APP.settings.getDisplayName();
|
||||
if (config.useNicks && !nick) {
|
||||
nick = APP.UI.askForNickname();
|
||||
APP.settings.setDisplayName(nick);
|
||||
}
|
||||
|
||||
if (nick) {
|
||||
room.setDisplayName(nick);
|
||||
}
|
||||
room.on(ConferenceEvents.DISPLAY_NAME_CHANGED, function (id, displayName) {
|
||||
APP.UI.changeDisplayName(id, displayName);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.RECORDING_STATE_CHANGED, (status, error) => {
|
||||
if(status == "error") {
|
||||
console.error(error);
|
||||
return;
|
||||
}
|
||||
APP.UI.updateRecordingState(status);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.NICKNAME_CHANGED, function (nickname) {
|
||||
APP.settings.setDisplayName(nickname);
|
||||
room.setDisplayName(nickname);
|
||||
APP.UI.changeDisplayName(APP.conference.localId, nickname);
|
||||
});
|
||||
|
||||
APP.UI.addListener(
|
||||
UIEvents.START_MUTED_CHANGED,
|
||||
function (startAudioMuted, startVideoMuted) {
|
||||
// FIXME start muted
|
||||
}
|
||||
);
|
||||
|
||||
APP.UI.addListener(UIEvents.USER_INVITED, function (roomUrl) {
|
||||
APP.UI.inviteParticipants(
|
||||
roomUrl,
|
||||
APP.conference.roomName,
|
||||
roomLocker.password,
|
||||
APP.settings.getDisplayName()
|
||||
);
|
||||
});
|
||||
|
||||
// call hangup
|
||||
APP.UI.addListener(UIEvents.HANGUP, function () {
|
||||
APP.UI.requestFeedback().then(function () {
|
||||
connection.disconnect();
|
||||
|
||||
if (config.enableWelcomePage) {
|
||||
setTimeout(function() {
|
||||
window.localStorage.welcomePageDisabled = false;
|
||||
window.location.pathname = "/";
|
||||
}, 3000);
|
||||
}
|
||||
}, function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
// logout
|
||||
APP.UI.addListener(UIEvents.LOGOUT, function () {
|
||||
// FIXME handle logout
|
||||
// APP.xmpp.logout(function (url) {
|
||||
// if (url) {
|
||||
// window.location.href = url;
|
||||
// } else {
|
||||
// hangup();
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SIP_DIAL, function (sipNumber) {
|
||||
room.dial(sipNumber);
|
||||
});
|
||||
|
||||
|
||||
// Starts or stops the recording for the conference.
|
||||
APP.UI.addListener(UIEvents.RECORDING_TOGGLE, function (predefinedToken) {
|
||||
if (predefinedToken) {
|
||||
room.toggleRecording({token: predefinedToken});
|
||||
return;
|
||||
}
|
||||
APP.UI.requestRecordingToken().then((token) => {
|
||||
room.toggleRecording({token: token});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.TOPIC_CHANGED, function (topic) {
|
||||
// FIXME handle topic change
|
||||
// APP.xmpp.setSubject(topic);
|
||||
// on SUBJECT_CHANGED UI.setSubject(topic);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.USER_KICKED, function (id) {
|
||||
room.kickParticipant(id);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.REMOTE_AUDIO_MUTED, function (id) {
|
||||
room.muteParticipant(id);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.KICKED, function () {
|
||||
APP.UI.notifyKicked();
|
||||
// FIXME close
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.AUTH_CLICKED, function () {
|
||||
AuthHandler.authenticate(room);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, function (id) {
|
||||
room.selectParticipant(id);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.DTMF_SUPPORT_CHANGED, function (isDTMFSupported) {
|
||||
APP.UI.updateDTMFSupport(isDTMFSupported);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.TOGGLE_SCREENSHARING, function () {
|
||||
APP.desktopsharing.toggleScreenSharing();
|
||||
});
|
||||
APP.UI.addListener(DSEvents.SWITCHING_DONE, function (isSharingScreen) {
|
||||
APP.UI.updateDesktopSharingButtons(isSharingScreen);
|
||||
});
|
||||
APP.desktopsharing.addListener(
|
||||
DSEvents.NEW_STREAM_CREATED,
|
||||
(track, callback) => {
|
||||
const localCallback = (newTrack) => {
|
||||
if (newTrack.isLocal() && newTrack === localVideo) {
|
||||
if(localVideo.isMuted() &&
|
||||
localVideo.videoType !== track.videoType) {
|
||||
localVideo.mute();
|
||||
}
|
||||
callback();
|
||||
room.off(ConferenceEvents.TRACK_ADDED, localCallback);
|
||||
}
|
||||
};
|
||||
|
||||
room.on(ConferenceEvents.TRACK_ADDED, localCallback);
|
||||
|
||||
localVideo.stop();
|
||||
localVideo = track;
|
||||
addTrack(track);
|
||||
APP.UI.addLocalStream(track);
|
||||
}
|
||||
);
|
||||
|
||||
const unload = () => {
|
||||
room.leave();
|
||||
connection.disconnect();
|
||||
};
|
||||
$(window).bind('beforeunload', unload );
|
||||
$(window).bind('unload', unload );
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, handleConferenceJoined);
|
||||
room.on(ConferenceEvents.CONFERENCE_FAILED, onConferenceFailed);
|
||||
|
||||
let password;
|
||||
let reconnectTimeout;
|
||||
|
||||
function unsubscribe() {
|
||||
room.off(
|
||||
ConferenceEvents.CONFERENCE_JOINED, handleConferenceJoined
|
||||
);
|
||||
room.off(
|
||||
ConferenceEvents.CONFERENCE_FAILED, onConferenceFailed
|
||||
);
|
||||
if (reconnectTimeout) {
|
||||
clearTimeout(reconnectTimeout);
|
||||
}
|
||||
AuthHandler.closeAuth();
|
||||
}
|
||||
|
||||
function handleConferenceJoined() {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
}
|
||||
|
||||
function handleConferenceFailed(err) {
|
||||
unsubscribe();
|
||||
reject(err);
|
||||
}
|
||||
|
||||
function onConferenceFailed(err, msg = '') {
|
||||
console.error('CONFERENCE FAILED:', err, msg);
|
||||
switch (err) {
|
||||
// room is locked by the password
|
||||
case ConferenceErrors.PASSWORD_REQUIRED:
|
||||
APP.UI.markRoomLocked(true);
|
||||
roomLocker.requirePassword().then(function () {
|
||||
room.join(roomLocker.password);
|
||||
});
|
||||
break;
|
||||
|
||||
case ConferenceErrors.CONNECTION_ERROR:
|
||||
APP.UI.notifyConnectionFailed(msg);
|
||||
break;
|
||||
|
||||
// not enough rights to create conference
|
||||
case ConferenceErrors.AUTHENTICATION_REQUIRED:
|
||||
// schedule reconnect to check if someone else created the room
|
||||
reconnectTimeout = setTimeout(function () {
|
||||
room.join(password);
|
||||
}, 5000);
|
||||
|
||||
// notify user that auth is required
|
||||
AuthHandler.requireAuth(APP.conference.roomName);
|
||||
break;
|
||||
|
||||
default:
|
||||
handleConferenceFailed(err);
|
||||
}
|
||||
}
|
||||
|
||||
room.join(password);
|
||||
});
|
||||
}
|
||||
|
||||
function connect() {
|
||||
return openConnection({retry: true}).catch(function (err) {
|
||||
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
APP.UI.notifyTokenAuthFailed();
|
||||
} else {
|
||||
APP.UI.notifyConnectionFailed(err);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
APP.UI.start();
|
||||
|
||||
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
|
||||
|
||||
JitsiMeetJS.init(config).then(function () {
|
||||
return Promise.all([
|
||||
APP.createLocalTracks('audio', 'video'),
|
||||
connect()
|
||||
]);
|
||||
}).then(function ([tracks, connection]) {
|
||||
console.log('initialized with %s local tracks', tracks.length);
|
||||
return initConference(tracks, connection);
|
||||
}).then(function () {
|
||||
APP.conference.init({roomName: buildRoomName()}).then(function () {
|
||||
APP.UI.initConference();
|
||||
|
||||
APP.UI.addListener(UIEvents.LANG_CHANGED, function (language) {
|
||||
|
|
|
@ -0,0 +1,614 @@
|
|||
/* global $, APP, JitsiMeetJS, config, interfaceConfig */
|
||||
import {openConnection} from './connection';
|
||||
//FIXME:
|
||||
import createRoomLocker from './modules/UI/authentication/RoomLocker';
|
||||
//FIXME:
|
||||
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
||||
|
||||
import CQEvents from './service/connectionquality/CQEvents';
|
||||
import UIEvents from './service/UI/UIEvents';
|
||||
import DSEvents from './service/desktopsharing/DesktopSharingEventTypes';
|
||||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
const ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
const ConferenceErrors = JitsiMeetJS.errors.conference;
|
||||
|
||||
let room, connection, localTracks, localAudio, localVideo;
|
||||
let roomLocker = createRoomLocker(room);
|
||||
|
||||
const Commands = {
|
||||
CONNECTION_QUALITY: "stats",
|
||||
EMAIL: "email",
|
||||
VIDEO_TYPE: "videoType",
|
||||
ETHERPAD: "etherpad",
|
||||
PREZI: "prezi",
|
||||
STOP_PREZI: "stop-prezi"
|
||||
};
|
||||
|
||||
function connect() {
|
||||
return openConnection({retry: true}).catch(function (err) {
|
||||
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
APP.UI.notifyTokenAuthFailed();
|
||||
} else {
|
||||
APP.UI.notifyConnectionFailed(err);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
const addTrack = (track) => {
|
||||
room.addTrack(track);
|
||||
if (track.isAudioTrack()) {
|
||||
return;
|
||||
}
|
||||
|
||||
room.removeCommand(Commands.VIDEO_TYPE);
|
||||
room.sendCommand(Commands.VIDEO_TYPE, {
|
||||
value: track.videoType,
|
||||
attributes: {
|
||||
xmlns: 'http://jitsi.org/jitmeet/video'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// share email with other users
|
||||
const sendEmail = (email) => {
|
||||
room.sendCommand(Commands.EMAIL, {
|
||||
value: email,
|
||||
attributes: {
|
||||
id: room.myUserId()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const unload = () => {
|
||||
room.leave();
|
||||
connection.disconnect();
|
||||
};
|
||||
|
||||
const getDisplayName = (id) => {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
return APP.settings.getDisplayName();
|
||||
}
|
||||
|
||||
let participant = room.getParticipantById(id);
|
||||
if (participant && participant.getDisplayName()) {
|
||||
return participant.getDisplayName();
|
||||
}
|
||||
};
|
||||
|
||||
class ConferenceConnector {
|
||||
constructor(resolve, reject) {
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
this.reconnectTimeout = null;
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED,
|
||||
this._handleConferenceJoined.bind(this));
|
||||
room.on(ConferenceEvents.CONFERENCE_FAILED,
|
||||
this._onConferenceFailed.bind(this));
|
||||
}
|
||||
_handleConferenceFailed(err) {
|
||||
this._unsubscribe();
|
||||
this._reject(err);
|
||||
}
|
||||
_onConferenceFailed(err, msg = '') {
|
||||
console.error('CONFERENCE FAILED:', err, msg);
|
||||
switch (err) {
|
||||
// room is locked by the password
|
||||
case ConferenceErrors.PASSWORD_REQUIRED:
|
||||
APP.UI.markRoomLocked(true);
|
||||
roomLocker.requirePassword().then(function () {
|
||||
room.join(roomLocker.password);
|
||||
});
|
||||
break;
|
||||
|
||||
case ConferenceErrors.CONNECTION_ERROR:
|
||||
APP.UI.notifyConnectionFailed(msg);
|
||||
break;
|
||||
|
||||
// not enough rights to create conference
|
||||
case ConferenceErrors.AUTHENTICATION_REQUIRED:
|
||||
// schedule reconnect to check if someone else created the room
|
||||
this.reconnectTimeout = setTimeout(function () {
|
||||
room.join();
|
||||
}, 5000);
|
||||
|
||||
// notify user that auth is required
|
||||
AuthHandler.requireAuth(APP.conference.roomName);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.handleConferenceFailed(err);
|
||||
}
|
||||
}
|
||||
_unsubscribe() {
|
||||
room.off(
|
||||
ConferenceEvents.CONFERENCE_JOINED, this._handleConferenceJoined);
|
||||
room.off(
|
||||
ConferenceEvents.CONFERENCE_FAILED, this._onConferenceFailed);
|
||||
if (this.reconnectTimeout !== null) {
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
}
|
||||
AuthHandler.closeAuth();
|
||||
}
|
||||
_handleConferenceJoined() {
|
||||
this._unsubscribe();
|
||||
this._resolve();
|
||||
}
|
||||
connect() {
|
||||
room.join();
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
localId: undefined,
|
||||
isModerator: false,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
init(options) {
|
||||
this.roomName = options.roomName;
|
||||
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
|
||||
|
||||
return JitsiMeetJS.init(config).then(() => {
|
||||
return Promise.all([
|
||||
this.createLocalTracks('audio', 'video'),
|
||||
connect()
|
||||
]);
|
||||
}).then(([tracks, con]) => {
|
||||
console.log('initialized with %s local tracks', tracks.length);
|
||||
localTracks = tracks;
|
||||
connection = con;
|
||||
this._createRoom();
|
||||
$(window).bind('beforeunload', unload );
|
||||
$(window).bind('unload', unload );
|
||||
return new Promise((resolve, reject) => {
|
||||
(new ConferenceConnector(resolve, reject)).connect();
|
||||
});
|
||||
});
|
||||
},
|
||||
createLocalTracks (...devices) {
|
||||
return JitsiMeetJS.createLocalTracks({
|
||||
// copy array to avoid mutations inside library
|
||||
devices: devices.slice(0),
|
||||
resolution: config.resolution
|
||||
}).catch(function (err) {
|
||||
console.error('failed to create local tracks', ...devices, err);
|
||||
APP.statistics.onGetUserMediaFailed(err);
|
||||
return [];
|
||||
});
|
||||
},
|
||||
isLocalId (id) {
|
||||
return this.localId === id;
|
||||
},
|
||||
/**
|
||||
* Simulates toolbar button click for audio mute. Used by shortcuts and API.
|
||||
* @param mute true for mute and false for unmute.
|
||||
*/
|
||||
muteAudio (mute) {
|
||||
//FIXME: Maybe we should create method for that in the UI instead of
|
||||
//accessing directly eventEmitter????
|
||||
APP.UI.eventEmitter.emit(UIEvents.AUDIO_MUTED, mute);
|
||||
},
|
||||
/**
|
||||
* Simulates toolbar button click for audio mute. Used by shortcuts and API.
|
||||
*/
|
||||
toggleAudioMuted () {
|
||||
this.muteAudio(!this.audioMuted);
|
||||
},
|
||||
/**
|
||||
* Simulates toolbar button click for video mute. Used by shortcuts and API.
|
||||
* @param mute true for mute and false for unmute.
|
||||
*/
|
||||
muteVideo (mute) {
|
||||
//FIXME: Maybe we should create method for that in the UI instead of
|
||||
//accessing directly eventEmitter????
|
||||
APP.UI.eventEmitter.emit(UIEvents.VIDEO_MUTED, mute);
|
||||
},
|
||||
/**
|
||||
* Simulates toolbar button click for video mute. Used by shortcuts and API.
|
||||
*/
|
||||
toggleVideoMuted () {
|
||||
this.muteVideo(!this.videoMuted);
|
||||
},
|
||||
listMembers () {
|
||||
return room.getParticipants();
|
||||
},
|
||||
listMembersIds () {
|
||||
return room.getParticipants().map(p => p.getId());
|
||||
},
|
||||
sipGatewayEnabled () {
|
||||
return room.isSIPCallingSupported();
|
||||
},
|
||||
get membersCount () {
|
||||
return room.getParticipants().length; // FIXME maybe +1?
|
||||
},
|
||||
// used by torture currently
|
||||
isJoined () {
|
||||
return this._room
|
||||
&& this._room.isJoined();
|
||||
},
|
||||
getConnectionState () {
|
||||
return this._room
|
||||
&& this._room.getConnectionState();
|
||||
},
|
||||
getMyUserId () {
|
||||
return this._room
|
||||
&& this._room.myUserId();
|
||||
},
|
||||
_createRoom () {
|
||||
room = connection.initJitsiConference(APP.conference.roomName,
|
||||
this._getConferenceOptions());
|
||||
this._room = room; // FIXME do not use this
|
||||
this.localId = room.myUserId();
|
||||
|
||||
let email = APP.settings.getEmail();
|
||||
email && sendEmail(email);
|
||||
|
||||
let nick = APP.settings.getDisplayName();
|
||||
(config.useNicks && !nick) && (() => {
|
||||
nick = APP.UI.askForNickname();
|
||||
APP.settings.setDisplayName(nick);
|
||||
})();
|
||||
nick && room.setDisplayName(nick);
|
||||
|
||||
this._setupListeners();
|
||||
},
|
||||
_getConferenceOptions() {
|
||||
let options = {
|
||||
openSctp: config.openSctp,
|
||||
disableAudioLevels: config.disableAudioLevels
|
||||
};
|
||||
if(config.enableRecording) {
|
||||
options.recordingType = (config.hosts &&
|
||||
(typeof config.hosts.jirecon != "undefined"))?
|
||||
"jirecon" : "colibri";
|
||||
}
|
||||
return options;
|
||||
},
|
||||
_setupListeners () {
|
||||
// add local streams when joined to the conference
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, () => {
|
||||
localTracks.forEach((track) => {
|
||||
if(track.isAudioTrack()) {
|
||||
localAudio = track;
|
||||
}
|
||||
else if (track.isVideoTrack()) {
|
||||
localVideo = track;
|
||||
}
|
||||
addTrack(track);
|
||||
APP.UI.addLocalStream(track);
|
||||
});
|
||||
|
||||
APP.UI.updateAuthInfo(room.isAuthEnabled(), room.getAuthLogin());
|
||||
});
|
||||
|
||||
|
||||
room.on(ConferenceEvents.USER_JOINED, (id, user) => {
|
||||
console.log('USER %s connnected', id, user);
|
||||
// FIXME email???
|
||||
APP.UI.addUser(id, user.getDisplayName());
|
||||
});
|
||||
room.on(ConferenceEvents.USER_LEFT, (id, user) => {
|
||||
console.log('USER %s LEFT', id, user);
|
||||
APP.UI.removeUser(id, user.getDisplayName());
|
||||
APP.UI.stopPrezi(id);
|
||||
});
|
||||
|
||||
|
||||
room.on(ConferenceEvents.USER_ROLE_CHANGED, (id, role) => {
|
||||
if (this.isLocalId(id)) {
|
||||
console.info(`My role changed, new role: ${role}`);
|
||||
this.isModerator = room.isModerator();
|
||||
APP.UI.updateLocalRole(room.isModerator());
|
||||
} else {
|
||||
let user = room.getParticipantById(id);
|
||||
if (user) {
|
||||
APP.UI.updateUserRole(user);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.TRACK_ADDED, (track) => {
|
||||
if(!track || track.isLocal())
|
||||
return;
|
||||
APP.UI.addRemoteStream(track);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.TRACK_REMOVED, (track) => {
|
||||
// FIXME handle
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.TRACK_MUTE_CHANGED, (track) => {
|
||||
if(!track)
|
||||
return;
|
||||
const handler = (track.getType() === "audio")?
|
||||
APP.UI.setAudioMuted : APP.UI.setVideoMuted;
|
||||
let id;
|
||||
const mute = track.isMuted();
|
||||
if(track.isLocal()){
|
||||
id = this.localId;
|
||||
(track.getType() === "audio")?
|
||||
APP.statistics.onAudioMute(mute) :
|
||||
APP.statistics.onVideoMute(mute);
|
||||
} else {
|
||||
id = track.getParticipantId();
|
||||
}
|
||||
handler(id , mute);
|
||||
});
|
||||
room.on(ConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, (id, lvl) => {
|
||||
if(this.isLocalId(id) && localAudio.isMuted()) {
|
||||
lvl = 0;
|
||||
}
|
||||
APP.UI.setAudioLevel(id, lvl);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.IN_LAST_N_CHANGED, (inLastN) => {
|
||||
//FIXME
|
||||
if (config.muteLocalVideoIfNotInLastN) {
|
||||
// TODO mute or unmute if required
|
||||
// mark video on UI
|
||||
// APP.UI.markVideoMuted(true/false);
|
||||
}
|
||||
});
|
||||
room.on(ConferenceEvents.LAST_N_ENDPOINTS_CHANGED, (ids) => {
|
||||
APP.UI.handleLastNEndpoints(ids);
|
||||
});
|
||||
room.on(ConferenceEvents.ACTIVE_SPEAKER_CHANGED, (id) => {
|
||||
APP.UI.markDominantSpiker(id);
|
||||
});
|
||||
|
||||
if (!interfaceConfig.filmStripOnly) {
|
||||
room.on(ConferenceEvents.CONNECTION_INTERRUPTED, () => {
|
||||
APP.UI.markVideoInterrupted(true);
|
||||
});
|
||||
room.on(ConferenceEvents.CONNECTION_RESTORED, () => {
|
||||
APP.UI.markVideoInterrupted(false);
|
||||
});
|
||||
room.on(ConferenceEvents.MESSAGE_RECEIVED, (id, text, ts) => {
|
||||
APP.UI.addMessage(id, getDisplayName(id), text, ts);
|
||||
});
|
||||
}
|
||||
|
||||
room.on(ConferenceEvents.DISPLAY_NAME_CHANGED, (id, displayName) => {
|
||||
APP.UI.changeDisplayName(id, displayName);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.RECORDING_STATE_CHANGED, (status, error) => {
|
||||
if(status == "error") {
|
||||
console.error(error);
|
||||
return;
|
||||
}
|
||||
APP.UI.updateRecordingState(status);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.KICKED, () => {
|
||||
APP.UI.notifyKicked();
|
||||
// FIXME close
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.DTMF_SUPPORT_CHANGED, (isDTMFSupported) => {
|
||||
APP.UI.updateDTMFSupport(isDTMFSupported);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.ROOM_LOCK_CLICKED, () => {
|
||||
if (room.isModerator()) {
|
||||
let promise = roomLocker.isLocked
|
||||
? roomLocker.askToUnlock()
|
||||
: roomLocker.askToLock();
|
||||
promise.then(() => {
|
||||
APP.UI.markRoomLocked(roomLocker.isLocked);
|
||||
});
|
||||
} else {
|
||||
roomLocker.notifyModeratorRequired();
|
||||
}
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.AUDIO_MUTED, (muted) => {
|
||||
(muted)? localAudio.mute() : localAudio.unmute();
|
||||
this.audioMuted = muted;
|
||||
});
|
||||
APP.UI.addListener(UIEvents.VIDEO_MUTED, (muted) => {
|
||||
(muted)? localVideo.mute() : localVideo.unmute();
|
||||
this.videoMuted = muted;
|
||||
});
|
||||
|
||||
if (!interfaceConfig.filmStripOnly) {
|
||||
APP.UI.addListener(UIEvents.MESSAGE_CREATED, (message) => {
|
||||
room.sendTextMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
APP.connectionquality.addListener(
|
||||
CQEvents.LOCALSTATS_UPDATED,
|
||||
(percent, stats) => {
|
||||
APP.UI.updateLocalStats(percent, stats);
|
||||
|
||||
// send local stats to other users
|
||||
room.sendCommandOnce(Commands.CONNECTION_QUALITY, {
|
||||
children: APP.connectionquality.convertToMUCStats(stats),
|
||||
attributes: {
|
||||
xmlns: 'http://jitsi.org/jitmeet/stats'
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
APP.connectionquality.addListener(CQEvents.STOP, () => {
|
||||
APP.UI.hideStats();
|
||||
room.removeCommand(Commands.CONNECTION_QUALITY);
|
||||
});
|
||||
|
||||
// listen to remote stats
|
||||
room.addCommandListener(Commands.CONNECTION_QUALITY,(values, from) => {
|
||||
APP.connectionquality.updateRemoteStats(from, values);
|
||||
});
|
||||
|
||||
APP.connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED,
|
||||
(id, percent, stats) => {
|
||||
APP.UI.updateRemoteStats(id, percent, stats);
|
||||
});
|
||||
|
||||
room.addCommandListener(Commands.ETHERPAD, ({value}) => {
|
||||
APP.UI.initEtherpad(value);
|
||||
});
|
||||
|
||||
room.addCommandListener(Commands.PREZI, ({value, attributes}) => {
|
||||
APP.UI.showPrezi(attributes.id, value, attributes.slide);
|
||||
});
|
||||
|
||||
room.addCommandListener(Commands.STOP_PREZI, ({attributes}) => {
|
||||
APP.UI.stopPrezi(attributes.id);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SHARE_PREZI, (url, slide) => {
|
||||
console.log('Sharing Prezi %s slide %s', url, slide);
|
||||
room.removeCommand(Commands.PREZI);
|
||||
room.sendCommand(Commands.PREZI, {
|
||||
value: url,
|
||||
attributes: {
|
||||
id: room.myUserId(),
|
||||
slide
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.STOP_SHARING_PREZI, () => {
|
||||
room.removeCommand(Commands.PREZI);
|
||||
room.sendCommandOnce(Commands.STOP_PREZI, {
|
||||
attributes: {
|
||||
id: room.myUserId()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
room.addCommandListener(Commands.VIDEO_TYPE, ({value}, from) => {
|
||||
APP.UI.onPeerVideoTypeChanged(from, value);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.EMAIL_CHANGED, (email) => {
|
||||
APP.settings.setEmail(email);
|
||||
APP.UI.setUserAvatar(room.myUserId(), email);
|
||||
sendEmail(email);
|
||||
});
|
||||
room.addCommandListener(Commands.EMAIL, (data) => {
|
||||
APP.UI.setUserAvatar(data.attributes.id, data.value);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.NICKNAME_CHANGED, (nickname) => {
|
||||
APP.settings.setDisplayName(nickname);
|
||||
room.setDisplayName(nickname);
|
||||
APP.UI.changeDisplayName(APP.conference.localId, nickname);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.START_MUTED_CHANGED,
|
||||
(startAudioMuted, startVideoMuted) => {
|
||||
// FIXME start muted
|
||||
}
|
||||
);
|
||||
|
||||
APP.UI.addListener(UIEvents.USER_INVITED, (roomUrl) => {
|
||||
APP.UI.inviteParticipants(
|
||||
roomUrl,
|
||||
APP.conference.roomName,
|
||||
roomLocker.password,
|
||||
APP.settings.getDisplayName()
|
||||
);
|
||||
});
|
||||
|
||||
// call hangup
|
||||
APP.UI.addListener(UIEvents.HANGUP, () => {
|
||||
APP.UI.requestFeedback().then(() => {
|
||||
connection.disconnect();
|
||||
config.enableWelcomePage && setTimeout(() => {
|
||||
window.localStorage.welcomePageDisabled = false;
|
||||
window.location.pathname = "/";
|
||||
}, 3000);
|
||||
}, (err) => {console.error(err);});
|
||||
});
|
||||
|
||||
// logout
|
||||
APP.UI.addListener(UIEvents.LOGOUT, () => {
|
||||
// FIXME handle logout
|
||||
// APP.xmpp.logout(function (url) {
|
||||
// if (url) {
|
||||
// window.location.href = url;
|
||||
// } else {
|
||||
// hangup();
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SIP_DIAL, (sipNumber) => {
|
||||
room.dial(sipNumber);
|
||||
});
|
||||
|
||||
|
||||
// Starts or stops the recording for the conference.
|
||||
APP.UI.addListener(UIEvents.RECORDING_TOGGLE, (predefinedToken) => {
|
||||
if (predefinedToken) {
|
||||
room.toggleRecording({token: predefinedToken});
|
||||
return;
|
||||
}
|
||||
APP.UI.requestRecordingToken().then((token) => {
|
||||
room.toggleRecording({token: token});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.TOPIC_CHANGED, (topic) => {
|
||||
// FIXME handle topic change
|
||||
// APP.xmpp.setSubject(topic);
|
||||
// on SUBJECT_CHANGED UI.setSubject(topic);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.USER_KICKED, (id) => {
|
||||
room.kickParticipant(id);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.REMOTE_AUDIO_MUTED, (id) => {
|
||||
room.muteParticipant(id);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.AUTH_CLICKED, () => {
|
||||
AuthHandler.authenticate(room);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, (id) => {
|
||||
room.selectParticipant(id);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.TOGGLE_SCREENSHARING, () => {
|
||||
APP.desktopsharing.toggleScreenSharing();
|
||||
});
|
||||
|
||||
APP.UI.addListener(DSEvents.SWITCHING_DONE, (isSharingScreen) => {
|
||||
APP.UI.updateDesktopSharingButtons(isSharingScreen);
|
||||
});
|
||||
|
||||
APP.desktopsharing.addListener(DSEvents.NEW_STREAM_CREATED,
|
||||
(track, callback) => {
|
||||
const localCallback = (newTrack) => {
|
||||
if(!newTrack)
|
||||
return;
|
||||
if (newTrack.isLocal() && newTrack === localVideo) {
|
||||
if(localVideo.isMuted() &&
|
||||
localVideo.videoType !== track.videoType) {
|
||||
localVideo.mute();
|
||||
}
|
||||
callback();
|
||||
room.off(ConferenceEvents.TRACK_ADDED, localCallback);
|
||||
}
|
||||
};
|
||||
|
||||
room.on(ConferenceEvents.TRACK_ADDED, localCallback);
|
||||
localVideo.stop();
|
||||
localVideo = track;
|
||||
addTrack(track);
|
||||
APP.UI.addLocalStream(track);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
/* global APP, JitsiMeetJS, config */
|
||||
|
||||
import LoginDialog from './UI/authentication/LoginDialog';
|
||||
//FIXME:
|
||||
import LoginDialog from './modules/UI/authentication/LoginDialog';
|
||||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
|
@ -13,7 +13,7 @@
|
|||
<script>console.log("(TIME) index.html loaded:\t", window.performance.now());</script>
|
||||
<script src="config.js?v=15"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||
<script src="interface_config.js?v=6"></script>
|
||||
<script src="lib-jitsi-meet.js?v=139"></script>
|
||||
<script src="libs/lib-jitsi-meet.js?v=139"></script>
|
||||
<script src="libs/app.bundle.min.js?v=139"></script>
|
||||
<!--
|
||||
Link used for inline installation of chrome desktop streaming extension,
|
||||
|
|
|
@ -2250,7 +2250,7 @@ RTC.prototype.createRemoteStream = function (data, sid, thessrc) {
|
|||
var remoteStream = new JitsiRemoteTrack(this, data, sid, thessrc);
|
||||
if(!data.peerjid)
|
||||
return;
|
||||
var jid = data.peerjid;
|
||||
var jid = Strophe.getResourceFromJid(data.peerjid);
|
||||
if(!this.remoteStreams[jid]) {
|
||||
this.remoteStreams[jid] = {};
|
||||
}
|
||||
|
@ -2337,8 +2337,11 @@ RTC.prototype.switchVideoStreams = function (newStream) {
|
|||
};
|
||||
|
||||
RTC.prototype.setAudioLevel = function (jid, audioLevel) {
|
||||
if(this.remoteStreams[jid] && this.remoteStreams[jid][JitsiTrack.AUDIO])
|
||||
this.remoteStreams[jid][JitsiTrack.AUDIO].setAudioLevel(audioLevel);
|
||||
if(!jid)
|
||||
return;
|
||||
var resource = Strophe.getResourceFromJid(jid);
|
||||
if(this.remoteStreams[resource] && this.remoteStreams[resource][JitsiTrack.AUDIO])
|
||||
this.remoteStreams[resource][JitsiTrack.AUDIO].setAudioLevel(audioLevel);
|
||||
}
|
||||
module.exports = RTC;
|
||||
|
||||
|
|
|
@ -382,7 +382,8 @@ UI.removeUser = function (id, displayName) {
|
|||
displayName,'notify.somebody', 'disconnected', 'notify.disconnected'
|
||||
);
|
||||
|
||||
if (!config.startAudioMuted || config.startAudioMuted > APP.conference.membersCount) {
|
||||
if (!config.startAudioMuted
|
||||
|| config.startAudioMuted > APP.conference.membersCount) {
|
||||
UIUtil.playSoundNotification('userLeft');
|
||||
}
|
||||
|
||||
|
@ -504,15 +505,22 @@ UI.askForNickname = function () {
|
|||
};
|
||||
|
||||
/**
|
||||
* Sets muted audio state for the local participant.
|
||||
* Sets muted audio state for participant
|
||||
*/
|
||||
UI.setAudioMuted = function (mute) {
|
||||
VideoLayout.showLocalAudioIndicator(mute);
|
||||
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
|
||||
UI.setAudioMuted = function (id, muted) {
|
||||
VideoLayout.onAudioMute(id, muted);
|
||||
if(APP.conference.isLocalId(id))
|
||||
UIUtil.buttonClick("#toolbar_button_mute",
|
||||
"icon-microphone icon-mic-disabled");
|
||||
};
|
||||
|
||||
UI.setVideoMuted = function (muted) {
|
||||
$('#toolbar_button_camera').toggleClass("icon-camera-disabled", muted);
|
||||
/**
|
||||
* Sets muted video state for participant
|
||||
*/
|
||||
UI.setVideoMuted = function (id, muted) {
|
||||
VideoLayout.onVideoMute(id, muted);
|
||||
if(APP.conference.isLocalId(id))
|
||||
$('#toolbar_button_camera').toggleClass("icon-camera-disabled", muted);
|
||||
};
|
||||
|
||||
UI.addListener = function (type, listener) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* global JitsiMeetJS, APP */
|
||||
|
||||
import LoginDialog from './UI/authentication/LoginDialog';
|
||||
import UIEvents from '../service/UI/UIEvents';
|
||||
import UIUtil from './UI/util/UIUtil';
|
||||
import {openConnection} from './connection';
|
||||
import LoginDialog from './LoginDialog';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import {openConnection} from '../../../connection';
|
||||
|
||||
const ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
/* global APP, JitsiMeetJS */
|
||||
import messageHandler from './UI/util/MessageHandler';
|
||||
import UIUtil from './UI/util/UIUtil';
|
||||
import AnalyticsAdapter from './statistics/AnalyticsAdapter';
|
||||
import messageHandler from '../util/MessageHandler';
|
||||
import UIUtil from '../util/UIUtil';
|
||||
//FIXME:
|
||||
import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
|
||||
|
||||
function askForNewPassword () {
|
||||
let passMsg = APP.translation.generateTranslationHTML("dialog.passwordMsg");
|
|
@ -11,6 +11,8 @@ const RTCBrowserType = require("../../RTC/RTCBrowserType");
|
|||
const avatarSize = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE;
|
||||
|
||||
function getStreamId(stream) {
|
||||
if(!stream)
|
||||
return;
|
||||
if (stream.isLocal()) {
|
||||
return APP.conference.localId;
|
||||
} else {
|
||||
|
|
|
@ -7,6 +7,8 @@ import SmallVideo from "./SmallVideo";
|
|||
var LargeVideo = require("./LargeVideo");
|
||||
var RTCBrowserType = require("../../RTC/RTCBrowserType");
|
||||
|
||||
const TrackEvents = JitsiMeetJS.events.track;
|
||||
|
||||
function LocalVideo(VideoLayout, emitter) {
|
||||
this.videoSpanId = "localVideoContainer";
|
||||
this.container = $("#localVideoContainer").get(0);
|
||||
|
@ -187,18 +189,13 @@ LocalVideo.prototype.changeVideo = function (stream) {
|
|||
// Attach WebRTC stream
|
||||
stream.attach(localVideoSelector);
|
||||
|
||||
// FIXME handle
|
||||
return;
|
||||
|
||||
// Add stream ended handler
|
||||
/**APP.RTC.addMediaStreamInactiveHandler(
|
||||
stream.getOriginalStream(), function () {
|
||||
// We have to re-select after attach when Temasys plugin is used,
|
||||
// because <video> element is replaced with <object>
|
||||
let endedHandler = () => {
|
||||
localVideo = $('#' + localVideo.id)[0];
|
||||
localVideoContainer.removeChild(localVideo);
|
||||
self.VideoLayout.updateRemovedVideo(self.id);
|
||||
});*/
|
||||
stream.off(TrackEvents.TRACK_STOPPED, endedHandler);
|
||||
};
|
||||
stream.on(TrackEvents.TRACK_STOPPED, endedHandler);
|
||||
};
|
||||
|
||||
LocalVideo.prototype.joined = function (id) {
|
||||
|
|
|
@ -128,7 +128,7 @@ var VideoLayout = {
|
|||
let localAudio = document.getElementById('localAudio');
|
||||
stream.attach($(localAudio));
|
||||
|
||||
return; // FIXME maybe move this into the library?
|
||||
//return; // FIXME maybe move this into the library?
|
||||
// Writing volume not allowed in IE
|
||||
if (!RTCBrowserType.isIExplorer()) {
|
||||
localAudio.autoplay = true;
|
||||
|
@ -253,7 +253,6 @@ var VideoLayout = {
|
|||
|
||||
onRemoteStreamAdded (stream) {
|
||||
let id = stream.getParticipantId();
|
||||
|
||||
remoteVideos[id].addRemoteStreamElement(stream);
|
||||
},
|
||||
|
||||
|
@ -475,14 +474,13 @@ var VideoLayout = {
|
|||
/**
|
||||
* On audio muted event.
|
||||
*/
|
||||
onAudioMute (jid, isMuted) {
|
||||
var resourceJid = Strophe.getResourceFromJid(jid);
|
||||
if (resourceJid === APP.xmpp.myResource()) {
|
||||
onAudioMute (id, isMuted) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
localVideoThumbnail.showAudioIndicator(isMuted);
|
||||
} else {
|
||||
remoteVideos[resourceJid].showAudioIndicator(isMuted);
|
||||
if (APP.xmpp.isModerator()) {
|
||||
remoteVideos[resourceJid].updateRemoteVideoMenu(isMuted);
|
||||
remoteVideos[id].showAudioIndicator(isMuted);
|
||||
if (APP.conference.isModerator) {
|
||||
remoteVideos[id].updateRemoteVideoMenu(isMuted);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -490,17 +488,11 @@ var VideoLayout = {
|
|||
/**
|
||||
* On video muted event.
|
||||
*/
|
||||
onVideoMute (jid, value) {
|
||||
if (jid !== APP.xmpp.myJid() &&
|
||||
!APP.RTC.muteRemoteVideoStream(jid, value))
|
||||
return;
|
||||
|
||||
if (jid === APP.xmpp.myJid()) {
|
||||
onVideoMute (id, value) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
localVideoThumbnail.showVideoIndicator(value);
|
||||
} else {
|
||||
var resource = Strophe.getResourceFromJid(jid);
|
||||
|
||||
var remoteVideo = remoteVideos[resource];
|
||||
var remoteVideo = remoteVideos[id];
|
||||
remoteVideo.showVideoIndicator(value);
|
||||
|
||||
var el = remoteVideo.selectVideoElement();
|
||||
|
@ -528,11 +520,7 @@ var VideoLayout = {
|
|||
*/
|
||||
onDominantSpeakerChanged (id) {
|
||||
// We ignore local user events.
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (id === currentDominantSpeaker) {
|
||||
if (APP.conference.isLocalId(id) || (id === currentDominantSpeaker)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -623,7 +611,7 @@ var VideoLayout = {
|
|||
// video
|
||||
// Detected from avatar tests, where lastN event override
|
||||
// local video pinning
|
||||
if(resourceJid == APP.xmpp.myResource())
|
||||
if(APP.conference.isLocalId(resourceJid))
|
||||
return;
|
||||
|
||||
var isReceived = true;
|
||||
|
@ -633,7 +621,7 @@ var VideoLayout = {
|
|||
console.log("Remove from last N", resourceJid);
|
||||
if (remoteVideos[resourceJid])
|
||||
remoteVideos[resourceJid].showPeerContainer('hide');
|
||||
else if (APP.xmpp.myResource() !== resourceJid)
|
||||
else if (!APP.conference.isLocalId(resourceJid))
|
||||
console.error("No remote video for: " + resourceJid);
|
||||
isReceived = false;
|
||||
} else if (resourceJid &&
|
||||
|
@ -642,7 +630,7 @@ var VideoLayout = {
|
|||
localLastNSet.indexOf(resourceJid) >= 0) {
|
||||
if (remoteVideos[resourceJid])
|
||||
remoteVideos[resourceJid].showPeerContainer('avatar');
|
||||
else if (APP.xmpp.myResource() !== resourceJid)
|
||||
else if (!APP.conference.isLocalId(resourceJid))
|
||||
console.error("No remote video for: " + resourceJid);
|
||||
isReceived = false;
|
||||
}
|
||||
|
@ -701,13 +689,10 @@ var VideoLayout = {
|
|||
|
||||
if (updateLargeVideo) {
|
||||
var resource;
|
||||
var myResource
|
||||
= APP.xmpp.myResource();
|
||||
|
||||
// Find out which endpoint to show in the large video.
|
||||
for (i = 0; i < lastNEndpoints.length; i++) {
|
||||
resource = lastNEndpoints[i];
|
||||
if (!resource || resource === myResource)
|
||||
if (!resource || APP.conference.isLocalId(resource))
|
||||
continue;
|
||||
|
||||
// videoSrcToSsrc needs to be update for this call to succeed.
|
||||
|
|
Loading…
Reference in New Issue