"Fossies" - the Fresh Open Source Software Archive

Member "jitsi-meet-6193/ios/sdk/src/callkit/JMCallKitProxy.swift" (20 May 2022, 8591 Bytes) of package /linux/misc/jitsi-meet-6193.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Swift source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright @ 2018-present 8x8, Inc.
    3  *
    4  * Licensed under the Apache License, Version 2.0 (the "License");
    5  * you may not use this file except in compliance with the License.
    6  * You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 import CallKit
   18 import Foundation
   19 
   20 public protocol CXProviderProtocol: AnyObject {
   21     var configuration: CXProviderConfiguration { get set }
   22     func setDelegate(_ delegate: CXProviderDelegate?, queue: DispatchQueue?)
   23     func reportNewIncomingCall(with UUID: UUID, update: CXCallUpdate, completion: @escaping (Error?) -> Void)
   24     func reportCall(with UUID: UUID, updated update: CXCallUpdate)
   25     func reportCall(with UUID: UUID, endedAt dateEnded: Date?, reason endedReason: CXCallEndedReason)
   26     func reportOutgoingCall(with UUID: UUID, startedConnectingAt dateStartedConnecting: Date?)
   27     func reportOutgoingCall(with UUID: UUID, connectedAt dateConnected: Date?)
   28     func invalidate()
   29 }
   30 
   31 public protocol CXCallControllerProtocol: AnyObject {
   32     var calls: [CXCall] { get }
   33     func request(_ transaction: CXTransaction, completion: @escaping (Error?) -> Swift.Void)
   34 }
   35 
   36 extension CXProvider: CXProviderProtocol {}
   37 extension CXCallController: CXCallControllerProtocol {
   38     public var calls: [CXCall] {
   39         return callObserver.calls
   40     }
   41 }
   42 
   43 /// JitsiMeet CallKit proxy
   44 // NOTE: The methods this class exposes are meant to be called in the UI thread.
   45 // All delegate methods called by JMCallKitEmitter will be called in the UI thread.
   46 @objc public final class JMCallKitProxy: NSObject {
   47 
   48     private override init() {}
   49 
   50     // MARK: - CallKit proxy
   51     
   52     public static var callKitProvider: CXProviderProtocol?
   53     public static var callKitCallController: CXCallControllerProtocol?
   54 
   55     private static var defaultProvider: CXProvider?
   56 
   57     private static var provider: CXProviderProtocol? {
   58         callKitProvider ?? defaultProvider
   59     }
   60     
   61     private static var callController: CXCallControllerProtocol {
   62         callKitCallController ?? defaultCallController
   63     }
   64 
   65     private static var providerConfiguration: CXProviderConfiguration? {
   66         didSet {
   67             guard let configuration = providerConfiguration else { return }
   68             provider?.configuration = configuration
   69             provider?.setDelegate(emitter, queue: nil)
   70         }
   71     }
   72     
   73     private static let defaultCallController: CXCallController = {
   74         return CXCallController()
   75     }()
   76     
   77     private static let emitter: JMCallKitEmitter = {
   78         return JMCallKitEmitter()
   79     }()
   80 
   81     /// Enables the proxy in between CallKit and the consumers of the SDK.
   82     /// Defaults to disabled. Set to true when you want to use CallKit.
   83     @objc public static var enabled: Bool = false {
   84         didSet {
   85             if callKitProvider == nil {
   86                 provider?.invalidate()
   87             }
   88             
   89             if enabled {
   90                 let configuration = providerConfiguration ?? CXProviderConfiguration(localizedName: "")
   91                 if callKitProvider == nil {
   92                     defaultProvider = CXProvider(configuration: configuration)
   93                 }
   94                 
   95                 provider?.setDelegate(emitter, queue: nil)
   96             } else {
   97                 provider?.setDelegate(nil, queue: nil)
   98             }
   99         }
  100     }
  101 
  102     @objc public static func configureProvider(localizedName: String,
  103                                                ringtoneSound: String?,
  104                                                iconTemplateImageData: Data?) {
  105         guard enabled else { return }
  106 
  107         let configuration = CXProviderConfiguration(localizedName: localizedName)
  108         configuration.iconTemplateImageData = iconTemplateImageData
  109         configuration.maximumCallGroups = 1
  110         configuration.maximumCallsPerCallGroup = 1
  111         configuration.ringtoneSound = ringtoneSound
  112         configuration.supportedHandleTypes = [CXHandle.HandleType.generic]
  113         configuration.supportsVideo = true
  114 
  115         providerConfiguration = configuration
  116     }
  117 
  118     @objc public static func isProviderConfigured() -> Bool {
  119         return providerConfiguration != nil
  120     }
  121 
  122     @objc public static func addListener(_ listener: JMCallKitListener) {
  123         emitter.addListener(listener)
  124     }
  125 
  126     @objc public static func removeListener(_ listener: JMCallKitListener) {
  127         emitter.removeListener(listener)
  128     }
  129 
  130     @objc public static func hasActiveCallForUUID(_ callUUID: String) -> Bool {
  131         let activeCallForUUID = callController.calls.first {
  132             $0.uuid == UUID(uuidString: callUUID)
  133         }
  134         guard activeCallForUUID != nil else { return false }
  135         return true
  136     }
  137 
  138     @objc public static func reportNewIncomingCall(UUID: UUID,
  139                                                    handle: String?,
  140                                                    displayName: String?,
  141                                                    hasVideo: Bool,
  142                                                    completion: @escaping (Error?) -> Void) {
  143         guard enabled else { return }
  144 
  145         let callUpdate = makeCXUpdate(handle: handle,
  146                                       displayName: displayName,
  147                                       hasVideo: hasVideo)
  148         provider?.reportNewIncomingCall(with: UUID,
  149                                         update: callUpdate,
  150                                         completion: completion)
  151     }
  152 
  153     @objc public static func reportCallUpdate(with UUID: UUID,
  154                                               handle: String?,
  155                                               displayName: String?,
  156                                               hasVideo: Bool) {
  157         guard enabled else { return }
  158 
  159         let callUpdate = makeCXUpdate(handle: handle,
  160                                       displayName: displayName,
  161                                       hasVideo: hasVideo)
  162         provider?.reportCall(with: UUID, updated: callUpdate)
  163     }
  164 
  165     @objc public static func reportCall(
  166             with UUID: UUID,
  167             endedAt dateEnded: Date?,
  168             reason endedReason: CXCallEndedReason) {
  169         guard enabled else { return }
  170         provider?.reportCall(with: UUID,
  171                              endedAt: dateEnded,
  172                              reason: endedReason)
  173     }
  174 
  175     @objc public static func reportOutgoingCall(
  176             with UUID: UUID,
  177             startedConnectingAt dateStartedConnecting: Date?) {
  178         guard enabled else { return }
  179         provider?.reportOutgoingCall(with: UUID,
  180                                      startedConnectingAt: dateStartedConnecting)
  181     }
  182 
  183     @objc public static func reportOutgoingCall(
  184             with UUID: UUID,
  185             connectedAt dateConnected: Date?) {
  186         guard enabled else { return }
  187 
  188         provider?.reportOutgoingCall(with: UUID, connectedAt: dateConnected)
  189     }
  190 
  191     @objc public static func request(
  192             _ transaction: CXTransaction,
  193             completion: @escaping (Error?) -> Swift.Void) {
  194         guard enabled else { return }
  195 
  196         // XXX keep track of muted actions to avoid "ping-pong"ing. See
  197         // JMCallKitEmitter for details on the CXSetMutedCallAction handling.
  198         for action in transaction.actions {
  199             if (action as? CXSetMutedCallAction) != nil {
  200                 emitter.addMuteAction(action.uuid)
  201             }
  202         }
  203 
  204         callController.request(transaction, completion: completion)
  205     }
  206 
  207     // MARK: - Callkit Proxy helpers
  208 
  209     private static func makeCXUpdate(handle: String?,
  210                                      displayName: String?,
  211                                      hasVideo: Bool) -> CXCallUpdate {
  212         let update = CXCallUpdate()
  213         update.supportsDTMF = false
  214         update.supportsHolding = false
  215         update.supportsGrouping = false
  216         update.supportsUngrouping = false
  217         update.hasVideo = hasVideo
  218 
  219         if let handle = handle {
  220             update.remoteHandle = CXHandle(type: .generic,
  221                                            value: handle)
  222         }
  223 
  224         if let displayName = displayName {
  225             update.localizedCallerName = displayName
  226         }
  227 
  228         return update
  229     }
  230 }
  231