diff --git a/lib/src/factory.dart b/lib/src/factory.dart index 2ea1e22..b23e5e3 100644 --- a/lib/src/factory.dart +++ b/lib/src/factory.dart @@ -2,15 +2,20 @@ import 'frame_cryptor.dart'; import 'media_recorder.dart'; import 'media_stream.dart'; import 'navigator.dart'; +import 'rtc_configuration.dart'; import 'rtc_peerconnection.dart'; import 'rtc_rtp_capabilities.dart'; import 'rtc_video_renderer.dart'; abstract class RTCFactory { + @Deprecated('use newPeerConnection() instead') Future createPeerConnection( Map configuration, [Map constraints]); + Future newPeerConnection(RTCConfiguration configuration) => + throw UnimplementedError(); + Future createLocalMediaStream(String label); Future getRtpSenderCapabilities(String kind); diff --git a/lib/src/media_constraints.dart b/lib/src/media_constraints.dart new file mode 100644 index 0000000..10f18b8 --- /dev/null +++ b/lib/src/media_constraints.dart @@ -0,0 +1,150 @@ +class MediaTrackConstraints { + MediaTrackConstraints({this.deviceId, this.groupId}); + factory MediaTrackConstraints.fromMap(Map map) { + return MediaTrackConstraints( + deviceId: map['deviceId'] as String?, + groupId: map['groupId'] as String?, + ); + } + final String? deviceId; + final String? groupId; + + Map toMap() { + return { + if (deviceId != null) 'deviceId': deviceId, + if (groupId != null) 'groupId': groupId, + }; + } +} + +class AudioTrackConstraints extends MediaTrackConstraints { + AudioTrackConstraints({ + required String deviceId, + required String groupId, + this.autoGainControl, + this.channelCount, + this.echoCancellation, + this.latency, + this.noiseSuppression, + this.sampleRate, + this.sampleSize, + this.volume, + }) : super(deviceId: deviceId, groupId: groupId); + + factory AudioTrackConstraints.fromMap(Map map) { + return AudioTrackConstraints( + deviceId: map['deviceId'] as String, + groupId: map['groupId'] as String, + autoGainControl: map['autoGainControl'] as bool?, + channelCount: map['channelCount'] as bool?, + echoCancellation: map['echoCancellation'] as bool?, + latency: map['latency'] as bool?, + noiseSuppression: map['noiseSuppression'] as bool?, + sampleRate: map['sampleRate'] as bool?, + sampleSize: map['sampleSize'] as bool?, + volume: map['volume'] as bool?, + ); + } + + bool? autoGainControl; + bool? channelCount; + bool? echoCancellation; + bool? latency; + bool? noiseSuppression; + bool? sampleRate; + bool? sampleSize; + bool? volume; + + @override + Map toMap() { + return { + if (deviceId != null) 'deviceId': deviceId, + if (groupId != null) 'groupId': groupId, + if (autoGainControl != null) 'autoGainControl': autoGainControl, + if (channelCount != null) 'channelCount': channelCount, + if (echoCancellation != null) 'echoCancellation': echoCancellation, + if (latency != null) 'latency': latency, + if (noiseSuppression != null) 'noiseSuppression': noiseSuppression, + if (sampleRate != null) 'sampleRate': sampleRate, + if (sampleSize != null) 'sampleSize': sampleSize, + if (volume != null) 'volume': volume, + }; + } +} + +class VideoTrackConstraints extends MediaTrackConstraints { + VideoTrackConstraints({ + required String deviceId, + required String groupId, + this.aspectRatio, + this.frameRate, + this.facingMode, + this.height, + this.width, + }) : super(deviceId: deviceId, groupId: groupId); + + factory VideoTrackConstraints.fromMap(Map map) { + return VideoTrackConstraints( + deviceId: map['deviceId'] as String, + groupId: map['groupId'] as String, + aspectRatio: map['aspectRatio'] as bool?, + frameRate: map['frameRate'] as bool?, + facingMode: map['facingMode'] as bool?, + height: map['height'] as bool?, + width: map['width'] as bool?, + ); + } + + bool? aspectRatio; + bool? frameRate; + bool? facingMode; + bool? height; + bool? width; + + @override + Map toMap() { + return { + if (deviceId != null) 'deviceId': deviceId, + if (groupId != null) 'groupId': groupId, + if (aspectRatio != null) 'aspectRatio': aspectRatio, + if (frameRate != null) 'frameRate': frameRate, + if (facingMode != null) 'facingMode': facingMode, + if (height != null) 'height': height, + if (width != null) 'width': width, + }; + } +} + +class MediaStreamConstraints { + MediaStreamConstraints({ + this.audio, + this.video, + }); + + factory MediaStreamConstraints.fromMap(Map map) { + return MediaStreamConstraints( + audio: map['audio'] is bool + ? map['audio'] + : AudioTrackConstraints.fromMap(map['audio']), + video: map['video'] is bool + ? map['video'] + : VideoTrackConstraints.fromMap(map['video']), + ); + } + + // bool or AudioTrackConstraints + dynamic audio; + // bool or VideoTrackConstraints + dynamic video; + + Map toMap() { + return { + if (audio != null) + 'audio': + audio is bool ? audio : (audio as AudioTrackConstraints).toMap(), + if (video != null) + 'video': + video is bool ? video : (video as VideoTrackConstraints).toMap(), + }; + } +} diff --git a/lib/src/mediadevices.dart b/lib/src/mediadevices.dart index 9e43527..000f965 100644 --- a/lib/src/mediadevices.dart +++ b/lib/src/mediadevices.dart @@ -1,23 +1,5 @@ import 'media_stream.dart'; -class MediaStreamConstraints { - MediaStreamConstraints({this.audio, this.video}); - - /// Either a bool (which indicates whether or not an audio track is requested) - /// or a MediaTrackConstraints object providing the constraints which must be - /// met by the audio track included in the returned MediaStream. - /// - /// If constraints are specified, an audio track is inherently requested. - dynamic audio; - - /// Either a bool (which indicates whether or not a video track is requested) - /// or a MediaTrackConstraints object providing the constraints which must be - /// met by the video track included in the returned MediaStream. - /// - /// If constraints are specified, a video track is inherently requested. - dynamic video; -} - /// [MediaTrackSupportedConstraints] represents the list of constraints /// controlling the capabilities of a [MediaStreamTrack]. class MediaTrackSupportedConstraints { diff --git a/lib/src/rtc_configuration.dart b/lib/src/rtc_configuration.dart index 0cac1a2..1297636 100644 --- a/lib/src/rtc_configuration.dart +++ b/lib/src/rtc_configuration.dart @@ -1,54 +1,66 @@ -// abstract class RTCOfferOptions { -// RTCOfferOptions({ -// bool iceRestart, -// bool offerToReceiveAudio, -// bool offerToReceiveVideo, -// bool voiceActivityDetection, -// }); -// bool get iceRestart; -// bool get offerToReceiveAudio; -// bool get offerToReceiveVideo; -// bool get voiceActivityDetection; -// } - -// abstract class RTCAnswerOptions { -// RTCAnswerOptions({bool voiceActivityDetection}); -// bool get voiceActivityDetection; -// } - -// abstract class RTCConfiguration { -// RTCConfiguration({ -// List iceServers, -// String rtcpMuxPolicy, -// String iceTransportPolicy, -// String bundlePolicy, -// String peerIdentity, -// int iceCandidatePoolSize, -// }); -// List get iceServers; - -// ///Optional: 'negotiate' or 'require' -// String get rtcpMuxPolicy; - -// ///Optional: 'relay' or 'all' -// String get iceTransportPolicy; - -// /// A DOMString which specifies the target peer identity for the -// /// RTCPeerConnection. If this value is set (it defaults to null), -// /// the RTCPeerConnection will not connect to a remote peer unless -// /// it can successfully authenticate with the given name. -// String get peerIdentity; - -// int get iceCandidatePoolSize; - -// ///Optional: 'balanced' | 'max-compat' | 'max-bundle' -// String get bundlePolicy; -// } - -// abstract class RTCIceServer { -// RTCIceServer({String urls, String username, String credential}); -// // String or List -// dynamic get urls; -// String get username; -// String get credential; -// } +class RTCOfferOptions { + bool? iceRestart; + bool? offerToReceiveAudio; + bool? offerToReceiveVideo; + bool? voiceActivityDetection; +} + +class RTCAnswerOptions { + bool? voiceActivityDetection; +} + +class RTCConfiguration { + RTCConfiguration( + {this.iceServers, + this.rtcpMuxPolicy, + this.iceTransportPolicy, + this.peerIdentity, + this.iceCandidatePoolSize, + this.bundlePolicy}); + factory RTCConfiguration.fromMap(Map map) { + return RTCConfiguration( + iceServers: map['iceServers'] != null + ? (map['iceServers'] as List) + .map((e) => RTCIceServer.fromMap(e)) + .toList() + : null, + rtcpMuxPolicy: map['rtcpMuxPolicy'], + iceTransportPolicy: map['iceTransportPolicy'], + peerIdentity: map['peerIdentity'], + iceCandidatePoolSize: map['iceCandidatePoolSize'], + bundlePolicy: map['bundlePolicy'], + ); + } + List? iceServers; + + ///Optional: 'negotiate' or 'require' + String? rtcpMuxPolicy; + + ///Optional: 'relay' or 'all' + String? iceTransportPolicy; + + /// A DOMString which specifies the target peer identity for the + /// RTCPeerConnection. If this value is set (it defaults to null), + /// the RTCPeerConnection will not connect to a remote peer unless + /// it can successfully authenticate with the given name. + String? peerIdentity; + + int? iceCandidatePoolSize; + + ///Optional: 'balanced' | 'max-compat' | 'max-bundle' + String? bundlePolicy; +} + +class RTCIceServer { + RTCIceServer({this.urls, this.username, this.credential}); + factory RTCIceServer.fromMap(Map map) { + return RTCIceServer( + urls: map['urls'] != null ? List.from(map['urls']) : null, + username: map['username'], + credential: map['credential'], + ); + } + List? urls; + String? username; + String? credential; +} diff --git a/lib/src/rtc_peerconnection.dart b/lib/src/rtc_peerconnection.dart index a7d26d0..dd7c7a1 100644 --- a/lib/src/rtc_peerconnection.dart +++ b/lib/src/rtc_peerconnection.dart @@ -22,10 +22,16 @@ abstract class RTCPeerConnection { Function(RTCIceGatheringState state)? onIceGatheringState; Function(RTCIceConnectionState state)? onIceConnectionState; Function(RTCIceCandidate candidate)? onIceCandidate; + + @Deprecated('Deprecated API') Function(MediaStream stream)? onAddStream; + @Deprecated('Deprecated API') Function(MediaStream stream)? onRemoveStream; + @Deprecated('Deprecated API') Function(MediaStream stream, MediaStreamTrack track)? onAddTrack; + @Deprecated('Deprecated API') Function(MediaStream stream, MediaStreamTrack track)? onRemoveTrack; + Function(RTCDataChannel channel)? onDataChannel; Function()? onRenegotiationNeeded; @@ -67,8 +73,10 @@ abstract class RTCPeerConnection { Future createAnswer( [Map constraints]); + @Deprecated('Deprecated API') Future addStream(MediaStream stream); + @Deprecated('Deprecated API') Future removeStream(MediaStream stream); Future getLocalDescription(); @@ -83,8 +91,10 @@ abstract class RTCPeerConnection { Future> getStats([MediaStreamTrack? track]); + @Deprecated('Deprecated API') List getLocalStreams(); + @Deprecated('Deprecated API') List getRemoteStreams(); Future createDataChannel( @@ -94,6 +104,7 @@ abstract class RTCPeerConnection { Future close(); + @Deprecated('Deprecated API, use RTCRtpSender.dtmf instead') RTCDTMFSender createDtmfSender(MediaStreamTrack track); /// Unified-Plan. diff --git a/lib/webrtc_interface.dart b/lib/webrtc_interface.dart index 0f90fca..7308a58 100644 --- a/lib/webrtc_interface.dart +++ b/lib/webrtc_interface.dart @@ -3,11 +3,13 @@ library webrtc_interface; export 'src/enums.dart'; export 'src/factory.dart'; export 'src/frame_cryptor.dart'; +export 'src/media_constraints.dart'; export 'src/media_recorder.dart'; export 'src/media_stream.dart'; export 'src/media_stream_track.dart'; export 'src/mediadevices.dart'; export 'src/navigator.dart'; +export 'src/rtc_configuration.dart'; export 'src/rtc_data_channel.dart'; export 'src/rtc_dtmf_sender.dart'; export 'src/rtc_ice_candidate.dart';