Skip to content

Commit 15b8e27

Browse files
authored
Merge pull request #30 from GetStream/chore/audio-devices-tweaks
chore: audio device related changes
2 parents ee48d8b + 9697a0c commit 15b8e27

File tree

5 files changed

+77
-2
lines changed

5 files changed

+77
-2
lines changed

android/src/main/java/io/getstream/webrtc/flutter/audio/AudioUtils.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,14 @@ static public String getAudioGroupId(AudioDeviceInfo device) {
231231
if (device.getType() == AudioDeviceInfo.TYPE_BUILTIN_MIC) {
232232
groupId = "microphone";
233233
}
234-
if (device.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
234+
if (device.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET
235+
|| device.getType() == AudioDeviceInfo.TYPE_USB_HEADSET
236+
|| device.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES) {
235237
groupId = "wired-headset";
236238
}
237-
if (device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
239+
if (device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO
240+
|| device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
241+
|| device.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) {
238242
groupId = "bluetooth";
239243
}
240244
return groupId;

common/darwin/Classes/FlutterRTCMediaStream.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@
2222
- (void)selectAudioInput:(nonnull NSString*)deviceId result:(nullable FlutterResult)result;
2323

2424
- (void)selectAudioOutput:(nonnull NSString*)deviceId result:(nullable FlutterResult)result;
25+
26+
- (void)triggeriOSAudioRouteSelectionUI:(nonnull FlutterResult)result;
2527
@end

common/darwin/Classes/FlutterRTCMediaStream.m

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#import "VideoProcessingAdapter.h"
88
#import "LocalVideoTrack.h"
99
#import "LocalAudioTrack.h"
10+
#import "AVKit/AVKit.h"
1011

1112
@implementation RTCMediaStreamTrack (Flutter)
1213

@@ -874,6 +875,60 @@ - (void)selectAudioOutput:(NSString*)deviceId result:(FlutterResult)result {
874875
details:nil]);
875876
}
876877

878+
- (void)triggeriOSAudioRouteSelectionUI:(FlutterResult)result {
879+
#if TARGET_OS_IPHONE
880+
if (@available(iOS 11.0, *)) {
881+
AVRoutePickerView *routePicker = [[AVRoutePickerView alloc] init];
882+
routePicker.frame = CGRectMake(0, 0, 44, 44);
883+
884+
// Add the route picker to a temporary window to ensure it's in the view hierarchy
885+
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
886+
if (!window) {
887+
// Fallback for iOS 13+ where keyWindow is deprecated
888+
for (UIWindowScene *windowScene in [UIApplication sharedApplication].connectedScenes) {
889+
if (windowScene.activationState == UISceneActivationStateForegroundActive) {
890+
window = windowScene.windows.firstObject;
891+
break;
892+
}
893+
}
894+
}
895+
896+
if (window) {
897+
[window addSubview:routePicker];
898+
899+
// Trigger the route picker programmatically
900+
for (UIView *view in routePicker.subviews) {
901+
if ([view isKindOfClass:[UIButton class]]) {
902+
UIButton *button = (UIButton *)view;
903+
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
904+
break; // Only trigger the first button found
905+
}
906+
}
907+
908+
// Remove the route picker after a short delay
909+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
910+
[routePicker removeFromSuperview];
911+
});
912+
913+
result(nil);
914+
} else {
915+
result([FlutterError errorWithCode:@"NoWindowError"
916+
message:@"Could not find a window to present the route picker"
917+
details:nil]);
918+
}
919+
} else {
920+
result([FlutterError errorWithCode:@"UnsupportedVersionError"
921+
message:@"AVRoutePickerView is only available on iOS 11.0 or later"
922+
details:nil]);
923+
}
924+
#else
925+
// macOS doesn't support iOS audio route selection UI
926+
result([FlutterError errorWithCode:@"UnsupportedPlatformError"
927+
message:@"triggeriOSAudioRouteSelectionUI is only supported on iOS"
928+
details:nil]);
929+
#endif
930+
}
931+
877932
- (void)mediaStreamTrackRelease:(RTCMediaStream*)mediaStream track:(RTCMediaStreamTrack*)track {
878933
// what's different to mediaStreamTrackStop? only call mediaStream explicitly?
879934
if (mediaStream && track) {

common/darwin/Classes/FlutterWebRTCPlugin.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#import <AVFoundation/AVFoundation.h>
2121
#import <WebRTC/RTCFieldTrials.h>
2222
#import <WebRTC/WebRTC.h>
23+
#import <AVKit/AVKit.h>
2324

2425
#import "LocalTrack.h"
2526
#import "LocalAudioTrack.h"
@@ -357,6 +358,8 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
357358
NSDictionary* argsMap = call.arguments;
358359
NSString* deviceId = argsMap[@"deviceId"];
359360
[self selectAudioOutput:deviceId result:result];
361+
} else if ([@"triggeriOSAudioRouteSelectionUI" isEqualToString:call.method]) {
362+
[self triggeriOSAudioRouteSelectionUI:result];
360363
} else if ([@"mediaStreamGetTracks" isEqualToString:call.method]) {
361364
NSDictionary* argsMap = call.arguments;
362365
NSString* streamId = argsMap[@"streamId"];

lib/src/helper.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,15 @@ class Helper {
191191
'enableIOSMultitaskingCameraAccess is only supported for iOS');
192192
}
193193
}
194+
195+
static Future<void> triggeriOSAudioRouteSelectionUI() async {
196+
if (WebRTC.platformIsIOS) {
197+
return await WebRTC.invokeMethod(
198+
'triggeriOSAudioRouteSelectionUI',
199+
);
200+
} else {
201+
throw Exception(
202+
'triggeriOSAudioRouteSelectionUI is only supported for iOS');
203+
}
204+
}
194205
}

0 commit comments

Comments
 (0)