Skip to content

Instantly share code, notes, and snippets.

@FabiolaRamirez
Created May 24, 2018 20:42
Show Gist options
  • Select an option

  • Save FabiolaRamirez/38f642fff9c17ef64cd5df3366b150ba to your computer and use it in GitHub Desktop.

Select an option

Save FabiolaRamirez/38f642fff9c17ef64cd5df3366b150ba to your computer and use it in GitHub Desktop.
//
// 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