Change AudioSession configuration logic (#104)

* impl

* ref

* ref
This commit is contained in:
Hiroshi Horie
2022-04-08 01:58:49 +09:00
committed by GitHub
parent 8c227574ac
commit 84b9ef130f
5 changed files with 111 additions and 55 deletions
+9
View File
@@ -81,6 +81,9 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
); );
addTrackPublication(pub); addTrackPublication(pub);
// did publish
await track.onPublish();
[events, room.events].emit(LocalTrackPublishedEvent( [events, room.events].emit(LocalTrackPublishedEvent(
participant: this, participant: this,
publication: pub, publication: pub,
@@ -175,6 +178,9 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
); );
addTrackPublication(pub); addTrackPublication(pub);
// did publish
await track.onPublish();
[events, room.events].emit(LocalTrackPublishedEvent( [events, room.events].emit(LocalTrackPublishedEvent(
participant: this, participant: this,
publication: pub, publication: pub,
@@ -215,6 +221,9 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
await room.engine.negotiate(); await room.engine.negotiate();
} }
} }
// did unpublish
await track.onUnpublish();
} }
if (notify) { if (notify) {
+67 -52
View File
@@ -4,8 +4,8 @@ import '../logger.dart';
import '../support/native.dart'; import '../support/native.dart';
import '../support/native_audio.dart'; import '../support/native_audio.dart';
import '../support/platform.dart'; import '../support/platform.dart';
import 'local/audio.dart';
import 'local/local.dart'; import 'local/local.dart';
import 'remote/remote.dart';
enum AudioTrackState { enum AudioTrackState {
none, none,
@@ -17,29 +17,51 @@ enum AudioTrackState {
typedef ConfigureNativeAudioFunc = Future<NativeAudioConfiguration> Function( typedef ConfigureNativeAudioFunc = Future<NativeAudioConfiguration> Function(
AudioTrackState state); AudioTrackState state);
mixin AudioManagementMixin on AudioTrack { // it's possible to set custom function here to customize audio session configuration
// it's possible to set custom function here to customize audio session configuration ConfigureNativeAudioFunc onConfigureNativeAudio =
static ConfigureNativeAudioFunc nativeAudioConfigurationForAudioTrackState = defaultNativeAudioConfigurationFunc;
defaultNativeAudioConfigurationFunc;
static final _trackCounterLock = sync.Lock(); final _trackCounterLock = sync.Lock();
static AudioTrackState audioTrackState = AudioTrackState.none; AudioTrackState _audioTrackState = AudioTrackState.none;
static int _localTrackCount = 0; int _localTrackCount = 0;
static int _remoteTrackCount = 0; int _remoteTrackCount = 0;
mixin LocalAudioManagementMixin on LocalTrack, AudioTrack {
@override
Future<bool> onPublish() async {
final didUpdate = await super.onPublish();
if (didUpdate) {
// update counter
await _trackCounterLock.synchronized(() async {
_localTrackCount++;
await _onAudioTrackCountDidChange();
});
}
return didUpdate;
}
@override
Future<bool> onUnpublish() async {
final didUpdate = await super.onUnpublish();
if (didUpdate) {
// update counter
await _trackCounterLock.synchronized(() async {
_localTrackCount--;
await _onAudioTrackCountDidChange();
});
}
return didUpdate;
}
}
mixin RemoteAudioManagementMixin on RemoteTrack, AudioTrack {
/// Start playing audio track. On web platform, create an audio element and /// Start playing audio track. On web platform, create an audio element and
/// start playback /// start playback
@override @override
Future<bool> start() async { Future<bool> start() async {
final didStart = await super.start(); final didStart = await super.start();
if (didStart) { if (didStart) {
// update counter
await _trackCounterLock.synchronized(() async { await _trackCounterLock.synchronized(() async {
if (this is LocalAudioTrack) { _remoteTrackCount++;
_localTrackCount++;
} else if (this is! LocalAudioTrack) {
_remoteTrackCount++;
}
await _onAudioTrackCountDidChange(); await _onAudioTrackCountDidChange();
}); });
} }
@@ -50,59 +72,52 @@ mixin AudioManagementMixin on AudioTrack {
Future<bool> stop() async { Future<bool> stop() async {
final didStop = await super.stop(); final didStop = await super.stop();
if (didStop) { if (didStop) {
// update counter
await _trackCounterLock.synchronized(() async { await _trackCounterLock.synchronized(() async {
if (this is LocalAudioTrack) { _remoteTrackCount--;
_localTrackCount--;
} else if (this is! LocalAudioTrack) {
_remoteTrackCount--;
}
await _onAudioTrackCountDidChange(); await _onAudioTrackCountDidChange();
}); });
} }
return didStop; return didStop;
} }
}
Future<void> _onAudioTrackCountDidChange() async { Future<void> _onAudioTrackCountDidChange() async {
logger.fine('[$runtimeType] onAudioTrackCountDidChange: ' logger.fine('onAudioTrackCountDidChange: '
'local: $_localTrackCount, remote: $_remoteTrackCount'); 'local: $_localTrackCount, remote: $_remoteTrackCount');
final newState = _computeAudioTrackState(); final newState = _computeAudioTrackState();
if (audioTrackState != newState) { if (_audioTrackState != newState) {
audioTrackState = newState; _audioTrackState = newState;
logger.fine('[$runtimeType] didUpdateSate: $audioTrackState'); logger.fine('didUpdateSate: $_audioTrackState');
NativeAudioConfiguration? config; NativeAudioConfiguration? config;
if (lkPlatformIs(PlatformType.iOS)) { if (lkPlatformIs(PlatformType.iOS)) {
// Only iOS for now... // Only iOS for now...
config = await nativeAudioConfigurationForAudioTrackState config = await onConfigureNativeAudio.call(_audioTrackState);
.call(audioTrackState); }
}
if (config != null) { if (config != null) {
logger.fine( logger.fine('configuring for ${_audioTrackState} using ${config}...');
'[$runtimeType] configuring for ${audioTrackState} using ${config}...'); try {
try { await Native.configureAudio(config);
await Native.configureAudio(config); } catch (error) {
} catch (error) { logger.warning('failed to configure ${error}');
logger.warning('[$runtimeType] Failed to configure ${error}');
}
} }
} }
} }
}
static AudioTrackState _computeAudioTrackState() { AudioTrackState _computeAudioTrackState() {
if (_localTrackCount > 0 && _remoteTrackCount == 0) { if (_localTrackCount > 0 && _remoteTrackCount == 0) {
return AudioTrackState.localOnly; return AudioTrackState.localOnly;
} else if (_localTrackCount == 0 && _remoteTrackCount > 0) { } else if (_localTrackCount == 0 && _remoteTrackCount > 0) {
return AudioTrackState.remoteOnly; return AudioTrackState.remoteOnly;
} else if (_localTrackCount > 0 && _remoteTrackCount > 0) { } else if (_localTrackCount > 0 && _remoteTrackCount > 0) {
return AudioTrackState.localAndRemote; return AudioTrackState.localAndRemote;
}
// Default
return AudioTrackState.none;
} }
// Default
return AudioTrackState.none;
} }
Future<NativeAudioConfiguration> defaultNativeAudioConfigurationFunc( Future<NativeAudioConfiguration> defaultNativeAudioConfigurationFunc(
+2 -1
View File
@@ -8,7 +8,8 @@ import '../audio_management.dart';
import '../options.dart'; import '../options.dart';
import 'local.dart'; import 'local.dart';
class LocalAudioTrack extends LocalTrack with AudioTrack, AudioManagementMixin { class LocalAudioTrack extends LocalTrack
with AudioTrack, LocalAudioManagementMixin {
// Options used for this track // Options used for this track
@override @override
covariant AudioCaptureOptions currentOptions; covariant AudioCaptureOptions currentOptions;
+32 -1
View File
@@ -1,10 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../../events.dart'; import '../../events.dart';
import '../../exceptions.dart'; import '../../exceptions.dart';
import '../../extensions.dart';
import '../../logger.dart'; import '../../logger.dart';
import '../../participant/remote.dart'; import '../../participant/remote.dart';
import '../../proto/livekit_models.pb.dart' as lk_models; import '../../proto/livekit_models.pb.dart' as lk_models;
@@ -46,6 +46,9 @@ abstract class LocalTrack extends Track {
/// Options used for this track /// Options used for this track
abstract LocalTrackOptions currentOptions; abstract LocalTrackOptions currentOptions;
bool _published = false;
bool get isPublished => _published;
LocalTrack( LocalTrack(
String name, String name,
lk_models.TrackType kind, lk_models.TrackType kind,
@@ -170,4 +173,32 @@ abstract class LocalTrack extends Track {
// mark as started // mark as started
await start(); await start();
} }
@internal
@mustCallSuper
Future<bool> onPublish() async {
if (_published) {
// already published
return false;
}
logger.fine('$objectId.publish()');
_published = true;
return true;
}
@internal
@mustCallSuper
Future<bool> onUnpublish() async {
if (!_published) {
// already unpublished
return false;
}
logger.fine('$objectId.unpublish()');
_published = false;
return true;
}
} }
+1 -1
View File
@@ -10,7 +10,7 @@ import '../web/_audio_api.dart' if (dart.library.html) '../web/_audio_html.dart'
as audio; as audio;
class RemoteAudioTrack extends RemoteTrack class RemoteAudioTrack extends RemoteTrack
with AudioTrack, AudioManagementMixin { with AudioTrack, RemoteAudioManagementMixin {
// //
RemoteAudioTrack( RemoteAudioTrack(
String name, String name,