@@ -11,30 +11,30 @@ struct LKEvents {
1111
1212@objc ( LivekitReactNativeModule)
1313public class LivekitReactNativeModule : RCTEventEmitter {
14-
14+
1515 // This cannot be initialized in init as self.bridge is given afterwards.
1616 private var _audioRendererManager : AudioRendererManager ? = nil
1717 public var audioRendererManager : AudioRendererManager {
1818 get {
1919 if _audioRendererManager == nil {
2020 _audioRendererManager = AudioRendererManager ( bridge: self . bridge)
2121 }
22-
22+
2323 return _audioRendererManager!
2424 }
2525 }
26-
26+
2727 @objc
2828 public override init ( ) {
2929 super. init ( )
3030 let config = RTCAudioSessionConfiguration ( )
3131 config. category = AVAudioSession . Category. playAndRecord. rawValue
3232 config. categoryOptions = [ . allowAirPlay, . allowBluetooth, . allowBluetoothA2DP, . defaultToSpeaker]
3333 config. mode = AVAudioSession . Mode. videoChat. rawValue
34-
34+
3535 RTCAudioSessionConfiguration . setWebRTC ( config)
3636 }
37-
37+
3838 @objc
3939 override public static func requiresMainQueueSetup( ) -> Bool {
4040 return false
@@ -48,19 +48,19 @@ public class LivekitReactNativeModule: RCTEventEmitter {
4848 options. videoEncoderFactory = simulcastVideoEncoderFactory
4949 options. audioProcessingModule = LKAudioProcessingManager . sharedInstance ( ) . audioProcessingModule
5050 }
51-
51+
5252 @objc ( configureAudio: )
5353 public func configureAudio( _ config: NSDictionary ) {
5454 guard let iOSConfig = config [ " ios " ] as? NSDictionary
5555 else {
5656 return
5757 }
58-
58+
5959 let defaultOutput = iOSConfig [ " defaultOutput " ] as? String ?? " speaker "
60-
60+
6161 let rtcConfig = RTCAudioSessionConfiguration ( )
6262 rtcConfig. category = AVAudioSession . Category. playAndRecord. rawValue
63-
63+
6464 if ( defaultOutput == " earpiece " ) {
6565 rtcConfig. categoryOptions = [ . allowAirPlay, . allowBluetooth, . allowBluetoothA2DP] ;
6666 rtcConfig. mode = AVAudioSession . Mode. voiceChat. rawValue
@@ -70,17 +70,39 @@ public class LivekitReactNativeModule: RCTEventEmitter {
7070 }
7171 RTCAudioSessionConfiguration . setWebRTC ( rtcConfig)
7272 }
73-
74- @objc ( startAudioSession)
75- public func startAudioSession( ) {
76- // intentionally left empty
73+
74+ @objc ( startAudioSession: withRejecter: )
75+ public func startAudioSession( resolve: RCTPromiseResolveBlock , reject: RCTPromiseRejectBlock ) {
76+ let session = RTCAudioSession . sharedInstance ( )
77+ session. lockForConfiguration ( )
78+ defer {
79+ session. unlockForConfiguration ( )
80+ }
81+
82+ do {
83+ try session. setActive ( true )
84+ resolve ( nil )
85+ } catch {
86+ reject ( " startAudioSession " , " Error activating audio session: \( error. localizedDescription) " , error)
87+ }
7788 }
78-
79- @objc ( stopAudioSession)
80- public func stopAudioSession( ) {
81- // intentionally left empty
89+
90+ @objc ( stopAudioSession: withRejecter: )
91+ public func stopAudioSession( resolve: RCTPromiseResolveBlock , reject: RCTPromiseRejectBlock ) {
92+ let session = RTCAudioSession . sharedInstance ( )
93+ session. lockForConfiguration ( )
94+ defer {
95+ session. unlockForConfiguration ( )
96+ }
97+
98+ do {
99+ try session. setActive ( false )
100+ resolve ( nil )
101+ } catch {
102+ reject ( " stopAudioSession " , " Error deactivating audio session: \( error. localizedDescription) " , error)
103+ }
82104 }
83-
105+
84106 @objc ( showAudioRoutePicker)
85107 public func showAudioRoutePicker( ) {
86108 if #available( iOS 11 . 0 , * ) {
@@ -95,12 +117,12 @@ public class LivekitReactNativeModule: RCTEventEmitter {
95117 }
96118 }
97119 }
98-
120+
99121 @objc ( getAudioOutputsWithResolver: withRejecter: )
100122 public func getAudioOutputs( resolve: RCTPromiseResolveBlock , reject: RCTPromiseRejectBlock ) {
101123 resolve ( [ " default " , " force_speaker " ] )
102124 }
103-
125+
104126 @objc ( selectAudioOutput: withResolver: withRejecter: )
105127 public func selectAudioOutput( _ deviceId: String , resolve: RCTPromiseResolveBlock , reject: RCTPromiseRejectBlock ) {
106128 let session = AVAudioSession . sharedInstance ( )
@@ -114,7 +136,7 @@ public class LivekitReactNativeModule: RCTEventEmitter {
114136 reject ( " selectAudioOutput error " , error. localizedDescription, error)
115137 return
116138 }
117-
139+
118140 resolve ( nil )
119141 }
120142
@@ -132,64 +154,26 @@ public class LivekitReactNativeModule: RCTEventEmitter {
132154 session. unlockForConfiguration ( )
133155 }
134156
135- var categoryChanged = false
136-
137- if let appleAudioCategoryOptions = appleAudioCategoryOptions {
138- categoryChanged = true
139-
140- var newOptions : AVAudioSession . CategoryOptions = [ ]
141- for option in appleAudioCategoryOptions {
142- if option == " mixWithOthers " {
143- newOptions. insert ( . mixWithOthers)
144- } else if option == " duckOthers " {
145- newOptions. insert ( . duckOthers)
146- } else if option == " allowBluetooth " {
147- newOptions. insert ( . allowBluetooth)
148- } else if option == " allowBluetoothA2DP " {
149- newOptions. insert ( . allowBluetoothA2DP)
150- } else if option == " allowAirPlay " {
151- newOptions. insert ( . allowAirPlay)
152- } else if option == " defaultToSpeaker " {
153- newOptions. insert ( . defaultToSpeaker)
154- }
155- }
156- config. categoryOptions = newOptions
157- }
158-
159157 if let appleAudioCategory = appleAudioCategory {
160- categoryChanged = true
161158 config. category = AudioUtils . audioSessionCategoryFromString ( appleAudioCategory) . rawValue
162159 }
163160
164- if categoryChanged {
165- do {
166- try session. setCategory ( AVAudioSession . Category ( rawValue: config. category) , with: config. categoryOptions)
167- } catch {
168- reject ( " setAppleAudioConfiguration " , " Error setting category: \( error. localizedDescription) " , error)
169- return
170- }
161+ if let appleAudioCategoryOptions = appleAudioCategoryOptions {
162+ config. categoryOptions = AudioUtils . audioSessionCategoryOptionsFromStrings ( appleAudioCategoryOptions)
171163 }
172164
173165 if let appleAudioMode = appleAudioMode {
174- let mode = AudioUtils . audioSessionModeFromString ( appleAudioMode)
175- config. mode = mode. rawValue
176- do {
177- try session. setMode ( mode)
178- } catch {
179- reject ( " setAppleAudioConfiguration " , " Error setting mode: \( error. localizedDescription) " , error)
180- return
181- }
166+ config. mode = AudioUtils . audioSessionModeFromString ( appleAudioMode) . rawValue
182167 }
183168
184- // Activate the audio session
185169 do {
186- try session. setActive ( true )
170+ try session. setConfiguration ( config)
171+ resolve ( nil )
187172 } catch {
188- reject ( " setAppleAudioConfiguration " , " Error activating audio session : \( error. localizedDescription) " , error)
173+ reject ( " setAppleAudioConfiguration " , " Error setting category : \( error. localizedDescription) " , error)
189174 return
190175 }
191176
192- resolve ( nil )
193177 }
194178
195179 @objc ( createAudioSinkListener: trackId: )
@@ -198,15 +182,15 @@ public class LivekitReactNativeModule: RCTEventEmitter {
198182 let reactTag = self . audioRendererManager. registerRenderer ( renderer)
199183 renderer. reactTag = reactTag
200184 self . audioRendererManager. attach ( renderer: renderer, pcId: pcId, trackId: trackId)
201-
185+
202186 return reactTag
203187 }
204188
205189 @objc ( deleteAudioSinkListener: pcId: trackId: )
206190 public func deleteAudioSinkListener( _ reactTag: String , pcId: NSNumber , trackId: String ) -> Any ? {
207191 self . audioRendererManager. detach ( rendererByTag: reactTag, pcId: pcId, trackId: trackId)
208192 self . audioRendererManager. unregisterRenderer ( forReactTag: reactTag)
209-
193+
210194 return nil
211195 }
212196
@@ -216,15 +200,15 @@ public class LivekitReactNativeModule: RCTEventEmitter {
216200 let reactTag = self . audioRendererManager. registerRenderer ( renderer)
217201 renderer. reactTag = reactTag
218202 self . audioRendererManager. attach ( renderer: renderer, pcId: pcId, trackId: trackId)
219-
203+
220204 return reactTag
221205 }
222206
223207 @objc ( deleteVolumeProcessor: pcId: trackId: )
224208 public func deleteVolumeProcessor( _ reactTag: String , pcId: NSNumber , trackId: String ) -> Any ? {
225209 self . audioRendererManager. detach ( rendererByTag: reactTag, pcId: pcId, trackId: trackId)
226210 self . audioRendererManager. unregisterRenderer ( forReactTag: reactTag)
227-
211+
228212 return nil
229213 }
230214
@@ -234,7 +218,7 @@ public class LivekitReactNativeModule: RCTEventEmitter {
234218 let minFrequency = ( options [ " minFrequency " ] as? NSNumber ) ? . floatValue ?? 1000
235219 let maxFrequency = ( options [ " maxFrequency " ] as? NSNumber ) ? . floatValue ?? 8000
236220 let intervalMs = ( options [ " updateInterval " ] as? NSNumber ) ? . floatValue ?? 40
237-
221+
238222 let renderer = MultibandVolumeAudioRenderer (
239223 bands: bands,
240224 minFrequency: minFrequency,
@@ -245,26 +229,26 @@ public class LivekitReactNativeModule: RCTEventEmitter {
245229 let reactTag = self . audioRendererManager. registerRenderer ( renderer)
246230 renderer. reactTag = reactTag
247231 self . audioRendererManager. attach ( renderer: renderer, pcId: pcId, trackId: trackId)
248-
232+
249233 return reactTag
250234 }
251-
235+
252236 @objc ( deleteMultibandVolumeProcessor: pcId: trackId: )
253237 public func deleteMultibandVolumeProcessor( _ reactTag: String , pcId: NSNumber , trackId: String ) -> Any ? {
254238 self . audioRendererManager. detach ( rendererByTag: reactTag, pcId: pcId, trackId: trackId)
255239 self . audioRendererManager. unregisterRenderer ( forReactTag: reactTag)
256-
240+
257241 return nil
258242 }
259-
243+
260244 @objc ( setDefaultAudioTrackVolume: )
261245 public func setDefaultAudioTrackVolume( _ volume: NSNumber ) -> Any ? {
262246 let options = WebRTCModuleOptions . sharedInstance ( )
263247 options. defaultTrackVolume = volume. doubleValue
264248
265249 return nil
266250 }
267-
251+
268252 override public func supportedEvents( ) -> [ String ] ! {
269253 return [
270254 LKEvents . kEventVolumeProcessed,
0 commit comments