@@ -200,29 +200,27 @@ final class AudioDeviceModule: NSObject, RTCAudioDeviceModuleDelegate, Encodable
200200 . store ( in: disposableBag)
201201
202202 source. manualRestoreVoiceProcessingOnMono = true
203- ( source as? RTCAudioDeviceModule ) ? . setRecordingAlwaysPreparedMode ( false )
203+ ( source as? RTCAudioDeviceModule ) ? . setRecordingAlwaysPreparedMode ( true )
204204 }
205205
206206 // MARK: - Recording
207207
208- func startPlayout( ) throws {
209- try throwingExecution ( " Unable to start playout " ) {
210- source. initAndStartPlayout ( )
208+ func setPlayout( _ isActive: Bool ) throws {
209+ try RetriableTask . run ( iterations: 3 ) {
210+ try throwingExecution ( " Unable to start playout " ) {
211+ if isActive {
212+ return source. initAndStartPlayout ( )
213+ } else {
214+ return source. stopPlayout ( )
215+ }
216+ }
211217 }
212218 }
213219
214220 /// Enables or disables recording on the wrapped audio device module.
215221 /// - Parameter isEnabled: When `true` recording starts, otherwise stops.
216222 /// - Throws: `ClientError` when the underlying module reports a failure.
217223 func setRecording( _ isEnabled: Bool ) throws {
218- defer {
219- log. throwing ( " Unable to start playout " , subsystems: . audioSession) {
220- try throwingExecution ( " setReocording defer " ) {
221- source. initAndStartPlayout ( )
222- }
223- }
224- }
225-
226224 guard isEnabled != isRecording else {
227225 return
228226 }
@@ -254,22 +252,12 @@ final class AudioDeviceModule: NSObject, RTCAudioDeviceModuleDelegate, Encodable
254252 /// - Parameter isMuted: `true` to mute the microphone, `false` to unmute.
255253 /// - Throws: `ClientError` when the underlying module reports a failure.
256254 func setMuted( _ isMuted: Bool ) throws {
257- defer {
258- log. throwing ( " Unable to start playout " , subsystems: . audioSession) {
259- try throwingExecution ( " setMuted defer " ) {
260- source. initAndStartPlayout ( )
261- }
262- }
263- }
264-
265255 guard isMuted != isMicrophoneMuted else {
266256 return
267257 }
268258
269- if isStereoPlayoutEnabled {
270- try throwingExecution ( " Unable to stop playout " ) {
271- source. stopPlayout ( )
272- }
259+ if !isMuted {
260+ _ = source. initAndStartRecording ( )
273261 }
274262
275263 try throwingExecution ( " Unable to setMicrophoneMuted: \( isMuted) " ) {
@@ -284,53 +272,8 @@ final class AudioDeviceModule: NSObject, RTCAudioDeviceModuleDelegate, Encodable
284272 function: StaticString = #function,
285273 line: UInt = #line
286274 ) throws {
287- defer {
288- log. throwing ( " Unable to start playout " , subsystems: . audioSession) {
289- try throwingExecution ( " setStereoPlayoutEnabled defer " ) {
290- source. initAndStartPlayout ( )
291- }
292- }
293- }
294- /// We explicitelly avoid checking the current state of isStereoPlayoutEnabled as there are case
295- /// where the value may be true but playout isn't stereo and a restart is required.
296- let currentVoiceProcessingEnabled = source. isVoiceProcessingEnabled
297- let currentVoiceProcessingBypassed = source. isVoiceProcessingBypassed
298-
299- func onFailureReset( ) {
300- _ = source. setVoiceProcessingEnabled ( currentVoiceProcessingEnabled)
301- _ = source. setVoiceProcessingBypassed ( currentVoiceProcessingBypassed)
302- _ = source. setVoiceProcessingAGCEnabled ( currentVoiceProcessingEnabled)
303- try ? startPlayout ( )
304- }
305-
306- /// To enable stereoPlayout we need to do the following in the order mentioned below:
307- /// 1. disable voice-processing
308- /// 2. disable voice-processing-agc
309- /// 3. set voice-processing-bypassed to `true`
310- /// 4. set stereo-playout to `true`
311- ///
312- /// To disable stereoPlayout we need to do the following in the order mentioned below:
313- /// 1. set stereo-playout to `false`
314- /// 2. set voice-processing-bypassed to `false`
315- /// 3. enable voice-processing
316- /// 4. enable voice-processing-agc
317-
318- _ = source. stopPlayout ( )
319- do {
320- if isEnabled {
321- try throwingExecution ( " Failed to disable VoiceProcessing. " ) { source. setVoiceProcessingEnabled ( false ) }
322- try throwingExecution ( " Failed to disable VoiceProcessingAGC. " ) { source. setVoiceProcessingAGCEnabled ( false ) }
323- try throwingExecution ( " Failed to enable VoiceProcessing bypass. " ) { source. setVoiceProcessingBypassed ( true ) }
324- try throwingExecution ( " Failed to enable Stereo Playout. " ) { source. setStereoPlayoutEnabled ( true ) }
325- } else {
326- try throwingExecution ( " Failed to disable Stereo Playout. " ) { source. setStereoPlayoutEnabled ( false ) }
327- try throwingExecution ( " Failed to disable VoiceProcessing bypass. " ) { source. setVoiceProcessingBypassed ( false ) }
328- try throwingExecution ( " Failed to enable VoiceProcessing. " ) { source. setVoiceProcessingEnabled ( true ) }
329- try throwingExecution ( " Failed to enable VoiceProcessingAGC. " ) { source. setVoiceProcessingAGCEnabled ( true ) }
330- }
331- } catch {
332- onFailureReset ( )
333- throw error
275+ try throwingExecution ( " Failed to enable Stereo Playout. " ) {
276+ source. setStereoPlayoutEnabled ( isEnabled)
334277 }
335278
336279 guard source. isStereoPlayoutEnabled != isEnabled else {
@@ -341,7 +284,6 @@ final class AudioDeviceModule: NSObject, RTCAudioDeviceModuleDelegate, Encodable
341284 return
342285 }
343286
344- onFailureReset ( )
345287 throw ClientError (
346288 " Failed to "
347289 + " setStereoPlayoutEnabled: \( isEnabled) . "
@@ -621,3 +563,40 @@ extension AVAudioEngine {
621563 return " \( asbd. mChannelsPerFrame) ch @ \( asbd. mSampleRate) Hz "
622564 }
623565}
566+
567+ enum RetriableTask {
568+ static func run(
569+ iterations: Int ,
570+ operation: ( ) throws -> Void
571+ ) throws {
572+ try execute (
573+ currentIteration: 0 ,
574+ iterations: iterations,
575+ operation: operation
576+ )
577+ }
578+
579+ private static func execute(
580+ currentIteration: Int ,
581+ iterations: Int ,
582+ operation: ( ) throws -> Void
583+ ) throws {
584+ do {
585+ return try operation ( )
586+ } catch {
587+ if currentIteration < iterations - 1 {
588+ do {
589+ return try execute (
590+ currentIteration: currentIteration + 1 ,
591+ iterations: iterations,
592+ operation: operation
593+ )
594+ } catch {
595+ throw error
596+ }
597+ } else {
598+ throw error
599+ }
600+ }
601+ }
602+ }
0 commit comments