support of CallKit for one call

This commit is contained in:
Benjamin Reis 2016-12-14 16:29:02 +01:00
parent 351ef54d0d
commit cd93c10576
15 changed files with 964 additions and 263 deletions

View file

@ -821,7 +821,8 @@ static UICompositeViewDescription *compositeDescription = nil;
return NSLocalizedString(@"Unknown error, please try again later.", nil);
}
- (void)showErrorPopup:(const char *)err {
- (void)showErrorPopup:(const char *)error {
const char *err = error ? error : "";
if (strcmp(err, "ERROR_BAD_CREDENTIALS") == 0) {
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Registration failure", nil)
message:[AssistantView StringForXMLRPCError:err]

View file

@ -119,7 +119,19 @@ static UICompositeViewDescription *compositeDescription = nil;
- (IBAction)onDeclineClick:(id)sender {
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call) {
/*if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = [LinphoneManager.instance.providerDelegate.uuids objectForKey:[NSString
stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(call))]];
if(!uuid) {
linphone_core_terminate_call(LC, call);
return;
}
CXEndCallAction *act = [[CXEndCallAction alloc] initWithCallUUID:uuid];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr completion:^(NSError *err){}];
} else {*/
linphone_core_terminate_call(LC, call);
//}
}
}

View file

@ -17,12 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <AudioToolbox/AudioToolbox.h>
#import <AddressBook/AddressBook.h>
#import <QuartzCore/CAAnimation.h>
#import <QuartzCore/QuartzCore.h>
#import <AudioToolbox/AudioToolbox.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/EAGLDrawable.h>
#import <QuartzCore/CAAnimation.h>
#import <QuartzCore/QuartzCore.h>
#import <UserNotifications/UserNotifications.h>
#import "CallView.h"
#import "CallSideMenuView.h"
@ -150,7 +151,6 @@ static UICompositeViewDescription *compositeDescription = nil;
linphone_core_set_native_preview_window_id(LC, (__bridge void *)(_videoPreview));
[self previewTouchLift];
// Enable tap
[singleFingerTap setEnabled:TRUE];
@ -563,9 +563,11 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
const LinphoneCallParams *remote = linphone_call_get_remote_params(call);
/* remote wants to add video */
if (linphone_core_video_display_enabled(LC) && !linphone_call_params_video_enabled(current) &&
linphone_call_params_video_enabled(remote) &&
!linphone_core_get_video_policy(LC)->automatically_accept) {
if ((linphone_core_video_display_enabled(LC) && !linphone_call_params_video_enabled(current) &&
linphone_call_params_video_enabled(remote)) &&
(!linphone_core_get_video_policy(LC)->automatically_accept ||
(([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) &&
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max))) {
linphone_core_defer_call_update(LC, call);
[self displayAskToEnableVideoCall:call];
} else if (linphone_call_params_video_enabled(current) && !linphone_call_params_video_enabled(remote)) {
@ -593,41 +595,61 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
#pragma mark - ActionSheet Functions
- (void)displayAskToEnableVideoCall:(LinphoneCall *)call {
if (linphone_core_get_video_policy(LC)->automatically_accept)
if (linphone_core_get_video_policy(LC)->automatically_accept &&
!([UIApplication sharedApplication].applicationState == UIApplicationStateBackground))
return;
NSString *username = [FastAddressBook displayNameForAddress:linphone_call_get_remote_address(call)];
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"%@ would like to enable video", nil), username];
UIConfirmationDialog *sheet = [UIConfirmationDialog ShowWithMessage:title
cancelMessage:nil
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
onCancelClick:^() {
LOGI(@"User declined video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC,call);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
[videoDismissTimer invalidate];
videoDismissTimer = nil;
}
}
onConfirmationClick:^() {
LOGI(@"User accept video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC,call);
linphone_call_params_enable_video(params, TRUE);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
[videoDismissTimer invalidate];
videoDismissTimer = nil;
}
}
inController:self];
videoDismissTimer = [NSTimer scheduledTimerWithTimeInterval:30
target:self
selector:@selector(dismissVideoActionSheet:)
userInfo:sheet
repeats:NO];
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground &&
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"Video request", nil);
content.body = title;
content.categoryIdentifier = @"video_request";
UNNotificationRequest *req =
[UNNotificationRequest requestWithIdentifier:@"video_request" content:content trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:req
withCompletionHandler:^(NSError *_Nullable error) {
// Enable or disable features based on authorization.
if (error) {
LOGD(@"Error while adding notification request :");
LOGD(error.description);
}
}];
} else {
UIConfirmationDialog *sheet = [UIConfirmationDialog ShowWithMessage:title
cancelMessage:nil
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
onCancelClick:^() {
LOGI(@"User declined video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
[videoDismissTimer invalidate];
videoDismissTimer = nil;
}
}
onConfirmationClick:^() {
LOGI(@"User accept video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_call_params_enable_video(params, TRUE);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
[videoDismissTimer invalidate];
videoDismissTimer = nil;
}
}
inController:self];
videoDismissTimer = [NSTimer scheduledTimerWithTimeInterval:30
target:self
selector:@selector(dismissVideoActionSheet:)
userInfo:sheet
repeats:NO];
}
}
- (void)dismissVideoActionSheet:(NSTimer *)timer {

View file

@ -22,6 +22,7 @@
#import <AddressBookUI/ABPeoplePickerNavigationController.h>
#import "LinphoneCoreSettingsStore.h"
#import "ProviderDelegate.h"
#import <UserNotifications/UserNotifications.h>
#import <UserNotificationsUI/UserNotificationsUI.h>
@ -31,14 +32,13 @@
BOOL startedInBackground;
}
- (void)processRemoteNotification:(NSDictionary*)userInfo;
- (void)registerForNotifications:(UIApplication *)app;
@property (nonatomic, retain) UIAlertController *waitingIndicator;
@property (nonatomic, retain) NSString *configURL;
@property (nonatomic, strong) UIWindow* window;
@property PKPushRegistry* voipRegistry;
@property ProviderDelegate *del;
@end

View file

@ -45,6 +45,7 @@
startedInBackground = FALSE;
}
return self;
[[UIApplication sharedApplication] setDelegate:self];
}
#pragma mark -
@ -113,7 +114,9 @@
}
instance->currentCallContextBeforeGoingBackground.call = 0;
} else if (linphone_call_get_state(call) == LinphoneCallIncomingReceived) {
[PhoneMainView.instance displayIncomingCall:call];
if (linphone_core_get_calls_nb(LC) > 1) {
[PhoneMainView.instance displayIncomingCall:call];
}
// in this case, the ringing sound comes from the notification.
// To stop it we have to do the iOS7 ring fix...
[self fixRing];
@ -200,25 +203,71 @@
- (void)registerForNotifications:(UIApplication *)app {
LinphoneManager *instance = [LinphoneManager instance];
if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) {
//[app unregisterForRemoteNotifications];
// iOS8 and more : PushKit
self.voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
self.voipRegistry.delegate = self;
// Initiate registration.
self.voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
} else {
/* iOS7 and below */
if (!instance.isTesting) {
NSUInteger notifTypes =
UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge;
[app registerForRemoteNotificationTypes:notifTypes];
}
}
self.voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
self.voipRegistry.delegate = self;
// Initiate registration.
self.voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
// Call category
UNNotificationAction *act_ans =
[UNNotificationAction actionWithIdentifier:@"Answer"
title:NSLocalizedString(@"Answer", nil)
options:UNNotificationActionOptionForeground];
UNNotificationAction *act_dec = [UNNotificationAction actionWithIdentifier:@"Decline"
title:NSLocalizedString(@"Decline", nil)
options:UNNotificationActionOptionNone];
UNNotificationCategory *cat_call =
[UNNotificationCategory categoryWithIdentifier:@"call_cat"
actions:[NSArray arrayWithObjects:act_ans, act_dec, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
// Msg category
UNTextInputNotificationAction *act_reply =
[UNTextInputNotificationAction actionWithIdentifier:@"Reply"
title:NSLocalizedString(@"Reply", nil)
options:UNNotificationActionOptionNone];
UNNotificationAction *act_seen =
[UNNotificationAction actionWithIdentifier:@"Seen"
title:NSLocalizedString(@"Mark as seen", nil)
options:UNNotificationActionOptionNone];
UNNotificationCategory *cat_msg =
[UNNotificationCategory categoryWithIdentifier:@"msg_cat"
actions:[NSArray arrayWithObjects:act_reply, act_seen, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
// Video Request Category
UNNotificationAction *act_accept =
[UNNotificationAction actionWithIdentifier:@"Accept"
title:NSLocalizedString(@"Accept", nil)
options:UNNotificationActionOptionForeground];
UNNotificationAction *act_refuse = [UNNotificationAction actionWithIdentifier:@"Cancel"
title:NSLocalizedString(@"Cancel", nil)
options:UNNotificationActionOptionNone];
UNNotificationCategory *video_call =
[UNNotificationCategory categoryWithIdentifier:@"video_request"
actions:[NSArray arrayWithObjects:act_accept, act_refuse, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
// ZRTP verification category
UNNotificationAction *act_confirm = [UNNotificationAction actionWithIdentifier:@"Confirm"
title:NSLocalizedString(@"Accept", nil)
options:UNNotificationActionOptionNone];
UNNotificationAction *act_deny = [UNNotificationAction actionWithIdentifier:@"Deny"
title:NSLocalizedString(@"Deny", nil)
options:UNNotificationActionOptionNone];
UNNotificationCategory *cat_zrtp =
[UNNotificationCategory categoryWithIdentifier:@"zrtp_request"
actions:[NSArray arrayWithObjects:act_confirm, act_deny, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound |
@ -229,6 +278,8 @@
LOGD(error.description);
}
}];
NSSet *categories = [NSSet setWithObjects:cat_call, cat_msg, video_call, cat_zrtp, nil];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories];
}
}
#pragma deploymate pop
@ -242,6 +293,11 @@
BOOL start_at_boot = [instance lpConfigBoolForKey:@"start_at_boot_preference"];
[self registerForNotifications:app];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
self.del = [[ProviderDelegate alloc] init];
[LinphoneManager.instance setProviderDelegate:self.del];
}
if (state == UIApplicationStateBackground) {
// we've been woken up directly to background;
if (!start_at_boot || !background_mode) {
@ -264,14 +320,6 @@
[PhoneMainView.instance startUp];
[PhoneMainView.instance updateStatusBar:nil];
if (floor(NSFoundationVersionNumber) < NSFoundationVersionNumber_iOS_8_0) {
NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotif) {
LOGI(@"PushNotification from launch received.");
[self processRemoteNotification:remoteNotif];
}
}
if (bgStartId != UIBackgroundTaskInvalid)
[[UIApplication sharedApplication] endBackgroundTask:bgStartId];
@ -290,7 +338,7 @@
- (void)applicationWillTerminate:(UIApplication *)application {
LOGI(@"%@", NSStringFromSelector(_cmd));
LinphoneManager.instance.conf = TRUE;
linphone_core_terminate_all_calls(LC);
// destroyLinphoneCore automatically unregister proxies but if we are using
@ -536,8 +584,7 @@ didInvalidatePushTokenForType:(NSString *)type {
forType:(NSString *)type {
LOGI(@"PushKit : incoming voip notfication: %@", payload.dictionaryPayload);
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
// Call category
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) { // Call category
UNNotificationAction *act_ans =
[UNNotificationAction actionWithIdentifier:@"Answer"
title:NSLocalizedString(@"Answer", nil)
@ -550,7 +597,6 @@ didInvalidatePushTokenForType:(NSString *)type {
actions:[NSArray arrayWithObjects:act_ans, act_dec, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
// Msg category
UNTextInputNotificationAction *act_reply =
[UNTextInputNotificationAction actionWithIdentifier:@"Reply"
@ -566,6 +612,35 @@ didInvalidatePushTokenForType:(NSString *)type {
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
// Video Request Category
UNNotificationAction *act_accept =
[UNNotificationAction actionWithIdentifier:@"Accept"
title:NSLocalizedString(@"Accept", nil)
options:UNNotificationActionOptionForeground];
UNNotificationAction *act_refuse = [UNNotificationAction actionWithIdentifier:@"Cancel"
title:NSLocalizedString(@"Cancel", nil)
options:UNNotificationActionOptionNone];
UNNotificationCategory *video_call =
[UNNotificationCategory categoryWithIdentifier:@"video_request"
actions:[NSArray arrayWithObjects:act_accept, act_refuse, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
// ZRTP verification category
UNNotificationAction *act_confirm = [UNNotificationAction actionWithIdentifier:@"Confirm"
title:NSLocalizedString(@"Accept", nil)
options:UNNotificationActionOptionNone];
UNNotificationAction *act_deny = [UNNotificationAction actionWithIdentifier:@"Deny"
title:NSLocalizedString(@"Deny", nil)
options:UNNotificationActionOptionNone];
UNNotificationCategory *cat_zrtp =
[UNNotificationCategory categoryWithIdentifier:@"zrtp_request"
actions:[NSArray arrayWithObjects:act_confirm, act_deny, nil]
intentIdentifiers:[[NSMutableArray alloc] init]
options:UNNotificationCategoryOptionCustomDismissAction];
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound |
@ -576,7 +651,7 @@ didInvalidatePushTokenForType:(NSString *)type {
LOGD(error.description);
}
}];
NSSet *categories = [NSSet setWithObjects:cat_call, cat_msg, nil];
NSSet *categories = [NSSet setWithObjects:cat_call, cat_msg, video_call, cat_zrtp, nil];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories];
}
[LinphoneManager.instance setupNetworkReachabilityCallback];
@ -590,44 +665,45 @@ didInvalidatePushTokenForType:(NSString *)type {
forType:(NSString *)type {
LOGI(@"PushKit credentials updated");
LOGI(@"voip token: %@", (credentials.token));
LOGI(@"%@ : %@", NSStringFromSelector(_cmd), credentials.token);
dispatch_async(dispatch_get_main_queue(), ^{[LinphoneManager.instance setPushNotificationToken:credentials.token];});
}
#pragma mark - UserNotifications Framework
#pragma mark - UNUserNotifications Framework
- (void) userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionAlert);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
LOGD(@"UN : response recieved");
LOGD(response.description);
LinphoneCall* call = linphone_core_get_current_call(LC);
if (call) {
LinphoneCallAppData *data = (__bridge LinphoneCallAppData *)linphone_call_get_user_data(call);
if (data->timer) {
[data->timer invalidate];
data->timer = nil;
}
}
if ([response.actionIdentifier isEqual:@"Answer"]) {
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
[LinphoneManager.instance acceptCallForCallId:[response.notification.request.content.userInfo objectForKey:@"callId"]];
} else if ([response.actionIdentifier isEqual:@"Decline"]) {
linphone_core_decline_call(LC, call, LinphoneReasonDeclined);
} else if ([response.actionIdentifier isEqual:@"Reply"]) {
LinphoneCore *lc = [LinphoneManager getLc];
NSString *replyText = [(UNTextInputNotificationResponse*)response userText];
NSString *from = [response.notification.request.content.userInfo objectForKey:@"from_addr"];
LinphoneChatRoom *room = linphone_core_get_chat_room_from_uri(lc, [from UTF8String]);
if (room) {
LinphoneChatMessage *msg = linphone_chat_room_create_message(room, replyText.UTF8String);
linphone_chat_room_send_chat_message(room, msg);
NSString *callId = (NSString *)[response.notification.request.content.userInfo objectForKey:@"CallId"];
LinphoneCall *call = [LinphoneManager.instance callByCallId:callId];
if (call) {
LinphoneCallAppData *data = (__bridge LinphoneCallAppData *)linphone_call_get_user_data(call);
if (data->timer) {
[data->timer invalidate];
data->timer = nil;
}
}
if ([response.actionIdentifier isEqual:@"Answer"]) {
// use the standard handler
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
linphone_core_accept_call(LC, call);
} else if ([response.actionIdentifier isEqual:@"Decline"]) {
linphone_core_decline_call(LC, call, LinphoneReasonDeclined);
} else if ([response.actionIdentifier isEqual:@"Reply"]) {
LinphoneCore *lc = [LinphoneManager getLc];
NSString *replyText = [(UNTextInputNotificationResponse *)response userText];
NSString *from = [response.notification.request.content.userInfo objectForKey:@"from_addr"];
LinphoneChatRoom *room = linphone_core_get_chat_room_from_uri(lc, [from UTF8String]);
if (room) {
LinphoneChatMessage *msg = linphone_chat_room_create_message(room, replyText.UTF8String);
linphone_chat_room_send_chat_message(room, msg);
linphone_chat_room_mark_as_read(room);
TabBarView *tab = (TabBarView *)[PhoneMainView.instance.mainViewController
getCachedController:NSStringFromClass(TabBarView.class)];
@ -645,18 +721,99 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response
[PhoneMainView.instance updateApplicationBadgeNumber];
}
} else if ([response.actionIdentifier isEqual:@"Cancel"]) {
LOGI(@"User declined video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
}
} else if ([response.actionIdentifier isEqual:@"Accept"]) {
LOGI(@"User accept video proposal");
if (call == linphone_core_get_current_call(LC)) {
[[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_call_params_enable_video(params, TRUE);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
}
} else if ([response.actionIdentifier isEqual:@"Confirm"]) {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, YES);
}
} else if ([response.actionIdentifier isEqual:@"Deny"]) {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, NO);
}
} else { // in this case the value is : com.apple.UNNotificationDefaultActionIdentifier
if ([response.notification.request.content.categoryIdentifier isEqual:@"call_cat"]) {
[PhoneMainView.instance displayIncomingCall:call];
} else if ([response.notification.request.content.categoryIdentifier isEqual:@"msg_cat"]) {
[PhoneMainView.instance changeCurrentView:ChatsListView.compositeViewDescription];
} else if ([response.notification.request.content.categoryIdentifier isEqual:@"video_request"]) {
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
NSTimer *videoDismissTimer = nil;
UIConfirmationDialog *sheet =
[UIConfirmationDialog ShowWithMessage:response.notification.request.content.body
cancelMessage:nil
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
onCancelClick:^() {
LOGI(@"User declined video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
[videoDismissTimer invalidate];
}
}
onConfirmationClick:^() {
LOGI(@"User accept video proposal");
if (call == linphone_core_get_current_call(LC)) {
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_call_params_enable_video(params, TRUE);
linphone_core_accept_call_update(LC, call, params);
linphone_call_params_destroy(params);
[videoDismissTimer invalidate];
}
}
inController:PhoneMainView.instance];
videoDismissTimer = [NSTimer scheduledTimerWithTimeInterval:30
target:self
selector:@selector(dismissVideoActionSheet:)
userInfo:sheet
repeats:NO];
} else if ([response.notification.request.content.categoryIdentifier isEqual:@"zrtp_request"]) {
[UIConfirmationDialog
ShowWithMessage:[NSString stringWithFormat:NSLocalizedString(
@"Confirm the following SAS with peer:\n%s", nil),
linphone_call_get_authentication_token(call)]
cancelMessage:NSLocalizedString(@"DENY", nil)
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
onCancelClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, NO);
}
}
onConfirmationClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, YES);
}
}];
} else { // Missed call
[PhoneMainView.instance changeCurrentView:HistoryListView.compositeViewDescription];
}
}
}
#pragma mark - User notifications
- (void)dismissVideoActionSheet:(NSTimer *)timer {
UIConfirmationDialog *sheet = (UIConfirmationDialog *)timer.userInfo;
[sheet dismiss];
}
#pragma mark - NSUser notifications
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier

View file

@ -34,6 +34,8 @@
#include "linphone/linphonecore.h"
#include "bctoolbox/list.h"
#import "ProviderDelegate.h"
extern NSString *const LINPHONERC_APPLICATION_KEY;
extern NSString *const kLinphoneCoreUpdate;
@ -136,6 +138,7 @@ typedef struct _LinphoneManagerSounds {
- (void)configurePushTokenForProxyConfig: (LinphoneProxyConfig*)cfg;
- (BOOL)popPushCallID:(NSString*) callId;
- (void)acceptCallForCallId:(NSString*)callid;
- (LinphoneCall *)callByCallId:(NSString *)call_id;
- (void)cancelLocalNotifTimerForCallId:(NSString*)callid;
+ (BOOL)langageDirectionIsRTL;
@ -188,6 +191,9 @@ typedef struct _LinphoneManagerSounds {
- (void)shouldPresentLinkPopup;
- (void)setProviderDelegate:(ProviderDelegate *)del;
@property ProviderDelegate *providerDelegate;
@property (readonly) BOOL isTesting;
@property(readonly, strong) FastAddressBook *fastAddressBook;
@property Connectivity connectivity;
@ -211,5 +217,6 @@ typedef struct _LinphoneManagerSounds {
@property(readonly) InAppProductsManager *iapManager;
@property(strong, nonatomic) NSMutableArray *fileTransferDelegates;
@property BOOL nextCallIsTransfer;
@property BOOL conf;
@end

View file

@ -251,7 +251,7 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
_database = NULL;
_speakerEnabled = FALSE;
_bluetoothEnabled = FALSE;
_conf = FALSE;
_fileTransferDelegates = [[NSMutableArray alloc] init];
pushCallIDs = [[NSMutableArray alloc] init];
@ -652,13 +652,16 @@ static void linphone_iphone_display_status(struct _LinphoneCore *lc, const char
const LinphoneAddress *addr = linphone_call_get_remote_address(call);
NSString *address = [FastAddressBook displayNameForAddress:addr];
LinphoneCallLog *callLog = linphone_call_get_call_log(call);
NSString *callId = [NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog)];
if (state == LinphoneCallIncomingReceived) {
/*first step is to re-enable ctcall center*/
CTCallCenter *lCTCallCenter = [[CTCallCenter alloc] init];
/*should we reject this call ?*/
if ([lCTCallCenter currentCalls] != nil) {
if ([lCTCallCenter currentCalls] != nil &&
floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
char *tmp = linphone_call_get_remote_address_as_string(call);
if (tmp) {
LOGI(@"Mobile call ongoing... rejecting call from [%s]", tmp);
@ -668,40 +671,68 @@ static void linphone_iphone_display_status(struct _LinphoneCore *lc, const char
return;
}
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call &&
(linphone_core_get_calls_nb(LC) < 2)) {
NSString *callId =
[NSString stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(call))];
NSString *address = [FastAddressBook displayNameForAddress:linphone_call_get_remote_address(call)];
LinphoneCallLog *callLog = linphone_call_get_call_log(call);
NSString *callId = [NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog)];
NSUUID *uuid = [NSUUID UUID];
[LinphoneManager.instance.providerDelegate.calls setObject:callId forKey:uuid];
[LinphoneManager.instance.providerDelegate.uuids setObject:uuid forKey:callId];
BOOL video = FALSE;
video = (([UIApplication sharedApplication].applicationState != UIApplicationStateBackground) &&
linphone_core_get_video_policy(LC)->automatically_accept &&
linphone_call_params_video_enabled(linphone_call_get_remote_params(call)));
[LinphoneManager.instance.providerDelegate reportIncomingCallwithUUID:uuid handle:address video:video];
} else if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
// Create a UNNotification
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"Incoming call", nil);
content.body = address;
content.sound = [UNNotificationSound soundNamed:@"notes_of_the_optimistic.caf"];
content.categoryIdentifier = @"call_cat";
content.userInfo = @{ @"CallId" : callId };
UNNotificationRequest *req =
[UNNotificationRequest requestWithIdentifier:@"call_request" content:content trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:req
withCompletionHandler:^(NSError *err){
}];
}
//if (![LinphoneManager.instance popPushCallID:callId]) {
// case where a remote notification is not already received
// Create a new local notification
if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIMutableUserNotificationAction *answer = [[UIMutableUserNotificationAction alloc] init];
answer.identifier = @"answer";
answer.title = NSLocalizedString(@"Answer", nil);
answer.activationMode = UIUserNotificationActivationModeForeground;
answer.destructive = NO;
answer.authenticationRequired = YES;
UIMutableUserNotificationAction *decline = [[UIMutableUserNotificationAction alloc] init];
decline.identifier = @"decline";
decline.title = NSLocalizedString(@"Decline", nil);
decline.activationMode = UIUserNotificationActivationModeBackground;
decline.destructive = YES;
decline.authenticationRequired = NO;
NSArray *callactions = @[ decline, answer ];
UIMutableUserNotificationCategory *callcat = [[UIMutableUserNotificationCategory alloc] init];
callcat.identifier = @"incoming_call";
[callcat setActions:callactions forContext:UIUserNotificationActionContextDefault];
[callcat setActions:callactions forContext:UIUserNotificationActionContextMinimal];
NSSet* categories = [NSSet setWithObjects:callcat, nil];
UIUserNotificationSettings *set = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:set];
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
// if (![LinphoneManager.instance popPushCallID:callId]) {
// case where a remote notification is not already received
// Create a new local notification
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
UIMutableUserNotificationAction *answer = [[UIMutableUserNotificationAction alloc] init];
answer.identifier = @"answer";
answer.title = NSLocalizedString(@"Answer", nil);
answer.activationMode = UIUserNotificationActivationModeForeground;
answer.destructive = NO;
answer.authenticationRequired = YES;
UIMutableUserNotificationAction *decline = [[UIMutableUserNotificationAction alloc] init];
decline.identifier = @"decline";
decline.title = NSLocalizedString(@"Decline", nil);
decline.activationMode = UIUserNotificationActivationModeBackground;
decline.destructive = YES;
decline.authenticationRequired = NO;
NSArray *callactions = @[ decline, answer ];
UIMutableUserNotificationCategory *callcat = [[UIMutableUserNotificationCategory alloc] init];
callcat.identifier = @"incoming_call";
[callcat setActions:callactions forContext:UIUserNotificationActionContextDefault];
[callcat setActions:callactions forContext:UIUserNotificationActionContextMinimal];
NSSet *categories = [NSSet setWithObjects:callcat, nil];
UIUserNotificationSettings *set = [UIUserNotificationSettings
settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge |
UIUserNotificationTypeSound)
categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:set];
data->notification = [[UILocalNotification alloc] init];
if (data->notification) {
// iOS8 doesn't need the timer trick for the local notification.
@ -745,40 +776,6 @@ static void linphone_iphone_display_status(struct _LinphoneCore *lc, const char
}
}
}
} else {
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"Incoming call", nil);
content.body = address;
content.sound = [UNNotificationSound soundNamed:@"notes_of_the_optimistic.caf"];
content.categoryIdentifier = @"call_cat";
content.userInfo = @{@"callId" : callId};
if ([self lpConfigBoolForKey:@"repeat_call_notification"] == YES) {
data->timer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:@selector(userNotifContinue:)
userInfo:content
repeats:TRUE];
}
UNNotificationRequest *req = [UNNotificationRequest requestWithIdentifier:@"call_request" content:content trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:req withCompletionHandler:^(NSError * _Nullable error) {
// Enable or disable features based on authorization.
if (error) {
LOGD(@"Error while adding notification request :");
LOGD(error.description);
}
}];
if (!incallBgTask) {
incallBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
LOGW(@"Call cannot ring any more, too late");
[[UIApplication sharedApplication] endBackgroundTask:incallBgTask];
incallBgTask = 0;
}];
if (data->timer) {
[[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes];
}
}
}
}
@ -800,55 +797,102 @@ static void linphone_iphone_display_status(struct _LinphoneCore *lc, const char
_bluetoothEnabled = FALSE;
/*IOS specific*/
linphone_core_start_dtmf_stream(theLinphoneCore);
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)) {
if (data->timer) {
[data->timer invalidate];
data->timer = nil;
}
LinphoneCallLog *UNlog = linphone_call_get_call_log(call);
if (UNlog == NULL || linphone_call_log_get_status(UNlog) == LinphoneCallMissed) {
UNMutableNotificationContent* missed_content = [[UNMutableNotificationContent alloc] init];
missed_content.title = NSLocalizedString(@"Missed call", nil);
missed_content.body = address;
UNNotificationRequest *missed_req = [UNNotificationRequest requestWithIdentifier:@"call_request" content:missed_content trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:missed_req withCompletionHandler:^(NSError * _Nullable error) {
// Enable or disable features based on authorization.
if (error) {
LOGD(@"Error while adding notification request :");
LOGD(error.description);
}
}];
}
linphone_core_set_network_reachable(LC, FALSE);
LinphoneManager.instance.connectivity = none;
}
}
if (incallBgTask) {
[[UIApplication sharedApplication] endBackgroundTask:incallBgTask];
incallBgTask = 0;
}
if (data != nil && data->notification != nil) {
LinphoneCallLog *log = linphone_call_get_call_log(call);
// cancel local notif if needed
if (data->timer) {
[data->timer invalidate];
data->timer = nil;
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
if (data->timer) {
[data->timer invalidate];
data->timer = nil;
}
LinphoneCallLog *UNlog = linphone_call_get_call_log(call);
if (UNlog == NULL || linphone_call_log_get_status(UNlog) == LinphoneCallMissed) {
UNMutableNotificationContent *missed_content = [[UNMutableNotificationContent alloc] init];
missed_content.title = NSLocalizedString(@"Missed call", nil);
missed_content.body = address;
UNNotificationRequest *missed_req = [UNNotificationRequest requestWithIdentifier:@"call_request"
content:missed_content
trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter]
addNotificationRequest:missed_req
withCompletionHandler:^(NSError *_Nullable error) {
// Enable or disable features based on authorization.
if (error) {
LOGD(@"Error while adding notification request :");
LOGD(error.description);
}
}];
}
linphone_core_set_network_reachable(LC, FALSE);
LinphoneManager.instance.connectivity = none;
}
[[UIApplication sharedApplication] cancelLocalNotification:data->notification];
LinphoneCallLog *callLog2 = linphone_call_get_call_log(call);
NSString *callId2 = [NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog2)];
NSUUID *uuid = (NSUUID *)[self.providerDelegate.uuids objectForKey:callId2];
if (uuid) {
// For security reasons do not display name
// CXCallUpdate *update = [[CXCallUpdate alloc] init];
// update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:@"Unknown"];
//[LinphoneManager.instance.providerDelegate.provider reportCallWithUUID:uuid updated:update];
data->notification = nil;
if (linphone_core_get_calls_nb(LC) > 0 && !_conf) {
// Create a CallKit call because there's not !
_conf = FALSE;
LinphoneCall *callKit_call = (LinphoneCall *)linphone_core_get_calls(LC)->data;
NSString *callKit_callId = [NSString
stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(callKit_call))];
NSUUID *callKit_uuid = [NSUUID UUID];
[LinphoneManager.instance.providerDelegate.uuids setObject:callKit_uuid forKey:callKit_callId];
[LinphoneManager.instance.providerDelegate.calls setObject:callKit_callId forKey:callKit_uuid];
NSString *address =
[FastAddressBook displayNameForAddress:linphone_call_get_remote_address(callKit_call)];
CXHandle *handle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:address];
CXStartCallAction *act = [[CXStartCallAction alloc] initWithCallUUID:callKit_uuid handle:handle];
CXTransaction *tr = [[CXTransaction alloc] initWithAction:act];
[LinphoneManager.instance.providerDelegate.controller requestTransaction:tr
completion:^(NSError *err){
}];
[LinphoneManager.instance.providerDelegate.provider reportOutgoingCallWithUUID:callKit_uuid
startedConnectingAtDate:nil];
[LinphoneManager.instance.providerDelegate.provider reportOutgoingCallWithUUID:callKit_uuid
connectedAtDate:nil];
}
if (log == NULL || linphone_call_log_get_status(log) == LinphoneCallMissed) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.repeatInterval = 0;
notification.alertBody =
[NSString stringWithFormat:NSLocalizedString(@"You missed a call from %@", nil), address];
notification.alertAction = NSLocalizedString(@"Show", nil);
notification.userInfo = [NSDictionary
dictionaryWithObject:[NSString stringWithUTF8String:linphone_call_log_get_call_id(log)]
forKey:@"callLog"];
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
[self.providerDelegate.uuids removeObjectForKey:callId2];
[self.providerDelegate.calls removeObjectForKey:uuid];
[self.providerDelegate.provider reportCallWithUUID:uuid
endedAtDate:NULL
reason:CXCallEndedReasonRemoteEnded];
}
} else {
if (data != nil && data->notification != nil) {
LinphoneCallLog *log = linphone_call_get_call_log(call);
// cancel local notif if needed
if (data->timer) {
[data->timer invalidate];
data->timer = nil;
}
[[UIApplication sharedApplication] cancelLocalNotification:data->notification];
data->notification = nil;
if (log == NULL || linphone_call_log_get_status(log) == LinphoneCallMissed) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.repeatInterval = 0;
notification.alertBody =
[NSString stringWithFormat:NSLocalizedString(@"You missed a call from %@", nil), address];
notification.alertAction = NSLocalizedString(@"Show", nil);
notification.userInfo = [NSDictionary
dictionaryWithObject:[NSString stringWithUTF8String:linphone_call_log_get_call_id(log)]
forKey:@"callLog"];
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
}
}
}
@ -1704,7 +1748,7 @@ static BOOL libStarted = FALSE;
// create linphone core
[self createLinphoneCore];
[self.providerDelegate config];
_iapManager = [[InAppProductsManager alloc] init];
// - Security fix - remove multi transport migration, because it enables tcp or udp, if by factoring settings only
@ -1915,6 +1959,13 @@ static int comp_call_id(const LinphoneCall *call, const char *callid) {
return strcmp(linphone_call_log_get_call_id(linphone_call_get_call_log(call)), callid);
}
- (LinphoneCall *)callByCallId:(NSString *)call_id {
const bctbx_list_t *calls = linphone_core_get_calls(LC);
bctbx_list_t *call_tmp = bctbx_list_find_custom(calls, (bctbx_compare_func)comp_call_id, [call_id UTF8String]);
LinphoneCall *call = (LinphoneCall *)call_tmp->data;
return call;
}
- (void)cancelLocalNotifTimerForCallId:(NSString *)callid {
// first, make sure this callid is not already involved in a call
const bctbx_list_t *calls = linphone_core_get_calls(theLinphoneCore);
@ -2137,7 +2188,22 @@ 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) {
linphone_core_pause_call(theLinphoneCore, c);
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);
}
}
}
@ -2330,16 +2396,16 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
// Then check that no GSM calls are in progress, abort otherwise.
CTCallCenter *callCenter = [[CTCallCenter alloc] init];
if ([callCenter currentCalls] != nil) {
if ([callCenter currentCalls] != nil && floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
LOGE(@"GSM call in progress, cancelling outgoing SIP call request");
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Cannot make call", nil)
message:NSLocalizedString(@"Please terminate GSM call first.", nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[errView addAction:defaultAction];
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
return FALSE;
@ -2360,6 +2426,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
return FALSE;
}
LinphoneAddress *addr = linphone_address_clone(iaddr);
NSString *displayName = [FastAddressBook displayNameForAddress:addr];
@ -2378,13 +2445,15 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
addr, [[LinphoneManager.instance lpConfigStringForKey:@"domain" inSection:@"assistant"] UTF8String]);
}
LinphoneCall *call;
if (LinphoneManager.instance.nextCallIsTransfer) {
char *caddr = linphone_address_as_string(addr);
linphone_core_transfer_call(theLinphoneCore, linphone_core_get_current_call(theLinphoneCore), caddr);
call = linphone_core_get_current_call(theLinphoneCore);
linphone_core_transfer_call(theLinphoneCore, call, caddr);
LinphoneManager.instance.nextCallIsTransfer = NO;
ms_free(caddr);
} else {
LinphoneCall *call = linphone_core_invite_address_with_params(theLinphoneCore, addr, lcallParams);
call = linphone_core_invite_address_with_params(theLinphoneCore, addr, lcallParams);
if (call) {
// The LinphoneCallAppData object should be set on call creation with callback
// - (void)onCall:StateChanged:withMessage:. If not, we are in big trouble and expect it to crash
@ -2704,20 +2773,22 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
}
- (void)handleGSMCallInteration:(id)cCenter {
CTCallCenter *ct = (CTCallCenter *)cCenter;
/* pause current call, if any */
LinphoneCall *call = linphone_core_get_current_call(theLinphoneCore);
if ([ct currentCalls] != nil) {
if (call) {
LOGI(@"Pausing SIP call because GSM call");
linphone_core_pause_call(theLinphoneCore, call);
[self startCallPausedLongRunningTask];
} else if (linphone_core_is_in_conference(theLinphoneCore)) {
LOGI(@"Leaving conference call because GSM call");
linphone_core_leave_conference(theLinphoneCore);
[self startCallPausedLongRunningTask];
}
} // else nop, keep call in paused state
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
CTCallCenter *ct = (CTCallCenter *)cCenter;
// pause current call, if any
LinphoneCall *call = linphone_core_get_current_call(theLinphoneCore);
if ([ct currentCalls] != nil) {
if (call) {
LOGI(@"Pausing SIP call because GSM call");
linphone_core_pause_call(theLinphoneCore, call);
[self startCallPausedLongRunningTask];
} else if (linphone_core_is_in_conference(theLinphoneCore)) {
LOGI(@"Leaving conference call because GSM call");
linphone_core_leave_conference(theLinphoneCore);
[self startCallPausedLongRunningTask];
}
} // else nop, keep call in paused state
}
}
- (NSString *)contactFilter {

View file

@ -20,6 +20,7 @@
#import "StatusBarView.h"
#import "LinphoneManager.h"
#import "PhoneMainView.h"
#import <UserNotifications/UserNotifications.h>
@implementation StatusBarView {
@ -320,23 +321,43 @@
NSString *message =
[NSString stringWithFormat:NSLocalizedString(@"Confirm the following SAS with peer:\n%s", nil),
linphone_call_get_authentication_token(call)];
if (securityDialog == nil) {
__block __strong StatusBarView *weakSelf = self;
securityDialog = [UIConfirmationDialog ShowWithMessage:message
cancelMessage:NSLocalizedString(@"DENY", nil)
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
onCancelClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, NO);
}
weakSelf->securityDialog = nil;
}
onConfirmationClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, YES);
}
weakSelf->securityDialog = nil;
}];
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground &&
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"ZRTP verification", nil);
content.body = message;
content.categoryIdentifier = @"zrtp_request";
UNNotificationRequest *req =
[UNNotificationRequest requestWithIdentifier:@"zrtp_request" content:content trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter]
addNotificationRequest:req
withCompletionHandler:^(NSError *_Nullable error) {
// Enable or disable features based on authorization.
if (error) {
LOGD(@"Error while adding notification request :");
LOGD(error.description);
}
}];
} else {
if (securityDialog == nil) {
__block __strong StatusBarView *weakSelf = self;
securityDialog = [UIConfirmationDialog ShowWithMessage:message
cancelMessage:NSLocalizedString(@"DENY", nil)
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
onCancelClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, NO);
}
weakSelf->securityDialog = nil;
}
onConfirmationClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, YES);
}
weakSelf->securityDialog = nil;
}];
}
}
}
}

View file

@ -94,8 +94,9 @@
if (linphone_core_is_in_conference(LC) || // In conference
(linphone_core_get_conference_size(LC) > 0 && [UIHangUpButton callCount] == 0) // Only one conf
) {
LinphoneManager.instance.conf = TRUE;
linphone_core_terminate_conference(LC);
} else if (currentcall != NULL) { // In a call
} else if (currentcall != NULL) {
linphone_core_terminate_call(LC, currentcall);
} else {
const MSList *calls = linphone_core_get_calls(LC);

View file

@ -82,7 +82,22 @@
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
linphone_core_pause_call(LC, call);
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);
}
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
@ -98,7 +113,22 @@
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
linphone_core_pause_call(LC, currentCall);
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);
}
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
@ -111,24 +141,65 @@
switch (type) {
case UIPauseButtonType_Call: {
if (call != nil) {
linphone_core_resume_call(LC, call);
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);
}
} else {
LOGW(@"Cannot toggle pause buttton, because no current call");
}
break;
}
case UIPauseButtonType_Conference: {
linphone_core_enter_conference(LC);
// Fake event
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
NSUUID *uuid = (NSUUID *)[LinphoneManager.instance.providerDelegate.uuids allValues].firstObject;
if (!uuid) {
linphone_core_enter_conference(LC);
// Fake event
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
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_enter_conference(LC);
// Fake event
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
}
break;
}
case UIPauseButtonType_CurrentCall: {
LinphoneCall *currentCall = [UIPauseButton getCall];
if (currentCall != nil) {
linphone_core_resume_call(LC, currentCall);
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 {
LOGW(@"Cannot toggle pause buttton, because no current call");
linphone_core_resume_call(LC, currentCall);
}
break;
}

View file

@ -323,7 +323,9 @@ static RootViewManager *rootViewManagerInstance = nil;
switch (state) {
case LinphoneCallIncomingReceived:
case LinphoneCallIncomingEarlyMedia: {
[self displayIncomingCall:call];
if (linphone_core_get_calls_nb(LC) > 1) {
[self displayIncomingCall:call];
}
break;
}
case LinphoneCallOutgoingInit: {
@ -334,6 +336,21 @@ static RootViewManager *rootViewManagerInstance = nil;
case LinphoneCallConnected:
case LinphoneCallStreamsRunning: {
[self changeCurrentView:CallView.compositeViewDescription];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call) {
NSString *callId =
[NSString stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(call))];
NSUUID *uuid = [LinphoneManager.instance.providerDelegate.uuids objectForKey:callId];
if (uuid) {
NSString *address = [FastAddressBook displayNameForAddress:linphone_call_get_remote_address(call)];
CXCallUpdate *update = [[CXCallUpdate alloc] init];
update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:address];
update.supportsGrouping = TRUE;
update.supportsDTMF = TRUE;
update.supportsHolding = TRUE;
update.supportsUngrouping = TRUE;
[LinphoneManager.instance.providerDelegate.provider reportCallWithUUID:uuid updated:update];
}
}
break;
}
case LinphoneCallUpdatedByRemote: {
@ -357,7 +374,23 @@ static RootViewManager *rootViewManagerInstance = nil;
[self popCurrentView];
}
} else {
linphone_core_resume_call(LC, (LinphoneCall *)calls->data);
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);
}
[self changeCurrentView:CallView.compositeViewDescription];
}
break;
@ -366,8 +399,45 @@ static RootViewManager *rootViewManagerInstance = nil;
case LinphoneCallEarlyUpdating:
case LinphoneCallIdle:
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingProgress: {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call &&
(linphone_core_get_calls_nb(LC) < 2)) {
// Create CallKit Call
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){
}];
}
}
case LinphoneCallOutgoingRinging: {
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max && call) {
NSString *callId =
[NSString stringWithUTF8String:linphone_call_log_get_call_id(linphone_call_get_call_log(call))];
NSUUID *uuid = [LinphoneManager.instance.providerDelegate.uuids objectForKey:callId];
if (uuid) {
[LinphoneManager.instance.providerDelegate.provider reportOutgoingCallWithUUID:uuid
startedConnectingAtDate:nil];
[LinphoneManager.instance.providerDelegate.provider reportOutgoingCallWithUUID:uuid
connectedAtDate:nil];
NSString *address = [FastAddressBook displayNameForAddress:linphone_call_get_remote_address(call)];
CXCallUpdate *update = [[CXCallUpdate alloc] init];
update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:address];
update.supportsGrouping = TRUE;
update.supportsDTMF = TRUE;
update.supportsHolding = TRUE;
update.supportsUngrouping = TRUE;
[LinphoneManager.instance.providerDelegate.provider reportCallWithUUID:uuid updated:update];
}
}
}
case LinphoneCallPaused:
case LinphoneCallPausing:
case LinphoneCallRefered:

View file

@ -0,0 +1,26 @@
//
// ProviderDelegate.h
// linphone
//
// Created by REIS Benjamin on 29/11/2016.
//
//
#import <CallKit/CallKit.h>
#ifndef ProviderDelegate_h
#define ProviderDelegate_h
@interface ProviderDelegate : NSObject <CXProviderDelegate, CXCallObserverDelegate>
@property CXProvider *provider;
@property CXCallObserver *observer;
@property CXCallController *controller;
@property NSMutableDictionary *calls;
@property NSMutableDictionary *uuids;
- (void)reportIncomingCallwithUUID:(NSUUID *)uuid handle:(NSString *)handle video:(BOOL)video;
- (void)config;
@end
#endif /* ProviderDelegate_h */

227
Classes/ProviderDelegate.m Normal file
View file

@ -0,0 +1,227 @@
//
// ProviderDelegate.m
// linphone
//
// Created by REIS Benjamin on 29/11/2016.
//
//
#import "ProviderDelegate.h"
#import "LinphoneManager.h"
#import "PhoneMainView.h"
#include "linphone/linphonecore.h"
#import <AVFoundation/AVAudioSession.h>
#import <Foundation/Foundation.h>
@implementation ProviderDelegate
- (instancetype)init {
self = [super init];
self.calls = [[NSMutableDictionary alloc] init];
self.uuids = [[NSMutableDictionary alloc] init];
CXCallController *callController = [[CXCallController alloc] initWithQueue:dispatch_get_main_queue()];
[callController.callObserver setDelegate:self queue:dispatch_get_main_queue()];
self.controller = callController;
if (!self) {
LOGD(@"ProviderDelegate not initialized...");
}
return self;
}
- (void)config {
CXProviderConfiguration *config = [[CXProviderConfiguration alloc] initWithLocalizedName:@"Linphone"];
config.ringtoneSound = @"shortring.caf";
config.supportsVideo = FALSE;
config.iconTemplateImageData = UIImagePNGRepresentation([UIImage imageNamed:@"callkit_logo"]);
NSArray *ar = @[ [NSNumber numberWithInt:(int)CXHandleTypeGeneric] ];
NSSet *handleTypes = [[NSSet alloc] initWithArray:ar];
[config setSupportedHandleTypes:handleTypes];
[config setMaximumCallGroups:2];
[config setMaximumCallsPerCallGroup:1];
self.provider = [[CXProvider alloc] initWithConfiguration:config];
[self.provider setDelegate:self queue:dispatch_get_main_queue()];
}
- (void)reportIncomingCallwithUUID:(NSUUID *)uuid handle:(NSString *)handle video:(BOOL)video {
// Create update to describe the incoming call and caller
CXCallUpdate *update = [[CXCallUpdate alloc] init];
update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:handle];
update.supportsDTMF = TRUE;
update.supportsHolding = TRUE;
update.supportsGrouping = TRUE;
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];
}];
}
#pragma mark - CXProdiverDelegate Protocol
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
LOGD(@"CallKit : Answering Call");
NSUUID *uuid = action.callUUID;
[action fulfill];
NSString *callID = [self.calls objectForKey:uuid]; // first, make sure this callid is not already involved in a call
LinphoneCall *call = [LinphoneManager.instance callByCallId:callID];
if (call != NULL) {
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];
return;
};
}
- (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];
[action fulfill];
}
- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
LOGD(@"CallKit : Ending the Call");
if (linphone_core_is_in_conference(LC)) {
LinphoneManager.instance.conf = TRUE;
linphone_core_terminate_conference(LC);
} else if (linphone_core_get_calls_nb(LC) > 1) {
LinphoneManager.instance.conf = TRUE;
linphone_core_terminate_all_calls(LC);
} else {
NSUUID *uuid = action.callUUID;
NSString *callID = [self.calls objectForKey:uuid];
LinphoneCall *call = [LinphoneManager.instance callByCallId:callID];
if (call) {
linphone_core_terminate_call(LC, (LinphoneCall *)call);
}
}
[action fulfill];
}
- (void)provider:(CXProvider *)provider performSetMutedCallAction:(nonnull CXSetMutedCallAction *)action {
[action fulfill];
if ([[PhoneMainView.instance currentView] equal:CallView.compositeViewDescription]) {
CallView *view = (CallView *)[PhoneMainView.instance popToView:CallView.compositeViewDescription];
[view.microButton toggle];
}
}
- (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];
return;
}
if (linphone_core_get_calls_nb(LC) > 1 && action.isOnHold) {
linphone_core_pause_all_calls(LC);
return;
}
NSUUID *uuid = action.callUUID;
NSString *callID = [self.calls objectForKey:uuid];
if (!callID) {
return;
}
LinphoneCall *call = [LinphoneManager.instance callByCallId:callID];
if (call) {
if (action.isOnHold) {
linphone_core_pause_call(LC, (LinphoneCall *)call);
} else {
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);
}
}
}
}
- (void)provider:(CXProvider *)provider performPlayDTMFCallAction:(CXPlayDTMFCallAction *)action {
[action fulfill];
LOGD(@"CallKit : playing DTMF");
NSUUID *call_uuid = action.callUUID;
NSString *callID = [self.calls objectForKey:call_uuid];
LinphoneCall *call = [LinphoneManager.instance callByCallId:callID];
char digit = action.digits.UTF8String[0];
linphone_call_send_dtmf((LinphoneCall *)call, digit);
}
- (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession {
LOGD(@"CallKit : Audio session activated");
}
- (void)provider:(CXProvider *)provider didDeactivateAudioSession:(nonnull AVAudioSession *)audioSession {
LOGD(@"CallKit : Audio session deactivated");
}
- (void)providerDidReset:(CXProvider *)provider {
LOGD(@"CallKit : Provider reset");
LinphoneManager.instance.conf = TRUE;
linphone_core_terminate_all_calls(LC);
[self.calls removeAllObjects];
[self.uuids removeAllObjects];
}
#pragma mark - CXCallObserverDelegate Protocol
- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call {
LOGD(@"CallKit : Call changed");
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -669,6 +669,9 @@
63FD3F121CA17FA400E9AECC /* libmbedx509.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 63FD3F081CA17F9100E9AECC /* libmbedx509.a */; };
70E542F313E147E3002BA2C0 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70E542F213E147E3002BA2C0 /* OpenGLES.framework */; };
70E542F513E147EB002BA2C0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70E542F413E147EB002BA2C0 /* QuartzCore.framework */; };
8C2595DD1DEDC92D007A6424 /* ProviderDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2595DC1DEDC92D007A6424 /* ProviderDelegate.m */; };
8C2595DF1DEDCC8E007A6424 /* CallKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C2595DE1DEDCC8E007A6424 /* CallKit.framework */; };
8C2595E11DEDDC67007A6424 /* callkit_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 8C2595E01DEDDC67007A6424 /* callkit_logo.png */; };
8C73477C1D9BA3A00022EE8C /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C73477B1D9BA3A00022EE8C /* UserNotifications.framework */; };
8CA2004C1D8158440095F859 /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CA2004B1D8158440095F859 /* PushKit.framework */; };
9EC6C1E11DF96991006C2FD2 /* armv7-apple-darwin.ios in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EC6C1E01DF96991006C2FD2 /* armv7-apple-darwin.ios */; };
@ -1588,6 +1591,10 @@
70E542F213E147E3002BA2C0 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
70E542F413E147EB002BA2C0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
8C23BCB71D82AAC3005F19BB /* linphone.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = linphone.entitlements; sourceTree = "<group>"; };
8C2595D51DEDC8E1007A6424 /* ProviderDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProviderDelegate.h; sourceTree = "<group>"; };
8C2595DC1DEDC92D007A6424 /* ProviderDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProviderDelegate.m; sourceTree = "<group>"; };
8C2595DE1DEDCC8E007A6424 /* CallKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CallKit.framework; path = System/Library/Frameworks/CallKit.framework; sourceTree = SDKROOT; };
8C2595E01DEDDC67007A6424 /* callkit_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = callkit_logo.png; sourceTree = "<group>"; };
8C5D1B991D9BC48100DC6539 /* UIShopTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIShopTableCell.h; sourceTree = "<group>"; };
8C5D1B9A1D9BC48100DC6539 /* UIShopTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIShopTableCell.m; sourceTree = "<group>"; };
8C5D1B9B1D9BC48100DC6539 /* UIShopTableCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UIShopTableCell.xib; sourceTree = "<group>"; };
@ -1830,6 +1837,7 @@
files = (
9EC6C1E31DF969AA006C2FD2 /* libturbojpeg.a in Frameworks */,
9EC6C1E11DF96991006C2FD2 /* armv7-apple-darwin.ios in Frameworks */,
8C2595DF1DEDCC8E007A6424 /* CallKit.framework in Frameworks */,
8C73477C1D9BA3A00022EE8C /* UserNotifications.framework in Frameworks */,
8CA2004C1D8158440095F859 /* PushKit.framework in Frameworks */,
340751971506459A00B89C47 /* CoreTelephony.framework in Frameworks */,
@ -2065,6 +2073,8 @@
63E27A311C4FECD000D332AE /* LaunchScreen.xib */,
1D3623240D0F684500981E51 /* LinphoneAppDelegate.h */,
1D3623250D0F684500981E51 /* LinphoneAppDelegate.m */,
8C2595D51DEDC8E1007A6424 /* ProviderDelegate.h */,
8C2595DC1DEDC92D007A6424 /* ProviderDelegate.m */,
D37DC6BF1594AE1800B2A5EB /* LinphoneCoreSettingsStore.h */,
D37DC6C01594AE1800B2A5EB /* LinphoneCoreSettingsStore.m */,
D3EA53FB159850E80037DC6B /* LinphoneManager.h */,
@ -2238,6 +2248,7 @@
children = (
9EC6C1E21DF969AA006C2FD2 /* libturbojpeg.a */,
9EC6C1E01DF96991006C2FD2 /* armv7-apple-darwin.ios */,
8C2595DE1DEDCC8E007A6424 /* CallKit.framework */,
8C73477B1D9BA3A00022EE8C /* UserNotifications.framework */,
8CA2004B1D8158440095F859 /* PushKit.framework */,
570742661D5A63DB004B9C84 /* StoreKit.framework */,
@ -2429,6 +2440,7 @@
633FEBE11D3CD5570014B822 /* images */ = {
isa = PBXGroup;
children = (
8C2595E01DEDDC67007A6424 /* callkit_logo.png */,
633FEBE21D3CD5570014B822 /* add_field_default.png */,
633FEBE31D3CD5570014B822 /* add_field_default@2x.png */,
633FEBE41D3CD5570014B822 /* add_field_over.png */,
@ -3163,6 +3175,7 @@
LastUpgradeCheck = 0800;
TargetAttributes = {
1D6058900D05DD3D006BFB54 = {
DevelopmentTeam = Z2V957B3D6;
SystemCapabilities = {
com.apple.InAppPurchase = {
enabled = 1;
@ -3328,6 +3341,7 @@
634610121B6140A500548952 /* CallOutgoingView.xib in Resources */,
633FEDC21D3CD5590014B822 /* call_hangup_default.png in Resources */,
633FEEB41D3CD55A0014B822 /* numpad_3_default@2x.png in Resources */,
8C2595E11DEDDC67007A6424 /* callkit_logo.png in Resources */,
633FEE471D3CD5590014B822 /* contacts_sip_selected@2x.png in Resources */,
633FEEE51D3CD55A0014B822 /* numpad_9_over.png in Resources */,
633FEECA1D3CD55A0014B822 /* numpad_5~ipad@2x.png in Resources */,
@ -3894,6 +3908,7 @@
340751E7150F38FD00B89C47 /* UIVideoButton.m in Sources */,
34216F401547EBCD00EA9777 /* VideoZoomHandler.m in Sources */,
D3F83EEC1582021700336684 /* CallView.m in Sources */,
8C2595DD1DEDC92D007A6424 /* ProviderDelegate.m in Sources */,
63F1DF4B1BCE983200EDED90 /* CallConferenceTableView.m in Sources */,
D3F83F8E15822ABE00336684 /* PhoneMainView.m in Sources */,
6377AC801BDE4069007F7625 /* UIBackToCallButton.m in Sources */,
@ -4511,7 +4526,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COMPRESS_PNG_FILES = NO;
COPY_PHASE_STRIP = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = Z2V957B3D6;
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_DYNAMIC_NO_PIC = NO;
@ -4600,7 +4615,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COMPRESS_PNG_FILES = NO;
COPY_PHASE_STRIP = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = Z2V957B3D6;
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_DYNAMIC_NO_PIC = NO;
@ -4688,7 +4703,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COMPRESS_PNG_FILES = NO;
COPY_PHASE_STRIP = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = Z2V957B3D6;
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_DYNAMIC_NO_PIC = NO;
@ -4776,7 +4791,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COMPRESS_PNG_FILES = NO;
COPY_PHASE_STRIP = NO;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = Z2V957B3D6;
FRAMEWORK_SEARCH_PATHS = "";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_DYNAMIC_NO_PIC = NO;