diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index 4e7cb15c4..5a9d5491d 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -90,7 +90,7 @@ typedef struct _LinphoneManagerSounds { BOOL stopWaitingRegisters; UIBackgroundTaskIdentifier pausedCallBgTask; UIBackgroundTaskIdentifier incallBgTask; - CTCallCenter* callCenter; + CTCallCenter* mCallCenter; @public CallContext currentCallContextBeforeGoingBackground; diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 02ab35476..e3c461ac6 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -387,70 +387,73 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char } - if (state == LinphoneCallIncomingReceived - &&[[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] - && [UIApplication sharedApplication].applicationState != UIApplicationStateActive) { + if (state == LinphoneCallIncomingReceived) { /*first step is to re-enable ctcall center*/ - [self setupGSMInteraction]; + CTCallCenter* lCTCallCenter = [[CTCallCenter alloc] init]; /*should we reject this call ?*/ - if ([callCenter currentCalls]!=nil) { + if ([lCTCallCenter currentCalls]!=nil) { [LinphoneLogger logc:LinphoneLoggerLog format:"Mobile call ongoing... rejecting call from [%s]",linphone_address_get_username(linphone_call_get_call_log(call)->from)]; linphone_core_decline_call([LinphoneManager getLc], call,LinphoneReasonBusy); + [lCTCallCenter release]; return; } + [lCTCallCenter release]; - - LinphoneCallLog* callLog=linphone_call_get_call_log(call); - NSString* callId=[NSString stringWithUTF8String:callLog->call_id]; - const LinphoneAddress *addr = linphone_call_get_remote_address(call); - NSString* address = nil; - if(addr != NULL) { - BOOL useLinphoneAddress = true; - // contact name - char* lAddress = linphone_address_as_string_uri_only(addr); - if(lAddress) { - NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]]; - ABRecordRef contact = [fastAddressBook getContact:normalizedSipAddress]; - if(contact) { - address = [FastAddressBook getContactDisplayName:contact]; - useLinphoneAddress = false; - } - ms_free(lAddress); - } - if(useLinphoneAddress) { - const char* lDisplayName = linphone_address_get_display_name(addr); - const char* lUserName = linphone_address_get_username(addr); - if (lDisplayName) - address = [NSString stringWithUTF8String:lDisplayName]; - else if(lUserName) - address = [NSString stringWithUTF8String:lUserName]; - } - } - if(address == nil) { - address = @"Unknown"; - } - - if (![[LinphoneManager instance] shouldAutoAcceptCallForCallId:callId]){ - // case where a remote notification is not already received - // Create a new local notification - data->notification = [[UILocalNotification alloc] init]; - if (data->notification) { - data->notification.repeatInterval = 0; - data->notification.alertBody =[NSString stringWithFormat:NSLocalizedString(@"IC_MSG",nil), address]; - data->notification.alertAction = NSLocalizedString(@"Answer", nil); - data->notification.soundName = @"ring.caf"; - data->notification.userInfo = [NSDictionary dictionaryWithObject:callId forKey:@"callId"]; - - [[UIApplication sharedApplication] presentLocalNotificationNow:data->notification]; - - if (!incallBgTask){ - incallBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ - [LinphoneLogger log:LinphoneLoggerWarning format:@"Call cannot ring any more, too late"]; - }]; + if( [[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] + && [UIApplication sharedApplication].applicationState != UIApplicationStateActive) { + + LinphoneCallLog* callLog=linphone_call_get_call_log(call); + NSString* callId=[NSString stringWithUTF8String:callLog->call_id]; + const LinphoneAddress *addr = linphone_call_get_remote_address(call); + NSString* address = nil; + if(addr != NULL) { + BOOL useLinphoneAddress = true; + // contact name + char* lAddress = linphone_address_as_string_uri_only(addr); + if(lAddress) { + NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]]; + ABRecordRef contact = [fastAddressBook getContact:normalizedSipAddress]; + if(contact) { + address = [FastAddressBook getContactDisplayName:contact]; + useLinphoneAddress = false; + } + ms_free(lAddress); + } + if(useLinphoneAddress) { + const char* lDisplayName = linphone_address_get_display_name(addr); + const char* lUserName = linphone_address_get_username(addr); + if (lDisplayName) + address = [NSString stringWithUTF8String:lDisplayName]; + else if(lUserName) + address = [NSString stringWithUTF8String:lUserName]; + } + } + if(address == nil) { + address = @"Unknown"; + } + + if (![[LinphoneManager instance] shouldAutoAcceptCallForCallId:callId]){ + // case where a remote notification is not already received + // Create a new local notification + data->notification = [[UILocalNotification alloc] init]; + if (data->notification) { + data->notification.repeatInterval = 0; + data->notification.alertBody =[NSString stringWithFormat:NSLocalizedString(@"IC_MSG",nil), address]; + data->notification.alertAction = NSLocalizedString(@"Answer", nil); + data->notification.soundName = @"ring.caf"; + data->notification.userInfo = [NSDictionary dictionaryWithObject:callId forKey:@"callId"]; + + [[UIApplication sharedApplication] presentLocalNotificationNow:data->notification]; + + if (!incallBgTask){ + incallBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ + [LinphoneLogger log:LinphoneLoggerWarning format:@"Call cannot ring any more, too late"]; + }]; + } + } - } } } @@ -466,8 +469,10 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char // Disable speaker when no more call if ((state == LinphoneCallEnd || state == LinphoneCallError)) { - if(linphone_core_get_calls_nb([LinphoneManager getLc]) == 0) + if(linphone_core_get_calls_nb([LinphoneManager getLc]) == 0) { [self setSpeakerEnabled:FALSE]; + [self removeCTCallCenterCb]; + } if (incallBgTask) { [[UIApplication sharedApplication] endBackgroundTask:incallBgTask]; incallBgTask=0; @@ -483,7 +488,10 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char [self setSpeakerEnabled:TRUE]; } } - + if (state == LinphoneCallConnected && !mCallCenter) { + /*only register CT call center CB for connected call*/ + [self setupGSMInteraction]; + } // Post event NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSValue valueWithPointer:call], @"call", @@ -754,7 +762,6 @@ static LinphoneCoreVTable linphonec_vtable = { #if HAVE_G729 libmsbcg729_init(); // load g729 plugin #endif - [self setupGSMInteraction]; /* Initialize linphone core*/ /*to make sure we don't loose debug trace*/ @@ -861,13 +868,8 @@ static LinphoneCoreVTable linphonec_vtable = { - (void)destroyLibLinphone { [mIterateTimer invalidate]; - // destroying eventHandler if app cannot go in background. - // Otherwise if a GSM call happen and Linphone is resumed, - // the handler will be called before LinphoneCore is built. - // Then handler will be restored in appDidBecomeActive cb - callCenter.callEventHandler = nil; - [callCenter release]; - callCenter = nil; + //just in case + [self removeCTCallCenterCb]; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setDelegate:nil]; @@ -958,6 +960,13 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) return linphone_call_get_state(call) != LinphoneCallPaused; } +- (void) startCallPausedLongRunningTask { + pausedCallBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ + [LinphoneLogger log:LinphoneLoggerWarning format:@"Call cannot be paused any more, too late"]; + }]; + [LinphoneLogger log:LinphoneLoggerLog format:@"Long running task started, remaining [%g s] because at least one call is paused" + ,[[UIApplication sharedApplication] backgroundTimeRemaining]]; +} - (BOOL)enterBackgroundMode { LinphoneProxyConfig* proxyCfg; linphone_core_get_default_proxy(theLinphoneCore, &proxyCfg); @@ -985,13 +994,6 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) return; } //kick up network cnx, just in case - [LinphoneManager kickOffNetworkConnection]; - - [self setupGSMInteraction]; - //to make sure presence status is correct - if ([callCenter currentCalls]==nil) - linphone_core_set_presence_info(theLinphoneCore, 0, nil, LinphoneStatusAltService); - [self refreshRegisters]; linphone_core_iterate(theLinphoneCore); } @@ -1007,13 +1009,8 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) if (!currentCall //no active call && callList // at least one call in a non active state && ms_list_find_custom((MSList*)callList, (MSCompareFunc) comp_call_state_paused, NULL)) { - pausedCallBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ - [LinphoneLogger log:LinphoneLoggerWarning format:@"Call cannot be paused any more, too late"]; - }]; - [LinphoneLogger log:LinphoneLoggerLog format:@"Long running task started, remaining [%fs] because at least one call is paused" - ,[[UIApplication sharedApplication] backgroundTimeRemaining]]; + [self startCallPausedLongRunningTask]; } - return YES; } else { @@ -1037,14 +1034,6 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) /*IOS specific*/ linphone_core_start_dtmf_stream(theLinphoneCore); - - //call center is unrelialable on the long run, so we change it each time the application is resumed. To avoid zombie GSM call - [self setupGSMInteraction]; - - //to make sure presence status is correct - if ([callCenter currentCalls]==nil) - linphone_core_set_presence_info(theLinphoneCore, 0, nil, LinphoneStatusAltService); - } @@ -1132,7 +1121,7 @@ static void audioRouteChangeListenerCallback ( return; } - + CTCallCenter* callCenter = [[CTCallCenter alloc] init]; if ([callCenter currentCalls]!=nil) { [LinphoneLogger logc:LinphoneLoggerError format:"GSM call in progress, cancelling outgoing SIP call request"]; UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Cannot make call",nil) @@ -1142,9 +1131,11 @@ static void audioRouteChangeListenerCallback ( otherButtonTitles:nil]; [error show]; [error release]; + [callCenter release]; return; } - + [callCenter release]; + LinphoneProxyConfig* proxyCfg; //get default proxy linphone_core_get_default_proxy([LinphoneManager getLc],&proxyCfg); @@ -1340,18 +1331,24 @@ static void audioRouteChangeListenerCallback ( } #pragma GSM management +-(void) removeCTCallCenterCb { + if (mCallCenter != nil) { + [LinphoneLogger log:LinphoneLoggerLog format:@"Removing CT call center listener [%p]",mCallCenter]; + mCallCenter.callEventHandler=NULL; + [mCallCenter release]; + } + mCallCenter=nil; +} - (void)setupGSMInteraction { - if (callCenter != nil) { - callCenter.callEventHandler=NULL; - [callCenter release]; - } - callCenter = [[CTCallCenter alloc] init]; - callCenter.callEventHandler = ^(CTCall* call) { + [self removeCTCallCenterCb]; + mCallCenter = [[CTCallCenter alloc] init]; + [LinphoneLogger log:LinphoneLoggerLog format:@"Adding CT call center listener [%p]",mCallCenter]; + mCallCenter.callEventHandler = ^(CTCall* call) { // post on main thread [self performSelectorOnMainThread:@selector(handleGSMCallInteration:) - withObject:callCenter + withObject:mCallCenter waitUntilDone:YES]; }; @@ -1362,12 +1359,15 @@ static void audioRouteChangeListenerCallback ( /* pause current call, if any */ LinphoneCall* call = linphone_core_get_current_call(theLinphoneCore); if ([ct currentCalls]!=nil) { - if (call) {[LinphoneLogger logc:LinphoneLoggerLog format:"Pausing SIP call"]; + if (call) { + [LinphoneLogger log:LinphoneLoggerLog format:@"Pausing SIP call because GSM call"]; linphone_core_pause_call(theLinphoneCore, call); + [self startCallPausedLongRunningTask]; + } else if (linphone_core_is_in_conference(theLinphoneCore)) { + [LinphoneLogger log:LinphoneLoggerLog format:@"Leaving conference call because GSM call"]; + linphone_core_leave_conference(theLinphoneCore); + [self startCallPausedLongRunningTask]; } - //set current status to busy - linphone_core_set_presence_info(theLinphoneCore, 0, nil, LinphoneStatusBusy); - } else - linphone_core_set_presence_info(theLinphoneCore, 0, nil, LinphoneStatusAltService); + } //else nop, keep call in paused state } @end