-
Notifications
You must be signed in to change notification settings - Fork 448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Select media device for video and audio input #1450
Changes from all commits
3366fd3
c05c791
a61f9bc
d606418
7cca819
3dc46b5
748eeee
834cd7c
a10b969
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,6 +218,106 @@ | |
}.bind(this)); | ||
}, | ||
|
||
onAudioOutputChange: function() { | ||
localStorage.setItem('audioOutput', $('#audioOutput').val()); | ||
|
||
}, | ||
|
||
onAudioSourceChange: function() { | ||
localStorage.setItem("audioSource", $('#audioSource').val()); | ||
Peterede marked this conversation as resolved.
Show resolved
Hide resolved
|
||
OCA.SpreedMe.app.setMediaSource(localStorage.getItem("audioSource"), localStorage.getItem("videoSource")); | ||
}, | ||
|
||
onVideoSourceChange: function() { | ||
localStorage.setItem("videoSource", $('#videoSource').val()); | ||
OCA.SpreedMe.app.setMediaSource(localStorage.getItem("audioSource"), localStorage.getItem("videoSource")); | ||
}, | ||
|
||
initMediaSources: function() { | ||
OCA.SpreedMe.app.setMediaSource(localStorage.getItem("audioSource"), localStorage.getItem("videoSource")); | ||
}, | ||
|
||
setMediaSource: function(audioSource, videoSource) { | ||
|
||
if (typeof OCA.SpreedMe.webrtc !== 'undefined') { | ||
OCA.SpreedMe.webrtc.config.media = { | ||
audio: { | ||
optional: [{sourceId: audioSource}] | ||
}, | ||
video: { | ||
optional: [{sourceId: videoSource}] | ||
} | ||
}; | ||
} | ||
|
||
if (OCA.SpreedMe.app.signaling.currentCallToken !== null) { | ||
this.changingMedia = true; | ||
OCA.SpreedMe.app.signaling.leaveCurrentCall(); | ||
OCA.SpreedMe.webrtc.stopLocalVideo(); | ||
|
||
OCA.SpreedMe.webrtc.startLocalVideo(OCA.SpreedMe.webrtc.config.media); | ||
OCA.SpreedMe.app.connection.joinCall(this.activeRoom.get('token')); | ||
|
||
/*var senders = existingPeer.pc.getLocalStreams(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the code is not needed remove it. |
||
for (var i = 0; i < senders.length; i++) { | ||
existingPeer.pc.removeStream(senders[i]); | ||
} | ||
OCA.SpreedMe.webrtc.on('localStream', function() { | ||
senders = this.webrtc.localStreams; | ||
var localStreams = existingPeer.pc.getLocalStreams(); | ||
for (var i = 0; i < senders.length; i++) { | ||
if (!localStreams.includes(senders[i])) { | ||
existingPeer.pc.addStream(senders[i]); | ||
} | ||
} | ||
});*/ | ||
} | ||
}, | ||
|
||
startShareScreen: function(mode) { | ||
var webrtc = OCA.SpreedMe.webrtc; | ||
var screensharingButton = $('#screensharing-button'); | ||
screensharingButton.prop('disabled', true); | ||
webrtc.shareScreen(mode, function(err) { | ||
screensharingButton.prop('disabled', false); | ||
if (!err) { | ||
$('#screensharing-button').attr('data-original-title', t('spreed', 'Screensharing options')) | ||
.removeClass('screensharing-disabled icon-screen-off') | ||
.addClass('icon-screen'); | ||
return; | ||
} | ||
switch (err.name) { | ||
case "HTTPS_REQUIRED": | ||
OC.Notification.showTemporary(t('spreed', 'Screensharing requires the page to be loaded through HTTPS.')); | ||
break; | ||
case "PERMISSION_DENIED": | ||
case "NotAllowedError": | ||
case "CEF_GETSCREENMEDIA_CANCELED": // Experimental, may go away in the future. | ||
break; | ||
case "FF52_REQUIRED": | ||
OC.Notification.showTemporary(t('spreed', 'Sharing your screen only works with Firefox version 52 or newer.')); | ||
break; | ||
case "EXTENSION_UNAVAILABLE": | ||
var extensionURL = null; | ||
if (!!window.chrome && !!window.chrome.webstore) {// Chrome | ||
extensionURL = 'https://chrome.google.com/webstore/detail/screensharing-for-nextclo/kepnpjhambipllfmgmbapncekcmabkol'; | ||
} | ||
if (extensionURL) { | ||
var text = t('spreed', 'Screensharing extension is required to share your screen.'); | ||
var element = $('<a>').attr('href', extensionURL).attr('target','_blank').text(text); | ||
OC.Notification.showTemporary(element, {isHTML: true}); | ||
} else { | ||
OC.Notification.showTemporary(t('spreed', 'Please use a different browser like Firefox or Chrome to share your screen.')); | ||
} | ||
break; | ||
default: | ||
OC.Notification.showTemporary(t('spreed', 'An error occurred while starting screensharing.')); | ||
console.log("Could not start screensharing", err); | ||
break; | ||
} | ||
}); | ||
}, | ||
|
||
_onKeyUp: function(event) { | ||
// Define which objects to check for the event properties. | ||
var key = event.which; | ||
|
@@ -363,6 +463,11 @@ | |
return; | ||
} | ||
|
||
if (this.changingMedia) { | ||
this.changingMedia = false; | ||
return; | ||
} | ||
|
||
var flags = this.activeRoom.get('participantFlags') || 0; | ||
var inCall = flags & OCA.SpreedMe.app.FLAG_IN_CALL !== 0; | ||
if (inCall && this._chatViewInMainView === true) { | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -71,8 +71,33 @@ | |||
' <div class="clipboard-button"><span class="button icon-clippy"></span></div>' + | ||||
' </div>' + | ||||
'{{/if}}' + | ||||
'<div class="talk-settings-button">' + | ||||
' <span class="button icon-settings"></span>' + | ||||
'</div>' + | ||||
'</div>' + | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
invalid HTML structure |
||||
'<div class="settings-menu hidden">' + | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this should be in the callinfo-section, as it is not specific to the conversation, but in general? Maybe it's time for us to start using the settings feature in the left sidebar. However I'm not sure we should go through the trouble, when we can do this easily after switching to Vue.JS ( #1347 ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is specific to the conversation just like the 'join call' button, the settings are used directly when joining the call and affect how the call appears and sounds. Putting the settings in the left sidebar might make them less obvious (and also I force the left sidebar to be hidden), the more exposed the camera, microphone and speaker settings are the better as this affects the user experience. If when the user connects their microphone is not working or their video is not working then the camera and microphone settings should be the first thing they check. |
||||
' <form class="settings-form">' + | ||||
' {{#if canPublish}}' + | ||||
' <div>' + | ||||
' <span class="menuitem icon-video settings-option">' + | ||||
' </span>' + | ||||
' <select id="videoSource" class="settings-input"></select>'+ | ||||
' </div>' + | ||||
' <div>' + | ||||
' <span class="menuitem icon-audio settings-option">' + | ||||
' </span>' + | ||||
' <select id="audioSource" class="settings-input"></select>'+ | ||||
' </div>' + | ||||
' {{/if}}' + | ||||
' <div>' + | ||||
' <span class="menuitem icon-speaker settings-option">' + | ||||
' </span>' + | ||||
' <select id="audioOutput" class="settings-input"></select>'+ | ||||
' </div>' + | ||||
' </form>' + | ||||
'</div>'; | ||||
|
||||
|
||||
var CallInfoView = Marionette.View.extend({ | ||||
|
||||
tagName: 'div', | ||||
|
@@ -91,6 +116,7 @@ | |||
canFullModerate: this._canFullModerate(), | ||||
isPublic: this.model.get('type') === 3, | ||||
showShareLink: !canModerate && this.model.get('type') === 3, | ||||
canPublish: OCA.SpreedMe.canPublish(), | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is from another pull request #1298 |
||||
isDeletable: canModerate && (Object.keys(this.model.get('participants')).length > 2 || this.model.get('numGuests') > 0) | ||||
}); | ||||
}, | ||||
|
@@ -112,6 +138,10 @@ | |||
'passwordConfirm': '.password-confirm', | ||||
|
||||
'menu': '.password-menu', | ||||
|
||||
'settingsButton': '.talk-settings-button', | ||||
'settingsMenu': '.settings-menu', | ||||
'settingsInput': '.settings-input', | ||||
}, | ||||
|
||||
regions: { | ||||
|
@@ -126,6 +156,7 @@ | |||
'click @ui.passwordButton': 'showPasswordInput', | ||||
'click @ui.passwordConfirm': 'confirmPassword', | ||||
'submit @ui.passwordForm': 'confirmPassword', | ||||
'click @ui.settingsButton': 'settingsButtonClicked', | ||||
}, | ||||
|
||||
modelEvents: { | ||||
|
@@ -242,6 +273,82 @@ | |||
$(self.ui.passwordInput).focus(); | ||||
}); | ||||
|
||||
this.initSettings(); | ||||
|
||||
}, | ||||
|
||||
gotSources: function(sourceInfos) { | ||||
var audioSelect = document.querySelector("select#audioSource"); | ||||
var videoSelect = document.querySelector("select#videoSource"); | ||||
var outputSelect = document.querySelector("select#audioOutput"); | ||||
|
||||
// clear the lists | ||||
$('#audioOutput').empty(); | ||||
$('#audioSource').empty(); | ||||
$('#videoSource').empty(); | ||||
|
||||
for (var i = 0; i != sourceInfos.length; ++i) { | ||||
var sourceInfo = sourceInfos[i]; | ||||
var option = document.createElement("option"); | ||||
option.value = sourceInfo.deviceId; | ||||
if (sourceInfo.kind === 'audioinput' && audioSelect !== null) { | ||||
option.text = sourceInfo.label || 'microphone ' + (audioSelect.length + 1); | ||||
audioSelect.appendChild(option); | ||||
} else if (sourceInfo.kind === 'videoinput' && videoSelect !== null) { | ||||
option.text = sourceInfo.label || 'camera ' + (videoSelect.length + 1); | ||||
videoSelect.appendChild(option); | ||||
} else if (sourceInfo.kind === 'audiooutput') { | ||||
option.text = sourceInfo.label || 'speaker ' + (outputSelect.length + 1); | ||||
outputSelect.appendChild(option); | ||||
} | ||||
} | ||||
|
||||
// hide empty options | ||||
if ($('#audioOutput option').length === 0) { | ||||
var option = document.createElement("option"); | ||||
option.value = sourceInfo.deviceId; | ||||
option.text = 'Default'; | ||||
outputSelect.appendChild(option); | ||||
} | ||||
else { | ||||
var val = localStorage.getItem("audioOutput"); | ||||
if (val !== null) { | ||||
$('#audioOutput').val(val); | ||||
} | ||||
outputSelect.onchange = OCA.SpreedMe.app.onAudioOutputChange; | ||||
} | ||||
|
||||
if ($('#videoSource option').length === 0) { | ||||
$('#videoSource').hide(); | ||||
} | ||||
else { | ||||
var val = localStorage.getItem("videoSource"); | ||||
if (val !== null) { | ||||
$('#videoSource').val(val); | ||||
} | ||||
videoSelect.onchange = OCA.SpreedMe.app.onVideoSourceChange; | ||||
} | ||||
|
||||
if ($('#audioSource option').length === 0) { | ||||
$('#audioSource').hide(); | ||||
} | ||||
else { | ||||
var val = localStorage.getItem("audioSource"); | ||||
if (val !== null) { | ||||
$('#audioSource').val(val); | ||||
} | ||||
audioSelect.onchange = OCA.SpreedMe.app.onAudioSourceChange; | ||||
} | ||||
|
||||
}, | ||||
|
||||
initSettings: function() { | ||||
navigator.mediaDevices.enumerateDevices().then(this.gotSources); | ||||
}, | ||||
|
||||
settingsButtonClicked: function(e) { | ||||
e.preventDefault(); | ||||
$('.settings-menu').toggle(); | ||||
}, | ||||
|
||||
_canModerate: function() { | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should have the same size as all other icons