Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: respecting default audio output setting #608

Merged
merged 5 commits into from Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/stream_video/lib/src/call/call.dart
Expand Up @@ -1192,11 +1192,24 @@ class Call {
custom: custom,
);

final mediaDevicesResult =
await RtcMediaDeviceNotifier.instance.enumerateDevices();
final mediaDevices = mediaDevicesResult.fold(
success: (success) => success.data,
failure: (failure) => <RtcMediaDevice>[],
);

return response.fold(
success: (it) {
_stateManager.lifecycleCallCreated(
CallCreated(it.data.data),
ringing: ringing,
audioOutputs: mediaDevices
.where((d) => d.kind == RtcMediaDeviceKind.audioOutput)
.toList(),
audioInputs: mediaDevices
.where((d) => d.kind == RtcMediaDeviceKind.audioInput)
.toList(),
);
_logger.v(() => '[getOrCreate] completed: ${it.data}');
return it;
Expand Down
Expand Up @@ -167,6 +167,13 @@ class CallSession extends Disposable {
if (CurrentPlatform.isIos) {
await rtcManager?.setAppleAudioConfiguration();
}

unawaited(
Future.delayed(const Duration(milliseconds: 250), () async {
Brazol marked this conversation as resolved.
Show resolved Hide resolved
await _applyCurrentAudioOutputDevice();
}),
);

_logger.v(() => '[start] completed');
return const Result.success(none);
} catch (e, stk) {
Expand Down
@@ -1,4 +1,5 @@
import 'package:state_notifier/state_notifier.dart';
import 'package:collection/collection.dart';

import '../../../../stream_video.dart';
import '../../../action/internal/lifecycle_action.dart';
Expand Down Expand Up @@ -101,7 +102,26 @@ mixin StateLifecycleMixin on StateNotifier<CallState> {
void lifecycleCallCreated(
CallCreated stage, {
bool ringing = false,
List<RtcMediaDevice>? audioOutputs,
List<RtcMediaDevice>? audioInputs,
}) {
final defaultAudioOutput = audioOutputs?.firstWhereOrNull((device) {
if (stage.data.metadata.settings.audio.defaultDevice ==
AudioSettingsRequestDefaultDeviceEnum.speaker) {
return device.id.equalsIgnoreCase(
AudioSettingsRequestDefaultDeviceEnum.speaker.value,
);
}

return !device.id.equalsIgnoreCase(
AudioSettingsRequestDefaultDeviceEnum.speaker.value,
);
});

final defaultAudioInput = audioInputs
?.firstWhereOrNull((d) => d.label == defaultAudioOutput?.label) ??
Brazol marked this conversation as resolved.
Show resolved Hide resolved
audioInputs?.firstOrNull;

_logger.d(() => '[lifecycleCallCreated] ringing: $ringing, state: $state');
state = state.copyWith(
status: stage.data.toCallStatus(state: state, ringing: ringing),
Expand All @@ -118,6 +138,8 @@ mixin StateLifecycleMixin on StateNotifier<CallState> {
isBackstage: stage.data.metadata.details.backstage,
isBroadcasting: stage.data.metadata.details.broadcasting,
isRecording: stage.data.metadata.details.recording,
audioOutputDevice: defaultAudioOutput,
audioInputDevice: defaultAudioInput,
);
}

Expand Down Expand Up @@ -361,3 +383,7 @@ extension on CallRingingData {
}
}
}

extension on String {
bool equalsIgnoreCase(String other) => toUpperCase() == other.toUpperCase();
}
@@ -1,6 +1,7 @@
import 'package:collection/collection.dart';

import '../../../../open_api/video/coordinator/api.dart' as open;
import '../../../stream_video.dart';
import '../../errors/video_error.dart';
import '../../logger/stream_log.dart';
import '../../models/call_cid.dart';
Expand Down Expand Up @@ -176,6 +177,7 @@ extension CallSettingsExt on open.CallSettingsResponse {
accessRequestEnabled: audio.accessRequestEnabled,
opusDtxEnabled: audio.opusDtxEnabled,
redundantCodingEnabled: audio.redundantCodingEnabled,
defaultDevice: audio.defaultDevice.toDomain(),
),
video: StreamVideoSettings(
accessRequestEnabled: video.accessRequestEnabled,
Expand Down Expand Up @@ -208,6 +210,16 @@ extension CallSettingsExt on open.CallSettingsResponse {
}
}

extension on open.AudioSettingsDefaultDeviceEnum {
AudioSettingsRequestDefaultDeviceEnum toDomain() {
if (this == open.AudioSettingsDefaultDeviceEnum.speaker) {
return AudioSettingsRequestDefaultDeviceEnum.speaker;
} else {
return AudioSettingsRequestDefaultDeviceEnum.earpiece;
}
}
}

extension on open.TranscriptionSettingsModeEnum {
TranscriptionSettingsMode toDomain() {
if (this == open.TranscriptionSettingsModeEnum.autoOn) {
Expand Down
Expand Up @@ -26,17 +26,19 @@ class RtcMediaDevice with EquatableMixin {
required this.id,
required this.label,
required this.kind,
this.groupId,
});

final String id;
final String label;
final String? groupId;
final RtcMediaDeviceKind kind;

@override
String toString() {
return 'RtcMediaDevice{id: $id, label: $label, kind: $kind}';
return 'RtcMediaDevice{id: $id, label: $label, groupId: $groupId, kind: $kind}';
}

@override
List<Object?> get props => [id, kind, label];
List<Object?> get props => [id, kind, groupId, label];
}
Expand Up @@ -37,6 +37,7 @@ class RtcMediaDeviceNotifier {
return RtcMediaDevice(
id: it.deviceId,
label: it.label,
groupId: it.groupId,
kind: RtcMediaDeviceKind.fromAlias(it.kind),
);
});
Expand Down