Skip to content

Commit e08727b

Browse files
author
Mikael Wills
committed
Audio session fixes
1 parent 27d850f commit e08727b

File tree

1 file changed

+124
-25
lines changed

1 file changed

+124
-25
lines changed

siprix_voip_sdk_ios/ios/Classes/SiprixVoipSdkPlugin.swift

Lines changed: 124 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,10 @@ public class SiprixVoipSdkPlugin: NSObject, FlutterPlugin {
782782
func handleModuleUnInitialize(_ args : ArgsMap, result: @escaping FlutterResult) {
783783
let err = _siprixModule.unInitialize()
784784
_initialized = false
785+
786+
_pushKitProvider = nil
787+
_callKitProvider = nil
788+
785789
sendResult(err, result:result)
786790
}
787791

@@ -1708,7 +1712,9 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
17081712
private var _cxProvider: CXProvider!
17091713
private var _cxCallCtrl: CXCallController
17101714
private var _callsList: [CallModel] = []
1711-
1715+
private var _audioSessionConfigured = false
1716+
private var _callPendingAnswer: CallModel? = nil
1717+
17121718
static let kECallNotFound: Int32 = -1040
17131719
static let kEConfRequires2Calls: Int32 = -1055
17141720

@@ -1719,7 +1725,31 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
17191725
createCxProvider(singleCallMode, includeInRecents:includeInRecents)
17201726
_siprixModule.writeLog("CxProvider: created")
17211727
}
1722-
1728+
1729+
//--------------------------------------------------------
1730+
//Audio Session Management
1731+
1732+
private func ensureAudioSessionConfigured() {
1733+
#if os(iOS)
1734+
guard !_audioSessionConfigured else { return }
1735+
1736+
let audioSession = AVAudioSession.sharedInstance()
1737+
1738+
do {
1739+
try audioSession.setCategory(.playAndRecord, options: [.allowBluetooth, .allowBluetoothA2DP])
1740+
try audioSession.setMode(.voiceChat)
1741+
try audioSession.setActive(true)
1742+
1743+
_audioSessionConfigured = true
1744+
_siprixModule.writeLog("CxProvider: Manual audio session activation successful")
1745+
1746+
} catch {
1747+
_siprixModule.writeLog("CxProvider: Manual audio config warning (might be ok): \(error)")
1748+
_audioSessionConfigured = true
1749+
}
1750+
#endif
1751+
}
1752+
17231753
//--------------------------------------------------------
17241754
//Event handlers
17251755

@@ -1754,14 +1784,17 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
17541784

17551785
self._cxProvider.reportCall(with:call.uuid, endedAt: nil, reason: reason)
17561786
}
1757-
//Remove call item from collection
1787+
1788+
if _callPendingAnswer?.id == call.id {
1789+
_callPendingAnswer = nil
1790+
_siprixModule.writeLog("CxProvider: cleared pending answer for terminated call \(call.id)")
1791+
}
1792+
17581793
_callsList.remove(at:callIdx!)
17591794
_siprixModule.writeLog("CxProvider: onSipTerminated remove callId:\(call.id) <=> \(call.uuid)")
17601795
}
17611796

17621797
func onSipConnected(_ callId: Int, withVideo:Bool) {
1763-
_siprixModule.activate( AVAudioSession.sharedInstance())
1764-
17651798
let call = self._callsList.first(where: {$0.id == callId})
17661799
if(call == nil) { return }
17671800

@@ -1788,20 +1821,24 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
17881821
}
17891822

17901823
func onSipIncoming(_ callId:Int, withVideo:Bool, hdrFrom:String, hdrTo:String) {
1824+
_siprixModule.writeLog("CxProvider: onSipIncoming CALLED - callId:\(callId) from:\(hdrFrom)")
17911825
let call = CallModel(callId:callId, withVideo:withVideo, from:hdrFrom)
17921826
_callsList.append(call)
1793-
1827+
_siprixModule.writeLog("CxProvider: onSipIncoming - call added to list, uuid:\(call.uuid)")
1828+
17941829
reportNewIncomingCall(call)
1795-
_siprixModule.writeLog("CxProvider: onSipIncoming - added new call with uuid:\(call.uuid)")
1830+
_siprixModule.writeLog("CxProvider: onSipIncoming - reportNewIncomingCall completed for uuid:\(call.uuid)")
17961831
}
1797-
1832+
17981833
public func onPushIncoming() -> String {
1834+
_siprixModule.writeLog("CxProvider: onPushIncoming CALLED")
17991835
let call = CallModel(callId:kInvalidId, withVideo:true, from:"SiprixPushKit")
18001836
_callsList.append(call)
1801-
1837+
_siprixModule.writeLog("CxProvider: onPushIncoming - call added with uuid:\(call.uuid), id:kInvalidId")
1838+
18021839
reportNewIncomingCall(call)
1803-
1804-
_siprixModule.writeLog("CxProvider: onPushIncoming - added new call with uuid:\(call.uuid)")
1840+
1841+
_siprixModule.writeLog("CxProvider: onPushIncoming - returning uuid:\(call.uuid)")
18051842
return call.uuid.uuidString
18061843
}
18071844

@@ -1821,8 +1858,9 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
18211858

18221859
func proceedCxAnswerAction(_ call: CallModel) {
18231860
let err = _siprixModule.callAccept(Int32(call.id), withVideo:call.withVideo)
1824-
if (err == kErrorCodeEOK) { call.cxAnswerAction?.fulfill() }
1825-
else { call.cxAnswerAction?.fail() }
1861+
if (err != kErrorCodeEOK) {
1862+
call.cxAnswerAction?.fail()
1863+
}
18261864
_siprixModule.writeLog("CxProvider: proceedCxAnswerAction err:\(err) sipCallId:\(call.id) uuid:\(call.uuid))")
18271865
}
18281866

@@ -1848,22 +1886,35 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
18481886

18491887
public func sipAppUpdateCallDetails(_ callKit_callUUID:UUID, callId:Int?,
18501888
localizedName:String?, genericHandle:String?, withVideo:Bool?) {
1889+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails CALLED - uuid:\(callKit_callUUID) callId:\(String(describing: callId))")
18511890
let call = self.getCallByUUID(callKit_callUUID)
18521891
if(call == nil) {
1853-
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails uuid:\(callKit_callUUID) call not found")
1892+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call NOT FOUND for uuid:\(callKit_callUUID)")
18541893
return
18551894
}
1856-
1895+
1896+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - found call, state: id=\(call!.id), answered=\(call!.answeredByCallKit), rejected=\(call!.rejectedByCallKit)")
1897+
18571898
if(callId != nil) {
18581899
//INVITE received - match SIP callId and UUID
1859-
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails uuid:\(callKit_callUUID) set sipCallId:\(callId!)")
1900+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - matching SIP callId:\(callId!) with CallKit uuid:\(callKit_callUUID)")
18601901
call!.setSipCallId(callId: callId!, withVideo: withVideo)
1861-
1902+
18621903
if(call!.rejectedByCallKit) {
1904+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call was rejected, proceeding with end action")
18631905
self.proceedCxEndAction(call!)
18641906
}
18651907
else if(call!.answeredByCallKit) {
1866-
self.proceedCxAnswerAction(call!)
1908+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call was answered! _audioSessionConfigured=\(_audioSessionConfigured)")
1909+
if _audioSessionConfigured {
1910+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - audio ready, accepting IMMEDIATELY")
1911+
self.proceedCxAnswerAction(call!)
1912+
} else {
1913+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - audio not ready, deferring until didActivate")
1914+
_callPendingAnswer = call
1915+
}
1916+
} else {
1917+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call not answered yet (waiting for user)")
18671918
}
18681919
}
18691920

@@ -2065,22 +2116,38 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
20652116
}
20662117

20672118
func provider(_: CXProvider, perform action: CXAnswerCallAction) {
2119+
_siprixModule.writeLog("CxProvider: CXAnswerCallAction CALLED - uuid:\(action.callUUID)")
20682120
let call = getCallByUUID(action.callUUID)
20692121
if(call == nil) {
2070-
_siprixModule.writeLog("CxProvider: CXAnswer uuid:\(action.callUUID) not found")
2122+
_siprixModule.writeLog("CxProvider: Call NOT FOUND for uuid:\(action.callUUID)")
20712123
action.fail()
20722124
return
20732125
}
2074-
2126+
2127+
_siprixModule.writeLog("CxProvider: Found call - sipCallId:\(call!.id) uuid:\(call!.uuid) fromTo:\(call!.fromTo)")
20752128
call!.cxAnswerAction = action
2076-
2129+
20772130
if (call!.id == kInvalidId) {
2131+
_siprixModule.writeLog("CxProvider: KILLED APP SCENARIO - SIP INVITE not received yet, setting answeredByCallKit=true")
20782132
call!.answeredByCallKit = true
2079-
_siprixModule.writeLog("CxProvider: CXAnswer uuid:\(action.callUUID) SIP hasn't received yet")
20802133
}else{
2081-
_siprixModule.writeLog("CxProvider: CXAnswer uuid:\(action.callUUID) callId:\(call!.id)")
2082-
proceedCxAnswerAction(call!)
2134+
_siprixModule.writeLog("CxProvider: FOREGROUND SCENARIO - SIP callId:\(call!.id) known, setting _callPendingAnswer")
2135+
_callPendingAnswer = call
2136+
2137+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
2138+
guard let self = self else { return }
2139+
if let pendingCall = self._callPendingAnswer, pendingCall.id == call!.id,
2140+
self._callsList.contains(where: { $0.id == pendingCall.id }) {
2141+
self._siprixModule.writeLog("CxProvider: FALLBACK TIMER FIRED - didActivate didn't fire, proceeding with answer anyway")
2142+
self.ensureAudioSessionConfigured()
2143+
self.proceedCxAnswerAction(pendingCall)
2144+
self._callPendingAnswer = nil
2145+
}
2146+
}
20832147
}
2148+
2149+
action.fulfill()
2150+
_siprixModule.writeLog("CxProvider: Fulfilled CXAnswerCallAction - CallKit will now activate audio")
20842151
}
20852152

20862153
func provider(_: CXProvider, perform action: CXPlayDTMFCallAction) {
@@ -2145,12 +2212,44 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
21452212
}
21462213

21472214
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
2148-
_siprixModule.writeLog("CxProvider: didActivate")
2215+
_siprixModule.writeLog("CxProvider: _callPendingAnswer: \(_callPendingAnswer?.id ?? -999)")
2216+
_siprixModule.writeLog("CxProvider: _audioSessionConfigured (before): \(_audioSessionConfigured)")
2217+
_siprixModule.writeLog("CxProvider: audioSession.isInputAvailable: \(audioSession.isInputAvailable) isOtherAudioPlaying: \(audioSession.isOtherAudioPlaying)")
2218+
2219+
#if os(iOS)
2220+
if !audioSession.isInputAvailable || audioSession.isOtherAudioPlaying {
2221+
_siprixModule.writeLog("CxProvider: Audio session interrupted/blocked - forcing reset")
2222+
do {
2223+
try audioSession.setActive(false)
2224+
try audioSession.setActive(true)
2225+
_siprixModule.writeLog("CxProvider: Audio session reset successful")
2226+
} catch {
2227+
_siprixModule.writeLog("CxProvider: Audio session reset failed: \(error)")
2228+
}
2229+
}
2230+
#endif
2231+
2232+
ensureAudioSessionConfigured()
21492233
_siprixModule.activate(audioSession)
2234+
_siprixModule.writeLog("CxProvider: _audioSessionConfigured (after): \(_audioSessionConfigured)")
2235+
2236+
if let call = _callPendingAnswer {
2237+
_siprixModule.writeLog("CxProvider: Found _callPendingAnswer: callId:\(call.id) uuid:\(call.uuid)")
2238+
let callStillExists = _callsList.contains(where: { $0.id == call.id })
2239+
if callStillExists {
2240+
_siprixModule.writeLog("CxProvider: Call still exists, proceeding with accept")
2241+
proceedCxAnswerAction(call)
2242+
} else {
2243+
_siprixModule.writeLog("CxProvider: Call no longer exists (cancelled)")
2244+
}
2245+
_callPendingAnswer = nil
2246+
}
2247+
_siprixModule.writeLog("CxProvider: ======================================== didActivate END")
21502248
}
21512249

21522250
func provider(_: CXProvider, didDeactivate audioSession: AVAudioSession) {
21532251
_siprixModule.writeLog("CxProvider: didDeactivate")
2252+
_audioSessionConfigured = false // Reset flag when deactivated
21542253
_siprixModule.deactivate(audioSession)
21552254
}
21562255

0 commit comments

Comments
 (0)