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

pull/1/head
Matthew Chen 8 years ago
commit 2a4170a32d

@ -42,18 +42,25 @@ import Foundation
internal func speakerphoneDidChange(call: SignalCall, isEnabled: Bool) {
AssertIsOnMainThread()
if isEnabled {
ensureIsEnabled(call: call)
}
internal func hasLocalVideoDidChange(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
ensureIsEnabled(call: call)
}
private func ensureIsEnabled(call: SignalCall) {
// Auto-enable speakerphone when local video is enabled.
if call.isSpeakerphoneEnabled || call.hasLocalVideo {
setAudioSession(category: AVAudioSessionCategoryPlayAndRecord, options: .defaultToSpeaker)
} else {
setAudioSession(category: AVAudioSessionCategoryPlayAndRecord)
}
}
internal func hasVideoDidChange(call: SignalCall, hasVideo: Bool) {
AssertIsOnMainThread()
// no-op
}
// MARK: - Service action handlers
public func handleState(_ state: CallState) {

@ -770,7 +770,7 @@ protocol CallServiceObserver: class {
*
* Can be used for Incoming and Outgoing calls.
*/
func setHasVideo(hasVideo: Bool) {
func setHasLocalVideo(hasLocalVideo: Bool) {
assertOnSignalingQueue()
guard let peerConnectionClient = self.peerConnectionClient else {
@ -783,13 +783,13 @@ protocol CallServiceObserver: class {
return
}
call.hasVideo = hasVideo
call.hasLocalVideo = hasLocalVideo
peerConnectionClient.setLocalVideoEnabled(enabled: shouldHaveLocalVideoTrack())
}
func handleCallKitStartVideo() {
CallService.signalingQueue.async {
self.setHasVideo(hasVideo:true)
self.setHasLocalVideo(hasLocalVideo:true)
}
}
@ -1000,9 +1000,9 @@ protocol CallServiceObserver: class {
self.updateIsVideoEnabled()
}
internal func hasVideoDidChange(call: SignalCall, hasVideo: Bool) {
internal func hasLocalVideoDidChange(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
Logger.info("\(self.TAG) \(#function): \(hasVideo)")
Logger.info("\(self.TAG) \(#function): \(hasLocalVideo)")
self.updateIsVideoEnabled()
}
@ -1027,7 +1027,7 @@ protocol CallServiceObserver: class {
return (!Platform.isSimulator &&
call != nil &&
call!.state == .connected &&
call!.hasVideo)
call!.hasLocalVideo)
}
private func updateIsVideoEnabled() {

@ -146,14 +146,14 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
}
}
func setHasVideo(call: SignalCall, hasVideo: Bool) {
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
CallService.signalingQueue.async {
guard call.localId == self.callService.call?.localId else {
assertionFailure("\(self.TAG) in \(#function) localId does not match current call")
return
}
self.callService.setHasVideo(hasVideo: hasVideo)
self.callService.setHasLocalVideo(hasLocalVideo: hasLocalVideo)
}
}
}

@ -20,7 +20,7 @@ enum CallState: String {
// All Observer methods will be invoked from the main thread.
protocol CallObserver: class {
func stateDidChange(call: SignalCall, state: CallState)
func hasVideoDidChange(call: SignalCall, hasVideo: Bool)
func hasLocalVideoDidChange(call: SignalCall, hasLocalVideo: Bool)
func muteDidChange(call: SignalCall, isMuted: Bool)
func speakerphoneDidChange(call: SignalCall, isEnabled: Bool)
}
@ -43,20 +43,20 @@ protocol CallObserver: class {
// Distinguishes between calls locally, e.g. in CallKit
let localId: UUID
var hasVideo = false {
var hasLocalVideo = false {
didSet {
// This should only occur on the signaling queue.
objc_sync_enter(self)
let observers = self.observers
let call = self
let hasVideo = self.hasVideo
let hasLocalVideo = self.hasLocalVideo
objc_sync_exit(self)
DispatchQueue.main.async {
for observer in observers {
observer.value?.hasVideoDidChange(call: call, hasVideo: hasVideo)
observer.value?.hasLocalVideoDidChange(call: call, hasLocalVideo: hasLocalVideo)
}
}
}

@ -25,7 +25,7 @@ final class CallKitCallManager: NSObject {
let handle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
let startCallAction = CXStartCallAction(call: call.localId, handle: handle)
startCallAction.isVideo = call.hasVideo
startCallAction.isVideo = call.hasLocalVideo
let transaction = CXTransaction()
transaction.addAction(startCallAction)

@ -34,7 +34,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
providerConfiguration.supportsVideo = true
providerConfiguration.maximumCallGroups = 1
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.supportedHandleTypes = [.phoneNumber]
@ -82,12 +82,12 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
update.hasVideo = call.hasVideo
update.hasVideo = call.hasLocalVideo
update.supportsHolding = false
update.supportsGrouping = false
update.supportsUngrouping = false
update.supportsDTMF = false
// Report the incoming call to the system
provider.reportNewIncomingCall(with: call.localId, update: update) { error in
/*
@ -136,16 +136,16 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
callManager.setIsMuted(call: call, isMuted: isMuted)
}
func setHasVideo(call: SignalCall, hasVideo: Bool) {
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
update.hasVideo = hasVideo
update.hasVideo = hasLocalVideo
// Update the CallKit UI.
provider.reportCall(with: call.localId, updated: update)
CallService.signalingQueue.async {
self.callService.setHasVideo(hasVideo: hasVideo)
self.callService.setHasLocalVideo(hasLocalVideo: hasLocalVideo)
}
}

@ -23,7 +23,7 @@ protocol CallUIAdaptee {
func remoteDidHangupCall(_ call: SignalCall)
func failCall(_ call: SignalCall, error: CallError)
func setIsMuted(call: SignalCall, isMuted: Bool)
func setHasVideo(call: SignalCall, hasVideo: Bool)
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool)
func callBack(recipientId: String)
}
@ -145,15 +145,17 @@ extension CallUIAdaptee {
adaptee.setIsMuted(call: call, isMuted: isMuted)
}
internal func setHasVideo(call: SignalCall, hasVideo: Bool) {
adaptee.setHasVideo(call: call, hasVideo: hasVideo)
internal func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
adaptee.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo)
}
internal func toggleSpeakerphone(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
// adaptee, relying on the AudioService CallObserver to put the system in a state consistent with the call's
// assigned property.
call.isSpeakerphoneEnabled = isEnabled
CallService.signalingQueue.async {
call.isSpeakerphoneEnabled = isEnabled
}
}
// CallKit handles ringing state on it's own. But for non-call kit we trigger ringing start/stop manually.

@ -46,10 +46,15 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
var ongoingCallView: UIView!
var hangUpButton: UIButton!
var muteButton: UIButton!
var speakerPhoneButton: UIButton!
var textMessageButton: UIButton!
var videoButton: UIButton!
var audioModeMuteButton: UIButton!
var audioModeVideoButton: UIButton!
var videoModeMuteButton: UIButton!
var videoModeVideoButton: UIButton!
// TODO: Later, we'll re-enable the text message button
// so users can send and read messages during a
// call.
// var textMessageButton: UIButton!
// MARK: Incoming Call Controls
@ -68,20 +73,6 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
var remoteVideoConstraints: [NSLayoutConstraint] = []
var localVideoConstraints: [NSLayoutConstraint] = []
// MARK: Control Groups
var allControls: [UIView] {
return incomingCallControls + ongoingCallControls
}
var incomingCallControls: [UIView] {
return [ acceptIncomingButton, declineIncomingButton ]
}
var ongoingCallControls: [UIView] {
return [ muteButton, speakerPhoneButton, textMessageButton, hangUpButton, videoButton ]
}
// MARK: Initializers
required init?(coder aDecoder: NSCoder) {
@ -195,29 +186,38 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
func createOngoingCallControls() {
textMessageButton = createButton(imageName:"message-active-wide",
action:#selector(didPressTextMessage))
muteButton = createButton(imageName:"mute-unselected-wide",
action:#selector(didPressMute))
speakerPhoneButton = createButton(imageName:"speaker-active-wide",
// textMessageButton = createButton(imageName:"message-active-wide",
// action:#selector(didPressTextMessage))
speakerPhoneButton = createButton(imageName:"speaker-inactive-wide",
action:#selector(didPressSpeakerphone))
videoButton = createButton(imageName:"video-inactive-wide",
action:#selector(didPressVideo))
hangUpButton = createButton(imageName:"hangup-active-wide",
action:#selector(didPressHangup))
audioModeMuteButton = createButton(imageName:"mute-unselected-wide",
action:#selector(didPressMute))
videoModeMuteButton = createButton(imageName:"mute-unselected-wide",
action:#selector(didPressMute))
audioModeVideoButton = createButton(imageName:"video-inactive-wide",
action:#selector(didPressVideo))
videoModeVideoButton = createButton(imageName:"video-inactive-wide",
action:#selector(didPressVideo))
let muteSelectedImage = UIImage(named:"mute-selected-wide")
assert(muteSelectedImage != nil)
muteButton.setImage(muteSelectedImage, for:.selected)
audioModeMuteButton.setImage(muteSelectedImage, for:.selected)
videoModeMuteButton.setImage(muteSelectedImage, for:.selected)
let videoSelectedImage = UIImage(named:"video-active-wide")
assert(videoSelectedImage != nil)
videoButton.setImage(videoSelectedImage, for:.selected)
audioModeVideoButton.setImage(videoSelectedImage, for:.selected)
videoModeVideoButton.setImage(videoSelectedImage, for:.selected)
let speakerPhoneSelectedImage = UIImage(named:"speaker-active-wide")
assert(speakerPhoneSelectedImage != nil)
speakerPhoneButton.setImage(speakerPhoneSelectedImage, for:.selected)
ongoingCallView = createContainerForCallControls(controlGroups : [
[textMessageButton, videoButton],
[muteButton, speakerPhoneButton ],
[hangUpButton ]
[audioModeMuteButton, speakerPhoneButton, audioModeVideoButton ],
[videoModeMuteButton, hangUpButton, videoModeVideoButton ]
])
}
@ -244,7 +244,7 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
var prevRow: UIView?
for row in rows {
containerView.addSubview(row)
row.autoPinWidthToSuperview()
row.autoHCenterInSuperview()
if prevRow != nil {
row.autoPinEdge(.top, to:.bottom, of:prevRow!, withOffset:rowspacing)
}
@ -310,7 +310,8 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
// If there's only one subview in this row, center it.
let subview = subviews.first!
row.addSubview(subview)
subview.autoCenterInSuperview()
subview.autoVCenterInSuperview()
subview.autoPinWidthToSuperview()
}
return row
@ -421,6 +422,7 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
}
self.remoteVideoConstraints = constraints
updateCallUI(callState: call.state)
}
internal func updateLocalVideoLayout() {
@ -442,14 +444,6 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
self.localVideoConstraints = constraints
}
func traverseViewHierarchy(view: UIView!, visitor: (UIView) -> Void) {
visitor(view)
for subview in view.subviews {
traverseViewHierarchy(view:subview, visitor:visitor)
}
}
// MARK: - Methods
// objc accessible way to set our swift enum.
@ -522,8 +516,11 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
assert(Thread.isMainThread)
updateCallStatusLabel(callState: callState)
videoButton.isSelected = call.hasVideo
muteButton.isSelected = call.isMuted
audioModeMuteButton.isSelected = call.isMuted
videoModeMuteButton.isSelected = call.isMuted
audioModeVideoButton.isSelected = call.hasLocalVideo
videoModeVideoButton.isSelected = call.hasLocalVideo
speakerPhoneButton.isSelected = call.isSpeakerphoneEnabled
// Show Incoming vs. Ongoing call controls
let isRinging = callState == .localRinging
@ -532,6 +529,14 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
ongoingCallView.isHidden = isRinging
ongoingCallView.isUserInteractionEnabled = !isRinging
// Rework control state if remote video is available.
contactAvatarView.isHidden = !remoteVideoView.isHidden
speakerPhoneButton.isHidden = !remoteVideoView.isHidden
audioModeMuteButton.isHidden = !remoteVideoView.isHidden
videoModeMuteButton.isHidden = remoteVideoView.isHidden
audioModeVideoButton.isHidden = !remoteVideoView.isHidden
videoModeVideoButton.isHidden = remoteVideoView.isHidden
// Dismiss Handling
switch callState {
case .remoteHangup, .remoteBusy, .localFailure:
@ -595,7 +600,7 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
Logger.info("\(TAG) called \(#function)")
speakerphoneButton.isSelected = !speakerphoneButton.isSelected
if let call = self.call {
callUIAdapter.toggleSpeakerphone(call: call, isEnabled: speakerphoneButton.isSelected)
callUIAdapter.setIsSpeakerphoneEnabled(call: call, isEnabled: speakerphoneButton.isSelected)
} else {
Logger.warn("\(TAG) pressed mute, but call was unexpectedly nil")
}
@ -624,9 +629,11 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
func didPressVideo(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
videoButton.isSelected = !videoButton.isSelected
let hasLocalVideo = !sender.isSelected
audioModeVideoButton.isSelected = hasLocalVideo
videoModeVideoButton.isSelected = hasLocalVideo
if let call = self.call {
callUIAdapter.setHasVideo(call: call, hasVideo: videoButton.isSelected)
callUIAdapter.setHasLocalVideo(call: call, hasLocalVideo: hasLocalVideo)
} else {
Logger.warn("\(TAG) pressed video, but call was unexpectedly nil")
}
@ -655,7 +662,7 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R
self.updateCallUI(callState: state)
}
internal func hasVideoDidChange(call: SignalCall, hasVideo: Bool) {
internal func hasLocalVideoDidChange(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
self.updateCallUI(callState: call.state)
}

Loading…
Cancel
Save