From 55a88095bda980739bbf367a706596aceb747ccd Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Wed, 24 Sep 2014 16:34:48 +0200 Subject: [PATCH] Voice mail feature: display number of unread messages on status bar and reformat code --- Classes/LinphoneManager.h | 27 +- Classes/LinphoneManager.m | 1926 +++++++++-------- Classes/LinphoneUI/Base.lproj/UICallBar.xib | 21 +- .../LinphoneUI/Base.lproj/UICallBar~ipad.xib | 21 +- .../LinphoneUI/UIDigitButtonLongVoiceMail.m | 1 + Classes/LinphoneUI/UIStateBar.h | 24 +- Classes/LinphoneUI/UIStateBar.m | 524 ++--- Classes/LinphoneUI/UIStateBar.xib | 32 +- 8 files changed, 1340 insertions(+), 1236 deletions(-) diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index 6fa0e1fd7..ab76faeec 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -4,18 +4,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #import #import @@ -50,6 +50,7 @@ extern NSString *const kLinphoneSettingsUpdate; extern NSString *const kLinphoneBluetoothAvailabilityUpdate; extern NSString *const kLinphoneConfiguringStateUpdate; extern NSString *const kLinphoneGlobalStateUpdate; +extern NSString *const kLinphoneNotifyReceived; typedef enum _NetworkType { network_none = 0, @@ -105,7 +106,7 @@ typedef struct _LinphoneManagerSounds { @interface LinphoneManager : NSObject { @protected SCNetworkReachabilityRef proxyReachability; - + @private NSTimer* mIterateTimer; NSMutableArray* pendindCallIdFromRemoteNotif; @@ -174,7 +175,7 @@ typedef struct _LinphoneManagerSounds { - (NSInteger)lpConfigIntForKey:(NSString*)key; - (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key forSection:(NSString*)section; - (NSInteger)lpConfigIntForKey:(NSString*)key forSection:(NSString*)section; -- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key; +- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key; - (BOOL)lpConfigBoolForKey:(NSString*)key; - (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key forSection:(NSString*)section; - (BOOL)lpConfigBoolForKey:(NSString*)key forSection:(NSString*)section; diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index ee9d64838..980ac3728 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -5,18 +5,18 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + */ #include #include @@ -38,11 +38,11 @@ #define LINPHONE_LOGS_MAX_ENTRY 5000 static void audioRouteChangeListenerCallback ( - void *inUserData, // 1 - AudioSessionPropertyID inPropertyID, // 2 - UInt32 inPropertyValueSize, // 3 - const void *inPropertyValue // 4 - ); + void *inUserData, // 1 + AudioSessionPropertyID inPropertyID, // 2 + UInt32 inPropertyValueSize, // 3 + const void *inPropertyValue // 4 + ); static LinphoneCore* theLinphoneCore = nil; static LinphoneManager* theLinphoneManager = nil; @@ -61,6 +61,7 @@ NSString *const kLinphoneSettingsUpdate = @"LinphoneSettingsUpdate"; NSString *const kLinphoneBluetoothAvailabilityUpdate = @"LinphoneBluetoothAvailabilityUpdate"; NSString *const kLinphoneConfiguringStateUpdate = @"LinphoneConfiguringStateUpdate"; NSString *const kLinphoneGlobalStateUpdate = @"LinphoneGlobalStateUpdate"; +NSString *const kLinphoneNotifyReceived = @"LinphoneNotifyReceived"; const int kLinphoneAudioVbrCodecDefaultBitrate=36; /*you can override this from linphonerc or linphonerc-factory*/ @@ -81,11 +82,11 @@ NSString *const kLinphoneInternalChatDBFilename = @"linphone_chats.db"; @implementation LinphoneCallAppData - (id)init { - if ((self = [super init])) { + if ((self = [super init])) { self->batteryWarningShown = FALSE; - self->notification = nil; + self->notification = nil; self->videoRequested = FALSE; - self->userInfos = [[NSMutableDictionary alloc] init]; + self->userInfos = [[NSMutableDictionary alloc] init]; } return self; } @@ -116,9 +117,9 @@ NSString *const kLinphoneInternalChatDBFilename = @"linphone_chats.db"; @synthesize configDb; struct codec_name_pref_table{ - const char *name; - int rate; - NSString *prefname; + const char *name; + int rate; + NSString *prefname; }; struct codec_name_pref_table codec_pref_table[]={ @@ -127,7 +128,7 @@ struct codec_name_pref_table codec_pref_table[]={ { "silk", 24000, @"silk_24k_preference" }, { "silk", 16000, @"silk_16k_preference" }, { "amr", 8000, @"amr_preference" }, - { "gsm", 8000, @"gsm_preference" }, + { "gsm", 8000, @"gsm_preference" }, { "ilbc", 8000, @"ilbc_preference"}, { "pcmu", 8000, @"pcmu_preference"}, { "pcma", 8000, @"pcma_preference"}, @@ -152,37 +153,37 @@ struct codec_name_pref_table codec_pref_table[]={ } + (NSSet *)unsupportedCodecs { - NSMutableSet *set = [NSMutableSet set]; + NSMutableSet *set = [NSMutableSet set]; for(int i=0;codec_pref_table[i].name!=NULL;++i) { - PayloadType* available = linphone_core_find_payload_type(theLinphoneCore, - codec_pref_table[i].name, - codec_pref_table[i].rate, - LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS); + PayloadType* available = linphone_core_find_payload_type(theLinphoneCore, + codec_pref_table[i].name, + codec_pref_table[i].rate, + LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS); - if( (available == NULL) - // these two codecs should not be hidden, even if not supported - && ![codec_pref_table[i].prefname isEqualToString:@"h264_preference"] - && ![codec_pref_table[i].prefname isEqualToString:@"mp4v-es_preference"] - ) - { - [set addObject:codec_pref_table[i].prefname]; + if( (available == NULL) + // these two codecs should not be hidden, even if not supported + && ![codec_pref_table[i].prefname isEqualToString:@"h264_preference"] + && ![codec_pref_table[i].prefname isEqualToString:@"mp4v-es_preference"] + ) + { + [set addObject:codec_pref_table[i].prefname]; } } return set; } + (BOOL)isCodecSupported: (const char *)codecName { - return (codecName != NULL) && - (NULL != linphone_core_find_payload_type(theLinphoneCore, codecName, - LINPHONE_FIND_PAYLOAD_IGNORE_RATE, - LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS)); + return (codecName != NULL) && + (NULL != linphone_core_find_payload_type(theLinphoneCore, codecName, + LINPHONE_FIND_PAYLOAD_IGNORE_RATE, + LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS)); } + (BOOL)runningOnIpad { #ifdef UI_USER_INTERFACE_IDIOM - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); + return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); #else - return NO; + return NO; #endif } @@ -197,84 +198,84 @@ struct codec_name_pref_table codec_pref_table[]={ sysctlbyname("hw.machine", machine, &size, NULL, 0); NSString *platform = [[NSString alloc ] initWithUTF8String:machine]; free(machine); - + result = ![platform isEqualToString:@"iPhone1,2"]; - + [platform release]; done=TRUE; } - return result; + return result; } + (NSString *)getUserAgent { - return [NSString stringWithFormat:@"LinphoneIphone/%@ (Linphone/%s; Apple %@/%@)", - [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey], - linphone_core_get_version(), - [UIDevice currentDevice].systemName, - [UIDevice currentDevice].systemVersion]; + return [NSString stringWithFormat:@"LinphoneIphone/%@ (Linphone/%s; Apple %@/%@)", + [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey], + linphone_core_get_version(), + [UIDevice currentDevice].systemName, + [UIDevice currentDevice].systemVersion]; } + (LinphoneManager*)instance { - if(theLinphoneManager == nil) { - theLinphoneManager = [LinphoneManager alloc]; - [theLinphoneManager init]; - } + if(theLinphoneManager == nil) { + theLinphoneManager = [LinphoneManager alloc]; + [theLinphoneManager init]; + } return theLinphoneManager; } #ifdef DEBUG + (void)instanceRelease { - if(theLinphoneManager != nil) { - [theLinphoneManager release]; - theLinphoneManager = nil; - } + if(theLinphoneManager != nil) { + [theLinphoneManager release]; + theLinphoneManager = nil; + } } #endif #pragma mark - Lifecycle Functions - (id)init { - if ((self = [super init])) { - AudioSessionInitialize(NULL, NULL, NULL, NULL); - OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, self); - if (lStatus) { - [LinphoneLogger logc:LinphoneLoggerError format:"cannot register route change handler [%ld]",lStatus]; - } - - // Sounds - { - NSString *path = [[NSBundle mainBundle] pathForResource:@"ring" ofType:@"wav"]; - sounds.call = 0; - OSStatus status = AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &sounds.call); - if(status != 0){ - [LinphoneLogger log:LinphoneLoggerWarning format:@"Can't set \"call\" system sound"]; - } - } - { - NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"]; - sounds.message = 0; - OSStatus status = AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &sounds.message); - if(status != 0){ - [LinphoneLogger log:LinphoneLoggerWarning format:@"Can't set \"message\" system sound"]; - } - } - sounds.vibrate = kSystemSoundID_Vibrate; - - logs = [[NSMutableArray alloc] init]; - database = NULL; - speakerEnabled = FALSE; - bluetoothEnabled = FALSE; - tunnelMode = FALSE; - [self copyDefaultSettings]; - pendindCallIdFromRemoteNotif = [[NSMutableArray alloc] init ]; - photoLibrary = [[ALAssetsLibrary alloc] init]; - + if ((self = [super init])) { + AudioSessionInitialize(NULL, NULL, NULL, NULL); + OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, self); + if (lStatus) { + [LinphoneLogger logc:LinphoneLoggerError format:"cannot register route change handler [%ld]",lStatus]; + } + + // Sounds + { + NSString *path = [[NSBundle mainBundle] pathForResource:@"ring" ofType:@"wav"]; + sounds.call = 0; + OSStatus status = AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &sounds.call); + if(status != 0){ + [LinphoneLogger log:LinphoneLoggerWarning format:@"Can't set \"call\" system sound"]; + } + } + { + NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"]; + sounds.message = 0; + OSStatus status = AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &sounds.message); + if(status != 0){ + [LinphoneLogger log:LinphoneLoggerWarning format:@"Can't set \"message\" system sound"]; + } + } + sounds.vibrate = kSystemSoundID_Vibrate; + + logs = [[NSMutableArray alloc] init]; + database = NULL; + speakerEnabled = FALSE; + bluetoothEnabled = FALSE; + tunnelMode = FALSE; + [self copyDefaultSettings]; + pendindCallIdFromRemoteNotif = [[NSMutableArray alloc] init ]; + photoLibrary = [[ALAssetsLibrary alloc] init]; + NSString* factoryConfig = [LinphoneManager bundleFile:[LinphoneManager runningOnIpad]?@"linphonerc-factory~ipad":@"linphonerc-factory"]; NSString *confiFileName = [LinphoneManager documentFile:@".linphonerc"]; configDb=lp_config_new_with_factory([confiFileName cStringUsingEncoding:[NSString defaultCStringEncoding]] , [factoryConfig cStringUsingEncoding:[NSString defaultCStringEncoding]]); - - [self migrateFromUserPrefs]; - + + [self migrateFromUserPrefs]; + //set default values for first boot if (lp_config_get_string(configDb,LINPHONERC_APPLICATION_KEY,"debugenable_preference",NULL)==NULL){ #ifdef DEBUG @@ -283,201 +284,201 @@ struct codec_name_pref_table codec_pref_table[]={ [self lpConfigSetBool:FALSE forKey:@"debugenable_preference"]; #endif } - } - return self; + } + return self; } - (void)dealloc { - if(sounds.call) { - AudioServicesDisposeSystemSoundID(sounds.call); - } - if(sounds.message) { - AudioServicesDisposeSystemSoundID(sounds.message); - } - - [fastAddressBook release]; - [logs release]; - - OSStatus lStatus = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, self); + if(sounds.call) { + AudioServicesDisposeSystemSoundID(sounds.call); + } + if(sounds.message) { + AudioServicesDisposeSystemSoundID(sounds.message); + } + + [fastAddressBook release]; + [logs release]; + + OSStatus lStatus = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, self); if (lStatus) { [LinphoneLogger logc:LinphoneLoggerError format:"cannot un register route change handler [%ld]", lStatus]; } - [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneGlobalStateUpdate]; - [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneConfiguringStateUpdate]; + [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneGlobalStateUpdate]; + [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneConfiguringStateUpdate]; - [photoLibrary release]; + [photoLibrary release]; [pendindCallIdFromRemoteNotif release]; - [super dealloc]; + [super dealloc]; } #pragma mark - Database Functions static int check_should_migrate_images(void* data ,int argc,char** argv,char** cnames){ - *((BOOL*)data) = TRUE; - return 0; + *((BOOL*)data) = TRUE; + return 0; } - (BOOL)migrateChatDBIfNeeded:(LinphoneCore*)lc { - sqlite3* newDb; - char *errMsg; - NSError* error; - NSString *oldDbPath = [LinphoneManager documentFile:kLinphoneOldChatDBFilename]; - NSString *newDbPath = [LinphoneManager documentFile:kLinphoneInternalChatDBFilename]; - BOOL shouldMigrate = [[NSFileManager defaultManager] fileExistsAtPath:oldDbPath]; - BOOL shouldMigrateImages = FALSE; - LinphoneProxyConfig* default_proxy; - const char* identity = NULL; - BOOL migrated = FALSE; - char* attach_stmt = NULL; + sqlite3* newDb; + char *errMsg; + NSError* error; + NSString *oldDbPath = [LinphoneManager documentFile:kLinphoneOldChatDBFilename]; + NSString *newDbPath = [LinphoneManager documentFile:kLinphoneInternalChatDBFilename]; + BOOL shouldMigrate = [[NSFileManager defaultManager] fileExistsAtPath:oldDbPath]; + BOOL shouldMigrateImages = FALSE; + LinphoneProxyConfig* default_proxy; + const char* identity = NULL; + BOOL migrated = FALSE; + char* attach_stmt = NULL; - linphone_core_get_default_proxy(lc, &default_proxy); + linphone_core_get_default_proxy(lc, &default_proxy); if( sqlite3_open([newDbPath UTF8String], &newDb) != SQLITE_OK) { - [LinphoneLogger log:LinphoneLoggerError format:@"Can't open \"%@\" sqlite3 database.", newDbPath]; + [LinphoneLogger log:LinphoneLoggerError format:@"Can't open \"%@\" sqlite3 database.", newDbPath]; return FALSE; - } + } - const char* check_appdata = "SELECT url,message FROM history WHERE url LIKE 'assets-library%' OR message LIKE 'assets-library%' LIMIT 1;"; - // will set "needToMigrateImages to TRUE if a result comes by - sqlite3_exec(newDb, check_appdata, check_should_migrate_images, &shouldMigrateImages, NULL); - if( !shouldMigrate && !shouldMigrateImages ) { - sqlite3_close(newDb); - return FALSE; - } + const char* check_appdata = "SELECT url,message FROM history WHERE url LIKE 'assets-library%' OR message LIKE 'assets-library%' LIMIT 1;"; + // will set "needToMigrateImages to TRUE if a result comes by + sqlite3_exec(newDb, check_appdata, check_should_migrate_images, &shouldMigrateImages, NULL); + if( !shouldMigrate && !shouldMigrateImages ) { + sqlite3_close(newDb); + return FALSE; + } - [LinphoneLogger logc:LinphoneLoggerLog format:"Starting migration procedure"]; + [LinphoneLogger logc:LinphoneLoggerLog format:"Starting migration procedure"]; - if( shouldMigrate ){ + if( shouldMigrate ){ - // attach old database to the new one: - attach_stmt = sqlite3_mprintf("ATTACH DATABASE %Q AS oldchats", [oldDbPath UTF8String]); - if( sqlite3_exec(newDb, attach_stmt, NULL, NULL, &errMsg) != SQLITE_OK ){ - [LinphoneLogger logc:LinphoneLoggerError format:"Can't attach old chat table, error[%s] ", errMsg]; - sqlite3_free(errMsg); - goto exit_dbmigration; - } + // attach old database to the new one: + attach_stmt = sqlite3_mprintf("ATTACH DATABASE %Q AS oldchats", [oldDbPath UTF8String]); + if( sqlite3_exec(newDb, attach_stmt, NULL, NULL, &errMsg) != SQLITE_OK ){ + [LinphoneLogger logc:LinphoneLoggerError format:"Can't attach old chat table, error[%s] ", errMsg]; + sqlite3_free(errMsg); + goto exit_dbmigration; + } - // migrate old chats to the new db. The iOS stores timestamp in UTC already, so we can directly put it in the 'utc' field and set 'time' to -1 - const char* migration_statement = "INSERT INTO history (localContact,remoteContact,direction,message,utc,read,status,time) " - "SELECT localContact,remoteContact,direction,message,time,read,state,'-1' FROM oldchats.chat"; + // migrate old chats to the new db. The iOS stores timestamp in UTC already, so we can directly put it in the 'utc' field and set 'time' to -1 + const char* migration_statement = "INSERT INTO history (localContact,remoteContact,direction,message,utc,read,status,time) " + "SELECT localContact,remoteContact,direction,message,time,read,state,'-1' FROM oldchats.chat"; - if( sqlite3_exec(newDb, migration_statement, NULL, NULL, &errMsg) != SQLITE_OK ){ - [LinphoneLogger logc:LinphoneLoggerError format:"DB migration failed, error[%s] ", errMsg]; - sqlite3_free(errMsg); - goto exit_dbmigration; - } + if( sqlite3_exec(newDb, migration_statement, NULL, NULL, &errMsg) != SQLITE_OK ){ + [LinphoneLogger logc:LinphoneLoggerError format:"DB migration failed, error[%s] ", errMsg]; + sqlite3_free(errMsg); + goto exit_dbmigration; + } - // invert direction of old messages, because iOS was storing the direction flag incorrectly - const char* invert_direction = "UPDATE history SET direction = NOT direction"; - if( sqlite3_exec(newDb, invert_direction, NULL, NULL, &errMsg) != SQLITE_OK){ - [LinphoneLogger log: LinphoneLoggerError format:@"Inverting direction failed, error[%s]", errMsg]; - sqlite3_free(errMsg); - goto exit_dbmigration; - } + // invert direction of old messages, because iOS was storing the direction flag incorrectly + const char* invert_direction = "UPDATE history SET direction = NOT direction"; + if( sqlite3_exec(newDb, invert_direction, NULL, NULL, &errMsg) != SQLITE_OK){ + [LinphoneLogger log: LinphoneLoggerError format:@"Inverting direction failed, error[%s]", errMsg]; + sqlite3_free(errMsg); + goto exit_dbmigration; + } - // replace empty from: or to: by the current identity. - if( default_proxy ){ - identity = linphone_proxy_config_get_identity(default_proxy); - } - if( !identity ){ - identity = "sip:unknown@sip.linphone.org"; - } + // replace empty from: or to: by the current identity. + if( default_proxy ){ + identity = linphone_proxy_config_get_identity(default_proxy); + } + if( !identity ){ + identity = "sip:unknown@sip.linphone.org"; + } - char* from_conversion = sqlite3_mprintf("UPDATE history SET localContact = %Q WHERE localContact = ''", identity); - if( sqlite3_exec(newDb, from_conversion, NULL, NULL, &errMsg) != SQLITE_OK ){ - [LinphoneLogger logc:LinphoneLoggerError format:"FROM conversion failed, error[%s] ", errMsg]; - sqlite3_free(errMsg); - } - sqlite3_free(from_conversion); + char* from_conversion = sqlite3_mprintf("UPDATE history SET localContact = %Q WHERE localContact = ''", identity); + if( sqlite3_exec(newDb, from_conversion, NULL, NULL, &errMsg) != SQLITE_OK ){ + [LinphoneLogger logc:LinphoneLoggerError format:"FROM conversion failed, error[%s] ", errMsg]; + sqlite3_free(errMsg); + } + sqlite3_free(from_conversion); - char* to_conversion = sqlite3_mprintf("UPDATE history SET remoteContact = %Q WHERE remoteContact = ''", identity); - if( sqlite3_exec(newDb, to_conversion, NULL, NULL, &errMsg) != SQLITE_OK ){ - [LinphoneLogger logc:LinphoneLoggerError format:"DB migration failed, error[%s] ", errMsg]; - sqlite3_free(errMsg); - } - sqlite3_free(to_conversion); - - } + char* to_conversion = sqlite3_mprintf("UPDATE history SET remoteContact = %Q WHERE remoteContact = ''", identity); + if( sqlite3_exec(newDb, to_conversion, NULL, NULL, &errMsg) != SQLITE_OK ){ + [LinphoneLogger logc:LinphoneLoggerError format:"DB migration failed, error[%s] ", errMsg]; + sqlite3_free(errMsg); + } + sqlite3_free(to_conversion); - // local image paths were stored in the 'message' field historically. They were - // very temporarily stored in the 'url' field, and now we migrated them to a JSON- - // encoded field. These are the migration steps to migrate them. + } - // move already stored images from the messages to the appdata JSON field - const char* assetslib_migration = "UPDATE history SET appdata='{\"localimage\":\"'||message||'\"}' , message='' WHERE message LIKE 'assets-library%'"; - if( sqlite3_exec(newDb, assetslib_migration, NULL, NULL, &errMsg) != SQLITE_OK ){ - [LinphoneLogger logc:LinphoneLoggerError format:"Assets-history migration for MESSAGE failed, error[%s] ", errMsg]; - sqlite3_free(errMsg); - } + // local image paths were stored in the 'message' field historically. They were + // very temporarily stored in the 'url' field, and now we migrated them to a JSON- + // encoded field. These are the migration steps to migrate them. - // move already stored images from the url to the appdata JSON field - const char* assetslib_migration_fromurl = "UPDATE history SET appdata='{\"localimage\":\"'||url||'\"}' , url='' WHERE url LIKE 'assets-library%'"; - if( sqlite3_exec(newDb, assetslib_migration_fromurl, NULL, NULL, &errMsg) != SQLITE_OK ){ - [LinphoneLogger logc:LinphoneLoggerError format:"Assets-history migration for URL failed, error[%s] ", errMsg]; - sqlite3_free(errMsg); - } + // move already stored images from the messages to the appdata JSON field + const char* assetslib_migration = "UPDATE history SET appdata='{\"localimage\":\"'||message||'\"}' , message='' WHERE message LIKE 'assets-library%'"; + if( sqlite3_exec(newDb, assetslib_migration, NULL, NULL, &errMsg) != SQLITE_OK ){ + [LinphoneLogger logc:LinphoneLoggerError format:"Assets-history migration for MESSAGE failed, error[%s] ", errMsg]; + sqlite3_free(errMsg); + } - // We will lose received messages with remote url, they will be displayed in plain. We can't do much for them.. - migrated = TRUE; + // move already stored images from the url to the appdata JSON field + const char* assetslib_migration_fromurl = "UPDATE history SET appdata='{\"localimage\":\"'||url||'\"}' , url='' WHERE url LIKE 'assets-library%'"; + if( sqlite3_exec(newDb, assetslib_migration_fromurl, NULL, NULL, &errMsg) != SQLITE_OK ){ + [LinphoneLogger logc:LinphoneLoggerError format:"Assets-history migration for URL failed, error[%s] ", errMsg]; + sqlite3_free(errMsg); + } + + // We will lose received messages with remote url, they will be displayed in plain. We can't do much for them.. + migrated = TRUE; exit_dbmigration: - if( attach_stmt ) sqlite3_free(attach_stmt); + if( attach_stmt ) sqlite3_free(attach_stmt); - sqlite3_close(newDb); + sqlite3_close(newDb); - // in any case, we should remove the old chat db - if( shouldMigrate && ![[NSFileManager defaultManager] removeItemAtPath:oldDbPath error:&error] ){ - [LinphoneLogger logc:LinphoneLoggerError format:"Could not remove old chat DB: %@", error]; - } + // in any case, we should remove the old chat db + if( shouldMigrate && ![[NSFileManager defaultManager] removeItemAtPath:oldDbPath error:&error] ){ + [LinphoneLogger logc:LinphoneLoggerError format:"Could not remove old chat DB: %@", error]; + } - [LinphoneLogger log:LinphoneLoggerLog format:@"Message storage migration finished: success = %@", migrated ? @"TRUE":@"FALSE"]; - return migrated; + [LinphoneLogger log:LinphoneLoggerLog format:@"Message storage migration finished: success = %@", migrated ? @"TRUE":@"FALSE"]; + return migrated; } - (void)migrateFromUserPrefs { - static const char* migration_flag = "userpref_migration_done"; + static const char* migration_flag = "userpref_migration_done"; - if( configDb == nil ) return; + if( configDb == nil ) return; - if( lp_config_get_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 0) ){ - Linphone_log(@"UserPrefs migration already performed, skip"); - return; - } + if( lp_config_get_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 0) ){ + Linphone_log(@"UserPrefs migration already performed, skip"); + return; + } - NSDictionary* defaults = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]; - NSArray* defaults_keys = [defaults allKeys]; - NSDictionary* values = @{@"backgroundmode_preference" :@YES, - @"debugenable_preference" :@NO, - @"start_at_boot_preference" :@YES}; - BOOL shouldSync = FALSE; + NSDictionary* defaults = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]; + NSArray* defaults_keys = [defaults allKeys]; + NSDictionary* values = @{@"backgroundmode_preference" :@YES, + @"debugenable_preference" :@NO, + @"start_at_boot_preference" :@YES}; + BOOL shouldSync = FALSE; - Linphone_log(@"%d user prefs", [defaults_keys count]); + Linphone_log(@"%d user prefs", [defaults_keys count]); - for( NSString* userpref in values ){ - if( [defaults_keys containsObject:userpref] ){ - Linphone_log(@"Migrating %@ from user preferences: %d", userpref, [[defaults objectForKey:userpref] boolValue]); - lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[defaults objectForKey:userpref] boolValue]); - [[NSUserDefaults standardUserDefaults] removeObjectForKey:userpref]; - shouldSync = TRUE; - } else if ( lp_config_get_string(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], NULL) == NULL ){ - // no default value found in our linphonerc, we need to add them - lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[values objectForKey:userpref] boolValue]); - } - } + for( NSString* userpref in values ){ + if( [defaults_keys containsObject:userpref] ){ + Linphone_log(@"Migrating %@ from user preferences: %d", userpref, [[defaults objectForKey:userpref] boolValue]); + lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[defaults objectForKey:userpref] boolValue]); + [[NSUserDefaults standardUserDefaults] removeObjectForKey:userpref]; + shouldSync = TRUE; + } else if ( lp_config_get_string(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], NULL) == NULL ){ + // no default value found in our linphonerc, we need to add them + lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[values objectForKey:userpref] boolValue]); + } + } - if( shouldSync ){ - Linphone_log(@"Synchronizing..."); - [[NSUserDefaults standardUserDefaults] synchronize]; - } - // don't get back here in the future - lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 1); + if( shouldSync ){ + Linphone_log(@"Synchronizing..."); + [[NSUserDefaults standardUserDefaults] synchronize]; + } + // don't get back here in the future + lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 1); } @@ -491,33 +492,33 @@ exit_dbmigration: } + (BOOL)isLcReady { - return theLinphoneCore != nil; + return theLinphoneCore != nil; } #pragma mark Debug functions struct _entry_data { - const LpConfig* conf; - const char* section; + const LpConfig* conf; + const char* section; }; static void dump_entry(const char* entry, void*data) { - struct _entry_data *d = (struct _entry_data*)data; - const char* value = lp_config_get_string(d->conf, d->section, entry, ""); - [LinphoneLogger log:LinphoneLoggerLog format:@"%s=%s", entry, value]; + struct _entry_data *d = (struct _entry_data*)data; + const char* value = lp_config_get_string(d->conf, d->section, entry, ""); + [LinphoneLogger log:LinphoneLoggerLog format:@"%s=%s", entry, value]; } static void dump_section(const char* section, void* data){ - [LinphoneLogger log:LinphoneLoggerLog format:@"[%s]", section ]; - struct _entry_data d = {(const LpConfig*)data, section}; - lp_config_for_each_entry((const LpConfig*)data, section, dump_entry, &d); + [LinphoneLogger log:LinphoneLoggerLog format:@"[%s]", section ]; + struct _entry_data d = {(const LpConfig*)data, section}; + lp_config_for_each_entry((const LpConfig*)data, section, dump_entry, &d); } + (void)dumpLCConfig { - if (theLinphoneCore ){ + if (theLinphoneCore ){ LpConfig *conf=[LinphoneManager instance].configDb; lp_config_for_each_section(conf, dump_section, conf); - } + } } @@ -528,33 +529,33 @@ void linphone_iphone_log_handler(int lev, const char *fmt, va_list args){ NSString* format = [[NSString alloc] initWithUTF8String:fmt]; NSLogv(format, args); // NSString* formatedString = [[NSString alloc] initWithFormat:format arguments:args]; -// +// // dispatch_async(dispatch_get_main_queue(), ^{ // if([[LinphoneManager instance].logs count] >= LINPHONE_LOGS_MAX_ENTRY) { // [[LinphoneManager instance].logs removeObjectAtIndex:0]; // } // [[LinphoneManager instance].logs addObject:formatedString]; -// +// // // Post event // NSDictionary *dict = [NSDictionary dictionaryWithObject:formatedString forKey:@"log"]; // [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneLogsUpdate object:[LinphoneManager instance] userInfo:dict]; // }); -// +// // [formatedString release]; - [format release]; + [format release]; } -//Error/warning log handler +//Error/warning log handler static void linphone_iphone_log(struct _LinphoneCore * lc, const char * message) { - NSString* log = [NSString stringWithCString:message encoding:[NSString defaultCStringEncoding]]; + NSString* log = [NSString stringWithCString:message encoding:[NSString defaultCStringEncoding]]; NSLog(log, NULL); - + // dispatch_async(dispatch_get_main_queue(), ^{ // if([[LinphoneManager instance].logs count] >= LINPHONE_LOGS_MAX_ENTRY) { // [[LinphoneManager instance].logs removeObjectAtIndex:0]; // } // [[LinphoneManager instance].logs addObject:log]; -// +// // // Post event // NSDictionary *dict = [NSDictionary dictionaryWithObject:log forKey:@"log"]; // [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneLogsUpdate object:[LinphoneManager instance] userInfo:dict]; @@ -565,83 +566,83 @@ static void linphone_iphone_log(struct _LinphoneCore * lc, const char * message) #pragma mark - Display Status Functions - (void)displayStatus:(NSString*) message { - // Post event - NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: - message, @"message", - nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneDisplayStatusUpdate object:self userInfo:dict]; + // Post event + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + message, @"message", + nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneDisplayStatusUpdate object:self userInfo:dict]; } static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char * message) { - NSString* status = [[NSString alloc] initWithCString:message encoding:[NSString defaultCStringEncoding]]; + NSString* status = [[NSString alloc] initWithCString:message encoding:[NSString defaultCStringEncoding]]; [(LinphoneManager*)linphone_core_get_user_data(lc) displayStatus:status]; - [status release]; + [status release]; } #pragma mark - Call State Functions - (void)localNotifContinue:(NSTimer*) timer { - UILocalNotification* notif = [timer userInfo]; - if (notif){ + UILocalNotification* notif = [timer userInfo]; + if (notif){ [LinphoneLogger log:LinphoneLoggerLog format:@"cancelling/presenting local notif"]; - [[UIApplication sharedApplication] cancelLocalNotification:notif]; - [[UIApplication sharedApplication] presentLocalNotificationNow:notif]; - } + [[UIApplication sharedApplication] cancelLocalNotification:notif]; + [[UIApplication sharedApplication] presentLocalNotificationNow:notif]; + } } - (void)onCall:(LinphoneCall*)call StateChanged:(LinphoneCallState)state withMessage:(const char *)message { - + // Handling wrapper LinphoneCallAppData* data=(LinphoneCallAppData*)linphone_call_get_user_pointer(call); if (!data) { - data = [[LinphoneCallAppData alloc] init]; - linphone_call_set_user_pointer(call, data); - } + data = [[LinphoneCallAppData alloc] init]; + linphone_call_set_user_pointer(call, data); + } - if (silentPushCompletion) { + if (silentPushCompletion) { - // we were woken up by a silent push. Call the completion handler with NEWDATA - // so that the push is notified to the user - [LinphoneLogger log:LinphoneLoggerLog format:@"onCall - handler %p", silentPushCompletion]; - silentPushCompletion(UIBackgroundFetchResultNewData); - silentPushCompletion = nil; - } + // we were woken up by a silent push. Call the completion handler with NEWDATA + // so that the push is notified to the user + [LinphoneLogger log:LinphoneLoggerLog format:@"onCall - handler %p", silentPushCompletion]; + silentPushCompletion(UIBackgroundFetchResultNewData); + silentPushCompletion = nil; + } + + 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"; + } - 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 (state == LinphoneCallIncomingReceived) { - + /*first step is to re-enable ctcall center*/ CTCallCenter* lCTCallCenter = [[CTCallCenter alloc] init]; - + /*should we reject this call ?*/ if ([lCTCallCenter currentCalls]!=nil) { char *tmp=linphone_call_get_remote_address_as_string(call); @@ -654,30 +655,30 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char return; } [lCTCallCenter release]; - + if( [[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] && [UIApplication sharedApplication].applicationState != UIApplicationStateActive) { - + LinphoneCallLog* callLog=linphone_call_get_call_log(call); NSString* callId=[NSString stringWithUTF8String:linphone_call_log_get_call_id(callLog)]; - + 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->timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(localNotifContinue:) userInfo:data->notification repeats:TRUE]; + data->timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(localNotifContinue:) userInfo:data->notification repeats:TRUE]; - data->notification.repeatInterval = 0; - data->notification.category = @"incoming_call"; + data->notification.repeatInterval = 0; + data->notification.category = @"incoming_call"; data->notification.alertBody =[NSString stringWithFormat:NSLocalizedString(@"IC_MSG",nil), address]; data->notification.alertAction = NSLocalizedString(@"Answer", nil); data->notification.soundName = @"shortring.caf"; data->notification.userInfo = @{@"callId": callId, @"timer":[NSNumber numberWithInt:1] }; - data->notification.applicationIconBadgeNumber = 1; + data->notification.applicationIconBadgeNumber = 1; [[UIApplication sharedApplication] presentLocalNotificationNow:data->notification]; - + if (!incallBgTask){ incallBgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ [LinphoneLogger log:LinphoneLoggerWarning format:@"Call cannot ring any more, too late"]; @@ -685,87 +686,87 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char incallBgTask=0; }]; - [[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes]; + [[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes]; } - + } } } } - // we keep the speaker auto-enabled state in this static so that we don't - // force-enable it on ICE re-invite if the user disabled it. - static BOOL speaker_already_enabled = FALSE; + // we keep the speaker auto-enabled state in this static so that we don't + // force-enable it on ICE re-invite if the user disabled it. + static BOOL speaker_already_enabled = FALSE; - // Disable speaker when no more call - if ((state == LinphoneCallEnd || state == LinphoneCallError)) { - speaker_already_enabled = FALSE; - if(linphone_core_get_calls_nb(theLinphoneCore) == 0) { - [self setSpeakerEnabled:FALSE]; + // Disable speaker when no more call + if ((state == LinphoneCallEnd || state == LinphoneCallError)) { + speaker_already_enabled = FALSE; + if(linphone_core_get_calls_nb(theLinphoneCore) == 0) { + [self setSpeakerEnabled:FALSE]; [self removeCTCallCenterCb]; - bluetoothAvailable = FALSE; - bluetoothEnabled = FALSE; - /*IOS specific*/ - linphone_core_start_dtmf_stream(theLinphoneCore); + bluetoothAvailable = FALSE; + bluetoothEnabled = FALSE; + /*IOS specific*/ + linphone_core_start_dtmf_stream(theLinphoneCore); } 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; - } - [[UIApplication sharedApplication] cancelLocalNotification:data->notification]; - - [data->notification release]; - 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]; - [notification release]; - } - - } - } - - if(state == LinphoneCallReleased) { - if(data != NULL) { - [data release]; - linphone_call_set_user_pointer(call, NULL); - } - } - - // Enable speaker when video - if(state == LinphoneCallIncomingReceived || - state == LinphoneCallOutgoingInit || - state == LinphoneCallConnected || - state == LinphoneCallStreamsRunning) { - if (linphone_call_params_video_enabled(linphone_call_get_current_params(call)) && !speaker_already_enabled) { - [self setSpeakerEnabled:TRUE]; - speaker_already_enabled = TRUE; - } - } + } + if(data != nil && data->notification != nil) { + LinphoneCallLog *log = linphone_call_get_call_log(call); - if (state == LinphoneCallConnected && !mCallCenter) { + // cancel local notif if needed + if( data->timer ){ + [data->timer invalidate]; + data->timer = nil; + } + [[UIApplication sharedApplication] cancelLocalNotification:data->notification]; + + [data->notification release]; + 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]; + [notification release]; + } + + } + } + + if(state == LinphoneCallReleased) { + if(data != NULL) { + [data release]; + linphone_call_set_user_pointer(call, NULL); + } + } + + // Enable speaker when video + if(state == LinphoneCallIncomingReceived || + state == LinphoneCallOutgoingInit || + state == LinphoneCallConnected || + state == LinphoneCallStreamsRunning) { + if (linphone_call_params_video_enabled(linphone_call_get_current_params(call)) && !speaker_already_enabled) { + [self setSpeakerEnabled:TRUE]; + speaker_already_enabled = 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", - [NSNumber numberWithInt:state], @"state", - [NSString stringWithUTF8String:message], @"message", nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self userInfo:dict]; + // Post event + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSValue valueWithPointer:call], @"call", + [NSNumber numberWithInt:state], @"state", + [NSString stringWithUTF8String:message], @"message", nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self userInfo:dict]; } static void linphone_iphone_call_state(LinphoneCore *lc, LinphoneCall* call, LinphoneCallState state,const char* message) { @@ -781,73 +782,73 @@ static void linphone_iphone_transfer_state_changed(LinphoneCore* lc, LinphoneCal #pragma mark - Global state change static void linphone_iphone_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) { - [(LinphoneManager*)linphone_core_get_user_data(lc) onGlobalStateChanged:gstate withMessage:message]; + [(LinphoneManager*)linphone_core_get_user_data(lc) onGlobalStateChanged:gstate withMessage:message]; } -(void)onGlobalStateChanged:(LinphoneGlobalState)state withMessage:(const char*)message { - [LinphoneLogger log:LinphoneLoggerLog format:@"onGlobalStateChanged: %d (message: %s)", state, message]; + [LinphoneLogger log:LinphoneLoggerLog format:@"onGlobalStateChanged: %d (message: %s)", state, message]; - NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:state], @"state", - [NSString stringWithUTF8String:message?message:""], @"message", - nil]; + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:state], @"state", + [NSString stringWithUTF8String:message?message:""], @"message", + nil]; - // dispatch the notification asynchronously - dispatch_async(dispatch_get_main_queue(), ^(void){ - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneGlobalStateUpdate object:self userInfo:dict]; - }); + // dispatch the notification asynchronously + dispatch_async(dispatch_get_main_queue(), ^(void){ + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneGlobalStateUpdate object:self userInfo:dict]; + }); } -(void)globalStateChangedNotificationHandler:(NSNotification*)notif { - if( (LinphoneGlobalState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneGlobalOn){ - [self finishCoreConfiguration]; - } + if( (LinphoneGlobalState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneGlobalOn){ + [self finishCoreConfiguration]; + } } #pragma mark - Configuring status changed static void linphone_iphone_configuring_status_changed(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) { - [(LinphoneManager*)linphone_core_get_user_data(lc) onConfiguringStatusChanged:status withMessage:message]; + [(LinphoneManager*)linphone_core_get_user_data(lc) onConfiguringStatusChanged:status withMessage:message]; } -(void)onConfiguringStatusChanged:(LinphoneConfiguringState)status withMessage:(const char*)message { - [LinphoneLogger log:LinphoneLoggerLog format:@"onConfiguringStatusChanged: %d (message: %s)", status, message]; + [LinphoneLogger log:LinphoneLoggerLog format:@"onConfiguringStatusChanged: %d (message: %s)", status, message]; - NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:status], @"state", - [NSString stringWithUTF8String:message?message:""], @"message", - nil]; + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:status], @"state", + [NSString stringWithUTF8String:message?message:""], @"message", + nil]; - // dispatch the notification asynchronously - dispatch_async(dispatch_get_main_queue(), ^(void){ - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneConfiguringStateUpdate object:self userInfo:dict]; - }); + // dispatch the notification asynchronously + dispatch_async(dispatch_get_main_queue(), ^(void){ + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneConfiguringStateUpdate object:self userInfo:dict]; + }); } -(void)configuringStateChangedNotificationHandler:(NSNotification*)notif { - if( (LinphoneConfiguringState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneConfiguringSuccessful){ - wasRemoteProvisioned = TRUE; - } else { - wasRemoteProvisioned = FALSE; - } + if( (LinphoneConfiguringState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneConfiguringSuccessful){ + wasRemoteProvisioned = TRUE; + } else { + wasRemoteProvisioned = FALSE; + } } #pragma mark - Registration State Functions - (void)onRegister:(LinphoneCore *)lc cfg:(LinphoneProxyConfig*) cfg state:(LinphoneRegistrationState) state message:(const char*) message { - [LinphoneLogger logc:LinphoneLoggerLog format:"NEW REGISTRATION STATE: '%s' (message: '%s')", linphone_registration_state_to_string(state), message]; - - // Post event - NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:state], @"state", - [NSValue valueWithPointer:cfg], @"cfg", - [NSString stringWithUTF8String:message], @"message", - nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneRegistrationUpdate object:self userInfo:dict]; + [LinphoneLogger logc:LinphoneLoggerLog format:"NEW REGISTRATION STATE: '%s' (message: '%s')", linphone_registration_state_to_string(state), message]; + + // Post event + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:state], @"state", + [NSValue valueWithPointer:cfg], @"cfg", + [NSString stringWithUTF8String:message], @"message", + nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneRegistrationUpdate object:self userInfo:dict]; } static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyConfig* cfg, LinphoneRegistrationState state,const char* message) { @@ -859,74 +860,90 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo - (void)onMessageReceived:(LinphoneCore *)lc room:(LinphoneChatRoom *)room message:(LinphoneChatMessage*)msg { - if (silentPushCompletion) { + if (silentPushCompletion) { - // we were woken up by a silent push. Call the completion handler with NEWDATA - // so that the push is notified to the user - [LinphoneLogger log:LinphoneLoggerLog format:@"onMessageReceived - handler %p", silentPushCompletion]; - silentPushCompletion(UIBackgroundFetchResultNewData); - silentPushCompletion = nil; - } - - if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] + // we were woken up by a silent push. Call the completion handler with NEWDATA + // so that the push is notified to the user + [LinphoneLogger log:LinphoneLoggerLog format:@"onMessageReceived - handler %p", silentPushCompletion]; + silentPushCompletion(UIBackgroundFetchResultNewData); + silentPushCompletion = nil; + } + + if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] && [UIApplication sharedApplication].applicationState != UIApplicationStateActive) { - - const LinphoneAddress* remoteAddress = linphone_chat_message_get_from_address(msg); - char* c_address = linphone_address_as_string_uri_only(remoteAddress); - NSString* address = [NSString stringWithUTF8String:c_address]; - NSString* from_address = [address copy]; - ABRecordRef contact = [fastAddressBook getContact:address]; - if(contact) { - address = [FastAddressBook getContactDisplayName:contact]; - } else { - if ([[LinphoneManager instance] lpConfigBoolForKey:@"show_contacts_emails_preference"] == true) { - LinphoneAddress *linphoneAddress = linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]); - address = [NSString stringWithUTF8String:linphone_address_get_username(linphoneAddress)]; - linphone_address_destroy(linphoneAddress); - } - } - if(address == nil) { - address = @"Unknown"; - } + const LinphoneAddress* remoteAddress = linphone_chat_message_get_from_address(msg); + char* c_address = linphone_address_as_string_uri_only(remoteAddress); + NSString* address = [NSString stringWithUTF8String:c_address]; + NSString* from_address = [address copy]; + + ABRecordRef contact = [fastAddressBook getContact:address]; + if(contact) { + address = [FastAddressBook getContactDisplayName:contact]; + } else { + if ([[LinphoneManager instance] lpConfigBoolForKey:@"show_contacts_emails_preference"] == true) { + LinphoneAddress *linphoneAddress = linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]); + address = [NSString stringWithUTF8String:linphone_address_get_username(linphoneAddress)]; + linphone_address_destroy(linphoneAddress); + } + } + if(address == nil) { + address = @"Unknown"; + } // Create a new notification UILocalNotification* notif = [[[UILocalNotification alloc] init] autorelease]; if (notif) { - notif.repeatInterval = 0; - notif.category = @"incoming_msg"; - notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG",nil), address]; - notif.alertAction = NSLocalizedString(@"Show", nil); - notif.soundName = @"msg.caf"; - notif.userInfo = @{@"from":from_address}; + notif.repeatInterval = 0; + notif.category = @"incoming_msg"; + notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG",nil), address]; + notif.alertAction = NSLocalizedString(@"Show", nil); + notif.soundName = @"msg.caf"; + notif.userInfo = @{@"from":from_address}; + - [[UIApplication sharedApplication] presentLocalNotificationNow:notif]; } - [from_address release]; + [from_address release]; } - - // Post event - NSDictionary* dict = @{@"room" :[NSValue valueWithPointer:room], - @"from_address":[NSValue valueWithPointer:linphone_chat_message_get_from(msg)], - @"message" :[NSValue valueWithPointer:msg]}; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self userInfo:dict]; + + // Post event + NSDictionary* dict = @{@"room" :[NSValue valueWithPointer:room], + @"from_address":[NSValue valueWithPointer:linphone_chat_message_get_from(msg)], + @"message" :[NSValue valueWithPointer:msg]}; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self userInfo:dict]; } static void linphone_iphone_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message) { - [(LinphoneManager*)linphone_core_get_user_data(lc) onMessageReceived:lc room:room message:message]; + [(LinphoneManager*)linphone_core_get_user_data(lc) onMessageReceived:lc room:room message:message]; } -#pragma mark - Message composition start +- (void)onNotifyReceived:(LinphoneCore *)lc event:(LinphoneEvent *)lev notifyEvent:(const char *)notified_event content:(const LinphoneContent *)body { + // Post event + NSMutableDictionary* dict = [NSMutableDictionary dictionary]; + [dict setObject:[NSValue valueWithPointer:lev] forKey:@"event"]; + [dict setObject:[NSString stringWithUTF8String:notified_event] forKey:@"notified_event"]; + if (body != NULL) { + [dict setObject:[NSValue valueWithPointer:body] forKey:@"content"]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneNotifyReceived object:self userInfo:dict]; + +} + +static void linphone_iphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) { + [(LinphoneManager*)linphone_core_get_user_data(lc) onNotifyReceived:lc event:lev notifyEvent:notified_event content:body]; +} + +#pragma mark - Message composition start - (void)onMessageComposeReceived:(LinphoneCore*)core forRoom:(LinphoneChatRoom*)room { - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextComposeEvent - object:self - userInfo:@{@"room":[NSValue valueWithPointer:room]}]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextComposeEvent + object:self + userInfo:@{@"room":[NSValue valueWithPointer:room]}]; } static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room){ - [(LinphoneManager*)linphone_core_get_user_data(lc) onMessageComposeReceived:lc forRoom:room]; + [(LinphoneManager*)linphone_core_get_user_data(lc) onMessageComposeReceived:lc forRoom:room]; } @@ -935,16 +952,16 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat + (void)kickOffNetworkConnection { /*start a new thread to avoid blocking the main ui in case of peer host failure*/ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - CFWriteStreamRef writeStream; - CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200"/*"linphone.org"*/, 15000, nil, &writeStream); - CFWriteStreamOpen (writeStream); - const char* buff="hello"; - CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff)); - CFWriteStreamClose (writeStream); - CFRelease(writeStream); - }); -} + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + CFWriteStreamRef writeStream; + CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200"/*"linphone.org"*/, 15000, nil, &writeStream); + CFWriteStreamOpen (writeStream); + const char* buff="hello"; + CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff)); + CFWriteStreamClose (writeStream); + CFRelease(writeStream); + }); +} static void showNetworkFlags(SCNetworkReachabilityFlags flags){ [LinphoneLogger logc:LinphoneLoggerLog format:"Network connection flags:"]; @@ -976,23 +993,23 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach LinphoneProxyConfig* proxy; linphone_core_get_default_proxy(theLinphoneCore, &proxy); - struct NetworkReachabilityContext* ctx = nilCtx ? ((struct NetworkReachabilityContext*)nilCtx) : 0; + struct NetworkReachabilityContext* ctx = nilCtx ? ((struct NetworkReachabilityContext*)nilCtx) : 0; if ((flags == 0) || (flags & networkDownFlags)) { linphone_core_set_network_reachable(theLinphoneCore, false); lLinphoneMgr.connectivity = none; [LinphoneManager kickOffNetworkConnection]; } else { - LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]); + LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]); Connectivity newConnectivity; BOOL isWifiOnly = lp_config_get_int(lLinphoneMgr.configDb, LINPHONERC_APPLICATION_KEY, "wifi_only_preference",FALSE); - if (!ctx || ctx->testWWan) - newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi; - else - newConnectivity = wifi; + if (!ctx || ctx->testWWan) + newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi; + else + newConnectivity = wifi; - if (newConnectivity == wwan - && proxy - && isWifiOnly + if (newConnectivity == wwan + && proxy + && isWifiOnly && (lLinphoneMgr.connectivity == newConnectivity || lLinphoneMgr.connectivity == none)) { linphone_proxy_config_expires(proxy, 0); } else if (proxy){ @@ -1001,53 +1018,53 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach linphone_proxy_config_expires(proxy, defaultExpire); //else keep default value from linphonecore } - + if (lLinphoneMgr.connectivity != newConnectivity) { - if (tunnel) linphone_tunnel_reconnect(tunnel); + if (tunnel) linphone_tunnel_reconnect(tunnel); // connectivity has changed linphone_core_set_network_reachable(theLinphoneCore,false); if (newConnectivity == wwan && proxy && isWifiOnly) { linphone_proxy_config_expires(proxy, 0); - } + } linphone_core_set_network_reachable(theLinphoneCore,true); linphone_core_iterate(theLinphoneCore); [LinphoneLogger logc:LinphoneLoggerLog format:"Network connectivity changed to type [%s]",(newConnectivity==wifi?"wifi":"wwan")]; } lLinphoneMgr.connectivity=newConnectivity; - switch (lLinphoneMgr.tunnelMode) { - case tunnel_wwan: - linphone_tunnel_enable(tunnel,lLinphoneMgr.connectivity == wwan); - break; - case tunnel_auto: - linphone_tunnel_auto_detect(tunnel); - break; - default: - //nothing to do - break; - } + switch (lLinphoneMgr.tunnelMode) { + case tunnel_wwan: + linphone_tunnel_enable(tunnel,lLinphoneMgr.connectivity == wwan); + break; + case tunnel_auto: + linphone_tunnel_auto_detect(tunnel); + break; + default: + //nothing to do + break; + } } if (ctx && ctx->networkStateChanged) { - (*ctx->networkStateChanged)(lLinphoneMgr.connectivity); - } + (*ctx->networkStateChanged)(lLinphoneMgr.connectivity); + } } } - (void)setupNetworkReachabilityCallback { SCNetworkReachabilityContext *ctx=NULL; - //any internet cnx + //any internet cnx struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; - - if (proxyReachability) { - [LinphoneLogger logc:LinphoneLoggerLog format:"Cancelling old network reachability"]; - SCNetworkReachabilityUnscheduleFromRunLoop(proxyReachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - CFRelease(proxyReachability); - proxyReachability = nil; - } - - proxyReachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress); + + if (proxyReachability) { + [LinphoneLogger logc:LinphoneLoggerLog format:"Cancelling old network reachability"]; + SCNetworkReachabilityUnscheduleFromRunLoop(proxyReachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + CFRelease(proxyReachability); + proxyReachability = nil; + } + + proxyReachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress); if (!SCNetworkReachabilitySetCallback(proxyReachability, (SCNetworkReachabilityCallBack)networkReachabilityCallBack, ctx)){ [LinphoneLogger logc:LinphoneLoggerError format:"Cannot register reachability cb: %s", SCErrorString(SCError())]; @@ -1065,22 +1082,22 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach } - (NetworkType)network { - UIApplication *app = [UIApplication sharedApplication]; - NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews]; - NSNumber *dataNetworkItemView = nil; - - for (id subview in subviews) { - if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) { - dataNetworkItemView = subview; - break; - } - } - NSNumber *number = (NSNumber*)[dataNetworkItemView valueForKey:@"dataNetworkType"]; - return [number intValue]; + UIApplication *app = [UIApplication sharedApplication]; + NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews]; + NSNumber *dataNetworkItemView = nil; + + for (id subview in subviews) { + if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) { + dataNetworkItemView = subview; + break; + } + } + NSNumber *number = (NSNumber*)[dataNetworkItemView valueForKey:@"dataNetworkType"]; + return [number intValue]; } -#pragma mark - +#pragma mark - static LinphoneCoreVTable linphonec_vtable = { .show =NULL, @@ -1096,10 +1113,11 @@ static LinphoneCoreVTable linphonec_vtable = { .text_received=NULL, .message_received=linphone_iphone_message_received, .dtmf_received=NULL, - .transfer_state_changed=linphone_iphone_transfer_state_changed, - .is_composing_received = linphone_iphone_is_composing_received, - .configuring_status = linphone_iphone_configuring_status_changed, - .global_state_changed = linphone_iphone_global_state_changed + .transfer_state_changed=linphone_iphone_transfer_state_changed, + .is_composing_received = linphone_iphone_is_composing_received, + .configuring_status = linphone_iphone_configuring_status_changed, + .global_state_changed = linphone_iphone_global_state_changed, + .notify_received = linphone_iphone_notify_received }; //scheduling loop @@ -1109,105 +1127,105 @@ static LinphoneCoreVTable linphonec_vtable = { - (void)audioSessionInterrupted:(NSNotification *)notification { - int interruptionType = [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue]; - if (interruptionType == AVAudioSessionInterruptionTypeBegan) { - [self beginInterruption]; - } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) { - [self endInterruption]; - } + int interruptionType = [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue]; + if (interruptionType == AVAudioSessionInterruptionTypeBegan) { + [self beginInterruption]; + } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) { + [self endInterruption]; + } } /** Should be called once per linphone_core_new() */ - (void)finishCoreConfiguration { //get default config from bundle - NSString *zrtpSecretsFileName = [LinphoneManager documentFile:@"zrtp_secrets"]; - NSString *chatDBFileName = [LinphoneManager documentFile:kLinphoneInternalChatDBFilename]; - const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; + NSString *zrtpSecretsFileName = [LinphoneManager documentFile:@"zrtp_secrets"]; + NSString *chatDBFileName = [LinphoneManager documentFile:kLinphoneInternalChatDBFilename]; + const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; - linphone_core_set_user_agent(theLinphoneCore,"LinphoneIPhone", - [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey] UTF8String]); + linphone_core_set_user_agent(theLinphoneCore,"LinphoneIPhone", + [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey] UTF8String]); [_contactSipField release]; _contactSipField = [[self lpConfigStringForKey:@"contact_im_type_value" withDefault:@"SIP"] retain]; fastAddressBook = [[FastAddressBook alloc] init]; - linphone_core_set_root_ca(theLinphoneCore, lRootCa); + linphone_core_set_root_ca(theLinphoneCore, lRootCa); // Set audio assets const char* lRing = [[LinphoneManager bundleFile:@"ring.wav"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; linphone_core_set_ring(theLinphoneCore, lRing); const char* lRingBack = [[LinphoneManager bundleFile:@"ringback.wav"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; linphone_core_set_ringback(theLinphoneCore, lRingBack); - const char* lPlay = [[LinphoneManager bundleFile:@"hold.wav"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; + const char* lPlay = [[LinphoneManager bundleFile:@"hold.wav"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; linphone_core_set_play_file(theLinphoneCore, lPlay); linphone_core_set_zrtp_secrets_file(theLinphoneCore, [zrtpSecretsFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); - linphone_core_set_chat_database_path(theLinphoneCore, [chatDBFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); + linphone_core_set_chat_database_path(theLinphoneCore, [chatDBFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); - // we need to proceed to the migration *after* the chat database was opened, so that we know it is in consistent state - BOOL migrated = [self migrateChatDBIfNeeded:theLinphoneCore]; - if( migrated ){ - // if a migration was performed, we should reinitialize the chat database - linphone_core_set_chat_database_path(theLinphoneCore, [chatDBFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); - } + // we need to proceed to the migration *after* the chat database was opened, so that we know it is in consistent state + BOOL migrated = [self migrateChatDBIfNeeded:theLinphoneCore]; + if( migrated ){ + // if a migration was performed, we should reinitialize the chat database + linphone_core_set_chat_database_path(theLinphoneCore, [chatDBFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); + } - /* AVPF migration */ - if( [self lpConfigBoolForKey:@"avpf_migration_done" forSection:@"app"] == FALSE ){ - const MSList* proxies = linphone_core_get_proxy_config_list(theLinphoneCore); - while(proxies){ - LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; - const char* addr = linphone_proxy_config_get_addr(proxy); - // we want to enable AVPF for the proxies - if( addr && strstr(addr, "sip.linphone.org") != 0 ){ - Linphone_log(@"Migrating proxy config to use AVPF"); - linphone_proxy_config_enable_avpf(proxy, TRUE); - } - proxies = proxies->next; - } - [self lpConfigSetBool:TRUE forKey:@"avpf_migration_done"]; - } - /* Quality Reporting migration */ - if( [self lpConfigBoolForKey:@"quality_report_migration_done" forSection:@"app"] == FALSE ){ - const MSList* proxies = linphone_core_get_proxy_config_list(theLinphoneCore); - while(proxies){ - LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; - const char* addr = linphone_proxy_config_get_addr(proxy); - // we want to enable quality reporting for the proxies that are on linphone.org - if( addr && strstr(addr, "sip.linphone.org") != 0 ){ - Linphone_log(@"Migrating proxy config to send quality report"); - linphone_proxy_config_set_quality_reporting_collector(proxy, "sip:voip-metrics@sip.linphone.org"); - linphone_proxy_config_set_quality_reporting_interval(proxy, 180); - linphone_proxy_config_enable_quality_reporting(proxy, TRUE); - } - proxies = proxies->next; - } - [self lpConfigSetBool:TRUE forKey:@"quality_report_migration_done"]; - } + /* AVPF migration */ + if( [self lpConfigBoolForKey:@"avpf_migration_done" forSection:@"app"] == FALSE ){ + const MSList* proxies = linphone_core_get_proxy_config_list(theLinphoneCore); + while(proxies){ + LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; + const char* addr = linphone_proxy_config_get_addr(proxy); + // we want to enable AVPF for the proxies + if( addr && strstr(addr, "sip.linphone.org") != 0 ){ + Linphone_log(@"Migrating proxy config to use AVPF"); + linphone_proxy_config_enable_avpf(proxy, TRUE); + } + proxies = proxies->next; + } + [self lpConfigSetBool:TRUE forKey:@"avpf_migration_done"]; + } + /* Quality Reporting migration */ + if( [self lpConfigBoolForKey:@"quality_report_migration_done" forSection:@"app"] == FALSE ){ + const MSList* proxies = linphone_core_get_proxy_config_list(theLinphoneCore); + while(proxies){ + LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; + const char* addr = linphone_proxy_config_get_addr(proxy); + // we want to enable quality reporting for the proxies that are on linphone.org + if( addr && strstr(addr, "sip.linphone.org") != 0 ){ + Linphone_log(@"Migrating proxy config to send quality report"); + linphone_proxy_config_set_quality_reporting_collector(proxy, "sip:voip-metrics@sip.linphone.org"); + linphone_proxy_config_set_quality_reporting_interval(proxy, 180); + linphone_proxy_config_enable_quality_reporting(proxy, TRUE); + } + proxies = proxies->next; + } + [self lpConfigSetBool:TRUE forKey:@"quality_report_migration_done"]; + } - [self setupNetworkReachabilityCallback]; + [self setupNetworkReachabilityCallback]; - NSString* path = [LinphoneManager bundleFile:@"nowebcamCIF.jpg"]; - if (path) { - const char* imagePath = [path cStringUsingEncoding:[NSString defaultCStringEncoding]]; - [LinphoneLogger logc:LinphoneLoggerLog format:"Using '%s' as source image for no webcam", imagePath]; - linphone_core_set_static_picture(theLinphoneCore, imagePath); - } + NSString* path = [LinphoneManager bundleFile:@"nowebcamCIF.jpg"]; + if (path) { + const char* imagePath = [path cStringUsingEncoding:[NSString defaultCStringEncoding]]; + [LinphoneLogger logc:LinphoneLoggerLog format:"Using '%s' as source image for no webcam", imagePath]; + linphone_core_set_static_picture(theLinphoneCore, imagePath); + } /*DETECT cameras*/ frontCamId= backCamId=nil; char** camlist = (char**)linphone_core_get_video_devices(theLinphoneCore); - for (char* cam = *camlist;*camlist!=NULL;cam=*++camlist) { - if (strcmp(FRONT_CAM_NAME, cam)==0) { - frontCamId = cam; - //great set default cam to front - linphone_core_set_video_device(theLinphoneCore, cam); - } - if (strcmp(BACK_CAM_NAME, cam)==0) { - backCamId = cam; - } + for (char* cam = *camlist;*camlist!=NULL;cam=*++camlist) { + if (strcmp(FRONT_CAM_NAME, cam)==0) { + frontCamId = cam; + //great set default cam to front + linphone_core_set_video_device(theLinphoneCore, cam); + } + if (strcmp(BACK_CAM_NAME, cam)==0) { + backCamId = cam; + } - } + } if (![LinphoneManager isNotIphone3G]){ PayloadType *pt=linphone_core_find_payload_type(theLinphoneCore,"SILK",24000,-1); @@ -1218,16 +1236,16 @@ static LinphoneCoreVTable linphonec_vtable = { linphone_core_enable_video(theLinphoneCore, FALSE, FALSE); } - [LinphoneLogger logc:LinphoneLoggerWarning format:"Linphone [%s] started on [%s]", linphone_core_get_version(), [[UIDevice currentDevice].model cStringUsingEncoding:[NSString defaultCStringEncoding]]]; - + [LinphoneLogger logc:LinphoneLoggerWarning format:"Linphone [%s] started on [%s]", linphone_core_get_version(), [[UIDevice currentDevice].model cStringUsingEncoding:[NSString defaultCStringEncoding]]]; - // Post event - NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:theLinphoneCore] - forKey:@"core"]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCoreUpdate - object:[LinphoneManager instance] - userInfo:dict]; + // Post event + NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:theLinphoneCore] + forKey:@"core"]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCoreUpdate + object:[LinphoneManager instance] + userInfo:dict]; } @@ -1236,12 +1254,12 @@ static BOOL libStarted = FALSE; - (void)startLibLinphone { - if ( libStarted ) { - [LinphoneLogger logc:LinphoneLoggerError format:"Liblinphone is already initialized!"]; - return; - } + if ( libStarted ) { + [LinphoneLogger logc:LinphoneLoggerError format:"Liblinphone is already initialized!"]; + return; + } - libStarted = TRUE; + libStarted = TRUE; connectivity = none; signal(SIGPIPE, SIG_IGN); @@ -1250,11 +1268,11 @@ static BOOL libStarted = FALSE; libmsilbc_init(); #if defined (HAVE_SILK) - libmssilk_init(); -#endif + libmssilk_init(); +#endif #ifdef HAVE_AMR - libmsamr_init(); //load amr plugin if present from the liblinphone sdk -#endif + libmsamr_init(); //load amr plugin if present from the liblinphone sdk +#endif #ifdef HAVE_X264 libmsx264_init(); //load x264 plugin if present from the liblinphone sdk #endif @@ -1269,21 +1287,21 @@ static BOOL libStarted = FALSE; /*to make sure we don't loose debug trace*/ if ([self lpConfigBoolForKey:@"debugenable_preference"]) { linphone_core_enable_logs_with_cb((OrtpLogFunc)linphone_iphone_log_handler); - ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); + ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); } - // create linphone core - [self createLinphoneCore]; - linphone_core_migrate_to_multi_transport(theLinphoneCore); + // create linphone core + [self createLinphoneCore]; + linphone_core_migrate_to_multi_transport(theLinphoneCore); - //init audio session + //init audio session AVAudioSession *audioSession = [AVAudioSession sharedInstance]; BOOL bAudioInputAvailable= audioSession.inputAvailable; NSError* err; if( ![audioSession setActive:NO error: &err] && err ){ - NSLog(@"audioSession setActive failed: %@", [err description]); - } + NSLog(@"audioSession setActive failed: %@", [err description]); + } if(!bAudioInputAvailable){ UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"No microphone",nil) message:NSLocalizedString(@"You need to plug a microphone to your device to use this application.",nil) @@ -1291,46 +1309,46 @@ static BOOL libStarted = FALSE; cancelButtonTitle:NSLocalizedString(@"Ok",nil) otherButtonTitles:nil ,nil]; [error show]; - [error release]; + [error release]; } - if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] + if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] && [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { //go directly to bg mode [self enterBackgroundMode]; } - + } - (void)createLinphoneCore { - if (theLinphoneCore != nil) { - [LinphoneLogger logc:LinphoneLoggerLog format:"linphonecore is already created"]; - return; - } - [LinphoneLogger logc:LinphoneLoggerLog format:"Create linphonecore"]; + if (theLinphoneCore != nil) { + [LinphoneLogger logc:LinphoneLoggerLog format:"linphonecore is already created"]; + return; + } + [LinphoneLogger logc:LinphoneLoggerLog format:"Create linphonecore"]; - connectivity=none; + connectivity=none; theLinphoneCore = linphone_core_new_with_config (&linphonec_vtable ,configDb ,self /* user_data */); - /* set the CA file no matter what, since the remote provisioning could be hitting an HTTPS server */ - const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; - linphone_core_set_root_ca(theLinphoneCore, lRootCa); + /* set the CA file no matter what, since the remote provisioning could be hitting an HTTPS server */ + const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; + linphone_core_set_root_ca(theLinphoneCore, lRootCa); - /* The core will call the linphone_iphone_configuring_status_changed callback when the remote provisioning is loaded (or skipped). - Wait for this to finish the code configuration */ + /* The core will call the linphone_iphone_configuring_status_changed callback when the remote provisioning is loaded (or skipped). + Wait for this to finish the code configuration */ + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionInterrupted:) name:AVAudioSessionInterruptionNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(globalStateChangedNotificationHandler:) name:kLinphoneGlobalStateUpdate object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(configuringStateChangedNotificationHandler:) name:kLinphoneConfiguringStateUpdate object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionInterrupted:) name:AVAudioSessionInterruptionNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(globalStateChangedNotificationHandler:) name:kLinphoneGlobalStateUpdate object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(configuringStateChangedNotificationHandler:) name:kLinphoneConfiguringStateUpdate object:nil]; - /*call iterate once immediately in order to initiate background connections with sip server, if any */ linphone_core_iterate(theLinphoneCore); - // start scheduler + // start scheduler mIterateTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(iterate) @@ -1339,37 +1357,37 @@ static BOOL libStarted = FALSE; } - (void)destroyLibLinphone { - [mIterateTimer invalidate]; + [mIterateTimer invalidate]; //just in case [self removeCTCallCenterCb]; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; if (theLinphoneCore != nil) { //just in case application terminate before linphone core initialization - [LinphoneLogger logc:LinphoneLoggerLog format:"Destroy linphonecore"]; + [LinphoneLogger logc:LinphoneLoggerLog format:"Destroy linphonecore"]; linphone_core_destroy(theLinphoneCore); theLinphoneCore = nil; ms_exit(); // Uninitialize mediastreamer2 - - // Post event - NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:theLinphoneCore] forKey:@"core"]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCoreUpdate object:[LinphoneManager instance] userInfo:dict]; - - SCNetworkReachabilityUnscheduleFromRunLoop(proxyReachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - if (proxyReachability) - CFRelease(proxyReachability); - proxyReachability=nil; - - } - libStarted = FALSE; + + // Post event + NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:theLinphoneCore] forKey:@"core"]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCoreUpdate object:[LinphoneManager instance] userInfo:dict]; + + SCNetworkReachabilityUnscheduleFromRunLoop(proxyReachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + if (proxyReachability) + CFRelease(proxyReachability); + proxyReachability=nil; + + } + libStarted = FALSE; } - (void) resetLinphoneCore { - [self destroyLibLinphone]; - [self createLinphoneCore]; + [self destroyLibLinphone]; + [self createLinphoneCore]; - // reset network state to trigger a new network connectivity assessment - linphone_core_set_network_reachable(theLinphoneCore, FALSE); + // reset network state to trigger a new network connectivity assessment + linphone_core_set_network_reachable(theLinphoneCore, FALSE); } static int comp_call_id(const LinphoneCall* call , const char *callid) { @@ -1381,34 +1399,34 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) { } - (void)cancelLocalNotifTimerForCallId:(NSString*)callid { - //first, make sure this callid is not already involved in a call + //first, make sure this callid is not already involved in a call if ([LinphoneManager isLcReady]) { MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore); - MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]); + MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]); if (call != NULL) { - LinphoneCallAppData* data = linphone_call_get_user_pointer((LinphoneCall*)call->data); - if ( data->timer ) - [data->timer invalidate]; - data->timer = nil; + LinphoneCallAppData* data = linphone_call_get_user_pointer((LinphoneCall*)call->data); + if ( data->timer ) + [data->timer invalidate]; + data->timer = nil; return; } } } - (void)acceptCallForCallId:(NSString*)callid { - //first, make sure this callid is not already involved in a call + //first, make sure this callid is not already involved in a call if ([LinphoneManager isLcReady]) { MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore); - MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]); + MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]); if (call != NULL) { - [self acceptCall:(LinphoneCall*)call->data]; + [self acceptCall:(LinphoneCall*)call->data]; return; }; } } - (void)enableAutoAnswerForCallId:(NSString*) callid { - //first, make sure this callid is not already involved in a call + //first, make sure this callid is not already involved in a call if ([LinphoneManager isLcReady]) { MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore); if (ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String])) { @@ -1419,23 +1437,23 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) { if ([pendindCallIdFromRemoteNotif count] > 10 /*max number of pending notif*/) [pendindCallIdFromRemoteNotif removeObjectAtIndex:0]; [pendindCallIdFromRemoteNotif addObject:callid]; - + } - (BOOL)shouldAutoAcceptCallForCallId:(NSString*) callId { - for (NSString* pendingNotif in pendindCallIdFromRemoteNotif) { + for (NSString* pendingNotif in pendindCallIdFromRemoteNotif) { if ([pendingNotif compare:callId] == NSOrderedSame) { [pendindCallIdFromRemoteNotif removeObject:pendingNotif]; return TRUE; } - } - return FALSE; + } + return FALSE; } - (BOOL)resignActive { linphone_core_stop_dtmf_stream(theLinphoneCore); - return YES; + return YES; } static int comp_call_state_paused (const LinphoneCall* call, const void* param) { @@ -1454,18 +1472,18 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) LinphoneProxyConfig* proxyCfg; linphone_core_get_default_proxy(theLinphoneCore, &proxyCfg); BOOL shouldEnterBgMode=FALSE; - + //handle proxy config if any if (proxyCfg) { if ([[LinphoneManager instance] lpConfigBoolForKey:@"backgroundmode_preference"] || [[LinphoneManager instance] lpConfigBoolForKey:@"pushnotification_preference"]) { - + //For registration register [self refreshRegisters]; } - + if ([[LinphoneManager instance] lpConfigBoolForKey:@"backgroundmode_preference"]) { - + //register keepalive if ([[UIApplication sharedApplication] setKeepAliveTimeout:600/*(NSTimeInterval)linphone_proxy_config_get_expires(proxyCfg)*/ handler:^{ @@ -1483,8 +1501,8 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) linphone_core_iterate(theLinphoneCore); } ]) { - - + + [LinphoneLogger logc:LinphoneLoggerLog format:"keepalive handler succesfully registered"]; } else { [LinphoneLogger logc:LinphoneLoggerLog format:"keepalive handler cannot be registered"]; @@ -1492,7 +1510,7 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) shouldEnterBgMode=TRUE; } } - + LinphoneCall* currentCall = linphone_core_get_current_call(theLinphoneCore); const MSList* callList = linphone_core_get_calls(theLinphoneCore); if (!currentCall //no active call @@ -1510,9 +1528,9 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) linphone_core_iterate(theLinphoneCore); } linphone_core_stop_dtmf_stream(theLinphoneCore); - + [LinphoneLogger logc:LinphoneLoggerLog format:"Entering [%s] bg mode",shouldEnterBgMode?"normal":"lite"]; - + if (!shouldEnterBgMode ) { if([[LinphoneManager instance] lpConfigBoolForKey:@"pushnotification_preference"]) { [LinphoneLogger logc:LinphoneLoggerLog format:"Keeping lc core to handle push"]; @@ -1523,25 +1541,25 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) } [self destroyLibLinphone]; return NO; - + } else return YES; } - (void)becomeActive { - [self refreshRegisters]; - if (pausedCallBgTask) { + [self refreshRegisters]; + if (pausedCallBgTask) { [[UIApplication sharedApplication] endBackgroundTask:pausedCallBgTask]; pausedCallBgTask=0; } - if (incallBgTask) { + if (incallBgTask) { [[UIApplication sharedApplication] endBackgroundTask:incallBgTask]; incallBgTask=0; } - + /*IOS specific*/ linphone_core_start_dtmf_stream(theLinphoneCore); - + /*start the video preview in case we are in the main view*/ if ([LinphoneManager runningOnIpad] && linphone_core_video_enabled(theLinphoneCore) && [self lpConfigBoolForKey:@"preview_preference"]){ linphone_core_enable_video_preview(theLinphoneCore, TRUE); @@ -1558,15 +1576,15 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) } - (void)beginInterruption { - LinphoneCall* c = linphone_core_get_current_call(theLinphoneCore); - [LinphoneLogger logc:LinphoneLoggerLog format:"Sound interruption detected!"]; - if (c && linphone_call_get_state(c) == LinphoneCallStreamsRunning) { - linphone_core_pause_call(theLinphoneCore, c); - } + LinphoneCall* c = linphone_core_get_current_call(theLinphoneCore); + [LinphoneLogger logc:LinphoneLoggerLog format:"Sound interruption detected!"]; + if (c && linphone_call_get_state(c) == LinphoneCallStreamsRunning) { + linphone_core_pause_call(theLinphoneCore, c); + } } - (void)endInterruption { - [LinphoneLogger logc:LinphoneLoggerLog format:"Sound interruption ended!"]; + [LinphoneLogger logc:LinphoneLoggerLog format:"Sound interruption ended!"]; } - (void)refreshRegisters{ @@ -1579,205 +1597,205 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param) - (void)copyDefaultSettings { - NSString *src = [LinphoneManager bundleFile:[LinphoneManager runningOnIpad]?@"linphonerc~ipad":@"linphonerc"]; - NSString *dst = [LinphoneManager documentFile:@".linphonerc"]; - [LinphoneManager copyFile:src destination:dst override:FALSE]; + NSString *src = [LinphoneManager bundleFile:[LinphoneManager runningOnIpad]?@"linphonerc~ipad":@"linphonerc"]; + NSString *dst = [LinphoneManager documentFile:@".linphonerc"]; + [LinphoneManager copyFile:src destination:dst override:FALSE]; } #pragma mark - Audio route Functions - (bool)allowSpeaker { - bool notallow = false; - CFStringRef lNewRoute = CFSTR("Unknown"); - UInt32 lNewRouteSize = sizeof(lNewRoute); - OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute); - if (!lStatus && lNewRouteSize > 0) { - NSString *route = (NSString *) lNewRoute; - notallow = [route isEqualToString: @"Headset"] || - [route isEqualToString: @"Headphone"] || - [route isEqualToString: @"HeadphonesAndMicrophone"] || - [route isEqualToString: @"HeadsetInOut"] || - [route isEqualToString: @"Lineout"] || - [LinphoneManager runningOnIpad]; - CFRelease(lNewRoute); - } - return !notallow; + bool notallow = false; + CFStringRef lNewRoute = CFSTR("Unknown"); + UInt32 lNewRouteSize = sizeof(lNewRoute); + OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute); + if (!lStatus && lNewRouteSize > 0) { + NSString *route = (NSString *) lNewRoute; + notallow = [route isEqualToString: @"Headset"] || + [route isEqualToString: @"Headphone"] || + [route isEqualToString: @"HeadphonesAndMicrophone"] || + [route isEqualToString: @"HeadsetInOut"] || + [route isEqualToString: @"Lineout"] || + [LinphoneManager runningOnIpad]; + CFRelease(lNewRoute); + } + return !notallow; } static void audioRouteChangeListenerCallback ( - void *inUserData, // 1 - AudioSessionPropertyID inPropertyID, // 2 - UInt32 inPropertyValueSize, // 3 - const void *inPropertyValue // 4 - ) { - if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; // 5 - LinphoneManager* lm = (LinphoneManager*)inUserData; - - bool speakerEnabled = false; - CFStringRef lNewRoute = CFSTR("Unknown"); - UInt32 lNewRouteSize = sizeof(lNewRoute); - OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute); - if (!lStatus && lNewRouteSize > 0) { - NSString *route = (NSString *) lNewRoute; - [LinphoneLogger logc:LinphoneLoggerLog format:"Current audio route is [%s]", [route cStringUsingEncoding:[NSString defaultCStringEncoding]]]; + void *inUserData, // 1 + AudioSessionPropertyID inPropertyID, // 2 + UInt32 inPropertyValueSize, // 3 + const void *inPropertyValue // 4 + ) { + if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; // 5 + LinphoneManager* lm = (LinphoneManager*)inUserData; - speakerEnabled = [route isEqualToString: @"Speaker"] || - [route isEqualToString: @"SpeakerAndMicrophone"]; - if (![LinphoneManager runningOnIpad] && [route isEqualToString:@"HeadsetBT"] && !speakerEnabled) { - lm.bluetoothEnabled = TRUE; - lm.bluetoothAvailable = TRUE; - NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:lm.bluetoothAvailable], @"available", nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneBluetoothAvailabilityUpdate object:lm userInfo:dict]; - } else { - lm.bluetoothEnabled = FALSE; - } - CFRelease(lNewRoute); - } - - if(speakerEnabled != lm.speakerEnabled) { // Reforce value - lm.speakerEnabled = lm.speakerEnabled; - } + bool speakerEnabled = false; + CFStringRef lNewRoute = CFSTR("Unknown"); + UInt32 lNewRouteSize = sizeof(lNewRoute); + OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute); + if (!lStatus && lNewRouteSize > 0) { + NSString *route = (NSString *) lNewRoute; + [LinphoneLogger logc:LinphoneLoggerLog format:"Current audio route is [%s]", [route cStringUsingEncoding:[NSString defaultCStringEncoding]]]; + + speakerEnabled = [route isEqualToString: @"Speaker"] || + [route isEqualToString: @"SpeakerAndMicrophone"]; + if (![LinphoneManager runningOnIpad] && [route isEqualToString:@"HeadsetBT"] && !speakerEnabled) { + lm.bluetoothEnabled = TRUE; + lm.bluetoothAvailable = TRUE; + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:lm.bluetoothAvailable], @"available", nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneBluetoothAvailabilityUpdate object:lm userInfo:dict]; + } else { + lm.bluetoothEnabled = FALSE; + } + CFRelease(lNewRoute); + } + + if(speakerEnabled != lm.speakerEnabled) { // Reforce value + lm.speakerEnabled = lm.speakerEnabled; + } } - (void)setSpeakerEnabled:(BOOL)enable { - speakerEnabled = enable; + speakerEnabled = enable; - if(enable && [self allowSpeaker]) { - UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; - AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute - , sizeof (audioRouteOverride) - , &audioRouteOverride); - bluetoothEnabled = FALSE; - } else { - UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None; - AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute - , sizeof (audioRouteOverride) - , &audioRouteOverride); - } + if(enable && [self allowSpeaker]) { + UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; + AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute + , sizeof (audioRouteOverride) + , &audioRouteOverride); + bluetoothEnabled = FALSE; + } else { + UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None; + AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute + , sizeof (audioRouteOverride) + , &audioRouteOverride); + } - if (bluetoothAvailable) { - UInt32 bluetoothInputOverride = bluetoothEnabled; - AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, sizeof(bluetoothInputOverride), &bluetoothInputOverride); - } + if (bluetoothAvailable) { + UInt32 bluetoothInputOverride = bluetoothEnabled; + AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, sizeof(bluetoothInputOverride), &bluetoothInputOverride); + } } - (void)setBluetoothEnabled:(BOOL)enable { - if (bluetoothAvailable) { - // The change of route will be done in setSpeakerEnabled - bluetoothEnabled = enable; - if (bluetoothEnabled) { - [self setSpeakerEnabled:FALSE]; - } else { - [self setSpeakerEnabled:speakerEnabled]; - } - } + if (bluetoothAvailable) { + // The change of route will be done in setSpeakerEnabled + bluetoothEnabled = enable; + if (bluetoothEnabled) { + [self setSpeakerEnabled:FALSE]; + } else { + [self setSpeakerEnabled:speakerEnabled]; + } + } } #pragma mark - Call Functions - (void)acceptCall:(LinphoneCall *)call { - LinphoneCallParams* lcallParams = linphone_core_create_default_call_parameters(theLinphoneCore); - if([self lpConfigBoolForKey:@"edge_opt_preference"]) { - bool low_bandwidth = self.network == network_2g; - if(low_bandwidth) { - [LinphoneLogger log:LinphoneLoggerLog format:@"Low bandwidth mode"]; - } - linphone_call_params_enable_low_bandwidth(lcallParams, low_bandwidth); - } + LinphoneCallParams* lcallParams = linphone_core_create_default_call_parameters(theLinphoneCore); + if([self lpConfigBoolForKey:@"edge_opt_preference"]) { + bool low_bandwidth = self.network == network_2g; + if(low_bandwidth) { + [LinphoneLogger log:LinphoneLoggerLog format:@"Low bandwidth mode"]; + } + linphone_call_params_enable_low_bandwidth(lcallParams, low_bandwidth); + } - // workaround for video policy not correctly updated for automatic accept - BOOL video = linphone_call_params_video_enabled(lcallParams); - const LinphoneVideoPolicy* policy = linphone_core_get_video_policy(theLinphoneCore); - video &= policy->automatically_accept; - linphone_call_params_enable_video(lcallParams, video); + // workaround for video policy not correctly updated for automatic accept + BOOL video = linphone_call_params_video_enabled(lcallParams); + const LinphoneVideoPolicy* policy = linphone_core_get_video_policy(theLinphoneCore); + video &= policy->automatically_accept; + linphone_call_params_enable_video(lcallParams, video); - linphone_core_accept_call_with_params(theLinphoneCore,call, lcallParams); + linphone_core_accept_call_with_params(theLinphoneCore,call, lcallParams); } - (void)call:(NSString *)address displayName:(NSString*)displayName transfer:(BOOL)transfer { - if (!linphone_core_is_network_reachable(theLinphoneCore)) { + if (!linphone_core_is_network_reachable(theLinphoneCore)) { UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Network Error",nil) - message:NSLocalizedString(@"There is no network connection available, enable WIFI or WWAN prior to place a call",nil) - delegate:nil - cancelButtonTitle:NSLocalizedString(@"Continue",nil) + message:NSLocalizedString(@"There is no network connection available, enable WIFI or WWAN prior to place a call",nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue",nil) otherButtonTitles:nil]; [error show]; - [error release]; + [error release]; return; } - - CTCallCenter* callCenter = [[CTCallCenter alloc] init]; - if ([callCenter currentCalls]!=nil) { - [LinphoneLogger logc:LinphoneLoggerError format:"GSM call in progress, cancelling outgoing SIP call request"]; + + 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) - message:NSLocalizedString(@"Please terminate GSM call",nil) - delegate:nil - cancelButtonTitle:NSLocalizedString(@"Continue",nil) + message:NSLocalizedString(@"Please terminate GSM call",nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue",nil) otherButtonTitles:nil]; [error show]; - [error release]; + [error release]; [callCenter release]; return; - } - [callCenter release]; - - LinphoneProxyConfig* proxyCfg; + } + [callCenter release]; + + LinphoneProxyConfig* proxyCfg; //get default proxy linphone_core_get_default_proxy(theLinphoneCore,&proxyCfg); LinphoneCallParams* lcallParams = linphone_core_create_default_call_parameters(theLinphoneCore); - if([self lpConfigBoolForKey:@"edge_opt_preference"]) { - bool low_bandwidth = self.network == network_2g; - if(low_bandwidth) { - [LinphoneLogger log:LinphoneLoggerLog format:@"Low bandwidth mode"]; - } - linphone_call_params_enable_low_bandwidth(lcallParams, low_bandwidth); - } + if([self lpConfigBoolForKey:@"edge_opt_preference"]) { + bool low_bandwidth = self.network == network_2g; + if(low_bandwidth) { + [LinphoneLogger log:LinphoneLoggerLog format:@"Low bandwidth mode"]; + } + linphone_call_params_enable_low_bandwidth(lcallParams, low_bandwidth); + } LinphoneCall* call=NULL; - + if ([address length] == 0) return; //just return if ([address hasPrefix:@"sip:"] || [address hasPrefix:@"sips:"]) { - LinphoneAddress* linphoneAddress = linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]); - if(displayName!=nil) { - linphone_address_set_display_name(linphoneAddress,[displayName cStringUsingEncoding:[NSString defaultCStringEncoding]]); - } - if ([[LinphoneManager instance] lpConfigBoolForKey:@"override_domain_with_default_one"]) - linphone_address_set_domain(linphoneAddress, [[[LinphoneManager instance] lpConfigStringForKey:@"domain" forSection:@"wizard"] cStringUsingEncoding:[NSString defaultCStringEncoding]]); - if(transfer) { - linphone_core_transfer_call(theLinphoneCore, linphone_core_get_current_call(theLinphoneCore), [address cStringUsingEncoding:[NSString defaultCStringEncoding]]); - } else { - call=linphone_core_invite_address_with_params(theLinphoneCore, linphoneAddress, lcallParams); - } - linphone_address_destroy(linphoneAddress); + LinphoneAddress* linphoneAddress = linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]); + if(displayName!=nil) { + linphone_address_set_display_name(linphoneAddress,[displayName cStringUsingEncoding:[NSString defaultCStringEncoding]]); + } + if ([[LinphoneManager instance] lpConfigBoolForKey:@"override_domain_with_default_one"]) + linphone_address_set_domain(linphoneAddress, [[[LinphoneManager instance] lpConfigStringForKey:@"domain" forSection:@"wizard"] cStringUsingEncoding:[NSString defaultCStringEncoding]]); + if(transfer) { + linphone_core_transfer_call(theLinphoneCore, linphone_core_get_current_call(theLinphoneCore), [address cStringUsingEncoding:[NSString defaultCStringEncoding]]); + } else { + call=linphone_core_invite_address_with_params(theLinphoneCore, linphoneAddress, lcallParams); + } + linphone_address_destroy(linphoneAddress); } else if (proxyCfg==nil){ UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid SIP address",nil) message:NSLocalizedString(@"Either configure a SIP proxy server from settings prior to place a call or use a valid SIP address (I.E sip:john@example.net)",nil) - delegate:nil - cancelButtonTitle:NSLocalizedString(@"Continue",nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Continue",nil) otherButtonTitles:nil]; [error show]; [error release]; } else { char normalizedUserName[256]; - LinphoneAddress* linphoneAddress = linphone_address_new(linphone_core_get_identity(theLinphoneCore)); + LinphoneAddress* linphoneAddress = linphone_address_new(linphone_core_get_identity(theLinphoneCore)); linphone_proxy_config_normalize_number(proxyCfg,[address cStringUsingEncoding:[NSString defaultCStringEncoding]],normalizedUserName,sizeof(normalizedUserName)); - linphone_address_set_username(linphoneAddress, normalizedUserName); - if(displayName!=nil) { - linphone_address_set_display_name(linphoneAddress, [displayName cStringUsingEncoding:[NSString defaultCStringEncoding]]); - } - if ([[LinphoneManager instance] lpConfigBoolForKey:@"override_domain_with_default_one"]) - linphone_address_set_domain(linphoneAddress, [[[LinphoneManager instance] lpConfigStringForKey:@"domain" forSection:@"wizard"] cStringUsingEncoding:[NSString defaultCStringEncoding]]); - if(transfer) { - linphone_core_transfer_call(theLinphoneCore, linphone_core_get_current_call(theLinphoneCore), linphone_address_as_string_uri_only(linphoneAddress)); - } else { - call=linphone_core_invite_address_with_params(theLinphoneCore, linphoneAddress, lcallParams); - } - linphone_address_destroy(linphoneAddress); + linphone_address_set_username(linphoneAddress, normalizedUserName); + if(displayName!=nil) { + linphone_address_set_display_name(linphoneAddress, [displayName cStringUsingEncoding:[NSString defaultCStringEncoding]]); + } + if ([[LinphoneManager instance] lpConfigBoolForKey:@"override_domain_with_default_one"]) + linphone_address_set_domain(linphoneAddress, [[[LinphoneManager instance] lpConfigStringForKey:@"domain" forSection:@"wizard"] cStringUsingEncoding:[NSString defaultCStringEncoding]]); + if(transfer) { + linphone_core_transfer_call(theLinphoneCore, linphone_core_get_current_call(theLinphoneCore), linphone_address_as_string_uri_only(linphoneAddress)); + } else { + call=linphone_core_invite_address_with_params(theLinphoneCore, linphoneAddress, lcallParams); + } + linphone_address_destroy(linphoneAddress); } if (call) { LinphoneCallAppData* data = [[LinphoneCallAppData alloc] init]; - data->videoRequested = linphone_call_params_video_enabled(lcallParams); /* will be used later to notify user if video was not activated because of the linphone core*/ + data->videoRequested = linphone_call_params_video_enabled(lcallParams); /* will be used later to notify user if video was not activated because of the linphone core*/ linphone_call_set_user_pointer(call, data); } linphone_call_params_destroy(lcallParams); @@ -1787,26 +1805,26 @@ static void audioRouteChangeListenerCallback ( #pragma mark - Property Functions - (void)setPushNotificationToken:(NSData *)apushNotificationToken { - if(apushNotificationToken == pushNotificationToken) { - return; - } - if(pushNotificationToken != nil) { - [pushNotificationToken release]; - pushNotificationToken = nil; - } - - if(apushNotificationToken != nil) { - pushNotificationToken = [apushNotificationToken retain]; - } - if([LinphoneManager isLcReady]) { + if(apushNotificationToken == pushNotificationToken) { + return; + } + if(pushNotificationToken != nil) { + [pushNotificationToken release]; + pushNotificationToken = nil; + } + + if(apushNotificationToken != nil) { + pushNotificationToken = [apushNotificationToken retain]; + } + if([LinphoneManager isLcReady]) { LinphoneProxyConfig *cfg=nil; linphone_core_get_default_proxy(theLinphoneCore, &cfg); - if (cfg) { + if (cfg) { linphone_proxy_config_edit(cfg); [self addPushTokenToProxyConfig: cfg]; linphone_proxy_config_done(cfg); } - } + } } - (void)addPushTokenToProxyConfig:(LinphoneProxyConfig*)proxyCfg{ @@ -1824,15 +1842,15 @@ static void audioRouteChangeListenerCallback ( #else #define APPMODE_SUFFIX @"prod" #endif - NSString *params; - if( [[[UIDevice currentDevice] systemVersion] doubleValue] >= 7 ){ /// use silent push for ios7 devices - params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IC_SIL;pn-call-str=IC_SIL;pn-call-snd=empty;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString]; - } else { - params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString]; - } + NSString *params; + if( [[[UIDevice currentDevice] systemVersion] doubleValue] >= 7 ){ /// use silent push for ios7 devices + params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IC_SIL;pn-call-str=IC_SIL;pn-call-snd=empty;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString]; + } else { + params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString]; + } linphone_proxy_config_set_contact_uri_parameters(proxyCfg, [params UTF8String]); - linphone_proxy_config_set_contact_parameters(proxyCfg, NULL); + linphone_proxy_config_set_contact_parameters(proxyCfg, NULL); } } @@ -1840,54 +1858,54 @@ static void audioRouteChangeListenerCallback ( #pragma mark - Misc Functions + (NSString*)bundleFile:(NSString*)file { - return [[NSBundle mainBundle] pathForResource:[file stringByDeletingPathExtension] ofType:[file pathExtension]]; + return [[NSBundle mainBundle] pathForResource:[file stringByDeletingPathExtension] ofType:[file pathExtension]]; } + (NSString*)documentFile:(NSString*)file { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsPath = [paths objectAtIndex:0]; - return [documentsPath stringByAppendingPathComponent:file]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsPath = [paths objectAtIndex:0]; + return [documentsPath stringByAppendingPathComponent:file]; } + (int)unreadMessageCount { - int count = 0; - MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]); - MSList* item = rooms; - while (item) { - LinphoneChatRoom* room = (LinphoneChatRoom*)item->data; - if( room ){ - count += linphone_chat_room_get_unread_messages_count(room); - } - item = item->next; - } - return count; + int count = 0; + MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]); + MSList* item = rooms; + while (item) { + LinphoneChatRoom* room = (LinphoneChatRoom*)item->data; + if( room ){ + count += linphone_chat_room_get_unread_messages_count(room); + } + item = item->next; + } + return count; } + (BOOL)copyFile:(NSString*)src destination:(NSString*)dst override:(BOOL)override { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - if ([fileManager fileExistsAtPath:dst] == YES) { - if(override) { - [fileManager removeItemAtPath:dst error:&error]; - if(error != nil) { - [LinphoneLogger log:LinphoneLoggerError format:@"Can't remove \"%@\": %@", dst, [error localizedDescription]]; - return FALSE; - } - } else { - [LinphoneLogger log:LinphoneLoggerWarning format:@"\"%@\" already exists", dst]; - return FALSE; - } - } - if ([fileManager fileExistsAtPath:src] == NO) { - [LinphoneLogger log:LinphoneLoggerError format:@"Can't find \"%@\": %@", src, [error localizedDescription]]; - return FALSE; - } - [fileManager copyItemAtPath:src toPath:dst error:&error]; - if(error != nil) { - [LinphoneLogger log:LinphoneLoggerError format:@"Can't copy \"%@\" to \"%@\": %@", src, dst, [error localizedDescription]]; - return FALSE; - } - return TRUE; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + if ([fileManager fileExistsAtPath:dst] == YES) { + if(override) { + [fileManager removeItemAtPath:dst error:&error]; + if(error != nil) { + [LinphoneLogger log:LinphoneLoggerError format:@"Can't remove \"%@\": %@", dst, [error localizedDescription]]; + return FALSE; + } + } else { + [LinphoneLogger log:LinphoneLoggerWarning format:@"\"%@\" already exists", dst]; + return FALSE; + } + } + if ([fileManager fileExistsAtPath:src] == NO) { + [LinphoneLogger log:LinphoneLoggerError format:@"Can't find \"%@\": %@", src, [error localizedDescription]]; + return FALSE; + } + [fileManager copyItemAtPath:src toPath:dst error:&error]; + if(error != nil) { + [LinphoneLogger log:LinphoneLoggerError format:@"Can't copy \"%@\" to \"%@\": %@", src, dst, [error localizedDescription]]; + return FALSE; + } + return TRUE; } - (void)configureVbrCodecs{ @@ -1909,36 +1927,36 @@ static void audioRouteChangeListenerCallback ( +(id)getMessageAppDataForKey:(NSString*)key inMessage:(LinphoneChatMessage*)msg { - if(msg == nil ) return nil; + if(msg == nil ) return nil; - id value = nil; - const char* appData = linphone_chat_message_get_appdata(msg); - if( appData) { - NSDictionary* appDataDict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:appData length:strlen(appData)] options:0 error:nil]; - value = [appDataDict objectForKey:key]; - } - return value; + id value = nil; + const char* appData = linphone_chat_message_get_appdata(msg); + if( appData) { + NSDictionary* appDataDict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:appData length:strlen(appData)] options:0 error:nil]; + value = [appDataDict objectForKey:key]; + } + return value; } +(void)setValueInMessageAppData:(id)value forKey:(NSString*)key inMessage:(LinphoneChatMessage*)msg { - NSMutableDictionary* appDataDict = [NSMutableDictionary dictionary]; - const char* appData = linphone_chat_message_get_appdata(msg); - if( appData) { - appDataDict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:appData length:strlen(appData)] options:NSJSONReadingMutableContainers error:nil]; - } + NSMutableDictionary* appDataDict = [NSMutableDictionary dictionary]; + const char* appData = linphone_chat_message_get_appdata(msg); + if( appData) { + appDataDict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithBytes:appData length:strlen(appData)] options:NSJSONReadingMutableContainers error:nil]; + } - [appDataDict setValue:value forKey:key]; + [appDataDict setValue:value forKey:key]; - NSData* data = [NSJSONSerialization dataWithJSONObject:appDataDict options:0 error:nil]; - NSString* appdataJSON = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - linphone_chat_message_set_appdata(msg, [appdataJSON UTF8String] ); + NSData* data = [NSJSONSerialization dataWithJSONObject:appDataDict options:0 error:nil]; + NSString* appdataJSON = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + linphone_chat_message_set_appdata(msg, [appdataJSON UTF8String] ); } #pragma mark - LPConfig Functions - (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key { - [self lpConfigSetString:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; + [self lpConfigSetString:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; } - (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key forSection:(NSString *)section { @@ -1947,7 +1965,7 @@ static void audioRouteChangeListenerCallback ( } - (NSString*)lpConfigStringForKey:(NSString*)key { - return [self lpConfigStringForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; + return [self lpConfigStringForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; } - (NSString*)lpConfigStringForKey:(NSString*)key withDefault:(NSString*)defaultValue { NSString* value = [self lpConfigStringForKey:key]; @@ -1955,7 +1973,7 @@ static void audioRouteChangeListenerCallback ( } - (NSString*)lpConfigStringForKey:(NSString*)key forSection:(NSString *)section { - if (!key) return nil; + if (!key) return nil; const char* value = lp_config_get_string(configDb, [section UTF8String], [key UTF8String], NULL); if (value) return [NSString stringWithUTF8String:value]; @@ -1964,25 +1982,25 @@ static void audioRouteChangeListenerCallback ( } - (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key { - [self lpConfigSetInt:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; + [self lpConfigSetInt:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; } - (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key forSection:(NSString *)section { - if (!key) return; + if (!key) return; lp_config_set_int(configDb, [section UTF8String], [key UTF8String], value ); } - (NSInteger)lpConfigIntForKey:(NSString*)key { - return [self lpConfigIntForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; + return [self lpConfigIntForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; } - (NSInteger)lpConfigIntForKey:(NSString*)key forSection:(NSString *)section { - if (!key) return -1; + if (!key) return -1; return lp_config_get_int(configDb, [section UTF8String], [key UTF8String], -1); } - (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key { - [self lpConfigSetBool:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; + [self lpConfigSetBool:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; } - (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key forSection:(NSString *)section { @@ -1990,7 +2008,7 @@ static void audioRouteChangeListenerCallback ( } - (BOOL)lpConfigBoolForKey:(NSString*)key { - return [self lpConfigBoolForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; + return [self lpConfigBoolForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]]; } - (BOOL)lpConfigBoolForKey:(NSString*)key forSection:(NSString *)section { @@ -1998,11 +2016,11 @@ static void audioRouteChangeListenerCallback ( } - (void)silentPushFailed:(NSTimer*)timer { - if( silentPushCompletion ){ - [LinphoneLogger log:LinphoneLoggerLog format:@"silentPush failed, silentPushCompletion block: %p", silentPushCompletion ]; - silentPushCompletion(UIBackgroundFetchResultNoData); - silentPushCompletion = nil; - } + if( silentPushCompletion ){ + [LinphoneLogger log:LinphoneLoggerLog format:@"silentPush failed, silentPushCompletion block: %p", silentPushCompletion ]; + silentPushCompletion(UIBackgroundFetchResultNoData); + silentPushCompletion = nil; + } } @@ -2018,21 +2036,21 @@ static void audioRouteChangeListenerCallback ( } - (void)setupGSMInteraction { - + [self removeCTCallCenterCb]; - mCallCenter = [[CTCallCenter alloc] init]; + mCallCenter = [[CTCallCenter alloc] init]; [LinphoneLogger log:LinphoneLoggerLog format:@"Adding CT call center listener [%p]",mCallCenter]; - mCallCenter.callEventHandler = ^(CTCall* call) { + mCallCenter.callEventHandler = ^(CTCall* call) { // post on main thread [self performSelectorOnMainThread:@selector(handleGSMCallInteration:) withObject:mCallCenter waitUntilDone:YES]; }; - + } - (void)handleGSMCallInteration: (id) cCenter { - CTCallCenter* ct = (CTCallCenter*) cCenter; + CTCallCenter* ct = (CTCallCenter*) cCenter; /* pause current call, if any */ LinphoneCall* call = linphone_core_get_current_call(theLinphoneCore); if ([ct currentCalls]!=nil) { @@ -2064,27 +2082,27 @@ static void audioRouteChangeListenerCallback ( #pragma Tunnel - (void)setTunnelMode:(TunnelMode)atunnelMode { - LinphoneTunnel *tunnel = linphone_core_get_tunnel(theLinphoneCore); - tunnelMode = atunnelMode; - switch (tunnelMode) { - case tunnel_off: - linphone_tunnel_enable(tunnel, false); - break; - case tunnel_on: - linphone_tunnel_enable(tunnel, true); - break; - case tunnel_wwan: - if (connectivity != wwan) { - linphone_tunnel_enable(tunnel, false); - } else { - linphone_tunnel_enable(tunnel, true); - } - break; - case tunnel_auto: - linphone_tunnel_auto_detect(tunnel); - break; - - } + LinphoneTunnel *tunnel = linphone_core_get_tunnel(theLinphoneCore); + tunnelMode = atunnelMode; + switch (tunnelMode) { + case tunnel_off: + linphone_tunnel_enable(tunnel, false); + break; + case tunnel_on: + linphone_tunnel_enable(tunnel, true); + break; + case tunnel_wwan: + if (connectivity != wwan) { + linphone_tunnel_enable(tunnel, false); + } else { + linphone_tunnel_enable(tunnel, true); + } + break; + case tunnel_auto: + linphone_tunnel_auto_detect(tunnel); + break; + + } } diff --git a/Classes/LinphoneUI/Base.lproj/UICallBar.xib b/Classes/LinphoneUI/Base.lproj/UICallBar.xib index b77602129..c70bfbb03 100644 --- a/Classes/LinphoneUI/Base.lproj/UICallBar.xib +++ b/Classes/LinphoneUI/Base.lproj/UICallBar.xib @@ -1,8 +1,8 @@ - + - + @@ -59,7 +59,7 @@ - - - - - + + + @@ -114,12 +124,26 @@ + + + - \ No newline at end of file + + + + + +