Better audio management (#10)
* add audio_session package * `AudioManager` initial design * try to integrate audio manager * configure audio session * `DisposeAware` disposing if already published causes exception. * organize * guard flutter_webrtc calls * websocket async fix * use `ConnectionState` instead of `_isClosed` and `isReconnecting` * change create audio track defaults * update protos * protocol 3 speaker updates * fix exception * emit `RoomDisconnectedEvent` only once * fix exception * keep track of local / remote audio tracks * explicit types * manage track state * re-structure audio management * change defaults * unpublish all * use experimental build * change defaults * configuring is optional * call native `RTCAudioSession.setConfiguration` * defaults adjustment * iOS only for now * use lib 92.4515.07 * clean up * revert audio options for now * remove pod source * rename apple related audio * `createListener` method * organize native audio * `SpeakingChangedEvent` only on `Participant` * refactoring * fix ios compile * fix configure audio only for iOS logic * minor fix & clean up * change dispose logic * format protos * fix unpublishTrack * `createListener` into a mixin * simplify * use flutter_webrtc master * unpublish for example * update ios icon * android icon * web icon * favicon
This commit is contained in:
+33
-30
@@ -1,23 +1,23 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'errors.dart';
|
||||
import 'events.dart';
|
||||
import 'exceptions.dart';
|
||||
import 'extensions.dart';
|
||||
import 'logger.dart';
|
||||
import 'managers/event.dart';
|
||||
import 'options.dart';
|
||||
import 'proto/livekit_models.pb.dart' as lk_models;
|
||||
import 'proto/livekit_rtc.pb.dart' as lk_rtc;
|
||||
import 'support/disposable.dart';
|
||||
import 'support/websocket.dart';
|
||||
import 'types.dart';
|
||||
import 'utils.dart';
|
||||
import 'ws/interface.dart';
|
||||
|
||||
class SignalClient {
|
||||
final events = EventsEmitter<SignalEvent>();
|
||||
class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
|
||||
//
|
||||
final ProtocolVersion protocol;
|
||||
|
||||
bool _connected = false;
|
||||
@@ -29,6 +29,11 @@ class SignalClient {
|
||||
events.listen((event) {
|
||||
logger.fine('[SignalEvent] $event');
|
||||
});
|
||||
|
||||
onDispose(() async {
|
||||
await events.dispose();
|
||||
await close();
|
||||
});
|
||||
}
|
||||
|
||||
bool get connected => _connected;
|
||||
@@ -51,7 +56,7 @@ class SignalClient {
|
||||
try {
|
||||
_ws = await LiveKitWebSocket.connect(
|
||||
rtcUri,
|
||||
WebSocketOptions(
|
||||
WebSocketEventHandlers(
|
||||
onData: _onSocketData,
|
||||
onDispose: _onSocketDone,
|
||||
onError: _handleError,
|
||||
@@ -71,8 +76,7 @@ class SignalClient {
|
||||
// Attempt Validation
|
||||
try {
|
||||
final validateResponse = await http.get(validateUri);
|
||||
if (validateResponse.statusCode != 200)
|
||||
throw ConnectException(validateResponse.body);
|
||||
if (validateResponse.statusCode != 200) throw ConnectException(validateResponse.body);
|
||||
throw ConnectException();
|
||||
} catch (error) {
|
||||
// Pass it up if it's already a `ConnectError`
|
||||
@@ -88,7 +92,7 @@ class SignalClient {
|
||||
String token,
|
||||
) async {
|
||||
_connected = false;
|
||||
_ws?.dispose();
|
||||
await _ws?.dispose();
|
||||
_ws = null;
|
||||
|
||||
final rtcUri = Utils.buildUri(
|
||||
@@ -100,7 +104,7 @@ class SignalClient {
|
||||
|
||||
_ws = await LiveKitWebSocket.connect(
|
||||
rtcUri,
|
||||
WebSocketOptions(
|
||||
WebSocketEventHandlers(
|
||||
onData: _onSocketData,
|
||||
onDispose: _onSocketDone,
|
||||
onError: _handleError,
|
||||
@@ -110,24 +114,27 @@ class SignalClient {
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
void close() {
|
||||
Future<void> close() async {
|
||||
_connected = false;
|
||||
_ws?.dispose();
|
||||
await _ws?.dispose();
|
||||
}
|
||||
|
||||
void sendOffer(rtc.RTCSessionDescription offer) =>
|
||||
_sendRequest(lk_rtc.SignalRequest(
|
||||
// @override
|
||||
// Future<void> dispose() async {
|
||||
// super.dispose();
|
||||
// await events.dispose();
|
||||
// await close();
|
||||
// }
|
||||
|
||||
void sendOffer(rtc.RTCSessionDescription offer) => _sendRequest(lk_rtc.SignalRequest(
|
||||
offer: offer.toSDKType(),
|
||||
));
|
||||
|
||||
void sendAnswer(rtc.RTCSessionDescription answer) =>
|
||||
_sendRequest(lk_rtc.SignalRequest(
|
||||
void sendAnswer(rtc.RTCSessionDescription answer) => _sendRequest(lk_rtc.SignalRequest(
|
||||
answer: answer.toSDKType(),
|
||||
));
|
||||
|
||||
void sendIceCandidate(
|
||||
rtc.RTCIceCandidate candidate, lk_rtc.SignalTarget target) =>
|
||||
_sendRequest(
|
||||
void sendIceCandidate(rtc.RTCIceCandidate candidate, lk_rtc.SignalTarget target) => _sendRequest(
|
||||
lk_rtc.SignalRequest(
|
||||
trickle: lk_rtc.TrickleRequest(
|
||||
candidateInit: candidate.toJson(),
|
||||
@@ -136,8 +143,7 @@ class SignalClient {
|
||||
),
|
||||
);
|
||||
|
||||
void sendMuteTrack(String trackSid, bool muted) =>
|
||||
_sendRequest(lk_rtc.SignalRequest(
|
||||
void sendMuteTrack(String trackSid, bool muted) => _sendRequest(lk_rtc.SignalRequest(
|
||||
mute: lk_rtc.MuteTrackRequest(
|
||||
sid: trackSid,
|
||||
muted: muted,
|
||||
@@ -174,8 +180,7 @@ class SignalClient {
|
||||
subscription: subscription,
|
||||
));
|
||||
|
||||
void sendSetSimulcastLayers(
|
||||
String trackSid, List<lk_rtc.VideoQuality> layers) =>
|
||||
void sendSetSimulcastLayers(String trackSid, List<lk_rtc.VideoQuality> layers) =>
|
||||
_sendRequest(lk_rtc.SignalRequest(
|
||||
simulcast: lk_rtc.SetSimulcastLayers(
|
||||
trackSid: trackSid,
|
||||
@@ -188,8 +193,8 @@ class SignalClient {
|
||||
));
|
||||
|
||||
void _sendRequest(lk_rtc.SignalRequest req) {
|
||||
if (_ws == null) {
|
||||
logger.warning('could not send message, not connected');
|
||||
if (_ws == null || isDisposed) {
|
||||
logger.warning('[$objectId] Could not send message, not connected or already disposed');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,8 +226,7 @@ class SignalClient {
|
||||
));
|
||||
break;
|
||||
case lk_rtc.SignalResponse_Message.update:
|
||||
events.emit(
|
||||
SignalParticipantUpdateEvent(updates: msg.update.participants));
|
||||
events.emit(SignalParticipantUpdateEvent(participants: msg.update.participants));
|
||||
break;
|
||||
case lk_rtc.SignalResponse_Message.trackPublished:
|
||||
events.emit(SignalLocalTrackPublishedEvent(
|
||||
@@ -230,9 +234,8 @@ class SignalClient {
|
||||
track: msg.trackPublished.track,
|
||||
));
|
||||
break;
|
||||
case lk_rtc.SignalResponse_Message.speaker:
|
||||
events.emit(
|
||||
SignalActiveSpeakersChangedEvent(speakers: msg.speaker.speakers));
|
||||
case lk_rtc.SignalResponse_Message.speakersChanged:
|
||||
events.emit(SignalSpeakersChangedEvent(speakers: msg.speakersChanged.speakers));
|
||||
break;
|
||||
case lk_rtc.SignalResponse_Message.leave:
|
||||
events.emit(SignalLeaveEvent(canReconnect: msg.leave.canReconnect));
|
||||
|
||||
Reference in New Issue
Block a user