From 4830d3816700d5c30b976d88c03651c8d0b6dcf8 Mon Sep 17 00:00:00 2001 From: QuentinArguillere Date: Tue, 4 Aug 2020 17:54:59 +0200 Subject: [PATCH] Added registration code for incoming calls, add incoming call actions to the UI --- .../CallTutorial.xcodeproj/project.pbxproj | 2 +- .../CallTutorial/CallExample.swift | 150 +++++++----------- .../CallTutorial/ContentView.swift | 78 +++++++-- 3 files changed, 126 insertions(+), 104 deletions(-) diff --git a/swift/CallTutorial/CallTutorial.xcodeproj/project.pbxproj b/swift/CallTutorial/CallTutorial.xcodeproj/project.pbxproj index ebb5e65..c858a80 100644 --- a/swift/CallTutorial/CallTutorial.xcodeproj/project.pbxproj +++ b/swift/CallTutorial/CallTutorial.xcodeproj/project.pbxproj @@ -84,11 +84,11 @@ children = ( 6604165624D451F10064FC6C /* AppDelegate.swift */, 6604165824D451F10064FC6C /* SceneDelegate.swift */, + 6604166A24D453240064FC6C /* CallExample.swift */, 6604165A24D451F10064FC6C /* ContentView.swift */, 6604165C24D451F40064FC6C /* Assets.xcassets */, 6604166124D451F40064FC6C /* LaunchScreen.storyboard */, 6604166424D451F40064FC6C /* Info.plist */, - 6604166A24D453240064FC6C /* CallExample.swift */, 6604165E24D451F40064FC6C /* Preview Content */, ); path = CallTutorial; diff --git a/swift/CallTutorial/CallTutorial/CallExample.swift b/swift/CallTutorial/CallTutorial/CallExample.swift index c220b05..3fd9380 100644 --- a/swift/CallTutorial/CallTutorial/CallExample.swift +++ b/swift/CallTutorial/CallTutorial/CallExample.swift @@ -29,18 +29,18 @@ class CallExampleContext : ObservableObject @Published var videoEnabled : Bool = false @Published var speakerEnabled : Bool = false @Published var callRunning : Bool = false + @Published var isCallIncoming : Bool = false @Published var dest : String = "sip:arguillq@sip.linphone.org" - - var proxy_cfg: ProxyConfig! + let mRegistrationDelegate = LinphoneRegistrationDelegate() @Published var id : String = "sip:peche5@sip.linphone.org" @Published var passwd : String = "peche5" @Published var loggedIn: Bool = false - init() { mCallStateTracer.tutorialContext = self + mRegistrationDelegate.tutorialContext = self let factory = Factory.Instance // Instanciate @@ -59,9 +59,35 @@ class CallExampleContext : ObservableObject try? mCore.start() mVideoDevices = mCore.videoDevicesList - - registrationExample() + mCore.addDelegate(delegate: mCallStateTracer) + mCore.addDelegate(delegate: mRegistrationDelegate) + } + + func registrationExample() + { + + let factory = Factory.Instance + do { + let proxy_cfg = try mCore.createProxyConfig() + let address = try factory.createAddress(addr: id) + let info = try factory.createAuthInfo(username: address.username, userid: "", passwd: passwd, ha1: "", realm: "", domain: address.domain) + mCore.addAuthInfo(info: info) + + try proxy_cfg.setIdentityaddress(newValue: address) + let server_addr = "sip:" + address.domain + ";transport=tls" + try proxy_cfg.setServeraddr(newValue: server_addr) + proxy_cfg.registerEnabled = true + try mCore.addProxyConfig(config: proxy_cfg) + if ( mCore.defaultProxyConfig == nil) + { + // IMPORTANT : default proxy config setting MUST be done AFTER adding the config to the core ! + mCore.defaultProxyConfig = proxy_cfg + } + + } catch { + print(error) + } } // Initiate a call @@ -82,7 +108,6 @@ class CallExampleContext : ObservableObject print("Could not place call to \(dest)\n") } else { print("Call to \(dest) is in progress...") - callRunning = true } } else @@ -96,18 +121,16 @@ class CallExampleContext : ObservableObject } // Terminate a call - func stopOutgoingCallExample() + func stopCall() { if (callRunning) { - callRunning = false if (mCall.state != Call.State.End){ // terminate the call print("Terminating the call...\n") do { try mCall.terminate() } catch { - callRunning = true print(error) } } @@ -138,67 +161,13 @@ class CallExampleContext : ObservableObject } } - /* - func acceptCall(incomingCall call : Call) - { - mCall = call - do { - try call.accept() - } catch { - print(error) - } - } - */ - func createProxyConfigAndRegister(identity sId : String, password sPwd : String, factoryUri fUri : String) -> ProxyConfig? + func acceptCall() { - let factory = Factory.Instance do { - let proxy_cfg = try mCore.createProxyConfig() - let address = try factory.createAddress(addr: sId) - let info = try factory.createAuthInfo(username: address.username, userid: "", passwd: sPwd, ha1: "", realm: "", domain: address.domain) - mCore.addAuthInfo(info: info) - - try proxy_cfg.setIdentityaddress(newValue: address) - let server_addr = "sip:" + address.domain + ";transport=tls" - try proxy_cfg.setServeraddr(newValue: server_addr) - proxy_cfg.registerEnabled = true - proxy_cfg.conferenceFactoryUri = fUri - try mCore.addProxyConfig(config: proxy_cfg) - if ( mCore.defaultProxyConfig == nil) - { - // IMPORTANT : default proxy config setting MUST be done AFTER adding the config to the core ! - mCore.defaultProxyConfig = proxy_cfg - } - return proxy_cfg - - } catch { - print(error) - } - return nil - } - - func registrationExample() - { - let factory = Factory.Instance - do { - let proxy_cfg = try mCore.createProxyConfig() - let address = try factory.createAddress(addr: id) - let info = try factory.createAuthInfo(username: address.username, userid: "", passwd: passwd, ha1: "", realm: "", domain: address.domain) - mCore.addAuthInfo(info: info) - - try proxy_cfg.setIdentityaddress(newValue: address) - let server_addr = "sip:" + address.domain + ";transport=tls" - try proxy_cfg.setServeraddr(newValue: server_addr) - proxy_cfg.registerEnabled = true - try mCore.addProxyConfig(config: proxy_cfg) - if ( mCore.defaultProxyConfig == nil) - { - // IMPORTANT : default proxy config setting MUST be done AFTER adding the config to the core ! - mCore.defaultProxyConfig = proxy_cfg - } - loggedIn = true - + try mCall.accept() + callRunning = true + isCallIncoming = false } catch { print(error) } @@ -206,7 +175,18 @@ class CallExampleContext : ObservableObject } - +class LinphoneRegistrationDelegate: CoreDelegate { + + var tutorialContext : CallExampleContext! + + override func onRegistrationStateChanged(lc: Core, cfg: ProxyConfig, cstate: RegistrationState, message: String?) { + print("New registration state \(cstate) for user id \( String(describing: cfg.identityAddress?.asString()))\n") + if (cstate == .Ok) + { + tutorialContext.loggedIn = true + } + } +} class LinphoneLoggingServiceManager: LoggingServiceDelegate { @@ -221,38 +201,20 @@ class LinphoneLoggingServiceManager: LoggingServiceDelegate { } } - + let mCallStateTracer = CallStateDelegate() class CallStateDelegate: CoreDelegate { var tutorialContext : CallExampleContext! override func onCallStateChanged(lc: Core, call: Call, cstate: Call.State, message: String) { print("CallTrace - \(cstate)") - /* - let traceFn = { print("CallTrace - \(cstate)") } - switch cstate - { - case .IncomingReceived: - tutorialContext.acceptCall(incomingCall: call) - case .IncomingEarlyMedia: - traceFn() - case .PushIncomingReceived: - traceFn() - case .OutgoingRinging: - print("CallTrace - It is now ringing remotely !\n") - case .OutgoingEarlyMedia: - print("CallTrace - Receiving some early media\n") - case .Connected: - print("CallTrace - We are connected !\n") - case .StreamsRunning: - print("CallTrace - Media streams established !\n") - case .End: - print("CallTrace - Call is terminated.\n") - case .Error: - print("CallTrace - Call failure !") - default: - print("CallTrace - Unhandled notification \(cstate)\n") + if (cstate == .IncomingReceived) { + tutorialContext.mCall = call + tutorialContext.isCallIncoming = true + } else if (cstate == .OutgoingRinging) { + tutorialContext.callRunning = true + } else if (cstate == .End) { + tutorialContext.callRunning = false } - */ } } diff --git a/swift/CallTutorial/CallTutorial/ContentView.swift b/swift/CallTutorial/CallTutorial/ContentView.swift index 0871711..d3c49b1 100644 --- a/swift/CallTutorial/CallTutorial/ContentView.swift +++ b/swift/CallTutorial/CallTutorial/ContentView.swift @@ -12,18 +12,73 @@ struct ContentView: View { @ObservedObject var tutorialContext = CallExampleContext() + func getCallButtonText() -> String + { + if (tutorialContext.isCallIncoming) { + return "Answer" + } + else if (tutorialContext.callRunning) { + return "Update Call" + } + else { + return "Call" + } + } + + func callStateString() -> String + { + if (tutorialContext.isCallIncoming) { + return "Incoming call" + } + else if (tutorialContext.callRunning) { + return "Call running" + } + else { + return "No Call" + } + } + var body: some View { - VStack(alignment: .leading) { + Group { + HStack { + Text("Identity :") + .font(.subheadline) + TextField("", text : $tutorialContext.id) + .textFieldStyle(RoundedBorderTextFieldStyle()) + } + HStack { + Text("Password :") + .font(.subheadline) + TextField("", text : $tutorialContext.passwd) + .textFieldStyle(RoundedBorderTextFieldStyle()) + } + HStack { + Button(action: tutorialContext.registrationExample) + { + Text("Login") + .font(.largeTitle) + .foregroundColor(Color.white) + .frame(width: 90.0, height: 42.0) + .background(Color.gray) + } + Text("Login State : ") + .font(.footnote) + Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered") + .font(.footnote) + .foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black) + } + } VStack(spacing: 0.0) { Text("Call Settings") .font(.largeTitle) + .padding(.top, 5) HStack { Text("Call destination :") TextField("", text : $tutorialContext.dest) .textFieldStyle(RoundedBorderTextFieldStyle()) } - .padding(.top) + .padding(.top, 5) } VStack(alignment: .leading) { Toggle(isOn: $tutorialContext.audioEnabled) { @@ -56,15 +111,22 @@ struct ContentView: View { Spacer() VStack { HStack { - Button(action: tutorialContext.outgoingCallExample) + Button(action: { + if (self.tutorialContext.isCallIncoming) { + self.tutorialContext.acceptCall() + } + else { + self.tutorialContext.outgoingCallExample() + } + }) { - Text(tutorialContext.callRunning ? "Update Call" : "Call") + Text(getCallButtonText()) .font(.largeTitle) .foregroundColor(Color.white) .frame(width: 180.0, height: 42.0) .background(Color.green) } - Button(action: tutorialContext.stopOutgoingCallExample) { + Button(action: tutorialContext.stopCall) { Text("Stop Call") .font(.largeTitle) .foregroundColor(Color.white) @@ -73,11 +135,9 @@ struct ContentView: View { } } HStack { - Text("Call State : ") + Text(callStateString()) .font(.footnote) - Text(tutorialContext.callRunning ? "Ongoing" : "Stopped") - .font(.footnote) - .foregroundColor(tutorialContext.callRunning ? Color.green : Color.black) + .foregroundColor(tutorialContext.callRunning || tutorialContext.isCallIncoming ? Color.green : Color.black) } .padding(.top) }