diff --git a/Classes/Base.lproj/WizardViews.xib b/Classes/Base.lproj/WizardViews.xib index 91718eeb3..9dfd810ea 100644 --- a/Classes/Base.lproj/WizardViews.xib +++ b/Classes/Base.lproj/WizardViews.xib @@ -1,7 +1,6 @@ - @@ -15,6 +14,7 @@ + @@ -73,7 +73,7 @@ + @@ -273,6 +291,13 @@ + @@ -410,6 +435,19 @@ + + + + + + + + + + + + + diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index 11f155928..feb65bb37 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -48,6 +48,7 @@ extern NSString *const kLinphoneLogsUpdate; extern NSString *const kLinphoneSettingsUpdate; extern NSString *const kLinphoneBluetoothAvailabilityUpdate; extern NSString *const kLinphoneConfiguringStateUpdate; +extern NSString *const kLinphoneGlobalStateUpdate; typedef enum _NetworkType { network_none = 0, @@ -119,6 +120,7 @@ typedef struct _LinphoneManagerSounds { + (NSString *)getUserAgent; +- (void)resetLinphoneCore; - (void)startLibLinphone; - (void)destroyLibLinphone; - (BOOL)resignActive; diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 2f34d88a4..9d14e929d 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -58,7 +58,8 @@ NSString *const kLinphoneMainViewChange = @"LinphoneMainViewChange"; NSString *const kLinphoneLogsUpdate = @"LinphoneLogsUpdate"; NSString *const kLinphoneSettingsUpdate = @"LinphoneSettingsUpdate"; NSString *const kLinphoneBluetoothAvailabilityUpdate = @"LinphoneBluetoothAvailabilityUpdate"; - +NSString *const kLinphoneConfiguringStateUpdate = @"LinphoneConfiguringStateUpdate"; +NSString *const kLinphoneGlobalStateUpdate = @"LinphoneGlobalStateUpdate"; extern void libmsilbc_init(); @@ -285,7 +286,9 @@ struct codec_name_pref_table codec_pref_table[]={ if (lStatus) { [LinphoneLogger logc:LinphoneLoggerError format:"cannot un register route change handler [%ld]", lStatus]; } - + + [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneGlobalStateUpdate]; + [photoLibrary release]; [pendindCallIdFromRemoteNotif release]; [super dealloc]; @@ -569,6 +572,53 @@ static void linphone_iphone_call_state(LinphoneCore *lc, LinphoneCall* call, Lin static void linphone_iphone_transfer_state_changed(LinphoneCore* lc, LinphoneCall* call, LinphoneCallState state) { } +#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]; +} + +-(void)onGlobalStateChanged:(LinphoneGlobalState)state withMessage:(const char*)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]; + + // 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]; + } +} + + +#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]; +} + +-(void)onConfiguringStatusChanged:(LinphoneConfiguringState)status withMessage:(const char*)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]; + + // dispatch the notification asynchronously + dispatch_async(dispatch_get_main_queue(), ^(void){ + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneConfiguringStateUpdate object:self userInfo:dict]; + }); +} #pragma mark - Registration State Functions @@ -840,7 +890,9 @@ static LinphoneCoreVTable linphonec_vtable = { .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 + .is_composing_received = linphone_iphone_is_composing_received, + .configuring_status = linphone_iphone_configuring_status_changed, + .global_state_changed = linphone_iphone_global_state_changed }; //scheduling loop @@ -859,17 +911,88 @@ static LinphoneCoreVTable linphonec_vtable = { } } +/** Should be called once per linphone_core_new() */ +- (void)finishCoreConfiguration { + + //get default config from bundle + NSString *zrtpSecretsFileName = [LinphoneManager documentFile:@"zrtp_secrets"]; + const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; + + 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); + // 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]]; + linphone_core_set_play_file(theLinphoneCore, lPlay); + + linphone_core_set_zrtp_secrets_file(theLinphoneCore, [zrtpSecretsFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); + + [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); + } + + /*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; + } + + } + + if (![LinphoneManager isNotIphone3G]){ + PayloadType *pt=linphone_core_find_payload_type(theLinphoneCore,"SILK",24000,-1); + if (pt) { + linphone_core_enable_payload_type(theLinphoneCore,pt,FALSE); + [LinphoneLogger logc:LinphoneLoggerWarning format:"SILK/24000 and video disabled on old iPhone 3G"]; + } + 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]]]; + + + // Post event + NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:theLinphoneCore] + forKey:@"core"]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCoreUpdate + object:[LinphoneManager instance] + userInfo:dict]; + +} + + - (void)startLibLinphone { if (theLinphoneCore != nil) { [LinphoneLogger logc:LinphoneLoggerLog format:"linphonecore is already created"]; return; } - - //get default config from bundle - NSString* factoryConfig = [LinphoneManager bundleFile:[LinphoneManager runningOnIpad]?@"linphonerc-factory~ipad":@"linphonerc-factory"]; + + NSString* factoryConfig = [LinphoneManager bundleFile:[LinphoneManager runningOnIpad]?@"linphonerc-factory~ipad":@"linphonerc-factory"]; NSString *confiFileName = [LinphoneManager documentFile:@".linphonerc"]; - NSString *zrtpSecretsFileName = [LinphoneManager documentFile:@"zrtp_secrets"]; - const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]]; + connectivity = none; signal(SIGPIPE, SIG_IGN); //log management @@ -900,27 +1023,10 @@ static LinphoneCoreVTable linphonec_vtable = { theLinphoneCore = linphone_core_new (&linphonec_vtable , [confiFileName cStringUsingEncoding:[NSString defaultCStringEncoding]] , [factoryConfig cStringUsingEncoding:[NSString defaultCStringEncoding]] - ,self); - 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]; - + ,self /* user_data */); - fastAddressBook = [[FastAddressBook alloc] init]; - - 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]]; - linphone_core_set_play_file(theLinphoneCore, lPlay); - - linphone_core_set_zrtp_secrets_file(theLinphoneCore, [zrtpSecretsFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]); - - [self setupNetworkReachabilityCallback]; + /* 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 */ // start scheduler mIterateTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 @@ -928,7 +1034,8 @@ static LinphoneCoreVTable linphonec_vtable = { selector:@selector(iterate) userInfo:nil repeats:YES]; - //init audio session + + //init audio session AVAudioSession *audioSession = [AVAudioSession sharedInstance]; BOOL bAudioInputAvailable= audioSession.inputAvailable; NSError* err; @@ -937,6 +1044,8 @@ static LinphoneCoreVTable linphonec_vtable = { selector:@selector(audioSessionInterrupted:) name:AVAudioSessionInterruptionNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(globalStateChangedNotificationHandler:) name:kLinphoneGlobalStateUpdate object:nil]; + if( ![audioSession setActive:NO error: &err] && err ){ @@ -951,55 +1060,13 @@ static LinphoneCoreVTable linphonec_vtable = { [error show]; [error release]; } - - 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; - } - - } - if (![LinphoneManager isNotIphone3G]){ - PayloadType *pt=linphone_core_find_payload_type(theLinphoneCore,"SILK",24000,-1); - if (pt) { - linphone_core_enable_payload_type(theLinphoneCore,pt,FALSE); - [LinphoneLogger logc:LinphoneLoggerWarning format:"SILK/24000 and video disabled on old iPhone 3G"]; - } - 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]]]; - if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)] && [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { //go directly to bg mode [self resignActive]; } - - // Post event - NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:theLinphoneCore] forKey:@"core"]; - [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCoreUpdate object:[LinphoneManager instance] userInfo:dict]; } - (void)destroyLibLinphone { @@ -1026,6 +1093,39 @@ static LinphoneCoreVTable linphonec_vtable = { } } +- (void) resetLinphoneCore { + [self destroyLibLinphone]; + if (theLinphoneCore != nil) { + [LinphoneLogger logc:LinphoneLoggerLog format:"linphonecore is already created"]; + return; + } + [LinphoneLogger logc:LinphoneLoggerLog format:"Create linphonecore"]; + + NSString* factoryConfig = [LinphoneManager bundleFile:[LinphoneManager runningOnIpad]?@"linphonerc-factory~ipad":@"linphonerc-factory"]; + NSString *confiFileName = [LinphoneManager documentFile:@".linphonerc"]; + theLinphoneCore = linphone_core_new (&linphonec_vtable + , [confiFileName cStringUsingEncoding:[NSString defaultCStringEncoding]] + , [factoryConfig cStringUsingEncoding:[NSString defaultCStringEncoding]] + ,self /* user_data */); + + /* 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]; + connectivity=none; + linphone_core_set_network_reachable(theLinphoneCore, FALSE); + // start scheduler + mIterateTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 + target:self + selector:@selector(iterate) + userInfo:nil + repeats:YES]; + + + +} + static int comp_call_id(const LinphoneCall* call , const char *callid) { if (linphone_call_log_get_call_id(linphone_call_get_call_log(call)) == nil) { ms_error ("no callid for call [%p]", call); diff --git a/Classes/LinphoneUI/UIStateBar.m b/Classes/LinphoneUI/UIStateBar.m index b2e485d84..7e7e1d37d 100644 --- a/Classes/LinphoneUI/UIStateBar.m +++ b/Classes/LinphoneUI/UIStateBar.m @@ -86,7 +86,10 @@ NSTimer *callSecurityTimer; name:kLinphoneRegistrationUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(globalStateUpdate:) + name:kLinphoneConfiguringStateUpdate + object:nil]; [callQualityImage setHidden: true]; [callSecurityImage setHidden: true]; @@ -104,7 +107,9 @@ NSTimer *callSecurityTimer; [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneRegistrationUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] removeObserver:self + name:kLinphoneConfiguringStateUpdate + object:nil]; if(callQualityTimer != nil) { [callQualityTimer invalidate]; callQualityTimer = nil; @@ -124,15 +129,23 @@ NSTimer *callSecurityTimer; [self proxyConfigUpdate:config]; } +- (void) globalStateUpdate:(NSNotification*) notif { + [self registrationUpdate:notif]; +} + #pragma mark - - (void)proxyConfigUpdate: (LinphoneProxyConfig*) config { - LinphoneRegistrationState state; + LinphoneRegistrationState state = LinphoneRegistrationNone; NSString* message = nil; UIImage* image = nil; + LinphoneCore* lc = [LinphoneManager getLc]; + LinphoneGlobalState gstate = linphone_core_get_global_state(lc); - if (config == NULL) { + if( gstate == LinphoneGlobalConfiguring ){ + message = NSLocalizedString(@"Fetching remote configuration", nil); + } else if (config == NULL) { state = LinphoneRegistrationNone; if(![LinphoneManager isLcReady] || linphone_core_is_network_reachable([LinphoneManager getLc])) message = NSLocalizedString(@"No SIP account configured", nil); diff --git a/Classes/PhoneMainView.m b/Classes/PhoneMainView.m index c2ac4d123..3b1f0e798 100644 --- a/Classes/PhoneMainView.m +++ b/Classes/PhoneMainView.m @@ -112,7 +112,11 @@ static PhoneMainView* phoneMainViewInstance=nil; selector:@selector(textReceived:) name:kLinphoneTextReceived object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onGlobalStateChanged:) + name:kLinphoneGlobalStateUpdate + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil]; @@ -135,10 +139,13 @@ static PhoneMainView* phoneMainViewInstance=nil; [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneRegistrationUpdate object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self + [[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneTextReceived object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self + [[NSNotificationCenter defaultCenter] removeObserver:self + name:kLinphoneConfiguringStateUpdate + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceBatteryLevelDidChangeNotification object:nil]; [[UIDevice currentDevice] setBatteryMonitoringEnabled:NO]; @@ -229,6 +236,19 @@ static PhoneMainView* phoneMainViewInstance=nil; } } +- (void)onGlobalStateChanged:(NSNotification*)notif { + LinphoneConfiguringState state = [[[notif userInfo] valueForKey:@"state"] integerValue]; + LinphoneAppDelegate *appDelegate = (LinphoneAppDelegate *)[[UIApplication sharedApplication] delegate]; + if( state == LinphoneGlobalOn && !(appDelegate.started) ){ + if( [[LinphoneManager instance] lpConfigBoolForKey:@"show_login_view" forSection:@"app"] ){ + WizardViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[WizardViewController compositeViewDescription]], WizardViewController); + if(controller != nil) { + [controller handleRemoteProvisioning]; + } + } + } +} + - (void)callUpdate:(NSNotification*)notif { LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue]; LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue]; @@ -321,8 +341,11 @@ static PhoneMainView* phoneMainViewInstance=nil; } } -- (void)startUp { - if ([[LinphoneManager instance] lpConfigBoolForKey:@"enable_first_login_view_preference"] == true) { +- (void)startUp { + + if( linphone_core_get_global_state([LinphoneManager getLc]) != LinphoneGlobalOn ){ + [self changeCurrentView: [DialerViewController compositeViewDescription]]; + } else if ([[LinphoneManager instance] lpConfigBoolForKey:@"enable_first_login_view_preference"] == true) { // Change to fist login view [self changeCurrentView: [FirstLoginViewController compositeViewDescription]]; } else { diff --git a/Classes/WizardViewController.h b/Classes/WizardViewController.h index 2e8123690..32be00f2e 100644 --- a/Classes/WizardViewController.h +++ b/Classes/WizardViewController.h @@ -21,7 +21,13 @@ #import #import "UICompositeViewController.h" -@interface WizardViewController : TPMultiLayoutViewController { +@interface WizardViewController : TPMultiLayoutViewController + +{ @private UITextField *activeTextField; UIView *currentView; @@ -44,12 +50,15 @@ @property (nonatomic, retain) IBOutlet UIButton *createAccountButton; @property (nonatomic, retain) IBOutlet UIButton *connectAccountButton; @property (nonatomic, retain) IBOutlet UIButton *externalAccountButton; +@property (retain, nonatomic) IBOutlet UIButton *remoteProvisioningButton; + @property (nonatomic, retain) IBOutlet UIImageView *choiceViewLogoImageView; @property (nonatomic, retain) IBOutlet UITapGestureRecognizer *viewTapGestureRecognizer; - (void)reset; +- (void)handleRemoteProvisioning; - (IBAction)onStartClick:(id)sender; - (IBAction)onBackClick:(id)sender; @@ -59,6 +68,7 @@ - (IBAction)onConnectAccountClick:(id)sender; - (IBAction)onExternalAccountClick:(id)sender; - (IBAction)onCheckValidationClick:(id)sender; +- (IBAction)onRemoteProvisioningClick:(id)sender; - (IBAction)onSignInClick:(id)sender; - (IBAction)onSignInExternalClick:(id)sender; diff --git a/Classes/WizardViewController.m b/Classes/WizardViewController.m index d0731f39b..56df6e29e 100644 --- a/Classes/WizardViewController.m +++ b/Classes/WizardViewController.m @@ -27,14 +27,15 @@ #import typedef enum _ViewElement { - ViewElement_Username = 100, - ViewElement_Password = 101, - ViewElement_Password2 = 102, - ViewElement_Email = 103, - ViewElement_Domain = 104, - ViewElement_Label = 200, - ViewElement_Error = 201, - ViewElement_Username_Error = 404 + ViewElement_Username = 100, + ViewElement_Password = 101, + ViewElement_Password2 = 102, + ViewElement_Email = 103, + ViewElement_Domain = 104, + ViewElement_RemoteProvDetails = 105, + ViewElement_Label = 200, + ViewElement_Error = 201, + ViewElement_Username_Error = 404 } ViewElement; @implementation WizardViewController @@ -102,6 +103,7 @@ typedef enum _ViewElement { [viewTapGestureRecognizer release]; + [_remoteProvisioningButton release]; [super dealloc]; } @@ -135,7 +137,11 @@ static UICompositeViewDescription *compositeDescription = nil; selector:@selector(registrationUpdateEvent:) name:kLinphoneRegistrationUpdate object:nil]; - + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(configuringUpdate:) + name:kLinphoneConfiguringStateUpdate + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification @@ -149,16 +155,19 @@ static UICompositeViewDescription *compositeDescription = nil; - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self - name:kLinphoneRegistrationUpdate - object:nil]; - - + name:kLinphoneRegistrationUpdate + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:kLinphoneConfiguringStateUpdate + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; + } - (void)viewDidLoad { @@ -191,6 +200,38 @@ static UICompositeViewDescription *compositeDescription = nil; } } +- (void)handleRemoteProvisioning { + + [self resetTextFields]; + + LinphoneProxyConfig* default_conf = linphone_core_create_proxy_config([LinphoneManager getLc]); + const char* identity = linphone_proxy_config_get_identity(default_conf); + if( identity ){ + LinphoneAddress* default_addr = linphone_address_new(identity); + if( default_addr ){ + const char* domain = linphone_address_get_domain(default_addr); + + if( domain && strlen(domain) > 0){ + UITextField* domainfield = [WizardViewController findTextField:ViewElement_Domain view:externalAccountView]; + [domainfield setText:[NSString stringWithUTF8String:domain]]; + } + } + } + [self changeView:externalAccountView back:FALSE animation:TRUE]; + + linphone_proxy_config_destroy(default_conf); + +} + +- (void)resetTextFields { + [WizardViewController cleanTextField:welcomeView]; + [WizardViewController cleanTextField:choiceView]; + [WizardViewController cleanTextField:createAccountView]; + [WizardViewController cleanTextField:connectAccountView]; + [WizardViewController cleanTextField:externalAccountView]; + [WizardViewController cleanTextField:validateAccountView]; +} + - (void)reset { [self clearProxyConfig]; [[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"pushnotification_preference"]; @@ -210,12 +251,7 @@ static UICompositeViewDescription *compositeDescription = nil; [[LinphoneManager instance] lpConfigSetString:@"" forKey:@"stun_preference"]; linphone_core_set_stun_server(lc, NULL); linphone_core_set_firewall_policy(lc, LinphonePolicyNoFirewall); - [WizardViewController cleanTextField:welcomeView]; - [WizardViewController cleanTextField:choiceView]; - [WizardViewController cleanTextField:createAccountView]; - [WizardViewController cleanTextField:connectAccountView]; - [WizardViewController cleanTextField:externalAccountView]; - [WizardViewController cleanTextField:validateAccountView]; + [self resetTextFields]; if ([[LinphoneManager instance] lpConfigBoolForKey:@"hide_wizard_welcome_view_preference"] == true) { [self changeView:choiceView back:FALSE animation:FALSE]; } else { @@ -286,6 +322,7 @@ static UICompositeViewDescription *compositeDescription = nil; // [ Create Btn ] // [ Connect Btn ] // [ External Btn ] + // [ Remote Prov ] BOOL show_logo = [[LinphoneManager instance] lpConfigBoolForKey:@"show_wizard_logo_in_choice_view_preference"]; BOOL show_extern = ![[LinphoneManager instance] lpConfigBoolForKey:@"hide_wizard_custom_account"]; @@ -437,9 +474,9 @@ static UICompositeViewDescription *compositeDescription = nil; [self setDefaultSettings:proxyCfg]; } linphone_proxy_config_enable_register(proxyCfg, true); + linphone_core_add_auth_info([LinphoneManager getLc], info); linphone_core_add_proxy_config([LinphoneManager getLc], proxyCfg); linphone_core_set_default_proxy([LinphoneManager getLc], proxyCfg); - linphone_core_add_auth_info([LinphoneManager getLc], info); } - (NSString*)identityFromUsername:(NSString*)username { @@ -614,6 +651,23 @@ static UICompositeViewDescription *compositeDescription = nil; [self checkAccountValidation:identity]; } +- (IBAction)onRemoteProvisioningClick:(id)sender { + UIAlertView* remoteInput = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Enter provisioning URL", @"") + message:@"" + delegate:self + cancelButtonTitle:NSLocalizedString(@"Cancel", @"") + otherButtonTitles:NSLocalizedString(@"Fetch", @""), nil]; + remoteInput.alertViewStyle = UIAlertViewStylePlainTextInput; + + UITextField* prov_url = [remoteInput textFieldAtIndex:0]; + prov_url.keyboardType = UIKeyboardTypeURL; + prov_url.text = [[LinphoneManager instance] lpConfigStringForKey:@"config-uri" forSection:@"misc"]; + prov_url.placeholder = @"URL"; + + [remoteInput show]; + [remoteInput release]; +} + - (IBAction)onSignInExternalClick:(id)sender { NSString *username = [WizardViewController findTextField:ViewElement_Username view:contentView].text; NSString *password = [WizardViewController findTextField:ViewElement_Password view:contentView].text; @@ -719,6 +773,55 @@ static UICompositeViewDescription *compositeDescription = nil; [LinphoneUtils findAndResignFirstResponder:currentView]; } +#pragma mark - UIAlertViewDelegate + +-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { + if (buttonIndex == 1) { /* fetch */ + NSString* url = [alertView textFieldAtIndex:0].text; + if( [url length] > 0 ){ + // missing prefix will result in http:// being used + if( [url rangeOfString:@"://"].location == NSNotFound ) + url = [NSString stringWithFormat:@"http://%@", url]; + + [LinphoneLogger log:LinphoneLoggerLog format:@"Should use remote provisioning URL %@", url]; + linphone_core_set_provisioning_uri([LinphoneManager getLc], [url UTF8String]); + + [waitView setHidden:false]; + [[LinphoneManager instance] resetLinphoneCore]; + } + } else { + [LinphoneLogger log:LinphoneLoggerLog format:@"Canceled remote provisioning"]; + } +} + +- (void)configuringUpdate:(NSNotification *)notif { + LinphoneConfiguringState status = (LinphoneConfiguringState)[[notif.userInfo valueForKey:@"state"] integerValue]; + + [waitView setHidden:true]; + + switch (status) { + case LinphoneConfiguringSuccessful: + [self handleRemoteProvisioning]; + break; + case LinphoneConfiguringFailed: + { + NSString* error_message = [notif.userInfo valueForKey:@"message"]; + UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Provisioning Load error", nil) + message:error_message + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", nil) + otherButtonTitles: nil]; + [alert show]; + [alert release]; + break; + } + + case LinphoneConfiguringSkipped: + default: + break; + } +} + #pragma mark - Event Functions @@ -914,4 +1017,8 @@ static UICompositeViewDescription *compositeDescription = nil; return YES; } +- (void)viewDidUnload { +[self setRemoteProvisioningButton:nil]; +[super viewDidUnload]; +} @end diff --git a/Resources/en.lproj/Localizable.strings b/Resources/en.lproj/Localizable.strings index da3e56166..5cd722cdd 100644 --- a/Resources/en.lproj/Localizable.strings +++ b/Resources/en.lproj/Localizable.strings @@ -302,3 +302,4 @@ "Enter an address" = "Enter SIP address or phone number..."; "%@ is composing..." = "%@ is composing..."; "Resend" = "Resend"; +"Fetching remote configuration" = "Fetching remote configuration"; diff --git a/Resources/fr.lproj/Localizable.strings b/Resources/fr.lproj/Localizable.strings index fd6db7002..982311060 100644 --- a/Resources/fr.lproj/Localizable.strings +++ b/Resources/fr.lproj/Localizable.strings @@ -302,3 +302,4 @@ "Enter an address" = "Entrez une addresse SIP ou un numéro de téléphone..."; "%@ is composing..." = "%@ rédige un message..."; "Resend" = "Renvoyer"; +"Fetching remote configuration" = "Récupération de la conf. distante"; diff --git a/Resources/ru.lproj/Localizable.strings b/Resources/ru.lproj/Localizable.strings index e8b5c0d8e..454eab294 100644 --- a/Resources/ru.lproj/Localizable.strings +++ b/Resources/ru.lproj/Localizable.strings @@ -302,3 +302,4 @@ "Enter an address" = "Введите адрес SIP или номер телефона..."; "%@ is composing..." = "%@ is composing..."; "Resend" = "Resend"; +"Fetching remote configuration" = "Fetching remote configuration";