Suggestions from CD for Async Call backs and Core objects associated with publishers
This commit is contained in:
@@ -8,17 +8,15 @@
|
||||
|
||||
import linphonesw
|
||||
import AVFoundation
|
||||
|
||||
import Combine
|
||||
|
||||
|
||||
class CallKitExampleContext : ObservableObject
|
||||
{
|
||||
private let queue = DispatchQueue(label:"core.queue")
|
||||
var mCore: Core!
|
||||
var mAccount: Account?
|
||||
var mCoreDelegate : CoreDelegate!
|
||||
var mIterateTimer : Timer!
|
||||
|
||||
|
||||
@Published var coreVersion: String = Core.getVersion
|
||||
@Published var username : String = "quentindev"
|
||||
@Published var passwd : String = "dev"
|
||||
@@ -32,101 +30,122 @@ class CallKitExampleContext : ObservableObject
|
||||
@Published var isSpeakerEnabled : Bool = false
|
||||
@Published var isMicrophoneEnabled : Bool = false
|
||||
|
||||
/* Async */
|
||||
let linphoneAsyncHelper = LinphoneAsyncHelper()
|
||||
|
||||
|
||||
/*------------ Callkit tutorial related variables ---------------*/
|
||||
let incomingCallName = "Incoming call example"
|
||||
var mCall : Call?
|
||||
var mProviderDelegate : CallKitProviderDelegate!
|
||||
var mCallAlreadyStopped : Bool = false;
|
||||
|
||||
|
||||
func postOnCoreQueue(lambda : @escaping ()->()) {
|
||||
queue.async {
|
||||
lambda()
|
||||
}
|
||||
func addRegistrationStateCallBack(core:Core) {
|
||||
core.createAccountRegistrationStateChangedPublisher()
|
||||
.postOnMainQueue { result in
|
||||
NSLog("New registration state is \(result.state) for user id \( String(describing: result.account.params?.identityAddress?.asString()))\n")
|
||||
if (result.state == .Ok) {
|
||||
self.loggedIn = true
|
||||
// Since core has "Push Enabled", the reception and setting of the push notification token is done automatically
|
||||
// It should have been set and used when we log in, you can check here or in the liblinphone logs
|
||||
NSLog("Account registered Push voip token: \(result.account.params?.pushNotificationConfig?.voipToken)")
|
||||
} else if (result.state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
}
|
||||
.postOnCoreQueue{ result in
|
||||
// optional something on core queue if needed
|
||||
}
|
||||
}
|
||||
|
||||
func postOnMainQueue(lambda : @escaping()->()) {
|
||||
DispatchQueue.main.async {
|
||||
lambda()
|
||||
}
|
||||
|
||||
func addCallStateChangedCallBack(core:Core) {
|
||||
core.createOnCallStateChangedPublisher()
|
||||
.postOnMainQueue { result in
|
||||
self.callMsg = result.message
|
||||
if (result.state == .PushIncomingReceived){
|
||||
// We're being called by someone (and app is in background)
|
||||
self.mCall = result.call
|
||||
self.mProviderDelegate.incomingCall()
|
||||
self.isCallIncoming = true
|
||||
self.callMsg = result.message
|
||||
} else if (result.state == .IncomingReceived) {
|
||||
// If app is in foreground, it's likely that we will receive the SIP invite before the Push notification
|
||||
if (!self.isCallIncoming) {
|
||||
self.mCall = result.call
|
||||
self.mProviderDelegate.incomingCall()
|
||||
|
||||
self.isCallIncoming = true
|
||||
self.callMsg = result.message
|
||||
}
|
||||
self.remoteAddress = result.call.remoteAddress!.asStringUriOnly()
|
||||
} else if (result.state == .Connected) {
|
||||
self.isCallIncoming = false
|
||||
self.isCallRunning = true
|
||||
} else if (result.state == .Released || result.state == .End || result.state == .Error) {
|
||||
// Call has been terminated by any side
|
||||
|
||||
// Report to CallKit that the call is over, if the terminate action was initiated by other end of the call
|
||||
if (self.isCallRunning) {
|
||||
self.mProviderDelegate.stopCall()
|
||||
}
|
||||
self.remoteAddress = "Nobody yet"
|
||||
}
|
||||
}
|
||||
.postOnCoreQueue{ result in
|
||||
// optional something on core queue if needed
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
{
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
let factory = Factory.Instance
|
||||
// IMPORTANT : In this tutorial, we require the use of a core configuration file.
|
||||
// This way, once the registration is done, and until it is cleared, it will return to the LoggedIn state on launch.
|
||||
// This allows us to have a functional call when the app was closed and is started by a VOIP push notification (incoming call
|
||||
// We also need to enable "Push Notitifications" and "Background Mode - Voice Over IP"
|
||||
let configDir = factory.getConfigDir(context: nil)
|
||||
try? mCore = factory.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
|
||||
// enabling push notifications management in the core
|
||||
mCore.callkitEnabled = true
|
||||
mCore.pushNotificationEnabled = true
|
||||
mCore.autoIterateEnabled = false
|
||||
|
||||
|
||||
mCoreDelegate = CoreDelegateStub( onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||
self.callMsg = message
|
||||
if (state == .PushIncomingReceived){
|
||||
// We're being called by someone (and app is in background)
|
||||
self.mCall = call
|
||||
self.mProviderDelegate.incomingCall()
|
||||
self.isCallIncoming = true
|
||||
self.callMsg = message
|
||||
} else if (state == .IncomingReceived) {
|
||||
// If app is in foreground, it's likely that we will receive the SIP invite before the Push notification
|
||||
if (!self.isCallIncoming) {
|
||||
self.mCall = call
|
||||
self.mProviderDelegate.incomingCall()
|
||||
|
||||
self.isCallIncoming = true
|
||||
self.callMsg = message
|
||||
linphoneAsyncHelper.postOnCoreQueue {
|
||||
let factory = Factory.Instance
|
||||
let configDir = factory.getConfigDir(context: nil)
|
||||
let corePublisher = self.linphoneAsyncHelper.createLinphoneObjectWithPublisher(createAction: {
|
||||
try factory.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
|
||||
})
|
||||
corePublisher
|
||||
.postOnCoreQueue (
|
||||
onError: { error in
|
||||
NSLog("failed creating core \(error)")
|
||||
},
|
||||
receiveValue: { core in
|
||||
self.mCore = core
|
||||
// enabling push notifications management in the core
|
||||
self.mCore.callkitEnabled = true
|
||||
self.mCore.pushNotificationEnabled = true
|
||||
self.mCore.autoIterateEnabled = false
|
||||
self.addRegistrationStateCallBack(core: core)
|
||||
self.addCallStateChangedCallBack(core: core)
|
||||
try? core.start()
|
||||
})
|
||||
.postOnMainQueue { core in
|
||||
self.mIterateTimer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { [weak self] timer in
|
||||
self?.linphoneAsyncHelper.postOnCoreQueue {
|
||||
core.iterate()
|
||||
}
|
||||
}
|
||||
self.remoteAddress = call.remoteAddress!.asStringUriOnly()
|
||||
} else if (state == .Connected) {
|
||||
self.isCallIncoming = false
|
||||
self.isCallRunning = true
|
||||
} else if (state == .Released || state == .End || state == .Error) {
|
||||
// Call has been terminated by any side
|
||||
|
||||
// Report to CallKit that the call is over, if the terminate action was initiated by other end of the call
|
||||
if (self.isCallRunning) {
|
||||
self.mProviderDelegate.stopCall()
|
||||
}
|
||||
self.remoteAddress = "Nobody yet"
|
||||
}
|
||||
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
|
||||
if (state == .Ok) {
|
||||
self.loggedIn = true
|
||||
// Since core has "Push Enabled", the reception and setting of the push notification token is done automatically
|
||||
// It should have been set and used when we log in, you can check here or in the liblinphone logs
|
||||
NSLog("Account registered Push voip token: \(account.params?.pushNotificationConfig?.voipToken)")
|
||||
} else if (state == .Cleared) {
|
||||
self.loggedIn = false
|
||||
}
|
||||
})
|
||||
|
||||
mIterateTimer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { [weak self] timer in
|
||||
self?.postOnCoreQueue {
|
||||
self?.mCore.iterate()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
mProviderDelegate = CallKitProviderDelegate(context: self)
|
||||
mCore.addDelegate(delegate: mCoreDelegate)
|
||||
|
||||
postOnCoreQueue {
|
||||
try? self.mCore.start()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func login() {
|
||||
|
||||
postOnCoreQueue {
|
||||
linphoneAsyncHelper.postOnCoreQueue {
|
||||
do {
|
||||
var transport : TransportType
|
||||
if (self.transportType == "TLS") { transport = TransportType.Tls }
|
||||
@@ -156,7 +175,7 @@ class CallKitExampleContext : ObservableObject
|
||||
|
||||
func unregister()
|
||||
{
|
||||
postOnCoreQueue {
|
||||
linphoneAsyncHelper.postOnCoreQueue {
|
||||
if let account = self.mCore.defaultAccount {
|
||||
let params = account.params
|
||||
let clonedParams = params?.clone()
|
||||
@@ -166,7 +185,7 @@ class CallKitExampleContext : ObservableObject
|
||||
}
|
||||
}
|
||||
func delete() {
|
||||
postOnCoreQueue {
|
||||
linphoneAsyncHelper.postOnCoreQueue {
|
||||
if let account = self.mCore.defaultAccount {
|
||||
self.mCore.removeAccount(account: account)
|
||||
self.mCore.clearAccounts()
|
||||
|
||||
Reference in New Issue
Block a user