Skip to content

Commit e4854d3

Browse files
author
Mikael Wills
committed
Audio session fixes
1 parent 0a48b58 commit e4854d3

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,22 +1821,26 @@ 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 {
17991834
_siprixModule.handleIncomingPush()
18001835

1836+
_siprixModule.writeLog("CxProvider: onPushIncoming CALLED")
18011837
let call = CallModel(callId:kInvalidId, withVideo:true, from:"SiprixPushKit")
18021838
_callsList.append(call)
1803-
1839+
_siprixModule.writeLog("CxProvider: onPushIncoming - call added with uuid:\(call.uuid), id:kInvalidId")
1840+
18041841
reportNewIncomingCall(call)
1805-
1806-
_siprixModule.writeLog("CxProvider: onPushIncoming - added new call with uuid:\(call.uuid)")
1842+
1843+
_siprixModule.writeLog("CxProvider: onPushIncoming - returning uuid:\(call.uuid)")
18071844
return call.uuid.uuidString
18081845
}
18091846

@@ -1823,8 +1860,9 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
18231860

18241861
func proceedCxAnswerAction(_ call: CallModel) {
18251862
let err = _siprixModule.callAccept(Int32(call.id), withVideo:call.withVideo)
1826-
if (err == kErrorCodeEOK) { call.cxAnswerAction?.fulfill() }
1827-
else { call.cxAnswerAction?.fail() }
1863+
if (err != kErrorCodeEOK) {
1864+
call.cxAnswerAction?.fail()
1865+
}
18281866
_siprixModule.writeLog("CxProvider: proceedCxAnswerAction err:\(err) sipCallId:\(call.id) uuid:\(call.uuid))")
18291867
}
18301868

@@ -1850,22 +1888,35 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
18501888

18511889
public func sipAppUpdateCallDetails(_ callKit_callUUID:UUID, callId:Int?,
18521890
localizedName:String?, genericHandle:String?, withVideo:Bool?) {
1891+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails CALLED - uuid:\(callKit_callUUID) callId:\(String(describing: callId))")
18531892
let call = self.getCallByUUID(callKit_callUUID)
18541893
if(call == nil) {
1855-
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails uuid:\(callKit_callUUID) call not found")
1894+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call NOT FOUND for uuid:\(callKit_callUUID)")
18561895
return
18571896
}
1858-
1897+
1898+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - found call, state: id=\(call!.id), answered=\(call!.answeredByCallKit), rejected=\(call!.rejectedByCallKit)")
1899+
18591900
if(callId != nil) {
18601901
//INVITE received - match SIP callId and UUID
1861-
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails uuid:\(callKit_callUUID) set sipCallId:\(callId!)")
1902+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - matching SIP callId:\(callId!) with CallKit uuid:\(callKit_callUUID)")
18621903
call!.setSipCallId(callId: callId!, withVideo: withVideo)
1863-
1904+
18641905
if(call!.rejectedByCallKit) {
1906+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call was rejected, proceeding with end action")
18651907
self.proceedCxEndAction(call!)
18661908
}
18671909
else if(call!.answeredByCallKit) {
1868-
self.proceedCxAnswerAction(call!)
1910+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call was answered! _audioSessionConfigured=\(_audioSessionConfigured)")
1911+
if _audioSessionConfigured {
1912+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - audio ready, accepting IMMEDIATELY")
1913+
self.proceedCxAnswerAction(call!)
1914+
} else {
1915+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - audio not ready, deferring until didActivate")
1916+
_callPendingAnswer = call
1917+
}
1918+
} else {
1919+
self._siprixModule.writeLog("CxProvider: sipAppUpdateCallDetails - call not answered yet (waiting for user)")
18691920
}
18701921
}
18711922

@@ -2067,22 +2118,38 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
20672118
}
20682119

20692120
func provider(_: CXProvider, perform action: CXAnswerCallAction) {
2121+
_siprixModule.writeLog("CxProvider: CXAnswerCallAction CALLED - uuid:\(action.callUUID)")
20702122
let call = getCallByUUID(action.callUUID)
20712123
if(call == nil) {
2072-
_siprixModule.writeLog("CxProvider: CXAnswer uuid:\(action.callUUID) not found")
2124+
_siprixModule.writeLog("CxProvider: Call NOT FOUND for uuid:\(action.callUUID)")
20732125
action.fail()
20742126
return
20752127
}
2076-
2128+
2129+
_siprixModule.writeLog("CxProvider: Found call - sipCallId:\(call!.id) uuid:\(call!.uuid) fromTo:\(call!.fromTo)")
20772130
call!.cxAnswerAction = action
2078-
2131+
20792132
if (call!.id == kInvalidId) {
2133+
_siprixModule.writeLog("CxProvider: KILLED APP SCENARIO - SIP INVITE not received yet, setting answeredByCallKit=true")
20802134
call!.answeredByCallKit = true
2081-
_siprixModule.writeLog("CxProvider: CXAnswer uuid:\(action.callUUID) SIP hasn't received yet")
20822135
}else{
2083-
_siprixModule.writeLog("CxProvider: CXAnswer uuid:\(action.callUUID) callId:\(call!.id)")
2084-
proceedCxAnswerAction(call!)
2136+
_siprixModule.writeLog("CxProvider: FOREGROUND SCENARIO - SIP callId:\(call!.id) known, setting _callPendingAnswer")
2137+
_callPendingAnswer = call
2138+
2139+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
2140+
guard let self = self else { return }
2141+
if let pendingCall = self._callPendingAnswer, pendingCall.id == call!.id,
2142+
self._callsList.contains(where: { $0.id == pendingCall.id }) {
2143+
self._siprixModule.writeLog("CxProvider: FALLBACK TIMER FIRED - didActivate didn't fire, proceeding with answer anyway")
2144+
self.ensureAudioSessionConfigured()
2145+
self.proceedCxAnswerAction(pendingCall)
2146+
self._callPendingAnswer = nil
2147+
}
2148+
}
20852149
}
2150+
2151+
action.fulfill()
2152+
_siprixModule.writeLog("CxProvider: Fulfilled CXAnswerCallAction - CallKit will now activate audio")
20862153
}
20872154

20882155
func provider(_: CXProvider, perform action: CXPlayDTMFCallAction) {
@@ -2147,12 +2214,44 @@ class SiprixCxProvider : NSObject, CXProviderDelegate {
21472214
}
21482215

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

21542252
func provider(_: CXProvider, didDeactivate audioSession: AVAudioSession) {
21552253
_siprixModule.writeLog("CxProvider: didDeactivate")
2254+
_audioSessionConfigured = false // Reset flag when deactivated
21562255
_siprixModule.deactivate(audioSession)
21572256
}
21582257

0 commit comments

Comments
 (0)