Files
client-sdk-flutter/lib/src/track/audio_management.dart
T
a23eb6332c Audio mute unmute fixes (#234)
* progress

* refresh

* Create Podfile.lock

* Update Podfile.lock

* pub

* update deps.

* fix tests

* dart format .

* fix duplicate imports

---------

Co-authored-by: cloudwebrtc <[email protected]>
2023-02-06 12:43:27 +09:00

154 lines
4.2 KiB
Dart

import 'package:synchronized/synchronized.dart' as sync;
import '../logger.dart';
import '../support/native.dart';
import '../support/native_audio.dart';
import '../support/platform.dart';
import 'local/local.dart';
import 'remote/remote.dart';
enum AudioTrackState {
none,
remoteOnly,
localOnly,
localAndRemote,
}
typedef ConfigureNativeAudioFunc = Future<NativeAudioConfiguration> Function(
AudioTrackState state);
// it's possible to set custom function here to customize audio session configuration
ConfigureNativeAudioFunc onConfigureNativeAudio =
defaultNativeAudioConfigurationFunc;
final _trackCounterLock = sync.Lock();
AudioTrackState _audioTrackState = AudioTrackState.none;
int _localTrackCount = 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 playback
@override
Future<bool> start() async {
final didStart = await super.start();
if (didStart) {
await _trackCounterLock.synchronized(() async {
_remoteTrackCount++;
await _onAudioTrackCountDidChange();
});
}
return didStart;
}
@override
Future<bool> stop() async {
final didStop = await super.stop();
if (didStop) {
await _trackCounterLock.synchronized(() async {
_remoteTrackCount--;
await _onAudioTrackCountDidChange();
});
}
return didStop;
}
}
Future<void> _onAudioTrackCountDidChange() async {
logger.fine('onAudioTrackCountDidChange: '
'local: $_localTrackCount, remote: $_remoteTrackCount');
final newState = _computeAudioTrackState();
if (_audioTrackState != newState) {
_audioTrackState = newState;
logger.fine('didUpdateSate: $_audioTrackState');
NativeAudioConfiguration? config;
if (lkPlatformIs(PlatformType.iOS)) {
// Only iOS for now...
config = await onConfigureNativeAudio.call(_audioTrackState);
}
if (config != null) {
logger.fine('configuring for ${_audioTrackState} using ${config}...');
try {
await Native.configureAudio(config);
} catch (error) {
logger.warning('failed to configure ${error}');
}
}
}
}
AudioTrackState _computeAudioTrackState() {
if (_localTrackCount > 0 && _remoteTrackCount == 0) {
return AudioTrackState.localOnly;
} else if (_localTrackCount == 0 && _remoteTrackCount > 0) {
return AudioTrackState.remoteOnly;
} else if (_localTrackCount > 0 && _remoteTrackCount > 0) {
return AudioTrackState.localAndRemote;
}
// Default
return AudioTrackState.none;
}
Future<NativeAudioConfiguration> defaultNativeAudioConfigurationFunc(
AudioTrackState state) async {
//
if (state == AudioTrackState.remoteOnly) {
return NativeAudioConfiguration(
appleAudioCategory: AppleAudioCategory.playback,
appleAudioCategoryOptions: {
AppleAudioCategoryOption.mixWithOthers,
},
appleAudioMode: AppleAudioMode.spokenAudio,
);
} else if ([
AudioTrackState.localOnly,
AudioTrackState.localAndRemote,
].contains(state)) {
return NativeAudioConfiguration(
appleAudioCategory: AppleAudioCategory.playAndRecord,
appleAudioCategoryOptions: {
AppleAudioCategoryOption.allowBluetooth,
AppleAudioCategoryOption.mixWithOthers,
},
appleAudioMode: AppleAudioMode.videoChat,
);
}
return NativeAudioConfiguration(
appleAudioCategory: AppleAudioCategory.soloAmbient,
appleAudioCategoryOptions: {},
appleAudioMode: AppleAudioMode.default_,
);
}