Suggestions from CD for Async Call backs and Core objects associated with publishers
This commit is contained in:
parent
59d7747e86
commit
8ee3e46dbc
@ -16,6 +16,7 @@
|
|||||||
6608A97224E197D5006E6C68 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */; };
|
6608A97224E197D5006E6C68 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */; };
|
||||||
6608A97A24E19817006E6C68 /* CallKitTutorial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97924E19817006E6C68 /* CallKitTutorial.swift */; };
|
6608A97A24E19817006E6C68 /* CallKitTutorial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97924E19817006E6C68 /* CallKitTutorial.swift */; };
|
||||||
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */; };
|
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */; };
|
||||||
|
C6FFD82E2AB199FA00DB168D /* LinphoneAsyncHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FFD82D2AB199FA00DB168D /* LinphoneAsyncHelper.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@ -32,6 +33,7 @@
|
|||||||
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CallKitTutorial.entitlements; sourceTree = "<group>"; };
|
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CallKitTutorial.entitlements; sourceTree = "<group>"; };
|
||||||
9D767CD0AA573757AD042365 /* Pods-CallKitTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.release.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.release.xcconfig"; sourceTree = "<group>"; };
|
9D767CD0AA573757AD042365 /* Pods-CallKitTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.release.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
C6E14A45B7F8F19111223509 /* Pods_CallKitTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallKitTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
C6E14A45B7F8F19111223509 /* Pods_CallKitTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallKitTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
C6FFD82D2AB199FA00DB168D /* LinphoneAsyncHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinphoneAsyncHelper.swift; sourceTree = "<group>"; };
|
||||||
D7FA91A3C73CAEE3300CB14C /* Pods-CallKitTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.debug.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.debug.xcconfig"; sourceTree = "<group>"; };
|
D7FA91A3C73CAEE3300CB14C /* Pods-CallKitTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.debug.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@ -78,6 +80,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */,
|
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */,
|
||||||
|
C6FFD82D2AB199FA00DB168D /* LinphoneAsyncHelper.swift */,
|
||||||
6608A96524E197D5006E6C68 /* AppDelegate.swift */,
|
6608A96524E197D5006E6C68 /* AppDelegate.swift */,
|
||||||
6608A96724E197D5006E6C68 /* SceneDelegate.swift */,
|
6608A96724E197D5006E6C68 /* SceneDelegate.swift */,
|
||||||
6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */,
|
6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */,
|
||||||
@ -225,6 +228,7 @@
|
|||||||
6608A97A24E19817006E6C68 /* CallKitTutorial.swift in Sources */,
|
6608A97A24E19817006E6C68 /* CallKitTutorial.swift in Sources */,
|
||||||
6608A96624E197D5006E6C68 /* AppDelegate.swift in Sources */,
|
6608A96624E197D5006E6C68 /* AppDelegate.swift in Sources */,
|
||||||
6608A96824E197D5006E6C68 /* SceneDelegate.swift in Sources */,
|
6608A96824E197D5006E6C68 /* SceneDelegate.swift in Sources */,
|
||||||
|
C6FFD82E2AB199FA00DB168D /* LinphoneAsyncHelper.swift in Sources */,
|
||||||
6608A96A24E197D5006E6C68 /* ContentView.swift in Sources */,
|
6608A96A24E197D5006E6C68 /* ContentView.swift in Sources */,
|
||||||
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */,
|
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
@ -109,14 +109,14 @@ extension CallKitProviderDelegate: CXProviderDelegate {
|
|||||||
NSLog("Callkit didActivateaudiosession -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ")
|
NSLog("Callkit didActivateaudiosession -- Is main thread ? \(Thread.isMainThread ? "yes" : "no") ")
|
||||||
// The linphone Core must be notified that CallKit has activated the AVAudioSession
|
// The linphone Core must be notified that CallKit has activated the AVAudioSession
|
||||||
// in order to start streaming audio.
|
// in order to start streaming audio.
|
||||||
tutorialContext.postOnCoreQueue {
|
tutorialContext.linphoneAsyncHelper.postOnCoreQueue {
|
||||||
self.tutorialContext.mCore.activateAudioSession(actived: true)
|
self.tutorialContext.mCore.activateAudioSession(actived: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
||||||
// The linphone Core must be notified that CallKit has deactivated the AVAudioSession.
|
// The linphone Core must be notified that CallKit has deactivated the AVAudioSession.
|
||||||
tutorialContext.postOnCoreQueue {
|
tutorialContext.linphoneAsyncHelper.postOnCoreQueue {
|
||||||
self.tutorialContext.mCore.activateAudioSession(actived: false)
|
self.tutorialContext.mCore.activateAudioSession(actived: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,13 @@
|
|||||||
|
|
||||||
import linphonesw
|
import linphonesw
|
||||||
import AVFoundation
|
import AVFoundation
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
|
||||||
class CallKitExampleContext : ObservableObject
|
class CallKitExampleContext : ObservableObject
|
||||||
{
|
{
|
||||||
private let queue = DispatchQueue(label:"core.queue")
|
|
||||||
var mCore: Core!
|
var mCore: Core!
|
||||||
var mAccount: Account?
|
var mAccount: Account?
|
||||||
var mCoreDelegate : CoreDelegate!
|
|
||||||
var mIterateTimer : Timer!
|
var mIterateTimer : Timer!
|
||||||
|
|
||||||
@Published var coreVersion: String = Core.getVersion
|
@Published var coreVersion: String = Core.getVersion
|
||||||
@ -32,63 +30,60 @@ class CallKitExampleContext : ObservableObject
|
|||||||
@Published var isSpeakerEnabled : Bool = false
|
@Published var isSpeakerEnabled : Bool = false
|
||||||
@Published var isMicrophoneEnabled : Bool = false
|
@Published var isMicrophoneEnabled : Bool = false
|
||||||
|
|
||||||
|
/* Async */
|
||||||
|
let linphoneAsyncHelper = LinphoneAsyncHelper()
|
||||||
|
|
||||||
|
|
||||||
/*------------ Callkit tutorial related variables ---------------*/
|
/*------------ Callkit tutorial related variables ---------------*/
|
||||||
let incomingCallName = "Incoming call example"
|
let incomingCallName = "Incoming call example"
|
||||||
var mCall : Call?
|
var mCall : Call?
|
||||||
var mProviderDelegate : CallKitProviderDelegate!
|
var mProviderDelegate : CallKitProviderDelegate!
|
||||||
var mCallAlreadyStopped : Bool = false;
|
var mCallAlreadyStopped : Bool = false;
|
||||||
|
|
||||||
func postOnCoreQueue(lambda : @escaping ()->()) {
|
|
||||||
queue.async {
|
func addRegistrationStateCallBack(core:Core) {
|
||||||
lambda()
|
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init()
|
func addCallStateChangedCallBack(core:Core) {
|
||||||
{
|
core.createOnCallStateChangedPublisher()
|
||||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
.postOnMainQueue { result in
|
||||||
|
self.callMsg = result.message
|
||||||
let factory = Factory.Instance
|
if (result.state == .PushIncomingReceived){
|
||||||
// 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)
|
// We're being called by someone (and app is in background)
|
||||||
self.mCall = call
|
self.mCall = result.call
|
||||||
self.mProviderDelegate.incomingCall()
|
self.mProviderDelegate.incomingCall()
|
||||||
self.isCallIncoming = true
|
self.isCallIncoming = true
|
||||||
self.callMsg = message
|
self.callMsg = result.message
|
||||||
} else if (state == .IncomingReceived) {
|
} 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 app is in foreground, it's likely that we will receive the SIP invite before the Push notification
|
||||||
if (!self.isCallIncoming) {
|
if (!self.isCallIncoming) {
|
||||||
self.mCall = call
|
self.mCall = result.call
|
||||||
self.mProviderDelegate.incomingCall()
|
self.mProviderDelegate.incomingCall()
|
||||||
|
|
||||||
self.isCallIncoming = true
|
self.isCallIncoming = true
|
||||||
self.callMsg = message
|
self.callMsg = result.message
|
||||||
}
|
}
|
||||||
self.remoteAddress = call.remoteAddress!.asStringUriOnly()
|
self.remoteAddress = result.call.remoteAddress!.asStringUriOnly()
|
||||||
} else if (state == .Connected) {
|
} else if (result.state == .Connected) {
|
||||||
self.isCallIncoming = false
|
self.isCallIncoming = false
|
||||||
self.isCallRunning = true
|
self.isCallRunning = true
|
||||||
} else if (state == .Released || state == .End || state == .Error) {
|
} else if (result.state == .Released || result.state == .End || result.state == .Error) {
|
||||||
// Call has been terminated by any side
|
// 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
|
// Report to CallKit that the call is over, if the terminate action was initiated by other end of the call
|
||||||
@ -97,36 +92,60 @@ class CallKitExampleContext : ObservableObject
|
|||||||
}
|
}
|
||||||
self.remoteAddress = "Nobody yet"
|
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
|
|
||||||
}
|
}
|
||||||
})
|
.postOnCoreQueue{ result in
|
||||||
|
// optional something on core queue if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mIterateTimer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { [weak self] timer in
|
init()
|
||||||
self?.postOnCoreQueue {
|
{
|
||||||
self?.mCore.iterate()
|
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
mProviderDelegate = CallKitProviderDelegate(context: self)
|
mProviderDelegate = CallKitProviderDelegate(context: self)
|
||||||
mCore.addDelegate(delegate: mCoreDelegate)
|
|
||||||
|
|
||||||
postOnCoreQueue {
|
|
||||||
try? self.mCore.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func login() {
|
func login() {
|
||||||
|
|
||||||
postOnCoreQueue {
|
linphoneAsyncHelper.postOnCoreQueue {
|
||||||
do {
|
do {
|
||||||
var transport : TransportType
|
var transport : TransportType
|
||||||
if (self.transportType == "TLS") { transport = TransportType.Tls }
|
if (self.transportType == "TLS") { transport = TransportType.Tls }
|
||||||
@ -156,7 +175,7 @@ class CallKitExampleContext : ObservableObject
|
|||||||
|
|
||||||
func unregister()
|
func unregister()
|
||||||
{
|
{
|
||||||
postOnCoreQueue {
|
linphoneAsyncHelper.postOnCoreQueue {
|
||||||
if let account = self.mCore.defaultAccount {
|
if let account = self.mCore.defaultAccount {
|
||||||
let params = account.params
|
let params = account.params
|
||||||
let clonedParams = params?.clone()
|
let clonedParams = params?.clone()
|
||||||
@ -166,7 +185,7 @@ class CallKitExampleContext : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func delete() {
|
func delete() {
|
||||||
postOnCoreQueue {
|
linphoneAsyncHelper.postOnCoreQueue {
|
||||||
if let account = self.mCore.defaultAccount {
|
if let account = self.mCore.defaultAccount {
|
||||||
self.mCore.removeAccount(account: account)
|
self.mCore.removeAccount(account: account)
|
||||||
self.mCore.clearAccounts()
|
self.mCore.clearAccounts()
|
||||||
|
@ -0,0 +1,121 @@
|
|||||||
|
//
|
||||||
|
// LinphoneAsyncWrapper.swift
|
||||||
|
// CallKitTutorial
|
||||||
|
//
|
||||||
|
// Created by CD on 13/09/2023.
|
||||||
|
// Copyright © 2023 BelledonneCommunications. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
import linphonesw
|
||||||
|
|
||||||
|
var coreQueue : DispatchQueue = DispatchQueue(label:"core.queue")
|
||||||
|
var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
// A publisher object that can old one or many LinphoneObject objects.
|
||||||
|
|
||||||
|
public class LinphoneObjectsPublisher <T> : Publisher {
|
||||||
|
public typealias Output = T
|
||||||
|
public typealias Failure = Error
|
||||||
|
let passThroughSubject = PassthroughSubject<Output, Failure>()
|
||||||
|
public func receive<S>(subscriber: S) where S : Subscriber, S.Failure == Failure, S.Input == Output {
|
||||||
|
passThroughSubject.receive(subscriber: subscriber)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func send(completion: Subscribers.Completion<Failure>) {
|
||||||
|
passThroughSubject.send(completion: completion)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public func postOnMainQueue(onError :@escaping ((Error) -> Void) = {_ in }, receiveValue:@escaping ((Output) -> Void)) -> LinphoneObjectsPublisher <T>{
|
||||||
|
doOnQueue(onError,receiveValue,queue: DispatchQueue.main)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public func postOnCoreQueue(onError :@escaping ((Error) -> Void) = {_ in }, receiveValue:@escaping ((Output) -> Void)) -> LinphoneObjectsPublisher <T>{
|
||||||
|
doOnQueue(onError,receiveValue,queue: coreQueue)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func doOnQueue(_ onError :@escaping ((Error) -> Void) = {_ in }, _ receiveValue:@escaping ((Output) -> Void), queue:DispatchQueue) {
|
||||||
|
passThroughSubject.receive(on:queue)
|
||||||
|
.sink { error in
|
||||||
|
onError(error as! Error)
|
||||||
|
} receiveValue: { result in
|
||||||
|
receiveValue(result)
|
||||||
|
}.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedReference : Any? = nil // Used when a reference is needed to avoid object from beeing GCd (example delegate stubs)
|
||||||
|
convenience init (reference: Any) {
|
||||||
|
self.init()
|
||||||
|
savedReference = reference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LinphoneAsyncHelper {
|
||||||
|
|
||||||
|
func postOnCoreQueue(lambda : @escaping ()->()) {
|
||||||
|
coreQueue.async {
|
||||||
|
lambda()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func postOnMainQueue(lambda : @escaping()->()) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
lambda()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a publisher from the object created by the action passed as parameter
|
||||||
|
// For example if passed a create core call this function will create the LinphoneObject Core on core queue, and created object will be published through the built publisher
|
||||||
|
func createLinphoneObjectWithPublisher<LinphoneObject>(createAction:@escaping()throws -> LinphoneObject ) -> LinphoneObjectsPublisher<LinphoneObject> {
|
||||||
|
let publisher = LinphoneObjectsPublisher<LinphoneObject>()
|
||||||
|
coreQueue.async {
|
||||||
|
do {
|
||||||
|
publisher.passThroughSubject.send(try createAction())
|
||||||
|
} catch {
|
||||||
|
publisher.send(completion: .failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return publisher
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Core {
|
||||||
|
|
||||||
|
// Methods below would generated by a script similar to the one that creates LinphoneWrapper
|
||||||
|
|
||||||
|
public func createAccountRegistrationStateChangedPublisher() -> LinphoneObjectsPublisher<(core:Core, account:Account, state:RegistrationState, message:String)> {
|
||||||
|
let publisher = LinphoneObjectsPublisher<(core:Core, account:Account, state:RegistrationState, message:String)>()
|
||||||
|
let coreDelegate = CoreDelegateStub (
|
||||||
|
onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
|
||||||
|
publisher.passThroughSubject.send((core,account,state,message))
|
||||||
|
})
|
||||||
|
publisher.savedReference = coreDelegate
|
||||||
|
addDelegate(delegate: coreDelegate)
|
||||||
|
return publisher
|
||||||
|
}
|
||||||
|
|
||||||
|
public func createOnCallStateChangedPublisher() -> LinphoneObjectsPublisher<(core: Core, call: Call, state: Call.State, message: String)> {
|
||||||
|
let publisher = LinphoneObjectsPublisher<(core: Core, call: Call, state: Call.State, message: String)>()
|
||||||
|
let coreDelegate = CoreDelegateStub (
|
||||||
|
onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||||
|
publisher.passThroughSubject.send((core,call,state,message))
|
||||||
|
})
|
||||||
|
publisher.savedReference = coreDelegate
|
||||||
|
addDelegate(delegate: coreDelegate)
|
||||||
|
return publisher
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user