// // ProviderDelegate.swift // CallTutorial // // Created by QuentinArguillere on 05/08/2020. // Copyright © 2020 BelledonneCommunications. All rights reserved. // import Foundation import CallKit import linphonesw import AVFoundation class CallKitProviderDelegate : NSObject { private let provider: CXProvider let mCallController = CXCallController() var tutorialContext : CallKitExampleContext! var incomingCallUUID : UUID! init(context: CallKitExampleContext) { tutorialContext = context let providerConfiguration = CXProviderConfiguration() providerConfiguration.supportsVideo = true providerConfiguration.supportedHandleTypes = [.generic] providerConfiguration.maximumCallsPerCallGroup = 1 providerConfiguration.maximumCallGroups = 1 provider = CXProvider(configuration: providerConfiguration) super.init() provider.setDelegate(self, queue: nil) // The CXProvider delegate will trigger CallKit related callbacks } func incomingCall() { NSLog("Callkit incomingCall -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ") incomingCallUUID = UUID() let update = CXCallUpdate() update.remoteHandle = CXHandle(type:.generic, value: tutorialContext.incomingCallName) provider.reportNewIncomingCall(with: incomingCallUUID, update: update, completion: { error in }) // Report to CallKit a call is incoming } func stopCall() { NSLog("Callkit stopCall -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ") let endCallAction = CXEndCallAction(call: incomingCallUUID) let transaction = CXTransaction(action: endCallAction) mCallController.request(transaction, completion: { error in }) // Report to CallKit a call must end } } // In this extension, we implement the action we want to be done when CallKit is notified of something. // This can happen through the CallKit GUI in the app, or directly in the code (see, incomingCall(), stopCall() functions above) extension CallKitProviderDelegate: CXProviderDelegate { func provider(_ provider: CXProvider, perform action: CXEndCallAction) { NSLog("Callkit CXEndCallAction -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ") do { if (tutorialContext.mCall?.state != .End && tutorialContext.mCall?.state != .Released) { try tutorialContext.mCall?.terminate() } } catch { NSLog(error.localizedDescription) } tutorialContext.isCallRunning = false tutorialContext.isCallIncoming = false action.fulfill() } func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { NSLog("Callkit CXAnswerCallAction -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ") do { // The audio stream is going to start shortly: the AVAudioSession must be configured now. // It is worth to note that an application does not have permission to configure the // AVAudioSession outside of this delegate action while it is running in background, // which is usually the case in an incoming call scenario. tutorialContext.mCore.configureAudioSession(); try tutorialContext.mCall?.accept() tutorialContext.isCallRunning = true } catch { print(error) } action.fulfill() } func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {} func provider(_ provider: CXProvider, perform action: CXStartCallAction) { // This tutorial is not doing outgoing calls. If it had to do so, // configureAudioSession() shall be called from here, just before launching the // call. // tutorialContext.mCore.configureAudioSession(); // tutorialContext.mCore.invite("sip:bob@example.net"); // action.fulfill(); } func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {} func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) {} func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {} func providerDidReset(_ provider: CXProvider) {} func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) { NSLog("Callkit didActivateaudiosession -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ") // The linphone Core must be notified that CallKit has activated the AVAudioSession // in order to start streaming audio. tutorialContext.linphoneAsyncHelper.postOnCoreQueue { self.tutorialContext.mCore.activateAudioSession(actived: true) } } func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { // The linphone Core must be notified that CallKit has deactivated the AVAudioSession. tutorialContext.linphoneAsyncHelper.postOnCoreQueue { self.tutorialContext.mCore.activateAudioSession(actived: false) } } }