Skip to content

Commit

Permalink
Merge pull request jitsi#492 from isymchych/device-selection
Browse files Browse the repository at this point in the history
Allow user to select camera and microphone
  • Loading branch information
paweldomas committed Feb 10, 2016
2 parents b4b9160 + f65d630 commit 61f4bb6
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 59 deletions.
145 changes: 105 additions & 40 deletions conference.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const ConferenceErrors = JitsiMeetJS.errors.conference;
const TrackEvents = JitsiMeetJS.events.track;
const TrackErrors = JitsiMeetJS.errors.track;

let room, connection, localTracks, localAudio, localVideo, roomLocker;
let room, connection, localAudio, localVideo, roomLocker;

/**
* Known custom conference commands.
Expand Down Expand Up @@ -120,6 +120,8 @@ function createLocalTracks (...devices) {
// copy array to avoid mutations inside library
devices: devices.slice(0),
resolution: config.resolution,
cameraDeviceId: APP.settings.getCameraDeviceId(),
micDeviceId: APP.settings.getMicDeviceId(),
// adds any ff fake device settings if any
firefox_fake_device: config.firefox_fake_device
}).catch(function (err) {
Expand Down Expand Up @@ -293,11 +295,19 @@ export default {
]);
}).then(([tracks, con]) => {
console.log('initialized with %s local tracks', tracks.length);
localTracks = tracks;
connection = con;
this._createRoom();
this._createRoom(tracks);
this.isDesktopSharingEnabled =
JitsiMeetJS.isDesktopSharingEnabled();

// update list of available devices
if (JitsiMeetJS.isDeviceListAvailable() &&
JitsiMeetJS.isDeviceChangeAvailable()) {
JitsiMeetJS.enumerateDevices((devices) => {
this.availableDevices = devices;
APP.UI.onAvailableDevicesChanged();
});
}
// XXX The API will take care of disconnecting from the XMPP server
// (and, thus, leaving the room) on unload.
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -360,6 +370,10 @@ export default {
listMembersIds () {
return room.getParticipants().map(p => p.getId());
},
/**
* List of available cameras and microphones.
*/
availableDevices: [],
/**
* Check if SIP is supported.
* @returns {boolean}
Expand Down Expand Up @@ -449,32 +463,30 @@ export default {
getLogs () {
return room.getLogs();
},
_createRoom () {
_createRoom (localTracks) {
room = connection.initJitsiConference(APP.conference.roomName,
this._getConferenceOptions());
this.localId = room.myUserId();
localTracks.forEach((track) => {
if(track.isAudioTrack()) {
localAudio = track;
}
else if (track.isVideoTrack()) {
localVideo = track;
}
room.addTrack(track);
APP.UI.addLocalStream(track);

if (track.isAudioTrack()) {
this.useAudioStream(track);
} else if (track.isVideoTrack()) {
this.useVideoStream(track);
}
});
roomLocker = createRoomLocker(room);
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) && (() => {
if (config.useNicks && !nick) {
nick = APP.UI.askForNickname();
APP.settings.setDisplayName(nick);
})();
}
nick && room.setDisplayName(nick);

this._setupListeners();
Expand All @@ -489,6 +501,55 @@ export default {
return options;
},

/**
* Start using provided video stream.
* Stops previous video stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null
*/
useVideoStream (stream) {
if (localVideo) {
localVideo.stop();
}
localVideo = stream;

if (stream) {
this.videoMuted = stream.isMuted();

APP.UI.addLocalStream(stream);

this.isSharingScreen = stream.videoType === 'desktop';
} else {
this.videoMuted = false;
this.isSharingScreen = false;
}

APP.UI.setVideoMuted(this.localId, this.videoMuted);

APP.UI.updateDesktopSharingButtons();
},

/**
* Start using provided audio stream.
* Stops previous audio stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null
*/
useAudioStream (stream) {
if (localAudio) {
localAudio.stop();
}
localAudio = stream;

if (stream) {
this.audioMuted = stream.isMuted();

APP.UI.addLocalStream(stream);
} else {
this.audioMuted = false;
}

APP.UI.setAudioMuted(this.localId, this.audioMuted);
},

videoSwitchInProgress: false,
toggleScreenSharing () {
if (this.videoSwitchInProgress) {
Expand All @@ -507,22 +568,13 @@ export default {
createLocalTracks('video').then(function ([stream]) {
return room.addTrack(stream);
}).then((stream) => {
if (localVideo) {
localVideo.stop();
}
localVideo = stream;
this.videoMuted = stream.isMuted();
APP.UI.setVideoMuted(this.localId, this.videoMuted);

APP.UI.addLocalStream(stream);
this.useVideoStream(stream);
this.videoSwitchInProgress = false;
console.log('sharing local video');
}).catch((err) => {
localVideo = null;
console.error('failed to share local video', err);
}).then(() => {
}).catch(function (err) {
this.useVideoStream(null);
this.videoSwitchInProgress = false;
this.isSharingScreen = false;
APP.UI.updateDesktopSharingButtons();
console.error('failed to share local video', err);
});
} else {
// stop sharing video and share desktop
Expand All @@ -541,19 +593,8 @@ export default {
);
return room.addTrack(stream);
}).then((stream) => {
if (localVideo) {
localVideo.stop();
}
localVideo = stream;

this.videoMuted = stream.isMuted();
APP.UI.setVideoMuted(this.localId, this.videoMuted);

APP.UI.addLocalStream(stream);

this.useVideoStream(stream);
this.videoSwitchInProgress = false;
this.isSharingScreen = true;
APP.UI.updateDesktopSharingButtons();
console.log('sharing local desktop');
}).catch((err) => {
this.videoSwitchInProgress = false;
Expand Down Expand Up @@ -907,6 +948,30 @@ export default {
room.pinParticipant(id);
});

APP.UI.addListener(
UIEvents.VIDEO_DEVICE_CHANGED,
(cameraDeviceId) => {
APP.settings.setCameraDeviceId(cameraDeviceId);
createLocalTracks('video').then(([stream]) => {
room.addTrack(stream);
this.useVideoStream(stream);
console.log('switched local video device');
});
}
);

APP.UI.addListener(
UIEvents.AUDIO_DEVICE_CHANGED,
(micDeviceId) => {
APP.settings.setMicDeviceId(micDeviceId);
createLocalTracks('audio').then(([stream]) => {
room.addTrack(stream);
this.useAudioStream(stream);
console.log('switched local audio device');
});
}
);

APP.UI.addListener(
UIEvents.TOGGLE_SCREENSHARING, this.toggleScreenSharing.bind(this)
);
Expand Down
22 changes: 22 additions & 0 deletions css/settingsmenu.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#settingsmenu {
background: black;
color: #00ccff;
overflow-y: auto;
}

#settingsmenu input, select {
Expand Down Expand Up @@ -52,6 +53,10 @@
#startMutedOptions {
padding-left: 10%;
text-indent: -10%;

/* clearfix */
overflow: auto;
zoom: 1;
}

#startAudioMuted {
Expand All @@ -66,3 +71,20 @@
width: 94%;
float: left;
}

#devicesOptions {
display: none;
}

#devicesOptions label {
display: block;
margin-top: 15px;
}

#devicesOptions span {
padding-left: 10%;
}

#devicesOptions select {
height: 40px;
}
10 changes: 10 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,16 @@
<span data-i18n="settings.startVideoMuted"></span>
</label>
</div>
<div id="devicesOptions">
<label className="devicesOptionsLabel">
<span data-i18n="settings.selectCamera"></span>
<select id="selectCamera"></select>
</label>
<label className="devicesOptionsLabel">
<span data-i18n="settings.selectMic"></span>
<select id="selectMic"></select>
</label>
</div>
<button id="updateSettings" data-i18n="settings.update"></button>
<a id="downloadlog" data-container="body" data-toggle="popover" data-placement="right" data-i18n="[data-content]downloadlogs" ><i class="fa fa-cloud-download"></i></a>
</div>
Expand Down
4 changes: 3 additions & 1 deletion lang/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@
"update": "Update",
"name": "Name",
"startAudioMuted": "start without audio",
"startVideoMuted": "start without video"
"startVideoMuted": "start without video",
"selectCamera": "select camera",
"selectMic": "select microphone"
},
"videothumbnail":
{
Expand Down
19 changes: 14 additions & 5 deletions modules/UI/UI.js
Original file line number Diff line number Diff line change
Expand Up @@ -660,18 +660,19 @@ UI.askForNickname = function () {
*/
UI.setAudioMuted = function (id, muted) {
VideoLayout.onAudioMute(id, muted);
if(APP.conference.isLocalId(id))
UIUtil.buttonClick("#toolbar_button_mute",
"icon-microphone icon-mic-disabled");
if (APP.conference.isLocalId(id)) {
Toolbar.markAudioIconAsMuted(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);
if (APP.conference.isLocalId(id)) {
Toolbar.markVideoIconAsMuted(muted);
}
};

UI.addListener = function (type, listener) {
Expand Down Expand Up @@ -1040,6 +1041,14 @@ UI.onStartMutedChanged = function () {
SettingsMenu.onStartMutedChanged();
};

/**
* Update list of available physical devices.
* @param {object[]} devices new list of available devices
*/
UI.onAvailableDevicesChanged = function (devices) {
SettingsMenu.onAvailableDevicesChanged(devices);
};

/**
* Returns the id of the current video shown on large.
* Currently used by tests (torture).
Expand Down
Loading

0 comments on commit 61f4bb6

Please sign in to comment.