linphone-ios/Classes/BuschJaegerMainView.m
2013-02-12 15:38:15 +01:00

445 lines
17 KiB
Objective-C

/* BuschJaegerMainView.m
*
* Copyright (C) 2011 Belledonne Comunications, Grenoble, France
*
* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "BuschJaegerMainView.h"
#import "BuschJaegerUtils.h"
#include "lpconfig.h"
@implementation UINavigationControllerEx
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[viewController view];
UIViewController *oldTopViewController = self.topViewController;
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[oldTopViewController viewWillDisappear:animated];
[viewController viewWillAppear:animated];
}
[super pushViewController:viewController animated:animated];
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[self.topViewController viewDidAppear:animated];
[oldTopViewController viewDidDisappear:animated];
}
}
- (NSArray*)popToViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
NSMutableArray *array = [NSMutableArray array];
while([self.viewControllers count] > 1 && self.topViewController != viewController) {
[array addObject:[self popViewControllerAnimated:animated]];
}
return array;
}
return [super popToViewController:viewController animated:animated];
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
int count = [self.viewControllers count];
if(count > 1) {
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[self.topViewController viewWillDisappear:animated];
UIViewController *nextView = nil;
nextView = [self.viewControllers objectAtIndex:count - 2];
[nextView viewWillAppear:animated];
}
UIViewController * ret = [super popViewControllerAnimated:animated];
if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
[ret viewDidDisappear:animated];
[self.topViewController viewDidAppear:animated];
}
return ret;
}
return nil;
}
@end
@implementation BuschJaegerMainView
@synthesize navigationController;
@synthesize callView;
@synthesize settingsView;
@synthesize manualSettingsView;
@synthesize welcomeView;
@synthesize historyView;
@synthesize historyDetailsView;
static BuschJaegerMainView* mainViewInstance=nil;
#pragma mark - Lifecycle Functions
- (void)initBuschJaegerMainView {
assert (!mainViewInstance);
mainViewInstance = self;
loadCount = 0;
historyTimer = nil;
historyQueue = [[NSOperationQueue alloc] init];
historyQueue.name = @"History queue";
historyQueue.maxConcurrentOperationCount = 1;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[self applicationWillEnterForeground:nil];
}
- (id)init {
self = [super init];
if (self) {
[self initBuschJaegerMainView];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self initBuschJaegerMainView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
[self initBuschJaegerMainView];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[navigationController release];
[callView release];
[settingsView release];
[manualSettingsView release];
[welcomeView release];
[historyView release];
[historyDetailsView release];
[historyTimer invalidate];
[historyQueue release];
// Remove all observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
// Avoid IOS 4 bug
if(loadCount++ > 0)
return;
[super viewDidLoad];
// [self setWantsFullScreenLayout:TRUE];
UIView *view = navigationController.view;
// [view setFrame:[self.view bounds]];
[self.view addSubview:view];
[navigationController pushViewController:welcomeView animated:FALSE];
[self networkUpdate:[[LinphoneManager instance].configuration.homeAP isEqualToData:[LinphoneManager getWifiData]]];
[self updateIconBadge:nil];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Avoid IOS 4 bug
loadCount--;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textReceivedEvent:)
name:kLinphoneTextReceived
object:nil];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(dtmfReceivedEvent:)
name:kLinphoneDtmfReceived
object:nil];
// Set observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(networkUpdateEvent:)
name:kLinphoneNetworkUpdate
object:nil];
}
- (void)vieWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneCallUpdate
object:nil];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneTextReceived
object:nil];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneDtmfReceived
object:nil];
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kLinphoneNetworkUpdate
object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return [navigationController.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
- (NSUInteger)supportedInterfaceOrientations {
return [navigationController.topViewController supportedInterfaceOrientations];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[BuschJaegerUtils resizeGradient:self.view];
}
#pragma mark - Event Functions
- (void)applicationWillEnterForeground:(NSNotification*)notif {
if(historyTimer != nil) {
historyTimer = [NSTimer scheduledTimerWithTimeInterval: 10.0
target: self
selector: @selector(updateIconBadge:)
userInfo: nil
repeats: YES];
}
}
- (void)applicationWillEnterBackground:(NSNotification*)notif {
[historyTimer invalidate];
historyTimer = nil;
}
- (void)updateIconBadge:(id)info {
if([historyQueue operationCount] == 0) {
[historyQueue addOperationWithBlock:^(void) {
if([[LinphoneManager instance] configuration].valid) {
NSMutableSet *set = [[[LinphoneManager instance] configuration] getHistory];
int missed = [set count] - [[[LinphoneManager instance] configuration].history count];
if(missed < 0) missed = 0;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:missed];
}
}];
}
}
- (void)callUpdateEvent: (NSNotification*) notif {
LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
[self callUpdate:call state:state animated:TRUE];
}
- (void)dtmfReceivedEvent: (NSNotification*) notif {
[self displayDtmf:notif];
}
- (void)textReceivedEvent: (NSNotification*) notif {
[self displayMessage:notif];
}
- (void)networkUpdateEvent: (NSNotification*) notif {
[self networkUpdate:[[LinphoneManager instance].configuration.homeAP isEqualToData:[LinphoneManager getWifiData]]];
if([[LinphoneManager instance] connectivity] == network_none) {
[self updateIconBadge:nil]; // Update history
}
}
#pragma mark -
- (void)networkUpdate:(BOOL)home {
if([LinphoneManager isLcReady]) {
LinphoneCore *lc = [LinphoneManager getLc];
LpConfig *config = linphone_core_get_config(lc);
int upload, download;
if(home) {
upload = lp_config_get_int(config, "net", "home_upload_bw", 0);
download = lp_config_get_int(config, "net", "home_download_bw", 0);
} else {
upload = lp_config_get_int(config, "net", "out_upload_bw", 0);
download = lp_config_get_int(config, "net", "out_download_bw", 0);
}
linphone_core_set_upload_bandwidth(lc, upload);
linphone_core_set_download_bandwidth(lc, download);
[[LinphoneManager instance] reconfigureProxyConfigs];
}
}
- (void)callUpdate:(LinphoneCall *)call state:(LinphoneCallState)state animated:(BOOL)animated {
// Fake call update
if(call == NULL) {
return;
}
switch (state) {
case LinphoneCallIncomingReceived:
{
[self displayIncomingCall:call];
}
case LinphoneCallOutgoingInit:
{
linphone_call_enable_camera(call, FALSE);
}
case LinphoneCallPausedByRemote:
case LinphoneCallConnected:
case LinphoneCallUpdating:
{
[navigationController popToViewController:welcomeView animated:FALSE];
[navigationController pushViewController:callView animated:FALSE]; // No animation... Come back when Apple have learned how to create a good framework
break;
}
case LinphoneCallError:
case LinphoneCallEnd:
{
int reason = linphone_call_get_reason(call);
if(reason == LinphoneReasonBusy) {
NSString *contactName = NSLocalizedString(@"Unknown", nil);
// Extract caller address
const LinphoneAddress* addr = linphone_call_get_remote_address(call);
if(addr) {
char *address = linphone_address_as_string_uri_only(addr);
if(address != NULL) {
contactName = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:address]];
ms_free(address);
}
}
// Find caller in outdoor stations
NSSet *outstations = [[LinphoneManager instance] configuration].outdoorStations;
for(OutdoorStation *os in outstations) {
if([[FastAddressBook normalizeSipURI:os.address] isEqualToString:contactName]) {
contactName = os.name;
break;
}
}
UIAlertView* error = [[UIAlertView alloc] initWithTitle:@"Welcome"
message: [NSString stringWithFormat:NSLocalizedString(@"%@ is busy",nil), contactName]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
otherButtonTitles:nil,nil];
[error show];
[error release];
}
[self dismissIncomingCall:call];
if ((linphone_core_get_calls([LinphoneManager getLc]) == NULL)) {
[navigationController popToViewController:welcomeView animated:FALSE]; // No animation... Come back when Apple have learned how to create a good framework
}
break;
}
default:
break;
}
}
- (void)dismissIncomingCall:(LinphoneCall*)call {
LinphoneCallAppData* appData = (LinphoneCallAppData*) linphone_call_get_user_pointer(call);
if(appData != nil && appData->notification != nil) {
// cancel local notif if needed
[[UIApplication sharedApplication] cancelLocalNotification:appData->notification];
[appData->notification release];
}
}
- (void)displayIncomingCall:(LinphoneCall *)call {
if (![[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]
|| [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
[[LinphoneManager instance] setSpeakerEnabled:TRUE];
AudioServicesPlaySystemSound([LinphoneManager instance].sounds.call);
}
}
- (void)displayDtmf:(id)message {
if (![[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]
|| [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
UIAlertView* error = [[UIAlertView alloc] initWithTitle:@"Welcome"
message: [NSString stringWithFormat:@"%@", [LinphoneManager instance].configuration.levelPushButton.name]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
otherButtonTitles:nil,nil];
[error show];
[error release];
// Not working during a call
// AudioServicesPlayAlertSound([LinphoneManager instance].sounds.level);
}
}
- (void)displayMessage:(id)message {
if (![[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]
|| [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
UIAlertView* error = [[UIAlertView alloc] initWithTitle:@"Welcome"
message: [NSString stringWithFormat:@"%@", [LinphoneManager instance].configuration.levelPushButton.name]
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
otherButtonTitles:nil,nil];
[error show];
[error release];
[[LinphoneManager instance] setSpeakerEnabled:TRUE];
AudioServicesPlayAlertSound([LinphoneManager instance].sounds.level);
}
}
+ (BuschJaegerMainView *) instance {
return mainViewInstance;
}
@end