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:
Hiroshi Horie
2021-10-01 02:47:18 +09:00
committed by GitHub
parent ec17907cdc
commit 001f688729
101 changed files with 1658 additions and 681 deletions
+16 -2
View File
@@ -1,9 +1,14 @@
import 'package:async/async.dart';
class CancelableDelayManager {
import '../support/disposable.dart';
class CancelableDelayManager extends Disposable {
//
final _delays = <CancelableOperation<void>>[];
CancelableDelayManager() {
onDispose(() async => await cancelAll());
}
// delay but cancelable
Future<void> waitFor(
Duration wait, {
@@ -19,7 +24,16 @@ class CancelableDelayManager {
if (!op.isCanceled) ifNotCancelled?.call();
}
Future<void> dispose() async {
// @override
// Future<bool> dispose() async {
// final didDispose = await super.dispose();
// if (didDispose) {
// await cancelAll();
// }
// return didDispose;
// }
Future<void> cancelAll() async {
// cancel all delays
if (_delays.isEmpty) return;
// make a copy so we don't mutate while iterating
+38 -20
View File
@@ -1,13 +1,19 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:synchronized/synchronized.dart' as sync;
import '../errors.dart';
import '../exceptions.dart';
import '../extensions.dart';
import '../logger.dart';
import '../support/disposable.dart';
import '../types.dart';
mixin EventsEmittable<T> {
final events = EventsEmitter<T>();
EventsListener<T> createListener({bool synchronized = false}) =>
EventsListener<T>(events, synchronized: synchronized);
}
// Type-safe, multi-listenable, dispose safe event handling
// TODO: Move to a separate package
@@ -17,7 +23,9 @@ class EventsEmitter<T> extends EventsListenable<T> {
EventsEmitter({
bool listenSynchronized = false,
}) : super(synchronized: listenSynchronized);
}) : super(synchronized: listenSynchronized) {
onDispose(() async => await streamCtrl.close());
}
@override
EventsEmitter<T> get emitter => this;
@@ -28,13 +36,6 @@ class EventsEmitter<T> extends EventsListenable<T> {
// emit the event
streamCtrl.add(event);
}
@override
@mustCallSuper
Future<void> dispose() async {
await streamCtrl.close();
await super.dispose();
}
}
// for listening only
@@ -51,7 +52,7 @@ class EventsListener<T> extends EventsListenable<T> {
}
// ensures all listeners will close on dispose
abstract class EventsListenable<T> {
abstract class EventsListenable<T> extends Disposable {
// the emitter to listen to
EventsEmitter<T> get emitter;
@@ -62,17 +63,34 @@ abstract class EventsListenable<T> {
EventsListenable({
required this.synchronized,
});
@mustCallSuper
Future<void> dispose() async {
// Stop listening to all events
logger.fine('${objectId} dispose() cancelling ${_listeners.length} event(s)');
for (final listener in _listeners) {
await listener.cancel();
}
}) {
onDispose(() async {
if (_listeners.isNotEmpty) {
// Stop listening to all events
logger.fine('${objectId} cancelling ${_listeners.length} listeners(s)');
for (final listener in _listeners) {
await listener.cancel();
}
}
});
}
// @override
// @mustCallSuper
// Future<bool> dispose() async {
// // mark as disposed
// final didDispose = await super.dispose();
// if (didDispose && _listeners.isNotEmpty) {
// // Stop listening to all events
// logger.fine('${objectId} dispose() cancelling ${_listeners.length} event(s)');
// for (final listener in _listeners) {
// await listener.cancel();
// }
// }
// return didDispose;
// }
// listens to all events, guaranteed to be cancelled on dispose
CancelListenFunc listen(FutureOr<void> Function(T) onEvent) {
//