From cc470d345343ceac25624bb3835e93065f6411b9 Mon Sep 17 00:00:00 2001
From: cloudwebrtc <duanweiwei1982@gmail.com>
Date: Mon, 8 Apr 2024 13:58:46 +0800
Subject: [PATCH 1/3] fix/migrate-dart-html-to-web-pkg.

---
 lib/src/factory.dart            |   5 ++
 lib/src/frame_cryptor.dart      |  22 +++++
 lib/src/media_constraints.dart  | 150 ++++++++++++++++++++++++++++++++
 lib/src/mediadevices.dart       |  18 ----
 lib/src/rtc_configuration.dart  | 120 +++++++++++++------------
 lib/src/rtc_peerconnection.dart |  11 +++
 lib/webrtc_interface.dart       |   2 +
 7 files changed, 256 insertions(+), 72 deletions(-)
 create mode 100644 lib/src/media_constraints.dart

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<RTCPeerConnection> createPeerConnection(
       Map<String, dynamic> configuration,
       [Map<String, dynamic> constraints]);
 
+  Future<RTCPeerConnection> newPeerConnection(RTCConfiguration configuration) =>
+      throw UnimplementedError();
+
   Future<MediaStream> createLocalMediaStream(String label);
 
   Future<RTCRtpCapabilities> getRtpSenderCapabilities(String kind);
diff --git a/lib/src/frame_cryptor.dart b/lib/src/frame_cryptor.dart
index 4308dd1..5268124 100644
--- a/lib/src/frame_cryptor.dart
+++ b/lib/src/frame_cryptor.dart
@@ -16,12 +16,19 @@ class KeyProviderOptions {
     required this.ratchetWindowSize,
     this.uncryptedMagicBytes,
     this.failureTolerance = -1,
+    this.key_ring_size = 16,
+    this.discard_frame_when_cryptor_not_ready = false,
   });
   bool sharedKey;
   Uint8List ratchetSalt;
   Uint8List? uncryptedMagicBytes;
   int ratchetWindowSize;
   int failureTolerance;
+
+  /// key ring size should be between 1 and 255
+  /// default is 16
+  int key_ring_size;
+  bool discard_frame_when_cryptor_not_ready;
   Map<String, dynamic> toJson() {
     return {
       'sharedKey': sharedKey,
@@ -30,6 +37,8 @@ class KeyProviderOptions {
         'uncryptedMagicBytes': uncryptedMagicBytes,
       'ratchetWindowSize': ratchetWindowSize,
       'failureTolerance': failureTolerance,
+      'keyRingSize': key_ring_size,
+      'discardFrameWhenCryptorNotReady': discard_frame_when_cryptor_not_ready,
     };
   }
 }
@@ -84,6 +93,19 @@ enum FrameCryptorState {
   FrameCryptorStateInternalError,
 }
 
+class FrameCryptorOptions {
+  FrameCryptorOptions({
+    this.discardUnableDecryptedFrames = false,
+  });
+
+  /// Discard frames when frame crypto is disabled.
+  /// Because of the wrong key or decoding the encrypted frame or outputting
+  /// garbled audio
+  /// when called FrameCryptor.setEnabled(false); if this parameter is true, the
+  /// frame will discarded
+  final bool discardUnableDecryptedFrames;
+}
+
 /// Frame encryption/decryption.
 ///
 abstract class FrameCryptor {
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<String, dynamic> map) {
+    return MediaTrackConstraints(
+      deviceId: map['deviceId'] as String?,
+      groupId: map['groupId'] as String?,
+    );
+  }
+  final String? deviceId;
+  final String? groupId;
+
+  Map<String, dynamic> toMap() {
+    return <String, dynamic>{
+      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<String, dynamic> 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<String, dynamic> toMap() {
+    return <String, dynamic>{
+      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<String, dynamic> 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<String, dynamic> toMap() {
+    return <String, dynamic>{
+      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<String, dynamic> 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<String, dynamic> toMap() {
+    return <String, dynamic>{
+      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<RTCIceServer> iceServers,
-//     String rtcpMuxPolicy,
-//     String iceTransportPolicy,
-//     String bundlePolicy,
-//     String peerIdentity,
-//     int iceCandidatePoolSize,
-//   });
-//   List<RTCIceServer> 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<String>
-//   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<String, dynamic> 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<RTCIceServer>? 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<String, dynamic> map) {
+    return RTCIceServer(
+      urls: map['urls'] != null ? List<String>.from(map['urls']) : null,
+      username: map['username'],
+      credential: map['credential'],
+    );
+  }
+  List<String>? 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<RTCSessionDescription> createAnswer(
       [Map<String, dynamic> constraints]);
 
+  @Deprecated('Deprecated API')
   Future<void> addStream(MediaStream stream);
 
+  @Deprecated('Deprecated API')
   Future<void> removeStream(MediaStream stream);
 
   Future<RTCSessionDescription?> getLocalDescription();
@@ -83,8 +91,10 @@ abstract class RTCPeerConnection {
 
   Future<List<StatsReport>> getStats([MediaStreamTrack? track]);
 
+  @Deprecated('Deprecated API')
   List<MediaStream?> getLocalStreams();
 
+  @Deprecated('Deprecated API')
   List<MediaStream?> getRemoteStreams();
 
   Future<RTCDataChannel> createDataChannel(
@@ -94,6 +104,7 @@ abstract class RTCPeerConnection {
 
   Future<void> 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';

From e31af0a93f618dcaf5ddcea240637748c6654fae Mon Sep 17 00:00:00 2001
From: cloudwebrtc <duanweiwei1982@gmail.com>
Date: Mon, 8 Apr 2024 13:59:57 +0800
Subject: [PATCH 2/3] cleanup.

---
 lib/src/frame_cryptor.dart | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/lib/src/frame_cryptor.dart b/lib/src/frame_cryptor.dart
index 5268124..a28addb 100644
--- a/lib/src/frame_cryptor.dart
+++ b/lib/src/frame_cryptor.dart
@@ -93,19 +93,6 @@ enum FrameCryptorState {
   FrameCryptorStateInternalError,
 }
 
-class FrameCryptorOptions {
-  FrameCryptorOptions({
-    this.discardUnableDecryptedFrames = false,
-  });
-
-  /// Discard frames when frame crypto is disabled.
-  /// Because of the wrong key or decoding the encrypted frame or outputting
-  /// garbled audio
-  /// when called FrameCryptor.setEnabled(false); if this parameter is true, the
-  /// frame will discarded
-  final bool discardUnableDecryptedFrames;
-}
-
 /// Frame encryption/decryption.
 ///
 abstract class FrameCryptor {

From ac08b9dbb103db44073707b01d2d495a6dd93fb7 Mon Sep 17 00:00:00 2001
From: cloudwebrtc <duanweiwei1982@gmail.com>
Date: Mon, 8 Apr 2024 14:32:02 +0800
Subject: [PATCH 3/3] revert changes.

---
 lib/src/frame_cryptor.dart | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/lib/src/frame_cryptor.dart b/lib/src/frame_cryptor.dart
index a28addb..4308dd1 100644
--- a/lib/src/frame_cryptor.dart
+++ b/lib/src/frame_cryptor.dart
@@ -16,19 +16,12 @@ class KeyProviderOptions {
     required this.ratchetWindowSize,
     this.uncryptedMagicBytes,
     this.failureTolerance = -1,
-    this.key_ring_size = 16,
-    this.discard_frame_when_cryptor_not_ready = false,
   });
   bool sharedKey;
   Uint8List ratchetSalt;
   Uint8List? uncryptedMagicBytes;
   int ratchetWindowSize;
   int failureTolerance;
-
-  /// key ring size should be between 1 and 255
-  /// default is 16
-  int key_ring_size;
-  bool discard_frame_when_cryptor_not_ready;
   Map<String, dynamic> toJson() {
     return {
       'sharedKey': sharedKey,
@@ -37,8 +30,6 @@ class KeyProviderOptions {
         'uncryptedMagicBytes': uncryptedMagicBytes,
       'ratchetWindowSize': ratchetWindowSize,
       'failureTolerance': failureTolerance,
-      'keyRingSize': key_ring_size,
-      'discardFrameWhenCryptorNotReady': discard_frame_when_cryptor_not_ready,
     };
   }
 }