diff --git a/Classes/VoiceBase/AddressBook/MGMContacts.m b/Classes/VoiceBase/AddressBook/MGMContacts.m index 61f9f70..410295a 100644 --- a/Classes/VoiceBase/AddressBook/MGMContacts.m +++ b/Classes/VoiceBase/AddressBook/MGMContacts.m @@ -305,11 +305,11 @@ const int MGMCMaxResults = 10; if (thePage==0) thePage = 1; long long int page = (thePage*maxResults)-maxResults; if (theString==nil || [string isEqual:@""]) { - result = [contactsConnection query:@"SELECT docid, * FROM contacts ORDER BY company, name LIMIT %qi, %i", page, maxResults]; + result = [contactsConnection query:@"SELECT docid, * FROM contacts ORDER BY company, name LIMIT %qi, %d", page, maxResults]; } else { if ([string isPhone]) { NSString *search = [NSString stringWithFormat:MGMCNum, [[string removePhoneWhiteSpace] littersToNumbers]]; - result = [contactsConnection query:@"SELECT docid, * FROM contacts WHERE number LIKE %@ ORDER BY company, name LIMIT %qi, %i", search, page, maxResults]; + result = [contactsConnection query:@"SELECT docid, * FROM contacts WHERE number LIKE %@ ORDER BY company, name LIMIT %qi, %d", search, page, maxResults]; } else { NSArray *words = [string componentsSeparatedByString:@" "]; NSMutableString *search = [NSMutableString string]; @@ -339,7 +339,7 @@ const int MGMCMaxResults = 10; } } } - result = [contactsConnection query:@"SELECT docid, *, offsets(contacts) AS offset FROM contacts WHERE contacts MATCH %@ ORDER BY offset LIMIT %qi, %i", search, page, maxResults]; + result = [contactsConnection query:@"SELECT docid, *, offsets(contacts) AS offset FROM contacts WHERE contacts MATCH %@ ORDER BY offset LIMIT %qi, %d", search, page, maxResults]; } } NSDictionary *contact = nil; @@ -364,7 +364,7 @@ const int MGMCMaxResults = 10; if ([string isPhone]) { for (int i=0; i<2; i++) { NSString *search = [NSString stringWithFormat:@"%@%%", (i==0 ? [string phoneFormat] : [string phoneFormatAreaCode:[delegate areaCode]])]; - MGMLiteResult *result = [contactsConnection query:@"SELECT docid, * FROM contacts WHERE number LIKE %@ ORDER BY company, name LIMIT %i", search, maxResults]; + MGMLiteResult *result = [contactsConnection query:@"SELECT docid, * FROM contacts WHERE number LIKE %@ ORDER BY company, name LIMIT %d", search, maxResults]; NSDictionary *contact = nil; while ((contact=[result nextRow])!=nil) { @@ -399,7 +399,7 @@ const int MGMCMaxResults = 10; [search appendFormat:MGMCWordSSA, word]; } } - MGMLiteResult *result = [contactsConnection query:@"SELECT docid, *, offsets(contacts) AS offset FROM contacts WHERE contacts MATCH %@ ORDER BY offset LIMIT %i", search, maxResults]; + MGMLiteResult *result = [contactsConnection query:@"SELECT docid, *, offsets(contacts) AS offset FROM contacts WHERE contacts MATCH %@ ORDER BY offset LIMIT %d", search, maxResults]; NSDictionary *contact = nil; while ((contact=[result nextRow])!=nil) { @@ -481,7 +481,9 @@ const int MGMCMaxResults = 10; else if (![[contact objectForKey:MGMCCompany] isEqual:@""]) return [contact objectForKey:MGMCCompany]; } - return [theNumber readableNumber]; + if ([theNumber isPhone]) + return [theNumber readableNumber]; + return theNumber; } - (NSArray *)groups { diff --git a/Classes/VoiceBase/MGMInbox.h b/Classes/VoiceBase/MGMInbox.h index 8edcde1..2297d7c 100644 --- a/Classes/VoiceBase/MGMInbox.h +++ b/Classes/VoiceBase/MGMInbox.h @@ -46,9 +46,9 @@ extern const int MGMIMissedType; extern const int MGMIReceivedType; extern const int MGMIVoicemailType; extern const int MGMIRecordedType; -extern const int MGMIPlaced; -extern const int MGMISMSIn; -extern const int MGMISMSOut; +extern const int MGMIPlacedType; +extern const int MGMISMSInType; +extern const int MGMISMSOutType; @interface MGMInbox : NSObject { MGMInstance *instance; diff --git a/Classes/VoiceBase/MGMInbox.m b/Classes/VoiceBase/MGMInbox.m index 4fb0052..10ea920 100644 --- a/Classes/VoiceBase/MGMInbox.m +++ b/Classes/VoiceBase/MGMInbox.m @@ -60,9 +60,9 @@ const int MGMIMissedType = 0; const int MGMIReceivedType = 1; const int MGMIVoicemailType = 2; const int MGMIRecordedType = 4; -const int MGMIPlaced = 8; -const int MGMISMSIn = 10; -const int MGMISMSOut = 11; +const int MGMIPlacedType = 8; +const int MGMISMSInType = 10; +const int MGMISMSOutType = 11; NSString * const MGMIPage = @"%@?page=p%d"; @@ -289,7 +289,7 @@ const BOOL MGMInboxInvisible = YES; [transcript appendFormat:@" %@", [[words objectAtIndex:w] stringValue]]; } [thisInfo setObject:transcript forKey:MGMIText]; - } else if (type==MGMISMSIn || type==MGMISMSOut) { + } else if (type==MGMISMSInType || type==MGMISMSOutType) { NSArray *messagesXML = [[message childAtIndex:0] nodesForXPath:[NSString stringWithFormat:@"/html[1]/body[1]/div[%d]/div[1]/div[2]/table[1]/tr[1]/td[3]/div[1]/table[1]/tr[2]/td[2]/table[1]/tr[2]/td[1]/div[1]/div[1]/table[1]/tr[1]/td[2]/div[1]/div[1]/div[1]/div", i+1] error:nil]; NSMutableArray *messagesArray = [NSMutableArray array]; for (unsigned int m=0; m<[messagesXML count]; m++) { diff --git a/Classes/VoiceBase/MGMSound.m b/Classes/VoiceBase/MGMSound.m index 9309064..0edf93f 100644 --- a/Classes/VoiceBase/MGMSound.m +++ b/Classes/VoiceBase/MGMSound.m @@ -42,6 +42,7 @@ } - (void)dealloc { if (sound!=nil) { + [sound setDelegate:nil]; [sound stop]; [sound release]; } diff --git a/Classes/VoiceBase/MGMThemeManager.m b/Classes/VoiceBase/MGMThemeManager.m index c236cd8..8453fbe 100644 --- a/Classes/VoiceBase/MGMThemeManager.m +++ b/Classes/VoiceBase/MGMThemeManager.m @@ -22,7 +22,7 @@ NSString * const MGMTCurrentThemePath = @"MGMTCurrentThemePath"; NSString * const MGMTCurrentThemeVariant = @"MGMTCurrentThemeVariant"; NSString * const MGMTShowHeader = @"MGMTShowHeader"; NSString * const MGMTShowFooter = @"MGMTShowFooter"; -NSString * const MGMTInfoPlist = @"info.plist"; +NSString * const MGMTInfoPlist = @"Info.plist"; NSString * const MGMTPResource = @"%RESOURCE%"; NSString * const MGMTPThemes = @"%THEMES%"; diff --git a/Classes/VoiceBase/SIP/MGMSIP.h b/Classes/VoiceBase/SIP/MGMSIP.h index 91f04fb..814cb3a 100644 --- a/Classes/VoiceBase/SIP/MGMSIP.h +++ b/Classes/VoiceBase/SIP/MGMSIP.h @@ -94,7 +94,9 @@ typedef enum { pjmedia_port *ringbackPort; pjsua_conf_port_id ringbackSlot; pjsua_transport_id UDPTransport; + pjsua_acc_id UDPAccount; pjsua_transport_id TCPTransport; + pjsua_acc_id TCPAccount; MGMSIPNATType NATType; BOOL shouldRestart; @@ -130,6 +132,10 @@ typedef enum { - (pjsua_media_config)mediaConfig; - (pjmedia_port *)ringbackPort; - (pjsua_conf_port_id)ringbackSlot; +- (pjsua_transport_id)UDPTransport; +- (pjsua_acc_id)UDPAccount; +- (pjsua_transport_id)TCPTransport; +- (pjsua_acc_id)TCPAccount; - (MGMSIPNATType)NATType; - (void)setNATType:(MGMSIPNATType)theNATType; @@ -139,13 +145,18 @@ typedef enum { - (void)computerSleep; - (void)computerWake; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 +- (void)keepAlive; +#endif + - (void)registerThread:(pj_thread_desc *)thePJThreadDesc; - (void)loginToAccount:(MGMSIPAccount *)theAccount; - (void)logoutOfAccount:(MGMSIPAccount *)theAccount; - (NSArray *)accounts; -- (MGMSIPAccount *)accountWithIdentifier:(int)theIdentifier; +- (pjsua_acc_id)accountIDForUserName:(NSString *)theUserName; +- (MGMSIPAccount *)accountWithIdentifier:(pjsua_acc_id)theIdentifier; - (int)ringbackCount; - (void)setRingbackCount:(int)theRingbackCount; @@ -167,6 +178,6 @@ typedef enum { - (void)receivedNewCall:(MGMSIPCall *)theCall; - (void)startingNewCall:(MGMSIPCall *)theCall; - (NSArray *)calls; -- (MGMSIPCall *)callWithIdentifier:(int)theIdentifier; +- (MGMSIPCall *)callWithIdentifier:(pjsua_call_id)theIdentifier; @end #endif \ No newline at end of file diff --git a/Classes/VoiceBase/SIP/MGMSIP.m b/Classes/VoiceBase/SIP/MGMSIP.m index acc700c..b357813 100644 --- a/Classes/VoiceBase/SIP/MGMSIP.m +++ b/Classes/VoiceBase/SIP/MGMSIP.m @@ -10,7 +10,9 @@ #import "MGMSIP.h" #import "MGMSIPAccount.h" #import "MGMSIPCall.h" +#import "MGMSIPURL.h" #import "MGMAddons.h" +#include #import #if !TARGET_OS_IPHONE #import @@ -20,6 +22,7 @@ NSString * const MGMSIPCopyright = @"Copyright (c) 2010 Mr. Gecko's Media (James const int MGMSIPMaxCalls = 8; const int MGMSIPDefaultOutboundProxyPort = 5060; +const int MGMSIPDefaultOutboundPort = 5060; const int MGMSIPDefaultSTUNPort = 3478; NSString * const MGMSIPOutboundProxy = @"MGMSIPOutboundProxy"; @@ -64,7 +67,17 @@ static MGMSIP *MGMSIPSingleton = nil; static void MGMSIPIncomingCallReceived(pjsua_acc_id accountIdentifier, pjsua_call_id callIdentifier, pjsip_rx_data *messageData) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; - PJ_LOG(3, (THIS_FILE, "Incoming call for account %d!", accountIdentifier)); + PJ_LOG(3, (THIS_FILE, "Incoming call %d for account %d", callIdentifier, accountIdentifier)); + + if (accountIdentifier==[[MGMSIP sharedSIP] UDPAccount] || accountIdentifier==[[MGMSIP sharedSIP] TCPAccount]) { + pjsua_call_info callInfo; + pj_status_t status = pjsua_call_get_info(callIdentifier, &callInfo); + if (status==PJ_SUCCESS) { + MGMSIPURL *localURL = [MGMSIPURL URLWithSIPID:[NSString stringWithPJString:callInfo.local_info]]; + accountIdentifier = [[MGMSIP sharedSIP] accountIDForUserName:[localURL userName]]; + } + } + MGMSIPAccount *account = [[MGMSIP sharedSIP] accountWithIdentifier:accountIdentifier]; MGMSIPCall *call = [account addCallWithIdentifier:callIdentifier]; [[MGMSIP sharedSIP] receivedNewCall:call]; @@ -193,7 +206,7 @@ static void MGMSIPCallTransferStatusChanged(pjsua_call_id callIdentifier, int st static void MGMSIPAccountRegistrationStateChanged(pjsua_acc_id accountIdentifier) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; MGMSIPAccount *account = [[MGMSIP sharedSIP] accountWithIdentifier:accountIdentifier]; - if ([account delegate]!=nil && [[account delegate] respondsToSelector:@selector(registrationChanged)]) [[account delegate] registrationChanged]; + if ([account delegate]!=nil && [[account delegate] respondsToSelector:@selector(registrationChanged)]) [(NSObject *)[account delegate] performSelectorOnMainThread:@selector(registrationChanged) withObject:nil waitUntilDone:NO]; [pool drain]; } @@ -351,6 +364,18 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void - (pjsua_conf_port_id)ringbackSlot { return ringbackSlot; } +- (pjsua_transport_id)UDPTransport { + return UDPTransport; +} +- (pjsua_acc_id)UDPAccount { + return UDPAccount; +} +- (pjsua_transport_id)TCPTransport { + return TCPTransport; +} +- (pjsua_acc_id)TCPAccount { + return TCPAccount; +} - (MGMSIPNATType)NATType { return NATType; } @@ -503,7 +528,8 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void [pool drain]; return; } - if (port == 0) { + pjsua_acc_add_local(UDPTransport, PJ_TRUE, &UDPAccount); + if (port==0) { pjsua_transport_info transportInfo; status = pjsua_transport_get_info(UDPTransport, &transportInfo); if (status!=PJ_SUCCESS) @@ -514,8 +540,12 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void } status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &transportConfig, &TCPTransport); - if (status!=PJ_SUCCESS) + if (status!=PJ_SUCCESS) { NSLog(@"Error creating TCP transport"); + } else { + pjsua_acc_add_local(TCPTransport, PJ_TRUE, &TCPAccount); + pjsua_acc_set_online_status(pjsua_acc_get_default(), PJ_TRUE); + } status = pjsua_start(); if (status!=PJ_SUCCESS) { @@ -649,6 +679,22 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void } } +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 +- (void)keepAlive { + if (state==MGMSIPStartedState) { + pj_thread_desc PJThreadDesc; + [self registerThread:&PJThreadDesc]; + + for (int i=0; i<(int)pjsua_acc_get_count(); ++i) { + if (!pjsua_acc_is_valid(i)) + continue; + pjsua_acc_set_registration(i, PJ_TRUE); + } + bzero(&PJThreadDesc, sizeof(pj_thread_desc)); + } +} +#endif + - (void)registerThread:(pj_thread_desc *)thePJThreadDesc { if (!pj_thread_is_registered()) { pj_thread_t *PJThread; @@ -697,7 +743,8 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void accountConfig.id = [[NSString stringWithFormat:@"%@ ", [theAccount fullName], [theAccount SIPAddress]] PJString]; else accountConfig.id = [[NSString stringWithFormat:@"", [theAccount SIPAddress]] PJString]; - accountConfig.reg_uri = [[NSString stringWithFormat:@"sip:%@", [theAccount registrar]] PJString]; + NSString *registerURI = [NSString stringWithFormat:@"sip:%@", [theAccount registrar]]; + accountConfig.reg_uri = [[registerURI stringByAppendingString:@";transport=tcp"] PJString]; if ([theAccount proxy]!=nil && ![[theAccount proxy] isEqual:@""]) { accountConfig.proxy_cnt = 1; @@ -715,13 +762,17 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void pjsua_acc_id identifier; pj_status_t status = pjsua_acc_add(&accountConfig, PJ_FALSE, &identifier); if (status!=PJ_SUCCESS) { - [theAccount setLastError:[NSString stringWithFormat:@"Unable to login with status %d.", status]]; - [theAccount loginErrored]; - NSLog(@"Error With Account %@: %@", theAccount, [theAccount lastError]); - [accounts removeObject:theAccount]; - bzero(&PJThreadDesc, sizeof(pj_thread_desc)); - [pool drain]; - return; + accountConfig.reg_uri = [registerURI PJString]; + pj_status_t status = pjsua_acc_add(&accountConfig, PJ_FALSE, &identifier); + if (status!=PJ_SUCCESS) { + [theAccount setLastError:[NSString stringWithFormat:@"Unable to login with status %d.", status]]; + [theAccount loginErrored]; + NSLog(@"Error With Account %@: %@", theAccount, [theAccount lastError]); + [accounts removeObject:theAccount]; + bzero(&PJThreadDesc, sizeof(pj_thread_desc)); + [pool drain]; + return; + } } [theAccount setIdentifier:identifier]; [theAccount setOnline:YES]; @@ -744,6 +795,8 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void pj_thread_desc PJThreadDesc; [self registerThread:&PJThreadDesc]; + [theAccount setOnline:NO]; + pj_status_t status = pjsua_acc_del([theAccount identifier]); if (status!=PJ_SUCCESS) { [theAccount setLastError:[NSString stringWithFormat:@"Unable to logout with status %d.", status]]; @@ -753,8 +806,8 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void return; } [theAccount setIdentifier:PJSUA_INVALID_ID]; + //if ([theAccount delegate]!=nil && [[theAccount delegate] respondsToSelector:@selector(loggedOut)]) [[theAccount delegate] loggedOut]; if (delegate!=nil && [delegate respondsToSelector:@selector(accountLoggedOut:)]) [delegate accountLoggedOut:theAccount]; - if ([theAccount delegate]!=nil && [[theAccount delegate] respondsToSelector:@selector(loggedOut)]) [[theAccount delegate] loggedOut]; [accounts removeObject:theAccount]; bzero(&PJThreadDesc, sizeof(pj_thread_desc)); [pool drain]; @@ -763,7 +816,31 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void - (NSArray *)accounts { return accounts; } -- (MGMSIPAccount *)accountWithIdentifier:(int)theIdentifier { +- (pjsua_acc_id)accountIDForUserName:(NSString *)theUserName { + for (int i=0; i<[accounts count]; i++) { + MGMSIPAccount *account = [accounts objectAtIndex:i]; + if ([[[account userName] lowercaseString] isEqual:[theUserName lowercaseString]]) + return [account identifier]; + + if ([[account userName] isPhone] && [[[account userName] phoneFormat] isEqual:[theUserName phoneFormat]]) + return [account identifier]; + + pjsua_acc_info info; + pj_status_t status = pjsua_acc_get_info([account identifier], &info); + if (status==PJ_SUCCESS) { + MGMSIPURL *url = [MGMSIPURL URLWithSIPID:[NSString stringWithPJString:info.acc_uri]]; + if ([[[url userName] lowercaseString] isEqual:[theUserName lowercaseString]]) + return [account identifier]; + + if ([[url userName] isPhone] && [[[url userName] phoneFormat] isEqual:[theUserName phoneFormat]]) + return [account identifier]; + } + } + if ([accounts count]<=1) + return [[accounts objectAtIndex:0] identifier]; + return PJSUA_INVALID_ID; +} +- (MGMSIPAccount *)accountWithIdentifier:(pjsua_acc_id)theIdentifier { for (int i=0; i<[accounts count]; i++) { if ([(MGMSIPAccount *)[accounts objectAtIndex:i] identifier]==theIdentifier) return [accounts objectAtIndex:i]; @@ -999,7 +1076,7 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void if (audioDevices!=nil) [audioDevices release]; audioDevices = [devicesArray copy]; - if ((currentInput==-1 ? defaultInputIndex!=lastInputDevice : currentInput!=lastInputDevice) && (currentOutput==-1 ? defaultOutputIndex!=lastOutputDevice : currentOutput!=lastOutputDevice)) { + //if ((currentInput==-1 ? defaultInputIndex!=lastInputDevice : currentInput!=lastInputDevice) && (currentOutput==-1 ? defaultOutputIndex!=lastOutputDevice : currentOutput!=lastOutputDevice)) { pj_thread_desc PJThreadDesc; [self registerThread:&PJThreadDesc]; @@ -1009,7 +1086,7 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void [self setInputSoundDevice:currentInput outputSoundDevice:currentOutput]; bzero(&PJThreadDesc, sizeof(pj_thread_desc)); - } + //} [[NSNotificationCenter defaultCenter] postNotificationName:MGMSIPAudioChangedNotification object:audioDevices]; @@ -1033,7 +1110,7 @@ static OSStatus MGMAudioDevicesChanged(AudioHardwarePropertyID propertyID, void [calls addObjectsFromArray:[[accounts objectAtIndex:i] calls]]; return calls; } -- (MGMSIPCall *)callWithIdentifier:(int)theIdentifier { +- (MGMSIPCall *)callWithIdentifier:(pjsua_call_id)theIdentifier { for (int i=0; i<[accounts count]; i++) { MGMSIPCall *call = [[accounts objectAtIndex:i] callWithIdentifier:theIdentifier]; if (call!=nil) diff --git a/Classes/VoiceBase/SIP/MGMSIPAccount.h b/Classes/VoiceBase/SIP/MGMSIPAccount.h index 8692736..0d505ee 100644 --- a/Classes/VoiceBase/SIP/MGMSIPAccount.h +++ b/Classes/VoiceBase/SIP/MGMSIPAccount.h @@ -12,6 +12,7 @@ #else #import #endif +#import extern NSString * const MGMSIPAccountFullName; extern NSString * const MGMSIPAccountUserName; @@ -49,7 +50,7 @@ extern const int MGMSIPAccountDefaultProxyPort; int reregisterTimeout; NSTimer *reregisterTimer; - int identifier; + pjsua_acc_id identifier; NSMutableArray *calls; @@ -78,8 +79,8 @@ extern const int MGMSIPAccountDefaultProxyPort; - (void)setProxyPort:(int)theProxyPort; - (int)reregisterTimeout; - (void)setReregisterTimeout:(int)theReregisterTimeout; -- (int)identifier; -- (void)setIdentifier:(int)theIdentifier; +- (pjsua_acc_id)identifier; +- (void)setIdentifier:(pjsua_acc_id)theIdentifier; - (NSString *)password; - (NSDictionary *)settings; diff --git a/Classes/VoiceBase/SIP/MGMSIPAccount.m b/Classes/VoiceBase/SIP/MGMSIPAccount.m index 6604ed3..01e1810 100644 --- a/Classes/VoiceBase/SIP/MGMSIPAccount.m +++ b/Classes/VoiceBase/SIP/MGMSIPAccount.m @@ -83,8 +83,8 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; return self; } - (void)dealloc { + NSLog(@"Releasing SIP Account"); [[NSNotificationCenter defaultCenter] removeObserver:self]; - [self logout]; if (calls!=nil) [calls release]; if (fullName!=nil) @@ -180,10 +180,10 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; else reregisterTimeout = theReregisterTimeout; } -- (int)identifier { +- (pjsua_acc_id)identifier { return identifier; } -- (void)setIdentifier:(int)theIdentifier { +- (void)setIdentifier:(pjsua_acc_id)theIdentifier { identifier = theIdentifier; } - (NSString *)password { @@ -355,7 +355,11 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; return call; } - (MGMSIPCall *)makeCallToNumber:(NSString *)theNumber { - MGMSIPURL *SIPURL = [MGMSIPURL URLWithFullName:nil userName:theNumber host:domain]; + MGMSIPURL *SIPURL = [MGMSIPURL URLWithSIPAddress:theNumber]; + if ([[SIPURL host] isEqual:theNumber]) { + [SIPURL setHost:domain]; + [SIPURL setUserName:theNumber]; + } return [self makeCallToSIPURL:SIPURL]; } - (MGMSIPCall *)makeCallToSIPURL:(MGMSIPURL *)theURL { diff --git a/Classes/VoiceBase/SIP/MGMSIPCall.h b/Classes/VoiceBase/SIP/MGMSIPCall.h index 9d4f873..c38f592 100644 --- a/Classes/VoiceBase/SIP/MGMSIPCall.h +++ b/Classes/VoiceBase/SIP/MGMSIPCall.h @@ -44,7 +44,7 @@ typedef enum { @interface MGMSIPCall : NSObject { id delegate; MGMSIPAccount *account; - int identifier; + pjsua_call_id identifier; MGMSIPURL *remoteURL; MGMSIPURL *localURL; @@ -57,6 +57,7 @@ typedef enum { BOOL incoming; BOOL muted; BOOL micMuted; + BOOL speaker; NSString *holdMusicPath; BOOL onHold; pjsua_player_id holdMusicPlayer; @@ -72,8 +73,8 @@ typedef enum { - (id)delegate; - (void)setDelegate:(id)theDelegate; - (MGMSIPAccount *)account; -- (int)identifier; -- (void)setIdentifier:(int)theIdentifier; +- (pjsua_call_id)identifier; +- (void)setIdentifier:(pjsua_call_id)theIdentifier; - (MGMSIPURL *)remoteURL; - (MGMSIPURL *)localURL; @@ -126,5 +127,10 @@ typedef enum { - (void)mute; - (BOOL)isMicMuted; - (void)muteMic; + +#if TARGET_OS_IPHONE +- (BOOL)isOnSpeaker; +- (void)speaker; +#endif @end #endif \ No newline at end of file diff --git a/Classes/VoiceBase/SIP/MGMSIPCall.m b/Classes/VoiceBase/SIP/MGMSIPCall.m index 32dfdfd..a60c76a 100644 --- a/Classes/VoiceBase/SIP/MGMSIPCall.m +++ b/Classes/VoiceBase/SIP/MGMSIPCall.m @@ -12,9 +12,10 @@ #import "MGMSIPURL.h" #import "MGMSIP.h" #import "MGMAddons.h" +#import @implementation MGMSIPCall -- (id)initWithIdentifier:(int)theIdentifier account:(MGMSIPAccount *)theAccount { +- (id)initWithIdentifier:(pjsua_call_id)theIdentifier account:(MGMSIPAccount *)theAccount { if (self = [super init]) { account = theAccount; identifier = theIdentifier; @@ -40,19 +41,8 @@ incoming = (state==MGMSIPCallIncomingState); muted = NO; - - pjsua_media_config mediaConfig = [[MGMSIP sharedSIP] mediaConfig]; - unsigned int samplesPerFrame = mediaConfig.audio_frame_ptime * mediaConfig.clock_rate * mediaConfig.channel_count / 1000; - pj_status_t status = pjmedia_tonegen_create([[MGMSIP sharedSIP] PJPool], mediaConfig.clock_rate, mediaConfig.channel_count, samplesPerFrame, 16, 0, &toneGenPort); - if (status!=PJ_SUCCESS) { - NSLog(@"Error creating tone generator"); - } else { - status = pjsua_conf_add_port([[MGMSIP sharedSIP] PJPool], toneGenPort, &toneGenSlot); - if (status!=PJ_SUCCESS) - NSLog(@"Error adding tone generator"); - else - pjsua_conf_connect(toneGenSlot, 0); - } + speaker = NO; + toneGenSlot = PJSUA_INVALID_ID; } bzero(&PJThreadDesc, sizeof(pj_thread_desc)); } @@ -74,7 +64,7 @@ [transferStatusText release]; if (holdMusicPath!=nil) [holdMusicPath release]; - if (toneGenPort!=NULL) { + if (toneGenSlot!=PJSUA_INVALID_ID) { pjsua_conf_remove_port(toneGenSlot); pjmedia_port_destroy(toneGenPort); toneGenPort = NULL; @@ -95,10 +85,10 @@ - (MGMSIPAccount *)account { return account; } -- (int)identifier { +- (pjsua_call_id)identifier { return identifier; } -- (void)setIdentifier:(int)theIdentifier { +- (void)setIdentifier:(pjsua_call_id)theIdentifier { identifier = theIdentifier; } @@ -114,6 +104,11 @@ } - (void)setState:(MGMSIPCallState)theState { if (theState==MGMSIPCallDisconnectedState) { +#if TARGET_OS_IPHONE + if (speaker) [self speaker]; +#endif + if (isRingbackOn) + [self stopRingback]; if (holdMusicPlayer!=PJSUA_INVALID_ID) [self performSelectorOnMainThread:@selector(stopHoldMusic) withObject:nil waitUntilDone:NO]; if (recorderID!=PJSUA_INVALID_ID) @@ -296,7 +291,7 @@ } - (void)startRingback { - if (identifier==PJSUA_INVALID_ID || state==MGMSIPCallDisconnectedState) + if (identifier==PJSUA_INVALID_ID) return; if (isRingbackOn) @@ -312,7 +307,7 @@ bzero(&PJThreadDesc, sizeof(pj_thread_desc)); } - (void)stopRingback { - if (identifier==PJSUA_INVALID_ID || state==MGMSIPCallDisconnectedState) + if (identifier==PJSUA_INVALID_ID) return; if (!isRingbackOn) @@ -323,7 +318,7 @@ [[MGMSIP sharedSIP] registerThread:&PJThreadDesc]; int ringbackCount = [[MGMSIP sharedSIP] ringbackCount]; - if (ringbackCount<0) return; + if (ringbackCount<=0) return; [[MGMSIP sharedSIP] setRingbackCount:ringbackCount-1]; if ([[MGMSIP sharedSIP] ringbackSlot]!=PJSUA_INVALID_ID) { pjsua_conf_disconnect([[MGMSIP sharedSIP] ringbackSlot], 0); @@ -356,6 +351,21 @@ sendSuccessful = (status==PJ_SUCCESS); } } + + if (toneGenSlot==PJSUA_INVALID_ID) { + pjsua_media_config mediaConfig = [[MGMSIP sharedSIP] mediaConfig]; + unsigned int samplesPerFrame = mediaConfig.audio_frame_ptime * mediaConfig.clock_rate * mediaConfig.channel_count / 1000; + pj_status_t status = pjmedia_tonegen_create([[MGMSIP sharedSIP] PJPool], mediaConfig.clock_rate, mediaConfig.channel_count, samplesPerFrame, 16, 0, &toneGenPort); + if (status!=PJ_SUCCESS) { + NSLog(@"Error creating tone generator"); + } else { + status = pjsua_conf_add_port([[MGMSIP sharedSIP] PJPool], toneGenPort, &toneGenSlot); + if (status!=PJ_SUCCESS) + NSLog(@"Error adding tone generator"); + else + pjsua_conf_connect(toneGenSlot, 0); + } + } if (!sendSuccessful) pjsua_conf_connect(toneGenSlot, pjsua_call_get_conf_port(identifier)); for (unsigned int i=0; i<[theDigits length]; i++) { @@ -520,5 +530,17 @@ micMuted = !micMuted; bzero(&PJThreadDesc, sizeof(pj_thread_desc)); } + +#if TARGET_OS_IPHONE +- (BOOL)isOnSpeaker { + return speaker; +} +- (void)speaker { + speaker = !speaker; + UInt32 route = (speaker ? kAudioSessionOverrideAudioRoute_Speaker : kAudioSessionOverrideAudioRoute_None); + if (AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(route), &route)!=noErr) + speaker = !speaker; +} +#endif @end #endif \ No newline at end of file diff --git a/Classes/VoiceMac/Inbox/MGMInboxWindow.m b/Classes/VoiceMac/Inbox/MGMInboxWindow.m index 9ce63c6..0fba351 100644 --- a/Classes/VoiceMac/Inbox/MGMInboxWindow.m +++ b/Classes/VoiceMac/Inbox/MGMInboxWindow.m @@ -380,7 +380,7 @@ NSString * const MGMSID = @"id"; int type = [[data objectForKey:MGMIType] intValue]; if (type==MGMIVoicemailType) { return [data objectForKey:MGMIText]; - } else if (type==MGMISMSIn || type==MGMISMSOut) { + } else if (type==MGMISMSInType || type==MGMISMSOutType) { return [[[[data objectForKey:MGMIMessages] lastObject] objectForKey:MGMIText] flattenHTML]; } else { return [[[data objectForKey:MGMIPhoneNumber] areaCode] areaCodeLocation]; @@ -425,7 +425,7 @@ NSString * const MGMSID = @"id"; rowRect.origin.x += ((rowRect.size.width-[playWindow frame].size.width)/2); [playWindow setFrameOrigin:rowRect.origin]; [playWindow makeKeyAndOrderFront:self]; - } else if (type==MGMISMSIn || type==MGMISMSOut) { + } else if (type==MGMISMSInType || type==MGMISMSOutType) { [[[(MGMVoiceUser *)[instance delegate] controller] SMSManager] messageWithData:data instance:instance]; } else { [(MGMVoiceUser *)[instance delegate] runAction:sender]; diff --git a/Classes/VoiceMac/MGMAccountSetup.m b/Classes/VoiceMac/MGMAccountSetup.m index f30cd1a..7bac7fb 100644 --- a/Classes/VoiceMac/MGMAccountSetup.m +++ b/Classes/VoiceMac/MGMAccountSetup.m @@ -437,6 +437,9 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; return [S7CheckUser password]; } - (void)registrationChanged { + [self performSelector:@selector(S7RegistrationChanged) withObject:nil afterDelay:0.5]; +} +- (void)S7RegistrationChanged { #if MGMSIPENABLED if (S7SIPRegistrationTimeout!=nil) { [S7SIPRegistrationTimeout invalidate]; diff --git a/Classes/VoiceMac/SIP/MGMSIPCallWindow.m b/Classes/VoiceMac/SIP/MGMSIPCallWindow.m index 8f65576..824e19c 100644 --- a/Classes/VoiceMac/SIP/MGMSIPCallWindow.m +++ b/Classes/VoiceMac/SIP/MGMSIPCallWindow.m @@ -76,7 +76,7 @@ NSString * const MGMSCTitleNoNameFormat = @"Call With %@"; [incomingWindow makeKeyAndOrderFront:self]; [call sendRingingNotification]; NSString *ringtonePath = [[[SIPUser controller] themeManager] currentSoundPath:MGMTSSIPRingtone]; - if (![ringtonePath isEqual:MGMTNoSound]) { + if (ringtonePath!=nil && ![ringtonePath isEqual:MGMTNoSound]) { ringtone = [[MGMSound alloc] initWithContentsOfFile:ringtonePath]; [ringtone setLoops:YES]; [ringtone play]; @@ -103,6 +103,14 @@ NSString * const MGMSCTitleNoNameFormat = @"Call With %@"; [callWindow makeKeyAndOrderFront:self]; } + if ([call state]==MGMSIPCallDisconnectedState) { + if (ringtone!=nil) { + [ringtone stop]; + [ringtone release]; + ringtone = nil; + } + } + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(soundChanged:) name:MGMTSoundChangedNotification object:nil]; [notificationCenter addObserver:self selector:@selector(volumeChanged:) name:MGMSIPVolumeChangedNotification object:nil]; diff --git a/Classes/VoiceMac/SIP/MGMSIPUser.m b/Classes/VoiceMac/SIP/MGMSIPUser.m index b950d6f..6c37aee 100644 --- a/Classes/VoiceMac/SIP/MGMSIPUser.m +++ b/Classes/VoiceMac/SIP/MGMSIPUser.m @@ -67,6 +67,14 @@ NSString * const MGMSIPUserAreaCode = @"MGMVSIPUserAreaCode"; [progressFadeAnimation release]; progressFadeAnimation = nil; } + if (progressView!=nil) { + [progressView stopProgess]; + [progressView release]; + } + if (SIPRegistrationTimeout!=nil) { + [SIPRegistrationTimeout invalidate]; + [SIPRegistrationTimeout release]; + } [super dealloc]; if (calls!=nil) { [calls removeAllObjects]; @@ -218,6 +226,19 @@ NSString * const MGMSIPUserAreaCode = @"MGMVSIPUserAreaCode"; - (IBAction)runAction:(id)sender { [self call:sender]; } +- (NSString *)currentPhoneNumber { + NSString *phoneNumber = nil; + if (phoneNumber==nil && ![[phoneField stringValue] isPhoneComplete]) { + if ([contactViews count]>0) { + [self selectFirstContact]; + } else { + return [phoneField stringValue]; + } + } + if (phoneNumber==nil) + phoneNumber = [[phoneField stringValue] phoneFormatWithAreaCode:[self areaCode]]; + return phoneNumber; +} - (IBAction)call:(id)sender { NSString *phoneNumber = [controller currentPhoneNumber]; if (phoneNumber==nil || [phoneNumber isEqual:@""]) { diff --git a/Frameworks/MGMUsers.framework/Versions/A/MGMUsers b/Frameworks/MGMUsers.framework/Versions/A/MGMUsers index 24c3102..6588d6f 100755 Binary files a/Frameworks/MGMUsers.framework/Versions/A/MGMUsers and b/Frameworks/MGMUsers.framework/Versions/A/MGMUsers differ diff --git a/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTaskView.nib b/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTaskView.nib index 198ab76..c3d84df 100644 Binary files a/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTaskView.nib and b/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTaskView.nib differ diff --git a/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTasksWindow.nib b/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTasksWindow.nib index dd64905..7059746 100644 Binary files a/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTasksWindow.nib and b/Frameworks/MGMUsers.framework/Versions/A/Resources/MGMTasksWindow.nib differ diff --git a/SIP/notes.txt b/SIP/notes.txt index 58cc98f..c16806e 100755 --- a/SIP/notes.txt +++ b/SIP/notes.txt @@ -3,7 +3,7 @@ To get the latest source to PJProject, run the command below. svn checkout http://svn.pjsip.org/repos/pjproject/trunk pjproject To get the revision that I am using in VoiceMac and VoiceMob, run the command below. -svn checkout -r 3334 http://svn.pjsip.org/repos/pjproject/trunk pjproject +svn checkout -r 3346 http://svn.pjsip.org/repos/pjproject/trunk pjproject Building. To build for VoiceMac, run the command below. diff --git a/VoiceBase.xcodeproj/project.pbxproj b/VoiceBase.xcodeproj/project.pbxproj index 285d922..2c85213 100644 --- a/VoiceBase.xcodeproj/project.pbxproj +++ b/VoiceBase.xcodeproj/project.pbxproj @@ -523,6 +523,7 @@ isa = PBXProject; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "VoiceBase" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en, @@ -874,14 +875,17 @@ "$(inherited)", "\"$(SRCROOT)/Libraries/lib\"", ); - OTHER_CFLAGS = "-fblocks"; + OTHER_CFLAGS = ( + "-D__IPHONE_OS_VERSION_MIN_REQUIRED=030000", + "-fblocks", + ); OTHER_LDFLAGS = ( "-ObjC", "-all_load", ); PREBINDING = NO; PRODUCT_NAME = VoiceBase; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; }; name = Debug; }; @@ -901,6 +905,7 @@ "\"$(SRCROOT)/Libraries/lib\"", ); OTHER_CFLAGS = ( + "-D__IPHONE_OS_VERSION_MIN_REQUIRED=030000", "-fblocks", "-DPJ_AUTOCONF=1", "-DNDEBUG", @@ -929,7 +934,7 @@ ); PREBINDING = NO; PRODUCT_NAME = VoiceBase; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; }; name = "Debug SIP"; }; @@ -951,14 +956,17 @@ "$(inherited)", "\"$(SRCROOT)/Libraries/lib\"", ); - OTHER_CFLAGS = "-fblocks"; + OTHER_CFLAGS = ( + "-D__IPHONE_OS_VERSION_MIN_REQUIRED=030000", + "-fblocks", + ); OTHER_LDFLAGS = ( "-ObjC", "-all_load", ); PREBINDING = NO; PRODUCT_NAME = VoiceBase; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; ZERO_LINK = NO; }; name = Release; @@ -979,6 +987,7 @@ "\"$(SRCROOT)/Libraries/lib\"", ); OTHER_CFLAGS = ( + "-D__IPHONE_OS_VERSION_MIN_REQUIRED=030000", "-fblocks", "-DPJ_AUTOCONF=1", "-DNDEBUG", @@ -1009,7 +1018,7 @@ PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/VoiceBase; PRODUCT_NAME = VoiceBase; PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/VoiceBase; - SDKROOT = iphoneos4.0; + SDKROOT = iphoneos4.1; }; name = "Release SIP"; }; diff --git a/VoiceMac.xcodeproj/project.pbxproj b/VoiceMac.xcodeproj/project.pbxproj index 2f33855..079c619 100644 --- a/VoiceMac.xcodeproj/project.pbxproj +++ b/VoiceMac.xcodeproj/project.pbxproj @@ -633,6 +633,7 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "VoiceMac" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en,