Subscriber as primary (#8)

* Update protos

* Signal client

* Improve transport

* First implementation

* Fix publish

* Update `PCTransport` for debounce negotiation

* debounce func

* reconnect & events

* Update debounce func

* engine events

* make sure events don't emit after dispose

* prefix flutter_webrtc

* Cleaner `iceServers` update

* don't mutate user provided params

* fix tests

* event manager

* Fix: `Room.onDisconnected` gets fired multiple times

* data publish in example

* cleaner logic

* safer events

* un-prefix with LK

* organize imports

* Clean up

* remove `Tuple`

* `EventsEmitter` can now be directly listened to

`EventsEmitter` extends `EventsListenable`
This commit is contained in:
Hiroshi Horie
2021-09-18 00:10:16 +09:00
committed by GitHub
parent 50f56c5e1e
commit f4bd82a919
36 changed files with 1334 additions and 588 deletions
+64 -35
View File
@@ -1,6 +1,25 @@
enum RTCIceTransportPolicy {
all,
relay,
import 'dart:convert';
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'proto/livekit_rtc.pb.dart' as lk_rtc;
import 'proto/livekit_models.pb.dart' as lk_models;
import 'types.dart';
extension IterableExt<E> on Iterable<E> {
E? elementAtOrNull(int index) => (index >= 0 && index < length) ? elementAt(index) : null;
}
extension RTCIceConnectionStateExt on rtc.RTCIceConnectionState {
bool isConnected() => [
rtc.RTCIceConnectionState.RTCIceConnectionStateConnected,
rtc.RTCIceConnectionState.RTCIceConnectionStateCompleted,
].contains(this);
}
extension ObjectExt on Object {
String get objectId => '${runtimeType}#${hashCode}';
}
extension RTCIceTransportPolicyExt on RTCIceTransportPolicy {
@@ -10,41 +29,51 @@ extension RTCIceTransportPolicyExt on RTCIceTransportPolicy {
}[this]!;
}
class RTCConfiguration {
int? iceCandidatePoolSize;
List<RTCIceServer>? iceServers;
RTCIceTransportPolicy? iceTransportPolicy;
Map<String, dynamic> toMap() {
final iceServersMap = <Map<String, dynamic>>[
if (iceServers != null)
for (final element in iceServers!) element.toMap()
];
return <String, dynamic>{
// only supports unified plan
'sdpSemantics': 'unified-plan',
if (iceServersMap.isNotEmpty) 'iceServers': iceServersMap,
if (iceCandidatePoolSize != null) 'iceCandidatePoolSize': iceCandidatePoolSize,
if (iceTransportPolicy != null) 'iceTransportPolicy': iceTransportPolicy!.toStringValue(),
};
extension SessionDescriptionExt on lk_rtc.SessionDescription {
rtc.RTCSessionDescription toSDKType() {
return rtc.RTCSessionDescription(sdp, type);
}
}
class RTCIceServer {
List<String> urls;
String? username;
String? credential;
extension RTCSessionDescriptionExt on rtc.RTCSessionDescription {
lk_rtc.SessionDescription toSDKType() {
return lk_rtc.SessionDescription(type: type, sdp: sdp);
}
}
RTCIceServer({
required this.urls,
this.username,
this.credential,
});
extension RTCIceCandidateExt on rtc.RTCIceCandidate {
static rtc.RTCIceCandidate fromJson(String jsonString) {
final map = json.decode(jsonString) as Map<String, dynamic>;
return rtc.RTCIceCandidate(
map['candidate'] as String?,
map['sdpMid'] as String?,
map['sdpMLineIndex'] as int?,
);
}
Map<String, dynamic> toMap() => <String, dynamic>{
'urls': urls,
if (username != null) 'username': username,
if (credential != null) 'credential': credential,
};
String toJson() => json.encode(toMap());
}
extension ICEServerExt on lk_rtc.ICEServer {
RTCIceServer toSDKType() => RTCIceServer(
urls: urls,
username: username.isNotEmpty ? username : null,
credential: credential.isNotEmpty ? username : null,
);
}
// not so neat to directly expose protobuf types so we
// define our own types (and convert methods)
extension DataPacketKindExt on lk_models.DataPacket_Kind {
Reliability toSDKType() => {
lk_models.DataPacket_Kind.RELIABLE: Reliability.reliable,
lk_models.DataPacket_Kind.LOSSY: Reliability.lossy,
}[this]!;
}
extension ReliabilityExt on Reliability {
lk_models.DataPacket_Kind toPBType() => {
Reliability.reliable: lk_models.DataPacket_Kind.RELIABLE,
Reliability.lossy: lk_models.DataPacket_Kind.LOSSY,
}[this]!;
}