Merge branch 'charlesmchen/webrtc/videoRefinements_' into feature/webrtc

pull/1/head
Matthew Chen 8 years ago
commit 08a0853bd2

@ -309,7 +309,9 @@ protocol CallServiceObserver: class {
in: thread) in: thread)
callRecord.save() callRecord.save()
self.callUIAdapter.reportMissedCall(call) DispatchQueue.main.async {
self.callUIAdapter.reportMissedCall(call)
}
} }
/** /**
@ -514,7 +516,9 @@ protocol CallServiceObserver: class {
call.state = .remoteRinging call.state = .remoteRinging
case .answering: case .answering:
call.state = .localRinging call.state = .localRinging
self.callUIAdapter.reportIncomingCall(call, thread: thread) DispatchQueue.main.async {
self.callUIAdapter.reportIncomingCall(call, thread: thread)
}
// cancel connection timeout // cancel connection timeout
self.fulfillCallConnectedPromise?() self.fulfillCallConnectedPromise?()
case .remoteRinging: case .remoteRinging:
@ -552,7 +556,9 @@ protocol CallServiceObserver: class {
call.state = .remoteHangup call.state = .remoteHangup
// Notify UI // Notify UI
callUIAdapter.remoteDidHangupCall(call) DispatchQueue.main.async {
self.callUIAdapter.remoteDidHangupCall(call)
}
// self.call is nil'd in `terminateCall`, so it's important we update it's state *before* calling `terminateCall` // self.call is nil'd in `terminateCall`, so it's important we update it's state *before* calling `terminateCall`
terminateCall() terminateCall()
@ -773,6 +779,38 @@ protocol CallServiceObserver: class {
func setHasLocalVideo(hasLocalVideo: Bool) { func setHasLocalVideo(hasLocalVideo: Bool) {
assertOnSignalingQueue() assertOnSignalingQueue()
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType:AVMediaTypeVideo)
switch authStatus {
case .notDetermined:
Logger.debug("\(TAG) authStatus: AVAuthorizationStatusNotDetermined")
break
case .restricted:
Logger.debug("\(TAG) authStatus: AVAuthorizationStatusRestricted")
break
case .denied:
Logger.debug("\(TAG) authStatus: AVAuthorizationStatusDenied")
break
case .authorized:
Logger.debug("\(TAG) authStatus: AVAuthorizationStatusAuthorized")
break
}
// We don't need to worry about the user granting or remoting this permission
// during a call while the app is in the background, because changing this
// permission kills the app.
if authStatus != .authorized {
DispatchQueue.main.async {
let title = NSLocalizedString("MISSING_CAMERA_PERMISSION_TITLE", comment: "Alert title when camera is not authorized")
let message = NSLocalizedString("MISSING_CAMERA_PERMISSION_MESSAGE", comment: "Alert body when camera is not authorized")
let okButton = NSLocalizedString("OK", comment:"")
let alert = UIAlertView(title:title, message:message, delegate:nil, cancelButtonTitle:okButton)
alert.show()
}
return
}
guard let peerConnectionClient = self.peerConnectionClient else { guard let peerConnectionClient = self.peerConnectionClient else {
handleFailedCall(error: .assertionError(description:"\(TAG) peerConnectionClient unexpectedly nil in \(#function)")) handleFailedCall(error: .assertionError(description:"\(TAG) peerConnectionClient unexpectedly nil in \(#function)"))
return return
@ -821,7 +859,9 @@ protocol CallServiceObserver: class {
return return
} }
callUIAdapter.recipientAcceptedCall(call) DispatchQueue.main.async {
self.callUIAdapter.recipientAcceptedCall(call)
}
handleConnectedCall(call) handleConnectedCall(call)
} else if message.hasHangup() { } else if message.hasHangup() {
@ -958,7 +998,9 @@ protocol CallServiceObserver: class {
// It's essential to set call.state before terminateCall, because terminateCall nils self.call // It's essential to set call.state before terminateCall, because terminateCall nils self.call
call.error = error call.error = error
call.state = .localFailure call.state = .localFailure
callUIAdapter.failCall(call, error: error) DispatchQueue.main.async {
self.callUIAdapter.failCall(call, error: error)
}
} else { } else {
// This can happen when we receive an out of band signaling message (e.g. IceUpdate) // This can happen when we receive an out of band signaling message (e.g. IceUpdate)
// after the call has ended // after the call has ended
@ -1113,6 +1155,14 @@ protocol CallServiceObserver: class {
remoteVideoTrack:remoteVideoTrack) remoteVideoTrack:remoteVideoTrack)
} }
} }
// Prevent screen from dimming during video call.
//
// fireDidUpdateVideoTracks() is called by the video track setters,
// which are cleared when the call ends. That ensures that this timer
// will be re-enabled.
let hasLocalOrRemoteVideo = localVideoTrack != nil || remoteVideoTrack != nil
UIApplication.shared.isIdleTimerDisabled = hasLocalOrRemoteVideo
} }
} }
} }

@ -23,6 +23,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func startOutgoingCall(handle: String) -> SignalCall { func startOutgoingCall(handle: String) -> SignalCall {
AssertIsOnMainThread()
let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle) let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle)
CallService.signalingQueue.async { CallService.signalingQueue.async {
@ -37,6 +39,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func reportIncomingCall(_ call: SignalCall, callerName: String) { func reportIncomingCall(_ call: SignalCall, callerName: String) {
AssertIsOnMainThread()
Logger.debug("\(TAG) \(#function)") Logger.debug("\(TAG) \(#function)")
// present Call View controller // present Call View controller
@ -52,10 +56,14 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func reportMissedCall(_ call: SignalCall, callerName: String) { func reportMissedCall(_ call: SignalCall, callerName: String) {
AssertIsOnMainThread()
notificationsAdapter.presentMissedCall(call, callerName: callerName) notificationsAdapter.presentMissedCall(call, callerName: callerName)
} }
func answerCall(localId: UUID) { func answerCall(localId: UUID) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
guard let call = self.callService.call else { guard let call = self.callService.call else {
assertionFailure("\(self.TAG) in \(#function) No current call.") assertionFailure("\(self.TAG) in \(#function) No current call.")
@ -72,6 +80,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func answerCall(_ call: SignalCall) { func answerCall(_ call: SignalCall) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
guard call.localId == self.callService.call?.localId else { guard call.localId == self.callService.call?.localId else {
assertionFailure("\(self.TAG) in \(#function) localId does not match current call") assertionFailure("\(self.TAG) in \(#function) localId does not match current call")
@ -84,6 +94,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func declineCall(localId: UUID) { func declineCall(localId: UUID) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
guard let call = self.callService.call else { guard let call = self.callService.call else {
assertionFailure("\(self.TAG) in \(#function) No current call.") assertionFailure("\(self.TAG) in \(#function) No current call.")
@ -100,6 +112,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func declineCall(_ call: SignalCall) { func declineCall(_ call: SignalCall) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
guard call.localId == self.callService.call?.localId else { guard call.localId == self.callService.call?.localId else {
assertionFailure("\(self.TAG) in \(#function) localId does not match current call") assertionFailure("\(self.TAG) in \(#function) localId does not match current call")
@ -111,10 +125,14 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func recipientAcceptedCall(_ call: SignalCall) { func recipientAcceptedCall(_ call: SignalCall) {
AssertIsOnMainThread()
PeerConnectionClient.startAudioSession() PeerConnectionClient.startAudioSession()
} }
func localHangupCall(_ call: SignalCall) { func localHangupCall(_ call: SignalCall) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
// If both parties hang up at the same moment, // If both parties hang up at the same moment,
// call might already be nil. // call might already be nil.
@ -128,14 +146,20 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
internal func remoteDidHangupCall(_ call: SignalCall) { internal func remoteDidHangupCall(_ call: SignalCall) {
AssertIsOnMainThread()
Logger.debug("\(TAG) in \(#function) is no-op") Logger.debug("\(TAG) in \(#function) is no-op")
} }
internal func failCall(_ call: SignalCall, error: CallError) { internal func failCall(_ call: SignalCall, error: CallError) {
AssertIsOnMainThread()
Logger.debug("\(TAG) in \(#function) is no-op") Logger.debug("\(TAG) in \(#function) is no-op")
} }
func setIsMuted(call: SignalCall, isMuted: Bool) { func setIsMuted(call: SignalCall, isMuted: Bool) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
guard call.localId == self.callService.call?.localId else { guard call.localId == self.callService.call?.localId else {
assertionFailure("\(self.TAG) in \(#function) localId does not match current call") assertionFailure("\(self.TAG) in \(#function) localId does not match current call")
@ -147,6 +171,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) { func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
CallService.signalingQueue.async { CallService.signalingQueue.async {
guard call.localId == self.callService.call?.localId else { guard call.localId == self.callService.call?.localId else {
assertionFailure("\(self.TAG) in \(#function) localId does not match current call") assertionFailure("\(self.TAG) in \(#function) localId does not match current call")

@ -147,15 +147,9 @@ class PeerConnectionClient: NSObject, RTCPeerConnectionDelegate, RTCDataChannelD
return return
} }
// TODO: What are the best values to use here? // TODO: We could cap the maximum video size.
let mediaConstraintsDictionary = [
kMediaConstraintsMinWidth: "240",
kMediaConstraintsMinHeight: "320",
kMediaConstraintsMaxWidth: "240",
kMediaConstraintsMaxHeight: "320"
]
let cameraConstraints = RTCMediaConstraints(mandatoryConstraints:nil, let cameraConstraints = RTCMediaConstraints(mandatoryConstraints:nil,
optionalConstraints:mediaConstraintsDictionary) optionalConstraints:nil)
// TODO: Revisit the cameraConstraints. // TODO: Revisit the cameraConstraints.
let videoSource = factory.avFoundationVideoSource(with: cameraConstraints) let videoSource = factory.avFoundationVideoSource(with: cameraConstraints)

@ -49,6 +49,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
init(callService: CallService, notificationsAdapter: CallNotificationsAdapter) { init(callService: CallService, notificationsAdapter: CallNotificationsAdapter) {
AssertIsOnMainThread()
self.callManager = CallKitCallManager() self.callManager = CallKitCallManager()
self.callService = callService self.callService = callService
self.notificationsAdapter = notificationsAdapter self.notificationsAdapter = notificationsAdapter
@ -62,6 +64,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// MARK: CallUIAdaptee // MARK: CallUIAdaptee
func startOutgoingCall(handle: String) -> SignalCall { func startOutgoingCall(handle: String) -> SignalCall {
AssertIsOnMainThread()
let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle) let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle)
// Add the new outgoing call to the app's list of calls. // Add the new outgoing call to the app's list of calls.
@ -74,11 +78,15 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// Called from CallService after call has ended to clean up any remaining CallKit call state. // Called from CallService after call has ended to clean up any remaining CallKit call state.
func failCall(_ call: SignalCall, error: CallError) { func failCall(_ call: SignalCall, error: CallError) {
AssertIsOnMainThread()
provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.failed) provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.failed)
self.callManager.removeCall(call) self.callManager.removeCall(call)
} }
func reportIncomingCall(_ call: SignalCall, callerName: String) { func reportIncomingCall(_ call: SignalCall, callerName: String) {
AssertIsOnMainThread()
// Construct a CXCallUpdate describing the incoming call, including the caller. // Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate() let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber) update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
@ -104,39 +112,57 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
func answerCall(localId: UUID) { func answerCall(localId: UUID) {
AssertIsOnMainThread()
assertionFailure("CallKit should answer calls via system call screen, not via notifications.") assertionFailure("CallKit should answer calls via system call screen, not via notifications.")
} }
func answerCall(_ call: SignalCall) { func answerCall(_ call: SignalCall) {
AssertIsOnMainThread()
callManager.answer(call: call) callManager.answer(call: call)
} }
func declineCall(localId: UUID) { func declineCall(localId: UUID) {
AssertIsOnMainThread()
assertionFailure("CallKit should decline calls via system call screen, not via notifications.") assertionFailure("CallKit should decline calls via system call screen, not via notifications.")
} }
func declineCall(_ call: SignalCall) { func declineCall(_ call: SignalCall) {
AssertIsOnMainThread()
callManager.localHangup(call: call) callManager.localHangup(call: call)
} }
func recipientAcceptedCall(_ call: SignalCall) { func recipientAcceptedCall(_ call: SignalCall) {
AssertIsOnMainThread()
// no - op // no - op
// TODO provider update call connected? // TODO provider update call connected?
} }
func localHangupCall(_ call: SignalCall) { func localHangupCall(_ call: SignalCall) {
AssertIsOnMainThread()
callManager.localHangup(call: call) callManager.localHangup(call: call)
} }
func remoteDidHangupCall(_ call: SignalCall) { func remoteDidHangupCall(_ call: SignalCall) {
AssertIsOnMainThread()
provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded) provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded)
} }
func setIsMuted(call: SignalCall, isMuted: Bool) { func setIsMuted(call: SignalCall, isMuted: Bool) {
AssertIsOnMainThread()
callManager.setIsMuted(call: call, isMuted: isMuted) callManager.setIsMuted(call: call, isMuted: isMuted)
} }
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) { func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
let update = CXCallUpdate() let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber) update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
update.hasVideo = hasLocalVideo update.hasVideo = hasLocalVideo
@ -152,6 +178,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// MARK: CXProviderDelegate // MARK: CXProviderDelegate
func providerDidReset(_ provider: CXProvider) { func providerDidReset(_ provider: CXProvider) {
AssertIsOnMainThread()
Logger.debug("\(TAG) in \(#function)") Logger.debug("\(TAG) in \(#function)")
// TODO // TODO
@ -174,6 +202,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
func provider(_ provider: CXProvider, perform action: CXStartCallAction) { func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
AssertIsOnMainThread()
Logger.debug("\(TAG) in \(#function) CXStartCallAction") Logger.debug("\(TAG) in \(#function) CXStartCallAction")
// TODO does this work when `action.handle.value` is not in e164 format, e.g. if called via intent? // TODO does this work when `action.handle.value` is not in e164 format, e.g. if called via intent?
@ -207,6 +237,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXAnswerCallAction") Logger.debug("\(TAG) Received \(#function) CXAnswerCallAction")
// Retrieve the SpeakerboxCall instance corresponding to the action's call UUID // Retrieve the SpeakerboxCall instance corresponding to the action's call UUID
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
@ -232,6 +264,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) { public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXEndCallAction") Logger.debug("\(TAG) Received \(#function) CXEndCallAction")
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
action.fail() action.fail()
@ -257,6 +291,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) { public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXSetHeldCallAction") Logger.debug("\(TAG) Received \(#function) CXSetHeldCallAction")
guard let call = callManager.callWithLocalId(action.callUUID) else { guard let call = callManager.callWithLocalId(action.callUUID) else {
action.fail() action.fail()
@ -282,6 +318,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) { public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function) CXSetMutedCallAction") Logger.debug("\(TAG) Received \(#function) CXSetMutedCallAction")
guard callManager.callWithLocalId(action.callUUID) != nil else { guard callManager.callWithLocalId(action.callUUID) != nil else {
Logger.error("\(TAG) Failing CXSetMutedCallAction for unknown call: \(action.callUUID)") Logger.error("\(TAG) Failing CXSetMutedCallAction for unknown call: \(action.callUUID)")
@ -296,20 +334,28 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
public func provider(_ provider: CXProvider, perform action: CXSetGroupCallAction) { public func provider(_ provider: CXProvider, perform action: CXSetGroupCallAction) {
AssertIsOnMainThread()
Logger.warn("\(TAG) unimplemented \(#function) for CXSetGroupCallAction") Logger.warn("\(TAG) unimplemented \(#function) for CXSetGroupCallAction")
} }
public func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) { public func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) {
AssertIsOnMainThread()
Logger.warn("\(TAG) unimplemented \(#function) for CXPlayDTMFCallAction") Logger.warn("\(TAG) unimplemented \(#function) for CXPlayDTMFCallAction")
} }
func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) { func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Timed out \(#function)") Logger.debug("\(TAG) Timed out \(#function)")
// React to the action timeout if necessary, such as showing an error UI. // React to the action timeout if necessary, such as showing an error UI.
} }
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) { func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function)") Logger.debug("\(TAG) Received \(#function)")
// Start recording // Start recording
@ -317,6 +363,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
AssertIsOnMainThread()
Logger.debug("\(TAG) Received \(#function)") Logger.debug("\(TAG) Received \(#function)")
/* /*

@ -63,6 +63,8 @@ extension CallUIAdaptee {
private let audioService: CallAudioService private let audioService: CallAudioService
required init(callService: CallService, contactsManager: OWSContactsManager, notificationsAdapter: CallNotificationsAdapter) { required init(callService: CallService, contactsManager: OWSContactsManager, notificationsAdapter: CallNotificationsAdapter) {
AssertIsOnMainThread()
self.contactsManager = contactsManager self.contactsManager = contactsManager
if Platform.isSimulator { if Platform.isSimulator {
// CallKit doesn't seem entirely supported in simulator. // CallKit doesn't seem entirely supported in simulator.
@ -82,6 +84,8 @@ extension CallUIAdaptee {
} }
internal func reportIncomingCall(_ call: SignalCall, thread: TSContactThread) { internal func reportIncomingCall(_ call: SignalCall, thread: TSContactThread) {
AssertIsOnMainThread()
call.addObserverAndSyncState(observer: audioService) call.addObserverAndSyncState(observer: audioService)
let callerName = self.contactsManager.displayName(forPhoneIdentifier: call.remotePhoneNumber) let callerName = self.contactsManager.displayName(forPhoneIdentifier: call.remotePhoneNumber)
@ -89,11 +93,15 @@ extension CallUIAdaptee {
} }
internal func reportMissedCall(_ call: SignalCall) { internal func reportMissedCall(_ call: SignalCall) {
AssertIsOnMainThread()
let callerName = self.contactsManager.displayName(forPhoneIdentifier: call.remotePhoneNumber) let callerName = self.contactsManager.displayName(forPhoneIdentifier: call.remotePhoneNumber)
adaptee.reportMissedCall(call, callerName: callerName) adaptee.reportMissedCall(call, callerName: callerName)
} }
internal func startOutgoingCall(handle: String) -> SignalCall { internal func startOutgoingCall(handle: String) -> SignalCall {
AssertIsOnMainThread()
let call = adaptee.startOutgoingCall(handle: handle) let call = adaptee.startOutgoingCall(handle: handle)
call.addObserverAndSyncState(observer: audioService) call.addObserverAndSyncState(observer: audioService)
@ -101,56 +109,82 @@ extension CallUIAdaptee {
} }
internal func answerCall(localId: UUID) { internal func answerCall(localId: UUID) {
AssertIsOnMainThread()
adaptee.answerCall(localId: localId) adaptee.answerCall(localId: localId)
} }
internal func answerCall(_ call: SignalCall) { internal func answerCall(_ call: SignalCall) {
AssertIsOnMainThread()
adaptee.answerCall(call) adaptee.answerCall(call)
} }
internal func declineCall(localId: UUID) { internal func declineCall(localId: UUID) {
AssertIsOnMainThread()
adaptee.declineCall(localId: localId) adaptee.declineCall(localId: localId)
} }
internal func declineCall(_ call: SignalCall) { internal func declineCall(_ call: SignalCall) {
AssertIsOnMainThread()
adaptee.declineCall(call) adaptee.declineCall(call)
} }
internal func callBack(recipientId: String) { internal func callBack(recipientId: String) {
AssertIsOnMainThread()
adaptee.callBack(recipientId: recipientId) adaptee.callBack(recipientId: recipientId)
} }
internal func recipientAcceptedCall(_ call: SignalCall) { internal func recipientAcceptedCall(_ call: SignalCall) {
AssertIsOnMainThread()
adaptee.recipientAcceptedCall(call) adaptee.recipientAcceptedCall(call)
} }
internal func remoteDidHangupCall(_ call: SignalCall) { internal func remoteDidHangupCall(_ call: SignalCall) {
AssertIsOnMainThread()
adaptee.remoteDidHangupCall(call) adaptee.remoteDidHangupCall(call)
} }
internal func localHangupCall(_ call: SignalCall) { internal func localHangupCall(_ call: SignalCall) {
AssertIsOnMainThread()
adaptee.localHangupCall(call) adaptee.localHangupCall(call)
} }
internal func failCall(_ call: SignalCall, error: CallError) { internal func failCall(_ call: SignalCall, error: CallError) {
AssertIsOnMainThread()
adaptee.failCall(call, error: error) adaptee.failCall(call, error: error)
} }
internal func showCall(_ call: SignalCall) { internal func showCall(_ call: SignalCall) {
AssertIsOnMainThread()
adaptee.showCall(call) adaptee.showCall(call)
} }
internal func setIsMuted(call: SignalCall, isMuted: Bool) { internal func setIsMuted(call: SignalCall, isMuted: Bool) {
AssertIsOnMainThread()
// With CallKit, muting is handled by a CXAction, so it must go through the adaptee // With CallKit, muting is handled by a CXAction, so it must go through the adaptee
adaptee.setIsMuted(call: call, isMuted: isMuted) adaptee.setIsMuted(call: call, isMuted: isMuted)
} }
internal func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) { internal func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
adaptee.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo) adaptee.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo)
} }
internal func setIsSpeakerphoneEnabled(call: SignalCall, isEnabled: Bool) { internal func setIsSpeakerphoneEnabled(call: SignalCall, isEnabled: Bool) {
// Speakerphone is not handled by CallKit (e.g. there is no CXAction), so we handle it w/o going through the AssertIsOnMainThread()
// Speakerphone is not handled by CallKit (e.g. there is no CXAction), so we handle it w/o going through the
// adaptee, relying on the AudioService CallObserver to put the system in a state consistent with the call's // adaptee, relying on the AudioService CallObserver to put the system in a state consistent with the call's
// assigned property. // assigned property.
CallService.signalingQueue.async { CallService.signalingQueue.async {
@ -160,6 +194,8 @@ extension CallUIAdaptee {
// CallKit handles ringing state on it's own. But for non-call kit we trigger ringing start/stop manually. // CallKit handles ringing state on it's own. But for non-call kit we trigger ringing start/stop manually.
internal var hasManualRinger: Bool { internal var hasManualRinger: Bool {
AssertIsOnMainThread()
return adaptee.hasManualRinger return adaptee.hasManualRinger
} }
} }

@ -662,8 +662,6 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
func didPressVideo(sender: UIButton) { func didPressVideo(sender: UIButton) {
Logger.info("\(TAG) called \(#function)") Logger.info("\(TAG) called \(#function)")
let hasLocalVideo = !sender.isSelected let hasLocalVideo = !sender.isSelected
audioModeVideoButton.isSelected = hasLocalVideo
videoModeVideoButton.isSelected = hasLocalVideo
if let call = self.call { if let call = self.call {
callUIAdapter.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo) callUIAdapter.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo)
} else { } else {

@ -68,7 +68,7 @@
"ATTACHMENT_QUEUED" = "New attachment queued for retrieval."; "ATTACHMENT_QUEUED" = "New attachment queued for retrieval.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"AUDIO_PERMISSION_MESSAGE" = "Signal requires access to your microphone to work properly. You can restore the permission in the Settings app >> Privacy >> Microphone >> Signal"; "AUDIO_PERMISSION_MESSAGE" = "Signal requires access to your microphone to work properly. You can grant this permission in the Settings app >> Privacy >> Microphone >> Signal";
/* Accessibilty label for placing call button */ /* Accessibilty label for placing call button */
"CALL_LABEL" = "Call"; "CALL_LABEL" = "Call";
@ -449,10 +449,12 @@
notification title */ notification title */
"MISSED_CALL" = "Missed call"; "MISSED_CALL" = "Missed call";
/* Alert body */ /* Alert body
"MISSING_CAMERA_PERMISSION_MESSAGE" = "You previously declined to let Signal access your camera. Update your system settings to proceed."; Alert body when camera is not authorized */
"MISSING_CAMERA_PERMISSION_MESSAGE" = "Signal needs access to your camera for video calls. You can grant this permission in the Settings app >> Privacy >> Camera >> Signal";
/* Alert title */ /* Alert title
Alert title when camera is not authorized */
"MISSING_CAMERA_PERMISSION_TITLE" = "Signal needs to access your camera."; "MISSING_CAMERA_PERMISSION_TITLE" = "Signal needs to access your camera.";
/* notification body /* notification body

Loading…
Cancel
Save