@@ -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,86 +136,61 @@ public class LivekitReactNativeModule: RCTEventEmitter {
114136 reject ( " selectAudioOutput error " , error. localizedDescription, error)
115137 return
116138 }
117-
139+
118140 resolve ( nil )
119141 }
120-
121- @objc ( setAppleAudioConfiguration: )
122- public func setAppleAudioConfiguration( _ configuration: NSDictionary ) {
142+
143+ @objc ( setAppleAudioConfiguration: withResolver : withRejecter : )
144+ public func setAppleAudioConfiguration( _ configuration: NSDictionary , resolve : RCTPromiseResolveBlock , reject : RCTPromiseRejectBlock ) {
123145 let session = RTCAudioSession . sharedInstance ( )
124146 let config = RTCAudioSessionConfiguration . webRTC ( )
125-
147+
126148 let appleAudioCategory = configuration [ " audioCategory " ] as? String
127149 let appleAudioCategoryOptions = configuration [ " audioCategoryOptions " ] as? [ String ]
128150 let appleAudioMode = configuration [ " audioMode " ] as? String
129-
151+
130152 session. lockForConfiguration ( )
131-
132- var categoryChanged = false
133-
134- if let appleAudioCategoryOptions = appleAudioCategoryOptions {
135- categoryChanged = true
136-
137- var newOptions : AVAudioSession . CategoryOptions = [ ]
138- for option in appleAudioCategoryOptions {
139- if option == " mixWithOthers " {
140- newOptions. insert ( . mixWithOthers)
141- } else if option == " duckOthers " {
142- newOptions. insert ( . duckOthers)
143- } else if option == " allowBluetooth " {
144- newOptions. insert ( . allowBluetooth)
145- } else if option == " allowBluetoothA2DP " {
146- newOptions. insert ( . allowBluetoothA2DP)
147- } else if option == " allowAirPlay " {
148- newOptions. insert ( . allowAirPlay)
149- } else if option == " defaultToSpeaker " {
150- newOptions. insert ( . defaultToSpeaker)
151- }
152- }
153- config. categoryOptions = newOptions
153+ defer {
154+ session. unlockForConfiguration ( )
154155 }
155-
156+
156157 if let appleAudioCategory = appleAudioCategory {
157- categoryChanged = true
158158 config. category = AudioUtils . audioSessionCategoryFromString ( appleAudioCategory) . rawValue
159159 }
160-
161- if categoryChanged {
162- do {
163- try session. setCategory ( AVAudioSession . Category ( rawValue: config. category) , with: config. categoryOptions)
164- } catch {
165- NSLog ( " Error setting category: %@ " , error. localizedDescription)
166- }
160+
161+ if let appleAudioCategoryOptions = appleAudioCategoryOptions {
162+ config. categoryOptions = AudioUtils . audioSessionCategoryOptionsFromStrings ( appleAudioCategoryOptions)
167163 }
168-
164+
169165 if let appleAudioMode = appleAudioMode {
170- let mode = AudioUtils . audioSessionModeFromString ( appleAudioMode)
171- config. mode = mode. rawValue
172- do {
173- try session. setMode ( mode)
174- } catch {
175- NSLog ( " Error setting mode: %@ " , error. localizedDescription)
176- }
166+ config. mode = AudioUtils . audioSessionModeFromString ( appleAudioMode) . rawValue
177167 }
178-
179- session. unlockForConfiguration ( )
168+
169+ do {
170+ try session. setConfiguration ( config)
171+ resolve ( nil )
172+ } catch {
173+ reject ( " setAppleAudioConfiguration " , " Error setting category: \( error. localizedDescription) " , error)
174+ return
175+ }
176+
180177 }
181-
178+
182179 @objc ( createAudioSinkListener: trackId: )
183180 public func createAudioSinkListener( _ pcId: NSNumber , trackId: String ) -> String {
184181 let renderer = AudioSinkRenderer ( eventEmitter: self )
185182 let reactTag = self . audioRendererManager. registerRenderer ( renderer)
186183 renderer. reactTag = reactTag
187184 self . audioRendererManager. attach ( renderer: renderer, pcId: pcId, trackId: trackId)
188-
185+
189186 return reactTag
190187 }
191188
192189 @objc ( deleteAudioSinkListener: pcId: trackId: )
193190 public func deleteAudioSinkListener( _ reactTag: String , pcId: NSNumber , trackId: String ) -> Any ? {
194191 self . audioRendererManager. detach ( rendererByTag: reactTag, pcId: pcId, trackId: trackId)
195192 self . audioRendererManager. unregisterRenderer ( forReactTag: reactTag)
196-
193+
197194 return nil
198195 }
199196
@@ -203,15 +200,15 @@ public class LivekitReactNativeModule: RCTEventEmitter {
203200 let reactTag = self . audioRendererManager. registerRenderer ( renderer)
204201 renderer. reactTag = reactTag
205202 self . audioRendererManager. attach ( renderer: renderer, pcId: pcId, trackId: trackId)
206-
203+
207204 return reactTag
208205 }
209206
210207 @objc ( deleteVolumeProcessor: pcId: trackId: )
211208 public func deleteVolumeProcessor( _ reactTag: String , pcId: NSNumber , trackId: String ) -> Any ? {
212209 self . audioRendererManager. detach ( rendererByTag: reactTag, pcId: pcId, trackId: trackId)
213210 self . audioRendererManager. unregisterRenderer ( forReactTag: reactTag)
214-
211+
215212 return nil
216213 }
217214
@@ -221,7 +218,7 @@ public class LivekitReactNativeModule: RCTEventEmitter {
221218 let minFrequency = ( options [ " minFrequency " ] as? NSNumber ) ? . floatValue ?? 1000
222219 let maxFrequency = ( options [ " maxFrequency " ] as? NSNumber ) ? . floatValue ?? 8000
223220 let intervalMs = ( options [ " updateInterval " ] as? NSNumber ) ? . floatValue ?? 40
224-
221+
225222 let renderer = MultibandVolumeAudioRenderer (
226223 bands: bands,
227224 minFrequency: minFrequency,
@@ -232,26 +229,26 @@ public class LivekitReactNativeModule: RCTEventEmitter {
232229 let reactTag = self . audioRendererManager. registerRenderer ( renderer)
233230 renderer. reactTag = reactTag
234231 self . audioRendererManager. attach ( renderer: renderer, pcId: pcId, trackId: trackId)
235-
232+
236233 return reactTag
237234 }
238-
235+
239236 @objc ( deleteMultibandVolumeProcessor: pcId: trackId: )
240237 public func deleteMultibandVolumeProcessor( _ reactTag: String , pcId: NSNumber , trackId: String ) -> Any ? {
241238 self . audioRendererManager. detach ( rendererByTag: reactTag, pcId: pcId, trackId: trackId)
242239 self . audioRendererManager. unregisterRenderer ( forReactTag: reactTag)
243-
240+
244241 return nil
245242 }
246-
243+
247244 @objc ( setDefaultAudioTrackVolume: )
248245 public func setDefaultAudioTrackVolume( _ volume: NSNumber ) -> Any ? {
249246 let options = WebRTCModuleOptions . sharedInstance ( )
250247 options. defaultTrackVolume = volume. doubleValue
251248
252249 return nil
253250 }
254-
251+
255252 override public func supportedEvents( ) -> [ String ] ! {
256253 return [
257254 LKEvents . kEventVolumeProcessed,
0 commit comments