Created
May 24, 2018 20:42
-
-
Save FabiolaRamirez/38f642fff9c17ef64cd5df3366b150ba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // LinphoneManager.swift | |
| // F3tch | |
| // | |
| // Created by Fabiola Ramirez on 5/18/18. | |
| // Copyright © 2018 F3tch. All rights reserved. | |
| // | |
| protocol CallStateDelegate { | |
| func callState(state: String) | |
| } | |
| var callStateDelegate: CallStateDelegate? | |
| import Foundation | |
| var answerCall: Bool = false | |
| struct theLinphone { | |
| static var lc: OpaquePointer? | |
| static var lct: LinphoneCoreVTable? | |
| static var manager: LinphoneManager? | |
| } | |
| let registrationStateChanged: LinphoneCoreRegistrationStateChangedCb = { | |
| (lc: Optional<OpaquePointer>, proxyConfig: Optional<OpaquePointer>, state: _LinphoneRegistrationState, message: Optional<UnsafePointer<Int8>>) in | |
| switch state{ | |
| case LinphoneRegistrationNone: /**<Initial state for registrations */ | |
| NSLog("____LinphoneRegistrationNone____") | |
| case LinphoneRegistrationProgress: | |
| NSLog("____LinphoneRegistrationProgress____") | |
| case LinphoneRegistrationOk: | |
| NSLog("____LinphoneRegistrationOk____") | |
| case LinphoneRegistrationCleared: | |
| NSLog("____LinphoneRegistrationCleared____") | |
| case LinphoneRegistrationFailed: | |
| NSLog("____LinphoneRegistrationFailed____") | |
| default: | |
| NSLog("____Unkown registration state____") | |
| } | |
| } as LinphoneCoreRegistrationStateChangedCb | |
| let callStateChanged: LinphoneCoreCallStateChangedCb = { | |
| (lc: Optional<OpaquePointer>, call: Optional<OpaquePointer>, callSate: LinphoneCallState, message: Optional<UnsafePointer<Int8>>) in | |
| print("ababbababa") | |
| switch callSate{ | |
| case LinphoneCallIncomingReceived: /**<This is a new incoming call */ | |
| NSLog("callStateChanged: LinphoneCallIncomingReceived") | |
| print("callSate: \(LinphoneCallIncomingReceived)") | |
| if answerCall{ | |
| ms_usleep(3 * 1000 * 1000); // Wait 3 seconds to pickup | |
| linphone_core_accept_call(lc, call) | |
| } | |
| case LinphoneCallStreamsRunning: /**<The media streams are established and running*/ | |
| NSLog("callStateChanged: LinphoneCallStreamsRunning") | |
| print("callSate: \(LinphoneCallError)") | |
| case LinphoneCallError: /**<The call encountered an error*/ | |
| NSLog("callStateChanged: LinphoneCallError") | |
| print("callSate: \(LinphoneCallError)") | |
| case LinphoneCallOutgoingProgress: | |
| NSLog("callStateChanged: LinphoneCallOutgoingProgress") | |
| print("callSate: \(LinphoneCallOutgoingProgress)") | |
| callStateDelegate?.callState(state: "xxxxx") | |
| case LinphoneCallEnd: | |
| NSLog("callStateChanged: LinphoneCallEnd") | |
| print("callSate: \(LinphoneCallEnd)") | |
| callStateDelegate?.callState(state: "xxxxx") | |
| case LinphoneCallOutgoingRinging: | |
| NSLog("callStateChanged: LinphoneCallOutgoingRinging") | |
| print("callSate: \(LinphoneCallOutgoingRinging)") | |
| case LinphoneCallConnected: | |
| NSLog("callStateChanged: LinphoneCallConnected") | |
| print("callSate: \(LinphoneCallConnected)") | |
| case LinphoneCallPausing: | |
| NSLog("callStateChanged: LinphoneCallPausing") | |
| print("callSate: \(LinphoneCallPausing)") | |
| case LinphoneCallPaused: | |
| NSLog("callStateChanged: LinphoneCallPaused") | |
| print("callSate: \(LinphoneCallPaused)") | |
| case LinphoneCallReleased: | |
| NSLog("callStateChanged: LinphoneCallReleased") | |
| print("callSate: \(LinphoneCallReleased)") | |
| default: | |
| NSLog("Default call state") | |
| print("callSate: \(callSate)") | |
| } | |
| } | |
| class LinphoneManager { | |
| static var iterateTimer: Timer? | |
| let hotel = Hotel.current() | |
| init() { | |
| print("init") | |
| theLinphone.lct = LinphoneCoreVTable() | |
| // Enable debug log to stdout | |
| linphone_core_set_log_file(nil) | |
| linphone_core_set_log_level(ORTP_DEBUG) | |
| // Load config | |
| let configFilename = documentFile("linphonerc222") | |
| let factoryConfigFilename = bundleFile("linphonerc-factory") | |
| let configFilenamePtr: UnsafePointer<Int8> = configFilename.cString(using: String.Encoding.utf8.rawValue)! | |
| let factoryConfigFilenamePtr: UnsafePointer<Int8> = factoryConfigFilename.cString(using: String.Encoding.utf8.rawValue)! | |
| let lpConfig = lp_config_new_with_factory(configFilenamePtr, factoryConfigFilenamePtr) | |
| // Set Callback | |
| theLinphone.lct?.registration_state_changed = registrationStateChanged | |
| theLinphone.lct?.call_state_changed = callStateChanged | |
| theLinphone.lc = linphone_core_new_with_config(&theLinphone.lct!, lpConfig, nil) | |
| //let jhhku = Bundle.main.path(forResource: "ringback", ofType: "wav") | |
| // Set ring asset | |
| let ringbackPath = URL(fileURLWithPath: Bundle.main.bundlePath).appendingPathComponent("ringback.wav").absoluteString | |
| linphone_core_set_ringback(theLinphone.lc, ringbackPath) | |
| let localRing = URL(fileURLWithPath: Bundle.main.bundlePath).appendingPathComponent("/toy-mono.wav").absoluteString | |
| linphone_core_set_ring(theLinphone.lc, localRing) | |
| } | |
| fileprivate func bundleFile(_ file: NSString) -> NSString{ | |
| print("bundleFile") | |
| return Bundle.main.path(forResource: file.deletingPathExtension, ofType: file.pathExtension)! as NSString | |
| } | |
| fileprivate func documentFile(_ file: NSString) -> NSString { | |
| print("documentFile") | |
| let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) | |
| let documentsPath: NSString = paths[0] as NSString | |
| return documentsPath.appendingPathComponent(file as String) as NSString | |
| } | |
| // | |
| // This is the start point to know how linphone library works. | |
| // | |
| func call(phoneNumber: String) { | |
| print("call") | |
| makeCall(phoneNumber: phoneNumber) | |
| //autoPickImcomingCall() | |
| idle() | |
| } | |
| func makeCall(phoneNumber: String){ | |
| print("makeCall") | |
| guard let _ = setIdentify() else { | |
| print("no identity") | |
| return; | |
| } | |
| linphone_core_invite(theLinphone.lc, phoneNumber) | |
| setTimer() | |
| // shutdown() | |
| } | |
| func receiveCall(){ | |
| print("receiveCall") | |
| guard let proxyConfig = setIdentify() else { | |
| print("no identity") | |
| return; | |
| } | |
| register(proxyConfig) | |
| setTimer() | |
| // shutdown() | |
| } | |
| func idle(){ | |
| print("idle") | |
| guard let proxyConfig = setIdentify() else { | |
| print("no identity") | |
| return; | |
| } | |
| register(proxyConfig) | |
| setTimer() | |
| // shutdown() | |
| } | |
| func setIdentify() -> OpaquePointer? { | |
| print("setIdentify") | |
| // Reference: http://www.linphone.org/docs/liblinphone/group__registration__tutorials.html | |
| let path = Bundle.main.path(forResource: "Secret", ofType: "plist") | |
| let dict = NSDictionary(contentsOfFile: path!) | |
| let account = dict?.object(forKey: "account") as! String | |
| let password = dict?.object(forKey: "password") as! String | |
| let domain = dict?.object(forKey: "domain") as! String | |
| //let account = hotel.room.extensionNumber | |
| //let password = hotel.password | |
| //let domain = hotel.hostname | |
| let identity = "sip:" + account + "@" + domain; | |
| /*create proxy config*/ | |
| let proxy_cfg = linphone_proxy_config_new(); | |
| /*parse identity*/ | |
| let from = linphone_address_new(identity); | |
| if (from == nil){ | |
| NSLog("\(identity) not a valid sip uri, must be like sip:toto@sip.linphone.org"); | |
| return nil | |
| } | |
| let info=linphone_auth_info_new(linphone_address_get_username(from), nil, password, nil, nil, nil); /*create authentication structure from identity*/ | |
| linphone_core_add_auth_info(theLinphone.lc, info); /*add authentication info to LinphoneCore*/ | |
| // configure proxy entries | |
| linphone_proxy_config_set_identity(proxy_cfg, identity); /*set identity with user name and domain*/ | |
| let server_addr = String(cString: linphone_address_get_domain(from)); /*extract domain address from identity*/ | |
| linphone_address_destroy(from); /*release resource*/ | |
| linphone_proxy_config_set_server_addr(proxy_cfg, server_addr); /* we assume domain = proxy server address*/ | |
| linphone_proxy_config_enable_register(proxy_cfg, 0); /* activate registration for this proxy config*/ | |
| linphone_core_add_proxy_config(theLinphone.lc, proxy_cfg); /*add proxy config to linphone core*/ | |
| linphone_core_set_default_proxy_config(theLinphone.lc, proxy_cfg); /*set to default proxy*/ | |
| return proxy_cfg! | |
| } | |
| func register(_ proxy_cfg: OpaquePointer){ | |
| print("register") | |
| linphone_proxy_config_enable_register(proxy_cfg, 1); /* activate registration for this proxy config*/ | |
| } | |
| func shutdown(){ | |
| print("shutdown") | |
| print("0") | |
| let proxy_cfg = linphone_core_get_default_proxy_config(theLinphone.lc); /* get default proxy config*/ | |
| print("1") | |
| linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/ | |
| print("2") | |
| linphone_proxy_config_enable_register(proxy_cfg, 0); /*de-activate registration for this proxy config*/ | |
| print("3") | |
| linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/ | |
| print("4") | |
| while(linphone_proxy_config_get_state(proxy_cfg) != LinphoneRegistrationCleared){ | |
| print("5") | |
| linphone_core_iterate(theLinphone.lc); /*to make sure we receive call backs before shutting down*/ | |
| ms_usleep(50000); | |
| } | |
| print("6") | |
| linphone_core_destroy(theLinphone.lc); | |
| } | |
| func hungUpCall() { | |
| print("hungUpCall") | |
| let call = linphone_core_get_current_call(theLinphone.lc) | |
| if let c = call { | |
| linphone_core_terminate_call(theLinphone.lc, c) | |
| } | |
| } | |
| @objc func iterate(){ | |
| print("iterate") | |
| if let lc = theLinphone.lc { | |
| linphone_core_iterate(lc); /* first iterate initiates registration */ | |
| } | |
| } | |
| fileprivate func setTimer(){ | |
| print("setTimer") | |
| LinphoneManager.iterateTimer = Timer.scheduledTimer( | |
| timeInterval: 0.02, target: self, selector: #selector(iterate), userInfo: nil, repeats: true) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment