diff --git a/Classes/CallManager.swift b/Classes/CallManager.swift index 85739737b..72c4889e9 100644 --- a/Classes/CallManager.swift +++ b/Classes/CallManager.swift @@ -39,8 +39,6 @@ import AVFoundation let callController: CXCallController! // to support callkit var lc: Core? @objc var speakerBeforePause : Bool = false - @objc var speakerEnabled : Bool = false - @objc var bluetoothEnabled : Bool = false @objc var nextCallIsTransfer: Bool = false @objc var alreadyRegisteredForNotification: Bool = false var referedFromCall: String? @@ -126,26 +124,8 @@ import AVFoundation #endif return false } - /* - @objc func allowSpeaker() -> Bool { - if (UIDevice.current.userInterfaceIdiom == .pad) { - // For now, ipad support only speaker. - return true - } - return true - var allow = true - let newRoute = AVAudioSession.sharedInstance().currentRoute - if (newRoute.outputs.count > 0) { - let route = newRoute.outputs[0].portType - allow = !( route == .lineOut || route == .headphones || (AudioHelper.bluetoothRoutes() as Array).contains(where: {($0 as! AVAudioSession.Port) == route})) - } - - return allow - } - */ @objc func changeRouteToSpeaker() { - speakerEnabled = true for device in lc!.audioDevices { if (device.type == AudioDeviceType.Speaker) { lc!.outputAudioDevice = device @@ -153,46 +133,46 @@ import AVFoundation } } UIDevice.current.isProximityMonitoringEnabled = false - bluetoothEnabled = false } @objc func changeRouteToBluetooth() { - bluetoothEnabled = true for device in lc!.audioDevices { if (device.type == AudioDeviceType.Bluetooth || device.type == AudioDeviceType.BluetoothA2DP) { lc!.outputAudioDevice = device break } } - speakerEnabled = false UIDevice.current.isProximityMonitoringEnabled = (lc!.callsNb > 0) } @objc func changeRouteToDefault() { - bluetoothEnabled = false - speakerEnabled = false lc!.outputAudioDevice = lc!.defaultOutputAudioDevice } - /* - @objc func enableSpeaker(enable: Bool) { - speakerEnabled = enable - do { - if (enable && allowSpeaker()) { - try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker) - UIDevice.current.isProximityMonitoringEnabled = false - bluetoothEnabled = false - } else { - try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none) - let buildinPort = AudioHelper.builtinAudioDevice() - try AVAudioSession.sharedInstance().setPreferredInput(buildinPort) - UIDevice.current.isProximityMonitoringEnabled = (lc!.callsNb > 0) + @objc func isBluetoothAvailable() -> Bool { + for device in lc!.audioDevices { + if (device.type == AudioDeviceType.Bluetooth || device.type == AudioDeviceType.BluetoothA2DP) { + let name = device.deviceName + return true; } - } catch { - Log.directLog(BCTBX_LOG_ERROR, text: "Failed to change audio route: err \(error)") } + return false; } -*/ + + @objc func isSpeakerEnabled() -> Bool { + if let outputDevice = lc!.outputAudioDevice { + return outputDevice.type == AudioDeviceType.Speaker + } + return false + } + + @objc func isBluetoothEnabled() -> Bool { + if let outputDevice = lc!.outputAudioDevice { + return (outputDevice.type == AudioDeviceType.Bluetooth || outputDevice.type == AudioDeviceType.BluetoothA2DP) + } + return false + } + func requestTransaction(_ transaction: CXTransaction, action: String) { callController.request(transaction) { error in if let error = error { @@ -575,7 +555,7 @@ import AVFoundation // 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 + //CallManager.instance().bluetoothEnabled = false } if UIApplication.shared.applicationState != .active && (callLog == nil || callLog?.status == .Missed || callLog?.status == .Aborted || callLog?.status == .EarlyAborted) { @@ -636,7 +616,8 @@ import AVFoundation } if (cstate == .IncomingReceived || cstate == .OutgoingInit || cstate == .Connected || cstate == .StreamsRunning) { - if ((call.currentParams?.videoEnabled ?? false) && !CallManager.speaker_already_enabled && !CallManager.instance().bluetoothEnabled) { + // if ((call.currentParams?.videoEnabled ?? false) && !CallManager.speaker_already_enabled && !CallManager.instance().bluetoothEnabled) { + if ((call.currentParams?.videoEnabled ?? false) && !CallManager.speaker_already_enabled && !CallManager.instance().isBluetoothEnabled()) { CallManager.instance().changeRouteToSpeaker() CallManager.speaker_already_enabled = true } diff --git a/Classes/CallOutgoingView.m b/Classes/CallOutgoingView.m index 10555ad92..c5057377d 100644 --- a/Classes/CallOutgoingView.m +++ b/Classes/CallOutgoingView.m @@ -185,8 +185,8 @@ static UICompositeViewDescription *compositeDescription = nil; [_routesButton setOn]; } - _routesBluetoothButton.selected = CallManager.instance.bluetoothEnabled; - _routesSpeakerButton.selected = CallManager.instance.speakerEnabled; + _routesBluetoothButton.selected = [CallManager.instance isBluetoothEnabled]; + _routesSpeakerButton.selected = [CallManager.instance isSpeakerEnabled]; _routesEarpieceButton.selected = !_routesBluetoothButton.selected && !_routesSpeakerButton.selected; if (hidden != _routesView.hidden) { diff --git a/Classes/CallView.m b/Classes/CallView.m index 739e0abe1..bf38ef65f 100644 --- a/Classes/CallView.m +++ b/Classes/CallView.m @@ -493,8 +493,8 @@ static void hideSpinner(LinphoneCall *call, void *user_data) { [_routesButton setOn]; } - _routesBluetoothButton.selected = CallManager.instance.bluetoothEnabled; - _routesSpeakerButton.selected = CallManager.instance.speakerEnabled; + _routesBluetoothButton.selected = [CallManager.instance isBluetoothEnabled]; + _routesSpeakerButton.selected = [CallManager.instance isSpeakerEnabled]; _routesEarpieceButton.selected = !_routesBluetoothButton.selected && !_routesSpeakerButton.selected; if (hidden != _routesView.hidden) { diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index 98e4856c4..3244079c2 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -190,7 +190,6 @@ typedef struct _LinphoneManagerSounds { - (void)migrationPerAccount; - (void)setupGSMInteraction; -//- (void)setBluetoothEnabled:(BOOL)enable; - (BOOL)isCTCallCenterExist; @property (readonly) BOOL isTesting; diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 1eeccefbc..d2ac42af7 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -1732,58 +1732,15 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) { if (IPAD) return; - // there is at least one bug when you disconnect an audio bluetooth headset - // since we only get notification of route having changed, we cannot tell if that is due to: - // -bluetooth headset disconnected or - // -user wanted to use earpiece - // the only thing we can assume is that when we lost a device, it must be a bluetooth one (strong hypothesis though) - if ([[notif.userInfo valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue] == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) - _bluetoothAvailable = NO; - - AVAudioSessionRouteDescription *newRoute = [AVAudioSession sharedInstance].currentRoute; - - if (newRoute && newRoute.outputs.count > 0) { - NSString *route = newRoute.outputs[0].portType; - LOGI(@"Current audio route is [%s]", [route UTF8String]); - linphone_core_audio_route_changed(theLinphoneCore); - - CallManager.instance.speakerEnabled = [route isEqualToString:AVAudioSessionPortBuiltInSpeaker]; - if (([[AudioHelper bluetoothRoutes] containsObject:route]) && !CallManager.instance.speakerEnabled) { - _bluetoothAvailable = TRUE; - CallManager.instance.bluetoothEnabled = TRUE; - } else - CallManager.instance.bluetoothEnabled = FALSE; - - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:_bluetoothAvailable], @"available", nil]; - [NSNotificationCenter.defaultCenter postNotificationName:kLinphoneBluetoothAvailabilityUpdate - object:self - userInfo:dict]; - } + _bluetoothAvailable = [CallManager.instance isBluetoothAvailable]; + + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:_bluetoothAvailable], @"available", nil]; + [NSNotificationCenter.defaultCenter postNotificationName:kLinphoneBluetoothAvailabilityUpdate + object:self + userInfo:dict]; + } -/* -- (void)setBluetoothEnabled:(BOOL)enable { - if (_bluetoothAvailable) { - // The change of route will be done in enableSpeaker - CallManager.instance.bluetoothEnabled = enable; - if (CallManager.instance.bluetoothEnabled) { - NSError *err = nil; - AVAudioSessionPortDescription *_bluetoothPort = [AudioHelper bluetoothAudioDevice]; - [[AVAudioSession sharedInstance] setPreferredInput:_bluetoothPort error:&err]; - // if setting bluetooth failed, it must be because the device is not available - // anymore (disconnected), so deactivate bluetooth. - if (err) { - CallManager.instance.bluetoothEnabled = FALSE; - LOGE(@"Failed to enable bluetooth: err %@", err.localizedDescription); - err = nil; - } else { - CallManager.instance.speakerEnabled = FALSE; - return; - } - } - } - [CallManager.instance enableSpeakerWithEnable:CallManager.instance.speakerEnabled]; -} -*/ + #pragma mark - Call Functions - (void)send:(NSString *)replyText toChatRoom:(LinphoneChatRoom *)room { LinphoneChatMessage *msg = linphone_chat_room_create_message(room, replyText.UTF8String); @@ -2108,7 +2065,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) { if ([ct currentCalls] != nil) { if (call) { LOGI(@"Pausing SIP call because GSM call"); - CallManager.instance.speakerBeforePause = CallManager.instance.speakerEnabled; + CallManager.instance.speakerBeforePause = [CallManager.instance isSpeakerEnabled]; linphone_call_pause(call); [self startCallPausedLongRunningTask]; } else if (linphone_core_is_in_conference(theLinphoneCore)) { diff --git a/Classes/LinphoneUI/UIPauseButton.m b/Classes/LinphoneUI/UIPauseButton.m index 261352c9b..a6ea08d7c 100644 --- a/Classes/LinphoneUI/UIPauseButton.m +++ b/Classes/LinphoneUI/UIPauseButton.m @@ -85,7 +85,7 @@ if ([CallManager callKitEnabled]) { [CallManager.instance setHeldWithCall:call hold:true]; } else { - CallManager.instance.speakerBeforePause = CallManager.instance.speakerEnabled; + CallManager.instance.speakerBeforePause = [CallManager.instance isSpeakerEnabled]; linphone_call_pause(call); } } else { @@ -106,7 +106,7 @@ if ([CallManager callKitEnabled]) { [CallManager.instance setHeldWithCall:currentCall hold:true]; } else { - CallManager.instance.speakerBeforePause = CallManager.instance.speakerEnabled; + CallManager.instance.speakerBeforePause = [CallManager.instance isSpeakerEnabled]; linphone_call_pause(currentCall); } } else { diff --git a/Classes/LinphoneUI/UISpeakerButton.m b/Classes/LinphoneUI/UISpeakerButton.m index 8ba12c8de..64c12d5b9 100644 --- a/Classes/LinphoneUI/UISpeakerButton.m +++ b/Classes/LinphoneUI/UISpeakerButton.m @@ -34,6 +34,15 @@ INIT_WITH_COMMON_CF { return self; } +- (void)onOn { + [CallManager.instance changeRouteToSpeaker]; +} + +- (void)onOff { + [CallManager.instance changeRouteToDefault]; +} + + - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } @@ -46,7 +55,7 @@ INIT_WITH_COMMON_CF { } - (bool)onUpdate { - return CallManager.instance.speakerEnabled; + return [CallManager.instance isSpeakerEnabled]; } @end diff --git a/Classes/PhoneMainView.m b/Classes/PhoneMainView.m index 4205e0eb3..7a74d0175 100644 --- a/Classes/PhoneMainView.m +++ b/Classes/PhoneMainView.m @@ -381,7 +381,7 @@ static RootViewManager *rootViewManagerInstance = nil; if (![LinphoneManager.instance isCTCallCenterExist]) { /*only register CT call center CB for connected call*/ [LinphoneManager.instance setupGSMInteraction]; - [[UIDevice currentDevice] setProximityMonitoringEnabled:!(CallManager.instance.speakerEnabled || CallManager.instance.bluetoothEnabled)]; + [[UIDevice currentDevice] setProximityMonitoringEnabled:!([CallManager.instance isSpeakerEnabled] || [CallManager.instance isBluetoothEnabled])]; } break; } diff --git a/Classes/ProviderDelegate.swift b/Classes/ProviderDelegate.swift index 81ada38b4..6526aec00 100644 --- a/Classes/ProviderDelegate.swift +++ b/Classes/ProviderDelegate.swift @@ -205,7 +205,7 @@ extension ProviderDelegate: CXProviderDelegate { if (call!.params?.localConferenceMode ?? false) { return } - CallManager.instance().speakerBeforePause = CallManager.instance().speakerEnabled + CallManager.instance().speakerBeforePause = CallManager.instance().isSpeakerEnabled() try call!.pause() } else { if (call?.conference != nil && CallManager.instance().lc?.callsNb ?? 0 > 1) {