diff --git a/js/getDisplayMedia.js b/js/getDisplayMedia.js
new file mode 100644
index 00000000..68354b0c
--- /dev/null
+++ b/js/getDisplayMedia.js
@@ -0,0 +1,55 @@
+/**
+ * Expose the getDisplayMedia function.
+ */
+module.exports = getDisplayMedia;
+
+/**
+ * Dependencies.
+ */
+var debug = require('debug')('iosrtc:getDisplayMedia'),
+ debugerror = require('debug')('iosrtc:ERROR:getDisplayMedia'),
+ exec = require('cordova/exec'),
+ MediaStream = require('./MediaStream'),
+ Errors = require('./Errors');
+
+function getDisplayMedia(constraints) {
+ // Detect callback usage to assist 5.0.1 to 5.0.2 migration
+ // TODO remove on 6.0.0
+ Errors.detectDeprecatedCallbaksUsage('cordova.plugins.iosrtc.getDisplayMedia', arguments);
+
+ debug('[original constraints:%o]', constraints);
+
+ var newConstraints = {};
+
+ if (
+ typeof constraints !== 'object' ||
+ (!constraints.hasOwnProperty('audio') && !constraints.hasOwnProperty('video'))
+ ) {
+ return new Promise(function (resolve, reject) {
+ reject(
+ new Errors.MediaStreamError(
+ 'constraints must be an object with at least "audio" or "video" keys'
+ )
+ );
+ });
+ }
+
+ debug('[computed constraints:%o]', newConstraints);
+
+ return new Promise(function (resolve, reject) {
+ function onResultOK(data) {
+ debug('getDisplayMedia() | success');
+ var stream = MediaStream.create(data.stream);
+ resolve(stream);
+ // Emit "connected" on the stream.
+ stream.emitConnected();
+ }
+
+ function onResultError(error) {
+ debugerror('getDisplayMedia() | failure: %s', error);
+ reject(new Errors.MediaStreamError('getDisplayMedia() failed: ' + error));
+ }
+
+ exec(onResultOK, onResultError, 'iosrtcPlugin', 'getDisplayMedia', [newConstraints]);
+ });
+}
diff --git a/js/iosrtc.js b/js/iosrtc.js
index 52b4d7fd..a8ffef2e 100644
--- a/js/iosrtc.js
+++ b/js/iosrtc.js
@@ -17,6 +17,7 @@ var // Dictionary of MediaStreamRenderers.
exec = require('cordova/exec'),
domready = require('domready'),
getUserMedia = require('./getUserMedia'),
+ getDisplayMedia = require('./getDisplayMedia'),
enumerateDevices = require('./enumerateDevices'),
RTCPeerConnection = require('./RTCPeerConnection'),
RTCSessionDescription = require('./RTCSessionDescription'),
@@ -33,6 +34,7 @@ var // Dictionary of MediaStreamRenderers.
module.exports = {
// Expose WebRTC classes and functions.
getUserMedia: getUserMedia,
+ getDisplayMedia: getDisplayMedia,
enumerateDevices: enumerateDevices,
getMediaDevices: enumerateDevices, // TMP
RTCPeerConnection: RTCPeerConnection,
@@ -190,6 +192,8 @@ function registerGlobals(doNotRestoreCallbacksSupport) {
restoreCallbacksSupport();
}
+ navigator.getDisplayMedia = getDisplayMedia;
+ navigator.mediaDevices.getDisplayMedia = getDisplayMedia;
navigator.getUserMedia = getUserMedia;
navigator.webkitGetUserMedia = getUserMedia;
diff --git a/plugin.xml b/plugin.xml
index f56a9be9..21adde99 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -71,6 +71,7 @@
+
diff --git a/src/PluginGetDisplayMedia.swift b/src/PluginGetDisplayMedia.swift
new file mode 100644
index 00000000..66b87e20
--- /dev/null
+++ b/src/PluginGetDisplayMedia.swift
@@ -0,0 +1,94 @@
+import Foundation
+import AVFoundation
+import ReplayKit
+
+class PluginGetDisplayMedia {
+
+ var rtcPeerConnectionFactory: RTCPeerConnectionFactory
+
+ init(rtcPeerConnectionFactory: RTCPeerConnectionFactory) {
+ NSLog("PluginGetDisplayMedia#init()")
+ self.rtcPeerConnectionFactory = rtcPeerConnectionFactory
+ }
+
+ deinit {
+ NSLog("PluginGetDisplayMedia#deinit()")
+ }
+
+ func call(
+ _ constraints: NSDictionary,
+ callback: @escaping (_ data: NSDictionary) -> Void,
+ errback: @escaping (_ error: String) -> Void,
+ eventListenerForNewStream: @escaping (_ pluginMediaStream: PluginMediaStream) -> Void
+ ) {
+
+ NSLog("PluginGetDisplayMedia#call()")
+ if #available(iOS 11.0, *) {
+
+ let recorder = RPScreenRecorder.shared()
+
+ if (recorder.isRecording) {
+ recorder.stopCapture(handler: {(error) in
+ if (error != nil) {
+ errback(error!.localizedDescription)
+ } else {
+ self.startCapture(recorder: recorder, callback: callback, errback: errback, eventListenerForNewStream: eventListenerForNewStream)
+ }
+ })
+ } else if (recorder.isAvailable) {
+ self.startCapture(recorder: recorder, callback: callback, errback: errback, eventListenerForNewStream: eventListenerForNewStream)
+ } else {
+ errback("Screen recorder is not available!")
+ }
+
+ } else {
+ errback("Screen recorder is not available!")
+ }
+ }
+
+ @available(iOS 11.0, *)
+ func startCapture(
+ recorder: RPScreenRecorder,
+ callback: @escaping (_ data: NSDictionary) -> Void,
+ errback: @escaping (_ error: String) -> Void,
+ eventListenerForNewStream: @escaping (_ pluginMediaStream: PluginMediaStream) -> Void
+ ) {
+
+ let rtcVideoSource: RTCVideoSource = self.rtcPeerConnectionFactory.videoSource()
+ let videoCapturer: RTCVideoCapturer = RTCVideoCapturer(delegate: rtcVideoSource)
+ let rtcMediaStream: RTCMediaStream = self.rtcPeerConnectionFactory.mediaStream(withStreamId: UUID().uuidString)
+ let rtcVideoTrack: RTCVideoTrack = self.rtcPeerConnectionFactory.videoTrack(
+ with: rtcVideoSource, trackId: UUID().uuidString)
+
+ let videoCaptureController: PluginRTCScreenCaptureController = PluginRTCScreenCaptureController(capturer: videoCapturer, recorder: recorder, source: rtcVideoSource)
+ rtcVideoTrack.videoCaptureController = videoCaptureController
+
+ // TODO use startCapture completionHandler
+ let captureStarted = videoCaptureController.startCapture()
+ if (!captureStarted) {
+ errback("constraints failed")
+ return
+ }
+
+ // If videoSource state is "ended" it means that constraints were not satisfied so
+ // invoke the given errback.
+ if (rtcVideoSource.state == RTCSourceState.ended) {
+ NSLog("PluginGetDisplayMedia() | rtcVideoSource.state is 'ended', constraints not satisfied")
+
+ errback("constraints not satisfied")
+ return
+ }
+
+ rtcMediaStream.addVideoTrack(rtcVideoTrack)
+
+ let pluginMediaStream: PluginMediaStream = PluginMediaStream(rtcMediaStream: rtcMediaStream)
+ pluginMediaStream.run()
+
+ // Let the plugin store it in its dictionary.
+ eventListenerForNewStream(pluginMediaStream)
+
+ callback([
+ "stream": pluginMediaStream.getJSON()
+ ])
+ }
+}
diff --git a/src/PluginGetUserMedia.swift b/src/PluginGetUserMedia.swift
index 1c3feb1b..35b06761 100644
--- a/src/PluginGetUserMedia.swift
+++ b/src/PluginGetUserMedia.swift
@@ -98,7 +98,7 @@ class PluginGetUserMedia {
// Ignore Simulator cause does not support Camera
#if !targetEnvironment(simulator)
let videoCapturer: RTCCameraVideoCapturer = RTCCameraVideoCapturer(delegate: rtcVideoSource!)
- let videoCaptureController: PluginRTCVideoCaptureController = PluginRTCVideoCaptureController(capturer: videoCapturer)
+ let videoCaptureController: PluginRTCCameraCaptureController = PluginRTCCameraCaptureController(capturer: videoCapturer)
rtcVideoTrack!.videoCaptureController = videoCaptureController
let constraintsSatisfied = videoCaptureController.setConstraints(constraints: videoConstraints)
diff --git a/src/PluginMediaStreamTrack.swift b/src/PluginMediaStreamTrack.swift
index ffa09587..39fd3c43 100644
--- a/src/PluginMediaStreamTrack.swift
+++ b/src/PluginMediaStreamTrack.swift
@@ -106,9 +106,11 @@ class PluginMediaStreamTrack : NSObject {
}
}
+ /*
func switchCamera() {
self.rtcMediaStreamTrack.videoCaptureController?.switchCamera()
}
+ */
func registerRender(render: PluginMediaStreamRenderer) {
if let exist = self.renders[render.id] {
diff --git a/src/PluginRTCVideoCaptureController.swift b/src/PluginRTCVideoCaptureController.swift
index 05597ce3..616904bc 100644
--- a/src/PluginRTCVideoCaptureController.swift
+++ b/src/PluginRTCVideoCaptureController.swift
@@ -1,5 +1,6 @@
import Foundation
import AVFoundation
+import ReplayKit
import func ObjectiveC.objc_getAssociatedObject
import func ObjectiveC.objc_setAssociatedObject
@@ -52,22 +53,123 @@ extension RTCMediaStreamTrack {
class PluginRTCVideoCaptureController : NSObject {
+ var isCapturing: Bool = false;
+
+ // Default to the front camera.
+ var device: AVCaptureDevice?
+ var deviceFormat: AVCaptureDevice.Format?
+ var deviceFrameRate: Int?
+
+ var constraints: NSDictionary = [:]
+
+ func startCapture(completionHandler: ((Error?) -> Void)? = nil) -> Bool {
+ return isCapturing;
+ }
+
+ func stopCapture() {
+
+ }
+}
+
+class PluginRTCScreenCaptureController : PluginRTCVideoCaptureController {
+
+ var capturer: RTCVideoCapturer
+ var source: RTCVideoSource
+ var recorder: RPScreenRecorder
+
+ init(capturer: RTCVideoCapturer, recorder: RPScreenRecorder, source: RTCVideoSource) {
+ self.capturer = capturer
+ self.recorder = recorder;
+ self.source = source;
+ }
+
+ override func startCapture(completionHandler: ((Error?) -> Void)? = nil) -> Bool {
+
+ // Stop previous capture in case of setConstraints, followed by startCapture
+ // aka future applyConstraints
+ if (isCapturing) {
+ stopCapture();
+ }
+
+ if #available(iOS 11.0, *) {
+ recorder.isMicrophoneEnabled = false
+ recorder.startCapture(handler: {(sampleBuffer, bufferType, error) in
+ if (bufferType == RPSampleBufferType.video) {
+ self.handleSourceBuffer(
+ source: self.source,
+ sampleBuffer: sampleBuffer,
+ sampleType: bufferType
+ )
+ }
+ if (completionHandler != nil && error != nil) {
+ completionHandler!(error)
+ }
+ }) { (error) in
+ if (completionHandler != nil && error != nil) {
+ completionHandler!(error)
+ } else {
+ // TODO Optional closure parameter
+ //completionHandler!()
+ }
+ }
+
+ isCapturing = true
+
+ NSLog("PluginRTCScreenCaptureController#startCapture Capture started");
+ }
+
+ return isCapturing;
+ }
+
+ override func stopCapture() {
+ // TODO: stopCaptureWithCompletionHandler with DispatchSemaphore
+ if (isCapturing) {
+ if #available(iOS 11.0, *) {
+ recorder.stopCapture {(error) in
+ // TODO debug error
+ }
+ isCapturing = false
+
+ NSLog("PluginRTCScreenCaptureController#stopCapture Capture stopped");
+ }
+ }
+ }
+
+ func handleSourceBuffer(source: RTCVideoSource, sampleBuffer: CMSampleBuffer, sampleType: RPSampleBufferType) {
+ if (CMSampleBufferGetNumSamples(sampleBuffer) != 1 || !CMSampleBufferIsValid(sampleBuffer) ||
+ !CMSampleBufferDataIsReady(sampleBuffer)) {
+ return;
+ }
+
+ let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
+ if (pixelBuffer == nil) {
+ return;
+ }
+
+ let width = CVPixelBufferGetWidth(pixelBuffer!);
+ let height = CVPixelBufferGetHeight(pixelBuffer!);
+
+ source.adaptOutputFormat(toWidth: Int32(width/2), height: Int32(height/2), fps: 8)
+
+ let rtcPixelBuffer = RTCCVPixelBuffer(pixelBuffer: pixelBuffer!)
+ let timeStampNs =
+ CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) * Float64(NSEC_PER_SEC)
+ let videoFrame = RTCVideoFrame(buffer: rtcPixelBuffer, rotation: RTCVideoRotation._0, timeStampNs: Int64(timeStampNs))
+ source.capturer(capturer, didCapture: videoFrame)
+ }
+}
+
+class PluginRTCCameraCaptureController : PluginRTCVideoCaptureController {
+
private let DEFAULT_HEIGHT : Int32 = 480
private let DEFAULT_WIDTH : Int32 = 640
+
private let DEFAULT_FPS : Int = 15
private let DEFAULT_ASPECT_RATIO : Float32 = 4/3
private let FACING_MODE_USER : String = "user";
private let FACING_MODE_ENV : String = "environment";
var capturer: RTCCameraVideoCapturer
- var isCapturing: Bool = false;
-
- // Default to the front camera.
- var device: AVCaptureDevice?
- var deviceFormat: AVCaptureDevice.Format?
- var deviceFrameRate: Int?
-
- var constraints: NSDictionary = [:]
init(capturer: RTCCameraVideoCapturer) {
self.capturer = capturer
@@ -139,7 +241,7 @@ class PluginRTCVideoCaptureController : NSObject {
return device != nil;
}
- func startCapture() -> Bool {
+ override func startCapture(completionHandler: ((Error?) -> Void)? = nil) -> Bool {
// Stop previous capture in case of setConstraints, followed by startCapture
// aka future applyConstraints
@@ -167,10 +269,10 @@ class PluginRTCVideoCaptureController : NSObject {
NSLog("PluginRTCVideoCaptureController#startCapture Capture started, device:%@, format:%@", device!, deviceFormat!);
- return true;
+ return isCapturing;
}
- func stopCapture() {
+ override func stopCapture() {
// TODO: stopCaptureWithCompletionHandler with DispatchSemaphore
if (isCapturing) {
capturer.stopCapture()
@@ -294,6 +396,7 @@ class PluginRTCVideoCaptureController : NSObject {
return captureDevices.firstObject as? AVCaptureDevice
}
+ /*
func switchCamera() -> Bool {
if (self.capturer.captureSession.isRunning) {
@@ -306,6 +409,7 @@ class PluginRTCVideoCaptureController : NSObject {
return self.startCapture()
}
+ */
fileprivate func findAlternativeDevicePosition(currentDevice: AVCaptureDevice?) -> AVCaptureDevice? {
let captureDevices: NSArray = RTCCameraVideoCapturer.captureDevices() as NSArray
@@ -468,7 +572,7 @@ class PluginRTCVideoCaptureController : NSObject {
return selectedFormat
}
-
+
//
// constraints parsers
//
diff --git a/src/iosrtcPlugin.swift b/src/iosrtcPlugin.swift
index 8bd1e4c0..0f00839a 100644
--- a/src/iosrtcPlugin.swift
+++ b/src/iosrtcPlugin.swift
@@ -8,6 +8,8 @@ class iosrtcPlugin : CDVPlugin {
var rtcPeerConnectionFactory: RTCPeerConnectionFactory!
// Single PluginGetUserMedia instance.
var pluginGetUserMedia: PluginGetUserMedia!
+ // Single PluginGetDisplayMedia instance.
+ var pluginGetDisplayMedia: PluginGetDisplayMedia!
// PluginRTCPeerConnection dictionary.
var pluginRTCPeerConnections: [Int : PluginRTCPeerConnection]!
// PluginMediaStream dictionary.
@@ -21,7 +23,6 @@ class iosrtcPlugin : CDVPlugin {
// Auto selecting output speaker
var audioOutputController: PluginRTCAudioController!
-
// This is just called if in plugin.xml.
@objc(pluginInitialize) override func pluginInitialize() {
NSLog("iosrtcPlugin#pluginInitialize()")
@@ -47,6 +48,11 @@ class iosrtcPlugin : CDVPlugin {
self.pluginGetUserMedia = PluginGetUserMedia(
rtcPeerConnectionFactory: rtcPeerConnectionFactory
)
+
+ // Create a PluginGetDisplayMedia instance.
+ self.pluginGetDisplayMedia = PluginGetDisplayMedia(
+ rtcPeerConnectionFactory: rtcPeerConnectionFactory
+ )
// Create a PluginRTCAudioController instance.
self.audioOutputController = PluginRTCAudioController()
@@ -1197,6 +1203,29 @@ class iosrtcPlugin : CDVPlugin {
eventListenerForNewStream: self.saveMediaStream
)
}
+
+ @objc(getDisplayMedia:) func getDisplayMedia(_ command: CDVInvokedUrlCommand) {
+ NSLog("iosrtcPlugin#getDisplayMedia()")
+
+ let constraints = command.argument(at: 0) as! NSDictionary
+
+ self.pluginGetDisplayMedia.call(constraints,
+ callback: { (data: NSDictionary) -> Void in
+ self.emit(command.callbackId,
+ result: CDVPluginResult(
+ status: CDVCommandStatus_OK,
+ messageAs: data as? [AnyHashable: Any]
+ )
+ )
+ },
+ errback: { (error: String) -> Void in
+ self.emit(command.callbackId,
+ result: CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error)
+ )
+ },
+ eventListenerForNewStream: self.saveMediaStream
+ )
+ }
@objc(enumerateDevices:) func enumerateDevices(_ command: CDVInvokedUrlCommand) {
NSLog("iosrtcPlugin#enumerateDevices()")
diff --git a/www/cordova-plugin-iosrtc.js b/www/cordova-plugin-iosrtc.js
index 3a80074d..574c5550 100644
--- a/www/cordova-plugin-iosrtc.js
+++ b/www/cordova-plugin-iosrtc.js
@@ -88,7 +88,7 @@ EventTarget.prototype.dispatchEvent = function (event) {
*/
module.exports = EventTarget;
-},{"yaeti":30}],3:[function(_dereq_,module,exports){
+},{"yaeti":31}],3:[function(_dereq_,module,exports){
/**
* Expose the MediaDeviceInfo class.
*/
@@ -202,7 +202,7 @@ MediaDevices.prototype.getSupportedConstraints = function () {
};
};
-},{"./EventTarget":2,"./enumerateDevices":19,"./getUserMedia":20}],5:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"./enumerateDevices":19,"./getUserMedia":21}],5:[function(_dereq_,module,exports){
/**
* Expose the MediaStream class.
*/
@@ -714,7 +714,7 @@ function onEvent(data) {
}
}
-},{"./EventTarget":2,"./MediaStreamTrack":7,"cordova/exec":undefined,"debug":23}],6:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"./MediaStreamTrack":7,"cordova/exec":undefined,"debug":24}],6:[function(_dereq_,module,exports){
/**
* Expose the MediaStreamRenderer class.
*/
@@ -1124,7 +1124,7 @@ function getElementPositionAndSize() {
};
}
-},{"./EventTarget":2,"./MediaStream":5,"cordova/exec":undefined,"debug":23,"random-number":28}],7:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"./MediaStream":5,"cordova/exec":undefined,"debug":24,"random-number":29}],7:[function(_dereq_,module,exports){
/**
* Expose the MediaStreamTrack class.
*/
@@ -1291,7 +1291,7 @@ function onEvent(data) {
}
}
-},{"./EventTarget":2,"./MediaTrackCapabilities":8,"./MediaTrackSettings":9,"./enumerateDevices":19,"cordova/exec":undefined,"debug":23}],8:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"./MediaTrackCapabilities":8,"./MediaTrackSettings":9,"./enumerateDevices":19,"cordova/exec":undefined,"debug":24}],8:[function(_dereq_,module,exports){
/**
* Expose the MediaTrackSettings class.
*/
@@ -1446,7 +1446,7 @@ function onEvent(data) {
}
}
-},{"./EventTarget":2,"cordova/exec":undefined,"debug":23,"random-number":28}],11:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"cordova/exec":undefined,"debug":24,"random-number":29}],11:[function(_dereq_,module,exports){
(function (setImmediate){
/**
* Expose the RTCDataChannel class.
@@ -1713,7 +1713,7 @@ function onEvent(data) {
}
}).call(this,_dereq_("timers").setImmediate)
-},{"./EventTarget":2,"cordova/exec":undefined,"debug":23,"random-number":28,"timers":29}],12:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"cordova/exec":undefined,"debug":24,"random-number":29,"timers":30}],12:[function(_dereq_,module,exports){
/**
* Expose the RTCIceCandidate class.
*/
@@ -2913,7 +2913,7 @@ function onEvent(data) {
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./Errors":1,"./EventTarget":2,"./MediaStream":5,"./MediaStreamTrack":7,"./RTCDTMFSender":10,"./RTCDataChannel":11,"./RTCIceCandidate":12,"./RTCRtpReceiver":14,"./RTCRtpSender":15,"./RTCRtpTransceiver":16,"./RTCSessionDescription":17,"./RTCStatsReport":18,"cordova/exec":undefined,"debug":23,"random-number":28}],14:[function(_dereq_,module,exports){
+},{"./Errors":1,"./EventTarget":2,"./MediaStream":5,"./MediaStreamTrack":7,"./RTCDTMFSender":10,"./RTCDataChannel":11,"./RTCIceCandidate":12,"./RTCRtpReceiver":14,"./RTCRtpSender":15,"./RTCRtpTransceiver":16,"./RTCSessionDescription":17,"./RTCStatsReport":18,"cordova/exec":undefined,"debug":24,"random-number":29}],14:[function(_dereq_,module,exports){
/**
* Expose the RTCRtpReceiver class.
*/
@@ -2948,7 +2948,7 @@ RTCRtpReceiver.prototype.update = function ({ track, params }) {
this.params = params;
};
-},{"random-number":28}],15:[function(_dereq_,module,exports){
+},{"random-number":29}],15:[function(_dereq_,module,exports){
/**
* Expose the RTCRtpSender class.
*/
@@ -3052,7 +3052,7 @@ RTCRtpSender.prototype.update = function ({ track, params }) {
this.params = params;
};
-},{"./MediaStreamTrack":7,"cordova/exec":undefined,"random-number":28}],16:[function(_dereq_,module,exports){
+},{"./MediaStreamTrack":7,"cordova/exec":undefined,"random-number":29}],16:[function(_dereq_,module,exports){
const RTCRtpSender = _dereq_('./RTCRtpSender');
const RTCRtpReceiver = _dereq_('./RTCRtpReceiver');
@@ -3209,7 +3209,7 @@ RTCRtpTransceiver.prototype.update = function (data) {
this.sender.update(data.sender);
};
-},{"./EventTarget":2,"./RTCRtpReceiver":14,"./RTCRtpSender":15,"cordova/exec":undefined,"debug":23,"random-number":28}],17:[function(_dereq_,module,exports){
+},{"./EventTarget":2,"./RTCRtpReceiver":14,"./RTCRtpSender":15,"cordova/exec":undefined,"debug":24,"random-number":29}],17:[function(_dereq_,module,exports){
/**
* Expose the RTCSessionDescription class.
*/
@@ -3304,7 +3304,64 @@ function getMediaDeviceInfos(devices) {
return mediaDeviceInfos;
}
-},{"./Errors":1,"./MediaDeviceInfo":3,"cordova/exec":undefined,"debug":23}],20:[function(_dereq_,module,exports){
+},{"./Errors":1,"./MediaDeviceInfo":3,"cordova/exec":undefined,"debug":24}],20:[function(_dereq_,module,exports){
+/**
+ * Expose the getDisplayMedia function.
+ */
+module.exports = getDisplayMedia;
+
+/**
+ * Dependencies.
+ */
+var debug = _dereq_('debug')('iosrtc:getDisplayMedia'),
+ debugerror = _dereq_('debug')('iosrtc:ERROR:getDisplayMedia'),
+ exec = _dereq_('cordova/exec'),
+ MediaStream = _dereq_('./MediaStream'),
+ Errors = _dereq_('./Errors');
+
+function getDisplayMedia(constraints) {
+ // Detect callback usage to assist 5.0.1 to 5.0.2 migration
+ // TODO remove on 6.0.0
+ Errors.detectDeprecatedCallbaksUsage('cordova.plugins.iosrtc.getDisplayMedia', arguments);
+
+ debug('[original constraints:%o]', constraints);
+
+ var newConstraints = {};
+
+ if (
+ typeof constraints !== 'object' ||
+ (!constraints.hasOwnProperty('audio') && !constraints.hasOwnProperty('video'))
+ ) {
+ return new Promise(function (resolve, reject) {
+ reject(
+ new Errors.MediaStreamError(
+ 'constraints must be an object with at least "audio" or "video" keys'
+ )
+ );
+ });
+ }
+
+ debug('[computed constraints:%o]', newConstraints);
+
+ return new Promise(function (resolve, reject) {
+ function onResultOK(data) {
+ debug('getDisplayMedia() | success');
+ var stream = MediaStream.create(data.stream);
+ resolve(stream);
+ // Emit "connected" on the stream.
+ stream.emitConnected();
+ }
+
+ function onResultError(error) {
+ debugerror('getDisplayMedia() | failure: %s', error);
+ reject(new Errors.MediaStreamError('getDisplayMedia() failed: ' + error));
+ }
+
+ exec(onResultOK, onResultError, 'iosrtcPlugin', 'getDisplayMedia', [newConstraints]);
+ });
+}
+
+},{"./Errors":1,"./MediaStream":5,"cordova/exec":undefined,"debug":24}],21:[function(_dereq_,module,exports){
/**
* Expose the getUserMedia function.
*/
@@ -3765,7 +3822,7 @@ function getUserMedia(constraints) {
});
}
-},{"./Errors":1,"./MediaStream":5,"cordova/exec":undefined,"debug":23}],21:[function(_dereq_,module,exports){
+},{"./Errors":1,"./MediaStream":5,"cordova/exec":undefined,"debug":24}],22:[function(_dereq_,module,exports){
(function (global){
/**
* Variables.
@@ -3786,6 +3843,7 @@ var // Dictionary of MediaStreamRenderers.
exec = _dereq_('cordova/exec'),
domready = _dereq_('domready'),
getUserMedia = _dereq_('./getUserMedia'),
+ getDisplayMedia = _dereq_('./getDisplayMedia'),
enumerateDevices = _dereq_('./enumerateDevices'),
RTCPeerConnection = _dereq_('./RTCPeerConnection'),
RTCSessionDescription = _dereq_('./RTCSessionDescription'),
@@ -3802,6 +3860,7 @@ var // Dictionary of MediaStreamRenderers.
module.exports = {
// Expose WebRTC classes and functions.
getUserMedia: getUserMedia,
+ getDisplayMedia: getDisplayMedia,
enumerateDevices: enumerateDevices,
getMediaDevices: enumerateDevices, // TMP
RTCPeerConnection: RTCPeerConnection,
@@ -3959,6 +4018,8 @@ function registerGlobals(doNotRestoreCallbacksSupport) {
restoreCallbacksSupport();
}
+ navigator.getDisplayMedia = getDisplayMedia;
+ navigator.mediaDevices.getDisplayMedia = getDisplayMedia;
navigator.getUserMedia = getUserMedia;
navigator.webkitGetUserMedia = getUserMedia;
@@ -4057,7 +4118,7 @@ function dump() {
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./MediaDevices":4,"./MediaStream":5,"./MediaStreamTrack":7,"./RTCIceCandidate":12,"./RTCPeerConnection":13,"./RTCRtpTransceiver":16,"./RTCSessionDescription":17,"./enumerateDevices":19,"./getUserMedia":20,"./videoElementsHandler":22,"cordova/exec":undefined,"debug":23,"domready":25}],22:[function(_dereq_,module,exports){
+},{"./MediaDevices":4,"./MediaStream":5,"./MediaStreamTrack":7,"./RTCIceCandidate":12,"./RTCPeerConnection":13,"./RTCRtpTransceiver":16,"./RTCSessionDescription":17,"./enumerateDevices":19,"./getDisplayMedia":20,"./getUserMedia":21,"./videoElementsHandler":23,"cordova/exec":undefined,"debug":24,"domready":26}],23:[function(_dereq_,module,exports){
/**
* Expose a function that must be called when the library is loaded.
* And also a helper function.
@@ -4444,7 +4505,7 @@ function releaseMediaStreamRenderer(video) {
delete video.readyState;
}
-},{"./MediaStreamRenderer":6,"debug":23}],23:[function(_dereq_,module,exports){
+},{"./MediaStreamRenderer":6,"debug":24}],24:[function(_dereq_,module,exports){
(function (process){
/* eslint-env browser */
@@ -4712,7 +4773,7 @@ formatters.j = function (v) {
};
}).call(this,_dereq_('_process'))
-},{"./common":24,"_process":27}],24:[function(_dereq_,module,exports){
+},{"./common":25,"_process":28}],25:[function(_dereq_,module,exports){
/**
* This is the common logic for both the Node.js and web browser
@@ -4980,7 +5041,7 @@ function setup(env) {
module.exports = setup;
-},{"ms":26}],25:[function(_dereq_,module,exports){
+},{"ms":27}],26:[function(_dereq_,module,exports){
/*!
* domready (c) Dustin Diaz 2014 - License MIT
*/
@@ -5012,7 +5073,7 @@ module.exports = setup;
});
-},{}],26:[function(_dereq_,module,exports){
+},{}],27:[function(_dereq_,module,exports){
/**
* Helpers.
*/
@@ -5176,7 +5237,7 @@ function plural(ms, msAbs, n, name) {
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
}
-},{}],27:[function(_dereq_,module,exports){
+},{}],28:[function(_dereq_,module,exports){
// shim for using process in browser
var process = module.exports = {};
@@ -5362,7 +5423,7 @@ process.chdir = function (dir) {
};
process.umask = function() { return 0; };
-},{}],28:[function(_dereq_,module,exports){
+},{}],29:[function(_dereq_,module,exports){
void function(root){
function defaults(options){
@@ -5408,7 +5469,7 @@ void function(root){
module.exports.defaults = defaults
}(this)
-},{}],29:[function(_dereq_,module,exports){
+},{}],30:[function(_dereq_,module,exports){
(function (setImmediate,clearImmediate){
var nextTick = _dereq_('process/browser.js').nextTick;
var apply = Function.prototype.apply;
@@ -5487,14 +5548,14 @@ exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate :
delete immediateIds[id];
};
}).call(this,_dereq_("timers").setImmediate,_dereq_("timers").clearImmediate)
-},{"process/browser.js":27,"timers":29}],30:[function(_dereq_,module,exports){
+},{"process/browser.js":28,"timers":30}],31:[function(_dereq_,module,exports){
module.exports =
{
EventTarget : _dereq_('./lib/EventTarget'),
Event : _dereq_('./lib/Event')
};
-},{"./lib/Event":31,"./lib/EventTarget":32}],31:[function(_dereq_,module,exports){
+},{"./lib/Event":32,"./lib/EventTarget":33}],32:[function(_dereq_,module,exports){
(function (global){
/**
* In browsers export the native Event interface.
@@ -5503,7 +5564,7 @@ module.exports =
module.exports = global.Event;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],32:[function(_dereq_,module,exports){
+},{}],33:[function(_dereq_,module,exports){
function yaetiEventTarget()
{
this._listeners = {};
@@ -5638,5 +5699,5 @@ yaetiEventTarget.prototype.dispatchEvent = function(event)
module.exports = yaetiEventTarget;
-},{}]},{},[21])(21)
+},{}]},{},[22])(22)
});