Browse Source
Merge pull request #4023 from nextcloud/make-possible-to-select-input-media-devices-during-calls
Merge pull request #4023 from nextcloud/make-possible-to-select-input-media-devices-during-calls
Make possible to select input media devices during callspull/4036/head
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 762 additions and 62 deletions
-
4src/components/MediaDevicesPreview.vue
-
114src/utils/webrtc/MediaDevicesManager.js
-
2src/utils/webrtc/index.js
-
40src/utils/webrtc/models/LocalMediaModel.js
-
113src/utils/webrtc/shims/MediaStream.js
-
99src/utils/webrtc/shims/MediaStreamTrack.js
-
341src/utils/webrtc/simplewebrtc/localmedia.js
-
58src/utils/webrtc/simplewebrtc/peer.js
-
53src/utils/webrtc/webrtc.js
@ -0,0 +1,113 @@ |
|||
/** |
|||
* |
|||
* @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
* |
|||
*/ |
|||
|
|||
if (window.MediaStream) { |
|||
const originalMediaStreamAddTrack = window.MediaStream.prototype.addTrack |
|||
window.MediaStream.prototype.addTrack = function(track) { |
|||
let addTrackEventDispatched = false |
|||
const testAddTrackEvent = () => { |
|||
addTrackEventDispatched = true |
|||
} |
|||
this.addEventListener('addtrack', testAddTrackEvent) |
|||
|
|||
originalMediaStreamAddTrack.apply(this, arguments) |
|||
|
|||
this.removeEventListener('addtrack', testAddTrackEvent) |
|||
|
|||
if (!addTrackEventDispatched) { |
|||
this.dispatchEvent(new MediaStreamTrackEvent('addtrack', { track: track })) |
|||
} |
|||
} |
|||
|
|||
const originalMediaStreamRemoveTrack = window.MediaStream.prototype.removeTrack |
|||
window.MediaStream.prototype.removeTrack = function(track) { |
|||
let removeTrackEventDispatched = false |
|||
const testRemoveTrackEvent = () => { |
|||
removeTrackEventDispatched = true |
|||
} |
|||
this.addEventListener('removetrack', testRemoveTrackEvent) |
|||
|
|||
originalMediaStreamRemoveTrack.apply(this, arguments) |
|||
|
|||
this.removeEventListener('removetrack', testRemoveTrackEvent) |
|||
|
|||
if (!removeTrackEventDispatched) { |
|||
this.dispatchEvent(new MediaStreamTrackEvent('removetrack', { track: track })) |
|||
} |
|||
} |
|||
|
|||
// Event implementations do not support advanced parameters like "options"
|
|||
// or "useCapture".
|
|||
const originalMediaStreamDispatchEvent = window.MediaStream.prototype.dispatchEvent |
|||
const originalMediaStreamAddEventListener = window.MediaStream.prototype.addEventListener |
|||
const originalMediaStreamRemoveEventListener = window.MediaStream.prototype.removeEventListener |
|||
|
|||
window.MediaStream.prototype.dispatchEvent = function(event) { |
|||
if (this._listeners && this._listeners[event.type]) { |
|||
this._listeners[event.type].forEach(listener => { |
|||
listener.apply(this, [event]) |
|||
}) |
|||
} |
|||
|
|||
return originalMediaStreamDispatchEvent.apply(this, arguments) |
|||
} |
|||
|
|||
let isMediaStreamDispatchEventSupported |
|||
|
|||
window.MediaStream.prototype.addEventListener = function(type, listener) { |
|||
if (isMediaStreamDispatchEventSupported === undefined) { |
|||
isMediaStreamDispatchEventSupported = false |
|||
const testDispatchEventSupportHandler = () => { |
|||
isMediaStreamDispatchEventSupported = true |
|||
} |
|||
originalMediaStreamAddEventListener.apply(this, ['test-dispatch-event-support', testDispatchEventSupportHandler]) |
|||
originalMediaStreamDispatchEvent.apply(this, [new Event('test-dispatch-event-support')]) |
|||
originalMediaStreamRemoveEventListener(this, ['test-dispatch-event-support', testDispatchEventSupportHandler]) |
|||
|
|||
console.debug('Is MediaStream.dispatchEvent() supported?: ', isMediaStreamDispatchEventSupported) |
|||
} |
|||
|
|||
if (!isMediaStreamDispatchEventSupported) { |
|||
if (!this._listeners) { |
|||
this._listeners = [] |
|||
} |
|||
|
|||
if (!this._listeners.hasOwnProperty(type)) { |
|||
this._listeners[type] = [listener] |
|||
} else if (!this._listeners[type].includes(listener)) { |
|||
this._listeners[type].push(listener) |
|||
} |
|||
} |
|||
|
|||
return originalMediaStreamAddEventListener.apply(this, arguments) |
|||
} |
|||
|
|||
window.MediaStream.prototype.removeEventListener = function(type, listener) { |
|||
if (this._listeners && this._listeners[type]) { |
|||
const index = this._listeners[type].indexOf(listener) |
|||
if (index >= 0) { |
|||
this._listeners[type].splice(index, 1) |
|||
} |
|||
} |
|||
|
|||
return originalMediaStreamRemoveEventListener.apply(this, arguments) |
|||
} |
|||
} |
@ -0,0 +1,99 @@ |
|||
/** |
|||
* |
|||
* @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
* |
|||
*/ |
|||
|
|||
if (window.MediaStreamTrack) { |
|||
const originalMediaStreamTrackClone = window.MediaStreamTrack.prototype.clone |
|||
window.MediaStreamTrack.prototype.clone = function() { |
|||
const newTrack = originalMediaStreamTrackClone.apply(this, arguments) |
|||
|
|||
this.dispatchEvent(new CustomEvent('cloned', { detail: newTrack })) |
|||
|
|||
return newTrack |
|||
} |
|||
|
|||
const originalMediaStreamTrackStop = window.MediaStreamTrack.prototype.stop |
|||
window.MediaStreamTrack.prototype.stop = function() { |
|||
const wasAlreadyEnded = this.readyState === 'ended' |
|||
|
|||
originalMediaStreamTrackStop.apply(this, arguments) |
|||
|
|||
if (!wasAlreadyEnded) { |
|||
this.dispatchEvent(new Event('ended')) |
|||
} |
|||
} |
|||
|
|||
// Event implementations do not support advanced parameters like "options"
|
|||
// or "useCapture".
|
|||
const originalMediaStreamTrackDispatchEvent = window.MediaStreamTrack.prototype.dispatchEvent |
|||
const originalMediaStreamTrackAddEventListener = window.MediaStreamTrack.prototype.addEventListener |
|||
const originalMediaStreamTrackRemoveEventListener = window.MediaStreamTrack.prototype.removeEventListener |
|||
|
|||
window.MediaStreamTrack.prototype.dispatchEvent = function(event) { |
|||
if (this._listeners && this._listeners[event.type]) { |
|||
this._listeners[event.type].forEach(listener => { |
|||
listener.apply(this, [event]) |
|||
}) |
|||
} |
|||
|
|||
return originalMediaStreamTrackDispatchEvent.apply(this, arguments) |
|||
} |
|||
|
|||
let isMediaStreamTrackDispatchEventSupported |
|||
|
|||
window.MediaStreamTrack.prototype.addEventListener = function(type, listener) { |
|||
if (isMediaStreamTrackDispatchEventSupported === undefined) { |
|||
isMediaStreamTrackDispatchEventSupported = false |
|||
const testDispatchEventSupportHandler = () => { |
|||
isMediaStreamTrackDispatchEventSupported = true |
|||
} |
|||
originalMediaStreamTrackAddEventListener.apply(this, ['test-dispatch-event-support', testDispatchEventSupportHandler]) |
|||
originalMediaStreamTrackDispatchEvent.apply(this, [new Event('test-dispatch-event-support')]) |
|||
originalMediaStreamTrackRemoveEventListener(this, ['test-dispatch-event-support', testDispatchEventSupportHandler]) |
|||
|
|||
console.debug('Is MediaStreamTrack.dispatchEvent() supported?: ', isMediaStreamTrackDispatchEventSupported) |
|||
} |
|||
|
|||
if (!isMediaStreamTrackDispatchEventSupported) { |
|||
if (!this._listeners) { |
|||
this._listeners = [] |
|||
} |
|||
|
|||
if (!this._listeners.hasOwnProperty(type)) { |
|||
this._listeners[type] = [listener] |
|||
} else if (!this._listeners[type].includes(listener)) { |
|||
this._listeners[type].push(listener) |
|||
} |
|||
} |
|||
|
|||
return originalMediaStreamTrackAddEventListener.apply(this, arguments) |
|||
} |
|||
|
|||
window.MediaStreamTrack.prototype.removeEventListener = function(type, listener) { |
|||
if (this._listeners && this._listeners[type]) { |
|||
const index = this._listeners[type].indexOf(listener) |
|||
if (index >= 0) { |
|||
this._listeners[type].splice(index, 1) |
|||
} |
|||
} |
|||
|
|||
return originalMediaStreamTrackRemoveEventListener.apply(this, arguments) |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue