@livekit/react-native 2.6.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/AudioUtils.swift +49 -0
- package/ios/LiveKitReactNativeModule.swift +234 -0
- package/ios/LivekitReactNative-Bridging-Header.h +3 -2
- package/ios/LivekitReactNative.h +1 -10
- package/ios/LivekitReactNative.m +2 -243
- package/ios/LivekitReactNativeModule.m +42 -0
- package/ios/audio/AudioProcessing.swift +1 -1
- package/ios/audio/AudioRendererManager.swift +3 -4
- package/ios/audio/MultibandVolumeAudioRenderer.swift +4 -2
- package/ios/audio/VolumeAudioRenderer.swift +4 -2
- package/lib/commonjs/LKNativeModule.js +1 -1
- package/lib/commonjs/LKNativeModule.js.map +1 -1
- package/lib/commonjs/audio/AudioSession.js +9 -17
- package/lib/commonjs/audio/AudioSession.js.map +1 -1
- package/lib/module/LKNativeModule.js +1 -1
- package/lib/module/LKNativeModule.js.map +1 -1
- package/lib/module/audio/AudioSession.js +9 -17
- package/lib/module/audio/AudioSession.js.map +1 -1
- package/livekit-react-native.podspec +25 -5
- package/package.json +1 -1
- package/src/LKNativeModule.ts +2 -2
- package/src/audio/AudioSession.ts +9 -24
- package/ios/AudioUtils.h +0 -9
- package/ios/AudioUtils.m +0 -48
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
|
|
3
|
+
public class AudioUtils {
|
|
4
|
+
public static func audioSessionModeFromString(_ mode: String) -> AVAudioSession.Mode {
|
|
5
|
+
let retMode: AVAudioSession.Mode = switch mode {
|
|
6
|
+
case "default_":
|
|
7
|
+
.default
|
|
8
|
+
case "voicePrompt":
|
|
9
|
+
.voicePrompt
|
|
10
|
+
case "videoRecording":
|
|
11
|
+
.videoRecording
|
|
12
|
+
case "videoChat":
|
|
13
|
+
.videoChat
|
|
14
|
+
case "voiceChat":
|
|
15
|
+
.voiceChat
|
|
16
|
+
case "gameChat":
|
|
17
|
+
.gameChat
|
|
18
|
+
case "measurement":
|
|
19
|
+
.measurement
|
|
20
|
+
case "moviePlayback":
|
|
21
|
+
.moviePlayback
|
|
22
|
+
case "spokenAudio":
|
|
23
|
+
.spokenAudio
|
|
24
|
+
default:
|
|
25
|
+
.default
|
|
26
|
+
}
|
|
27
|
+
return retMode
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public static func audioSessionCategoryFromString(_ category: String) -> AVAudioSession.Category {
|
|
31
|
+
let retCategory: AVAudioSession.Category = switch category {
|
|
32
|
+
case "ambient":
|
|
33
|
+
.ambient
|
|
34
|
+
case "soloAmbient":
|
|
35
|
+
.soloAmbient
|
|
36
|
+
case "playback":
|
|
37
|
+
.playback
|
|
38
|
+
case "record":
|
|
39
|
+
.record
|
|
40
|
+
case "playAndRecord":
|
|
41
|
+
.playAndRecord
|
|
42
|
+
case "multiRoute":
|
|
43
|
+
.multiRoute
|
|
44
|
+
default:
|
|
45
|
+
.ambient
|
|
46
|
+
}
|
|
47
|
+
return retCategory
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import livekit_react_native_webrtc
|
|
2
|
+
import AVFoundation
|
|
3
|
+
import AVFAudio
|
|
4
|
+
import React
|
|
5
|
+
|
|
6
|
+
struct LKEvents {
|
|
7
|
+
static let kEventVolumeProcessed = "LK_VOLUME_PROCESSED";
|
|
8
|
+
static let kEventMultibandProcessed = "LK_MULTIBAND_PROCESSED";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@objc(LivekitReactNativeModule)
|
|
12
|
+
public class LivekitReactNativeModule: RCTEventEmitter {
|
|
13
|
+
|
|
14
|
+
// This cannot be initialized in init as self.bridge is given afterwards.
|
|
15
|
+
private var _audioRendererManager: AudioRendererManager? = nil
|
|
16
|
+
public var audioRendererManager: AudioRendererManager {
|
|
17
|
+
get {
|
|
18
|
+
if _audioRendererManager == nil {
|
|
19
|
+
_audioRendererManager = AudioRendererManager(bridge: self.bridge)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return _audioRendererManager!
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@objc
|
|
27
|
+
public override init() {
|
|
28
|
+
super.init()
|
|
29
|
+
let config = RTCAudioSessionConfiguration()
|
|
30
|
+
config.category = AVAudioSession.Category.playAndRecord.rawValue
|
|
31
|
+
config.categoryOptions = [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker]
|
|
32
|
+
config.mode = AVAudioSession.Mode.videoChat.rawValue
|
|
33
|
+
|
|
34
|
+
RTCAudioSessionConfiguration.setWebRTC(config)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@objc
|
|
38
|
+
override public static func requiresMainQueueSetup() -> Bool {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc
|
|
43
|
+
public static func setup() {
|
|
44
|
+
let videoEncoderFactory = RTCDefaultVideoEncoderFactory()
|
|
45
|
+
let simulcastVideoEncoderFactory = RTCVideoEncoderFactorySimulcast(primary: videoEncoderFactory, fallback: videoEncoderFactory)
|
|
46
|
+
let options = WebRTCModuleOptions.sharedInstance()
|
|
47
|
+
options.videoEncoderFactory = simulcastVideoEncoderFactory
|
|
48
|
+
options.audioProcessingModule = LKAudioProcessingManager.sharedInstance().audioProcessingModule
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@objc(configureAudio:)
|
|
52
|
+
public func configureAudio(_ config: NSDictionary) {
|
|
53
|
+
guard let iOSConfig = config["ios"] as? NSDictionary
|
|
54
|
+
else {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let defaultOutput = iOSConfig["defaultOutput"] as? String ?? "speaker"
|
|
59
|
+
|
|
60
|
+
let rtcConfig = RTCAudioSessionConfiguration()
|
|
61
|
+
rtcConfig.category = AVAudioSession.Category.playAndRecord.rawValue
|
|
62
|
+
|
|
63
|
+
if (defaultOutput == "earpiece") {
|
|
64
|
+
rtcConfig.categoryOptions = [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP];
|
|
65
|
+
rtcConfig.mode = AVAudioSession.Mode.voiceChat.rawValue
|
|
66
|
+
} else {
|
|
67
|
+
rtcConfig.categoryOptions = [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker]
|
|
68
|
+
rtcConfig.mode = AVAudioSession.Mode.videoChat.rawValue
|
|
69
|
+
}
|
|
70
|
+
RTCAudioSessionConfiguration.setWebRTC(rtcConfig)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@objc(startAudioSession)
|
|
74
|
+
public func startAudioSession() {
|
|
75
|
+
// intentionally left empty
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@objc(stopAudioSession)
|
|
79
|
+
public func stopAudioSession() {
|
|
80
|
+
// intentionally left empty
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@objc(showAudioRoutePicker)
|
|
84
|
+
public func showAudioRoutePicker() {
|
|
85
|
+
if #available(iOS 11.0, *) {
|
|
86
|
+
let routePickerView = AVRoutePickerView()
|
|
87
|
+
let subviews = routePickerView.subviews
|
|
88
|
+
for subview in subviews {
|
|
89
|
+
if subview.isKind(of: UIButton.self) {
|
|
90
|
+
let button = subview as! UIButton
|
|
91
|
+
button.sendActions(for: .touchUpInside)
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@objc(getAudioOutputsWithResolver:withRejecter:)
|
|
99
|
+
public func getAudioOutputs(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){
|
|
100
|
+
resolve(["default", "force_speaker"])
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@objc(selectAudioOutput:withResolver:withRejecter:)
|
|
104
|
+
public func selectAudioOutput(_ deviceId: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
105
|
+
let session = AVAudioSession.sharedInstance()
|
|
106
|
+
do {
|
|
107
|
+
if (deviceId == "default") {
|
|
108
|
+
try session.overrideOutputAudioPort(.none)
|
|
109
|
+
} else if (deviceId == "force_speaker") {
|
|
110
|
+
try session.overrideOutputAudioPort(.speaker)
|
|
111
|
+
}
|
|
112
|
+
} catch {
|
|
113
|
+
reject("selectAudioOutput error", error.localizedDescription, error)
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
resolve(nil)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@objc(setAppleAudioConfiguration:)
|
|
121
|
+
public func setAppleAudioConfiguration(_ configuration: NSDictionary) {
|
|
122
|
+
let session = RTCAudioSession.sharedInstance()
|
|
123
|
+
let config = RTCAudioSessionConfiguration.webRTC()
|
|
124
|
+
|
|
125
|
+
let appleAudioCategory = configuration["audioCategory"] as? String
|
|
126
|
+
let appleAudioCategoryOptions = configuration["audioCategoryOptions"] as? [String]
|
|
127
|
+
let appleAudioMode = configuration["audioMode"] as? String
|
|
128
|
+
|
|
129
|
+
session.lockForConfiguration()
|
|
130
|
+
|
|
131
|
+
var categoryChanged = false
|
|
132
|
+
|
|
133
|
+
if let appleAudioCategoryOptions = appleAudioCategoryOptions {
|
|
134
|
+
categoryChanged = true
|
|
135
|
+
|
|
136
|
+
var newOptions: AVAudioSession.CategoryOptions = []
|
|
137
|
+
for option in appleAudioCategoryOptions {
|
|
138
|
+
if option == "mixWithOthers" {
|
|
139
|
+
newOptions.insert(.mixWithOthers)
|
|
140
|
+
} else if option == "duckOthers" {
|
|
141
|
+
newOptions.insert(.duckOthers)
|
|
142
|
+
} else if option == "allowBluetooth" {
|
|
143
|
+
newOptions.insert(.allowBluetooth)
|
|
144
|
+
} else if option == "allowBluetoothA2DP" {
|
|
145
|
+
newOptions.insert(.allowBluetoothA2DP)
|
|
146
|
+
} else if option == "allowAirPlay" {
|
|
147
|
+
newOptions.insert(.allowAirPlay)
|
|
148
|
+
} else if option == "defaultToSpeaker" {
|
|
149
|
+
newOptions.insert(.defaultToSpeaker)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
config.categoryOptions = newOptions
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if let appleAudioCategory = appleAudioCategory {
|
|
156
|
+
categoryChanged = true
|
|
157
|
+
config.category = AudioUtils.audioSessionCategoryFromString(appleAudioCategory).rawValue
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if categoryChanged {
|
|
161
|
+
do {
|
|
162
|
+
try session.setCategory(AVAudioSession.Category(rawValue: config.category), with: config.categoryOptions)
|
|
163
|
+
} catch {
|
|
164
|
+
NSLog("Error setting category: %@", error.localizedDescription)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if let appleAudioMode = appleAudioMode {
|
|
169
|
+
let mode = AudioUtils.audioSessionModeFromString(appleAudioMode)
|
|
170
|
+
config.mode = mode.rawValue
|
|
171
|
+
do {
|
|
172
|
+
try session.setMode(mode)
|
|
173
|
+
} catch {
|
|
174
|
+
NSLog("Error setting mode: %@", error.localizedDescription)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
session.unlockForConfiguration()
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@objc(createVolumeProcessor:trackId:)
|
|
182
|
+
public func createVolumeProcessor(_ pcId: NSNumber, trackId: String) -> String {
|
|
183
|
+
let renderer = VolumeAudioRenderer(intervalMs: 40.0, eventEmitter: self)
|
|
184
|
+
let reactTag = self.audioRendererManager.registerRenderer(renderer)
|
|
185
|
+
renderer.reactTag = reactTag
|
|
186
|
+
self.audioRendererManager.attach(renderer: renderer, pcId: pcId, trackId: trackId)
|
|
187
|
+
|
|
188
|
+
return reactTag
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@objc(deleteVolumeProcessor:pcId:trackId:)
|
|
192
|
+
public func deleteVolumeProcessor(_ reactTag: String, pcId: NSNumber, trackId: String) -> Any? {
|
|
193
|
+
self.audioRendererManager.detach(rendererByTag: reactTag, pcId: pcId, trackId: trackId)
|
|
194
|
+
self.audioRendererManager.unregisterRenderer(forReactTag: reactTag)
|
|
195
|
+
|
|
196
|
+
return nil
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@objc(createMultibandVolumeProcessor:pcId:trackId:)
|
|
200
|
+
public func createMultibandVolumeProcessor(_ options: NSDictionary, pcId: NSNumber, trackId: String) -> String {
|
|
201
|
+
let bands = (options["bands"] as? NSString)?.integerValue ?? 5
|
|
202
|
+
let minFrequency = (options["minFrequency"] as? NSString)?.floatValue ?? 1000
|
|
203
|
+
let maxFrequency = (options["maxFrequency"] as? NSString)?.floatValue ?? 8000
|
|
204
|
+
let intervalMs = (options["updateInterval"] as? NSString)?.floatValue ?? 40
|
|
205
|
+
|
|
206
|
+
let renderer = MultibandVolumeAudioRenderer(
|
|
207
|
+
bands: bands,
|
|
208
|
+
minFrequency: minFrequency,
|
|
209
|
+
maxFrequency: maxFrequency,
|
|
210
|
+
intervalMs: intervalMs,
|
|
211
|
+
eventEmitter: self
|
|
212
|
+
)
|
|
213
|
+
let reactTag = self.audioRendererManager.registerRenderer(renderer)
|
|
214
|
+
renderer.reactTag = reactTag
|
|
215
|
+
self.audioRendererManager.attach(renderer: renderer, pcId: pcId, trackId: trackId)
|
|
216
|
+
|
|
217
|
+
return reactTag
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@objc(deleteMultibandVolumeProcessor:pcId:trackId:)
|
|
221
|
+
public func deleteMultibandVolumeProcessor(_ reactTag: String, pcId: NSNumber, trackId: String) -> Any? {
|
|
222
|
+
self.audioRendererManager.detach(rendererByTag: reactTag, pcId: pcId, trackId: trackId)
|
|
223
|
+
self.audioRendererManager.unregisterRenderer(forReactTag: reactTag)
|
|
224
|
+
|
|
225
|
+
return nil
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
override public func supportedEvents() -> [String]! {
|
|
229
|
+
return [
|
|
230
|
+
LKEvents.kEventVolumeProcessed,
|
|
231
|
+
LKEvents.kEventMultibandProcessed,
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
}
|
package/ios/LivekitReactNative.h
CHANGED
|
@@ -2,18 +2,9 @@
|
|
|
2
2
|
// LivekitReactNative.h
|
|
3
3
|
// LivekitReactNative
|
|
4
4
|
//
|
|
5
|
-
// Created by David Liu on 9/4/22.
|
|
6
5
|
// Copyright © 2022-2025 LiveKit. All rights reserved.
|
|
7
6
|
//
|
|
8
|
-
#import <React/RCTBridgeModule.h>
|
|
9
|
-
#import <WebRTC/WebRTC.h>
|
|
10
|
-
#import <React/RCTEventEmitter.h>
|
|
11
7
|
|
|
12
|
-
@
|
|
13
|
-
@interface LivekitReactNative : RCTEventEmitter <RCTBridgeModule>
|
|
14
|
-
@property(nonatomic, strong) AudioRendererManager* _Nonnull audioRendererManager;
|
|
8
|
+
@interface LivekitReactNative : NSObject
|
|
15
9
|
+(void)setup;
|
|
16
10
|
@end
|
|
17
|
-
|
|
18
|
-
extern NSString * _Nonnull const kEventVolumeProcessed;
|
|
19
|
-
extern NSString * _Nonnull const kEventMultibandProcessed;
|
package/ios/LivekitReactNative.m
CHANGED
|
@@ -1,46 +1,10 @@
|
|
|
1
|
-
#import "AudioUtils.h"
|
|
2
|
-
#import "LivekitReactNative.h"
|
|
3
|
-
#import "LKAudioProcessingManager.h"
|
|
4
1
|
#import "WebRTCModule.h"
|
|
5
2
|
#import "WebRTCModuleOptions.h"
|
|
6
|
-
#import
|
|
7
|
-
#import
|
|
8
|
-
#import <AVFAudio/AVFAudio.h>
|
|
9
|
-
#import <AVKit/AVKit.h>
|
|
10
|
-
#import "livekit_react_native-Swift.h"
|
|
11
|
-
|
|
12
|
-
NSString *const kEventVolumeProcessed = @"LK_VOLUME_PROCESSED";
|
|
13
|
-
NSString *const kEventMultibandProcessed = @"LK_MULTIBAND_PROCESSED";
|
|
3
|
+
#import "LivekitReactNative.h"
|
|
4
|
+
#import "LKAudioProcessingManager.h"
|
|
14
5
|
|
|
15
6
|
@implementation LivekitReactNative
|
|
16
7
|
|
|
17
|
-
|
|
18
|
-
RCT_EXPORT_MODULE();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-(instancetype)init {
|
|
22
|
-
if(self = [super init]) {
|
|
23
|
-
|
|
24
|
-
RTCAudioSessionConfiguration* config = [[RTCAudioSessionConfiguration alloc] init];
|
|
25
|
-
[config setCategory:AVAudioSessionCategoryPlayAndRecord];
|
|
26
|
-
[config setCategoryOptions:
|
|
27
|
-
AVAudioSessionCategoryOptionAllowAirPlay|
|
|
28
|
-
AVAudioSessionCategoryOptionAllowBluetooth|
|
|
29
|
-
AVAudioSessionCategoryOptionAllowBluetoothA2DP|
|
|
30
|
-
AVAudioSessionCategoryOptionDefaultToSpeaker
|
|
31
|
-
];
|
|
32
|
-
[config setMode:AVAudioSessionModeVideoChat];
|
|
33
|
-
[RTCAudioSessionConfiguration setWebRTCConfiguration: config];
|
|
34
|
-
return self;
|
|
35
|
-
} else {
|
|
36
|
-
return nil;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
+(BOOL)requiresMainQueueSetup {
|
|
41
|
-
return NO;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
8
|
+(void)setup {
|
|
45
9
|
RTCDefaultVideoEncoderFactory *videoEncoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init];
|
|
46
10
|
RTCVideoEncoderFactorySimulcast *simulcastVideoEncoderFactory = [[RTCVideoEncoderFactorySimulcast alloc] initWithPrimary:videoEncoderFactory fallback:videoEncoderFactory];
|
|
@@ -49,209 +13,4 @@ RCT_EXPORT_MODULE();
|
|
|
49
13
|
options.audioProcessingModule = LKAudioProcessingManager.sharedInstance.audioProcessingModule;
|
|
50
14
|
}
|
|
51
15
|
|
|
52
|
-
/// Configure default audio config for WebRTC
|
|
53
|
-
RCT_EXPORT_METHOD(configureAudio:(NSDictionary *) config){
|
|
54
|
-
NSDictionary *iOSConfig = [config objectForKey:@"ios"];
|
|
55
|
-
if(iOSConfig == nil) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
NSString * defaultOutput = [iOSConfig objectForKey:@"defaultOutput"];
|
|
60
|
-
if (defaultOutput == nil) {
|
|
61
|
-
defaultOutput = @"speaker";
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
RTCAudioSessionConfiguration* rtcConfig = [[RTCAudioSessionConfiguration alloc] init];
|
|
65
|
-
[rtcConfig setCategory:AVAudioSessionCategoryPlayAndRecord];
|
|
66
|
-
|
|
67
|
-
if([defaultOutput isEqualToString:@"earpiece"]){
|
|
68
|
-
[rtcConfig setCategoryOptions:
|
|
69
|
-
AVAudioSessionCategoryOptionAllowAirPlay|
|
|
70
|
-
AVAudioSessionCategoryOptionAllowBluetooth|
|
|
71
|
-
AVAudioSessionCategoryOptionAllowBluetoothA2DP];
|
|
72
|
-
[rtcConfig setMode:AVAudioSessionModeVoiceChat];
|
|
73
|
-
} else {
|
|
74
|
-
[rtcConfig setCategoryOptions:
|
|
75
|
-
AVAudioSessionCategoryOptionAllowAirPlay|
|
|
76
|
-
AVAudioSessionCategoryOptionAllowBluetooth|
|
|
77
|
-
AVAudioSessionCategoryOptionAllowBluetoothA2DP|
|
|
78
|
-
AVAudioSessionCategoryOptionDefaultToSpeaker];
|
|
79
|
-
[rtcConfig setMode:AVAudioSessionModeVideoChat];
|
|
80
|
-
}
|
|
81
|
-
[RTCAudioSessionConfiguration setWebRTCConfiguration: rtcConfig];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
RCT_EXPORT_METHOD(startAudioSession){
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
RCT_EXPORT_METHOD(stopAudioSession){
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
RCT_EXPORT_METHOD(showAudioRoutePicker){
|
|
92
|
-
if (@available(iOS 11.0, *)) {
|
|
93
|
-
AVRoutePickerView *routePickerView = [[AVRoutePickerView alloc] init];
|
|
94
|
-
NSArray<UIView *> *subviews = routePickerView.subviews;
|
|
95
|
-
for (int i = 0; i < subviews.count; i++) {
|
|
96
|
-
UIView *subview = [subviews objectAtIndex:i];
|
|
97
|
-
if([subview isKindOfClass:[UIButton class]]) {
|
|
98
|
-
UIButton *button = (UIButton *) subview;
|
|
99
|
-
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
RCT_EXPORT_METHOD(getAudioOutputsWithResolver:(RCTPromiseResolveBlock)resolve
|
|
107
|
-
withRejecter:(RCTPromiseRejectBlock)reject){
|
|
108
|
-
resolve(@[@"default", @"force_speaker"]);
|
|
109
|
-
}
|
|
110
|
-
RCT_EXPORT_METHOD(selectAudioOutput:(NSString *)deviceId
|
|
111
|
-
withResolver:(RCTPromiseResolveBlock)resolve
|
|
112
|
-
withRejecter:(RCTPromiseRejectBlock)reject){
|
|
113
|
-
|
|
114
|
-
AVAudioSession *session = [AVAudioSession sharedInstance];
|
|
115
|
-
NSError *error = nil;
|
|
116
|
-
|
|
117
|
-
if ([deviceId isEqualToString:@"default"]) {
|
|
118
|
-
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];
|
|
119
|
-
} else if ([deviceId isEqualToString:@"force_speaker"]) {
|
|
120
|
-
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (error != nil) {
|
|
124
|
-
reject(@"selectAudioOutput error", error.localizedDescription, error);
|
|
125
|
-
} else {
|
|
126
|
-
resolve(nil);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
/// Configure audio config for WebRTC
|
|
132
|
-
RCT_EXPORT_METHOD(setAppleAudioConfiguration:(NSDictionary *) configuration){
|
|
133
|
-
RTCAudioSession* session = [RTCAudioSession sharedInstance];
|
|
134
|
-
RTCAudioSessionConfiguration* config = [RTCAudioSessionConfiguration webRTCConfiguration];
|
|
135
|
-
|
|
136
|
-
NSString* appleAudioCategory = configuration[@"audioCategory"];
|
|
137
|
-
NSArray* appleAudioCategoryOptions = configuration[@"audioCategoryOptions"];
|
|
138
|
-
NSString* appleAudioMode = configuration[@"audioMode"];
|
|
139
|
-
|
|
140
|
-
[session lockForConfiguration];
|
|
141
|
-
|
|
142
|
-
NSError* error = nil;
|
|
143
|
-
BOOL categoryChanged = NO;
|
|
144
|
-
if(appleAudioCategoryOptions != nil) {
|
|
145
|
-
categoryChanged = YES;
|
|
146
|
-
config.categoryOptions = 0;
|
|
147
|
-
for(NSString* option in appleAudioCategoryOptions) {
|
|
148
|
-
if([@"mixWithOthers" isEqualToString:option]) {
|
|
149
|
-
config.categoryOptions |= AVAudioSessionCategoryOptionMixWithOthers;
|
|
150
|
-
} else if([@"duckOthers" isEqualToString:option]) {
|
|
151
|
-
config.categoryOptions |= AVAudioSessionCategoryOptionDuckOthers;
|
|
152
|
-
} else if([@"allowBluetooth" isEqualToString:option]) {
|
|
153
|
-
config.categoryOptions |= AVAudioSessionCategoryOptionAllowBluetooth;
|
|
154
|
-
} else if([@"allowBluetoothA2DP" isEqualToString:option]) {
|
|
155
|
-
config.categoryOptions |= AVAudioSessionCategoryOptionAllowBluetoothA2DP;
|
|
156
|
-
} else if([@"allowAirPlay" isEqualToString:option]) {
|
|
157
|
-
config.categoryOptions |= AVAudioSessionCategoryOptionAllowAirPlay;
|
|
158
|
-
} else if([@"defaultToSpeaker" isEqualToString:option]) {
|
|
159
|
-
config.categoryOptions |= AVAudioSessionCategoryOptionDefaultToSpeaker;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if(appleAudioCategory != nil) {
|
|
165
|
-
categoryChanged = YES;
|
|
166
|
-
config.category = [AudioUtils audioSessionCategoryFromString:appleAudioCategory];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if(categoryChanged) {
|
|
170
|
-
[session setCategory:config.category withOptions:config.categoryOptions error:&error];
|
|
171
|
-
if(error != nil) {
|
|
172
|
-
NSLog(@"Error setting category: %@", [error localizedDescription]);
|
|
173
|
-
error = nil;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if(appleAudioMode != nil) {
|
|
178
|
-
config.mode = [AudioUtils audioSessionModeFromString:appleAudioMode];
|
|
179
|
-
[session setMode:config.mode error:&error];
|
|
180
|
-
if(error != nil) {
|
|
181
|
-
NSLog(@"Error setting category: %@", [error localizedDescription]);
|
|
182
|
-
error = nil;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
[session unlockForConfiguration];
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
-(AudioRendererManager *)audioRendererManager {
|
|
190
|
-
if(!_audioRendererManager) {
|
|
191
|
-
_audioRendererManager = [[AudioRendererManager alloc] initWithBridge:self.bridge];
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return _audioRendererManager;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(createVolumeProcessor:(nonnull NSNumber *)pcId
|
|
198
|
-
trackId:(nonnull NSString *)trackId) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
VolumeAudioRenderer *renderer = [[VolumeAudioRenderer alloc] initWithIntervalMs:40.0 eventEmitter:self];
|
|
202
|
-
|
|
203
|
-
NSString *reactTag = [self.audioRendererManager registerRenderer:renderer];
|
|
204
|
-
renderer.reactTag = reactTag;
|
|
205
|
-
[self.audioRendererManager attachWithRenderer:renderer pcId:pcId trackId:trackId];
|
|
206
|
-
return reactTag;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(deleteVolumeProcessor:(nonnull NSString *)reactTag
|
|
210
|
-
pcId:(nonnull NSNumber *)pcId
|
|
211
|
-
trackId:(nonnull NSString *)trackId) {
|
|
212
|
-
|
|
213
|
-
[self.audioRendererManager detachWithRendererByTag:reactTag pcId:pcId trackId:trackId];
|
|
214
|
-
[self.audioRendererManager unregisterRendererForReactTag:reactTag];
|
|
215
|
-
|
|
216
|
-
return nil;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(createMultibandVolumeProcessor:(NSDictionary *)options
|
|
220
|
-
pcId:(nonnull NSNumber *)pcId
|
|
221
|
-
trackId:(nonnull NSString *)trackId) {
|
|
222
|
-
|
|
223
|
-
NSInteger bands = [(NSNumber *)options[@"bands"] integerValue];
|
|
224
|
-
float minFrequency = [(NSNumber *)options[@"minFrequency"] floatValue];
|
|
225
|
-
float maxFrequency = [(NSNumber *)options[@"maxFrequency"] floatValue];
|
|
226
|
-
float intervalMs = [(NSNumber *)options[@"updateInterval"] floatValue];
|
|
227
|
-
MultibandVolumeAudioRenderer *renderer = [[MultibandVolumeAudioRenderer alloc] initWithBands:bands
|
|
228
|
-
minFrequency:minFrequency
|
|
229
|
-
maxFrequency:maxFrequency
|
|
230
|
-
intervalMs:intervalMs
|
|
231
|
-
eventEmitter:self];
|
|
232
|
-
|
|
233
|
-
NSString *reactTag = [self.audioRendererManager registerRenderer:renderer];
|
|
234
|
-
renderer.reactTag = reactTag;
|
|
235
|
-
[self.audioRendererManager attachWithRenderer:renderer pcId:pcId trackId:trackId];
|
|
236
|
-
return reactTag;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(deleteMultibandVolumeProcessor:(nonnull NSString *)reactTag
|
|
240
|
-
pcId:(nonnull NSNumber *)pcId
|
|
241
|
-
trackId:(nonnull NSString *)trackId) {
|
|
242
|
-
|
|
243
|
-
[self.audioRendererManager detachWithRendererByTag:reactTag pcId:pcId trackId:trackId];
|
|
244
|
-
[self.audioRendererManager unregisterRendererForReactTag:reactTag];
|
|
245
|
-
|
|
246
|
-
return nil;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
- (NSArray<NSString *> *)supportedEvents {
|
|
251
|
-
return @[
|
|
252
|
-
kEventVolumeProcessed,
|
|
253
|
-
kEventMultibandProcessed,
|
|
254
|
-
];
|
|
255
|
-
}
|
|
256
|
-
|
|
257
16
|
@end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
#import "WebRTCModule.h"
|
|
4
|
+
|
|
5
|
+
@interface RCT_EXTERN_MODULE(LivekitReactNativeModule, RCTEventEmitter)
|
|
6
|
+
|
|
7
|
+
RCT_EXTERN_METHOD(configureAudio:(NSDictionary *) config)
|
|
8
|
+
RCT_EXTERN_METHOD(startAudioSession)
|
|
9
|
+
RCT_EXTERN_METHOD(stopAudioSession)
|
|
10
|
+
|
|
11
|
+
RCT_EXTERN_METHOD(showAudioRoutePicker)
|
|
12
|
+
RCT_EXTERN_METHOD(getAudioOutputsWithResolver:(RCTPromiseResolveBlock)resolve
|
|
13
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
14
|
+
RCT_EXTERN_METHOD(selectAudioOutput:(NSString *)deviceId
|
|
15
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
16
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/// Configure audio config for WebRTC
|
|
20
|
+
RCT_EXTERN_METHOD(setAppleAudioConfiguration:(NSDictionary *) configuration)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(createVolumeProcessor:(nonnull NSNumber *)pcId
|
|
24
|
+
trackId:(nonnull NSString *)trackId)
|
|
25
|
+
|
|
26
|
+
RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(deleteVolumeProcessor:(nonnull NSString *)reactTag
|
|
27
|
+
pcId:(nonnull NSNumber *)pcId
|
|
28
|
+
trackId:(nonnull NSString *)trackId)
|
|
29
|
+
|
|
30
|
+
RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(createMultibandVolumeProcessor:(NSDictionary *)options
|
|
31
|
+
pcId:(nonnull NSNumber *)pcId
|
|
32
|
+
trackId:(nonnull NSString *)trackId)
|
|
33
|
+
|
|
34
|
+
RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(deleteMultibandVolumeProcessor:(nonnull NSString *)reactTag
|
|
35
|
+
pcId:(nonnull NSNumber *)pcId
|
|
36
|
+
trackId:(nonnull NSString *)trackId)
|
|
37
|
+
|
|
38
|
+
+(BOOL)requiresMainQueueSetup {
|
|
39
|
+
return NO;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@end
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import WebRTC
|
|
1
|
+
import livekit_react_native_webrtc
|
|
3
2
|
|
|
3
|
+
@objc
|
|
4
4
|
public class AudioRendererManager: NSObject {
|
|
5
5
|
private let bridge: RCTBridge
|
|
6
6
|
public private(set) var renderers: [String: RTCAudioRenderer] = [:]
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
public init(bridge: RCTBridge) {
|
|
8
|
+
init(bridge: RCTBridge) {
|
|
10
9
|
self.bridge = bridge
|
|
11
10
|
}
|
|
12
11
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import livekit_react_native_webrtc
|
|
2
|
+
import React
|
|
2
3
|
|
|
4
|
+
@objc
|
|
3
5
|
public class MultibandVolumeAudioRenderer: BaseMultibandVolumeAudioRenderer {
|
|
4
6
|
private let eventEmitter: RCTEventEmitter
|
|
5
7
|
|
|
@@ -24,7 +26,7 @@ public class MultibandVolumeAudioRenderer: BaseMultibandVolumeAudioRenderer {
|
|
|
24
26
|
override func onMagnitudesCalculated(_ magnitudes: [Float]) {
|
|
25
27
|
guard !magnitudes.isEmpty, let reactTag = self.reactTag
|
|
26
28
|
else { return }
|
|
27
|
-
eventEmitter.sendEvent(withName: kEventMultibandProcessed, body: [
|
|
29
|
+
eventEmitter.sendEvent(withName: LKEvents.kEventMultibandProcessed, body: [
|
|
28
30
|
"magnitudes": magnitudes,
|
|
29
31
|
"id": reactTag
|
|
30
32
|
])
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import livekit_react_native_webrtc
|
|
2
|
+
import React
|
|
2
3
|
|
|
4
|
+
@objc
|
|
3
5
|
public class VolumeAudioRenderer: BaseVolumeAudioRenderer {
|
|
4
6
|
private let eventEmitter: RCTEventEmitter
|
|
5
7
|
|
|
@@ -16,7 +18,7 @@ public class VolumeAudioRenderer: BaseVolumeAudioRenderer {
|
|
|
16
18
|
guard let rmsAvg = audioLevels.combine()?.average,
|
|
17
19
|
let reactTag = self.reactTag
|
|
18
20
|
else { return }
|
|
19
|
-
eventEmitter.sendEvent(withName: kEventVolumeProcessed, body: [
|
|
21
|
+
eventEmitter.sendEvent(withName: LKEvents.kEventVolumeProcessed, body: [
|
|
20
22
|
"volume": rmsAvg,
|
|
21
23
|
"id": reactTag
|
|
22
24
|
])
|
|
@@ -9,7 +9,7 @@ const LINKING_ERROR = `The package '@livekit/react-native' doesn't seem to be li
|
|
|
9
9
|
ios: "- You have run 'pod install'\n",
|
|
10
10
|
default: ''
|
|
11
11
|
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
|
|
12
|
-
const LiveKitModule = _reactNative.NativeModules.
|
|
12
|
+
const LiveKitModule = _reactNative.NativeModules.LivekitReactNativeModule ? _reactNative.NativeModules.LivekitReactNativeModule : new Proxy({}, {
|
|
13
13
|
get() {
|
|
14
14
|
throw new Error(LINKING_ERROR);
|
|
15
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","LiveKitModule","NativeModules","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","LiveKitModule","NativeModules","LivekitReactNativeModule","Proxy","get","Error","_default","exports"],"sources":["LKNativeModule.ts"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nconst LINKING_ERROR =\n `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nconst LiveKitModule = NativeModules.LivekitReactNativeModule\n ? NativeModules.LivekitReactNativeModule\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\nexport default LiveKitModule;\n"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,MAAMC,aAAa,GACjB,gFAAgF,GAChFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,6CAA6C;AAE/C,MAAMC,aAAa,GAAGC,0BAAa,CAACC,wBAAwB,GACxDD,0BAAa,CAACC,wBAAwB,GACtC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACV,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAAC,IAAAW,QAAA,GAAAC,OAAA,CAAAR,OAAA,GAESC,aAAa","ignoreList":[]}
|
|
@@ -6,19 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = exports.AndroidAudioTypePresets = void 0;
|
|
7
7
|
exports.getDefaultAppleAudioConfigurationForMode = getDefaultAppleAudioConfigurationForMode;
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
|
+
var _LKNativeModule = _interopRequireDefault(require("../LKNativeModule"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
11
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
10
12
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
11
13
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
12
|
-
const LINKING_ERROR = `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
|
|
13
|
-
ios: "- You have run 'pod install'\n",
|
|
14
|
-
default: ''
|
|
15
|
-
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
|
|
16
|
-
const LivekitReactNative = _reactNative.NativeModules.LivekitReactNative ? _reactNative.NativeModules.LivekitReactNative : new Proxy({}, {
|
|
17
|
-
get() {
|
|
18
|
-
throw new Error(LINKING_ERROR);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
14
|
/**
|
|
23
15
|
* Configuration for the underlying AudioSession.
|
|
24
16
|
*
|
|
@@ -95,19 +87,19 @@ exports.default = AudioSession;
|
|
|
95
87
|
* See also useIOSAudioManagement for automatic configuration of iOS audio options.
|
|
96
88
|
*/
|
|
97
89
|
_defineProperty(AudioSession, "configureAudio", async config => {
|
|
98
|
-
await
|
|
90
|
+
await _LKNativeModule.default.configureAudio(config);
|
|
99
91
|
});
|
|
100
92
|
/**
|
|
101
93
|
* Starts an AudioSession.
|
|
102
94
|
*/
|
|
103
95
|
_defineProperty(AudioSession, "startAudioSession", async () => {
|
|
104
|
-
await
|
|
96
|
+
await _LKNativeModule.default.startAudioSession();
|
|
105
97
|
});
|
|
106
98
|
/**
|
|
107
99
|
* Stops the existing AudioSession.
|
|
108
100
|
*/
|
|
109
101
|
_defineProperty(AudioSession, "stopAudioSession", async () => {
|
|
110
|
-
await
|
|
102
|
+
await _LKNativeModule.default.stopAudioSession();
|
|
111
103
|
});
|
|
112
104
|
/**
|
|
113
105
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
@@ -137,7 +129,7 @@ _defineProperty(AudioSession, "getAudioOutputs", async () => {
|
|
|
137
129
|
if (_reactNative.Platform.OS === 'ios') {
|
|
138
130
|
return ['default', 'force_speaker'];
|
|
139
131
|
} else if (_reactNative.Platform.OS === 'android') {
|
|
140
|
-
return await
|
|
132
|
+
return await _LKNativeModule.default.getAudioOutputs();
|
|
141
133
|
} else {
|
|
142
134
|
return [];
|
|
143
135
|
}
|
|
@@ -150,7 +142,7 @@ _defineProperty(AudioSession, "getAudioOutputs", async () => {
|
|
|
150
142
|
* @param deviceId A deviceId retrieved from {@link getAudioOutputs}
|
|
151
143
|
*/
|
|
152
144
|
_defineProperty(AudioSession, "selectAudioOutput", async deviceId => {
|
|
153
|
-
await
|
|
145
|
+
await _LKNativeModule.default.selectAudioOutput(deviceId);
|
|
154
146
|
});
|
|
155
147
|
/**
|
|
156
148
|
* iOS only, requires iOS 11+.
|
|
@@ -159,7 +151,7 @@ _defineProperty(AudioSession, "selectAudioOutput", async deviceId => {
|
|
|
159
151
|
*/
|
|
160
152
|
_defineProperty(AudioSession, "showAudioRoutePicker", async () => {
|
|
161
153
|
if (_reactNative.Platform.OS === 'ios') {
|
|
162
|
-
await
|
|
154
|
+
await _LKNativeModule.default.showAudioRoutePicker();
|
|
163
155
|
}
|
|
164
156
|
});
|
|
165
157
|
/**
|
|
@@ -170,7 +162,7 @@ _defineProperty(AudioSession, "showAudioRoutePicker", async () => {
|
|
|
170
162
|
*/
|
|
171
163
|
_defineProperty(AudioSession, "setAppleAudioConfiguration", async config => {
|
|
172
164
|
if (_reactNative.Platform.OS === 'ios') {
|
|
173
|
-
await
|
|
165
|
+
await _LKNativeModule.default.setAppleAudioConfiguration(config);
|
|
174
166
|
}
|
|
175
167
|
});
|
|
176
168
|
//# sourceMappingURL=AudioSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_defineProperty","e","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","LINKING_ERROR","Platform","select","ios","default","LivekitReactNative","NativeModules","Proxy","get","Error","AndroidAudioTypePresets","exports","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","config","configureAudio","startAudioSession","stopAudioSession","OS","getAudioOutputs","deviceId","selectAudioOutput","showAudioRoutePicker","setAppleAudioConfiguration"],"sources":["AudioSession.ts"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nconst LINKING_ERROR =\n `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nconst LivekitReactNative = NativeModules.LivekitReactNative\n ? NativeModules.LivekitReactNative\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\n/**\n * Configuration for the underlying AudioSession.\n *\n * ----\n * Android specific options:\n *\n * * preferredOutputList - The preferred order in which to automatically select an audio output.\n * This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.\n *\n * By default, the order is set to:\n * 1. `\"bluetooth\"\n * 2. `\"headset\"``\n * 3. `\"speaker\"`\n * 4. `\"earpiece\"`\n *\n * * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the\n * audio options to use on Android.\n *\n * See {@link AndroidAudioTypePresets} for pre-configured values.\n *\n * ----\n * iOS\n *\n * * defaultOutput - The default preferred output to use when a wired headset or bluetooth output is unavailable.\n *\n * By default, this is set to `\"speaker\"`\n */\nexport type AudioConfiguration = {\n android?: {\n preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];\n audioTypeOptions: AndroidAudioTypeOptions;\n };\n ios?: {\n defaultOutput?: 'speaker' | 'earpiece';\n };\n};\n\nexport type AndroidAudioTypeOptions = {\n /**\n * Whether LiveKit should handle managing the audio focus or not.\n *\n * Defaults to true.\n */\n manageAudioFocus?: boolean;\n\n /**\n * Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}\n *\n * Defaults to 'inCommunication'.\n */\n audioMode?:\n | 'normal'\n | 'callScreening'\n | 'inCall'\n | 'inCommunication'\n | 'ringtone';\n\n /**\n * Corresponds to the duration hint when requesting audio focus.\n *\n * Defaults to 'gain'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}\n */\n audioFocusMode?:\n | 'gain'\n | 'gainTransient'\n | 'gainTransientExclusive'\n | 'gainTransientMayDuck';\n\n /**\n * Corresponds to Android's AudioAttributes usage type.\n *\n * Defaults to 'voiceCommunication'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesUsageType?:\n | 'alarm'\n | 'assistanceAccessibility'\n | 'assistanceNavigationGuidance'\n | 'assistanceSonification'\n | 'assistant'\n | 'game'\n | 'media'\n | 'notification'\n | 'notificationEvent'\n | 'notificationRingtone'\n | 'unknown'\n | 'voiceCommunication'\n | 'voiceCommunicationSignalling';\n\n /**\n * Corresponds to Android's AndroidAttributes content type.\n *\n * Defaults to 'speech'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesContentType?:\n | 'movie'\n | 'music'\n | 'sonification'\n | 'speech'\n | 'unknown';\n\n /**\n * Corresponds to the stream type when requesting audio focus. Used on pre-O devices.\n *\n * Defaults to 'voiceCall'\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}\n */\n audioStreamType?:\n | 'accessibility'\n | 'alarm'\n | 'dtmf'\n | 'music'\n | 'notification'\n | 'ring'\n | 'system'\n | 'voiceCall';\n\n /**\n * On certain Android devices, audio routing does not function properly and\n * bluetooth microphones will not work unless audio mode is set to\n * `inCommunication` or `inCall`. Audio routing is turned off those cases.\n *\n * If this set to true, will attempt to do audio routing regardless of audio mode.\n *\n * Defaults to false.\n */\n forceHandleAudioRouting?: boolean;\n};\n\nexport const AndroidAudioTypePresets: {\n /**\n * A pre-configured AndroidAudioConfiguration for voice communication.\n */\n communication: AndroidAudioTypeOptions;\n /**\n * A pre-configured AndroidAudioConfiguration for media playback.\n */\n media: AndroidAudioTypeOptions;\n} = {\n communication: {\n manageAudioFocus: true,\n audioMode: 'inCommunication',\n audioFocusMode: 'gain',\n audioStreamType: 'voiceCall',\n audioAttributesUsageType: 'voiceCommunication',\n audioAttributesContentType: 'speech',\n },\n media: {\n manageAudioFocus: true,\n audioMode: 'normal',\n audioFocusMode: 'gain',\n audioStreamType: 'music',\n audioAttributesUsageType: 'media',\n audioAttributesContentType: 'unknown',\n },\n} as const;\n\nexport type AppleAudioMode =\n | 'default'\n | 'gameChat'\n | 'measurement'\n | 'moviePlayback'\n | 'spokenAudio'\n | 'videoChat'\n | 'videoRecording'\n | 'voiceChat'\n | 'voicePrompt';\n\nexport type AppleAudioCategory =\n | 'soloAmbient'\n | 'playback'\n | 'record'\n | 'playAndRecord'\n | 'multiRoute';\n\nexport type AppleAudioCategoryOption =\n | 'mixWithOthers'\n | 'duckOthers'\n | 'interruptSpokenAudioAndMixWithOthers'\n | 'allowBluetooth'\n | 'allowBluetoothA2DP'\n | 'allowAirPlay'\n | 'defaultToSpeaker';\n\nexport type AppleAudioConfiguration = {\n audioCategory?: AppleAudioCategory;\n audioCategoryOptions?: AppleAudioCategoryOption[];\n audioMode?: AppleAudioMode;\n};\n\nexport type AudioTrackState =\n | 'none'\n | 'remoteOnly'\n | 'localOnly'\n | 'localAndRemote';\n\nexport function getDefaultAppleAudioConfigurationForMode(\n mode: AudioTrackState,\n preferSpeakerOutput: boolean = true\n): AppleAudioConfiguration {\n if (mode === 'remoteOnly') {\n return {\n audioCategory: 'playback',\n audioCategoryOptions: ['mixWithOthers'],\n audioMode: 'spokenAudio',\n };\n } else if (mode === 'localAndRemote' || mode === 'localOnly') {\n return {\n audioCategory: 'playAndRecord',\n audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],\n audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',\n };\n }\n\n return {\n audioCategory: 'soloAmbient',\n audioCategoryOptions: [],\n audioMode: 'default',\n };\n}\n\nexport default class AudioSession {\n /**\n * Applies the provided audio configuration to the underlying AudioSession.\n *\n * Must be called prior to connecting to a Room for the configuration to apply correctly.\n *\n * See also useIOSAudioManagement for automatic configuration of iOS audio options.\n */\n static configureAudio = async (config: AudioConfiguration) => {\n await LivekitReactNative.configureAudio(config);\n };\n\n /**\n * Starts an AudioSession.\n */\n static startAudioSession = async () => {\n await LivekitReactNative.startAudioSession();\n };\n\n /**\n * Stops the existing AudioSession.\n */\n static stopAudioSession = async () => {\n await LivekitReactNative.stopAudioSession();\n };\n\n /**\n * Gets the available audio outputs for use with {@link selectAudioOutput}.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * For Android, will return if available:\n * * \"speaker\"\n * * \"earpiece\"\n * * \"headset\"\n * * \"bluetooth\"\n *\n * ----\n *\n * For iOS, due to OS limitations, the only available types are:\n * * \"default\" - Use default iOS audio routing\n * * \"force_speaker\" - Force audio output through speaker\n *\n * See also {@link showAudioRoutePicker} to display a route picker that\n * can choose between other audio devices (i.e. headset/bluetooth/airplay),\n * or use a library like `react-native-avroutepicker` for a native platform\n * control.\n *\n * @returns the available audio output types\n */\n static getAudioOutputs = async (): Promise<string[]> => {\n if (Platform.OS === 'ios') {\n return ['default', 'force_speaker'];\n } else if (Platform.OS === 'android') {\n return (await LivekitReactNative.getAudioOutputs()) as string[];\n } else {\n return [];\n }\n };\n\n /**\n * Select the provided audio output if available.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * @param deviceId A deviceId retrieved from {@link getAudioOutputs}\n */\n static selectAudioOutput = async (deviceId: string) => {\n await LivekitReactNative.selectAudioOutput(deviceId);\n };\n\n /**\n * iOS only, requires iOS 11+.\n *\n * Displays an AVRoutePickerView for the user to choose their audio output.\n */\n static showAudioRoutePicker = async () => {\n if (Platform.OS === 'ios') {\n await LivekitReactNative.showAudioRoutePicker();\n }\n };\n\n /**\n * Directly change the AVAudioSession category/mode.\n *\n * @param config The configuration to use. Null values will be omitted and the\n * existing values will be unchanged.\n */\n static setAppleAudioConfiguration = async (\n config: AppleAudioConfiguration\n ) => {\n if (Platform.OS === 'ios') {\n await LivekitReactNative.setAppleAudioConfiguration(config);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_LKNativeModule","_interopRequireDefault","e","__esModule","default","_defineProperty","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","AndroidAudioTypePresets","exports","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","config","LiveKitModule","configureAudio","startAudioSession","stopAudioSession","Platform","OS","getAudioOutputs","deviceId","selectAudioOutput","showAudioRoutePicker","setAppleAudioConfiguration"],"sources":["AudioSession.ts"],"sourcesContent":["import { Platform } from 'react-native';\nimport LiveKitModule from '../LKNativeModule';\n\n/**\n * Configuration for the underlying AudioSession.\n *\n * ----\n * Android specific options:\n *\n * * preferredOutputList - The preferred order in which to automatically select an audio output.\n * This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.\n *\n * By default, the order is set to:\n * 1. `\"bluetooth\"\n * 2. `\"headset\"``\n * 3. `\"speaker\"`\n * 4. `\"earpiece\"`\n *\n * * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the\n * audio options to use on Android.\n *\n * See {@link AndroidAudioTypePresets} for pre-configured values.\n *\n * ----\n * iOS\n *\n * * defaultOutput - The default preferred output to use when a wired headset or bluetooth output is unavailable.\n *\n * By default, this is set to `\"speaker\"`\n */\nexport type AudioConfiguration = {\n android?: {\n preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];\n audioTypeOptions: AndroidAudioTypeOptions;\n };\n ios?: {\n defaultOutput?: 'speaker' | 'earpiece';\n };\n};\n\nexport type AndroidAudioTypeOptions = {\n /**\n * Whether LiveKit should handle managing the audio focus or not.\n *\n * Defaults to true.\n */\n manageAudioFocus?: boolean;\n\n /**\n * Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}\n *\n * Defaults to 'inCommunication'.\n */\n audioMode?:\n | 'normal'\n | 'callScreening'\n | 'inCall'\n | 'inCommunication'\n | 'ringtone';\n\n /**\n * Corresponds to the duration hint when requesting audio focus.\n *\n * Defaults to 'gain'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}\n */\n audioFocusMode?:\n | 'gain'\n | 'gainTransient'\n | 'gainTransientExclusive'\n | 'gainTransientMayDuck';\n\n /**\n * Corresponds to Android's AudioAttributes usage type.\n *\n * Defaults to 'voiceCommunication'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesUsageType?:\n | 'alarm'\n | 'assistanceAccessibility'\n | 'assistanceNavigationGuidance'\n | 'assistanceSonification'\n | 'assistant'\n | 'game'\n | 'media'\n | 'notification'\n | 'notificationEvent'\n | 'notificationRingtone'\n | 'unknown'\n | 'voiceCommunication'\n | 'voiceCommunicationSignalling';\n\n /**\n * Corresponds to Android's AndroidAttributes content type.\n *\n * Defaults to 'speech'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesContentType?:\n | 'movie'\n | 'music'\n | 'sonification'\n | 'speech'\n | 'unknown';\n\n /**\n * Corresponds to the stream type when requesting audio focus. Used on pre-O devices.\n *\n * Defaults to 'voiceCall'\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}\n */\n audioStreamType?:\n | 'accessibility'\n | 'alarm'\n | 'dtmf'\n | 'music'\n | 'notification'\n | 'ring'\n | 'system'\n | 'voiceCall';\n\n /**\n * On certain Android devices, audio routing does not function properly and\n * bluetooth microphones will not work unless audio mode is set to\n * `inCommunication` or `inCall`. Audio routing is turned off those cases.\n *\n * If this set to true, will attempt to do audio routing regardless of audio mode.\n *\n * Defaults to false.\n */\n forceHandleAudioRouting?: boolean;\n};\n\nexport const AndroidAudioTypePresets: {\n /**\n * A pre-configured AndroidAudioConfiguration for voice communication.\n */\n communication: AndroidAudioTypeOptions;\n /**\n * A pre-configured AndroidAudioConfiguration for media playback.\n */\n media: AndroidAudioTypeOptions;\n} = {\n communication: {\n manageAudioFocus: true,\n audioMode: 'inCommunication',\n audioFocusMode: 'gain',\n audioStreamType: 'voiceCall',\n audioAttributesUsageType: 'voiceCommunication',\n audioAttributesContentType: 'speech',\n },\n media: {\n manageAudioFocus: true,\n audioMode: 'normal',\n audioFocusMode: 'gain',\n audioStreamType: 'music',\n audioAttributesUsageType: 'media',\n audioAttributesContentType: 'unknown',\n },\n} as const;\n\nexport type AppleAudioMode =\n | 'default'\n | 'gameChat'\n | 'measurement'\n | 'moviePlayback'\n | 'spokenAudio'\n | 'videoChat'\n | 'videoRecording'\n | 'voiceChat'\n | 'voicePrompt';\n\nexport type AppleAudioCategory =\n | 'soloAmbient'\n | 'playback'\n | 'record'\n | 'playAndRecord'\n | 'multiRoute';\n\nexport type AppleAudioCategoryOption =\n | 'mixWithOthers'\n | 'duckOthers'\n | 'interruptSpokenAudioAndMixWithOthers'\n | 'allowBluetooth'\n | 'allowBluetoothA2DP'\n | 'allowAirPlay'\n | 'defaultToSpeaker';\n\nexport type AppleAudioConfiguration = {\n audioCategory?: AppleAudioCategory;\n audioCategoryOptions?: AppleAudioCategoryOption[];\n audioMode?: AppleAudioMode;\n};\n\nexport type AudioTrackState =\n | 'none'\n | 'remoteOnly'\n | 'localOnly'\n | 'localAndRemote';\n\nexport function getDefaultAppleAudioConfigurationForMode(\n mode: AudioTrackState,\n preferSpeakerOutput: boolean = true\n): AppleAudioConfiguration {\n if (mode === 'remoteOnly') {\n return {\n audioCategory: 'playback',\n audioCategoryOptions: ['mixWithOthers'],\n audioMode: 'spokenAudio',\n };\n } else if (mode === 'localAndRemote' || mode === 'localOnly') {\n return {\n audioCategory: 'playAndRecord',\n audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],\n audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',\n };\n }\n\n return {\n audioCategory: 'soloAmbient',\n audioCategoryOptions: [],\n audioMode: 'default',\n };\n}\n\nexport default class AudioSession {\n /**\n * Applies the provided audio configuration to the underlying AudioSession.\n *\n * Must be called prior to connecting to a Room for the configuration to apply correctly.\n *\n * See also useIOSAudioManagement for automatic configuration of iOS audio options.\n */\n static configureAudio = async (config: AudioConfiguration) => {\n await LiveKitModule.configureAudio(config);\n };\n\n /**\n * Starts an AudioSession.\n */\n static startAudioSession = async () => {\n await LiveKitModule.startAudioSession();\n };\n\n /**\n * Stops the existing AudioSession.\n */\n static stopAudioSession = async () => {\n await LiveKitModule.stopAudioSession();\n };\n\n /**\n * Gets the available audio outputs for use with {@link selectAudioOutput}.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * For Android, will return if available:\n * * \"speaker\"\n * * \"earpiece\"\n * * \"headset\"\n * * \"bluetooth\"\n *\n * ----\n *\n * For iOS, due to OS limitations, the only available types are:\n * * \"default\" - Use default iOS audio routing\n * * \"force_speaker\" - Force audio output through speaker\n *\n * See also {@link showAudioRoutePicker} to display a route picker that\n * can choose between other audio devices (i.e. headset/bluetooth/airplay),\n * or use a library like `react-native-avroutepicker` for a native platform\n * control.\n *\n * @returns the available audio output types\n */\n static getAudioOutputs = async (): Promise<string[]> => {\n if (Platform.OS === 'ios') {\n return ['default', 'force_speaker'];\n } else if (Platform.OS === 'android') {\n return (await LiveKitModule.getAudioOutputs()) as string[];\n } else {\n return [];\n }\n };\n\n /**\n * Select the provided audio output if available.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * @param deviceId A deviceId retrieved from {@link getAudioOutputs}\n */\n static selectAudioOutput = async (deviceId: string) => {\n await LiveKitModule.selectAudioOutput(deviceId);\n };\n\n /**\n * iOS only, requires iOS 11+.\n *\n * Displays an AVRoutePickerView for the user to choose their audio output.\n */\n static showAudioRoutePicker = async () => {\n if (Platform.OS === 'ios') {\n await LiveKitModule.showAudioRoutePicker();\n }\n };\n\n /**\n * Directly change the AVAudioSession category/mode.\n *\n * @param config The configuration to use. Null values will be omitted and the\n * existing values will be unchanged.\n */\n static setAppleAudioConfiguration = async (\n config: AppleAudioConfiguration\n ) => {\n if (Platform.OS === 'ios') {\n await LiveKitModule.setAppleAudioConfiguration(config);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,7 +3,7 @@ const LINKING_ERROR = `The package '@livekit/react-native' doesn't seem to be li
|
|
|
3
3
|
ios: "- You have run 'pod install'\n",
|
|
4
4
|
default: ''
|
|
5
5
|
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
|
|
6
|
-
const LiveKitModule = NativeModules.
|
|
6
|
+
const LiveKitModule = NativeModules.LivekitReactNativeModule ? NativeModules.LivekitReactNativeModule : new Proxy({}, {
|
|
7
7
|
get() {
|
|
8
8
|
throw new Error(LINKING_ERROR);
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","LiveKitModule","
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","LiveKitModule","LivekitReactNativeModule","Proxy","get","Error"],"sources":["LKNativeModule.ts"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nconst LINKING_ERROR =\n `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nconst LiveKitModule = NativeModules.LivekitReactNativeModule\n ? NativeModules.LivekitReactNativeModule\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\nexport default LiveKitModule;\n"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AACtD,MAAMC,aAAa,GACjB,gFAAgF,GAChFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,6CAA6C;AAE/C,MAAMC,aAAa,GAAGN,aAAa,CAACO,wBAAwB,GACxDP,aAAa,CAACO,wBAAwB,GACtC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,eAAeI,aAAa","ignoreList":[]}
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
2
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
3
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
ios: "- You have run 'pod install'\n",
|
|
7
|
-
default: ''
|
|
8
|
-
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
|
|
9
|
-
const LivekitReactNative = NativeModules.LivekitReactNative ? NativeModules.LivekitReactNative : new Proxy({}, {
|
|
10
|
-
get() {
|
|
11
|
-
throw new Error(LINKING_ERROR);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
4
|
+
import { Platform } from 'react-native';
|
|
5
|
+
import LiveKitModule from '../LKNativeModule';
|
|
14
6
|
|
|
15
7
|
/**
|
|
16
8
|
* Configuration for the underlying AudioSession.
|
|
@@ -87,19 +79,19 @@ export default class AudioSession {}
|
|
|
87
79
|
* See also useIOSAudioManagement for automatic configuration of iOS audio options.
|
|
88
80
|
*/
|
|
89
81
|
_defineProperty(AudioSession, "configureAudio", async config => {
|
|
90
|
-
await
|
|
82
|
+
await LiveKitModule.configureAudio(config);
|
|
91
83
|
});
|
|
92
84
|
/**
|
|
93
85
|
* Starts an AudioSession.
|
|
94
86
|
*/
|
|
95
87
|
_defineProperty(AudioSession, "startAudioSession", async () => {
|
|
96
|
-
await
|
|
88
|
+
await LiveKitModule.startAudioSession();
|
|
97
89
|
});
|
|
98
90
|
/**
|
|
99
91
|
* Stops the existing AudioSession.
|
|
100
92
|
*/
|
|
101
93
|
_defineProperty(AudioSession, "stopAudioSession", async () => {
|
|
102
|
-
await
|
|
94
|
+
await LiveKitModule.stopAudioSession();
|
|
103
95
|
});
|
|
104
96
|
/**
|
|
105
97
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
@@ -129,7 +121,7 @@ _defineProperty(AudioSession, "getAudioOutputs", async () => {
|
|
|
129
121
|
if (Platform.OS === 'ios') {
|
|
130
122
|
return ['default', 'force_speaker'];
|
|
131
123
|
} else if (Platform.OS === 'android') {
|
|
132
|
-
return await
|
|
124
|
+
return await LiveKitModule.getAudioOutputs();
|
|
133
125
|
} else {
|
|
134
126
|
return [];
|
|
135
127
|
}
|
|
@@ -142,7 +134,7 @@ _defineProperty(AudioSession, "getAudioOutputs", async () => {
|
|
|
142
134
|
* @param deviceId A deviceId retrieved from {@link getAudioOutputs}
|
|
143
135
|
*/
|
|
144
136
|
_defineProperty(AudioSession, "selectAudioOutput", async deviceId => {
|
|
145
|
-
await
|
|
137
|
+
await LiveKitModule.selectAudioOutput(deviceId);
|
|
146
138
|
});
|
|
147
139
|
/**
|
|
148
140
|
* iOS only, requires iOS 11+.
|
|
@@ -151,7 +143,7 @@ _defineProperty(AudioSession, "selectAudioOutput", async deviceId => {
|
|
|
151
143
|
*/
|
|
152
144
|
_defineProperty(AudioSession, "showAudioRoutePicker", async () => {
|
|
153
145
|
if (Platform.OS === 'ios') {
|
|
154
|
-
await
|
|
146
|
+
await LiveKitModule.showAudioRoutePicker();
|
|
155
147
|
}
|
|
156
148
|
});
|
|
157
149
|
/**
|
|
@@ -162,7 +154,7 @@ _defineProperty(AudioSession, "showAudioRoutePicker", async () => {
|
|
|
162
154
|
*/
|
|
163
155
|
_defineProperty(AudioSession, "setAppleAudioConfiguration", async config => {
|
|
164
156
|
if (Platform.OS === 'ios') {
|
|
165
|
-
await
|
|
157
|
+
await LiveKitModule.setAppleAudioConfiguration(config);
|
|
166
158
|
}
|
|
167
159
|
});
|
|
168
160
|
//# sourceMappingURL=AudioSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","LivekitReactNative","Proxy","get","Error","AndroidAudioTypePresets","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","_defineProperty","config","configureAudio","startAudioSession","stopAudioSession","OS","getAudioOutputs","deviceId","selectAudioOutput","showAudioRoutePicker","setAppleAudioConfiguration"],"sources":["AudioSession.ts"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nconst LINKING_ERROR =\n `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nconst LivekitReactNative = NativeModules.LivekitReactNative\n ? NativeModules.LivekitReactNative\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\n/**\n * Configuration for the underlying AudioSession.\n *\n * ----\n * Android specific options:\n *\n * * preferredOutputList - The preferred order in which to automatically select an audio output.\n * This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.\n *\n * By default, the order is set to:\n * 1. `\"bluetooth\"\n * 2. `\"headset\"``\n * 3. `\"speaker\"`\n * 4. `\"earpiece\"`\n *\n * * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the\n * audio options to use on Android.\n *\n * See {@link AndroidAudioTypePresets} for pre-configured values.\n *\n * ----\n * iOS\n *\n * * defaultOutput - The default preferred output to use when a wired headset or bluetooth output is unavailable.\n *\n * By default, this is set to `\"speaker\"`\n */\nexport type AudioConfiguration = {\n android?: {\n preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];\n audioTypeOptions: AndroidAudioTypeOptions;\n };\n ios?: {\n defaultOutput?: 'speaker' | 'earpiece';\n };\n};\n\nexport type AndroidAudioTypeOptions = {\n /**\n * Whether LiveKit should handle managing the audio focus or not.\n *\n * Defaults to true.\n */\n manageAudioFocus?: boolean;\n\n /**\n * Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}\n *\n * Defaults to 'inCommunication'.\n */\n audioMode?:\n | 'normal'\n | 'callScreening'\n | 'inCall'\n | 'inCommunication'\n | 'ringtone';\n\n /**\n * Corresponds to the duration hint when requesting audio focus.\n *\n * Defaults to 'gain'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}\n */\n audioFocusMode?:\n | 'gain'\n | 'gainTransient'\n | 'gainTransientExclusive'\n | 'gainTransientMayDuck';\n\n /**\n * Corresponds to Android's AudioAttributes usage type.\n *\n * Defaults to 'voiceCommunication'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesUsageType?:\n | 'alarm'\n | 'assistanceAccessibility'\n | 'assistanceNavigationGuidance'\n | 'assistanceSonification'\n | 'assistant'\n | 'game'\n | 'media'\n | 'notification'\n | 'notificationEvent'\n | 'notificationRingtone'\n | 'unknown'\n | 'voiceCommunication'\n | 'voiceCommunicationSignalling';\n\n /**\n * Corresponds to Android's AndroidAttributes content type.\n *\n * Defaults to 'speech'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesContentType?:\n | 'movie'\n | 'music'\n | 'sonification'\n | 'speech'\n | 'unknown';\n\n /**\n * Corresponds to the stream type when requesting audio focus. Used on pre-O devices.\n *\n * Defaults to 'voiceCall'\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}\n */\n audioStreamType?:\n | 'accessibility'\n | 'alarm'\n | 'dtmf'\n | 'music'\n | 'notification'\n | 'ring'\n | 'system'\n | 'voiceCall';\n\n /**\n * On certain Android devices, audio routing does not function properly and\n * bluetooth microphones will not work unless audio mode is set to\n * `inCommunication` or `inCall`. Audio routing is turned off those cases.\n *\n * If this set to true, will attempt to do audio routing regardless of audio mode.\n *\n * Defaults to false.\n */\n forceHandleAudioRouting?: boolean;\n};\n\nexport const AndroidAudioTypePresets: {\n /**\n * A pre-configured AndroidAudioConfiguration for voice communication.\n */\n communication: AndroidAudioTypeOptions;\n /**\n * A pre-configured AndroidAudioConfiguration for media playback.\n */\n media: AndroidAudioTypeOptions;\n} = {\n communication: {\n manageAudioFocus: true,\n audioMode: 'inCommunication',\n audioFocusMode: 'gain',\n audioStreamType: 'voiceCall',\n audioAttributesUsageType: 'voiceCommunication',\n audioAttributesContentType: 'speech',\n },\n media: {\n manageAudioFocus: true,\n audioMode: 'normal',\n audioFocusMode: 'gain',\n audioStreamType: 'music',\n audioAttributesUsageType: 'media',\n audioAttributesContentType: 'unknown',\n },\n} as const;\n\nexport type AppleAudioMode =\n | 'default'\n | 'gameChat'\n | 'measurement'\n | 'moviePlayback'\n | 'spokenAudio'\n | 'videoChat'\n | 'videoRecording'\n | 'voiceChat'\n | 'voicePrompt';\n\nexport type AppleAudioCategory =\n | 'soloAmbient'\n | 'playback'\n | 'record'\n | 'playAndRecord'\n | 'multiRoute';\n\nexport type AppleAudioCategoryOption =\n | 'mixWithOthers'\n | 'duckOthers'\n | 'interruptSpokenAudioAndMixWithOthers'\n | 'allowBluetooth'\n | 'allowBluetoothA2DP'\n | 'allowAirPlay'\n | 'defaultToSpeaker';\n\nexport type AppleAudioConfiguration = {\n audioCategory?: AppleAudioCategory;\n audioCategoryOptions?: AppleAudioCategoryOption[];\n audioMode?: AppleAudioMode;\n};\n\nexport type AudioTrackState =\n | 'none'\n | 'remoteOnly'\n | 'localOnly'\n | 'localAndRemote';\n\nexport function getDefaultAppleAudioConfigurationForMode(\n mode: AudioTrackState,\n preferSpeakerOutput: boolean = true\n): AppleAudioConfiguration {\n if (mode === 'remoteOnly') {\n return {\n audioCategory: 'playback',\n audioCategoryOptions: ['mixWithOthers'],\n audioMode: 'spokenAudio',\n };\n } else if (mode === 'localAndRemote' || mode === 'localOnly') {\n return {\n audioCategory: 'playAndRecord',\n audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],\n audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',\n };\n }\n\n return {\n audioCategory: 'soloAmbient',\n audioCategoryOptions: [],\n audioMode: 'default',\n };\n}\n\nexport default class AudioSession {\n /**\n * Applies the provided audio configuration to the underlying AudioSession.\n *\n * Must be called prior to connecting to a Room for the configuration to apply correctly.\n *\n * See also useIOSAudioManagement for automatic configuration of iOS audio options.\n */\n static configureAudio = async (config: AudioConfiguration) => {\n await LivekitReactNative.configureAudio(config);\n };\n\n /**\n * Starts an AudioSession.\n */\n static startAudioSession = async () => {\n await LivekitReactNative.startAudioSession();\n };\n\n /**\n * Stops the existing AudioSession.\n */\n static stopAudioSession = async () => {\n await LivekitReactNative.stopAudioSession();\n };\n\n /**\n * Gets the available audio outputs for use with {@link selectAudioOutput}.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * For Android, will return if available:\n * * \"speaker\"\n * * \"earpiece\"\n * * \"headset\"\n * * \"bluetooth\"\n *\n * ----\n *\n * For iOS, due to OS limitations, the only available types are:\n * * \"default\" - Use default iOS audio routing\n * * \"force_speaker\" - Force audio output through speaker\n *\n * See also {@link showAudioRoutePicker} to display a route picker that\n * can choose between other audio devices (i.e. headset/bluetooth/airplay),\n * or use a library like `react-native-avroutepicker` for a native platform\n * control.\n *\n * @returns the available audio output types\n */\n static getAudioOutputs = async (): Promise<string[]> => {\n if (Platform.OS === 'ios') {\n return ['default', 'force_speaker'];\n } else if (Platform.OS === 'android') {\n return (await LivekitReactNative.getAudioOutputs()) as string[];\n } else {\n return [];\n }\n };\n\n /**\n * Select the provided audio output if available.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * @param deviceId A deviceId retrieved from {@link getAudioOutputs}\n */\n static selectAudioOutput = async (deviceId: string) => {\n await LivekitReactNative.selectAudioOutput(deviceId);\n };\n\n /**\n * iOS only, requires iOS 11+.\n *\n * Displays an AVRoutePickerView for the user to choose their audio output.\n */\n static showAudioRoutePicker = async () => {\n if (Platform.OS === 'ios') {\n await LivekitReactNative.showAudioRoutePicker();\n }\n };\n\n /**\n * Directly change the AVAudioSession category/mode.\n *\n * @param config The configuration to use. Null values will be omitted and the\n * existing values will be unchanged.\n */\n static setAppleAudioConfiguration = async (\n config: AppleAudioConfiguration\n ) => {\n if (Platform.OS === 'ios') {\n await LivekitReactNative.setAppleAudioConfiguration(config);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["Platform","LiveKitModule","AndroidAudioTypePresets","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","_defineProperty","config","configureAudio","startAudioSession","stopAudioSession","OS","getAudioOutputs","deviceId","selectAudioOutput","showAudioRoutePicker","setAppleAudioConfiguration"],"sources":["AudioSession.ts"],"sourcesContent":["import { Platform } from 'react-native';\nimport LiveKitModule from '../LKNativeModule';\n\n/**\n * Configuration for the underlying AudioSession.\n *\n * ----\n * Android specific options:\n *\n * * preferredOutputList - The preferred order in which to automatically select an audio output.\n * This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.\n *\n * By default, the order is set to:\n * 1. `\"bluetooth\"\n * 2. `\"headset\"``\n * 3. `\"speaker\"`\n * 4. `\"earpiece\"`\n *\n * * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the\n * audio options to use on Android.\n *\n * See {@link AndroidAudioTypePresets} for pre-configured values.\n *\n * ----\n * iOS\n *\n * * defaultOutput - The default preferred output to use when a wired headset or bluetooth output is unavailable.\n *\n * By default, this is set to `\"speaker\"`\n */\nexport type AudioConfiguration = {\n android?: {\n preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];\n audioTypeOptions: AndroidAudioTypeOptions;\n };\n ios?: {\n defaultOutput?: 'speaker' | 'earpiece';\n };\n};\n\nexport type AndroidAudioTypeOptions = {\n /**\n * Whether LiveKit should handle managing the audio focus or not.\n *\n * Defaults to true.\n */\n manageAudioFocus?: boolean;\n\n /**\n * Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}\n *\n * Defaults to 'inCommunication'.\n */\n audioMode?:\n | 'normal'\n | 'callScreening'\n | 'inCall'\n | 'inCommunication'\n | 'ringtone';\n\n /**\n * Corresponds to the duration hint when requesting audio focus.\n *\n * Defaults to 'gain'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}\n */\n audioFocusMode?:\n | 'gain'\n | 'gainTransient'\n | 'gainTransientExclusive'\n | 'gainTransientMayDuck';\n\n /**\n * Corresponds to Android's AudioAttributes usage type.\n *\n * Defaults to 'voiceCommunication'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesUsageType?:\n | 'alarm'\n | 'assistanceAccessibility'\n | 'assistanceNavigationGuidance'\n | 'assistanceSonification'\n | 'assistant'\n | 'game'\n | 'media'\n | 'notification'\n | 'notificationEvent'\n | 'notificationRingtone'\n | 'unknown'\n | 'voiceCommunication'\n | 'voiceCommunicationSignalling';\n\n /**\n * Corresponds to Android's AndroidAttributes content type.\n *\n * Defaults to 'speech'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesContentType?:\n | 'movie'\n | 'music'\n | 'sonification'\n | 'speech'\n | 'unknown';\n\n /**\n * Corresponds to the stream type when requesting audio focus. Used on pre-O devices.\n *\n * Defaults to 'voiceCall'\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}\n */\n audioStreamType?:\n | 'accessibility'\n | 'alarm'\n | 'dtmf'\n | 'music'\n | 'notification'\n | 'ring'\n | 'system'\n | 'voiceCall';\n\n /**\n * On certain Android devices, audio routing does not function properly and\n * bluetooth microphones will not work unless audio mode is set to\n * `inCommunication` or `inCall`. Audio routing is turned off those cases.\n *\n * If this set to true, will attempt to do audio routing regardless of audio mode.\n *\n * Defaults to false.\n */\n forceHandleAudioRouting?: boolean;\n};\n\nexport const AndroidAudioTypePresets: {\n /**\n * A pre-configured AndroidAudioConfiguration for voice communication.\n */\n communication: AndroidAudioTypeOptions;\n /**\n * A pre-configured AndroidAudioConfiguration for media playback.\n */\n media: AndroidAudioTypeOptions;\n} = {\n communication: {\n manageAudioFocus: true,\n audioMode: 'inCommunication',\n audioFocusMode: 'gain',\n audioStreamType: 'voiceCall',\n audioAttributesUsageType: 'voiceCommunication',\n audioAttributesContentType: 'speech',\n },\n media: {\n manageAudioFocus: true,\n audioMode: 'normal',\n audioFocusMode: 'gain',\n audioStreamType: 'music',\n audioAttributesUsageType: 'media',\n audioAttributesContentType: 'unknown',\n },\n} as const;\n\nexport type AppleAudioMode =\n | 'default'\n | 'gameChat'\n | 'measurement'\n | 'moviePlayback'\n | 'spokenAudio'\n | 'videoChat'\n | 'videoRecording'\n | 'voiceChat'\n | 'voicePrompt';\n\nexport type AppleAudioCategory =\n | 'soloAmbient'\n | 'playback'\n | 'record'\n | 'playAndRecord'\n | 'multiRoute';\n\nexport type AppleAudioCategoryOption =\n | 'mixWithOthers'\n | 'duckOthers'\n | 'interruptSpokenAudioAndMixWithOthers'\n | 'allowBluetooth'\n | 'allowBluetoothA2DP'\n | 'allowAirPlay'\n | 'defaultToSpeaker';\n\nexport type AppleAudioConfiguration = {\n audioCategory?: AppleAudioCategory;\n audioCategoryOptions?: AppleAudioCategoryOption[];\n audioMode?: AppleAudioMode;\n};\n\nexport type AudioTrackState =\n | 'none'\n | 'remoteOnly'\n | 'localOnly'\n | 'localAndRemote';\n\nexport function getDefaultAppleAudioConfigurationForMode(\n mode: AudioTrackState,\n preferSpeakerOutput: boolean = true\n): AppleAudioConfiguration {\n if (mode === 'remoteOnly') {\n return {\n audioCategory: 'playback',\n audioCategoryOptions: ['mixWithOthers'],\n audioMode: 'spokenAudio',\n };\n } else if (mode === 'localAndRemote' || mode === 'localOnly') {\n return {\n audioCategory: 'playAndRecord',\n audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],\n audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',\n };\n }\n\n return {\n audioCategory: 'soloAmbient',\n audioCategoryOptions: [],\n audioMode: 'default',\n };\n}\n\nexport default class AudioSession {\n /**\n * Applies the provided audio configuration to the underlying AudioSession.\n *\n * Must be called prior to connecting to a Room for the configuration to apply correctly.\n *\n * See also useIOSAudioManagement for automatic configuration of iOS audio options.\n */\n static configureAudio = async (config: AudioConfiguration) => {\n await LiveKitModule.configureAudio(config);\n };\n\n /**\n * Starts an AudioSession.\n */\n static startAudioSession = async () => {\n await LiveKitModule.startAudioSession();\n };\n\n /**\n * Stops the existing AudioSession.\n */\n static stopAudioSession = async () => {\n await LiveKitModule.stopAudioSession();\n };\n\n /**\n * Gets the available audio outputs for use with {@link selectAudioOutput}.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * For Android, will return if available:\n * * \"speaker\"\n * * \"earpiece\"\n * * \"headset\"\n * * \"bluetooth\"\n *\n * ----\n *\n * For iOS, due to OS limitations, the only available types are:\n * * \"default\" - Use default iOS audio routing\n * * \"force_speaker\" - Force audio output through speaker\n *\n * See also {@link showAudioRoutePicker} to display a route picker that\n * can choose between other audio devices (i.e. headset/bluetooth/airplay),\n * or use a library like `react-native-avroutepicker` for a native platform\n * control.\n *\n * @returns the available audio output types\n */\n static getAudioOutputs = async (): Promise<string[]> => {\n if (Platform.OS === 'ios') {\n return ['default', 'force_speaker'];\n } else if (Platform.OS === 'android') {\n return (await LiveKitModule.getAudioOutputs()) as string[];\n } else {\n return [];\n }\n };\n\n /**\n * Select the provided audio output if available.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * @param deviceId A deviceId retrieved from {@link getAudioOutputs}\n */\n static selectAudioOutput = async (deviceId: string) => {\n await LiveKitModule.selectAudioOutput(deviceId);\n };\n\n /**\n * iOS only, requires iOS 11+.\n *\n * Displays an AVRoutePickerView for the user to choose their audio output.\n */\n static showAudioRoutePicker = async () => {\n if (Platform.OS === 'ios') {\n await LiveKitModule.showAudioRoutePicker();\n }\n };\n\n /**\n * Directly change the AVAudioSession category/mode.\n *\n * @param config The configuration to use. Null values will be omitted and the\n * existing values will be unchanged.\n */\n static setAppleAudioConfiguration = async (\n config: AppleAudioConfiguration\n ) => {\n if (Platform.OS === 'ios') {\n await LiveKitModule.setAppleAudioConfiguration(config);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
4
5
|
|
|
5
6
|
Pod::Spec.new do |s|
|
|
6
7
|
s.name = "livekit-react-native"
|
|
@@ -17,11 +18,30 @@ Pod::Spec.new do |s|
|
|
|
17
18
|
|
|
18
19
|
s.framework = 'AVFAudio'
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
# Swift/Objective-C compatibility
|
|
22
|
+
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
|
23
|
+
|
|
21
24
|
s.dependency "livekit-react-native-webrtc"
|
|
22
25
|
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
27
|
+
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
28
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
29
|
+
install_modules_dependencies(s)
|
|
30
|
+
else
|
|
31
|
+
s.dependency "React-Core"
|
|
32
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
33
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
34
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
35
|
+
s.pod_target_xcconfig = {
|
|
36
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
37
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
38
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
39
|
+
}
|
|
40
|
+
s.dependency "React-Codegen"
|
|
41
|
+
s.dependency "RCT-Folly"
|
|
42
|
+
s.dependency "RCTRequired"
|
|
43
|
+
s.dependency "RCTTypeSafety"
|
|
44
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
27
47
|
end
|
package/package.json
CHANGED
package/src/LKNativeModule.ts
CHANGED
|
@@ -5,8 +5,8 @@ const LINKING_ERROR =
|
|
|
5
5
|
'- You rebuilt the app after installing the package\n' +
|
|
6
6
|
'- You are not using Expo managed workflow\n';
|
|
7
7
|
|
|
8
|
-
const LiveKitModule = NativeModules.
|
|
9
|
-
? NativeModules.
|
|
8
|
+
const LiveKitModule = NativeModules.LivekitReactNativeModule
|
|
9
|
+
? NativeModules.LivekitReactNativeModule
|
|
10
10
|
: new Proxy(
|
|
11
11
|
{},
|
|
12
12
|
{
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
`The package '@livekit/react-native' doesn't seem to be linked. Make sure: \n\n` +
|
|
4
|
-
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
5
|
-
'- You rebuilt the app after installing the package\n' +
|
|
6
|
-
'- You are not using Expo managed workflow\n';
|
|
7
|
-
|
|
8
|
-
const LivekitReactNative = NativeModules.LivekitReactNative
|
|
9
|
-
? NativeModules.LivekitReactNative
|
|
10
|
-
: new Proxy(
|
|
11
|
-
{},
|
|
12
|
-
{
|
|
13
|
-
get() {
|
|
14
|
-
throw new Error(LINKING_ERROR);
|
|
15
|
-
},
|
|
16
|
-
}
|
|
17
|
-
);
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import LiveKitModule from '../LKNativeModule';
|
|
18
3
|
|
|
19
4
|
/**
|
|
20
5
|
* Configuration for the underlying AudioSession.
|
|
@@ -252,21 +237,21 @@ export default class AudioSession {
|
|
|
252
237
|
* See also useIOSAudioManagement for automatic configuration of iOS audio options.
|
|
253
238
|
*/
|
|
254
239
|
static configureAudio = async (config: AudioConfiguration) => {
|
|
255
|
-
await
|
|
240
|
+
await LiveKitModule.configureAudio(config);
|
|
256
241
|
};
|
|
257
242
|
|
|
258
243
|
/**
|
|
259
244
|
* Starts an AudioSession.
|
|
260
245
|
*/
|
|
261
246
|
static startAudioSession = async () => {
|
|
262
|
-
await
|
|
247
|
+
await LiveKitModule.startAudioSession();
|
|
263
248
|
};
|
|
264
249
|
|
|
265
250
|
/**
|
|
266
251
|
* Stops the existing AudioSession.
|
|
267
252
|
*/
|
|
268
253
|
static stopAudioSession = async () => {
|
|
269
|
-
await
|
|
254
|
+
await LiveKitModule.stopAudioSession();
|
|
270
255
|
};
|
|
271
256
|
|
|
272
257
|
/**
|
|
@@ -297,7 +282,7 @@ export default class AudioSession {
|
|
|
297
282
|
if (Platform.OS === 'ios') {
|
|
298
283
|
return ['default', 'force_speaker'];
|
|
299
284
|
} else if (Platform.OS === 'android') {
|
|
300
|
-
return (await
|
|
285
|
+
return (await LiveKitModule.getAudioOutputs()) as string[];
|
|
301
286
|
} else {
|
|
302
287
|
return [];
|
|
303
288
|
}
|
|
@@ -311,7 +296,7 @@ export default class AudioSession {
|
|
|
311
296
|
* @param deviceId A deviceId retrieved from {@link getAudioOutputs}
|
|
312
297
|
*/
|
|
313
298
|
static selectAudioOutput = async (deviceId: string) => {
|
|
314
|
-
await
|
|
299
|
+
await LiveKitModule.selectAudioOutput(deviceId);
|
|
315
300
|
};
|
|
316
301
|
|
|
317
302
|
/**
|
|
@@ -321,7 +306,7 @@ export default class AudioSession {
|
|
|
321
306
|
*/
|
|
322
307
|
static showAudioRoutePicker = async () => {
|
|
323
308
|
if (Platform.OS === 'ios') {
|
|
324
|
-
await
|
|
309
|
+
await LiveKitModule.showAudioRoutePicker();
|
|
325
310
|
}
|
|
326
311
|
};
|
|
327
312
|
|
|
@@ -335,7 +320,7 @@ export default class AudioSession {
|
|
|
335
320
|
config: AppleAudioConfiguration
|
|
336
321
|
) => {
|
|
337
322
|
if (Platform.OS === 'ios') {
|
|
338
|
-
await
|
|
323
|
+
await LiveKitModule.setAppleAudioConfiguration(config);
|
|
339
324
|
}
|
|
340
325
|
};
|
|
341
326
|
}
|
package/ios/AudioUtils.h
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
#if TARGET_OS_IPHONE
|
|
2
|
-
#import <AVFoundation/AVFoundation.h>
|
|
3
|
-
|
|
4
|
-
@interface AudioUtils : NSObject
|
|
5
|
-
+ (AVAudioSessionMode)audioSessionModeFromString:(NSString*)mode;
|
|
6
|
-
+ (AVAudioSessionCategory)audioSessionCategoryFromString:(NSString *)category;
|
|
7
|
-
@end
|
|
8
|
-
|
|
9
|
-
#endif
|
package/ios/AudioUtils.m
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
#if TARGET_OS_IPHONE
|
|
2
|
-
#import "AudioUtils.h"
|
|
3
|
-
#import <AVFoundation/AVFoundation.h>
|
|
4
|
-
|
|
5
|
-
@implementation AudioUtils
|
|
6
|
-
|
|
7
|
-
+ (AVAudioSessionMode)audioSessionModeFromString:(NSString*)mode {
|
|
8
|
-
if([@"default_" isEqualToString:mode]) {
|
|
9
|
-
return AVAudioSessionModeDefault;
|
|
10
|
-
} else if([@"voicePrompt" isEqualToString:mode]) {
|
|
11
|
-
return AVAudioSessionModeVoicePrompt;
|
|
12
|
-
} else if([@"videoRecording" isEqualToString:mode]) {
|
|
13
|
-
return AVAudioSessionModeVideoRecording;
|
|
14
|
-
} else if([@"videoChat" isEqualToString:mode]) {
|
|
15
|
-
return AVAudioSessionModeVideoChat;
|
|
16
|
-
} else if([@"voiceChat" isEqualToString:mode]) {
|
|
17
|
-
return AVAudioSessionModeVoiceChat;
|
|
18
|
-
} else if([@"gameChat" isEqualToString:mode]) {
|
|
19
|
-
return AVAudioSessionModeGameChat;
|
|
20
|
-
} else if([@"measurement" isEqualToString:mode]) {
|
|
21
|
-
return AVAudioSessionModeMeasurement;
|
|
22
|
-
} else if([@"moviePlayback" isEqualToString:mode]) {
|
|
23
|
-
return AVAudioSessionModeMoviePlayback;
|
|
24
|
-
} else if([@"spokenAudio" isEqualToString:mode]) {
|
|
25
|
-
return AVAudioSessionModeSpokenAudio;
|
|
26
|
-
}
|
|
27
|
-
return AVAudioSessionModeDefault;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
+ (AVAudioSessionCategory)audioSessionCategoryFromString:(NSString *)category {
|
|
31
|
-
if([@"ambient" isEqualToString:category]) {
|
|
32
|
-
return AVAudioSessionCategoryAmbient;
|
|
33
|
-
} else if([@"soloAmbient" isEqualToString:category]) {
|
|
34
|
-
return AVAudioSessionCategorySoloAmbient;
|
|
35
|
-
} else if([@"playback" isEqualToString:category]) {
|
|
36
|
-
return AVAudioSessionCategoryPlayback;
|
|
37
|
-
} else if([@"record" isEqualToString:category]) {
|
|
38
|
-
return AVAudioSessionCategoryRecord;
|
|
39
|
-
} else if([@"playAndRecord" isEqualToString:category]) {
|
|
40
|
-
return AVAudioSessionCategoryPlayAndRecord;
|
|
41
|
-
} else if([@"multiRoute" isEqualToString:category]) {
|
|
42
|
-
return AVAudioSessionCategoryMultiRoute;
|
|
43
|
-
}
|
|
44
|
-
return AVAudioSessionCategoryAmbient;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
@end
|
|
48
|
-
#endif
|