Refactor of CallKit

This commit is contained in:
Benjamin Reis 2017-01-30 15:04:05 +01:00
parent 8aca5a7e28
commit 50950337a7
7 changed files with 122 additions and 171 deletions

View file

@ -158,7 +158,8 @@ typedef struct _LinphoneManagerSounds {
+ (NSString*)cacheDirectory;
- (void)acceptCall:(LinphoneCall *)call evenWithVideo:(BOOL)video;
- (BOOL)call:(const LinphoneAddress *)address;
- (void)call:(const LinphoneAddress *)address;
- (BOOL)doCall:(const LinphoneAddress *)iaddr;
+(id)getMessageAppDataForKey:(NSString*)key inMessage:(LinphoneChatMessage*)msg;
+(void)setValueInMessageAppData:(id)value forKey:(NSString*)key inMessage:(LinphoneChatMessage*)msg;

View file

@ -237,7 +237,6 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
- (id)init {
if ((self = [super init])) {
AudioSessionInitialize(NULL, NULL, NULL, NULL);
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(audioRouteChangeListenerCallback:)
name:AVAudioSessionRouteChangeNotification
@ -2262,22 +2261,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
LinphoneCall *c = linphone_core_get_current_call(theLinphoneCore);
LOGI(@"Sound interruption detected!");
if (c && linphone_call_get_state(c) == LinphoneCallStreamsRunning) {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString
stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(c))]];
if (!uuid) {
linphone_core_pause_call(theLinphoneCore, c);
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:YES];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_pause_call(theLinphoneCore, c);
}
linphone_core_pause_call(theLinphoneCore, c);
}
}
@ -2452,7 +2436,25 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
linphone_core_accept_call_with_params(theLinphoneCore, call, lcallParams);
}
- (BOOL)call:(const LinphoneAddress *)iaddr {
- (void)call:(const LinphoneAddress *)iaddr {
if (linphone_core_get_calls_nb(theLinphoneCore) < 1 &&
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = [NSUUID UUID];
[LinphoneManager.instance.providerDelegate.uuids setObject:uuid forKey:@""];
LinphoneManager.instance.providerDelegate.pendingAddr = linphone_address_clone(iaddr);
NSString *address = [FastAddressBook displayNameForAddress:iaddr];
CXHandle *handle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:address];
CXStartCallAction *act = [[CXStartCallAction alloc] initWithCallUUID:uuid handle:handle];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
[self doCall:iaddr];
}
}
- (BOOL)doCall:(const LinphoneAddress *)iaddr {
// First verify that network is available, abort otherwise.
if (!linphone_core_is_network_reachable(theLinphoneCore)) {
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Network Error", nil)

View file

@ -82,22 +82,7 @@
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString stringWithUTF8String:linphone_call_log_get_call_id(
linphone_call_get_call_log(call))]];
if (!uuid) {
linphone_core_pause_call(LC, call);
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:YES];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_pause_call(LC, call);
}
linphone_core_pause_call(LC, call);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
@ -113,22 +98,7 @@
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString stringWithUTF8String:linphone_call_log_get_call_id(
linphone_call_get_call_log(currentCall))]];
if (!uuid) {
linphone_core_pause_call(LC, currentCall);
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:YES];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_pause_call(LC, currentCall);
}
linphone_core_pause_call(LC, currentCall);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
@ -141,22 +111,7 @@
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString stringWithUTF8String:linphone_call_log_get_call_id(
linphone_call_get_call_log(call))]];
if (!uuid) {
linphone_core_resume_call(LC, call);
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:NO];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_resume_call(LC, call);
}
linphone_core_resume_call(LC, call);
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
@ -164,11 +119,9 @@
}
case UIPauseButtonType_Conference: {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids allValues].firstObject;
NSString *key = (NSString *)[LinphoneManager.instance.providerDelegate.uuids allKeys][0];
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids objectForKey:key];
if (!uuid) {
linphone_core_enter_conference(LC);
// Fake event
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:NO];
@ -176,31 +129,15 @@
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_enter_conference(LC);
// Fake event
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
}
linphone_core_enter_conference(LC);
// Fake event
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
break;
}
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString stringWithUTF8String:linphone_call_log_get_call_id(
linphone_call_get_call_log(currentCall))]];
if (!uuid) {
linphone_core_resume_call(LC, currentCall);
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:NO];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_resume_call(LC, currentCall);
}
linphone_core_resume_call(LC, currentCall);
break;
}
}

View file

@ -19,7 +19,6 @@
#import <QuartzCore/QuartzCore.h>
#import <AudioToolbox/AudioServices.h>
#import "LinphoneAppDelegate.h"
#import "PhoneMainView.h"
@ -366,6 +365,7 @@ static RootViewManager *rootViewManagerInstance = nil;
}
case LinphoneCallError: {
[self displayCallError:call message:message];
break;
}
case LinphoneCallEnd: {
const MSList *calls = linphone_core_get_calls(LC);
@ -376,23 +376,7 @@ static RootViewManager *rootViewManagerInstance = nil;
[self popCurrentView];
}
} else {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString
stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(
(LinphoneCall *)calls->data))]];
if (!uuid) {
linphone_core_resume_call(LC, (LinphoneCall *)calls->data);
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:NO];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
} else {
linphone_core_resume_call(LC, (LinphoneCall *)calls->data);
}
linphone_core_resume_call(LC, (LinphoneCall *)calls->data);
[self changeCurrentView:CallView.compositeViewDescription];
}
break;
@ -405,20 +389,17 @@ static RootViewManager *rootViewManagerInstance = nil;
case LinphoneCallOutgoingProgress: {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call &&
(linphone_core_get_calls_nb(LC) < 2)) {
// Create CallKit Call
// Link call ID to UUID
NSString *callId =
[NSString stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(call))];
NSUUID *uuid = [NSUUID UUID];
[LinphoneManager.instance.providerDelegate.uuids setObject:uuid forKey:callId];
[LinphoneManager.instance.providerDelegate.calls setObject:callId forKey:uuid];
NSString *address = [FastAddressBook displayNameForAddress:linphone_call_get_remote_address(call)];
CXHandle *handle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:address];
CXStartCallAction *act = [[CXStartCallAction alloc] initWithCallUUID:uuid handle:handle];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
NSUUID *uuid = [LinphoneManager.instance.providerDelegate.uuids objectForKey:@""];
if (uuid) {
[LinphoneManager.instance.providerDelegate.uuids removeObjectForKey:@""];
[LinphoneManager.instance.providerDelegate.uuids setObject:uuid forKey:callId];
[LinphoneManager.instance.providerDelegate.calls setObject:callId forKey:uuid];
}
}
break;
}
case LinphoneCallOutgoingRinging: {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call) {
@ -440,12 +421,29 @@ static RootViewManager *rootViewManagerInstance = nil;
[LinphoneManager.instance.providerDelegate.provider reportCallWithUUID:uuid updated:update];
}
}
break;
}
case LinphoneCallPaused:
case LinphoneCallPausing:
case LinphoneCallRefered:
case LinphoneCallReleased:
case LinphoneCallResuming:
break;
case LinphoneCallResuming: {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids
objectForKey:[NSString stringWithUTF8String:linphone_call_log_get_call_id(
linphone_call_get_call_log(call))]];
if (!uuid) {
return;
}
CXSetHeldCallAction *act = [[CXSetHeldCallAction alloc] initWithCallUUID:uuid onHold:NO];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
}
break;
}
case LinphoneCallUpdating:
break;
}

View file

@ -18,9 +18,13 @@
@property CXCallController *controller;
@property NSMutableDictionary *calls;
@property NSMutableDictionary *uuids;
@property LinphoneCall *pendingCall;
@property LinphoneAddress *pendingAddr;
@property BOOL pendingCallVideo;
- (void)reportIncomingCallwithUUID:(NSUUID *)uuid handle:(NSString *)handle video:(BOOL)video;
- (void)config;
- (void)configAudioSession:(AVAudioSession *)audioSession;
@end
#endif /* ProviderDelegate_h */

View file

@ -19,7 +19,9 @@
self = [super init];
self.calls = [[NSMutableDictionary alloc] init];
self.uuids = [[NSMutableDictionary alloc] init];
self.pendingCall = NULL;
self.pendingAddr = NULL;
self.pendingCallVideo = FALSE;
CXCallController *callController = [[CXCallController alloc] initWithQueue:dispatch_get_main_queue()];
[callController.callObserver setDelegate:self queue:dispatch_get_main_queue()];
self.controller = callController;
@ -46,6 +48,13 @@
[self.provider setDelegate:self queue:dispatch_get_main_queue()];
}
- (void)configAudioSession:(AVAudioSession *)audioSession {
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setMode:AVAudioSessionModeVoiceChat error:nil];
double sampleRate = 44100.0;
[audioSession setPreferredSampleRate:sampleRate error:nil];
}
- (void)reportIncomingCallwithUUID:(NSUUID *)uuid handle:(NSString *)handle video:(BOOL)video {
// Create update to describe the incoming call and caller
CXCallUpdate *update = [[CXCallUpdate alloc] init];
@ -56,36 +65,11 @@
update.supportsUngrouping = TRUE;
update.hasVideo = video;
LOGD(@"configuring audio session");
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setMode:AVAudioSessionModeVoiceChat error:nil];
double sampleRate = 44100.0;
[audioSession setPreferredSampleRate:sampleRate error:nil];
NSTimeInterval bufferDuration = .005;
[audioSession setPreferredIOBufferDuration:bufferDuration error:nil];
LOGD(@"Activating audio session");
[audioSession setActive:TRUE error:nil];
// Report incoming call to system
LOGD(@"CallKit: report new incoming call");
[self.provider reportNewIncomingCallWithUUID:uuid
update:update
completion:^(NSError *error) {
LOGD(@"configuring audio session");
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setMode:AVAudioSessionModeVoiceChat error:nil];
double sampleRate = 44100.0;
[audioSession setPreferredSampleRate:sampleRate error:nil];
NSTimeInterval bufferDuration = .005;
[audioSession setPreferredIOBufferDuration:bufferDuration error:nil];
LOGD(@"Activating audio session");
[audioSession setActive:TRUE error:nil];
}];
}
@ -93,8 +77,9 @@
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
LOGD(@"CallKit : Answering Call");
NSUUID *uuid = action.callUUID;
[self configAudioSession:[AVAudioSession sharedInstance]];
[action fulfill];
NSUUID *uuid = action.callUUID;
NSString *callID = [self.calls objectForKey:uuid]; // first, make sure this callid is not already involved in a call
LinphoneCall *call = [LinphoneManager.instance callByCallId:callID];
@ -102,7 +87,8 @@
BOOL video = (!([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) &&
linphone_core_get_video_policy(LC)->automatically_accept &&
linphone_call_params_video_enabled(linphone_call_get_remote_params((LinphoneCall *)call)));
[LinphoneManager.instance acceptCall:(LinphoneCall *)call evenWithVideo:video];
self.pendingCall = call;
self.pendingCallVideo = video;
return;
};
}
@ -110,19 +96,25 @@
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
LOGD(@"CallKit : Starting Call");
// To restart Audio Unit
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setMode:AVAudioSessionModeVoiceChat error:nil];
double sampleRate = 44100.0;
[audioSession setPreferredSampleRate:sampleRate error:nil];
NSTimeInterval bufferDuration = .005;
[audioSession setPreferredIOBufferDuration:bufferDuration error:nil];
[audioSession setActive:TRUE error:nil];
[self configAudioSession:[AVAudioSession sharedInstance]];
[action fulfill];
NSUUID *uuid = action.callUUID;
NSString *callID = [self.calls objectForKey:uuid]; // first, make sure this callid is not already involved in a call
LinphoneCall *call;
if (![callID isEqualToString:@""]) {
call = linphone_core_get_current_call(LC);
} else {
call = [LinphoneManager.instance callByCallId:callID];
}
if (call != NULL) {
_pendingCall = call;
}
}
- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
LOGD(@"CallKit : Ending the Call");
[action fulfill];
if (linphone_core_is_in_conference(LC)) {
LinphoneManager.instance.conf = TRUE;
linphone_core_terminate_conference(LC);
@ -137,7 +129,6 @@
linphone_core_terminate_call(LC, (LinphoneCall *)call);
}
}
[action fulfill];
}
- (void)provider:(CXProvider *)provider performSetMutedCallAction:(nonnull CXSetMutedCallAction *)action {
@ -150,17 +141,7 @@
- (void)provider:(CXProvider *)provider performSetHeldCallAction:(nonnull CXSetHeldCallAction *)action {
LOGD(@"CallKit : Call paused status changed");
// To restart Audio Unit
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setMode:AVAudioSessionModeVoiceChat error:nil];
double sampleRate = 44100.0;
[audioSession setPreferredSampleRate:sampleRate error:nil];
NSTimeInterval bufferDuration = .005;
[audioSession setPreferredIOBufferDuration:bufferDuration error:nil];
[audioSession setActive:TRUE error:nil];
[action fulfill];
if (linphone_core_is_in_conference(LC) && action.isOnHold) {
linphone_core_leave_conference(LC);
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
@ -183,19 +164,20 @@
if (action.isOnHold) {
linphone_core_pause_call(LC, (LinphoneCall *)call);
} else {
[self configAudioSession:[AVAudioSession sharedInstance]];
if (linphone_core_get_conference(LC)) {
linphone_core_enter_conference(LC);
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
} else {
linphone_core_resume_call(LC, (LinphoneCall *)call);
_pendingCall = call;
}
}
}
}
- (void)provider:(CXProvider *)provider performPlayDTMFCallAction:(CXPlayDTMFCallAction *)action {
[action fulfill];
LOGD(@"CallKit : playing DTMF");
[action fulfill];
NSUUID *call_uuid = action.callUUID;
NSString *callID = [self.calls objectForKey:call_uuid];
LinphoneCall *call = [LinphoneManager.instance callByCallId:callID];
@ -205,6 +187,33 @@
- (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession {
LOGD(@"CallKit : Audio session activated");
// Now we can (re)start the call
if (_pendingCall) {
LinphoneCallState state = linphone_call_get_state(_pendingCall);
switch (state) {
case LinphoneCallIncomingReceived:
[LinphoneManager.instance acceptCall:(LinphoneCall *)_pendingCall evenWithVideo:_pendingCallVideo];
break;
case LinphoneCallPaused:
linphone_core_resume_call(LC, (LinphoneCall *)_pendingCall);
break;
case LinphoneCallStreamsRunning:
// May happen when multiple calls
break;
default:
break;
}
} else {
if (_pendingAddr) {
[LinphoneManager.instance doCall:_pendingAddr];
} else {
LOGE(@"CallKit : No pending call");
}
}
_pendingCall = NULL;
_pendingAddr = NULL;
_pendingCallVideo = FALSE;
}
- (void)provider:(CXProvider *)provider didDeactivateAudioSession:(nonnull AVAudioSession *)audioSession {

View file

@ -51,7 +51,7 @@ static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, con
UIAlertController *errView = [UIAlertController
alertControllerWithTitle:NSLocalizedString(@"File download error", nil)
message:NSLocalizedString(@"Error while downloading the file.\n"
@"The file is probably emcrypted.\n"
@"The file is probably encrypted.\n"
@"Please retry to download this file after activating LIME.",
nil)
preferredStyle:UIAlertControllerStyleAlert];