|
@@ -22,6 +22,7 @@ import Foundation
|
22
|
22
|
internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {
|
23
|
23
|
|
24
|
24
|
private var listeners = Set<JMCallKitEventListenerWrapper>()
|
|
25
|
+ private var pendingMuteActions = Set<UUID>()
|
25
|
26
|
|
26
|
27
|
internal override init() {}
|
27
|
28
|
|
|
@@ -29,13 +30,10 @@ internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {
|
29
|
30
|
|
30
|
31
|
func addListener(_ listener: JMCallKitListener) {
|
31
|
32
|
let wrapper = JMCallKitEventListenerWrapper(listener: listener)
|
32
|
|
- objc_sync_enter(listeners)
|
33
|
33
|
listeners.insert(wrapper)
|
34
|
|
- objc_sync_exit(listeners)
|
35
|
34
|
}
|
36
|
35
|
|
37
|
36
|
func removeListener(_ listener: JMCallKitListener) {
|
38
|
|
- objc_sync_enter(listeners)
|
39
|
37
|
// XXX Constructing a new JMCallKitEventListenerWrapper instance in
|
40
|
38
|
// order to remove the specified listener from listeners is (1) a bit
|
41
|
39
|
// funny (though may make a statement about performance) and (2) not
|
|
@@ -58,76 +56,76 @@ internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {
|
58
|
56
|
listeners.remove($0)
|
59
|
57
|
}
|
60
|
58
|
}
|
61
|
|
- objc_sync_exit(listeners)
|
|
59
|
+ }
|
|
60
|
+
|
|
61
|
+ // MARK: - Add mute action
|
|
62
|
+
|
|
63
|
+ func addMuteAction(_ actionUUID: UUID) {
|
|
64
|
+ pendingMuteActions.insert(actionUUID)
|
62
|
65
|
}
|
63
|
66
|
|
64
|
67
|
// MARK: - CXProviderDelegate
|
65
|
68
|
|
66
|
69
|
func providerDidReset(_ provider: CXProvider) {
|
67
|
|
- objc_sync_enter(listeners)
|
68
|
70
|
listeners.forEach { $0.listener?.providerDidReset?() }
|
69
|
|
- objc_sync_exit(listeners)
|
|
71
|
+ pendingMuteActions.removeAll()
|
70
|
72
|
}
|
71
|
73
|
|
72
|
74
|
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
73
|
|
- objc_sync_enter(listeners)
|
74
|
75
|
listeners.forEach {
|
75
|
76
|
$0.listener?.performAnswerCall?(UUID: action.callUUID)
|
76
|
77
|
}
|
77
|
|
- objc_sync_exit(listeners)
|
78
|
78
|
|
79
|
79
|
action.fulfill()
|
80
|
80
|
}
|
81
|
81
|
|
82
|
82
|
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
83
|
|
- objc_sync_enter(listeners)
|
84
|
83
|
listeners.forEach {
|
85
|
84
|
$0.listener?.performEndCall?(UUID: action.callUUID)
|
86
|
85
|
}
|
87
|
|
- objc_sync_exit(listeners)
|
88
|
86
|
|
89
|
87
|
action.fulfill()
|
90
|
88
|
}
|
91
|
89
|
|
92
|
90
|
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
93
|
|
- objc_sync_enter(listeners)
|
94
|
|
- listeners.forEach {
|
95
|
|
- $0.listener?.performSetMutedCall?(UUID: action.callUUID,
|
96
|
|
- isMuted: action.isMuted)
|
|
91
|
+ let uuid = pendingMuteActions.remove(action.uuid)
|
|
92
|
+
|
|
93
|
+ // XXX avoid mute actions ping-pong: if the mute action was caused by
|
|
94
|
+ // the JS side (we requested a transaction) don't call the delegate
|
|
95
|
+ // method. If it was called by the provder itself (when the user presses
|
|
96
|
+ // the mute button in the CallKit view) then call the delegate method.
|
|
97
|
+ if (uuid == nil) {
|
|
98
|
+ listeners.forEach {
|
|
99
|
+ $0.listener?.performSetMutedCall?(UUID: action.callUUID,
|
|
100
|
+ isMuted: action.isMuted)
|
|
101
|
+ }
|
97
|
102
|
}
|
98
|
|
- objc_sync_exit(listeners)
|
99
|
103
|
|
100
|
104
|
action.fulfill()
|
101
|
105
|
}
|
102
|
106
|
|
103
|
107
|
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
104
|
|
- objc_sync_enter(listeners)
|
105
|
108
|
listeners.forEach {
|
106
|
109
|
$0.listener?.performStartCall?(UUID: action.callUUID,
|
107
|
110
|
isVideo: action.isVideo)
|
108
|
111
|
}
|
109
|
|
- objc_sync_exit(listeners)
|
110
|
112
|
|
111
|
113
|
action.fulfill()
|
112
|
114
|
}
|
113
|
115
|
|
114
|
116
|
func provider(_ provider: CXProvider,
|
115
|
117
|
didActivate audioSession: AVAudioSession) {
|
116
|
|
- objc_sync_enter(listeners)
|
117
|
118
|
listeners.forEach {
|
118
|
119
|
$0.listener?.providerDidActivateAudioSession?(session: audioSession)
|
119
|
120
|
}
|
120
|
|
- objc_sync_exit(listeners)
|
121
|
121
|
}
|
122
|
122
|
|
123
|
123
|
func provider(_ provider: CXProvider,
|
124
|
124
|
didDeactivate audioSession: AVAudioSession) {
|
125
|
|
- objc_sync_enter(listeners)
|
126
|
125
|
listeners.forEach {
|
127
|
126
|
$0.listener?.providerDidDeactivateAudioSession?(
|
128
|
127
|
session: audioSession)
|
129
|
128
|
}
|
130
|
|
- objc_sync_exit(listeners)
|
131
|
129
|
}
|
132
|
130
|
}
|
133
|
131
|
|