JLChen
2021-08-02 38f4fb064df09f344fc3237409c76a9fba2a8a9e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//
//  CallManagerDelegate.swift
//  VoipTest
//
//  Created by StevStark on 2020/11/11.
//
 
import Foundation
import linphonesw
import CallKit
import AVFoundation
 
 
class CoreManagerDelegate: CoreDelegate {
    
    static var speaker_already_enabled : Bool = false
 
    override func onCallStateChanged(lc: Core, call: Call, cstate: Call.State, message: String) {
        let addr = call.remoteAddress;
        let address = "Unknow"
        let callLog = call.callLog
        let callId = callLog?.callId
        let video = UIApplication.shared.applicationState == .active && (lc.videoActivationPolicy?.automaticallyAccept ?? false) && (call.remoteParams?.videoEnabled ?? false)
        // we keep the speaker auto-enabled state in this static so that we don't
        // force-enable it on ICE re-invite if the user disabled it.
        CoreManagerDelegate.speaker_already_enabled = false
 
        if (call.userData == nil) {
            let appData = CallAppData()
            CallManager.setAppData(sCall: call, appData: appData)
        }
 
 
        switch cstate {
            case .IncomingReceived:
                if (CallManager.callKitEnabled()) {
                    let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
                    if (uuid != nil) {
                        // Tha app is now registered, updated the call already existed.
                        CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: address, hasVideo: video)
                        let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
                        if (callInfo?.declined ?? false) {
                            // The call is already declined.
                            try? call.decline(reason: Reason.Unknown)
                        } else if (callInfo?.accepted ?? false) {
                            // The call is already answered.
                            CallManager.instance().acceptCall(call: call, hasVideo: video)
                        }
                    } else {
                        CallManager.instance().displayIncomingCall(call: call, handle: address, hasVideo: video, callId: callId!)
                    }
                }
                break
            case .StreamsRunning:
                if (CallManager.callKitEnabled()) {
                    let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
                    if (uuid != nil) {
                        let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
                        if (callInfo != nil && callInfo!.isOutgoing && !callInfo!.connected) {
                           
                            CallManager.instance().providerDelegate.reportOutgoingCallConnected(uuid: uuid!)
                            callInfo!.connected = true
                            CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
                        }
                    }
                }
 
                if (CallManager.instance().speakerBeforePause) {
                    CallManager.instance().speakerBeforePause = false
                    CallManager.instance().enableSpeaker(enable: true)
                    CoreManagerDelegate.speaker_already_enabled = true
                }
                break
            case .OutgoingRinging:
                if (CallManager.callKitEnabled()) {
                    let uuid = CallManager.instance().providerDelegate.uuids[""]
                    if (uuid != nil) {
                        let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
                        callInfo!.callId = callId!
                        CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
                        CallManager.instance().providerDelegate.uuids.removeValue(forKey: "")
                        CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callId!)
 
                        CallManager.instance().providerDelegate.reportOutgoingCallStartedConnecting(uuid: uuid!)
                    } else {
                        CallManager.instance().referedToCall = callId
                    }
                }
                break
            case .End,
                 .Error:
                UIDevice.current.isProximityMonitoringEnabled = false
                CoreManagerDelegate.speaker_already_enabled = false
                if (CallManager.instance().lc!.callsNb == 0) {
                    CallManager.instance().enableSpeaker(enable: false)
                    // disable this because I don't find anygood reason for it: _bluetoothAvailable = FALSE;
                    // furthermore it introduces a bug when calling multiple times since route may not be
                    // reconfigured between cause leading to bluetooth being disabled while it should not
                    CallManager.instance().bluetoothEnabled = false
                }
 
                if UIApplication.shared.applicationState != .active && (callLog == nil || callLog?.status == .Missed || callLog?.status == .Aborted || callLog?.status == .EarlyAborted)  {
                    // Configure the notification's payload.
                    let content = UNMutableNotificationContent()
                    content.title = NSString.localizedUserNotificationString(forKey: NSLocalizedString("Missed call", comment: ""), arguments: nil)
                    content.body = NSString.localizedUserNotificationString(forKey: address, arguments: nil)
 
                    // Deliver the notification.
                    let request = UNNotificationRequest(identifier: "call_request", content: content, trigger: nil) // Schedule the notification.
                    let center = UNUserNotificationCenter.current()
                    center.add(request) { (error : Error?) in
                        if error != nil {
                       
                        }
                    }
                }
 
                if (CallManager.callKitEnabled()) {
                    var uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
                    if (callId == CallManager.instance().referedToCall) {
                        // refered call ended before connecting
                        CallManager.instance().referedFromCall = nil
                        CallManager.instance().referedToCall = nil
                    }
                    if uuid == nil {
                        // the call not yet connected
                        uuid = CallManager.instance().providerDelegate.uuids[""]
                    }
                    if (uuid != nil) {
                        if (callId == CallManager.instance().referedFromCall) {
                           
                            CallManager.instance().referedFromCall = nil
                            let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
                            callInfo!.callId = CallManager.instance().referedToCall ?? ""
                            CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
                            CallManager.instance().providerDelegate.uuids.removeValue(forKey: callId!)
                            CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callInfo!.callId)
                            CallManager.instance().referedToCall = nil
                            break
                        }
 
                        let transaction = CXTransaction(action:
                        CXEndCallAction(call: uuid!))
                        CallManager.instance().requestTransaction(transaction, action: "endCall")
                    }
                }
                break
            case .Released:
                call.userData = nil
                break
            case .Referred:
                CallManager.instance().referedFromCall = call.callLog?.callId
                break
            default:
                break
        }
 
        if (cstate == .IncomingReceived || cstate == .OutgoingInit || cstate == .Connected || cstate == .StreamsRunning) {
            if ((call.currentParams?.videoEnabled ?? false) && !CoreManagerDelegate.speaker_already_enabled && !CallManager.instance().bluetoothEnabled) {
                CallManager.instance().enableSpeaker(enable: true)
                CoreManagerDelegate.speaker_already_enabled = true
            }
        }
 
        // post Notification kLinphoneCallUpdate
        NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self, userInfo: [
            AnyHashable("call"): NSValue.init(pointer:UnsafeRawPointer(call.getCobject)),
            AnyHashable("state"): NSNumber(value: cstate.rawValue),
            AnyHashable("message"): message
        ])
    }
}