Fix an issue where audio does not work when a VoIP Call is resumed after a GSM call has been terminated by the remote party.

This commit is contained in:
Simon Morlat 2022-11-22 12:08:19 +01:00 committed by QuentinArguillere
parent fc9c9b9508
commit c49013aa2b
2 changed files with 42 additions and 20 deletions

View file

@ -49,6 +49,7 @@ import AVFoundation
var actionsToPerformOnceWhenCoreIsOn : [(()->Void)] = []
var conference: Conference?
var callkitAudioSessionActivated : Bool? = nil // if "nil", ignore.
var actionToFulFill : CXCallAction? = nil;
var backgroundContextCall : Call?
@objc var backgroundContextCameraIsEnabled : Bool = false
@ -556,7 +557,7 @@ import AVFoundation
switch cstate {
case .IncomingReceived:
let addr = call.remoteAddress
var displayName = incomingDisplayName(call: call)
var displayName = incomingDisplayName(call: call)
if (CallManager.callKitEnabled()) {
let isConference = isConferenceCall(call: call)
@ -608,7 +609,13 @@ import AVFoundation
CallManager.instance().speakerBeforePause = false
CallManager.instance().changeRouteToSpeaker()
}
actionToFulFill?.fulfill()
actionToFulFill = nil
break
case .Paused:
actionToFulFill?.fulfill()
actionToFulFill = nil
break
case .OutgoingInit,
.OutgoingProgress,
.OutgoingRinging,

View file

@ -205,8 +205,10 @@ extension ProviderDelegate: CXProviderDelegate {
let uuid = action.callUUID
let callId = callInfos[uuid]?.callId
let call = CallManager.instance().callByCallId(callId: callId)
action.fulfill()
if (call == nil) {
Log.directLog(BCTBX_LOG_ERROR, text: "CXSetHeldCallAction: no call !")
action.fail()
return
}
@ -215,33 +217,46 @@ extension ProviderDelegate: CXProviderDelegate {
try CallManager.instance().lc?.leaveConference()
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: call-id: [\(String(describing: callId))] leaving conference")
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
return
}
let state = action.isOnHold ? "Paused" : "Resumed"
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: Call with call-id: [\(String(describing: callId))] and UUID: [\(uuid)] paused status changed to: [\(state)]")
if (action.isOnHold) {
if (call!.params?.localConferenceMode ?? false) {
return
}
CallManager.instance().speakerBeforePause = CallManager.instance().isSpeakerEnabled()
try call!.pause()
} else {
if (CallManager.instance().lc?.conference != nil && CallManager.instance().lc?.callsNb ?? 0 > 1) {
try CallManager.instance().lc?.enterConference()
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
action.fulfill()
}else{
let state = action.isOnHold ? "Paused" : "Resumed"
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: Call with call-id: [\(String(describing: callId))] and UUID: [\(uuid)] paused status changed to: [\(state)]")
if (action.isOnHold) {
CallManager.instance().speakerBeforePause = CallManager.instance().isSpeakerEnabled()
try call!.pause()
CallManager.instance().actionToFulFill = action;
} else {
try call!.resume()
if (CallManager.instance().lc?.conference != nil && CallManager.instance().lc?.callsNb ?? 0 > 1) {
try CallManager.instance().lc?.enterConference()
action.fulfill()
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
} else {
try call!.resume()
CallManager.instance().actionToFulFill = action;
// HORRIBLE HACK HERE - PLEASE APPLE FIX THIS !!
// When resuming a SIP call after a native call has ended remotely, didActivate: audioSession
// is never called.
// It looks like in this case, it is implicit.
// As a result we have to notify the Core that the AudioSession is active.
// The SpeakerBox demo application written by Apple exhibits this behavior.
// https://developer.apple.com/documentation/callkit/making_and_receiving_voip_calls_with_callkit
// We can clearly see there that startAudio() is called immediately in the CXSetHeldCallAction
// handler, while it is called from didActivate: audioSession otherwise.
// Callkit's design is not consistent, or its documentation imcomplete, wich is somewhat disapointing.
//
Log.directLog(BCTBX_LOG_DEBUG, text: "Assuming AudioSession is active when executing a CXSetHeldCallAction with isOnHold=false.")
CallManager.instance().lc?.activateAudioSession(actived: true)
CallManager.instance().callkitAudioSessionActivated = true
}
}
}
} catch {
Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: Call set held (paused or resumed) \(uuid) failed because \(error)")
action.fail()
}
}
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
do {
let uuid = action.callUUID