diff --git a/Classes/VoiceBase/AddressBook/MGMContacts.m b/Classes/VoiceBase/AddressBook/MGMContacts.m index 47175b2..962e62c 100644 --- a/Classes/VoiceBase/AddressBook/MGMContacts.m +++ b/Classes/VoiceBase/AddressBook/MGMContacts.m @@ -158,7 +158,7 @@ const int MGMCMaxResults = 10; NSLog(@"Getting Contacts"); [updateConnection setLogQuery:YES]; #endif - [updateConnection query:@"CREATE VIRTUAL TABLE contacts USING fts3(name, company, number, label, photo)"]; + [updateConnection query:@"CREATE VIRTUAL TABLE contacts USING fts3(name, company, number INTEGER, label, photo)"]; [updateConnection query:@"CREATE TABLE groups (docid INTEGER PRIMARY KEY AUTOINCREMENT, name)"]; [updateConnection query:@"CREATE TABLE groupMembers (docid INTEGER PRIMARY KEY AUTOINCREMENT, groupid INTEGER, contactid INTEGER)"]; [updateLock unlock]; diff --git a/Classes/VoiceBase/MGMAddons.m b/Classes/VoiceBase/MGMAddons.m index b258081..8773592 100644 --- a/Classes/VoiceBase/MGMAddons.m +++ b/Classes/VoiceBase/MGMAddons.m @@ -56,20 +56,19 @@ while (1) { NSRange rangeToCopy; NSRange foundRange = [self rangeOfString:targetString options:0 range:rangeInOriginalString]; - if (foundRange.length == 0) break; + if (foundRange.length==0) break; rangeToCopy = NSMakeRange(rangeInOriginalString.location, foundRange.location - rangeInOriginalString.location); [temp appendString:[self substringWithRange:rangeToCopy]]; [temp appendString:replaceString]; - rangeInOriginalString.length -= NSMaxRange(foundRange) - - rangeInOriginalString.location; + rangeInOriginalString.length -= (NSMaxRange(foundRange)-rangeInOriginalString.location); rangeInOriginalString.location = NSMaxRange(foundRange); replaced++; - if (replaced % 100 == 0) { + if ((replaced%100)==0) { [pool drain]; pool = [NSAutoreleasePool new]; } } - if (rangeInOriginalString.length > 0) [temp appendString:[self substringWithRange:rangeInOriginalString]]; + if (rangeInOriginalString.length>0) [temp appendString:[self substringWithRange:rangeInOriginalString]]; [pool drain]; return [temp autorelease]; @@ -1309,13 +1308,10 @@ - (NSString *)addPercentEscapes { NSString *result = [self stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("!*'();:^@&=+$,/?%#[]|"), kCFStringEncodingUTF8); - if (escapedString) { - result = [NSString stringWithString:(NSString *)escapedString]; - CFRelease(escapedString); - } + if (escapedString!=NULL) + result = [(NSString *)escapedString autorelease]; return result; } diff --git a/Classes/VoiceBase/MGMInstance.m b/Classes/VoiceBase/MGMInstance.m index 220378d..2fd9766 100644 --- a/Classes/VoiceBase/MGMInstance.m +++ b/Classes/VoiceBase/MGMInstance.m @@ -530,8 +530,18 @@ const BOOL MGMInstanceInvisible = YES; [handler setFinish:@selector(indexDidFinish:)]; [handler setInvisible:MGMInstanceInvisible]; [connectionManager addHandler:handler]; - } else { - NSString *string, *guser = @"", *phonesInfo = @""; + } else if ([[[[theHandler request] URL] relativeString] containsString:@"NewPrivacyPolicy"]) { + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://accounts.google.com/b/0/NewPrivacyPolicy"]]; + [request setHTTPMethod:MGMPostMethod]; + [request setValue:MGMURLForm forHTTPHeaderField:MGMContentType]; + [request setHTTPBody:[@"service=grandcentral&continue=https://www.google.com/voice&submitbutton=OK,%20got%20it" dataUsingEncoding:NSUTF8StringEncoding]]; + MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:request delegate:self]; + [handler setFailWithError:@selector(index:didFailWithError:)]; + [handler setFinish:@selector(indexDidFinish:)]; + [handler setInvisible:MGMInstanceInvisible]; + [connectionManager addHandler:handler]; + } else { + NSString *string, *guser = @"", *phonesInfo = @""; NSRange range; #if MGMInstanceDebug diff --git a/Classes/VoiceBase/SIP/MGMSIPAccount.h b/Classes/VoiceBase/SIP/MGMSIPAccount.h index b5a59e5..254d3f5 100644 --- a/Classes/VoiceBase/SIP/MGMSIPAccount.h +++ b/Classes/VoiceBase/SIP/MGMSIPAccount.h @@ -69,9 +69,9 @@ extern const int MGMSIPAccountDefaultProxyPort; NSString *lastError; } - (id)initWithSettings:(NSDictionary *)theSettings; -- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain; -- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress; -- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress registrar:(NSString *)theRegistrar; +- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar; +- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress; +- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress domain:(NSString *)theDomain; - (BOOL)informationComplete; - (id)delegate; - (void)setDelegate:(id)theDelegate; diff --git a/Classes/VoiceBase/SIP/MGMSIPAccount.m b/Classes/VoiceBase/SIP/MGMSIPAccount.m index 9df5f38..6b54d84 100644 --- a/Classes/VoiceBase/SIP/MGMSIPAccount.m +++ b/Classes/VoiceBase/SIP/MGMSIPAccount.m @@ -44,16 +44,16 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; @implementation MGMSIPAccount - (id)initWithSettings:(NSDictionary *)theSettings { if ((self = [self init])) { - if ([theSettings objectForKey:MGMSIPAccountUserName]==nil || [[theSettings objectForKey:MGMSIPAccountUserName] isEqual:@""] || [theSettings objectForKey:MGMSIPAccountDomain]==nil || [[theSettings objectForKey:MGMSIPAccountDomain] isEqual:@""]) { + if ([theSettings objectForKey:MGMSIPAccountUserName]==nil || [[theSettings objectForKey:MGMSIPAccountUserName] isEqual:@""] || [theSettings objectForKey:MGMSIPAccountRegistrar]==nil || [[theSettings objectForKey:MGMSIPAccountRegistrar] isEqual:@""]) { [self release]; self = nil; } else { if ([theSettings objectForKey:MGMSIPAccountFullName]!=nil && ![[theSettings objectForKey:MGMSIPAccountFullName] isEqual:@""]) fullName = [[theSettings objectForKey:MGMSIPAccountFullName] copy]; userName = [[theSettings objectForKey:MGMSIPAccountUserName] copy]; - domain = [[theSettings objectForKey:MGMSIPAccountDomain] copy]; - if ([theSettings objectForKey:MGMSIPAccountRegistrar]!=nil && ![[theSettings objectForKey:MGMSIPAccountRegistrar] isEqual:@""]) - registrar = [[theSettings objectForKey:MGMSIPAccountRegistrar] copy]; + registrar = [[theSettings objectForKey:MGMSIPAccountRegistrar] copy]; + if ([theSettings objectForKey:MGMSIPAccountDomain]!=nil && ![[theSettings objectForKey:MGMSIPAccountDomain] isEqual:@""]) + domain = [[theSettings objectForKey:MGMSIPAccountDomain] copy]; if ([theSettings objectForKey:MGMSIPAccountSIPAddress]!=nil && ![[theSettings objectForKey:MGMSIPAccountSIPAddress] isEqual:@""]) SIPAddress = [[theSettings objectForKey:MGMSIPAccountSIPAddress] copy]; if ([theSettings objectForKey:MGMSIPAccountProxy]!=nil && ![[theSettings objectForKey:MGMSIPAccountProxy] isEqual:@""]) @@ -76,23 +76,23 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; } return self; } -- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain { - return [self initWithFullName:theFullName userName:theUserName domain:theDomain SIPAddress:nil]; +- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar { + return [self initWithFullName:theFullName userName:theUserName registrar:theRegistrar SIPAddress:nil]; } -- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress { - return [self initWithFullName:theFullName userName:theUserName domain:theDomain SIPAddress:theSIPAddress registrar:nil]; +- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress { + return [self initWithFullName:theFullName userName:theUserName registrar:theRegistrar SIPAddress:theSIPAddress domain:nil]; } -- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress registrar:(NSString *)theRegistrar { - if (theUserName==nil || theDomain==nil) return nil; +- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress domain:(NSString *)theDomain { + if (theUserName==nil || theRegistrar==nil) return nil; NSMutableDictionary *settings = [NSMutableDictionary dictionary]; if (theFullName!=nil) [settings setObject:theFullName forKey:MGMSIPAccountFullName]; [settings setObject:theUserName forKey:MGMSIPAccountUserName]; - [settings setObject:theDomain forKey:MGMSIPAccountDomain]; + [settings setObject:theRegistrar forKey:MGMSIPAccountRegistrar]; if (theSIPAddress!=nil) [settings setObject:theSIPAddress forKey:MGMSIPAccountSIPAddress]; - if (theRegistrar!=nil) - [settings setObject:theRegistrar forKey:MGMSIPAccountRegistrar]; + if (theDomain!=nil) + [settings setObject:theDomain forKey:MGMSIPAccountDomain]; return [self initWithSettings:settings]; } - (id)init { @@ -118,7 +118,7 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; } - (BOOL)informationComplete { - return ((delegate!=nil && [delegate respondsToSelector:@selector(password)]) && userName!=nil && (domain!=nil || [self SIPAddress]!=nil)); + return ((delegate!=nil && [delegate respondsToSelector:@selector(password)]) && userName!=nil && (registrar!=nil || [self SIPAddress]!=nil)); } - (NSString *)description { return [NSString stringWithFormat:@"%@ %@", [super description], [self SIPAddress]]; @@ -145,6 +145,7 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; userName = [theUserName copy]; } - (NSString *)domain { + if ((domain==nil || [domain isEqual:@""]) && registrar!=nil) return registrar; return domain; } - (void)setDomain:(NSString *)theDomain { @@ -152,7 +153,6 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300; domain = [theDomain copy]; } - (NSString *)registrar { - if (registrar==nil && domain!=nil) return domain; return registrar; } - (void)setRegistrar:(NSString *)theRegistrar { diff --git a/Classes/VoiceMac/MGMAccountSetup.h b/Classes/VoiceMac/MGMAccountSetup.h index a63d7b2..d499084 100644 --- a/Classes/VoiceMac/MGMAccountSetup.h +++ b/Classes/VoiceMac/MGMAccountSetup.h @@ -97,7 +97,7 @@ extern NSString * const MGMSAccountType; //Step 6 - (IBAction)S6UserNameChanged:(id)sender; -- (IBAction)S6DomainChanged:(id)sender; +- (IBAction)S6RegistrarChanged:(id)sender; - (void)S6Reset; //Step 7 diff --git a/Classes/VoiceMac/MGMAccountSetup.m b/Classes/VoiceMac/MGMAccountSetup.m index 9955a3d..876d22e 100644 --- a/Classes/VoiceMac/MGMAccountSetup.m +++ b/Classes/VoiceMac/MGMAccountSetup.m @@ -303,11 +303,11 @@ NSString * const MGMS7SIPWaiting = @"Waiting for Registration Status."; - (IBAction)S6UserNameChanged:(id)sender { [[S6FullNameField cell] setPlaceholderString:[S6UserNameField stringValue]]; } -- (IBAction)S6DomainChanged:(id)sender { - if ([[S6DomainField stringValue] isEqual:@""]) - [[S6RegistrarField cell] setPlaceholderString:@""]; +- (IBAction)S6RegistrarChanged:(id)sender { + if ([[S6RegistrarField stringValue] isEqual:@""]) + [[S6DomainField cell] setPlaceholderString:@"Providers usually require *"]; else - [[S6RegistrarField cell] setPlaceholderString:[S6DomainField stringValue]]; + [[S6DomainField cell] setPlaceholderString:[S6DomainField stringValue]]; } - (void)S6Reset { [S6FullNameField setStringValue:@""]; diff --git a/Classes/VoiceMac/MGMController.m b/Classes/VoiceMac/MGMController.m index 723ce87..b475ec0 100644 --- a/Classes/VoiceMac/MGMController.m +++ b/Classes/VoiceMac/MGMController.m @@ -69,8 +69,9 @@ NSString * const MGMLoading = @"Loading..."; [defaults removeObjectForKey:MGMMakeDefault]; } + NSString *appVersion = [[MGMSystemInfo info] applicationVersion]; if ([defaults objectForKey:MGMVersion]==nil) { - [defaults setObject:[[MGMSystemInfo info] applicationVersion] forKey:MGMVersion]; + [defaults setObject:appVersion forKey:MGMVersion]; [defaults removeObjectForKey:@"actionCall"]; [defaults removeObjectForKey:@"googleContact"]; [defaults removeObjectForKey:@"lastPhone"]; @@ -85,6 +86,24 @@ NSString * const MGMLoading = @"Loading..."; [defaults removeObjectForKey:@"SMSThemePath"]; [defaults removeObjectForKey:@"SMSThemeVariant"]; } +#if MGMSIPENABLED + if (![[defaults objectForKey:MGMVersion] isEqual:@"0.3"]) { + [defaults setObject:appVersion forKey:MGMVersion]; + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + NSArray *users = [MGMUser users]; + for (int i=0; i<[users count]; i++) { + MGMUser *user = [MGMUser userWithID:[users objectAtIndex:i]]; + if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) { + if ([user settingForKey:MGMSIPAccountRegistrar]==nil || [[user settingForKey:MGMSIPAccountRegistrar] isEqual:@""]) + [user setSetting:[user settingForKey:MGMSIPAccountDomain] forKey:MGMSIPAccountRegistrar]; + } + } + [pool drain]; + } +#endif + if (![[defaults objectForKey:MGMVersion] isEqual:appVersion]) { + [defaults setObject:appVersion forKey:MGMVersion]; + } [self registerDefaults]; if ([defaults integerForKey:MGMLaunchCount]!=5) { [defaults setInteger:[defaults integerForKey:MGMLaunchCount]+1 forKey:MGMLaunchCount]; diff --git a/Classes/VoiceMac/MGMVoiceVerify.h b/Classes/VoiceMac/MGMVoiceVerify.h index 32b7920..e7407b9 100644 --- a/Classes/VoiceMac/MGMVoiceVerify.h +++ b/Classes/VoiceMac/MGMVoiceVerify.h @@ -25,6 +25,7 @@ MGMInstance *instance; IBOutlet NSWindow *window; + IBOutlet NSTextField *accountNameField; IBOutlet NSTextField *codeField; } + (id)verifyWithInstance:(MGMInstance *)theInstance; diff --git a/Classes/VoiceMac/MGMVoiceVerify.m b/Classes/VoiceMac/MGMVoiceVerify.m index 7b479ca..f6f1997 100644 --- a/Classes/VoiceMac/MGMVoiceVerify.m +++ b/Classes/VoiceMac/MGMVoiceVerify.m @@ -19,6 +19,7 @@ #import "MGMVoiceVerify.h" #import +#import @implementation MGMVoiceVerify + (id)verifyWithInstance:(MGMInstance *)theInstance { @@ -33,6 +34,7 @@ self = nil; } else { instance = theInstance; + [accountNameField setStringValue:[[instance user] settingForKey:MGMUserName]]; [window makeKeyAndOrderFront:self]; } } diff --git a/Classes/VoiceMac/Preferences/MGMAccountsPane.m b/Classes/VoiceMac/Preferences/MGMAccountsPane.m index 2746dee..ee9173d 100644 --- a/Classes/VoiceMac/Preferences/MGMAccountsPane.m +++ b/Classes/VoiceMac/Preferences/MGMAccountsPane.m @@ -260,17 +260,17 @@ NSString * const MGMLogout = @"Logout"; [SIPFullNameField setStringValue:[user settingForKey:MGMSIPAccountFullName]]; else [SIPFullNameField setStringValue:@""]; - if ([user settingForKey:MGMSIPAccountDomain]==nil || [[user settingForKey:MGMSIPAccountDomain] isEqual:@""]) { - [[SIPRegistrarField cell] setPlaceholderString:@""]; - [SIPDomainField setStringValue:@""]; - } else { - [[SIPRegistrarField cell] setPlaceholderString:[user settingForKey:MGMSIPAccountDomain]]; + if ([user settingForKey:MGMSIPAccountDomain]!=nil) [SIPDomainField setStringValue:[user settingForKey:MGMSIPAccountDomain]]; - } - if ([user settingForKey:MGMSIPAccountRegistrar]!=nil) - [SIPRegistrarField setStringValue:[user settingForKey:MGMSIPAccountRegistrar]]; else + [SIPDomainField setStringValue:@""]; + if ([user settingForKey:MGMSIPAccountRegistrar]==nil || [[user settingForKey:MGMSIPAccountRegistrar] isEqual:@""]) { + [[SIPDomainField cell] setPlaceholderString:@"Usually *"]; [SIPRegistrarField setStringValue:@""]; + } else { + [[SIPDomainField cell] setPlaceholderString:[user settingForKey:MGMSIPAccountRegistrar]]; + [SIPRegistrarField setStringValue:[user settingForKey:MGMSIPAccountRegistrar]]; + } if ([user settingForKey:MGMSIPAccountUserName]!=nil) [SIPUserNameField setStringValue:[user settingForKey:MGMSIPAccountUserName]]; else @@ -292,7 +292,7 @@ NSString * const MGMLogout = @"Logout"; [SIPSIPAddressField setStringValue:[user settingForKey:MGMSIPAccountSIPAddress]]; else [SIPSIPAddressField setStringValue:@""]; - [[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountDomain]]]; + [[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountRegistrar]]]; if ([user settingForKey:MGMSIPAccountRegisterTimeout]!=nil && [[user settingForKey:MGMSIPAccountRegisterTimeout] intValue]!=0) [SIPRegistrarTimeoutField setIntValue:[[user settingForKey:MGMSIPAccountRegisterTimeout] intValue]]; else @@ -368,17 +368,17 @@ NSString * const MGMLogout = @"Logout"; #if MGMSIPENABLED MGMUser *user = [MGMUser userWithID:[[MGMUser users] objectAtIndex:[usersTable selectedRow]]]; [user setSetting:[SIPFullNameField stringValue] forKey:MGMSIPAccountFullName]; - if ([[SIPDomainField stringValue] isEqual:@""]) { - [[SIPRegistrarField cell] setPlaceholderString:@""]; - [user setSetting:@"" forKey:MGMSIPAccountDomain]; + if ([[SIPRegistrarField stringValue] isEqual:@""]) { + [[SIPDomainField cell] setPlaceholderString:@"Usually *"]; + [user setSetting:@"" forKey:MGMSIPAccountRegistrar]; } else { - [[SIPRegistrarField cell] setPlaceholderString:[SIPDomainField stringValue]]; - [user setSetting:[SIPDomainField stringValue] forKey:MGMSIPAccountDomain]; + [[SIPDomainField cell] setPlaceholderString:[SIPRegistrarField stringValue]]; + [user setSetting:[SIPRegistrarField stringValue] forKey:MGMSIPAccountRegistrar]; } if ([[SIPRegistrarField stringValue] isEqual:@""] && [[SIPDomainField stringValue] isEqual:@""]) NSBeep(); else - [user setSetting:[SIPRegistrarField stringValue] forKey:MGMSIPAccountRegistrar]; + [user setSetting:[SIPDomainField stringValue] forKey:MGMSIPAccountDomain]; if ([[SIPUserNameField stringValue] isEqual:@""] || [[SIPPasswordField stringValue] isEqual:@""]) { NSBeep(); if ([user settingForKey:MGMSIPAccountUserName]!=nil) { @@ -396,7 +396,7 @@ NSString * const MGMLogout = @"Logout"; [user setSetting:[SIPProxyHostField stringValue] forKey:MGMSIPAccountProxy]; [user setSetting:[NSNumber numberWithInt:[SIPProxyPortField intValue]] forKey:MGMSIPAccountProxyPort]; [user setSetting:[SIPSIPAddressField stringValue] forKey:MGMSIPAccountSIPAddress]; - [[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountDomain]]]; + [[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountRegistrar]]]; [user setSetting:[NSNumber numberWithInt:[SIPRegistrarTimeoutField intValue]] forKey:MGMSIPAccountRegisterTimeout]; [user setSetting:[NSNumber numberWithInt:[SIPTransportPopUp indexOfSelectedItem]] forKey:MGMSIPAccountTransport]; [user setSetting:[NSNumber numberWithInt:[SIPToneTypePopUp indexOfSelectedItem]] forKey:MGMSIPAccountDTMFToneType]; diff --git a/Classes/VoiceMac/SMS/MGMSMSMessageView.m b/Classes/VoiceMac/SMS/MGMSMSMessageView.m index 0991249..0ebce0b 100644 --- a/Classes/VoiceMac/SMS/MGMSMSMessageView.m +++ b/Classes/VoiceMac/SMS/MGMSMSMessageView.m @@ -97,11 +97,13 @@ } - (void)sendNotifications { - for (unsigned int i=[messages count]-1; i>=0; i--) { + for (unsigned int i=[messages count]-1;; i--) { if (![[[messages objectAtIndex:i] objectForKey:MGMIYou] boolValue]) { [GrowlApplicationBridge notifyWithTitle:[NSString stringWithFormat:@"SMS from %@", [messageInfo objectForKey:MGMTInName]] description:[[[messages objectAtIndex:i] objectForKey:MGMIText] flattenHTML] notificationName:@"SMS" iconData:[[instance contacts] photoDataForNumber:[messageInfo objectForKey:MGMIPhoneNumber]] priority:0 isSticky:NO clickContext:nil]; break; } + if (i==0) + break; } } diff --git a/Classes/VoiceMac/Views/MGMViewCell.m b/Classes/VoiceMac/Views/MGMViewCell.m index 655cef3..a3735df 100644 --- a/Classes/VoiceMac/Views/MGMViewCell.m +++ b/Classes/VoiceMac/Views/MGMViewCell.m @@ -29,7 +29,7 @@ } - (void)addSubview:(NSView *)theView { - subview = theView; + subview = (NSView *)theView; } - (NSView *)view { return subview; diff --git a/Classes/VoiceMob/MGMAccountController.h b/Classes/VoiceMob/MGMAccountController.h index 31c9969..e43d3d3 100644 --- a/Classes/VoiceMob/MGMAccountController.h +++ b/Classes/VoiceMob/MGMAccountController.h @@ -3,12 +3,12 @@ // VoiceMob // // Created by Mr. Gecko on 9/27/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // -#import +#import -@class MGMAccountController, MGMController, MGMAccounts, MGMUser; +@class MGMAccountController, MGMController, MGMAccounts, MGMSettings, MGMSound, MGMUser, MGMInstance; @protocol MGMAccountProtocol - (MGMAccountController *)accountController; @@ -18,28 +18,40 @@ - (UIView *)view; - (void)releaseView; -@end +- (void)showOptionsForNumber:(NSString *)theNumber; +@end @interface MGMAccountController : NSObject { MGMController *controller; NSMutableArray *contactsControllers; int currentContactsController; + NSMutableDictionary *badgeValues; MGMAccounts *accounts; + MGMSettings *settings; + MGMSound *soundPlayer; IBOutlet UIView *view; IBOutlet UIToolbar *toolbar; NSArray *accountsItems; NSArray *accountItems; - IBOutlet UILabel *titleField; + NSArray *settingsItems; + IBOutlet UIButton *phoneButton; IBOutlet UIView *contentView; + BOOL shouldRefreshSounds; } - (id)initWithController:(MGMController *)theController; - (void)registerDefaults; - (MGMController *)controller; +- (NSArray *)contactsControllers; +- (id)contactControllerWithUser:(MGMUser *)theUser; +- (NSDictionary *)badgeValues; +- (int)badgeValueForInstance:(MGMInstance *)theInstance; +- (void)setBadge:(int)theBadge forInstance:(MGMInstance *)theInstance; - (UIView *)view; +- (void)releaseView; - (UIToolbar *)toolbar; - (void)setItems:(NSArray *)theItems animated:(BOOL)isAnimated; - (NSArray *)accountsItems; @@ -50,6 +62,12 @@ - (IBAction)showAccounts:(id)sender; - (IBAction)showSettings:(id)sender; +- (NSString *)soundTitleForKey:(NSString *)theKey; +- (int)soundSectionForKey:(NSString *)theKey; +- (int)soundSettingRowForKey:(NSString *)theKey; +- (NSDictionary *)soundMenuWithSounds:(NSDictionary *)theSounds key:(NSString *)key; - (void)showUser:(MGMUser *)theUser; + +- (IBAction)phone:(id)sender; @end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMAccountController.m b/Classes/VoiceMob/MGMAccountController.m index 0469ed0..01ebd7a 100644 --- a/Classes/VoiceMob/MGMAccountController.m +++ b/Classes/VoiceMob/MGMAccountController.m @@ -3,85 +3,75 @@ // VoiceMob // // Created by Mr. Gecko on 9/27/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMAccountController.h" #import "MGMController.h" #import "MGMAccounts.h" +#import "MGMGContactUser.h" #import "MGMVoiceUser.h" #import "MGMSIPUser.h" +#import "MGMPhotoSelector.h" #import "MGMVMAddons.h" #import "MGMAccountSetup.h" +#import "MGMConverter.h" #import #import NSString * const MGMLastContactsController = @"MGMLastContactsController"; NSString * const MGMAccountsTitle = @"Accounts"; +NSString * const MGMBackTitle = @"Back"; +NSString * const MGMLogInOut = @"MGMLogInOut"; +NSString * const MGMLogin = @"Login"; +NSString * const MGMLogout = @"Logout"; @implementation MGMAccountController - (id)initWithController:(MGMController *)theController { - if (self = [super init]) { - if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"AccountController"] owner:self options:nil]) { - NSLog(@"Unable to load Account Controller"); - [self release]; - self = nil; - } else { - controller = theController; - - [self registerDefaults]; - - contactsControllers = [NSMutableArray new]; - NSArray *lastUsers = [MGMUser lastUsers]; - for (int i=0; i<[lastUsers count]; i++) { - MGMUser *user = [MGMUser userWithID:[lastUsers objectAtIndex:i]]; - if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) { - [contactsControllers addObject:[MGMVoiceUser voiceUser:user accountController:self]]; - } + if ((self = [super init])) { + controller = theController; + + [self registerDefaults]; + + contactsControllers = [NSMutableArray new]; + NSArray *lastUsers = [MGMUser lastUsers]; + for (int i=0; i<[lastUsers count]; i++) { + MGMUser *user = [MGMUser userWithID:[lastUsers objectAtIndex:i]]; + if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) { + [contactsControllers addObject:[MGMVoiceUser voiceUser:user accountController:self]]; + } #if MGMSIPENABLED - else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) { - if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start]; - [contactsControllers addObject:[MGMSIPUser SIPUser:user accountController:self]]; - } + else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) { + if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start]; + [contactsControllers addObject:[MGMSIPUser SIPUser:user accountController:self]]; + } #endif - } - currentContactsController = [[NSUserDefaults standardUserDefaults] integerForKey:MGMLastContactsController]; - - accounts = [[MGMAccounts alloc] initWithAccountController:self]; - accountsItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addAccount:)] autorelease], nil] retain]; - accountItems = [[toolbar items] copy]; - if ([contactsControllers count]==0 || currentContactsController==-1) { - [self setItems:accountsItems animated:NO]; - [contentView addSubview:[accounts view]]; - [self setTitle:MGMAccountsTitle]; - } else { - id contactsController = [contactsControllers objectAtIndex:currentContactsController]; - [self setItems:accountItems animated:NO]; - [contentView addSubview:[contactsController view]]; - - [self setTitle:[contactsController title]]; - } - - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter addObserver:self selector:@selector(userStarted:) name:MGMUserStartNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(userDone:) name:MGMUserDoneNotification object:nil]; } + currentContactsController = [[NSUserDefaults standardUserDefaults] integerForKey:MGMLastContactsController]; + badgeValues = [NSMutableDictionary new]; + + accounts = [[MGMAccounts alloc] initWithAccountController:self]; + shouldRefreshSounds = NO; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self selector:@selector(userStarted:) name:MGMUserStartNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(userDone:) name:MGMUserDoneNotification object:nil]; } return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [[NSNotificationCenter defaultCenter] removeObserver:self]; - if (contactsControllers!=nil) - [contactsControllers release]; - if (accounts!=nil) - [accounts release]; - if (view!=nil) - [view release]; - if (accountsItems!=nil) - [accountsItems release]; - if (accountItems!=nil) - [accountItems release]; + [self releaseView]; + [contactsControllers release]; + [badgeValues release]; + [accounts release]; + [accountsItems release]; + [accountItems release]; + [settingsItems release]; [super dealloc]; } @@ -94,9 +84,88 @@ NSString * const MGMAccountsTitle = @"Accounts"; - (MGMController *)controller { return controller; } +- (NSArray *)contactsControllers { + return contactsControllers; +} +- (id)contactControllerWithUser:(MGMUser *)theUser { + for (int i=0; i<[contactsControllers count]; i++) { + if ([[[contactsControllers objectAtIndex:i] user] isEqual:theUser]) + return [contactsControllers objectAtIndex:i]; + } + return nil; +} +- (NSDictionary *)badgeValues { + return badgeValues; +} +- (int)badgeValueForInstance:(MGMInstance *)theInstance { + return [[badgeValues objectForKey:[theInstance userNumber]] intValue]; +} +- (void)setBadge:(int)theBadge forInstance:(MGMInstance *)theInstance { + if (![theInstance isLoggedIn]) return; + if (theBadge==0) + [badgeValues removeObjectForKey:[theInstance userNumber]]; + else + [badgeValues setObject:[NSNumber numberWithInt:theBadge] forKey:[theInstance userNumber]]; + NSArray *valueKeys = [badgeValues allKeys]; + int value = 0; + for (int i=0; i<[valueKeys count]; i++) + value += [[badgeValues objectForKey:[valueKeys objectAtIndex:i]] intValue]; + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:value]; + if (currentContactsController==-1) + [(UITableView *)[accounts view] reloadData]; +} - (UIView *)view { + if (view==nil) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"AccountController"] owner:self options:nil]) { + NSLog(@"Unable to load Account Controller"); + } else { + accountsItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(showSettings:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addAccount:)] autorelease], nil] retain]; + accountItems = [[toolbar items] copy]; + settingsItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:MGMBackTitle style:UIBarButtonItemStyleBordered target:self action:@selector(goBack:)] autorelease], nil] retain]; + + if ([contactsControllers count]==0 || currentContactsController==-1) { + [self setItems:accountsItems animated:NO]; + CGRect viewFrame = [[accounts view] frame]; + viewFrame.size = [contentView frame].size; + [[accounts view] setFrame:viewFrame]; + [contentView addSubview:[accounts view]]; + [self setTitle:MGMAccountsTitle]; + } else { + id contactsController = [contactsControllers objectAtIndex:currentContactsController]; + [self setItems:accountItems animated:NO]; + CGRect viewFrame = [[contactsController view] frame]; + viewFrame.size = [contentView frame].size; + [[contactsController view] setFrame:viewFrame]; + [contentView addSubview:[contactsController view]]; + + [self setTitle:[contactsController title]]; + } + } + } return view; } +- (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + if (currentContactsController!=-1) + [[contactsControllers objectAtIndex:currentContactsController] releaseView]; + [accounts releaseView]; + [view release]; + view = nil; + [toolbar release]; + toolbar = nil; + [phoneButton release]; + phoneButton = nil; + [contentView release]; + contentView = nil; + [accountsItems release]; + accountsItems = nil; + [accountItems release]; + accountItems = nil; + [settingsItems release]; + settingsItems = nil; +} - (UIToolbar *)toolbar { return toolbar; } @@ -115,7 +184,7 @@ NSString * const MGMAccountsTitle = @"Accounts"; return ([contactsControllers indexOfObject:theUser]==currentContactsController); } - (void)setTitle:(NSString *)theTitle { - [titleField setText:theTitle]; + [phoneButton setTitle:theTitle forState:UIControlStateNormal]; } - (IBAction)addAccount:(id)sender { @@ -123,12 +192,17 @@ NSString * const MGMAccountsTitle = @"Accounts"; } - (IBAction)showAccounts:(id)sender { - id contactsController = [contactsControllers objectAtIndex:currentContactsController]; - currentContactsController = -1; - [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; + id contactsController = nil; + if (currentContactsController!=-1) { + contactsController = [contactsControllers objectAtIndex:currentContactsController]; + currentContactsController = -1; + [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; + } [self setItems:accountsItems animated:YES]; [self setTitle:MGMAccountsTitle]; + CGRect outViewFrame = [[contactsController view] frame]; CGRect inViewFrame = [[accounts view] frame]; + inViewFrame.size = outViewFrame.size; inViewFrame.origin.x = -inViewFrame.size.width; [[accounts view] setFrame:inViewFrame]; [contentView addSubview:[accounts view]]; @@ -137,14 +211,560 @@ NSString * const MGMAccountsTitle = @"Accounts"; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(contactsControllerAnimationDidStop:finished:contactsController:)]; - [[accounts view] setFrame:[[contactsController view] frame]]; - CGRect outViewFrame = [[contactsController view] frame]; + [[accounts view] setFrame:outViewFrame]; outViewFrame.origin.x = +outViewFrame.size.width; [[contactsController view] setFrame:outViewFrame]; [UIView commitAnimations]; } - (IBAction)showSettings:(id)sender { + settings = [[MGMSettings alloc] initWithDisplayView:contentView delegate:self]; + if (currentContactsController==-1) { + NSMutableDictionary *settingsDic = [NSPropertyListSerialization propertyListFromData:[NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"settings.plist"]] mutabilityOption:NSPropertyListMutableContainersAndLeaves format:nil errorDescription:nil]; + NSMutableArray *allSettings = [[[settingsDic objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey]; + + NSMutableArray *soundSections = [[[allSettings objectAtIndex:0] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey]; + NSDictionary *sounds = [[controller themeManager] sounds]; + NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil]; + for (int i=0; i<[rebuild count]; i++) { + [[[soundSections objectAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] objectForKey:MGMSObjectsKey] replaceObjectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]] withObject:[self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]]]; + } + + NSMutableArray *themesArray = [[[[[allSettings objectAtIndex:1] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey]; + NSMutableArray *themesValue = [NSMutableArray array]; + NSArray *themes = [[controller themeManager] themes]; + for (int i=0; i<[themes count]; i++) { + [themesValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[themes objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [[[themes objectAtIndex:i] objectForKey:MGMTThemePath] lastPathComponent], MGMSValueKey, nil]]; + } + [[themesArray objectAtIndex:0] setObject:themesValue forKey:MGMSValueKey]; + NSDictionary *theme = [[controller themeManager] theme]; + [[themesArray objectAtIndex:2] setObject:[theme objectForKey:MGMTAuthor] forKey:MGMSValueKey]; + [[themesArray objectAtIndex:2] setObject:[theme objectForKey:MGMTSite] forKey:MGMSExtraKey]; + NSArray *fonts = [UIFont familyNames]; + fonts = [fonts sortedArrayUsingSelector:@selector(compare:)]; + NSMutableArray *fontsValue = [NSMutableArray array]; + for (int i=0; i<[fonts count]; i++) { + NSString *font = [fonts objectAtIndex:i]; + NSArray *fontNames = [UIFont fontNamesForFamilyName:font]; + for (int i=0; i<[fontNames count]; i++) { + NSString *fontName = [fontNames objectAtIndex:i]; + NSArray *fontComponents = [fontName componentsSeparatedByString:@"-"]; + NSString *name = font; + if ([fontComponents count]>=2) + name = [NSString stringWithFormat:@"%@ - %@", name, [fontComponents objectAtIndex:1]]; + [fontsValue addObject:[NSDictionary dictionaryWithObjectsAndKeys:name, MGMSTitleKey, fontName, MGMSValueKey, nil]]; + } + } + [[themesArray objectAtIndex:6] setObject:fontsValue forKey:MGMSValueKey]; + NSArray *variants = [theme objectForKey:MGMTVariants]; + NSMutableArray *varientsValue = [NSMutableArray array]; + for (int i=0; i<[variants count]; i++) { + [varientsValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[variants objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [NSNumber numberWithInt:i], MGMSValueKey, nil]]; + } + [[themesArray objectAtIndex:1] setObject:varientsValue forKey:MGMSValueKey]; + + NSMutableArray *sipSections = [[[allSettings objectAtIndex:2] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey]; + NSArray *codecs = [[[MGMSIP sharedSIP] codecs] allKeys]; + codecs = [codecs sortedArrayUsingSelector:@selector(compare:)]; + NSMutableArray *codecsValue = [NSMutableArray array]; + for (int i=0; i<[codecs count]; i++) { + NSString *codec = [codecs objectAtIndex:i]; + [codecsValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:codec, MGMSTitleKey, codec, MGMSValueKey, nil]]; + } + [[[[sipSections objectAtIndex:4] objectForKey:MGMSObjectsKey] objectAtIndex:2] setObject:codecsValue forKey:MGMSValueKey]; + + if (![[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom]) + [[[[[[[[[sipSections objectAtIndex:1] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey] objectAtIndex:1] setObject:[NSNumber numberWithInt:MGMSOCheckMark] forKey:MGMSOptionsKey]; + + [settings setSections:[MGMSettingSections sectionsWithDictionary:settingsDic target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]]; + } else { + NSString *settingsFile = nil; + id account = [contactsControllers objectAtIndex:currentContactsController]; + if ([account isKindOfClass:[MGMVoiceUser class]]) + settingsFile = @"voicesettings.plist"; + else if ([account isKindOfClass:[MGMSIPUser class]]) + settingsFile = @"sipsettings.plist"; + else if ([account isKindOfClass:[MGMGContactUser class]]) + settingsFile = @"gcontactsettings.plist"; + NSMutableDictionary *settingsDic = [NSPropertyListSerialization propertyListFromData:[NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:settingsFile]] mutabilityOption:NSPropertyListMutableContainersAndLeaves format:nil errorDescription:nil]; + + NSMutableArray *objects = [settingsDic objectForKey:MGMSObjectsKey]; + for (int i=0; i<[objects count]; i++) { + if ([[[[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSKeyKey] isEqual:MGMSContactsSourceKey]) { + NSMutableDictionary *contacts = [[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0]; + [contacts removeObjectForKey:MGMSKeyKey]; + NSMutableDictionary *extra = [NSMutableDictionary dictionaryWithObject:MGMSContactsSourceKey forKey:MGMSKeyKey]; + if ([[[account user] settingForKey:MGMSContactsSourceKey] isEqual:NSStringFromClass([MGMAddressBook class])]) + [extra setObject:[[account user] settingForKey:MGMSContactsSourceKey] forKey:MGMSValueKey]; + else + [extra setObject:[[account user] settingForKey:MGMCGoogleContactsUser] forKey:MGMSValueKey]; + [contacts setValue:extra forKey:MGMSExtraKey]; + + NSMutableArray *contactSources = [NSMutableArray array]; + [contactSources addObject:[NSDictionary dictionaryWithObjectsAndKeys:NSStringFromClass([MGMAddressBook class]), MGMSValueKey, @"Address Book", MGMSTitleKey, nil]]; + NSArray *users = [MGMUser users]; + for (int i=0; i<[users count]; i++) { + MGMUser *gcUser = [MGMUser userWithID:[users objectAtIndex:i]]; + if ([[gcUser settingForKey:MGMSAccountType] isEqual:MGMSGoogleContacts]) { + NSMutableDictionary *contactSource = [NSMutableDictionary dictionary]; + [contactSource setObject:[gcUser settingForKey:MGMUserName] forKey:MGMSTitleKey]; + [contactSource setObject:[gcUser settingForKey:MGMUserID] forKey:MGMSValueKey]; + [contactSources addObject:contactSource]; + } + } + [contacts setObject:contactSources forKey:MGMSValueKey]; + } else if ([[[[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSKeyKey] isEqual:MGMLogInOut]) { + NSMutableDictionary *logInOut = [[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0]; + if ([[account user] isStarted]) { + [logInOut setObject:MGMLogout forKey:MGMSTitleKey]; + } else { + [logInOut setObject:MGMLogin forKey:MGMSTitleKey]; + } + } + } + + [settings setSections:[MGMSettingSections sectionsWithDictionary:settingsDic target:[account user] getter:@selector(settingForKey:) setter:@selector(setSetting:forKey:)]]; + } + [self setItems:nil animated:YES]; + [self setTitle:[settings title]]; + CGRect outViewFrame = [((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) frame]; + CGRect inViewFrame = [[settings view] frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = +inViewFrame.size.width; + [[settings view] setFrame:inViewFrame]; + [contentView addSubview:[settings view]]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(showSettingsAnimationDidStop:finished:context:)]; + [[settings view] setFrame:outViewFrame]; + outViewFrame.origin.x = -outViewFrame.size.width; + [((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (NSString *)soundTitleForKey:(NSString *)theKey { + if ([theKey isEqual:MGMTSSMSMessage]) + return @"SMS Message"; + if ([theKey isEqual:MGMTSVoicemail]) + return @"Voicemail"; + if ([theKey isEqual:MGMTSSIPRingtone]) + return @"Ringtone"; + if ([theKey isEqual:MGMTSSIPHoldMusic]) + return @"Hold Music"; + if ([theKey isEqual:MGMTSSIPConnected]) + return @"Connected"; + if ([theKey isEqual:MGMTSSIPDisconnected]) + return @"Disconnected"; + if ([theKey isEqual:MGMTSSIPSound1]) + return @"Sound 1"; + if ([theKey isEqual:MGMTSSIPSound2]) + return @"Sound 2"; + if ([theKey isEqual:MGMTSSIPSound3]) + return @"Sound 3"; + if ([theKey isEqual:MGMTSSIPSound4]) + return @"Sound 4"; + if ([theKey isEqual:MGMTSSIPSound5]) + return @"Sound 5"; + return nil; +} +- (int)soundSectionForKey:(NSString *)theKey { + if ([theKey isEqual:MGMTSSMSMessage] || [theKey isEqual:MGMTSVoicemail]) + return 0; + if ([theKey isEqual:MGMTSSIPRingtone] || [theKey isEqual:MGMTSSIPHoldMusic]) + return 1; + if ([theKey isEqual:MGMTSSIPConnected] || [theKey isEqual:MGMTSSIPDisconnected]) + return 2; + if ([theKey isEqual:MGMTSSIPSound1] || [theKey isEqual:MGMTSSIPSound2] || [theKey isEqual:MGMTSSIPSound3] || [theKey isEqual:MGMTSSIPSound4] || [theKey isEqual:MGMTSSIPSound5]) + return 3; + return 0; +} +- (int)soundSettingRowForKey:(NSString *)theKey { + if ([theKey isEqual:MGMTSSMSMessage]) + return 0; + if ([theKey isEqual:MGMTSVoicemail]) + return 1; + if ([theKey isEqual:MGMTSSIPRingtone]) + return 0; + if ([theKey isEqual:MGMTSSIPHoldMusic]) + return 1; + if ([theKey isEqual:MGMTSSIPConnected]) + return 0; + if ([theKey isEqual:MGMTSSIPDisconnected]) + return 1; + if ([theKey isEqual:MGMTSSIPSound1]) + return 0; + if ([theKey isEqual:MGMTSSIPSound2]) + return 1; + if ([theKey isEqual:MGMTSSIPSound3]) + return 2; + if ([theKey isEqual:MGMTSSIPSound4]) + return 3; + if ([theKey isEqual:MGMTSSIPSound5]) + return 4; + return 0; +} +- (NSDictionary *)soundMenuWithSounds:(NSDictionary *)theSounds key:(NSString *)key { + NSMutableDictionary *mainMenu = [NSMutableDictionary dictionary]; + [mainMenu setObject:[self soundTitleForKey:key] forKey:MGMSTitleKey]; + [mainMenu setObject:[NSNumber numberWithInt:MGMSTitleType] forKey:MGMSTypeKey]; + NSString *soundPath = [[controller themeManager] currentSoundPath:key]; + if ([soundPath isEqual:MGMTNoSound]) + [mainMenu setObject:@"No Sound" forKey:MGMSValueKey]; + NSArray *soundKeys = [theSounds allKeys]; + NSMutableArray *soundsArray = [NSMutableArray array]; + for (int i=0; i<[soundKeys count]; i++) { + NSArray *sounds = [theSounds objectForKey:[soundKeys objectAtIndex:i]]; + NSMutableDictionary *sound = [NSMutableDictionary dictionary]; + NSMutableDictionary *soundExtra = [NSMutableDictionary dictionary]; + [sound setObject:[soundKeys objectAtIndex:i] forKey:MGMSTitleKey]; + [soundExtra setObject:[[[sounds objectAtIndex:0] objectForKey:MGMTSPath] stringByDeletingLastPathComponent] forKey:MGMTSPath]; + [sound setObject:[NSNumber numberWithInt:MGMSMultiType] forKey:MGMSTypeKey]; + BOOL isCurrent = [[soundPath stringByDeletingLastPathComponent] isEqual:[soundExtra objectForKey:MGMTSPath]]; + if (isCurrent) + [sound setObject:[MGMTSName stringByAppendingString:key] forKey:MGMSKeyKey]; + else + [soundExtra setObject:[MGMTSName stringByAppendingString:key] forKey:MGMSKeyKey]; + [sound setObject:soundExtra forKey:MGMSExtraKey]; + if ([[soundKeys objectAtIndex:i] isEqual:@"Unknown"] || [[soundKeys objectAtIndex:i] isEqual:@"User Sounds"]) + [sound setObject:[NSNumber numberWithInt:8] forKey:MGMSOptionsKey]; + else if (![[soundKeys objectAtIndex:i] isEqual:@"System Sounds"] && ![[soundKeys objectAtIndex:i] isEqual:@"VoiceMob"]) + [sound setObject:[NSNumber numberWithInt:4] forKey:MGMSOptionsKey]; + NSMutableArray *soundArray = [NSMutableArray array]; + for (int s=0; s<[sounds count]; s++) { + if (isCurrent && [[[sounds objectAtIndex:s] objectForKey:MGMTSPath] isEqual:soundPath]) + [mainMenu setObject:[[sounds objectAtIndex:s] objectForKey:MGMTSName] forKey:MGMSValueKey]; + NSMutableDictionary *soundDic = [NSMutableDictionary dictionary]; + [soundDic setObject:[[sounds objectAtIndex:s] objectForKey:MGMTSName] forKey:MGMSTitleKey]; + [soundDic setObject:[[[sounds objectAtIndex:s] objectForKey:MGMTSPath] lastPathComponent] forKey:MGMSValueKey]; + [soundArray addObject:soundDic]; + } + [sound setObject:soundArray forKey:MGMSValueKey]; + [soundsArray addObject:sound]; + } + NSDictionary *soundDicionary = [NSDictionary dictionaryWithObject:soundsArray forKey:MGMSObjectsKey]; + NSMutableDictionary *noSoundDic = [NSMutableDictionary dictionary]; + [noSoundDic setObject:@"No Sound" forKey:MGMSTitleKey]; + [noSoundDic setObject:MGMTNoSound forKey:MGMSExtraKey]; + [noSoundDic setObject:[MGMTSName stringByAppendingString:key] forKey:MGMSKeyKey]; + [noSoundDic setObject:[NSNumber numberWithInt:MGMSNullType] forKey:MGMSTypeKey]; + if ([soundPath isEqual:MGMTNoSound]) + [noSoundDic setObject:[NSNumber numberWithInt:MGMSOCheckMark] forKey:MGMSOptionsKey]; + NSDictionary *noSoundDicDicionary = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:noSoundDic] forKey:MGMSObjectsKey]; + NSArray *soundObject = [NSArray arrayWithObjects:soundDicionary, noSoundDicDicionary, nil]; + [mainMenu setObject:[NSDictionary dictionaryWithObjectsAndKeys:[self soundTitleForKey:key], MGMSTitleKey, soundObject, MGMSObjectsKey, nil] forKey:MGMSObjectsKey]; + return mainMenu; +} +- (IBAction)goBack:(id)sender { + [soundPlayer stop]; + [soundPlayer release]; + soundPlayer = nil; + if (![settings goBack]) { + BOOL account = (currentContactsController!=-1 && [(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]); + if (!account) + [[accountsItems objectAtIndex:0] setEnabled:NO]; + else + [[accountItems objectAtIndex:0] setEnabled:NO]; + [self setItems:(!account ? accountsItems : accountItems) animated:YES]; + if (!account) + [self setTitle:MGMAccountsTitle]; + else + [self setTitle:[[contactsControllers objectAtIndex:currentContactsController] title]]; + CGRect outViewFrame = [[settings view] frame]; + CGRect inViewFrame = [(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = -inViewFrame.size.width; + [(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) setFrame:inViewFrame]; + [contentView addSubview:(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view])]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(hideSettingsAnimationDidStop:finished:context:)]; + [(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) setFrame:outViewFrame]; + outViewFrame.origin.x = +outViewFrame.size.width; + [[settings view] setFrame:outViewFrame]; + [UIView commitAnimations]; + } +} +- (void)settingsWillTransition { + [[settingsItems objectAtIndex:0] setEnabled:NO]; +} +- (void)settingsDidTransition { + if ([settings parentTitle]!=nil) + [[settingsItems objectAtIndex:0] setTitle:[settings parentTitle]]; + else + [[settingsItems objectAtIndex:0] setTitle:MGMBackTitle]; + [[settingsItems objectAtIndex:0] setEnabled:YES]; + if (shouldRefreshSounds) { + shouldRefreshSounds = NO; + NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil]; + MGMSettingSections *sections = [[settings sections] parent]; + NSDictionary *sounds = [[controller themeManager] sounds]; + for (int i=0; i<[rebuild count]; i++) { + NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]]; + MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]; + if ([settings sections]==[(MGMSettings *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] sections]) { + [(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setValue:[setting objectForKey:MGMSValueKey]]; + [[settings sections] setSections:[settingSections sections]]; + } else { + [(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections]; + } + } + [(UITableView *)[settings view] reloadData]; + } + [self setTitle:[settings title]]; +} +- (void)setting:(MGMSetting *)theSetting changedToValue:(id)theValue forKey:(NSString *)theKey { + if ([theKey isEqual:MGMTCurrentThemeName] || [theKey isEqual:@"MGMTDownloader"]) { + if ([theKey isEqual:MGMTCurrentThemeName]) { + int index = 0; + for (int i=0; i<[[theSetting value] count]; i++) { + if ([[[[theSetting value] objectAtIndex:i] objectForKey:MGMSValueKey] isEqual:theValue]) { + index = i; + break; + } + } + [[controller themeManager] setTheme:[[[controller themeManager] themes] objectAtIndex:index]]; + } + NSArray *themesArray = [[[settings sections] sectionAtIndex:0] settings]; + NSMutableArray *themesValue = [NSMutableArray array]; + NSArray *themes = [[controller themeManager] themes]; + for (int i=0; i<[themes count]; i++) { + [themesValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[themes objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [[[themes objectAtIndex:i] objectForKey:MGMTThemePath] lastPathComponent], MGMSValueKey, nil]]; + } + [(MGMSetting *)[themesArray objectAtIndex:0] setValue:themesValue]; + NSDictionary *theme = [[controller themeManager] theme]; + [(MGMSetting *)[themesArray objectAtIndex:2] setValue:[theme objectForKey:MGMTAuthor]]; + NSArray *variants = [theme objectForKey:MGMTVariants]; + NSMutableArray *varientsValue = [NSMutableArray array]; + for (int i=0; i<[variants count]; i++) { + [varientsValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[variants objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [NSNumber numberWithInt:i], MGMSValueKey, nil]]; + } + [(MGMSetting *)[themesArray objectAtIndex:1] setValue:varientsValue]; + } else if ([theKey isEqual:MGMTCurrentThemeName] || [theKey isEqual:@"MGMSDownloader"]) { + NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil]; + NSDictionary *sounds = [[controller themeManager] sounds]; + for (int i=0; i<[rebuild count]; i++) { + NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]]; + MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]; + [(MGMSetting *)[[[[settings sections] sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections]; + } + } else if ([theKey hasPrefix:MGMTSName] || ([[theSetting extra] isKindOfClass:[NSDictionary class]] && [[[theSetting extra] objectForKey:MGMSKeyKey] hasPrefix:MGMTSName])) { + NSString *key = nil; + if (theKey!=nil) + key = theKey; + else + key = [[theSetting extra] objectForKey:MGMSKeyKey]; + NSString *path = [[[theSetting extra] objectForKey:MGMTSPath] stringByAppendingPathComponent:theValue]; + NSString *soundName = [key substringFromIndex:[MGMTSName length]]; + [[controller themeManager] setSound:soundName withPath:path]; + [soundPlayer stop]; + [soundPlayer release]; + soundPlayer = nil; + soundPlayer = [[controller themeManager] playSound:soundName]; + [soundPlayer setDelegate:self]; +#if MGMSIPENABLED + if ([soundName isEqual:MGMTSSIPHoldMusic] || [soundName isEqual:MGMTSSIPSound1] || [soundName isEqual:MGMTSSIPSound2] || [soundName isEqual:MGMTSSIPSound3] || [soundName isEqual:MGMTSSIPSound4] || [soundName isEqual:MGMTSSIPSound5]) + [[MGMConverter alloc] initWithSound:soundName file:path]; +#endif + NSDictionary *soundDic = [self soundMenuWithSounds:[[controller themeManager] sounds] key:soundName]; + [(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[soundDic objectForKey:MGMSValueKey]]; + MGMSettingSections *sections = [MGMSettingSections sectionsWithDictionary:[soundDic objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]; + [[settings sections] setSections:[sections sections]]; + } else if ([[theSetting extra] isKindOfClass:[NSDictionary class]] && [[[theSetting extra] objectForKey:MGMSKeyKey] isEqual:MGMSContactsSourceKey]) { + if ([theValue isEqual:NSStringFromClass([MGMAddressBook class])]) { + NSString *key = MGMSContactsSourceKey; + NSMethodSignature *signature = [[theSetting target] methodSignatureForSelector:[theSetting action]]; + if (signature!=nil) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:[theSetting action]]; + [invocation setArgument:&theValue atIndex:2]; + [invocation setArgument:&key atIndex:3]; + [invocation invokeWithTarget:[theSetting target]]; + } + } else { + NSString *key = MGMSContactsSourceKey; + NSString *value = NSStringFromClass([MGMGoogleContacts class]); + NSMethodSignature *signature = [[theSetting target] methodSignatureForSelector:[theSetting action]]; + if (signature!=nil) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:[theSetting action]]; + [invocation setArgument:&value atIndex:2]; + [invocation setArgument:&key atIndex:3]; + [invocation invokeWithTarget:[theSetting target]]; + } + key = MGMCGoogleContactsUser; + signature = [[theSetting target] methodSignatureForSelector:[theSetting action]]; + if (signature!=nil) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:[theSetting action]]; + [invocation setArgument:&theValue atIndex:2]; + [invocation setArgument:&key atIndex:3]; + [invocation invokeWithTarget:[theSetting target]]; + } + } + } else if ([[theSetting extra] isKindOfClass:[NSDictionary class]] && [[[theSetting extra] objectForKey:MGMSExtraKey] isEqual:@"MGMCustom"]) { + if ([[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom]) + [[[[[settings sections] sectionAtIndex:0] settings] objectAtIndex:1] setOptions:0]; + else + [[[[[settings sections] sectionAtIndex:0] settings] objectAtIndex:1] setOptions:MGMSOCheckMark]; + } +} +- (void)soundDidFinishPlaying:(MGMSound *)theSound { + [soundPlayer release]; + soundPlayer = nil; +} +- (void)didSelectSetting:(MGMSetting *)theSetting { + if ([[theSetting key] isEqual:@"MGMTAuthor"]) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[theSetting extra]]]; + } else if ([[theSetting extra] isEqual:MGMTNoSound]) { + NSString *soundName = [[theSetting key] substringFromIndex:[MGMTSName length]]; + [[controller themeManager] setSound:soundName withPath:MGMTNoSound]; + NSDictionary *soundDic = [self soundMenuWithSounds:[[controller themeManager] sounds] key:soundName]; + [(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[soundDic objectForKey:MGMSValueKey]]; + MGMSettingSections *sections = [MGMSettingSections sectionsWithDictionary:[soundDic objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]; + [[settings sections] setSections:[sections sections]]; + [self goBack:self]; + } else if ([[theSetting extra] isEqual:@"MGMDefault"]) { + [theSetting setOptions:MGMSOCheckMark]; + [[NSUserDefaults standardUserDefaults] setObject:MGMSIPBDefault forKey:MGMSIPBackground]; + [[NSFileManager defaultManager] removeItemAtPath:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground]]; + [self goBack:self]; + } else if ([[theSetting key] isEqual:MGMLogInOut]) { + id account = [[[contactsControllers objectAtIndex:currentContactsController] retain] autorelease]; + MGMUser *user = [account user]; + [contactsControllers removeObjectAtIndex:currentContactsController]; + if ([user isStarted]) { + [user done]; + [theSetting setTitle:MGMLogin]; + id contactsController = nil; + if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) { + contactsController = [MGMVoiceUser voiceUser:user accountController:self]; + [contactsControllers addObject:contactsController]; + } else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleContacts]) { + contactsController = [MGMGContactUser gContactUser:user accountController:self]; + [contactsControllers addObject:contactsController]; + } +#if MGMSIPENABLED + else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) { + if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start]; + contactsController = [MGMSIPUser SIPUser:user accountController:self]; + [contactsControllers addObject:contactsController]; + } +#endif + } else { + [user start]; + [theSetting setTitle:MGMLogout]; + } + currentContactsController = [contactsControllers count]-1; + [(UITableView *)[settings view] reloadData]; + } +} +- (void)settingDeleted:(MGMSetting *)theSetting { + NSString *key = [theSetting key]; + if (key==nil) + key = [[theSetting extra] objectForKey:MGMSKeyKey]; + NSString *path = [[theSetting extra] objectForKey:MGMTSPath]; + [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; + + NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil]; + MGMSettingSections *sections = [[settings sections] parent]; + NSDictionary *sounds = [[controller themeManager] sounds]; + for (int i=0; i<[rebuild count]; i++) { + NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]]; + MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]; + if ([[MGMTSName stringByAppendingString:[rebuild objectAtIndex:i]] isEqual:key]) { + NSString *soundName = [[theSetting key] substringFromIndex:[MGMTSName length]]; + [(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[setting objectForKey:MGMSValueKey]]; + [[settings sections] setSections:[settingSections sections]]; + } else { + [(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections]; + } + } +} +- (void)settingDeleted:(MGMSetting *)theSetting value:(id)theValue { + if ([[theSetting key] isEqual:MGMTCurrentThemeName]) { + int index = 0; + for (int i=0; i<[[theSetting value] count]; i++) { + if ([[[[theSetting value] objectAtIndex:i] objectForKey:MGMSValueKey] isEqual:theValue]) { + index = i; + break; + } + } + NSString *path = [[[[controller themeManager] themes] objectAtIndex:index] objectForKey:MGMTThemePath]; + if ([path rangeOfString:[[NSBundle mainBundle] resourcePath]].location!=NSNotFound) { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error Deleting"]; + [alert setMessage:@"You cannot delete a built in theme."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } else if ([([[theSetting extra] isKindOfClass:[NSDictionary class]] ? [[theSetting extra] objectForKey:MGMSValueKey] : [theSetting extra]) isEqual:theValue]) { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error Deleting"]; + [alert setMessage:@"You cannot delete the current theme."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } else { + [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; + NSMutableArray *themesValue = [NSMutableArray array]; + NSArray *themes = [[controller themeManager] themes]; + for (int i=0; i<[themes count]; i++) { + [themesValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[themes objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [[[themes objectAtIndex:i] objectForKey:MGMTThemePath] lastPathComponent], MGMSValueKey, nil]]; + } + [theSetting setValue:themesValue]; + } + } else { + NSString *key = [theSetting key]; + if (key==nil) + key = [[theSetting extra] objectForKey:MGMSKeyKey]; + NSString *path = [[[theSetting extra] objectForKey:MGMTSPath] stringByAppendingPathComponent:theValue]; + [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; + if ([[theSetting value] count]==1) { + [self goBack:self]; + shouldRefreshSounds = YES; + } else { + NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil]; + MGMSettingSections *sections = [[settings sections] parent]; + NSDictionary *sounds = [[controller themeManager] sounds]; + for (int i=0; i<[rebuild count]; i++) { + NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]]; + MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]; + if ([[MGMTSName stringByAppendingString:[rebuild objectAtIndex:i]] isEqual:key]) { + NSString *soundName = [[theSetting key] substringFromIndex:[MGMTSName length]]; + [(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[setting objectForKey:MGMSValueKey]]; + [theSetting setValue:[[[[settingSections sectionAtIndex:0] settings] objectAtIndex:[[[[settings sections] sectionAtIndex:0] settings] indexOfObject:theSetting]] value]]; + } else { + [(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections]; + } + } + } + } +} +- (void)showSettingsAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + if ([settings parentTitle]!=nil) + [[settingsItems objectAtIndex:0] setTitle:[settings parentTitle]]; + else + [[settingsItems objectAtIndex:0] setTitle:MGMBackTitle]; + [self setItems:settingsItems animated:YES]; + [((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) removeFromSuperview]; + [((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? accounts : [contactsControllers objectAtIndex:currentContactsController]) releaseView]; +} +- (void)hideSettingsAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [[settings view] removeFromSuperview]; + [settings release]; + settings = nil; + if (currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) { + if (currentContactsController!=-1) { + [contactsControllers removeObjectAtIndex:currentContactsController]; + currentContactsController = -1; + [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; + } + [[NSUserDefaults standardUserDefaults] synchronize]; + [[accountsItems objectAtIndex:0] setEnabled:YES]; + } else { + [[accountItems objectAtIndex:0] setEnabled:YES]; + } } - (void)userStarted:(NSNotification *)theNotification { @@ -161,31 +781,16 @@ NSString * const MGMAccountsTitle = @"Accounts"; } - (void)userDone:(NSNotification *)theNotification { for (int i=0; i<[contactsControllers count]; i++) { - if ([[contactsControllers objectAtIndex:i] isKindOfClass:[MGMVoiceUser class]]) { - MGMVoiceUser *voiceUser = [contactsControllers objectAtIndex:i]; - if ([[voiceUser user] isEqual:[theNotification object]]) { - if (currentContactsController==i) { - currentContactsController = -1; - [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; - } else { - [contactsControllers removeObject:voiceUser]; - } - break; + id account = [contactsControllers objectAtIndex:i]; + if ([[account user] isEqual:[theNotification object]]) { + if (currentContactsController==i) { + currentContactsController = -1; + [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; + } else { + [contactsControllers removeObject:account]; } + break; } -#if MGMSIPENABLED - else if ([[contactsControllers objectAtIndex:i] isKindOfClass:[MGMSIPUser class]]) { - MGMSIPUser *SIPUser = [contactsControllers objectAtIndex:i]; - if ([[SIPUser user] isEqual:[theNotification object]]) { - if (currentContactsController==i) { - currentContactsController = -1; - [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; - } else { - [contactsControllers removeObject:SIPUser]; - } - } - } -#endif } } @@ -201,45 +806,60 @@ NSString * const MGMAccountsTitle = @"Accounts"; if ([[theUser settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) { contactsController = [MGMVoiceUser voiceUser:theUser accountController:self]; [contactsControllers addObject:contactsController]; + } else if ([[theUser settingForKey:MGMSAccountType] isEqual:MGMSGoogleContacts]) { + contactsController = [MGMGContactUser gContactUser:theUser accountController:self]; + [contactsControllers addObject:contactsController]; } #if MGMSIPENABLED else if ([[theUser settingForKey:MGMSAccountType] isEqual:MGMSSIP]) { + NSLog(@"Hello"); if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start]; contactsController = [MGMSIPUser SIPUser:theUser accountController:self]; [contactsControllers addObject:contactsController]; } #endif } - if ([theUser isStarted]) { - currentContactsController = [contactsControllers indexOfObject:contactsController]; - [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; + if (contactsController==nil) + return; + currentContactsController = [contactsControllers indexOfObject:contactsController]; + if (![theUser isStarted]) { + [self showSettings:self]; + } else if ([contactsController view]!=nil) { + [[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController]; + + [self setItems:nil animated:YES]; + [self setTitle:[contactsController title]]; + + CGRect outViewFrame = [[accounts view] frame]; + CGRect inViewFrame = [[contactsController view] frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = +inViewFrame.size.width; + [[contactsController view] setFrame:inViewFrame]; + [contentView addSubview:[contactsController view]]; + [UIView beginAnimations:nil context:accounts]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(contactsControllerAnimationDidStop:finished:contactsController:)]; + [[contactsController view] setFrame:outViewFrame]; + outViewFrame.origin.x = -outViewFrame.size.width; + [[accounts view] setFrame:outViewFrame]; + [UIView commitAnimations]; } - [self setItems:nil animated:YES]; - [self setTitle:[contactsController title]]; - - CGRect inViewFrame = [[contactsController view] frame]; - inViewFrame.origin.x = +inViewFrame.size.width; - [[contactsController view] setFrame:inViewFrame]; - [contentView addSubview:[contactsController view]]; - [UIView beginAnimations:nil context:accounts]; - [UIView setAnimationDuration:0.5]; - [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(contactsControllerAnimationDidStop:finished:contactsController:)]; - [[contactsController view] setFrame:[[accounts view] frame]]; - CGRect outViewFrame = [[accounts view] frame]; - outViewFrame.origin.x = -outViewFrame.size.width; - [[accounts view] setFrame:outViewFrame]; - [UIView commitAnimations]; } - (void)contactsControllerAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished contactsController:(id)theContactsController { [[theContactsController view] removeFromSuperview]; [theContactsController releaseView]; if ([theContactsController isKindOfClass:[MGMAccounts class]]) { [self setItems:accountItems animated:YES]; - } else { - if (![[theContactsController user] isStarted]) - [contactsControllers removeObject:theContactsController]; + } +} + +- (IBAction)phone:(id)sender { + if (currentContactsController!=-1) { + id contactsController = [contactsControllers objectAtIndex:currentContactsController]; + if (![[phoneButton titleForState:UIControlStateNormal] isEqual:[contactsController title]] && [[phoneButton titleForState:UIControlStateNormal] isPhone]) + [contactsController showOptionsForNumber:[[phoneButton titleForState:UIControlStateNormal] phoneFormatWithAreaCode:[contactsController areaCode]]]; } } @end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMAccountSetup.h b/Classes/VoiceMob/MGMAccountSetup.h index 5c63372..9e7bd34 100644 --- a/Classes/VoiceMob/MGMAccountSetup.h +++ b/Classes/VoiceMob/MGMAccountSetup.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import @@ -22,8 +22,6 @@ extern NSString * const MGMSIPDefaultDomain; BOOL setupOnly; IBOutlet UIView *setupView; - CGRect setupRect; - CGRect setupKeyboardRect; IBOutlet UIView *view; IBOutlet UILabel *titleField; IBOutlet UIBarButtonItem *backButton; @@ -77,6 +75,8 @@ extern NSString * const MGMSIPDefaultDomain; IBOutlet UILabel *S7StatusField; MGMUser *S7CheckUser; MGMInstance *S7CheckInstance; + UIAlertView *S7VerificationView; + UITextField *S7VerificationField; MGMURLConnectionManager *S7ConnectionManager; #if MGMSIPENABLED MGMSIPAccount *S7CheckSIPAccount; @@ -115,8 +115,6 @@ extern NSString * const MGMSIPDefaultDomain; - (void)S5Reset; //Step 6 -- (IBAction)S6ShowKeyboard:(id)sender; -- (IBAction)S6CloseKeyboard:(id)sender; - (IBAction)S6UserNameChanged:(id)sender; - (IBAction)S6DomainChanged:(id)sender; - (void)S6Reset; diff --git a/Classes/VoiceMob/MGMAccountSetup.m b/Classes/VoiceMob/MGMAccountSetup.m index 587aad5..0632266 100644 --- a/Classes/VoiceMob/MGMAccountSetup.m +++ b/Classes/VoiceMob/MGMAccountSetup.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMAccountSetup.h" @@ -33,9 +33,11 @@ NSString * const MGMS7SIPWaiting = @"Waiting for Registration Status."; NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; +NSString * const MGMASKeyboardBounds = @"UIKeyboardBoundsUserInfoKey"; + @implementation MGMAccountSetup - (id)initWithController:(MGMController *)theController { - if (self = [super init]) { + if ((self = [super init])) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"AccountSetup"] owner:self options:nil]) { NSLog(@"Unable to load Account Setup"); [self release]; @@ -50,48 +52,60 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; accountType = 0; accountsCreated = [NSMutableArray new]; S7ConnectionManager = [[MGMURLConnectionManager managerWithCookieStorage:nil] retain]; - setupRect = [setupView frame]; - setupKeyboardRect = setupRect; - setupKeyboardRect.origin.y = (-(setupKeyboardRect.size.height-45))+246; + + NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter]; + [notifications addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [notifications addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } } return self; } - (void)dealloc { - if (setupView!=nil) - [setupView release]; - if (S1View!=nil) - [S1View release]; - if (S2View!=nil) - [S2View release]; - if (S3View!=nil) - [S3View release]; - if (S4View!=nil) - [S4View release]; - if (S5View!=nil) - [S5View release]; - if (S6View!=nil) - [S6View release]; - if (S7View!=nil) - [S7View release]; - if (S8View!=nil) - [S8View release]; - if (S9View!=nil) - [S9View release]; - if (accountsCreated!=nil) - [accountsCreated release]; - if (S7CheckUser!=nil) - [S7CheckUser release]; - if (S7CheckInstance!=nil) - [S7CheckInstance release]; - if (S7ConnectionManager!=nil) - [S7ConnectionManager release]; -#if MGMSIPENABLED - if (S7CheckSIPAccount!=nil) - [S7CheckSIPAccount release]; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); #endif - if (S8Message!=nil) - [S8Message release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [setupView release]; + [view release]; + [titleField release]; + [backButton release]; + [continueButton release]; + [S1View release]; + [S2View release]; + [S2GVButton release]; + [S2GCButton release]; + [S2SIPButton release]; + [S3View release]; + [S3Browser release]; + [S4View release]; + [S4EmailField release]; + [S4PasswordField release]; + [S5View release]; + [S5EmailField release]; + [S5PasswordField release]; + [S6View release]; + [S6FullNameField release]; + [S6DomainField release]; + [S6RegistrarField release]; + [S6UserNameField release]; + [S6PasswordField release]; + [S7View release]; + [S7Progress release]; + [S7StatusField release]; + [S7CheckUser release]; + [S7CheckInstance release]; + [S7ConnectionManager release]; +#if MGMSIPENABLED + [S7CheckSIPAccount release]; + [S7SIPRegistrationTimeout invalidate]; + [S7SIPRegistrationTimeout release]; +#endif + [S8View release]; + [S8MessageField release]; + [S8Message release]; + [S9View release]; + [S9MessageField release]; + [accountsCreated release]; [super dealloc]; } @@ -104,6 +118,42 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; - (IBAction)closeKeyboard:(id)sender { } +- (void)keyboardWillShow:(NSNotification *)theNotification { + if (step!=6) return; + CGSize keyboardSize = CGSizeZero; + if ([[theNotification userInfo] objectForKey:MGMASKeyboardBounds]!=nil) + keyboardSize = [[[theNotification userInfo] objectForKey:MGMASKeyboardBounds] CGRectValue].size; + else + keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + CGRect setupRect = [setupView frame]; + setupRect.origin.y = (-keyboardSize.height)+44; + if (!CGRectEqualToRect([setupView frame], setupRect)) { + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.3]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [setupView setFrame:setupRect]; + [UIView commitAnimations]; + } +} +- (void)keyboardWillHide:(NSNotification *)theNotification { + if (step!=6) return; + CGSize keyboardSize = CGSizeZero; + if ([[theNotification userInfo] objectForKey:MGMASKeyboardBounds]!=nil) + keyboardSize = [[[theNotification userInfo] objectForKey:MGMASKeyboardBounds] CGRectValue].size; + else + keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + CGRect setupRect = [setupView frame]; + setupRect.origin.y = 0; + if (!CGRectEqualToRect([setupView frame], setupRect)) { + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.3]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [setupView setFrame:setupRect]; + [UIView commitAnimations]; + } +} - (void)setSetupOnly:(BOOL)isSetupOnly { setupOnly = isSetupOnly; @@ -203,11 +253,17 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; [backButton setEnabled:YES]; [continueButton setTitle:MGMSContinue]; [continueButton setEnabled:NO]; +<<<<<<< HEAD + [S8MessageField setText:[NSString stringWithFormat:@"Unable to set up your %@ account, the error we receviced was \"%@\" Please go back and correct the problem.", type, S8Message]]; + [S8Message release]; + S8Message = nil; +======= [S8MessageField setText:[NSString stringWithFormat:@"Unable to set up your %@ account, the error we received was \"%@\" Please go back and correct the problem.", type, S8Message]]; if (S8Message!=nil) { [S8Message release]; S8Message = nil; } +>>>>>>> 13b6d2ac024f36826fdb6cd6dcb05710e133e842 break; } case 9: { @@ -239,7 +295,9 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; [continueButton setEnabled:NO]; displaying = YES; if (goingBack) { + CGRect outViewFrame = [lastView frame]; CGRect inViewFrame = [nextView frame]; + inViewFrame.size = outViewFrame.size; inViewFrame.origin.x = -inViewFrame.size.width; [nextView setFrame:inViewFrame]; [view addSubview:nextView]; @@ -248,13 +306,14 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(displayAnimationDidStop:finished:context:)]; - [nextView setFrame:[lastView frame]]; - CGRect outViewFrame = [lastView frame]; + [nextView setFrame:outViewFrame]; outViewFrame.origin.x = +outViewFrame.size.width; [lastView setFrame:outViewFrame]; [UIView commitAnimations]; } else { + CGRect outViewFrame = [lastView frame]; CGRect inViewFrame = [nextView frame]; + inViewFrame.size = outViewFrame.size; inViewFrame.origin.x = +inViewFrame.size.width; [nextView setFrame:inViewFrame]; [view addSubview:nextView]; @@ -263,8 +322,7 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(displayAnimationDidStop:finished:context:)]; - [nextView setFrame:[lastView frame]]; - CGRect outViewFrame = [lastView frame]; + [nextView setFrame:outViewFrame]; outViewFrame.origin.x = -outViewFrame.size.width; [lastView setFrame:outViewFrame]; [UIView commitAnimations]; @@ -334,11 +392,11 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; #if MGMSIPENABLED step = 6; #else - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Unable to Add Account"]; - [theAlert setMessage:@"MGMSIP is not compiled with VoiceMob, you can not add a SIP account without first compiling with MGMSIP."]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Unable to Add Account"]; + [alert setMessage:@"MGMSIP is not compiled with VoiceMob, you can not add a SIP account without first compiling with MGMSIP."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; return; #endif break; @@ -363,11 +421,11 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; emptyFields = YES; } if (emptyFields) { - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Missing Information"]; - [theAlert setMessage:@"It appears as if you did not fill the required fields, please fill out the required fields and then continue."]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Missing Information"]; + [alert setMessage:@"It appears as if you did not fill the required fields, please fill out the required fields and then continue."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; return; } step = 7; @@ -412,22 +470,6 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; } //Step 6 -- (IBAction)S6ShowKeyboard:(id)sender { - if (CGRectEqualToRect([setupView frame], setupRect)) { - [UIView beginAnimations:nil context:nil]; - [UIView setAnimationDuration:0.3]; - [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; - [setupView setFrame:setupKeyboardRect]; - [UIView commitAnimations]; - } -} -- (IBAction)S6CloseKeyboard:(id)sender { - [UIView beginAnimations:nil context:nil]; - [UIView setAnimationDuration:0.3]; - [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; - [setupView setFrame:setupRect]; - [UIView commitAnimations]; -} - (IBAction)S6UserNameChanged:(id)sender { [S6FullNameField setPlaceholder:[S6UserNameField text]]; } @@ -453,21 +495,51 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; S7CheckInstance = [[MGMInstance instanceWithUser:S7CheckUser delegate:self isCheck:YES] retain]; } - (void)loginError:(NSError *)theError { - if (S7CheckUser!=nil) { - [S7CheckUser remove]; - [S7CheckUser release]; - S7CheckUser = nil; - } - if (S7CheckInstance!=nil) { - [S7CheckInstance release]; - S7CheckInstance = nil; - } + [S7VerificationView release]; + S7VerificationView = nil; + [S7VerificationField release]; + S7VerificationField = nil; + [S7CheckUser remove]; + [S7CheckUser release]; + S7CheckUser = nil; + [S7CheckInstance release]; + S7CheckInstance = nil; NSLog(@"Login Failed %@", theError); S8Message = [[theError localizedDescription] copy]; step = 8; [self displayStep]; } +- (void)loginVerificationRequested { + [S7VerificationView release]; + S7VerificationView = [UIAlertView new]; + [S7VerificationView setTitle:@"Account Verification"]; + [S7VerificationView setMessage:@" "]; + [S7VerificationView addButtonWithTitle:@"Cancel"]; + [S7VerificationView addButtonWithTitle:@"Verify"]; + [S7VerificationView setCancelButtonIndex:1]; + [S7VerificationView setDelegate:self]; + [S7VerificationField release]; + S7VerificationField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)]; + [S7VerificationField setBorderStyle:UITextBorderStyleLine]; + [S7VerificationField setBackgroundColor:[UIColor whiteColor]]; + [S7VerificationField setKeyboardType:UIKeyboardTypeNumbersAndPunctuation]; + [S7VerificationView addSubview:S7VerificationField]; + [S7VerificationView show]; + [S7VerificationField becomeFirstResponder]; +} +- (void)alertView:(UIAlertView *)theAlertView clickedButtonAtIndex:(NSInteger)theIndex { + if (theAlertView==S7VerificationView) { + if (theIndex==1) + [S7CheckInstance verifyWithCode:[S7VerificationField text]]; + else + [S7CheckInstance cancelVerification]; + } +} - (void)loginSuccessful { + [S7VerificationView release]; + S7VerificationView = nil; + [S7VerificationField release]; + S7VerificationField = nil; if (S7CheckUser!=nil) { [accountsCreated addObject:S7CheckUser]; MGMUser *contactsUser = [MGMUser createUserWithName:[S4EmailField text] password:[S4PasswordField text]]; @@ -476,10 +548,8 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; [S7CheckUser release]; S7CheckUser = nil; } - if (S7CheckInstance!=nil) { - [S7CheckInstance release]; - S7CheckInstance = nil; - } + [S7CheckInstance release]; + S7CheckInstance = nil; [self S4Reset]; step = 9; [self displayStep]; @@ -494,44 +564,41 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; NSURLCredential *credentials = [NSURLCredential credentialWithUser:username password:[S7CheckUser password] persistence:NSURLCredentialPersistenceForSession]; [S7ConnectionManager setCookieStorage:[S7CheckUser cookieStorage]]; [S7ConnectionManager setCredentials:credentials]; - [S7ConnectionManager setCustomUseragent:MGMGCUseragent]; + [S7ConnectionManager setUserAgent:MGMGCUseragent]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:MGMGCAuthenticationURL] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0]; [request setHTTPMethod:MGMPostMethod]; [request setValue:MGMURLForm forHTTPHeaderField:MGMContentType]; [request setHTTPBody:[[NSString stringWithFormat:MGMGCAuthenticationBody, [username addPercentEscapes], [[S7CheckUser password] addPercentEscapes]] dataUsingEncoding:NSUTF8StringEncoding]]; - [S7ConnectionManager connectionWithRequest:request delegate:self didFailWithError:@selector(authentication:didFailWithError:) didFinish:@selector(authenticationDidFinish:) invisible:NO object:nil]; + MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:request delegate:self]; + [handler setFailWithError:@selector(authentication:didFailWithError:)]; + [handler setFinish:@selector(authenticationDidFinish:)]; + [S7ConnectionManager addHandler:handler]; } -- (void)authentication:(NSDictionary *)theInfo didFailWithError:(NSError *)theError { - if (S7CheckUser!=nil) { - [S7CheckUser remove]; - [S7CheckUser release]; - S7CheckUser = nil; - } - if (S7ConnectionManager!=nil) - [S7ConnectionManager setCookieStorage:nil]; +- (void)authentication:(MGMURLBasicHandler *)theHandler didFailWithError:(NSError *)theError { + [S7CheckUser remove]; + [S7CheckUser release]; + S7CheckUser = nil; + [S7ConnectionManager setCookieStorage:nil]; NSLog(@"Login Failed %@", theError); S8Message = [[theError localizedDescription] copy]; step = 8; [self displayStep]; } -- (void)authenticationDidFinish:(NSDictionary *)theInfo { - NSDictionary *info = [MGMGoogleContacts dictionaryWithData:[theInfo objectForKey:MGMConnectionData]]; - if (S7ConnectionManager!=nil) - [S7ConnectionManager setCookieStorage:nil]; - if (S7CheckUser!=nil) { - if ([info objectForKey:@"Error"]!=nil) { - [S7CheckUser remove]; - [S7CheckUser release]; - S7CheckUser = nil; - S8Message = [@"Unable to login. Please check your Credentials." retain]; - step = 8; - [self displayStep]; - return; - } - [S7CheckUser done]; +- (void)authenticationDidFinish:(MGMURLBasicHandler *)theHandler { + NSDictionary *info = [MGMGoogleContacts dictionaryWithString:[theHandler string]]; + [S7ConnectionManager setCookieStorage:nil]; + if ([info objectForKey:@"Error"]!=nil) { + [S7CheckUser remove]; [S7CheckUser release]; S7CheckUser = nil; + S8Message = [@"Unable to login. Please check your Credentials." retain]; + step = 8; + [self displayStep]; + return; } + [S7CheckUser done]; + [S7CheckUser release]; + S7CheckUser = nil; [self S5Reset]; step = 9; @@ -557,6 +624,7 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; if (![[S6RegistrarField text] isEqual:@""]) [S7CheckUser setSetting:[S6RegistrarField text] forKey:MGMSIPAccountRegistrar]; S7CheckSIPAccount = [[MGMSIPAccount alloc] initWithSettings:[S7CheckUser settings]]; + [S7CheckUser registerSettings:[S7CheckSIPAccount settings]]; [S7CheckSIPAccount setDelegate:self]; S7AccountRegistered = NO; NSLog(@"Logging in"); @@ -567,23 +635,22 @@ 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]; - [S7SIPRegistrationTimeout release]; - S7SIPRegistrationTimeout = nil; - } - if (S7CheckSIPAccount!=nil) { - if (![S7CheckSIPAccount isRegistered]) { - [S7CheckSIPAccount setLastError:@"Unable to Register with Server. Please check your credentials."]; - [self loginErrored]; - return; - } - [S7CheckSIPAccount setDelegate:nil]; - [S7CheckSIPAccount logout]; - [S7CheckSIPAccount release]; - S7CheckSIPAccount = nil; + [S7SIPRegistrationTimeout invalidate]; + [S7SIPRegistrationTimeout release]; + S7SIPRegistrationTimeout = nil; + if (![S7CheckSIPAccount isRegistered]) { + [S7CheckSIPAccount setLastError:@"Unable to Register with Server. Please check your credentials."]; + [self loginErrored]; + return; } + [S7CheckSIPAccount setDelegate:nil]; + [S7CheckSIPAccount logout]; + [S7CheckSIPAccount release]; + S7CheckSIPAccount = nil; if (S7CheckUser!=nil) { [accountsCreated addObject:S7CheckUser]; [S7CheckUser release]; @@ -592,16 +659,14 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; [self S6Reset]; S7AccountRegistered = YES; step = 9; - [self performSelectorOnMainThread:@selector(displayStep) withObject:nil waitUntilDone:NO]; + [self displayStep]; #endif } #if MGMSIPENABLED - (void)S7SIPTimeout { - if (S7SIPRegistrationTimeout!=nil) { - [S7SIPRegistrationTimeout invalidate]; - [S7SIPRegistrationTimeout release]; - S7SIPRegistrationTimeout = nil; - } + [S7SIPRegistrationTimeout invalidate]; + [S7SIPRegistrationTimeout release]; + S7SIPRegistrationTimeout = nil; [S7CheckSIPAccount setLastError:@"Registration Timeout."]; [self loginErrored]; } @@ -614,19 +679,15 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com"; S7SIPRegistrationTimeout = [[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(S7SIPTimeout) userInfo:nil repeats:NO] retain]; } - (void)loginErrored { - if (S7CheckUser!=nil) { - [S7CheckUser remove]; - [S7CheckUser release]; - S7CheckUser = nil; - } - if (S7CheckSIPAccount!=nil) { - NSLog(@"Login Failed %@", [S7CheckSIPAccount lastError]); - S8Message = [[S7CheckSIPAccount lastError] copy]; - [S7CheckSIPAccount setDelegate:nil]; - [S7CheckSIPAccount logout]; - [S7CheckSIPAccount release]; - S7CheckSIPAccount = nil; - } + [S7CheckUser remove]; + [S7CheckUser release]; + S7CheckUser = nil; + NSLog(@"Login Failed %@", [S7CheckSIPAccount lastError]); + S8Message = [[S7CheckSIPAccount lastError] copy]; + [S7CheckSIPAccount setDelegate:nil]; + [S7CheckSIPAccount logout]; + [S7CheckSIPAccount release]; + S7CheckSIPAccount = nil; step = 8; [self performSelectorOnMainThread:@selector(displayStep) withObject:nil waitUntilDone:NO]; } diff --git a/Classes/VoiceMob/MGMAccounts.h b/Classes/VoiceMob/MGMAccounts.h index d2dec14..e026fa7 100644 --- a/Classes/VoiceMob/MGMAccounts.h +++ b/Classes/VoiceMob/MGMAccounts.h @@ -3,10 +3,10 @@ // VoiceMob // // Created by Mr. Gecko on 9/27/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // -#import +#import @class MGMAccountController; diff --git a/Classes/VoiceMob/MGMAccounts.m b/Classes/VoiceMob/MGMAccounts.m index e108153..b01ae7f 100644 --- a/Classes/VoiceMob/MGMAccounts.m +++ b/Classes/VoiceMob/MGMAccounts.m @@ -3,12 +3,14 @@ // VoiceMob // // Created by Mr. Gecko on 9/27/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMAccounts.h" #import "MGMAccountController.h" +#import "MGMBadgeView.h" #import "MGMAccountSetup.h" +#import "MGMVoiceUser.h" #import "MGMVMAddons.h" #import #import @@ -17,12 +19,15 @@ NSString * const MGMAccountCellIdentifier = @"MGMAccountCellIdentifier"; @implementation MGMAccounts - (id)initWithAccountController:(MGMAccountController *)theAccountController { - if (self = [super init]) { + if ((self = [super init])) { accountController = theAccountController; } return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [self releaseView]; [super dealloc]; } @@ -31,8 +36,6 @@ NSString * const MGMAccountCellIdentifier = @"MGMAccountCellIdentifier"; if (tableView==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"Accounts"] owner:self options:nil]) { NSLog(@"Unable to load Accounts"); - [self release]; - self = nil; } else { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:tableView selector:@selector(reloadData) name:MGMUserStartNotification object:nil]; @@ -42,32 +45,45 @@ NSString * const MGMAccountCellIdentifier = @"MGMAccountCellIdentifier"; return tableView; } - (void)releaseView { - if (tableView!=nil) { - [tableView release]; - tableView = nil; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - } +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [tableView release]; + tableView = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section { return [[MGMUser users] count]; } - (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MGMAccountCellIdentifier]; + MGMBadgeView *cell = (MGMBadgeView *)[tableView dequeueReusableCellWithIdentifier:MGMAccountCellIdentifier]; if (cell==nil) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMAccountCellIdentifier] autorelease]; + cell = [[[MGMBadgeView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMAccountCellIdentifier] autorelease]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } NSArray *users = [MGMUser users]; if ([users count]<=[indexPath indexAtPosition:1]) { - [cell setText:@"Unknown"]; + [cell setName:@"Unknown"]; } else { - [cell setText:[[MGMUser userNames] objectAtIndex:[indexPath indexAtPosition:1]]]; + [cell setName:[[MGMUser userNames] objectAtIndex:[indexPath indexAtPosition:1]]]; MGMUser *user = [MGMUser userWithID:[users objectAtIndex:[indexPath indexAtPosition:1]]]; + id account = [accountController contactControllerWithUser:user]; + if ([account isKindOfClass:[MGMVoiceUser class]]) { + int count = [accountController badgeValueForInstance:[(MGMVoiceUser *)account instance]]; + if (count!=0) + [cell setBadge:[[NSNumber numberWithInt:count] stringValue]]; + else + [cell setBadge:nil]; + } else { + [cell setBadge:nil]; + } +#if MGMSPENABLED if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) { if ([user settingForKey:MGMSIPAccountFullName]!=nil && ![[user settingForKey:MGMSIPAccountFullName] isEqual:@""]) - [cell setText:[user settingForKey:MGMSIPAccountFullName]]; + [cell setName:[user settingForKey:MGMSIPAccountFullName]]; } +#endif } return cell; } diff --git a/Classes/VoiceMob/MGMContactsController.h b/Classes/VoiceMob/MGMContactsController.h index 1ea9741..58026ef 100644 --- a/Classes/VoiceMob/MGMContactsController.h +++ b/Classes/VoiceMob/MGMContactsController.h @@ -3,14 +3,14 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import @class MGMAccountController, MGMContacts; -@interface MGMContactsController : NSObject { +@interface MGMContactsController : NSObject { MGMAccountController *accountController; IBOutlet UISearchBar *searchBar; @@ -29,6 +29,7 @@ - (void)awakeFromNib; - (void)releaseView; +- (void)cleanup; - (MGMContacts *)contacts; - (NSString *)filterString; diff --git a/Classes/VoiceMob/MGMContactsController.m b/Classes/VoiceMob/MGMContactsController.m index 76c05f9..3791689 100644 --- a/Classes/VoiceMob/MGMContactsController.m +++ b/Classes/VoiceMob/MGMContactsController.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMContactsController.h" @@ -15,10 +15,8 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier"; @implementation MGMContactsController -- (id)initWithAccountController:(MGMAccountController *)theAccountController { - if (self = [super init]) { - accountController = theAccountController; - +- (id)init { + if ((self = [super init])) { filterLock = [NSLock new]; filterWaiting = 0; contactViews = [NSMutableArray new]; @@ -26,28 +24,43 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier"; } return self; } +- (id)initWithAccountController:(MGMAccountController *)theAccountController { + if ((self = [self init])) { + accountController = theAccountController; + } + return self; +} - (void)awakeFromNib { - if (contactsMatchString!=nil) - [searchBar setText:contactsMatchString]; + [searchBar setText:contactsMatchString]; [self filterContacts]; [searchCancelButton setHidden:YES]; } +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [filterLock release]; + [contactsMatchString release]; + [contactViews release]; + [super dealloc]; +} - (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [searchBar release]; searchBar = nil; + [searchCancelButton release]; searchCancelButton = nil; + [contactsTable release]; contactsTable = nil; + [self cleanup]; +} +- (void)cleanup { contactsCount = 0; [contactViews removeAllObjects]; } -- (void)dealloc { - if (filterLock!=nil) - [filterLock release]; - if (contactsMatchString!=nil) - [contactsMatchString release]; - if (contactViews!=nil) - [contactViews release]; - [super dealloc]; -} - (MGMContacts *)contacts { return nil; @@ -56,9 +69,12 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier"; return [searchBar text]; } - (void)updateMatchString { - if (contactsMatchString!=nil) [contactsMatchString release]; + [contactsMatchString release]; contactsMatchString = [[self filterString] copy]; } +- (void)scrollToTop { + [contactsTable scrollRectToVisible:CGRectMake(0, 0, [contactsTable frame].size.width, 20) animated:NO]; +} - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)theSearchBar { [searchCancelButton setHidden:NO]; @@ -87,6 +103,7 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier"; cell = [[[MGMContactView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMContactViewCellIdentifier] autorelease]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; [cell setThemeManager:[[accountController controller] themeManager]]; + [cell setContacts:[self contacts]]; } int row = [indexPath indexAtPosition:1]; @@ -137,13 +154,13 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier"; contactsVisible.location = 0; contactsVisible.length = [[self contacts] maxResults]; - [contactViews addObjectsFromArray:[[self contacts] contactsMatching:contactsMatchString page:1]]; + [contactViews addObjectsFromArray:[[self contacts] contactsMatching:contactsMatchString page:1 includePhoto:NO]]; contactsCount = count; [filterLock unlock]; if (contactsTable==nil) return; [contactsTable performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; if (contactsCount!=0) - [contactsTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; + [self performSelectorOnMainThread:@selector(scrollToTop) withObject:nil waitUntilDone:NO]; [pool drain]; } - (void)loadContacts:(BOOL)updatingCount { @@ -161,7 +178,7 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier"; int times = contactsLoading.length/maxResults; for (int t=0; t -@class MGMThemeManager, MGMAccountController, MGMAccountSetup; +@class MGMThemeManager, MGMAccountController, MGMAccountSetup, MGMReverseLookup, MGMInstance, MGMVoiceMultiSMS; + +#if MGMSIPENABLED +@class MGMSIPCallView; +#endif @interface MGMController : UIViewController { IBOutlet UIWindow *mainWindow; + BOOL inBackground; + MGMThemeManager *themeManager; MGMAccountController *accountController; } +- (BOOL)isInBackground; - (MGMThemeManager *)themeManager; +- (MGMAccountController *)accountController; - (void)showAccountSetup; - (void)dismissAccountSetup:(MGMAccountSetup *)theAccountSetup; + +- (void)showReverseLookupWithNumber:(NSString *)theNumber; +- (void)dismissReverseLookup:(MGMReverseLookup *)theReverseLookup; + +- (void)showMultiSMSWithInstance:(MGMInstance *)theInstance; +- (void)dismissMultiSMS:(MGMVoiceMultiSMS *)theMultiSMS; + +#if MGMSIPENABLED +- (void)showCallView:(MGMSIPCallView *)theCallView; +- (void)dismissCallView:(MGMSIPCallView *)theCallView; +#endif @end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMController.m b/Classes/VoiceMob/MGMController.m index 5fa4a90..7bf7290 100644 --- a/Classes/VoiceMob/MGMController.m +++ b/Classes/VoiceMob/MGMController.m @@ -3,37 +3,94 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMController.h" #import "MGMAccountController.h" #import "MGMAccountSetup.h" +#import "MGMReverseLookup.h" +#import "MGMVoiceMultiSMS.h" #import "MGMVMAddons.h" #import #import +#if MGMSIPENABLED +#import "MGMSIPUser.h" +#import "MGMSIPCallView.h" +#endif + @implementation MGMController - (void)awakeFromNib { + inBackground = NO; + themeManager = [MGMThemeManager new]; accountController = [[MGMAccountController alloc] initWithController:self]; - [[self view] addSubview:[accountController view]]; [mainWindow addSubview:[self view]]; + [mainWindow makeKeyAndVisible]; +} +- (void)dealloc { + [mainWindow release]; + [themeManager release]; + [accountController release]; + [super dealloc]; +} + +- (BOOL)isInBackground { + return inBackground; +} +- (MGMThemeManager *)themeManager { + return themeManager; +} +- (MGMAccountController *)accountController { + return accountController; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + [accountController releaseView]; +} +- (void)applicationDidBecomeActive:(UIApplication *)application { + inBackground = NO; + [self performSelector:@selector(clearCalls) withObject:nil afterDelay:0.1]; + CGRect viewFrame = [[accountController view] frame]; + viewFrame.size = [[self view] frame].size; + [[accountController view] setFrame:viewFrame]; + [[self view] addSubview:[accountController view]]; if ([[MGMUser userNames] count]==0) { MGMAccountSetup *accountSetup = [[MGMAccountSetup alloc] initWithController:self]; [[self view] addSubview:[accountSetup view]]; } - [mainWindow makeKeyAndVisible]; } -- (MGMThemeManager *)themeManager { - return themeManager; +#if MGMSIPENABLED +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { + for (int i=0; i<[[accountController contactsControllers] count]; i++) { + if ([[[accountController contactsControllers] objectAtIndex:i] isKindOfClass:[MGMSIPUser class]]) + [[[accountController contactsControllers] objectAtIndex:i] answerCall]; + } } +- (void)applicationDidEnterBackground:(UIApplication *)application { + [[MGMSIP sharedSIP] performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES]; + [application setKeepAliveTimeout:600 handler: ^{ + [[MGMSIP sharedSIP] performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES]; + }]; + inBackground = YES; +} +- (void)clearCalls { + for (int i=0; i<[[accountController contactsControllers] count]; i++) { + if ([[[accountController contactsControllers] objectAtIndex:i] isKindOfClass:[MGMSIPUser class]]) + [[[accountController contactsControllers] objectAtIndex:i] clearCall]; + } +} +#endif +#endif - (void)showAccountSetup { MGMAccountSetup *accountSetup = [[MGMAccountSetup alloc] initWithController:self]; [accountSetup setSetupOnly:YES]; CGRect inViewFrame = [[accountSetup view] frame]; + inViewFrame.size = [[self view] frame].size; inViewFrame.origin.y = +inViewFrame.size.height; [[accountSetup view] setFrame:inViewFrame]; [[self view] addSubview:[accountSetup view]]; @@ -60,4 +117,100 @@ [[theAccountSetup view] removeFromSuperview]; [theAccountSetup release]; } + +- (void)showReverseLookupWithNumber:(NSString *)theNumber { + MGMReverseLookup *reverseLookup = [[MGMReverseLookup alloc] initWithController:self]; + [reverseLookup setNumber:theNumber]; + CGRect inViewFrame = [[reverseLookup view] frame]; + inViewFrame.size = [[self view] frame].size; + inViewFrame.origin.y = +inViewFrame.size.height; + [[reverseLookup view] setFrame:inViewFrame]; + [[self view] addSubview:[reverseLookup view]]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [[reverseLookup view] frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [[reverseLookup view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissReverseLookup:(MGMReverseLookup *)theReverseLookup { + [UIView beginAnimations:nil context:theReverseLookup]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:reverseLookup:)]; + CGRect outViewFrame = [[theReverseLookup view] frame]; + outViewFrame.origin.y = +outViewFrame.size.height; + [[theReverseLookup view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished reverseLookup:(MGMReverseLookup *)theReverseLookup { + [[theReverseLookup view] removeFromSuperview]; + [theReverseLookup release]; +} + +- (void)showMultiSMSWithInstance:(MGMInstance *)theInstance { + MGMVoiceMultiSMS *multiSMS = [[MGMVoiceMultiSMS alloc] initWithInstance:theInstance controller:self]; + CGRect inViewFrame = [[multiSMS view] frame]; + inViewFrame.size = [[self view] frame].size; + inViewFrame.origin.y = +inViewFrame.size.height; + [[multiSMS view] setFrame:inViewFrame]; + [[self view] addSubview:[multiSMS view]]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [[multiSMS view] frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [[multiSMS view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissMultiSMS:(MGMVoiceMultiSMS *)theMultiSMS { + [UIView beginAnimations:nil context:theMultiSMS]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:reverseLookup:)]; + CGRect outViewFrame = [[theMultiSMS view] frame]; + outViewFrame.origin.y = +outViewFrame.size.height; + [[theMultiSMS view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished multiSMS:(MGMVoiceMultiSMS *)theMultiSMS { + [[theMultiSMS view] removeFromSuperview]; + [theMultiSMS release]; +} + +#if MGMSIPENABLED +- (void)showCallView:(MGMSIPCallView *)theCallView { + CGRect inViewFrame = [[theCallView view] frame]; + inViewFrame.size = [[self view] frame].size; + inViewFrame.origin.y = +inViewFrame.size.height; + [[theCallView view] setFrame:inViewFrame]; + [[self view] addSubview:[theCallView view]]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.3]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [[theCallView view] frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [[theCallView view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissCallView:(MGMSIPCallView *)theCallView { + [theCallView retain]; + [UIView beginAnimations:nil context:theCallView]; + [UIView setAnimationDuration:0.3]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:callView:)]; + CGRect outViewFrame = [[theCallView view] frame]; + outViewFrame.origin.y = +outViewFrame.size.height; + [[theCallView view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished callView:(MGMSIPCallView *)theCallView { + [[theCallView view] removeFromSuperview]; + [theCallView release]; +} +#endif @end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMGContactUser.h b/Classes/VoiceMob/MGMGContactUser.h new file mode 100644 index 0000000..488470f --- /dev/null +++ b/Classes/VoiceMob/MGMGContactUser.h @@ -0,0 +1,25 @@ +// +// MGMGContactUser.h +// VoiceMob +// +// Created by Mr. Gecko on 11/9/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +@class MGMAccountController, MGMUser; + +@interface MGMGContactUser : NSObject { + MGMAccountController *accountController; + MGMUser *user; +} ++ (id)gContactUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController; +- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController; + +- (MGMAccountController *)accountController; +- (MGMUser *)user; + +- (UIView *)view; +- (void)releaseView; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMGContactUser.m b/Classes/VoiceMob/MGMGContactUser.m new file mode 100644 index 0000000..3d9ed2a --- /dev/null +++ b/Classes/VoiceMob/MGMGContactUser.m @@ -0,0 +1,47 @@ +// +// MGMGContactUser.m +// VoiceMob +// +// Created by Mr. Gecko on 11/9/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMGContactUser.h" +#import "MGMAccountController.h" +#import +#import + +@implementation MGMGContactUser ++ (id)gContactUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController { + return [[[self alloc] initWithUser:theUser accountController:theAccountController] autorelease]; +} +- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController { + if ((self = [super init])) { + accountController = theAccountController; + user = [theUser retain]; + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [user release]; + [super dealloc]; +} + +- (MGMAccountController *)accountController { + return accountController; +} +- (MGMUser *)user { + return user; +} + +- (UIView *)view { + return nil; +} +- (void)releaseView { + +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMReverseLookup.h b/Classes/VoiceMob/MGMReverseLookup.h new file mode 100644 index 0000000..ab16b7d --- /dev/null +++ b/Classes/VoiceMob/MGMReverseLookup.h @@ -0,0 +1,45 @@ +// +// MGMReverseLookup.h +// VoiceMob +// +// Created by Mr. Gecko on 10/5/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +#define MGMMKEnabled 1 + +@class MGMController, MGMURLConnectionManager, MKMapView; + +@interface MGMReverseLookup : NSObject { + MGMController *controller; + MGMURLConnectionManager *connectionManager; + + NSString *currentNumber; +#if !MGMMKEnabled + BOOL mapLoaded; + NSString *mapCall; +#endif + + IBOutlet UIView *view; + IBOutlet UITextView *RLName; + IBOutlet UITextView *RLAddress; + IBOutlet UITextView *RLCityState; + IBOutlet UITextView *RLZipCode; + IBOutlet UITextView *RLPhoneNumber; +#if MGMMKEnabled + IBOutlet MKMapView *map; +#else + IBOutlet UIWebView *RLMap; +#endif +} +- (id)initWithController:(MGMController *)theController; + +- (MGMController *)controller; +- (UIView *)view; + +- (void)setNumber:(NSString *)theNumber; + +- (IBAction)close:(id)sender; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMReverseLookup.m b/Classes/VoiceMob/MGMReverseLookup.m new file mode 100644 index 0000000..9703f34 --- /dev/null +++ b/Classes/VoiceMob/MGMReverseLookup.m @@ -0,0 +1,237 @@ +// +// MGMReverseLookup.m +// VoiceMob +// +// Created by Mr. Gecko on 10/5/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMReverseLookup.h" +#import "MGMController.h" +#import "MGMVMAddons.h" +#if MGMMKEnabled +#import +#endif +#import +#import + +#if MGMMKEnabled +@interface MGMMapPin : NSObject { + CLLocationCoordinate2D coordinate; + NSString *title; + NSString *subtitle; +} +- (CLLocationCoordinate2D)coordinate; +- (void)setCoordinate:(CLLocationCoordinate2D)theCoordinate; + +- (NSString *)title; +- (void)setTitle:(NSString *)theTitle; +- (NSString *)subtitle; +- (void)setSubtitle:(NSString *)theTitle; +@end + +@implementation MGMMapPin +- (void)dealloc { + [title release]; + [subtitle release]; + [super dealloc]; +} +- (CLLocationCoordinate2D)coordinate { + return coordinate; +} +- (void)setCoordinate:(CLLocationCoordinate2D)theCoordinate { + coordinate = theCoordinate; +} + +- (NSString *)title { + return title; +} +- (void)setTitle:(NSString *)theTitle { + [title release]; + title = [theTitle copy]; +} +- (NSString *)subtitle { + return subtitle; +} +- (void)setSubtitle:(NSString *)theTitle { + [subtitle release]; + subtitle = [theTitle copy]; +} +@end +#endif + +NSString * const MGMRLLoading = @"Loading..."; + +@implementation MGMReverseLookup +- (id)initWithController:(MGMController *)theController { + if ((self = [super init])) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"ReverseLookup"] owner:self options:nil]) { + NSLog(@"Unable to load Reverse Lookup"); + [self release]; + self = nil; + } else { + controller = theController; + connectionManager = [MGMURLConnectionManager new]; +#if !MGMMKEnabled + mapLoaded = NO; + [RLMap setDelegate:self]; + [RLMap loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"map" ofType:@"html"]]]]; +#endif + } + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [connectionManager cancelAll]; + [connectionManager release]; + [currentNumber release]; + [view release]; + [RLName release]; + [RLAddress release]; + [RLCityState release]; + [RLZipCode release]; + [RLPhoneNumber release]; +#if MGMMKEnabled + [map release]; +#else + [RLMap release]; + [mapCall release]; +#endif + [super dealloc]; +} + +- (MGMController *)controller { + return controller; +} +- (UIView *)view { + return view; +} + +- (void)setNumber:(NSString *)theNumber { + [currentNumber release]; + currentNumber = [theNumber copy]; + [RLPhoneNumber setText:[currentNumber readableNumber]]; + MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:currentNumber delegate:self]; + [connectionManager addHandler:handler]; + [RLName setText:MGMRLLoading]; + [RLAddress setText:MGMRLLoading]; + [RLCityState setText:MGMRLLoading]; + [RLZipCode setText:MGMRLLoading]; +} +- (void)reverseLookup:(MGMWhitePagesHandler *)theHandler didFailWithError:(NSError *)theError { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Reverse Lookup Failed"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; +} +- (void)reverseLookupDidFindInfo:(MGMWhitePagesHandler *)theHandler { + if ([theHandler name]!=nil) { + [RLName setText:[theHandler name]]; + } else { + [RLName setText:@""]; + } + if ([theHandler address]!=nil) { + [RLAddress setText:[theHandler address]]; + } else { + [RLAddress setText:@""]; + } + if ([theHandler location]!=nil) { + [RLCityState setText:[theHandler location]]; + } else { + [RLCityState setText:@""]; + } + if ([theHandler zip]!=nil) { + [RLZipCode setText:[theHandler zip]]; + } else { + [RLZipCode setText:@""]; + } + if ([theHandler phoneNumber]!=nil) { + [RLPhoneNumber setText:[[theHandler phoneNumber] readableNumber]]; + } else { + [RLPhoneNumber setText:@""]; + } + + int zoom = 0; + NSString *address = nil; + if ([theHandler address]!=nil) { + address = [NSString stringWithFormat:@"%@, %@", [theHandler address], [theHandler zip]]; + zoom = 15; + } else if ([theHandler zip]!=nil) { + address = [theHandler zip]; + zoom = 13; + } else if ([theHandler location]!=nil) { + address = [theHandler location]; + zoom = 13; + } else if ([theHandler latitude]!=nil && [theHandler longitude]!=nil) { + address = [NSString stringWithFormat:@"%@, %@", [theHandler latitude], [theHandler longitude]]; + zoom = 13; + } + +#if MGMMKEnabled + double latitude = 0.0; + double longitude = 0.0; + if (address!=nil && [theHandler latitude]==nil) { + NSData *geocodeData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false", [address addPercentEscapes]]]]; + if (geocodeData!=nil) { + NSDictionary *geocode = [geocodeData parseJSON]; + if ([[geocode objectForKey:@"status"] isEqual:@"OK"]) { + NSDictionary *location = [[[[geocode objectForKey:@"results"] objectAtIndex:0] objectForKey:@"geometry"] objectForKey:@"location"]; + latitude = [[location objectForKey:@"lat"] doubleValue]; + longitude = [[location objectForKey:@"lng"] doubleValue]; + } + } + } else { + latitude = [[theHandler latitude] doubleValue]; + longitude = [[theHandler longitude] doubleValue]; + } + + if (latitude!=0.0 || longitude!=0.0) { + CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude); + double span = (zoom==15 ? 0.002 : 0.3); + [map setRegion:MKCoordinateRegionMake(coordinate, MKCoordinateSpanMake(span, span))]; + MGMMapPin *pin = [[MGMMapPin new] autorelease]; + [pin setCoordinate:coordinate]; + if ([theHandler name]!=nil) + [pin setTitle:[theHandler name]]; + else if (address!=nil) + [pin setTitle:address]; + if ([pin title]!=nil) { + [pin setSubtitle:[currentNumber readableNumber]]; + } else { + [pin setTitle:[currentNumber readableNumber]]; + [pin setSubtitle:[NSString stringWithFormat:@"%lf, %lf", coordinate.latitude, coordinate.longitude]]; + } + [map addAnnotation:pin]; + } +#else + if (address!=nil && !mapLoaded) { + [mapCall release]; + mapCall = [[NSString stringWithFormat:@"showAddress('%@', %d);", [address javascriptEscape], zoom] retain]; + } else if (address!=nil) { + [RLMap stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"showAddress('%@', %d);", [address javascriptEscape], zoom]]; + } +#endif +} +#if !MGMMKEnabled +- (void)webViewDidFinishLoad:(UIWebView *)webView { + mapLoaded = YES; + if (mapCall!=nil) { + [RLMap stringByEvaluatingJavaScriptFromString:mapCall]; + [mapCall release]; + mapCall = nil; + } +} +#endif + +- (IBAction)close:(id)sender { +#if !MGMMKEnabled + [RLMap setDelegate:nil]; +#endif + [connectionManager cancelAll]; + [controller dismissReverseLookup:self]; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMVMAddons.h b/Classes/VoiceMob/MGMVMAddons.h index dc18c1c..38ee2c9 100644 --- a/Classes/VoiceMob/MGMVMAddons.h +++ b/Classes/VoiceMob/MGMVMAddons.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import @@ -13,6 +13,10 @@ - (NSString *)appendDeviceSuffixToString:(NSString *)theString; @end +@interface UIScreen (MGMVMAddons) +- (BOOL)isRetina; +@end + @interface UIColor (MGMVMAddons) - (UIColor *)colorWithDifference:(CGFloat)theDifference; @end \ No newline at end of file diff --git a/Classes/VoiceMob/MGMVMAddons.m b/Classes/VoiceMob/MGMVMAddons.m index ea0f83a..ba87c75 100644 --- a/Classes/VoiceMob/MGMVMAddons.m +++ b/Classes/VoiceMob/MGMVMAddons.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMVMAddons.h" @@ -22,6 +22,12 @@ } @end +@implementation UIScreen (MGMVMAddons) +- (BOOL)isRetina { + return ([self respondsToSelector:@selector(scale)] && [self scale]==2); +} +@end + @implementation UIColor (MGMVMAddons) - (UIColor *)colorWithDifference:(CGFloat)theDifference { CGColorRef colorRef = [self CGColor]; diff --git a/Classes/VoiceMob/SIP/MGMSIPCallView.h b/Classes/VoiceMob/SIP/MGMSIPCallView.h new file mode 100644 index 0000000..4cc713c --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPCallView.h @@ -0,0 +1,77 @@ +// +// MGMSIPCallView.h +// VoiceMob +// +// Created by Mr. Gecko on 10/9/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#if MGMSIPENABLED +#import + +@class MGMSIPCall, MGMSIPAccount, MGMSIPUser, MGMURLConnectionManager, MGMSound, MGMMiddleView; + +@interface MGMSIPCallView : NSObject { + MGMSIPCall *call; + MGMSIPAccount *account; + MGMSIPUser *SIPUser; + MGMURLConnectionManager *connectionManager; + + IBOutlet UIView *backgroundView; + IBOutlet UIImageView *iImageView; + + IBOutlet UIView *incomingView; + IBOutlet UILabel *iPhoneField; + IBOutlet UILabel *iNameField; + NSString *fullName; + NSString *phoneNumber; + + MGMSound *ringtone; + + NSDate *startTime; + NSTimer *durationUpdater; + + BOOL answered; + + IBOutlet UIView *callView; + IBOutlet UIScrollView *scrollView; + IBOutlet UILabel *phoneField; + IBOutlet UILabel *nameField; + IBOutlet UILabel *durationField; + IBOutlet UILabel *statusField; + IBOutlet MGMMiddleView *optionsView; + IBOutlet MGMMiddleView *keypadView; + IBOutlet UISlider *volumeSlider; + IBOutlet UISlider *micVolumeSlider; + IBOutlet UIButton *sound1Button; + IBOutlet UIButton *sound2Button; + IBOutlet UIButton *sound3Button; + IBOutlet UIButton *sound4Button; + IBOutlet UIButton *sound5Button; + IBOutlet UIButton *holdButton; +} ++ (id)viewWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser; +- (id)initWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser; + +- (MGMSIPUser *)SIPUser; +- (MGMSIPCall *)call; +- (BOOL)didAnswer; + +- (UIView *)view; + +- (void)startDurationTimer; + +- (void)fillCallView; + +- (IBAction)answer:(id)sender; +- (IBAction)ignore:(id)sender; + +- (IBAction)sound:(id)sender; + +- (IBAction)volume:(id)sender; +- (IBAction)micVolume:(id)sender; + +- (IBAction)hold:(id)sender; +- (IBAction)hangUp:(id)sender; +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPCallView.m b/Classes/VoiceMob/SIP/MGMSIPCallView.m new file mode 100644 index 0000000..ab3c724 --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPCallView.m @@ -0,0 +1,429 @@ +// +// MGMSIPCallView.m +// VoiceMob +// +// Created by Mr. Gecko on 10/9/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#if MGMSIPENABLED +#import "MGMSIPCallView.h" +#import "MGMSIPUser.h" +#import "MGMSIPRecordings.h" +#import "MGMAccountController.h" +#import "MGMController.h" +#import "MGMMiddleView.h" +#import "MGMPhotoSelector.h" +#import "MGMVMAddons.h" +#import +#import + +@implementation MGMSIPCallView ++ (id)viewWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser { + return [[[self alloc] initWithCall:theCall SIPUser:theSIPUser] autorelease]; +} +- (id)initWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser { + if ((self = [super init])) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPCall"] owner:self options:nil]) { + NSLog(@"Unable to load SIP Call View"); + [self release]; + self = nil; + } else { + call = [theCall retain]; + [call setDelegate:self]; + [call setHoldMusicPath:[[[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMTCallSoundsFolder] stringByAppendingPathComponent:MGMTSSIPHoldMusic] stringByAppendingPathExtension:MGMWavExt]]; + account = [call account]; + SIPUser = theSIPUser; + answered = NO; + + UIImage *background = nil; + if ([[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom]) + background = [UIImage imageWithContentsOfFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground]]; + else + background = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"background" ofType:@"png"]]; + [iImageView setImage:background]; + + + CGSize scrollViewSize = [scrollView frame].size; + [scrollView setContentSize:CGSizeMake(scrollViewSize.width * 4, scrollViewSize.height)]; + [scrollView scrollRectToVisible:CGRectMake(scrollViewSize.width, 0, scrollViewSize.width, scrollViewSize.height) animated:NO]; + + [optionsView addButtonWithTitle:@"Keypad" imageName:@"keypad" target:self action:@selector(showKeypad:atIndex:)]; + [optionsView addButtonWithTitle:@"Record" imageName:@"record" target:self action:@selector(startRecording:atIndex:)]; + [optionsView addButtonWithTitle:@"Speaker" imageName:@"speaker" target:self action:@selector(playThroughSpeakers:atIndex:)]; + [optionsView addButtonWithTitle:@"Mute Microphone" imageName:@"mutemicrophone" target:self action:@selector(muteMicrophone:atIndex:)]; + [optionsView addButtonWithTitle:@"Mute Speaker" imageName:@"mutespeaker" target:self action:@selector(muteSpeakers:atIndex:)]; + [optionsView addButtonWithTitle:@"Sound Effects" imageName:@"soundeffects" target:self action:@selector(showSoundEffects:atIndex:)]; + + [keypadView addButtonWithTitle:nil imageName:@"n1" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"ABC" imageName:@"n2" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"DEF" imageName:@"n3" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"GHI" imageName:@"n4" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"JKL" imageName:@"n5" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"MNO" imageName:@"n6" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"PQRS" imageName:@"n7" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"TUV" imageName:@"n8" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"WXYZ" imageName:@"n9" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:nil imageName:@"n*" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:@"+" imageName:@"n0" target:self action:@selector(dial:atIndex:)]; + [keypadView addButtonWithTitle:nil imageName:@"n#" target:self action:@selector(dial:atIndex:)]; + + NSString *phoneCalling = [SIPUser phoneCalling]; + if (phoneCalling!=nil) + [[call remoteURL] setUserName:phoneCalling]; + + if ([call isIncoming] && phoneCalling==nil) { + if ([[[call remoteURL] userName] isPhone]) { + NSString *number = [[[call remoteURL] userName] phoneFormat]; + phoneNumber = [[number readableNumber] copy]; + [iPhoneField setText:phoneNumber]; + NSString *name = [[SIPUser contacts] nameForNumber:number]; + if (name==nil || [name isEqual:phoneNumber]) { + connectionManager = [MGMURLConnectionManager new]; + MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:number delegate:self]; + [connectionManager addHandler:handler]; + [iNameField setText:@"Loading..."]; + } else { + fullName = [name copy]; + [iNameField setText:fullName]; + } + } else { + phoneNumber = [[[call remoteURL] SIPAddress] copy]; + [iPhoneField setText:phoneNumber]; + if ([[call remoteURL] fullName]!=nil && ![[[call remoteURL] fullName] isEqual:@""]) { + fullName = [[[call remoteURL] fullName] copy]; + [iNameField setText:fullName]; + } else { + [iNameField setText:@"Unknown"]; + } + } + [backgroundView addSubview:incomingView]; + [call sendRingingNotification]; + NSString *ringtonePath = [[[[SIPUser accountController] controller] themeManager] currentSoundPath:MGMTSSIPRingtone]; + if (ringtonePath!=nil && ![ringtonePath isEqual:MGMTNoSound]) { + ringtone = [[MGMSound alloc] initWithContentsOfFile:ringtonePath]; + [ringtone setLoops:YES]; + [ringtone play]; + } + } else { + if ([[[call remoteURL] userName] isPhone]) { + NSString *number = [[[call remoteURL] userName] phoneFormat]; + phoneNumber = [[number readableNumber] copy]; + NSString *name = [[SIPUser contacts] nameForNumber:number]; + if (name==nil || [name isEqual:phoneNumber]) { + connectionManager = [MGMURLConnectionManager new]; + MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:number delegate:self]; + [connectionManager addHandler:handler]; + } else { + fullName = [name copy]; + } + } else { + phoneNumber = [[[call remoteURL] SIPAddress] copy]; + if ([[call remoteURL] fullName]!=nil && ![[[call remoteURL] fullName] isEqual:@""]) + fullName = [[[call remoteURL] fullName] copy]; + } + [self fillCallView]; + if (phoneCalling!=nil) + [call answer]; + [backgroundView addSubview:callView]; + } + + if ([call state]==MGMSIPCallDisconnectedState) { + [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]; + [notificationCenter addObserver:self selector:@selector(micVolumeChanged:) name:MGMSIPMicVolumeChangedNotification object:nil]; + } + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [call setDelegate:nil]; + [call release]; + [connectionManager cancelAll]; + [connectionManager release]; + [fullName release]; + [phoneNumber release]; + [ringtone stop]; + [ringtone release]; + [durationUpdater invalidate]; + [durationUpdater release]; + [startTime release]; + [backgroundView release]; + [iImageView release]; + [incomingView release]; + [iPhoneField release]; + [iNameField release]; + [callView release]; + [scrollView release]; + [phoneField release]; + [nameField release]; + [durationField release]; + [statusField release]; + [optionsView release]; + [keypadView release]; + [volumeSlider release]; + [micVolumeSlider release]; + [sound1Button release]; + [sound2Button release]; + [sound3Button release]; + [sound4Button release]; + [sound5Button release]; + [holdButton release]; + [super dealloc]; +} + +- (MGMSIPUser *)SIPUser { + return SIPUser; +} +- (MGMSIPCall *)call { + return call; +} +- (BOOL)didAnswer { + return answered; +} + +- (UIView *)view { + return backgroundView; +} + +- (void)disconnected:(MGMSIPCall *)theCall { + [ringtone stop]; + [ringtone release]; + ringtone = nil; + if ([callView superview]!=nil) { + [durationUpdater invalidate]; + [durationUpdater release]; + durationUpdater = nil; + [startTime release]; + startTime = nil; + [statusField performSelectorOnMainThread:@selector(setText:) withObject:@"Disconnected" waitUntilDone:NO]; + [[[[SIPUser accountController] controller] themeManager] playSound:MGMTSSIPDisconnected]; + } else { + [ringtone stop]; + [ringtone release]; + ringtone = nil; + [SIPUser callDone:self]; + } +} +- (void)confirmed:(MGMSIPCall *)theCall { + [statusField performSelectorOnMainThread:@selector(setText:) withObject:@"Connected" waitUntilDone:NO]; + [[[[SIPUser accountController] controller] themeManager] playSound:MGMTSSIPConnected]; + [self performSelectorOnMainThread:@selector(startDurationTimer) withObject:nil waitUntilDone:NO]; +} +- (void)startDurationTimer { + startTime = [NSDate new]; + durationUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateDuration) userInfo:nil repeats:YES] retain]; +} + +- (void)soundChanged:(NSNotification *)theNotification { + if ([[theNotification object] isEqual:MGMTSSIPSound1]) + [sound1Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound1] forState:UIControlStateNormal]; + if ([[theNotification object] isEqual:MGMTSSIPSound2]) + [sound2Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound2] forState:UIControlStateNormal]; + if ([[theNotification object] isEqual:MGMTSSIPSound3]) + [sound3Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound3] forState:UIControlStateNormal]; + if ([[theNotification object] isEqual:MGMTSSIPSound4]) + [sound4Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound4] forState:UIControlStateNormal]; + if ([[theNotification object] isEqual:MGMTSSIPSound5]) + [sound5Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound5] forState:UIControlStateNormal]; +} + +- (void)fillCallView { + if (fullName!=nil) + [nameField setText:fullName]; + else + [nameField setText:@"Unkown"]; + [phoneField setText:phoneNumber]; + [durationField setText:[NSString stringWithSeconds:0]]; + [volumeSlider setValue:[[MGMSIP sharedSIP] volume]]; + [micVolumeSlider setValue:[[MGMSIP sharedSIP] micVolume]]; + if ([call state]!=MGMSIPCallConfirmedState) + [statusField setText:@"Connecting..."]; + else + [self confirmed:call]; + + [sound1Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound1] forState:UIControlStateNormal]; + [sound2Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound2] forState:UIControlStateNormal]; + [sound3Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound3] forState:UIControlStateNormal]; + [sound4Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound4] forState:UIControlStateNormal]; + [sound5Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound5] forState:UIControlStateNormal]; +} + +- (IBAction)answer:(id)sender { + [ringtone stop]; + [ringtone release]; + ringtone = nil; + [call answer]; + [self fillCallView]; + [incomingView removeFromSuperview]; + [backgroundView addSubview:callView]; + answered = YES; +} +- (IBAction)ignore:(id)sender { + [ringtone stop]; + [ringtone release]; + ringtone = nil; + [SIPUser callDone:self]; +} + +- (void)updateDuration { + int time = [[NSDate date] timeIntervalSinceDate:startTime]; + [durationField setText:[NSString stringWithSeconds:time]]; +} + +- (void)volumeChanged:(NSNotification *)theNotification { + [volumeSlider setValue:[[theNotification object] floatValue]]; +} +- (IBAction)volume:(id)sender { + [[MGMSIP sharedSIP] setVolume:[volumeSlider value]]; +} +- (void)micVolumeChanged:(NSNotification *)theNotification { + [micVolumeSlider setValue:[[theNotification object] floatValue]]; +} +- (IBAction)micVolume:(id)sender { + [[MGMSIP sharedSIP] setMicVolume:[micVolumeSlider value]]; +} + +- (IBAction)hold:(id)sender { + [call hold]; + [holdButton setTitle:([call isLocalOnHold] ? @"Unhold" : @"Hold") forState:UIControlStateNormal]; +} +- (IBAction)hangUp:(id)sender { + [durationUpdater invalidate]; + [durationUpdater release]; + durationUpdater = nil; + [startTime release]; + startTime = nil; + [call hangUp]; + [SIPUser callDone:self]; +} + +- (void)middleViewDidCancel:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + if (theIndex==1) { + if ([call isRecording]) + [theMiddleView setHighlighted:YES forButtonAtIndex:1]; + } else if (theIndex==2) { + if ([call isOnSpeaker]) + [theMiddleView setHighlighted:YES forButtonAtIndex:2]; + } else if (theIndex==3) { + if ([call isMicMuted]) + [theMiddleView setHighlighted:YES forButtonAtIndex:3]; + } else if (theIndex==4) { + if ([call isMuted]) + [theMiddleView setHighlighted:YES forButtonAtIndex:4]; + } +} + +- (void)showKeypad:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + CGSize scrollViewSize = [scrollView frame].size; + [scrollView scrollRectToVisible:CGRectMake(scrollViewSize.width*2, 0, scrollViewSize.width, scrollViewSize.height) animated:YES]; +} + +- (void)startRecording:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + if ([call isRecording]) { + [call stopRecording]; + } else { + NSFileManager *manager = [NSFileManager defaultManager]; + NSString *baseName = [[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ - ", phoneNumber]]; + if (![manager fileExistsAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder]]) + [manager createDirectoryAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder] withIntermediateDirectories:YES attributes:nil error:nil]; + + NSString *name = nil; + for (int i=1; i<50; i++) { // Not like someone will have 50 recordings with one person on their desktop... + name = [[baseName stringByAppendingFormat:@"%02d", i] stringByAppendingPathExtension:MGMWavExt]; + if (![manager fileExistsAtPath:name]) + break; + } + [call startRecording:name]; + } + if ([call isRecording]) + [theMiddleView setHighlighted:YES forButtonAtIndex:1]; +} + +- (void)playThroughSpeakers:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + [call speaker]; + if ([call isOnSpeaker]) + [theMiddleView setHighlighted:YES forButtonAtIndex:2]; +} + +- (void)muteMicrophone:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + [call muteMic]; + if ([call isMicMuted]) + [theMiddleView setHighlighted:YES forButtonAtIndex:3]; +} +- (void)muteSpeakers:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + [call mute]; + if ([call isMuted]) + [theMiddleView setHighlighted:YES forButtonAtIndex:4]; +} + +- (void)showSoundEffects:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + CGSize scrollViewSize = [scrollView frame].size; + [scrollView scrollRectToVisible:CGRectMake(0, 0, scrollViewSize.width, scrollViewSize.height) animated:YES]; +} + +- (IBAction)sound:(id)sender { + NSString *soundName = nil; + if (sender==sound1Button) + soundName = MGMTSSIPSound1; + else if (sender==sound2Button) + soundName = MGMTSSIPSound2; + else if (sender==sound3Button) + soundName = MGMTSSIPSound3; + else if (sender==sound4Button) + soundName = MGMTSSIPSound4; + else if (sender==sound5Button) + soundName = MGMTSSIPSound5; + NSString *soundFile = [[[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMTCallSoundsFolder] stringByAppendingPathComponent:soundName] stringByAppendingPathExtension:MGMWavExt]; + [call playSound:soundFile]; + [[[[SIPUser accountController] controller] themeManager] performSelector:@selector(playSound:) withObject:soundName afterDelay:0.2]; // The phone has a delay, so why not delay this so you hear it at the same time? +} +- (void)dial:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex { + if (theIndex==0) + [call sendDTMFDigits:@"1"]; + else if (theIndex==1) + [call sendDTMFDigits:@"2"]; + else if (theIndex==2) + [call sendDTMFDigits:@"3"]; + else if (theIndex==3) + [call sendDTMFDigits:@"4"]; + else if (theIndex==4) + [call sendDTMFDigits:@"5"]; + else if (theIndex==5) + [call sendDTMFDigits:@"6"]; + else if (theIndex==6) + [call sendDTMFDigits:@"7"]; + else if (theIndex==7) + [call sendDTMFDigits:@"8"]; + else if (theIndex==8) + [call sendDTMFDigits:@"9"]; + else if (theIndex==9) + [call sendDTMFDigits:@"*"]; + else if (theIndex==10) + [call sendDTMFDigits:@"0"]; + else if (theIndex==11) + [call sendDTMFDigits:@"#"]; +} + +- (void)reverseLookupDidFindInfo:(MGMWhitePagesHandler *)theHandler forRequest:(NSDictionary *)theRequest { + if ([theHandler name]!=nil) + fullName = [[theHandler name] copy]; + else if ([theHandler location]!=nil) + fullName = [[theHandler location] copy]; + if (fullName!=nil && [callView superview]!=nil) + [nameField setText:fullName]; + else if (fullName!=nil && [incomingView superview]!=nil) + [iNameField setText:fullName]; +} +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPContacts.h b/Classes/VoiceMob/SIP/MGMSIPContacts.h new file mode 100644 index 0000000..0914f3f --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPContacts.h @@ -0,0 +1,28 @@ +// +// MGMSIPContacts.h +// VoiceMob +// +// Created by Mr. Gecko on 9/29/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#if MGMSIPENABLED +#import +#import "MGMContactsController.h" + +@class MGMSIPUser; + +@interface MGMSIPContacts : MGMContactsController { + MGMSIPUser *SIPUser; + + IBOutlet UIView *view; +} ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser; +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser; + +- (MGMSIPUser *)SIPUser; + +- (UIView *)view; +- (void)releaseView; +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPContacts.m b/Classes/VoiceMob/SIP/MGMSIPContacts.m new file mode 100644 index 0000000..8b5e718 --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPContacts.m @@ -0,0 +1,66 @@ +// +// MGMSIPContacts.m +// VoiceMob +// +// Created by Mr. Gecko on 9/29/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#if MGMSIPENABLED +#import "MGMSIPContacts.h" +#import "MGMSIPUser.h" +#import "MGMAccountController.h" +#import "MGMController.h" +#import "MGMVMAddons.h" +#import + +@implementation MGMSIPContacts ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser { + return [[[self alloc] initWithSIPUser:theSIPUser] autorelease]; +} +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser { + if ((self = [super initWithAccountController:[theSIPUser accountController]])) { + SIPUser = theSIPUser; + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [super dealloc]; +} + +- (MGMSIPUser *)SIPUser { + return SIPUser; +} +- (MGMContacts *)contacts { + return [SIPUser contacts]; +} + +- (UIView *)view { + if (view==nil) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPContacts"] owner:self options:nil]) { + NSLog(@"Unable to load SIP Contacts"); + } else { + [super awakeFromNib]; + } + } + return view; +} +- (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [view release]; + view = nil; + [super releaseView]; +} + +- (void)selectedContact:(NSDictionary *)theContact { + [SIPUser showOptionsForNumber:[theContact objectForKey:MGMCNumber]]; + [contactsTable deselectRowAtIndexPath:[contactsTable indexPathForSelectedRow] animated:YES]; +} +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPInbox.h b/Classes/VoiceMob/SIP/MGMSIPInbox.h new file mode 100644 index 0000000..9486619 --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPInbox.h @@ -0,0 +1,50 @@ +// +// MGMSIPHistory.h +// VoiceMob +// +// Created by Mr. Gecko on 10/14/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +@class MGMSIPUser, MGMLiteConnection; + +@interface MGMSIPInbox : NSObject { + MGMSIPUser *SIPUser; + MGMLiteConnection *inboxConnection; + + NSDate *lastUpdate; + + int currentView; + NSArray *inboxItems; + + IBOutlet UITableView *inboxesTable; + IBOutlet UITableView *inboxTable; + + int currentInbox; + int maxResults; + unsigned int start; + int resultsCount; + + NSMutableArray *currentData; +} ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser; +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser; + +- (void)registerSettings; + +- (MGMSIPUser *)SIPUser; + +- (UIView *)view; +- (void)releaseView; + +- (void)addPhoneNumber:(NSString *)thePhoneNumber type:(int)theType; + +- (NSArray *)dataForType:(int)theType start:(unsigned int)theStart; + +- (void)loadInbox; + +- (void)addData:(NSArray *)theData; +- (int)currentInbox; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPInbox.m b/Classes/VoiceMob/SIP/MGMSIPInbox.m new file mode 100644 index 0000000..40f186d --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPInbox.m @@ -0,0 +1,323 @@ +// +// MGMSIPHistory.m +// VoiceMob +// +// Created by Mr. Gecko on 10/14/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMSIPInbox.h" +#import "MGMSIPUser.h" +#import "MGMAccountController.h" +#import "MGMInboxMessageView.h" +#import "MGMVMAddons.h" +#import +#import + +static NSMutableArray *MGMSIPInboxItems; + +NSString * const MGMHInboxDB = @"inbox.db"; + +NSString * const MGMHInboxPlist = @"inbox.plist"; +NSString * const MGMHInbox = @"MGMHInbox"; +NSString * const MGMHStart = @"MGMHStart"; +NSString * const MGMHResultsCount = @"MGMHResultsCount"; +NSString * const MGMHLastUpdate = @"MGMHLastUpdate"; + +NSString * const MGMHName = @"name"; +NSString * const MGMHID = @"id"; + +NSString * const MGMSIPInboxesCellIdentifier = @"MGMSIPInboxesCellIdentifier"; +NSString * const MGMSIPInboxMessageCellIdentifier = @"MGMSIPInboxMessageCellIdentifier"; +NSString * const MGMSIPInboxMessageLoadCellIdentifier = @"MGMSIPInboxMessageLoadCellIdentifier"; + +@implementation MGMSIPInbox ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser { + return [[[self alloc] initWithSIPUser:theSIPUser] autorelease]; +} +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser { + if ((self = [super init])) { + if (MGMSIPInboxItems==nil) { + MGMSIPInboxItems = [NSMutableArray new]; + [MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Inbox", MGMHName, [NSNumber numberWithInt:0], MGMHID, nil]]; + [MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Placed", MGMHName, [NSNumber numberWithInt:1], MGMHID, nil]]; + [MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Received", MGMHName, [NSNumber numberWithInt:2], MGMHID, nil]]; + [MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Missed", MGMHName, [NSNumber numberWithInt:3], MGMHID, nil]]; + } + SIPUser = theSIPUser; + + BOOL buildDB = ![[NSFileManager defaultManager] fileExistsAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxDB]]; + inboxConnection = [[MGMLiteConnection connectionWithPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxDB]] retain]; + //[inboxConnection setLogQuery:YES]; + if (buildDB) + [inboxConnection query:@"CREATE TABLE inbox (id INTEGER PRIMARY KEY AUTOINCREMENT, type INTEGER, isRead INTEGER, time INTEGER, phoneNumber TEXT)"]; + + [self registerSettings]; + + lastUpdate = [[[SIPUser user] settingForKey:MGMHLastUpdate] retain]; + + currentView = 1; + currentInbox = [[[SIPUser user] settingForKey:MGMHInbox] intValue]; + maxResults = 10; + start = [[[SIPUser user] settingForKey:MGMHStart] intValue]; + resultsCount = [[[SIPUser user] settingForKey:MGMHResultsCount] intValue]; + inboxItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inboxes" style:UIBarButtonItemStyleBordered target:self action:@selector(showInboxes:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[SIPUser accountController] action:@selector(showSettings:)] autorelease], nil] retain]; + currentData = [NSMutableArray new]; + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [inboxConnection release]; + [lastUpdate release]; + [inboxItems release]; + [currentData release]; + [super dealloc]; +} + +- (void)registerSettings { + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMHInbox]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMHResultsCount]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMHStart]; + [[SIPUser user] registerSettings:settings]; +} + +- (MGMSIPUser *)SIPUser { + return SIPUser; +} + +- (UIView *)view { + if (inboxesTable==nil) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPInbox"] owner:self options:nil]) { + NSLog(@"Unable to load SIP Inbox"); + } else { + if (start==0 || lastUpdate==nil || [lastUpdate earlierDate:[NSDate dateWithTimeIntervalSinceNow:-300]]==lastUpdate) { + start = 0; + resultsCount = 0; + [self loadInbox]; + } else if ([currentData count]<=0 && [[NSFileManager defaultManager] fileExistsAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxPlist]]) { + [currentData addObjectsFromArray:[NSArray arrayWithContentsOfFile:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxPlist]]]; + } + if (currentView==1) + [[SIPUser accountController] setItems:inboxItems animated:YES]; + else + [[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES]; + } + } + if (currentView==1) + return inboxTable; + return inboxesTable; +} +- (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [inboxesTable release]; + inboxesTable = nil; + [inboxTable release]; + inboxTable = nil; + if (start!=0) { + [currentData writeToFile:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxPlist] atomically:YES]; + [currentData removeAllObjects]; + } +} + +- (void)addPhoneNumber:(NSString *)thePhoneNumber type:(int)theType { + [inboxConnection query:@"INSERT INTO inbox (type, isRead, time, phoneNumber) VALUES (%d, %d, %qu, %@)", theType, (theType==MGMIMissedType ? 0 : 1), (unsigned long long)[[NSDate date] timeIntervalSince1970], thePhoneNumber]; +} + +- (IBAction)showInboxes:(id)sender { + CGRect outViewFrame = [inboxTable frame]; + CGRect inViewFrame = [inboxesTable frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = -inViewFrame.size.width; + [inboxesTable setFrame:inViewFrame]; + [[SIPUser tabView] addSubview:inboxesTable]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(inboxesAnimationDidStop:finished:context:)]; + [inboxesTable setFrame:outViewFrame]; + outViewFrame.origin.x = +outViewFrame.size.width; + [inboxTable setFrame:outViewFrame]; + [UIView commitAnimations]; + [[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES]; + currentView = 0; +} +- (void)inboxesAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [inboxTable removeFromSuperview]; + currentInbox = -1; + start = 0; + resultsCount = 0; + [currentData removeAllObjects]; + [inboxTable reloadData]; +} + +- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section { + if (theTableView==inboxesTable) + return [MGMSIPInboxItems count]; + else if (theTableView==inboxTable) + return (resultsCount==maxResults ? [currentData count]+1 : [currentData count]); + return 0; +} +- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + if (theTableView==inboxesTable) { + UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMSIPInboxesCellIdentifier]; + if (cell==nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMSIPInboxesCellIdentifier] autorelease]; + [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; + } + if ([cell respondsToSelector:@selector(textLabel)]) + [[cell textLabel] setText:[[MGMSIPInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMHName]]; + else + [cell setText:[[MGMSIPInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMHName]]; + return cell; + } else if (theTableView==inboxTable) { + if ([currentData count]<=[indexPath indexAtPosition:1]) { + UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMSIPInboxMessageLoadCellIdentifier]; + if (cell==nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMSIPInboxMessageLoadCellIdentifier] autorelease]; + NSString *text = @"Load More..."; + if ([cell respondsToSelector:@selector(textLabel)]) { + [[cell textLabel] setText:text]; + [[cell textLabel] setTextColor:[UIColor blueColor]]; + [[cell textLabel] setTextAlignment:UITextAlignmentCenter]; + } else { + [cell setText:text]; + [cell setTextColor:[UIColor blueColor]]; + [cell setTextAlignment:UITextAlignmentCenter]; + } + } + return cell; + } else { + MGMInboxMessageView *cell = (MGMInboxMessageView *)[inboxTable dequeueReusableCellWithIdentifier:MGMSIPInboxMessageCellIdentifier]; + if (cell==nil) { + cell = [[[MGMInboxMessageView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMSIPInboxMessageCellIdentifier] autorelease]; + [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; + [cell setInstance:(MGMInstance *)SIPUser]; + } + [cell setMessageData:[currentData objectAtIndex:[indexPath indexAtPosition:1]]]; + return cell; + } + } + return nil; +} +- (BOOL)tableView:(UITableView *)theTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + if (theTableView==inboxesTable) + return NO; + return YES; +} +- (UITableViewCellEditingStyle)tableView:(UITableView *)theTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewCellEditingStyleDelete; +} +- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { + return @"Delete"; +} +- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + NSDictionary *data = [currentData objectAtIndex:[indexPath indexAtPosition:1]]; + [inboxConnection query:@"DELETE FROM inbox WHERE id=%@", [data objectForKey:MGMHID]]; + [currentData removeObjectAtIndex:[indexPath indexAtPosition:1]]; + [inboxTable reloadData]; + +} +- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if (theTableView==inboxesTable) { + currentInbox = [[[MGMSIPInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMHID] intValue]; + [[SIPUser user] setSetting:[NSNumber numberWithInt:currentInbox] forKey:MGMHInbox]; + [[inboxItems objectAtIndex:0] setEnabled:NO]; + [[SIPUser accountController] setItems:inboxItems animated:YES]; + + CGRect outViewFrame = [inboxesTable frame]; + CGRect inViewFrame = [inboxTable frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = +inViewFrame.size.width; + [inboxTable setFrame:inViewFrame]; + [[SIPUser tabView] addSubview:inboxTable]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(inboxAnimationDidStop:finished:context:)]; + [inboxTable setFrame:outViewFrame]; + outViewFrame.origin.x = -outViewFrame.size.width; + [inboxesTable setFrame:outViewFrame]; + [UIView commitAnimations]; + currentView = 1; + [self loadInbox]; + } else if (theTableView==inboxTable) { + if ([indexPath indexAtPosition:1]>=[currentData count]) { + start += maxResults; + [self loadInbox]; + } else { + NSMutableDictionary *data = [[[currentData objectAtIndex:[indexPath indexAtPosition:1]] mutableCopy] autorelease]; + if (![[data objectForKey:MGMIRead] boolValue]) { + [inboxConnection query:@"UPDATE inbox SET isRead=1 WHERE id=%@", [data objectForKey:MGMHID]]; + [data setObject:[NSNumber numberWithBool:![[data objectForKey:MGMIRead] boolValue]] forKey:MGMIRead]; + [currentData replaceObjectAtIndex:[indexPath indexAtPosition:1] withObject:data]; + [inboxTable reloadData]; + } + [SIPUser showOptionsForNumber:[data objectForKey:MGMIPhoneNumber]]; + [inboxTable deselectRowAtIndexPath:[inboxTable indexPathForSelectedRow] animated:YES]; + } + } +} +- (void)inboxAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [inboxesTable removeFromSuperview]; + [inboxesTable deselectRowAtIndexPath:[inboxesTable indexPathForSelectedRow] animated:NO]; + [[inboxItems objectAtIndex:0] setEnabled:YES]; +} + +- (NSArray *)dataForType:(int)theType start:(unsigned int)theStart { + MGMLiteResult *result = nil; + if (theType==-1) + result = [inboxConnection query:@"SELECT * FROM inbox ORDER BY id DESC LIMIT %u, %d", theStart, maxResults]; + else + result = [inboxConnection query:@"SELECT * FROM inbox WHERE type = %d ORDER BY id DESC LIMIT %u, %d", theType, theStart, maxResults]; + NSMutableArray *data = [NSMutableArray array]; + NSDictionary *thisData = nil; + while ((thisData=[result nextRow])!=nil) { + NSMutableDictionary *dataDic = [NSMutableDictionary dictionaryWithDictionary:thisData]; + [dataDic setObject:[NSDate dateWithTimeIntervalSince1970:[[thisData objectForKey:MGMITime] unsignedLongLongValue]] forKey:MGMITime]; + [data addObject:dataDic]; + } + return data; +} + +- (void)loadInbox { + [lastUpdate release]; + lastUpdate = [NSDate new]; + [[SIPUser user] setSetting:lastUpdate forKey:MGMHLastUpdate]; + [[SIPUser user] setSetting:[NSNumber numberWithInt:start] forKey:MGMHStart]; + NSArray *data = nil; + switch (currentInbox) { + case 0: + data = [self dataForType:-1 start:start]; + break; + case 1: + data = [self dataForType:MGMIPlacedType start:start]; + break; + case 2: + data = [self dataForType:MGMIReceivedType start:start]; + break; + case 3: + data = [self dataForType:MGMIMissedType start:start]; + break; + } + [self addData:data]; +} + +- (void)addData:(NSArray *)theData { + resultsCount = [theData count]; + [[SIPUser user] setSetting:[NSNumber numberWithInt:resultsCount] forKey:MGMHResultsCount]; + [currentData addObjectsFromArray:theData]; + [inboxTable reloadData]; +} +- (int)currentInbox { + return currentInbox; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPPad.h b/Classes/VoiceMob/SIP/MGMSIPPad.h new file mode 100644 index 0000000..9348943 --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPPad.h @@ -0,0 +1,56 @@ +// +// MGMSIPPad.h +// VoiceMob +// +// Created by Mr. Gecko on 9/29/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#if MGMSIPENABLED +#import + +@class MGMSIPUser, MGMNumberView; + +@interface MGMSIPPad : NSObject { + MGMSIPUser *SIPUser; + + IBOutlet UIView *view; + + UITextField *keyboard; + BOOL keyboardInput; + IBOutlet UIButton *closeKeyboardButon; + + NSString *numberString; + IBOutlet MGMNumberView *numberView; + IBOutlet MGMNumberView *number1View; + IBOutlet MGMNumberView *number2View; + IBOutlet MGMNumberView *number3View; + IBOutlet MGMNumberView *number4View; + IBOutlet MGMNumberView *number5View; + IBOutlet MGMNumberView *number6View; + IBOutlet MGMNumberView *number7View; + IBOutlet MGMNumberView *number8View; + IBOutlet MGMNumberView *number9View; + IBOutlet MGMNumberView *numberStarView; + IBOutlet MGMNumberView *number0View; + IBOutlet MGMNumberView *numberPondView; + IBOutlet MGMNumberView *numberKeyboardView; + IBOutlet MGMNumberView *numberCallView; + IBOutlet MGMNumberView *numberDeleteView; +} ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser; +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser; + +- (MGMSIPUser *)SIPUser; + +- (UIView *)view; +- (void)releaseView; + +- (IBAction)numberDecide:(id)sender; +- (IBAction)dial:(id)sender; +- (IBAction)delete:(id)sender; +- (IBAction)call:(id)sender; +- (IBAction)showKeyboard:(id)sender; +- (IBAction)hideKeyboard:(id)sender; +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPPad.m b/Classes/VoiceMob/SIP/MGMSIPPad.m new file mode 100644 index 0000000..b6d343e --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPPad.m @@ -0,0 +1,247 @@ +// +// MGMSIPPad.m +// VoiceMob +// +// Created by Mr. Gecko on 9/29/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#if MGMSIPENABLED +#import "MGMSIPPad.h" +#import "MGMSIPUser.h" +#import "MGMAccountController.h" +#import "MGMController.h" +#import "MGMNumberView.h" +#import "MGMVMAddons.h" +#import + +@implementation MGMSIPPad ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser { + return [[[self alloc] initWithSIPUser:theSIPUser] autorelease]; +} +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser { + if ((self = [super init])) { + SIPUser = theSIPUser; + keyboardInput = NO; + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [numberString release]; + [super dealloc]; +} + +- (MGMSIPUser *)SIPUser { + return SIPUser; +} + +- (UIView *)view { + if (view==nil) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPPad"] owner:self options:nil]) { + NSLog(@"Unable to load SIP Pad"); + } else { + keyboard = [[UITextField alloc] initWithFrame:CGRectMake(-22, -22, 22, 22)]; + [keyboard setDelegate:self]; + [keyboard setReturnKeyType:UIReturnKeyDone]; + [keyboard setAutocapitalizationType:UITextAutocapitalizationTypeNone]; + [keyboard setText:@" "]; + [view addSubview:keyboard]; + [closeKeyboardButon setHidden:YES]; + + if (numberString!=nil) + [numberView setNumber:numberString]; + else + [numberView setNumber:@""]; + [numberView setStartColor:[UIColor colorWithRed:0.19 green:0.22 blue:0.37 alpha:1.0]]; + [numberView setEndColor:[UIColor colorWithRed:0.04 green:0.16 blue:0.33 alpha:1.0]]; + [numberView setGlass:YES]; + [number1View setNumber:@"1"]; + [number1View setAlphabet:@""]; + [number2View setNumber:@"2"]; + [number2View setAlphabet:@"ABC"]; + [number3View setNumber:@"3"]; + [number3View setAlphabet:@"DEF"]; + [number4View setNumber:@"4"]; + [number4View setAlphabet:@"GHI"]; + [number5View setNumber:@"5"]; + [number5View setAlphabet:@"JKL"]; + [number6View setNumber:@"6"]; + [number6View setAlphabet:@"MNO"]; + [number7View setNumber:@"7"]; + [number7View setAlphabet:@"PQRS"]; + [number8View setNumber:@"8"]; + [number8View setAlphabet:@"TUV"]; + [number9View setNumber:@"9"]; + [number9View setAlphabet:@"WXYZ"]; + [numberStarView setNumber:@"✱"]; + [numberStarView setAlphabet:@""]; + [number0View setNumber:@"0"]; + [number0View setAlphabet:@"+"]; + [numberPondView setNumber:@"#"]; + [numberPondView setAlphabet:@""]; + [numberKeyboardView setNumber:@"ABC"]; + UIColor *darkColor = [UIColor colorWithRed:0.02 green:0.09 blue:0.19 alpha:1.0]; + [numberKeyboardView setStartColor:darkColor]; + [numberKeyboardView setEndColor:darkColor]; + [numberKeyboardView setGlass:YES]; + [numberCallView setNumber:@"Call"]; + [numberCallView setStartColor:[UIColor colorWithRed:0.13 green:0.81 blue:0.1 alpha:1.0]]; + [numberCallView setEndColor:[UIColor colorWithRed:0.11 green:0.69 blue:0.09 alpha:1.0]]; + [numberCallView setGlass:YES]; + [numberDeleteView setImage:[[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DeleteKey" ofType:@"png"]] autorelease]]; + [numberDeleteView setStartColor:darkColor]; + [numberDeleteView setEndColor:darkColor]; + [numberDeleteView setGlass:YES]; + } + } + return view; +} +- (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [view release]; + view = nil; + [keyboard release]; + keyboard = nil; + [closeKeyboardButon release]; + closeKeyboardButon = nil; + [numberView release]; + numberView = nil; + [number1View release]; + number1View = nil; + [number2View release]; + number2View = nil; + [number3View release]; + number3View = nil; + [number4View release]; + number4View = nil; + [number5View release]; + number5View = nil; + [number6View release]; + number6View = nil; + [number7View release]; + number7View = nil; + [number8View release]; + number8View = nil; + [number9View release]; + number9View = nil; + [numberStarView release]; + numberStarView = nil; + [number0View release]; + number0View = nil; + [numberPondView release]; + numberPondView = nil; + [numberKeyboardView release]; + numberKeyboardView = nil; + [numberCallView release]; + numberCallView = nil; + [numberDeleteView release]; + numberDeleteView = nil; +} + +- (IBAction)numberDecide:(id)sender { + UIActionSheet *theAction = [[UIActionSheet new] autorelease]; + [theAction addButtonWithTitle:@"Copy"]; + BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil); + if (pasteEnabled) + [theAction addButtonWithTitle:@"Paste"]; + [theAction addButtonWithTitle:@"Reverse Lookup"]; + [theAction addButtonWithTitle:@"Cancel"]; + [theAction setCancelButtonIndex:(pasteEnabled ? 3 : 2)]; + [theAction setDelegate:self]; + [theAction showInView:[SIPUser view]]; +} +- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { + BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil); + if (buttonIndex==0) { + [[UIPasteboard generalPasteboard] setString:numberString]; + } else if (pasteEnabled && buttonIndex==1) { + [numberString release]; + keyboardInput = ![[[UIPasteboard generalPasteboard] string] isPhoneComplete]; + numberString = [(keyboardInput ? [[UIPasteboard generalPasteboard] string] : [[[UIPasteboard generalPasteboard] string] readableNumber]) copy]; + [numberView setNumber:numberString]; + } else if ((pasteEnabled && buttonIndex==2) || (!pasteEnabled && buttonIndex==1)) { + [[[SIPUser accountController] controller] showReverseLookupWithNumber:[numberString phoneFormatWithAreaCode:[SIPUser areaCode]]]; + } +} +- (IBAction)dial:(id)sender { + NSString *number = [numberView number]; + if ([number length]==0 && [sender tag]==0) { + [numberView setNumber:@"+"]; + } else { + NSString *numberAdd = nil; + switch ([sender tag]) { + case 10: + case 11: + break; + default: + numberAdd = [[NSNumber numberWithInt:[sender tag]] stringValue]; + break; + } + if (numberAdd!=nil) + number = [number stringByAppendingString:numberAdd]; + [numberString release]; + numberString = [(keyboardInput ? number : [number readableNumber]) copy]; + [numberView setNumber:numberString]; + } +} +- (IBAction)delete:(id)sender { + if ([numberString isEqual:@""]) + keyboardInput = NO; + NSString *number = [numberView number]; + if ([number length]!=0) { + number = [number substringToIndex:[number length]-1]; + [numberString release]; + numberString = [(keyboardInput ? number : [number readableNumber]) copy]; + [numberView setNumber:numberString]; + if ([numberString isEqual:@""]) + keyboardInput = NO; + } +} +- (IBAction)call:(id)sender { + if ([numberString isPhoneComplete]) { + [SIPUser call:[numberString phoneFormatWithAreaCode:[SIPUser areaCode]]]; + } else if (keyboardInput) { + [SIPUser call:numberString]; + } else { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Incorrect Number"]; + [alert setMessage:@"The phone number you have entered is incorrect."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } +} +- (IBAction)showKeyboard:(id)sender { + [closeKeyboardButon setHidden:NO]; + [keyboard becomeFirstResponder]; +} +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + if ([string isEqual:@""]) + [self delete:keyboard]; + keyboardInput = YES; + NSString *number = [numberView number]; + number = [number stringByAppendingString:string]; + [numberString release]; + numberString = [(keyboardInput ? number : [number readableNumber]) copy]; + [numberView setNumber:numberString]; + [keyboard setText:@" "]; + return NO; +} +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + [closeKeyboardButon setHidden:YES]; + return YES; +} +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + [keyboard resignFirstResponder]; + return NO; +} +- (IBAction)hideKeyboard:(id)sender { + [keyboard resignFirstResponder]; +} +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPRecordings.h b/Classes/VoiceMob/SIP/MGMSIPRecordings.h new file mode 100644 index 0000000..8fff5e8 --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPRecordings.h @@ -0,0 +1,41 @@ +// +// MGMSIPRecordings.h +// VoiceMob +// +// Created by Mr. Gecko on 10/14/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import +#import + +extern NSString * const MGMRecordingsFolder; + +extern NSString * const MGMRName; +extern NSString * const MGMRDate; + +@class MGMSIPUser; + +@interface MGMSIPRecordings : NSObject { + MGMSIPUser *SIPUser; + + NSMutableArray *recordings; + NSArray *recordingItems; + + IBOutlet UITableView *recordingsTable; + IBOutlet UIWebView *recordingView; + + int currentRecording; + AVAudioPlayer *recordingPlayer; + NSTimer *recordingUpdater; +} ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser; +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser; + +- (MGMSIPUser *)SIPUser; + +- (UIView *)view; +- (void)releaseView; + +- (void)setRecording:(int)theRecording; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPRecordings.m b/Classes/VoiceMob/SIP/MGMSIPRecordings.m new file mode 100644 index 0000000..016f269 --- /dev/null +++ b/Classes/VoiceMob/SIP/MGMSIPRecordings.m @@ -0,0 +1,254 @@ +// +// MGMSIPRecordings.m +// VoiceMob +// +// Created by Mr. Gecko on 10/14/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMSIPRecordings.h" +#import "MGMSIPUser.h" +#import "MGMRecordingView.h" +#import "MGMAccountController.h" +#import "MGMVMAddons.h" +#import +#import + +NSString * const MGMRecordingsFolder = @"recordings"; + +NSString * const MGMRName = @"name"; +NSString * const MGMRDate = @"date"; +NSString * const MGMRFile = @"file"; + +NSString * const MGMRecordingCellIdentifier = @"MGMRecordingCellIdentifier"; + +@implementation MGMSIPRecordings ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser { + return [[[self alloc] initWithSIPUser:theSIPUser] autorelease]; +} +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser { + if ((self = [super init])) { + SIPUser = theSIPUser; + + recordingItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Recordings" style:UIBarButtonItemStyleBordered target:self action:@selector(showRecordings:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[SIPUser accountController] action:@selector(showSettings:)] autorelease], nil] retain]; + currentRecording = -1; + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [recordingItems release]; + [recordingPlayer release]; + [super dealloc]; +} + +- (MGMSIPUser *)SIPUser { + return SIPUser; +} + +- (UIView *)view { + if (recordingsTable==nil) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPRecordings"] owner:self options:nil]) { + NSLog(@"Unable to load SIP Recordings"); + } else { + recordings = [NSMutableArray new]; + NSDirectoryEnumerator *recordingFolder = [[NSFileManager defaultManager] enumeratorAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder]]; + NSString *recordingName = nil; + while ((recordingName = [recordingFolder nextObject])) { + NSMutableDictionary *recording = [NSMutableDictionary dictionary]; + [recording setObject:[recordingName stringByDeletingPathExtension] forKey:MGMRName]; + [recording setObject:[[recordingFolder fileAttributes] objectForKey:NSFileCreationDate] forKey:MGMRDate]; + [recording setObject:[[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder] stringByAppendingPathComponent:recordingName] forKey:MGMRFile]; + [recordings addObject:recording]; + } + [recordingsTable reloadData]; + + [recordingView setDelegate:self]; + [recordingView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"recording" ofType:@"html"]]]]; + + if (currentRecording!=-1) + [[SIPUser accountController] setItems:recordingItems animated:YES]; + else + [[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES]; + } + } + if (currentRecording!=-1) + return recordingView; + return recordingsTable; +} +- (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [recordingsTable release]; + recordingsTable = nil; + [recordings release]; + recordings = nil; + [recordingView release]; + recordingView = nil; + [recordingUpdater invalidate]; + [recordingUpdater release]; + recordingUpdater = nil; + [recordingPlayer pause]; +} + +- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section { + return [recordings count]; +} +- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + MGMRecordingView *cell = (MGMRecordingView *)[recordingsTable dequeueReusableCellWithIdentifier:MGMRecordingCellIdentifier]; + if (cell==nil) { + cell = [[[MGMRecordingView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMRecordingCellIdentifier] autorelease]; + [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; + } + [cell setRecording:[recordings objectAtIndex:[indexPath indexAtPosition:1]]]; + return cell; +} +- (BOOL)tableView:(UITableView *)theTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + return YES; +} +- (UITableViewCellEditingStyle)tableView:(UITableView *)theTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewCellEditingStyleDelete; +} +- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { + return @"Delete"; +} +- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + NSDictionary *recording = [recordings objectAtIndex:[indexPath indexAtPosition:1]]; + [[NSFileManager defaultManager] removeItemAtPath:[recording objectForKey:MGMRFile] error:nil]; + [recordings removeObject:recording]; + [recordingsTable reloadData]; +} +- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [self setRecording:[indexPath indexAtPosition:1]]; +} + +- (void)setRecording:(int)theRecording { + currentRecording = theRecording; + if (currentRecording==-1) + return; + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerLoading()"]; + + [[recordingItems objectAtIndex:0] setEnabled:NO]; + [[SIPUser accountController] setItems:recordingItems animated:YES]; + + recordingPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[recordings objectAtIndex:currentRecording] objectForKey:MGMRFile]] error:nil]; + [recordingPlayer setDelegate:self]; + if (recordingView!=nil) { + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setCurrent(0)"]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"]; + [recordingPlayer play]; + recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain]; + } + + CGRect outViewFrame = [recordingsTable frame]; + CGRect inViewFrame = [recordingView frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = +inViewFrame.size.width; + [recordingView setFrame:inViewFrame]; + [[SIPUser tabView] addSubview:recordingView]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(recordingAnimationDidStop:finished:context:)]; + [recordingView setFrame:outViewFrame]; + outViewFrame.origin.x = -outViewFrame.size.width; + [recordingsTable setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)recordingAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [recordingsTable removeFromSuperview]; + [recordingsTable deselectRowAtIndexPath:[recordingsTable indexPathForSelectedRow] animated:NO]; + [[recordingItems objectAtIndex:0] setEnabled:YES]; +} + +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPaused()"]; +} +- (void)updateRecording { + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]]; +} +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + NSURL *url = [request URL]; + NSString *scheme = [[url scheme] lowercaseString]; + NSString *data = [url resourceSpecifier]; + NSString *queryData = [url query]; + NSDictionary *query; + if (queryData) { + NSMutableArray *dataArr = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:@"?"]]; + [dataArr removeLastObject]; + data = [dataArr componentsJoinedByString:@"?"]; + NSMutableDictionary *dataDic = [NSMutableDictionary dictionary]; + NSArray *parameters = [queryData componentsSeparatedByString:@"&"]; + for (int i=0; i<[parameters count]; i++) { + NSArray *info = [[parameters objectAtIndex:i] componentsSeparatedByString:@"="]; + [dataDic setObject:[[[info subarrayWithRange:NSMakeRange(1, [info count]-1)] componentsJoinedByString:@"="] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[info objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + } + query = [NSDictionary dictionaryWithDictionary:dataDic]; + } + if ([data hasPrefix:@"//"]) + data = [data substringFromIndex:2]; + + if ([scheme isEqual:@"voicemob"]) { + if ([data isEqual:@"pause"]) + [recordingPlayer pause]; + else if ([data isEqual:@"play"]) + [recordingPlayer play]; + else if ([data isEqual:@"start"]) + [recordingPlayer setCurrentTime:[[query objectForKey:@"time"] intValue]]; + } else if ([scheme isEqual:@"tel"]) { + [SIPUser call:[data phoneFormatWithAreaCode:[SIPUser areaCode]]]; + } else if ([scheme isEqual:@"file"]) { + return YES; + } else { + [[UIApplication sharedApplication] openURL:url]; + } + return NO; +} +- (void)webViewDidFinishLoad:(UIWebView *)webView { + if (currentRecording!=-1) { + if (recordingPlayer!=nil) { + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]]; + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"]; + [recordingPlayer play]; + recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain]; + } + } +} + +- (IBAction)showRecordings:(id)sender { + [[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES]; + + [recordingPlayer release]; + recordingPlayer = nil; + [recordingUpdater invalidate]; + [recordingUpdater release]; + recordingUpdater = nil; + + CGRect outViewFrame = [recordingView frame]; + CGRect inViewFrame = [recordingsTable frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = -inViewFrame.size.width; + [recordingsTable setFrame:inViewFrame]; + [[SIPUser tabView] addSubview:recordingsTable]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(showRecordingsAnimationDidStop:finished:context:)]; + [recordingsTable setFrame:outViewFrame]; + outViewFrame.origin.x = +outViewFrame.size.width; + [recordingView setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)showRecordingsAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [recordingView removeFromSuperview]; + currentRecording = -1; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPUser.h b/Classes/VoiceMob/SIP/MGMSIPUser.h index 61c1400..3e065dd 100644 --- a/Classes/VoiceMob/SIP/MGMSIPUser.h +++ b/Classes/VoiceMob/SIP/MGMSIPUser.h @@ -3,27 +3,83 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // +#if MGMSIPENABLED #import +@class MGMSIPUser, MGMAccountController, MGMUser, MGMSIPAccount, MGMContacts, MGMProgressView, MGMSIPCall, MGMSIPCallView; + +extern const int MGMSIPKeypadTabIndex; +extern const int MGMSIPContactsTabIndex; +extern const int MGMSIPInboxTabIndex; +extern const int MGMSIPRecordingsTabIndex; + extern NSString * const MGMSIPUserAreaCode; -@class MGMAccountController, MGMUser; +@protocol MGMSIPUserTabProtocol ++ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser; +- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser; -@interface MGMSIPUser : NSObject { +- (MGMSIPUser *)SIPUser; + +- (UIView *)view; +- (void)releaseView; +@end + +@interface MGMSIPUser : NSObject { MGMAccountController *accountController; MGMUser *user; + MGMSIPAccount *account; + NSMutableArray *calls; + MGMContacts *contacts; + int currentTab; + NSMutableArray *tabObjects; + + BOOL loggingIn; + BOOL acountRegistered; + NSTimer *SIPRegistrationTimeout; + + MGMProgressView *progressView; IBOutlet UIView *view; + IBOutlet UIView *tabView; + IBOutlet UITabBar *tabBar; + + NSString *optionsNumber; + MGMSIPCall *callToAwnswer; } + (id)SIPUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController; - (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController; +- (void)registerSettings; + - (MGMAccountController *)accountController; - (MGMUser *)user; +- (MGMContacts *)contacts; +- (NSArray *)calls; +- (NSString *)title; +- (NSString *)areaCode; + +- (void)loginErrored; - (UIView *)view; +- (NSArray *)tabObjects; +- (UIView *)tabView; +- (UITabBar *)tabBar; - (void)releaseView; -@end \ No newline at end of file + +- (void)call:(NSString *)theNumber; + +- (NSString *)phoneCalling; +- (void)gotNewCall:(MGMSIPCall *)theCall; +- (void)answerCall; +- (void)clearCall; +- (void)callDone:(MGMSIPCallView *)theCall; + +- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item; + +- (void)showOptionsForNumber:(NSString *)theNumber; +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/SIP/MGMSIPUser.m b/Classes/VoiceMob/SIP/MGMSIPUser.m index f0351ab..c2af964 100644 --- a/Classes/VoiceMob/SIP/MGMSIPUser.m +++ b/Classes/VoiceMob/SIP/MGMSIPUser.m @@ -3,62 +3,353 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // +#if MGMSIPENABLED #import "MGMSIPUser.h" +#import "MGMSIPCallView.h" +#import "MGMSIPPad.h" +#import "MGMSIPContacts.h" +#import "MGMSIPInbox.h" +#import "MGMSIPRecordings.h" +#import "MGMAccountController.h" +#import "MGMController.h" +#import "MGMVoiceUser.h" +#import "MGMProgressView.h" #import "MGMVMAddons.h" #import #import +const int MGMSIPKeypadTabIndex = 0; +const int MGMSIPContactsTabIndex = 1; +const int MGMSIPInboxTabIndex = 2; +const int MGMSIPRecordingsTabIndex = 3; + NSString * const MGMSIPUserAreaCode = @"MGMVSIPUserAreaCode"; +NSString * const MGMSIPCurrentTab = @"MGMSIPCurrentTab"; @implementation MGMSIPUser + (id)SIPUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController { return [[[self alloc] initWithUser:theUser accountController:theAccountController] autorelease]; } - (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController { - if (self = [super init]) { + if ((self = [super init])) { accountController = theAccountController; user = [theUser retain]; + [self registerSettings]; + + if ([user isStarted]) { + account = [[MGMSIPAccount alloc] initWithSettings:[user settings]]; + [account setDelegate:self]; + calls = [NSMutableArray new]; + loggingIn = NO; + acountRegistered = NO; + contacts = [[MGMContacts contactsWithClass:NSClassFromString([user settingForKey:MGMSContactsSourceKey]) delegate:self] retain]; + [contacts updateContacts]; + + currentTab = [[user settingForKey:MGMSIPCurrentTab] intValue]; + tabObjects = [NSMutableArray new]; + [tabObjects addObject:[MGMSIPPad tabWithSIPUser:self]]; + [tabObjects addObject:[MGMSIPContacts tabWithSIPUser:self]]; + [tabObjects addObject:[MGMSIPInbox tabWithSIPUser:self]]; + [tabObjects addObject:[MGMSIPRecordings tabWithSIPUser:self]]; + + loggingIn = YES; + [NSThread detachNewThreadSelector:@selector(login) toTarget:account withObject:nil]; + } } return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [self releaseView]; - if (user!=nil) - [user release]; + [tabObjects removeAllObjects]; + [tabObjects release]; + [SIPRegistrationTimeout invalidate]; + [SIPRegistrationTimeout release]; + [calls removeAllObjects]; + [calls release]; + [account setDelegate:nil]; + [account logout]; + [account release]; + [contacts stop]; + [contacts setDelegate:nil]; + [contacts release]; + [user release]; + [callToAwnswer release]; + [optionsNumber release]; + [callToAwnswer release]; [super dealloc]; } +- (void)registerSettings { + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings setObject:NSStringFromClass([MGMAddressBook class]) forKey:MGMSContactsSourceKey]; + [settings setObject:[NSNumber numberWithInt:MGMSIPKeypadTabIndex] forKey:MGMSIPCurrentTab]; + [user registerSettings:settings]; +} + - (MGMAccountController *)accountController { return accountController; } - (MGMUser *)user { return user; } +- (MGMContacts *)contacts { + return contacts; +} +- (NSArray *)calls { + return calls; +} - (NSString *)title { if ([user settingForKey:MGMSIPAccountFullName]!=nil && ![[user settingForKey:MGMSIPAccountFullName] isEqual:@""]) return [user settingForKey:MGMSIPAccountFullName]; - return [user settingForKey:MGMUserName]; + NSString *userName = [user settingForKey:MGMUserName]; + if ([userName isPhoneComplete]) + userName = [userName readableNumber]; + return userName; +} +- (NSString *)areaCode { + return [user settingForKey:MGMSIPUserAreaCode]; +} +- (NSString *)password { + return [user password]; +} + +- (void)registrationChanged { + [SIPRegistrationTimeout invalidate]; + [SIPRegistrationTimeout release]; + SIPRegistrationTimeout = nil; + if (!acountRegistered) { + if (![account isRegistered]) { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Unable to Register with Server. Please check your credentials."]; + [alert setMessage:[account lastError]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } + acountRegistered = YES; + [self performSelectorOnMainThread:@selector(removeLoginProgress) withObject:nil waitUntilDone:NO]; + } +} +- (void)loggedIn { + loggingIn = NO; + [self performSelectorOnMainThread:@selector(startRegistrationTimeoutTimer) withObject:nil waitUntilDone:NO]; +} +- (void)startRegistrationTimeoutTimer { + if (!acountRegistered) + SIPRegistrationTimeout = [[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(SIPTimeout) userInfo:nil repeats:NO] retain]; +} +- (void)SIPTimeout { + [SIPRegistrationTimeout invalidate]; + [SIPRegistrationTimeout release]; + SIPRegistrationTimeout = nil; + [account setLastError:@"Registration Timeout."]; + [self loginErrored]; +} +- (void)removeLoginProgress { + if (progressView!=nil) { + [progressView stopProgess]; + [progressView setNeedsDisplay]; + + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:1.0]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(progressFadeAnimationDidStop:finished:context:)]; + [progressView setAlpha:0.0]; + [UIView commitAnimations]; + } +} +- (void)progressFadeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [progressView removeFromSuperview]; + [progressView release]; + progressView = nil; +} +- (void)loginErrored { + loggingIn = NO; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error logging in"]; + [alert setMessage:[account lastError]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + + [progressView stopProgess]; + [progressView removeFromSuperview]; + [progressView release]; + progressView = nil; + [self performSelectorOnMainThread:@selector(removeLoginProgress) withObject:nil waitUntilDone:NO]; +} +- (void)logoutErrored { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error logging out"]; + [alert setMessage:[account lastError]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } - (UIView *)view { if (view==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPUser"] owner:self options:nil]) { NSLog(@"Unable to load SIP User"); - [self release]; - self = nil; } else { - + [tabView addSubview:[[tabObjects objectAtIndex:currentTab] view]]; + [tabBar setSelectedItem:[[tabBar items] objectAtIndex:currentTab]]; + if (![account isRegistered]) { + CGSize contentSize = [view frame].size; + progressView = [[MGMProgressView alloc] initWithFrame:CGRectMake(0, 0, contentSize.width, contentSize.height)]; + [progressView setProgressTitle:@"Logging In"]; + [view addSubview:progressView]; + [progressView startProgess]; + [progressView becomeFirstResponder]; + } } } return view; } +- (NSArray *)tabObjects { + return tabObjects; +} +- (UIView *)tabView { + return tabView; +} +- (UITabBar *)tabBar { + return tabBar; +} - (void)releaseView { - if (view!=nil) { - [view release]; - view = nil; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [[tabObjects objectAtIndex:currentTab] releaseView]; + [view release]; + view = nil; + [tabView release]; + tabView = nil; + [tabBar release]; + tabBar = nil; + [progressView stopProgess]; + [progressView release]; + progressView = nil; +} + +- (void)updatedContacts { + [[tabObjects objectAtIndex:MGMSIPContactsTabIndex] updatedContacts]; +} + +- (void)call:(NSString *)theNumber { + [[tabObjects objectAtIndex:MGMSIPInboxTabIndex] addPhoneNumber:theNumber type:MGMIPlacedType]; + [account makeCallToNumber:theNumber]; +} + +- (NSString *)phoneCalling { + for (int i=0; i<[[accountController contactsControllers] count]; i++) { + if ([[[accountController contactsControllers] objectAtIndex:i] isKindOfClass:[MGMVoiceUser class]] && [[[accountController contactsControllers] objectAtIndex:i] isPlacingCall]) { + MGMVoiceUser *voiceUser = [[accountController contactsControllers] objectAtIndex:i]; + [voiceUser donePlacingCall]; + return [voiceUser currentPhoneNumber]; + } + } + return nil; +} +- (void)gotNewCall:(MGMSIPCall *)theCall { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 + if ([[accountController controller] isInBackground]) { + [self performSelectorOnMainThread:@selector(showNotificationForCall:) withObject:theCall waitUntilDone:YES]; + } else { +#endif + [self performSelectorOnMainThread:@selector(mainGotNewCall:) withObject:theCall waitUntilDone:NO]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 + } +#endif +} +- (void)answerCall { + if (callToAwnswer!=nil) { + if ([callToAwnswer state]!=MGMSIPCallDisconnectedState) { + [callToAwnswer answer]; + [self performSelectorOnMainThread:@selector(mainGotNewCall:) withObject:callToAwnswer waitUntilDone:NO]; + } + [callToAwnswer release]; + callToAwnswer = nil; } } -@end \ No newline at end of file +- (void)clearCall { + [callToAwnswer release]; + callToAwnswer = nil; +} +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 +- (void)showNotificationForCall:(MGMSIPCall *)theCall { + UILocalNotification *alert = [[[UILocalNotification alloc] init] autorelease]; + if (alert!=nil) { + [callToAwnswer release]; + callToAwnswer = [theCall retain]; + [alert setRepeatInterval:0]; + NSString *name = [[theCall remoteURL] userName]; + if ([name isPhone]) + name = [contacts nameForNumber:[name phoneFormatWithAreaCode:[self areaCode]]]; + [alert setAlertBody:[NSString stringWithFormat:@"Call from %@", name]]; + [alert setAlertAction:@"Answer"]; + + [[UIApplication sharedApplication] presentLocalNotificationNow:alert]; + //[theCall sendRingingNotification]; + } +} +#endif +- (void)mainGotNewCall:(MGMSIPCall *)theCall { + MGMSIPCallView *callView = [MGMSIPCallView viewWithCall:theCall SIPUser:self]; + [calls addObject:callView]; + [[accountController controller] showCallView:callView]; +} +- (void)callDone:(MGMSIPCallView *)theCall { + if ([[theCall call] isIncoming]) + [[tabObjects objectAtIndex:MGMSIPInboxTabIndex] addPhoneNumber:[[[theCall call] remoteURL] userName] type:([theCall didAnswer] ? MGMIReceivedType : MGMIMissedType)]; + [[accountController controller] performSelectorOnMainThread:@selector(dismissCallView:) withObject:theCall waitUntilDone:NO]; + [calls removeObject:theCall]; +} + +- (BOOL)isUserDone:(MGMUser *)theUser { + return !loggingIn; +} + +- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item { + int tabIndex = [[tabBar items] indexOfObject:item]; + if (tabIndex==currentTab) + return; + + if (tabIndex!=MGMSIPRecordingsTabIndex) + [accountController setItems:[accountController accountItems] animated:YES]; + + id tab = [tabObjects objectAtIndex:currentTab]; + currentTab = tabIndex; + [user setSetting:[NSNumber numberWithInt:currentTab] forKey:MGMSIPCurrentTab]; + id newTab = [tabObjects objectAtIndex:currentTab]; + CGRect tabFrame = [[newTab view] frame]; + tabFrame.size = [tabView frame].size; + [[newTab view] setFrame:tabFrame]; + [tabView addSubview:[newTab view]]; + [[tab view] removeFromSuperview]; + [tab releaseView]; +} + +- (void)showOptionsForNumber:(NSString *)theNumber { + optionsNumber = [theNumber copy]; + UIActionSheet *theAction = [[UIActionSheet new] autorelease]; + [theAction addButtonWithTitle:@"Call"]; + [theAction addButtonWithTitle:@"Reverse Lookup"]; + [theAction addButtonWithTitle:@"Cancel"]; + [theAction setCancelButtonIndex:2]; + [theAction setDelegate:self]; + [theAction showInView:view]; +} +- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { + if (buttonIndex==0) + [self call:optionsNumber]; + else if (buttonIndex==1) + [[accountController controller] showReverseLookupWithNumber:optionsNumber]; + [optionsNumber release]; + optionsNumber = nil; +} +@end +#endif \ No newline at end of file diff --git a/Classes/VoiceMob/Settings/MGMDownloader.h b/Classes/VoiceMob/Settings/MGMDownloader.h new file mode 100644 index 0000000..3f2e145 --- /dev/null +++ b/Classes/VoiceMob/Settings/MGMDownloader.h @@ -0,0 +1,39 @@ +// +// MGMThemeDownloader.h +// VoiceMob +// +// Created by Mr. Gecko on 11/6/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import +#import + +@class MGMURLConnectionManager; + +@interface MGMDownloader : MGMSettingView { + MGMURLConnectionManager *connectionManager; + IBOutlet UIWebView *webView; + + IBOutlet UIView *downloadView; + IBOutlet UIProgressView *progressView; + IBOutlet UILabel *nameField; + IBOutlet UILabel *sizeField; + IBOutlet UILabel *speedField; + IBOutlet UILabel *estimentField; + + NSString *URLScheme; + NSString *tmpFile; + NSFileHandle *fileHandle; + int startTime; + int bytesReceivedSec; + int bytesReceived; + NSTimer *secCheckTimer; + NSString *receivedSec; + int receivedContentLength; + int expectedContentLength; +} +- (void)downloadURL:(NSURL *)theURL; +- (void)secCheck; +- (IBAction)close:(id)sender; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Settings/MGMDownloader.m b/Classes/VoiceMob/Settings/MGMDownloader.m new file mode 100644 index 0000000..61395ec --- /dev/null +++ b/Classes/VoiceMob/Settings/MGMDownloader.m @@ -0,0 +1,197 @@ +// +// MGMThemeDownloader.m +// VoiceMob +// +// Created by Mr. Gecko on 11/6/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMDownloader.h" +#import "ZipArchive.h" +#import +#import + +NSString * const MGMTMPPath = @"~/tmp/"; +NSString * const MGMZIPEXT = @"zip"; + +NSString * const MGMVMTURL = @"vmtheme"; +NSString * const MGMVMSURL = @"vmsound"; + +@implementation MGMDownloader +- (id)initWithSetting:(MGMSetting *)theSetting { + if ((self = [super initWithSetting:theSetting])) { + connectionManager = [MGMURLConnectionManager new]; + } + return self; +} +- (id)init { + if ((self = [super init])) { + connectionManager = [MGMURLConnectionManager new]; + } + return self; +} +- (void)dealloc { + [self releaseView]; + [URLScheme release]; + [tmpFile release]; + [fileHandle release]; + [secCheckTimer invalidate]; + [secCheckTimer release]; + [receivedSec release]; + [super dealloc]; +} + +- (UIView *)view { + if (webView==nil) { + if (![[NSBundle mainBundle] loadNibNamed:@"Downloader" owner:self options:nil]) { + NSLog(@"Unable to load Downloader"); + [self release]; + self = nil; + } else { + [webView setDelegate:self]; + [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[[setting extra] objectForKey:MGMSExtraKey]]]]; + } + } + return webView; +} +- (void)releaseView { + [webView release]; + webView = nil; + [downloadView release]; + downloadView = nil; + [progressView release]; + progressView = nil; + [nameField release]; + nameField = nil; + [sizeField release]; + sizeField = nil; + [speedField release]; + speedField = nil; + [estimentField release]; + estimentField = nil; +} + +- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + if ([[[[request URL] scheme] lowercaseString] isEqual:MGMVMTURL]) { + [self downloadURL:[request URL]]; + return NO; + } else if ([[[[request URL] scheme] lowercaseString] isEqual:MGMVMSURL]) { + [self downloadURL:[request URL]]; + return NO; + } + return YES; +} +- (void)downloadURL:(NSURL *)theURL { + [URLScheme release]; + URLScheme = [[[theURL scheme] lowercaseString] copy]; + theURL = [NSURL URLWithString:[@"http:" stringByAppendingString:[theURL resourceSpecifier]]]; + UIView *view = [[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0]; + CGRect inViewFrame = [downloadView frame]; + inViewFrame.size = [view frame].size; + inViewFrame.origin.y = +inViewFrame.size.height; + [downloadView setFrame:inViewFrame]; + [view addSubview:downloadView]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [downloadView frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [downloadView setFrame:outViewFrame]; + [UIView commitAnimations]; + + bytesReceivedSec = 1; + receivedContentLength = 0; + expectedContentLength = 0; + [self secCheck]; + [progressView setProgress:0.0]; + [nameField setText:@""]; + + srandomdev(); + [tmpFile release]; + tmpFile = [[[[[NSNumber numberWithLong:random()] stringValue] MD5] stringByAppendingPathExtension:MGMZIPEXT] retain]; + + if (secCheckTimer==nil) + secCheckTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(secCheck) userInfo:nil repeats:YES] retain]; + + MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:[NSURLRequest requestWithURL:theURL] delegate:self]; + [handler setFile:[[MGMTMPPath stringByExpandingTildeInPath] stringByAppendingPathComponent:tmpFile]]; + [connectionManager addHandler:handler]; +} +- (IBAction)close:(id)sender { + [connectionManager cancelAll]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(closeAnimationDidStop:finished:context:)]; + CGRect outViewFrame = [downloadView frame]; + outViewFrame.origin.y = +outViewFrame.size.height; + [downloadView setFrame:outViewFrame]; + [UIView commitAnimations]; + [secCheckTimer release]; + secCheckTimer = nil; + [fileHandle closeFile]; + [fileHandle release]; + fileHandle = nil; + [tmpFile release]; + tmpFile = nil; +} +- (void)closeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [downloadView removeFromSuperview]; +} + +- (NSString *)bytesToString:(double)bytes { + NSString *type = @"Bytes"; + if (bytes>1024.00) { + type = @"KB"; + bytes = bytes/1024.00; + if (bytes>1024.00) { + type = @"MB"; + bytes = bytes/1024.00; + if (bytes>1024.00) { + type = @"GB"; + bytes = bytes/1024.00; + } + } + } + return [NSString stringWithFormat:@"%.2f %@", bytes, type]; +} + +- (void)secCheck { + [receivedSec release]; + receivedSec = [[self bytesToString:(double)bytesReceived] retain]; + bytesReceivedSec = (bytesReceived==0 ? 1 : bytesReceived); + bytesReceived = 0; + int secs = (expectedContentLength-receivedContentLength)/bytesReceivedSec; + [sizeField setText:[NSString stringWithFormat:@"%@ of %@", [self bytesToString:(double)receivedContentLength], [self bytesToString:(double)expectedContentLength]]]; + [speedField setText:[NSString stringWithFormat:@"%@/sec", receivedSec]]; + [estimentField setText:[NSString stringWithSeconds:secs]]; +} + +- (void)handler:(MGMURLBasicHandler *)theHandler didReceiveResponse:(NSHTTPURLResponse *)theResponse { + [nameField setText:[theResponse suggestedFilename]]; +} +- (void)handler:(MGMURLBasicHandler *)theHandler receivedBytes:(unsigned long)theBytes totalBytes:(unsigned long)theTotalBytes expectedBytes:(unsigned long)theExpectedBytes { + expectedContentLength = theExpectedBytes; + receivedContentLength = theTotalBytes; + bytesReceived += theBytes; + [progressView setProgress:(double)theTotalBytes/(double)theExpectedBytes]; +} +- (void)handler:(MGMURLBasicHandler *)theHandler didFailWithError:(NSError *)theError { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error downloading"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + [self close:self]; +} +- (void)handlerDidFinish:(MGMURLBasicHandler *)theHandler { + ZipArchive *zip = [ZipArchive new]; + [zip UnzipOpenFile:[[MGMTMPPath stringByExpandingTildeInPath] stringByAppendingPathComponent:tmpFile]]; + [zip UnzipFileTo:([URLScheme isEqual:MGMVMTURL] ? [[[MGMThemeManager new] autorelease] themesFolderPath] : [[[MGMThemeManager new] autorelease] soundsFolderPath]) overWrite:YES]; + [zip UnzipCloseFile]; + [zip release]; + [[NSFileManager defaultManager] removeItemAtPath:[[MGMTMPPath stringByExpandingTildeInPath] stringByAppendingPathComponent:tmpFile] error:nil]; + [self performSelector:@selector(close:) withObject:nil afterDelay:0.5]; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Settings/MGMPhotoSelector.h b/Classes/VoiceMob/Settings/MGMPhotoSelector.h new file mode 100644 index 0000000..542e03e --- /dev/null +++ b/Classes/VoiceMob/Settings/MGMPhotoSelector.h @@ -0,0 +1,24 @@ +// +// MGMPhotoSelector.h +// VoiceMob +// +// Created by James on 3/25/11. +// Copyright 2011 Mr. Gecko's Media. All rights reserved. +// + +#import +#import + +extern NSString * const MGMSIPBackground; +extern NSString * const MGMSIPBCustom; +extern NSString * const MGMSIPBDefault; +extern NSString * const MGMPSBackground; + +@interface MGMPhotoSelector : MGMSettingView { + IBOutlet UIView *view; + IBOutlet UIImageView *imageView; + UIImagePickerController *imagePickerController; +} +- (IBAction)selectPhoto:(id)sender; +- (void)dismiss; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Settings/MGMPhotoSelector.m b/Classes/VoiceMob/Settings/MGMPhotoSelector.m new file mode 100644 index 0000000..695a020 --- /dev/null +++ b/Classes/VoiceMob/Settings/MGMPhotoSelector.m @@ -0,0 +1,159 @@ +// +// MGMPhotoSelector.m +// VoiceMob +// +// Created by James on 3/25/11. +// Copyright 2011 Mr. Gecko's Media. All rights reserved. +// + +#import "MGMPhotoSelector.h" +#import "MGMVMAddons.h" +#import + +NSString * const MGMSIPBackground = @"MGMSIPBackground"; +NSString * const MGMSIPBCustom = @"custom"; +NSString * const MGMSIPBDefault = @"default"; +NSString * const MGMPSBackground = @"background.png"; + +@implementation MGMPhotoSelector +- (id)initWithSetting:(MGMSetting *)theSetting { + if ((self = [super initWithSetting:theSetting])) { + + } + return self; +} +- (void)dealloc { + [self releaseView]; + [super dealloc]; +} + +- (UIView *)view { + if (view==nil) { + if (![[NSBundle mainBundle] loadNibNamed:@"PhotoSelector" owner:self options:nil]) { + NSLog(@"Unable to load Photo Selector."); + } else { + if ([[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom]) + [imageView setImage:[UIImage imageWithContentsOfFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground]]]; + else + [self selectPhoto:self]; + } + } + return view; +} +- (void)releaseView { + [view release]; + view = nil; + [imagePickerController release]; + imagePickerController = nil; + [imageView release]; + imageView = nil; +} + +- (IBAction)selectPhoto:(id)sender { + imagePickerController = [[UIImagePickerController alloc] init]; + [imagePickerController setDelegate:self]; + [imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; + + UIView *viewController = [[[[[UIApplication sharedApplication] windows] objectAtIndex:0] subviews] objectAtIndex:0]; + CGRect inViewFrame = [[imagePickerController view] frame]; + inViewFrame.size = [viewController frame].size; + inViewFrame.origin.y = +inViewFrame.size.height; + [[imagePickerController view] setFrame:inViewFrame]; + [viewController addSubview:[imagePickerController view]]; + [imagePickerController viewWillAppear:YES]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [[imagePickerController view] frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [[imagePickerController view] setFrame:outViewFrame]; + [UIView commitAnimations]; + [imagePickerController viewDidAppear:YES]; +} + +- (UIImage *)cropImage:(UIImage *)theImage toSize:(CGSize)theSize { + if (theImage!=nil) { + CGSize size = [theImage size]; + float scaleFactor = 0.0; + float scaledWidth = theSize.width; + float scaledHeight = theSize.height; + + if (!CGSizeEqualToSize(size, theSize)) { + float widthFactor = theSize.width / size.width; + float heightFactor = theSize.height / size.height; + + if (widthFactor > heightFactor) + scaleFactor = widthFactor; + else + scaleFactor = heightFactor; + + scaledWidth = size.width * scaleFactor; + scaledHeight = size.height * scaleFactor; + } + CGSize newSize = CGSizeMake(scaledWidth, scaledHeight); + if (!CGSizeEqualToSize(newSize, CGSizeZero)) { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + UIGraphicsBeginImageContext(theSize); + [theImage drawInRect:CGRectMake((theSize.width-scaledWidth)/2, (theSize.height-scaledHeight)/2, scaledWidth, scaledHeight)]; + UIImage *newImage = [UIGraphicsGetImageFromCurrentImageContext() retain]; + UIGraphicsEndImageContext(); + [pool drain]; + return [newImage autorelease]; + } + } + return theImage; +} + +- (void)imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)theInfo { + CGSize size; + if ([[UIScreen mainScreen] isRetina]) + size = CGSizeMake(640, 920); + else + size = CGSizeMake(320, 460); + UIImage *image = [self cropImage:[theInfo objectForKey:UIImagePickerControllerOriginalImage] toSize:size]; + NSData *data = UIImagePNGRepresentation(image); + if (data!=nil) { + [imageView setImage:image]; + [data writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground] atomically:YES]; + [[NSUserDefaults standardUserDefaults] setObject:MGMSIPBCustom forKey:MGMSIPBackground]; + } + [self dismiss]; +} +- (void)imagePickerController:(UIImagePickerController *)thePicker didFinishPickingImage:(UIImage *)theImage editingInfo:(NSDictionary *)theInfo { + CGSize size; + if ([[UIScreen mainScreen] isRetina]) + size = CGSizeMake(640, 920); + else + size = CGSizeMake(320, 460); + UIImage *image = [self cropImage:theImage toSize:size]; + NSData *data = UIImagePNGRepresentation(image); + if (data!=nil) { + [imageView setImage:image]; + [data writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground] atomically:YES]; + [[NSUserDefaults standardUserDefaults] setObject:MGMSIPBCustom forKey:MGMSIPBackground]; + } + [self dismiss]; +} +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)thePicker { + [self dismiss]; +} + +- (void)dismiss { + [imagePickerController viewWillDisappear:YES]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:context:)]; + CGRect outViewFrame = [[imagePickerController view] frame]; + outViewFrame.origin.y = +outViewFrame.size.height; + [[imagePickerController view] setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(id)theContext { + [imagePickerController viewDidDisappear:YES]; + [[imagePickerController view] removeFromSuperview]; + [imagePickerController release]; + imagePickerController = nil; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Settings/MGMThemePreviewer.h b/Classes/VoiceMob/Settings/MGMThemePreviewer.h new file mode 100644 index 0000000..0e02012 --- /dev/null +++ b/Classes/VoiceMob/Settings/MGMThemePreviewer.h @@ -0,0 +1,21 @@ +// +// MGMThemePreviewer.h +// VoiceMob +// +// Created by Mr. Gecko on 11/6/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import +#import + +@class MGMThemeManager; + +@interface MGMThemePreviewer : MGMSettingView { + MGMThemeManager *themeManager; + UIWebView *SMSView; + NSMutableArray *testMessages; + NSMutableDictionary *testMessageInfo; +} + +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Settings/MGMThemePreviewer.m b/Classes/VoiceMob/Settings/MGMThemePreviewer.m new file mode 100644 index 0000000..9fba66a --- /dev/null +++ b/Classes/VoiceMob/Settings/MGMThemePreviewer.m @@ -0,0 +1,86 @@ +// +// MGMThemePreviewer.m +// VoiceMob +// +// Created by Mr. Gecko on 11/6/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMThemePreviewer.h" +#import + +NSString * const MGMTestTYPhoto = @"yPhoto"; +NSString * const MGMTestTTPhoto = @"tPhoto"; + +@implementation MGMThemePreviewer +- (id)initWithSetting:(MGMSetting *)theSetting { + if ((self = [super initWithSetting:theSetting])) { + themeManager = [MGMThemeManager new]; + testMessages = [NSMutableArray new]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Hey, you got the message?", MGMIText, @"5:56 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"No, can you resend it?", MGMIText, @"5:57 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"No, all local copies were destroyed, because we don't want this to get out.", MGMIText, @"5:58 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Oh, yea, right, that thing.", MGMIText, @"5:59 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"I can't send you on SMS because your cell phone company spy's on you.", MGMIText, @"6:00 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"True. We can meet in the secret spot.", MGMIText, @"6:00 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"No thanks, I think we should meet at my house.", MGMIText, @"6:01 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Would you like to come for dinner?", MGMIText, @"6:01 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"I'd love, but my girl needs me more.", MGMIText, @"6:02 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Well why not make it a double date? I bring my wife and you bring yours.", MGMIText, @"6:03 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Sure I pick Mucha Pizza. What time should we meet?", MGMIText, @"6:05 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"7PM?", MGMIText, @"6:05 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"That sounds good.", MGMIText, @"6:06 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]]; + [testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Great, meet you then.", MGMIText, @"6:07 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]]; + testMessageInfo = [NSMutableDictionary new]; + [testMessageInfo setObject:[NSDate dateWithTimeIntervalSince1970:1598915245] forKey:MGMITime]; + [testMessageInfo setObject:@"Noah Jonson" forKey:MGMTInName]; + [testMessageInfo setObject:@"+15555555555" forKey:MGMIPhoneNumber]; + [testMessageInfo setObject:@"+17204325686" forKey:MGMTUserNumber]; + [testMessageInfo setObject:@"673bd22599231d1a9ba78760f2df085a7237b4b3" forKey:MGMIID]; + [testMessageInfo setObject:[[themeManager outgoingIconPath] filePath] forKey:MGMTestTYPhoto]; + [testMessageInfo setObject:[[themeManager incomingIconPath] filePath] forKey:MGMTestTTPhoto]; + } + return self; +} +- (void)dealloc { + [self releaseView]; + [themeManager release]; + [testMessages release]; + [testMessageInfo release]; + [super dealloc]; +} + +- (UIView *)view { + if (SMSView==nil) { + SMSView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 418)]; + [SMSView setDelegate:self]; + + NSMutableArray *messageArray = [NSMutableArray array]; + for (unsigned int i=0; i<[testMessages count]; i++) { + NSMutableDictionary *message = [NSMutableDictionary dictionaryWithDictionary:[testMessages objectAtIndex:i]]; + [message setObject:[[NSNumber numberWithInt:i] stringValue] forKey:MGMIID]; + if ([[message objectForKey:MGMIYou] boolValue]) { + [message setObject:[testMessageInfo objectForKey:MGMTestTYPhoto] forKey:MGMTPhoto]; + [message setObject:NSFullUserName() forKey:MGMTName]; + [message setObject:[testMessageInfo objectForKey:MGMTUserNumber] forKey:MGMIPhoneNumber]; + } else { + [message setObject:[testMessageInfo objectForKey:MGMTestTTPhoto] forKey:MGMTPhoto]; + [message setObject:[testMessageInfo objectForKey:MGMTInName] forKey:MGMTName]; + [message setObject:[testMessageInfo objectForKey:MGMIPhoneNumber] forKey:MGMIPhoneNumber]; + } + [messageArray addObject:message]; + } + NSString *html = [themeManager buildHTMLWithMessages:messageArray messageInfo:testMessageInfo]; + [SMSView loadHTMLString:html baseURL:[NSURL fileURLWithPath:[themeManager currentThemeVariantPath]]]; + } + return SMSView; +} +- (void)releaseView { + [SMSView release]; + SMSView = nil; +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + [SMSView stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"]; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMBadgeView.h b/Classes/VoiceMob/Views/MGMBadgeView.h new file mode 100644 index 0000000..f3b7d60 --- /dev/null +++ b/Classes/VoiceMob/Views/MGMBadgeView.h @@ -0,0 +1,17 @@ +// +// MGMInboxItem.h +// VoiceMob +// +// Created by James on 11/21/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +@interface MGMBadgeView : UITableViewCell { + NSString *badge; + UILabel *nameField; +} +- (void)setName:(NSString *)theName; +- (void)setBadge:(NSString *)theBadge; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMBadgeView.m b/Classes/VoiceMob/Views/MGMBadgeView.m new file mode 100644 index 0000000..df0662e --- /dev/null +++ b/Classes/VoiceMob/Views/MGMBadgeView.m @@ -0,0 +1,62 @@ +// +// MGMInboxItem.m +// VoiceMob +// +// Created by James on 11/21/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMBadgeView.h" +#import + +@implementation MGMBadgeView +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { + nameField = [[UILabel alloc] initWithFrame:CGRectZero]; + [nameField setBackgroundColor:[UIColor clearColor]]; + [nameField setFont:[UIFont boldSystemFontOfSize:20.0]]; + [[self contentView] addSubview:nameField]; + } + return self; +} +- (void)dealloc { + [badge release]; + [nameField release]; + [super dealloc]; +} +- (void)setName:(NSString *)theName { + [nameField setText:theName]; +} +- (void)setBadge:(NSString *)theBadge { + [badge release]; + badge = [theBadge copy]; + [self setNeedsDisplay]; +} +- (void)layoutSubviews { + [super layoutSubviews]; + + CGRect frameRect = [[self contentView] bounds]; + if (badge!=nil && ![badge isEqual:@""]) { + UIFont *badgeFont = [UIFont systemFontOfSize:18]; + CGSize badgeSize = [badge sizeWithFont:badgeFont]; + [nameField setFrame:CGRectMake(5, (frameRect.size.height/2)-12, (frameRect.size.width-badgeSize.width)-20, 24)]; + } else { + [nameField setFrame:CGRectMake(5, (frameRect.size.height/2)-12, frameRect.size.width-10, 24)]; + } +} + +- (void)drawRect:(CGRect)rect { + if (badge!=nil && ![badge isEqual:@""]) { + CGRect frameRect = [[self contentView] bounds]; + UIFont *badgeFont = [UIFont systemFontOfSize:18]; + CGSize badgeSize = [badge sizeWithFont:badgeFont]; + CGRect borderRect = CGRectMake((frameRect.size.width-(badgeSize.width+13))-5, (frameRect.size.height/2)-(badgeSize.height/2), badgeSize.width+13, badgeSize.height); + MGMPath *path = [MGMPath pathWithRoundedRect:borderRect cornerRadius:borderRect.size.height/2]; + [[UIColor colorWithRed:0.5019 green:0.5843 blue:0.7412 alpha:1.0] setFill]; + [path fill]; + [[UIColor whiteColor] setFill]; + [badge drawInRect:CGRectMake(borderRect.origin.x+((borderRect.size.width-badgeSize.width)/2), borderRect.origin.y-((borderRect.size.height-badgeSize.height)/2), badgeSize.width, badgeSize.height) withFont:badgeFont]; + } + [super drawRect:rect]; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMContactView.h b/Classes/VoiceMob/Views/MGMContactView.h index 6a32111..1f87fdb 100644 --- a/Classes/VoiceMob/Views/MGMContactView.h +++ b/Classes/VoiceMob/Views/MGMContactView.h @@ -3,20 +3,28 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // -#import +#import -@class MGMThemeManager; +@class MGMThemeManager, MGMContacts; @interface MGMContactView : UITableViewCell { MGMThemeManager *themeManager; + MGMContacts *contacts; UIImageView *photoView; UILabel *nameField; UILabel *phoneField; NSDictionary *contact; + NSString *number; + + NSLock *photoLock; + int photoWaiting; } - (void)setThemeManager:(MGMThemeManager *)theThemeManager; +- (void)setContacts:(MGMContacts *)theContacts; - (void)setContact:(NSDictionary *)theContact; + +- (void)getPhotoForNumber:(NSString *)theNumber; @end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMContactView.m b/Classes/VoiceMob/Views/MGMContactView.m index 6542a89..7ef7ade 100644 --- a/Classes/VoiceMob/Views/MGMContactView.m +++ b/Classes/VoiceMob/Views/MGMContactView.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMContactView.h" @@ -11,7 +11,7 @@ @implementation MGMContactView - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { photoView = [[UIImageView alloc] initWithFrame:CGRectZero]; [[self contentView] addSubview:photoView]; nameField = [[UILabel alloc] initWithFrame:CGRectZero]; @@ -22,24 +22,31 @@ [phoneField setBackgroundColor:[UIColor clearColor]]; [phoneField setFont:[UIFont systemFontOfSize:15.0]]; [[self contentView] addSubview:phoneField]; + photoLock = [NSLock new]; } return self; } - (void)dealloc { - if (photoView!=nil) - [photoView release]; - if (nameField!=nil) - [nameField release]; - if (phoneField!=nil) - [phoneField release]; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [photoView release]; + [nameField release]; + [phoneField release]; + [contact release]; + [photoLock release]; + [number release]; [super dealloc]; } - (void)setThemeManager:(MGMThemeManager *)theThemeManager { themeManager = theThemeManager; } +- (void)setContacts:(MGMContacts *)theContacts { + contacts = theContacts; +} - (void)setContact:(NSDictionary *)theContact { - if (contact!=nil) [contact release]; + [contact release]; contact = [theContact retain]; } @@ -49,10 +56,12 @@ CGRect frameRect = [[self contentView] bounds]; if (contact!=nil) { - if ([contact objectForKey:MGMCPhoto]==nil || [[contact objectForKey:MGMCPhoto] isKindOfClass:[NSNull class]]) - [photoView setImage:[[[UIImage alloc] initWithContentsOfFile:[themeManager incomingIconPath]] autorelease]]; - else - [photoView setImage:[[[UIImage alloc] initWithData:[contact objectForKey:MGMCPhoto]] autorelease]]; + if (![number isEqual:[contact objectForKey:MGMCNumber]]) { + [number release]; + number = [[contact objectForKey:MGMCNumber] retain]; + [photoView setImage:nil]; + [NSThread detachNewThreadSelector:@selector(getPhotoForNumber:) toTarget:self withObject:number]; + } if ([[contact objectForKey:MGMCName] isEqual:@""]) [nameField setText:[contact objectForKey:MGMCCompany]]; else @@ -67,4 +76,27 @@ [nameField setFrame:CGRectMake(frameRect.size.height+8, 10, frameRect.size.width-(frameRect.size.height+12), 20)]; [phoneField setFrame:CGRectMake(frameRect.size.height+8, frameRect.size.height-27, frameRect.size.width-(frameRect.size.height+12), 20)]; } + +- (void)getPhotoForNumber:(NSString *)theNumber { + photoWaiting++; + [photoLock lock]; + photoWaiting--; + if (photoWaiting>=1) { + [photoLock unlock]; + return; + } + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + NSData *photo = [contacts photoDataForNumber:number]; + if (photoWaiting>=1) { + [pool release]; + [photoLock unlock]; + return; + } + if (photo==nil || [photo isKindOfClass:[NSNull class]]) + [photoView setImage:[[[UIImage alloc] initWithContentsOfFile:[themeManager incomingIconPath]] autorelease]]; + else + [photoView setImage:[[[UIImage alloc] initWithData:photo] autorelease]]; + [pool release]; + [photoLock unlock]; +} @end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMGlassButton.h b/Classes/VoiceMob/Views/MGMGlassButton.h new file mode 100644 index 0000000..f5bab5c --- /dev/null +++ b/Classes/VoiceMob/Views/MGMGlassButton.h @@ -0,0 +1,18 @@ +// +// MGMGlassButton.h +// VoiceMob +// +// Created by Mr. Gecko on 10/1/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +@interface MGMGlassButton : UIButton { + UIColor *buttonColor; + UIColor *buttonTouchColor; + UIColor *buttonDisabledColor; + BOOL touching; +} + +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMGlassButton.m b/Classes/VoiceMob/Views/MGMGlassButton.m new file mode 100644 index 0000000..17b9254 --- /dev/null +++ b/Classes/VoiceMob/Views/MGMGlassButton.m @@ -0,0 +1,108 @@ +// +// MGMGlassButton.m +// VoiceMob +// +// Created by Mr. Gecko on 10/1/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMGlassButton.h" +#import +#import "MGMVMAddons.h" + +@implementation MGMGlassButton +- (void)awakeFromNib { + buttonColor = [[self backgroundColor] retain]; + buttonTouchColor = [[buttonColor colorWithDifference:-0.1] retain]; + buttonDisabledColor = [[buttonColor colorWithDifference:0.1] retain]; + [self setBackgroundColor:[UIColor clearColor]]; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [buttonColor release]; + [buttonTouchColor release]; + [buttonDisabledColor release]; + [super dealloc]; +} + +- (void)setTouching:(BOOL)isTouching { + touching = isTouching; + [self setNeedsDisplay]; +} +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesBegan:touches withEvent:event]; + [self setTouching:YES]; +} +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesEnded:touches withEvent:event]; + [self setTouching:NO]; +} +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesCancelled:touches withEvent:event]; + [self setTouching:NO]; +} +- (void)setEnabled:(BOOL)isEnabled { + [super setEnabled:isEnabled]; + [self setNeedsDisplay]; +} + +- (UIEdgeInsets)titleEdgeInsets { + return UIEdgeInsetsMake(-2.0, 0.0, 0.0, 0.0); +} +- (void)drawRect:(CGRect)frameRect { + UIColor *color = nil; + if (![self isEnabled]) + color = buttonDisabledColor; + else if (touching) + color = buttonTouchColor; + else + color = buttonColor; + CGRect pathBounds = [self bounds]; + pathBounds.size.width -= 1.0; + pathBounds.origin.x += 0.5; + pathBounds.size.height -= 1.0; + pathBounds.origin.y += 0.5; + MGMPath *path = [MGMPath pathWithRoundedRect:pathBounds cornerRadius:12]; + [path setLineWidth:1.0]; + [color setFill]; + [[color colorWithDifference:-0.1] setStroke]; + [path fill]; + [path stroke]; + + CGRect gradientRect = pathBounds; + gradientRect.size.width -= 1.0; + gradientRect.origin.x += 0.5; + gradientRect.size.height -= 0.5; + gradientRect.origin.y += 0.5; + CGFloat gradientRadius = 12.0; + MGMPath *gradientPath = [MGMPath path]; + float maxRadiusX = gradientRect.size.width / 2.0; + float maxRadiusY = gradientRect.size.height / 2.0; + gradientRadius = (gradientRadius + +@interface MGMGlassView : UIView { + +} + +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMGlassView.m b/Classes/VoiceMob/Views/MGMGlassView.m new file mode 100644 index 0000000..d99a728 --- /dev/null +++ b/Classes/VoiceMob/Views/MGMGlassView.m @@ -0,0 +1,43 @@ +// +// MGMGlassView.m +// VoiceMob +// +// Created by Mr. Gecko on 10/9/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMGlassView.h" +#import + +@implementation MGMGlassView +- (void)drawRect:(CGRect)frameRect { + CGRect bounds = [self bounds]; + MGMPath *path = [MGMPath pathWithRect:bounds]; + [[UIColor colorWithWhite:0.0 alpha:0.6] setFill]; + [path fill]; + CGRect glassBounds = bounds; + glassBounds.size.height = glassBounds.size.height/2; + MGMPath *glassPath = [MGMPath pathWithRect:glassBounds]; + [glassPath fillGradientFrom:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5] to:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.1]]; + + [[UIColor colorWithWhite:0.0 alpha:0.6] setFill]; + CGRect line1Bounds = bounds; + line1Bounds.size.height = 1; + MGMPath *line1Path = [MGMPath pathWithRect:line1Bounds]; + [line1Path fill]; + CGRect line3Bounds = line1Bounds; + line3Bounds.origin.y += bounds.size.height-1; + MGMPath *line3Path = [MGMPath pathWithRect:line3Bounds]; + [line3Path fill]; + + [[UIColor colorWithWhite:1.0 alpha:0.1] setFill]; + CGRect line2Bounds = line1Bounds; + line2Bounds.origin.y += 1; + MGMPath *line2Path = [MGMPath pathWithRect:line2Bounds]; + [line2Path fill]; + CGRect line4Bounds = line3Bounds; + line4Bounds.origin.y -= 1; + MGMPath *line4Path = [MGMPath pathWithRect:line4Bounds]; + [line4Path fill]; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMGradientButton.h b/Classes/VoiceMob/Views/MGMGradientButton.h index 1029f16..e1a35a5 100644 --- a/Classes/VoiceMob/Views/MGMGradientButton.h +++ b/Classes/VoiceMob/Views/MGMGradientButton.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 10/1/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import diff --git a/Classes/VoiceMob/Views/MGMGradientButton.m b/Classes/VoiceMob/Views/MGMGradientButton.m index ebf6dce..1c0064e 100644 --- a/Classes/VoiceMob/Views/MGMGradientButton.m +++ b/Classes/VoiceMob/Views/MGMGradientButton.m @@ -3,11 +3,11 @@ // VoiceMob // // Created by Mr. Gecko on 10/1/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMGradientButton.h" -#import "MGMPath.h" +#import #import "MGMVMAddons.h" @implementation MGMGradientButton @@ -18,12 +18,12 @@ [self setBackgroundColor:[UIColor clearColor]]; } - (void)dealloc { - if (buttonColor!=nil) - [buttonColor release]; - if (buttonTouchColor!=nil) - [buttonTouchColor release]; - if (buttonDisabledColor!=nil) - [buttonDisabledColor release]; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [buttonColor release]; + [buttonTouchColor release]; + [buttonDisabledColor release]; [super dealloc]; } @@ -63,8 +63,8 @@ CGRect pathBounds = whitePathBounds; whitePathBounds.size.width -= 2.0; whitePathBounds.origin.x += 1.0; - whitePathBounds.size.height -= 2.0; - whitePathBounds.origin.y += 0.7; + whitePathBounds.size.height -= 2.3; + whitePathBounds.origin.y += 1.0; MGMPath *whitePath = [MGMPath pathWithRoundedRect:whitePathBounds cornerRadius:12]; [[UIColor colorWithWhite:1.0 alpha:1.0] setStroke]; [whitePath setLineWidth:2.0]; @@ -103,7 +103,7 @@ [gradientPath addCurveToPoint:CGPointMake(CGRectGetMaxX(gradientRect), edges.origin.y) controlPoint1:CGPointMake(CGRectGetMaxX(edges) + controlX, gradientRect.origin.y) controlPoint2:CGPointMake(CGRectGetMaxX(gradientRect), edges.origin.y - controlY)]; [gradientPath addLineToPoint:CGPointMake(CGRectGetMaxX(gradientRect), CGRectGetMidY(gradientRect))]; - [gradientPath addLineToPoint:CGPointMake(CGRectGetMidX(gradientRect), CGRectGetMidY(gradientRect))]; + [gradientPath addLineToPoint:CGPointMake(CGRectGetMinX(gradientRect), CGRectGetMidY(gradientRect))]; // top left corner [gradientPath addLineToPoint:CGPointMake(gradientRect.origin.x, edges.origin.y)]; diff --git a/Classes/VoiceMob/Views/MGMInboxMessageView.h b/Classes/VoiceMob/Views/MGMInboxMessageView.h index 48397b6..f9fce30 100644 --- a/Classes/VoiceMob/Views/MGMInboxMessageView.h +++ b/Classes/VoiceMob/Views/MGMInboxMessageView.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/30/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import diff --git a/Classes/VoiceMob/Views/MGMInboxMessageView.m b/Classes/VoiceMob/Views/MGMInboxMessageView.m index 5d0eeaa..a8351b1 100644 --- a/Classes/VoiceMob/Views/MGMInboxMessageView.m +++ b/Classes/VoiceMob/Views/MGMInboxMessageView.m @@ -3,15 +3,16 @@ // VoiceMob // // Created by Mr. Gecko on 9/30/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMInboxMessageView.h" #import +#import @implementation MGMInboxMessageView - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { nameField = [[UILabel alloc] initWithFrame:CGRectZero]; [nameField setBackgroundColor:[UIColor clearColor]]; [nameField setFont:[UIFont boldSystemFontOfSize:18.0]]; @@ -33,12 +34,13 @@ return self; } - (void)dealloc { - if (nameField!=nil) - [nameField release]; - if (dateField!=nil) - [dateField release]; - if (messageField!=nil) - [messageField release]; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [nameField release]; + [dateField release]; + [messageField release]; + [messageData release]; [super dealloc]; } @@ -46,7 +48,7 @@ instance = theInstance; } - (void)setMessageData:(NSDictionary *)theMessageData { - if (messageData!=nil) [messageData release]; + [messageData release]; messageData = [theMessageData retain]; } @@ -55,16 +57,15 @@ CGRect frameRect = [[self contentView] bounds]; - if (messageField!=nil) { + if (messageData!=nil) { [nameField setText:[[instance contacts] nameForNumber:[messageData objectForKey:MGMIPhoneNumber]]]; int type = [[messageData objectForKey:MGMIType] intValue]; - if (type==MGMIVoicemailType) { + if (type==MGMIVoicemailType) [messageField setText:[messageData objectForKey:MGMIText]]; - } else if (type==MGMISMSIn || type==MGMISMSOut) { + else if (type==MGMISMSInType || type==MGMISMSOutType) [messageField setText:[[[[messageData objectForKey:MGMIMessages] lastObject] objectForKey:MGMIText] flattenHTML]]; - } else { + else [messageField setText:[[[messageData objectForKey:MGMIPhoneNumber] areaCode] areaCodeLocation]]; - } NSDate *today = [NSDate dateWithTimeIntervalSinceNow:-86400]; if ([[messageData objectForKey:MGMITime] earlierDate:today]==today) { NSDateFormatter *formatter = [[NSDateFormatter new] autorelease]; @@ -77,8 +78,19 @@ } } - [nameField setFrame:CGRectMake(8, 3, frameRect.size.width-74, 20)]; + [nameField setFrame:CGRectMake(20, 3, frameRect.size.width-86, 20)]; [dateField setFrame:CGRectMake(frameRect.size.width-64, 3, 60, 20)]; - [messageField setFrame:CGRectMake(8, frameRect.size.height-35, frameRect.size.width-12, 32)]; + [messageField setFrame:CGRectMake(20, frameRect.size.height-41, frameRect.size.width-18, 32)]; + [self setNeedsDisplay]; +} +- (void)drawRect:(CGRect)rect { + if (messageData!=nil) { + if (![[messageData objectForKey:MGMIRead] boolValue]) { + CGRect frameRect = [[self contentView] bounds]; + MGMPath *path = [MGMPath pathWithRoundedRect:CGRectMake(4, (frameRect.size.height/2)-6.5, 13, 13) cornerRadius:6.5]; + [path fillGradientFrom:[UIColor colorWithRed:0.5215 green:0.6901 blue:0.9607 alpha:1.0] to:[UIColor colorWithRed:0.1255 green:0.3138 blue:0.6589 alpha:1.0]]; + } + } + [super drawRect:rect]; } @end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMMiddleView.h b/Classes/VoiceMob/Views/MGMMiddleView.h new file mode 100644 index 0000000..9140642 --- /dev/null +++ b/Classes/VoiceMob/Views/MGMMiddleView.h @@ -0,0 +1,65 @@ +// +// MGMMiddleView.h +// VoiceMob +// +// Created by Mr. Gecko on 10/11/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +extern NSString * const MGMMTitle; +extern NSString * const MGMMImage; +extern NSString * const MGMMTarget; +extern NSString * const MGMMAction; +extern NSString * const MGMMHighlighted; +extern NSString * const MGMMRect; + +@class MGMMiddleView; + +@interface MGMMiddleViewButton : NSObject { + NSString *title; + NSString *image; + id target; + SEL action; + BOOL highlighted; + CGRect rect; +} ++ (id)buttonWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction; +- (id)initWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction; +- (void)setTitle:(NSString *)theTitle; +- (NSString *)title; +- (void)setImage:(NSString *)theImage; +- (NSString *)image; +- (void)setTarget:(id)theTarget; +- (id)target; +- (void)setAction:(SEL)theAction; +- (SEL)action; +- (void)setHighlighted:(BOOL)isHighlighted; +- (BOOL)highlighted; +- (void)setRect:(CGRect)theRect; +- (CGRect)rect; +@end + +@protocol MGMMiddleViewDelegate +- (void)middleViewDidCancel:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex; +- (void)middleViewDidSelect:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex; +@end + +@interface MGMMiddleView : UIView { + IBOutlet id delegate; + NSMutableArray *buttons; + CGPoint touchStartPoint; + int touchStartIndex; +} +- (void)setDelegate:(id)theDelegate; +- (id)delegate; + +- (void)addButtonWithTitle:(NSString *)theTitle imageName:(NSString *)theImage target:(id)theTarget action:(SEL)theAction; +- (void)setButtons:(NSArray *)theButtons; +- (NSArray *)buttons; + +- (void)updateButtonRects; + +- (void)setHighlighted:(BOOL)isHighlighted forButtonAtIndex:(int)theIndex; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMMiddleView.m b/Classes/VoiceMob/Views/MGMMiddleView.m new file mode 100644 index 0000000..3dd438d --- /dev/null +++ b/Classes/VoiceMob/Views/MGMMiddleView.m @@ -0,0 +1,291 @@ +// +// MGMMiddleView.m +// VoiceMob +// +// Created by Mr. Gecko on 10/11/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMMiddleView.h" +#import + +NSString * const MGMMFontName = @"Helvetica"; + +@implementation MGMMiddleViewButton ++ (id)buttonWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction { + return [[[self alloc] initWithTitle:theTitle image:theImage target:theTarget action:theAction] autorelease]; +} +- (id)initWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction { + if ((self = [super init])) { + title = [theTitle copy]; + image = [theImage copy]; + target = theTarget; + action = theAction; + } + return self; +} +- (void)dealloc { + [title release]; + [image release]; + [super dealloc]; +} +- (void)setTitle:(NSString *)theTitle { + [title release]; + title = [theTitle copy]; +} +- (NSString *)title { + return title; +} +- (void)setImage:(NSString *)theImage { + [image release]; + image = [theImage copy]; +} +- (NSString *)image { + return image; +} +- (void)setTarget:(id)theTarget { + target = theTarget; +} +- (id)target { + return target; +} +- (void)setAction:(SEL)theAction { + action = theAction; +} +- (SEL)action { + return action; +} +- (void)setHighlighted:(BOOL)isHighlighted { + highlighted = isHighlighted; +} +- (BOOL)highlighted { + return highlighted; +} +- (void)setRect:(CGRect)theRect { + rect = theRect; +} +- (CGRect)rect { + return rect; +} +@end + + +@implementation MGMMiddleView +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [buttons release]; + [super dealloc]; +} +- (void)setDelegate:(id)theDelegate { + delegate = theDelegate; +} +- (id)delegate { + return delegate; +} + +- (void)addButtonWithTitle:(NSString *)theTitle imageName:(NSString *)theImage target:(id)theTarget action:(SEL)theAction { + if (buttons==nil) buttons = [NSMutableArray new]; + [buttons addObject:[MGMMiddleViewButton buttonWithTitle:theTitle image:theImage target:theTarget action:theAction]]; + [self updateButtonRects]; + [self setNeedsDisplay]; +} +- (void)setButtons:(NSArray *)theButtons { + [buttons release]; + buttons = [theButtons mutableCopy]; + [self updateButtonRects]; +} +- (NSArray *)buttons { + return buttons; +} + +- (void)updateButtonRects { + CGRect bounds = [self bounds]; + + int count = [buttons count]; + int row = 3; + int numRow = count/row; + if (numRow<=1) { + row = 2; + numRow = count/row; + } + int width = bounds.size.width/row; + int height = bounds.size.height/numRow; + int index = 0; + for (int r=0; r @interface MGMNumberView : UIControl { NSString *number; + NSString *info; + NSString *credit; + UIImage *image; NSString *alphabet; BOOL touching; + + UIColor *startColor; + UIColor *endColor; + UIColor *touchingStartColor; + UIColor *touchingEndColor; + BOOL glass; } -- (NSString *)number; +- (void)setStartColor:(UIColor *)theColor; +- (UIColor *)startColor; +- (void)setEndColor:(UIColor *)theColor; +- (UIColor *)endColor; +- (void)setTouchingStartColor:(UIColor *)theColor; +- (UIColor *)touchingStartColor; +- (void)setTouchingEndColor:(UIColor *)theColor; +- (UIColor *)touchingEndColor; + +- (void)setImage:(UIImage *)theImage; +- (UIImage *)image; - (void)setNumber:(NSString *)theNumber; +- (NSString *)number; +- (void)setInfo:(NSString *)theInfo; +- (NSString *)info; +- (void)setCredit:(NSString *)theCredit; +- (NSString *)credit; +- (void)setAlphabet:(NSString *)theAlphabet; - (NSString *)alphabet; + +- (void)setGlass:(BOOL)isGlass; +- (BOOL)glass; @end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMNumberView.m b/Classes/VoiceMob/Views/MGMNumberView.m index 1f877e5..3a36e9b 100644 --- a/Classes/VoiceMob/Views/MGMNumberView.m +++ b/Classes/VoiceMob/Views/MGMNumberView.m @@ -3,92 +3,111 @@ // VoiceMob // // Created by Mr. Gecko on 9/28/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMNumberView.h" -#import "MGMPath.h" - -NSString * const MGMFontName = @"Helvetica"; +#import @implementation MGMNumberView - (void)dealloc { - if (number!=nil) - [number release]; - if (alphabet!=nil) - [alphabet release]; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [number release]; + [info release]; + [credit release]; + [image release]; + [alphabet release]; + [startColor release]; + [endColor release]; + [touchingStartColor release]; + [touchingEndColor release]; [super dealloc]; } -- (NSString *)number { - if (number==nil) { - switch ([self tag]) { - case -1: - break; - case 10: - number = [@"✱" retain]; - break; - case 11: - number = [@"#" retain]; - break; - case 12: - number = [@"SMS" retain]; - break; - case 13: - number = [@"Call" retain]; - break; - case 14: - number = [@"↵" retain]; - break; - default: - number = [[[NSNumber numberWithInt:[self tag]] stringValue] copy]; - break; - } - } - return number; +- (void)setFrame:(CGRect)frameRect { + [super setFrame:frameRect]; + [self setNeedsDisplay]; +} + +- (void)setStartColor:(UIColor *)theColor { + [startColor release]; + startColor = [theColor retain]; +} +- (UIColor *)startColor { + return startColor; +} +- (void)setEndColor:(UIColor *)theColor { + [endColor release]; + endColor = [theColor retain]; +} +- (UIColor *)endColor { + return endColor; +} +- (void)setTouchingStartColor:(UIColor *)theColor { + [touchingStartColor release]; + touchingStartColor = [theColor retain]; +} +- (UIColor *)touchingStartColor { + return touchingStartColor; +} +- (void)setTouchingEndColor:(UIColor *)theColor { + [touchingEndColor release]; + touchingEndColor = [theColor retain]; +} +- (UIColor *)touchingEndColor { + return touchingEndColor; +} + +- (void)setImage:(UIImage *)theImage { + [image release]; + image = [theImage retain]; + [self setNeedsDisplay]; +} +- (UIImage *)image { + return image; +} +- (void)setInfo:(NSString *)theInfo { + [info release]; + info = [theInfo retain]; + [self setNeedsDisplay]; +} +- (NSString *)info { + return info; +} +- (void)setCredit:(NSString *)theCredit { + [credit release]; + credit = [theCredit retain]; + [self setNeedsDisplay]; +} +- (NSString *)credit { + return credit; } - (void)setNumber:(NSString *)theNumber { - if (number!=nil) [number release]; + [number release]; number = [theNumber copy]; [self setNeedsDisplay]; } +- (NSString *)number { + return number; +} +- (void)setAlphabet:(NSString *)theAlphabet { + [alphabet release]; + alphabet = [theAlphabet copy]; + [self setNeedsDisplay]; +} - (NSString *)alphabet { - if (alphabet==nil) { - switch ([self tag]) { - case 0: - alphabet = [@"+" retain]; - break; - case 2: - alphabet = [@"ABC" retain]; - break; - case 3: - alphabet = [@"DEF" retain]; - break; - case 4: - alphabet = [@"GHI" retain]; - break; - case 5: - alphabet = [@"JKL" retain]; - break; - case 6: - alphabet = [@"MNO" retain]; - break; - case 7: - alphabet = [@"PQRS" retain]; - break; - case 8: - alphabet = [@"TUV" retain]; - break; - case 9: - alphabet = [@"WXYZ" retain]; - break; - default: - break; - } - } return alphabet; } +- (void)setGlass:(BOOL)isGlass { + glass = isGlass; +} +- (BOOL)glass { + return glass; +} + - (void)setTouching:(BOOL)isTouching { touching = isTouching; [self setNeedsDisplay]; @@ -99,7 +118,7 @@ NSString * const MGMFontName = @"Helvetica"; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; - [self setTouching:NO]; + [self setTouching:NO]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; @@ -107,64 +126,113 @@ NSString * const MGMFontName = @"Helvetica"; } - (void)drawRect:(CGRect)frameRect { - UIColor *startColor = nil; - UIColor *endColor = nil; - if (touching) { - startColor = [UIColor colorWithRed:0.5 green:0.5 blue:1.0 alpha:1.0]; - endColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.5 alpha:1.0]; - } else { - if ([self tag]==13) { - startColor = [UIColor colorWithRed:0.5 green:1.0 blue:0.5 alpha:1.0]; - endColor = [UIColor colorWithRed:0.1 green:0.5 blue:0.1 alpha:1.0]; - } else if ([self tag]==14) { - startColor = [UIColor colorWithRed:1.0 green:0.5 blue:0.5 alpha:1.0]; - endColor = [UIColor colorWithRed:0.5 green:0.1 blue:0.1 alpha:1.0]; - } else { - startColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]; - endColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0]; - } + if (startColor==nil) { + startColor = [[UIColor colorWithRed:0.11 green:0.14 blue:0.18 alpha:1.0] retain]; + endColor = [[UIColor colorWithRed:0.04 green:0.06 blue:0.1 alpha:1.0] retain]; + } + if (touchingStartColor==nil) { + UIColor *touchColor = [UIColor colorWithRed:0.12 green:0.42 blue:0.91 alpha:1.0]; + touchingStartColor = [touchColor retain]; + touchingEndColor = [touchColor retain]; } - CGRect bounds = [self bounds]; MGMPath *path = [MGMPath pathWithRect:bounds]; - [path setLineWidth:2.0]; - [[UIColor colorWithWhite:1.0 alpha:1.0] setStroke]; - [path fillGradientFrom:startColor to:endColor]; - [path stroke]; + [path fillGradientFrom:(touching ? touchingStartColor : startColor) to:(touching ? touchingEndColor : endColor)]; + if (glass) { + CGRect glassBounds = bounds; + glassBounds.size.height = glassBounds.size.height/2; + MGMPath *glassPath = [MGMPath pathWithRect:glassBounds]; + [glassPath fillGradientFrom:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.3] to:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.1]]; + } + CGRect line = bounds; + line.size.width += 1.5; + line.size.height += 1.5; + line.origin.x -= 0.2; + line.origin.y -= 0.2; + MGMPath *linePath = [MGMPath pathWithRect:line]; + [[UIColor colorWithRed:0.3 green:0.32 blue:0.36 alpha:1.0] setStroke]; + [linePath setLineWidth:2]; + [linePath stroke]; - [[UIColor whiteColor] set]; - if ([self number]!=nil) { - if ([self tag]>=0 && [self tag]<=11) { - UIFont *font = [UIFont fontWithName:MGMFontName size:bounds.size.height-20.0]; - CGFloat actualSize; - CGSize numberSize = [[self number] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; - font = [UIFont fontWithName:MGMFontName size:actualSize]; - numberSize = [[self number] sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; - CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)/2, 1); - [[self number] drawAtPoint:numberPoint withFont:font]; - } else { - UIFont *font = nil; - if ([self tag]<=13) - font = [UIFont fontWithName:MGMFontName size:bounds.size.height-10.0]; + CGContextRef currentContext = UIGraphicsGetCurrentContext(); + CGContextSaveGState(currentContext); + CGContextSetShadowWithColor(currentContext, CGSizeMake(0, 1), 3.0, [[UIColor colorWithWhite:0.0 alpha:1.0] CGColor]); + [[UIColor whiteColor] setFill]; + if (image!=nil) { + CGRect imageRect; + int y = 1; + if (alphabet!=nil) + imageRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height-20.0); + else + imageRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height-12.0); + + CGSize size = [image size]; + float scaleFactor = 0.0; + float scaledWidth = imageRect.size.width; + float scaledHeight = imageRect.size.height; + + if (!CGSizeEqualToSize(size, imageRect.size)) { + float widthFactor = imageRect.size.width / size.width; + float heightFactor = imageRect.size.height / size.height; + + if (widthFactor < heightFactor) + scaleFactor = widthFactor; else - font = [UIFont fontWithName:MGMFontName size:bounds.size.height-6.0]; - CGFloat actualSize; - CGSize numberSize = [[self number] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; - font = [UIFont fontWithName:MGMFontName size:actualSize]; - numberSize = [[self number] sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; - CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)/2, (bounds.size.height-numberSize.height)/2); - [[self number] drawAtPoint:numberPoint withFont:font]; + scaleFactor = heightFactor; + + scaledWidth = size.width * scaleFactor; + scaledHeight = size.height * scaleFactor; } + + if (alphabet==nil) + y = (bounds.size.height-scaledHeight)/2; + [image drawInRect:CGRectMake((bounds.size.width-scaledWidth)/2, y, scaledWidth, scaledHeight)]; } - - if ([self alphabet]!=nil) { - UIFont *font = [UIFont fontWithName:MGMFontName size:14.0]; + if (number!=nil) { + UIFont *font = nil; + int y = 1; + if (alphabet!=nil) + font = [UIFont boldSystemFontOfSize:bounds.size.height-20.0]; + else + font = [UIFont boldSystemFontOfSize:bounds.size.height-10.0]; CGFloat actualSize; - CGSize alphabetSize = [[self alphabet] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; - font = [UIFont fontWithName:MGMFontName size:actualSize]; - alphabetSize = [[self alphabet] sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; - CGPoint alphabetPoint = CGPointMake((bounds.size.width-alphabetSize.width)/2, bounds.size.height-20); - [[self alphabet] drawAtPoint:alphabetPoint withFont:font]; + CGSize numberSize = [number sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width-4 lineBreakMode:UILineBreakModeClip]; + font = [UIFont boldSystemFontOfSize:actualSize]; + numberSize = [number sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; + if (alphabet==nil) + y = (bounds.size.height-numberSize.height)/2; + CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)/2, y); + [number drawAtPoint:numberPoint withFont:font]; } + if (!touching) + [[UIColor colorWithRed:0.44 green:0.45 blue:0.46 alpha:1.0] setFill]; + if (info!=nil) { + UIFont *font = [UIFont boldSystemFontOfSize:10.0]; + CGFloat actualSize; + CGSize numberSize = [info sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width-4 lineBreakMode:UILineBreakModeClip]; + font = [UIFont boldSystemFontOfSize:actualSize]; + numberSize = [info sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; + CGPoint numberPoint = CGPointMake(4, bounds.size.height-numberSize.height); + [info drawAtPoint:numberPoint withFont:font]; + } + if (credit!=nil) { + UIFont *font = [UIFont boldSystemFontOfSize:10.0]; + CGFloat actualSize; + CGSize numberSize = [credit sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width-4 lineBreakMode:UILineBreakModeClip]; + font = [UIFont boldSystemFontOfSize:actualSize]; + numberSize = [credit sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; + CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)-4, bounds.size.height-numberSize.height); + [credit drawAtPoint:numberPoint withFont:font]; + } + if (alphabet!=nil) { + UIFont *font = [UIFont boldSystemFontOfSize:14.0]; + CGFloat actualSize; + CGSize alphabetSize = [alphabet sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; + font = [UIFont boldSystemFontOfSize:actualSize]; + alphabetSize = [alphabet sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip]; + CGPoint alphabetPoint = CGPointMake((bounds.size.width-alphabetSize.width)/2, bounds.size.height-20); + [alphabet drawAtPoint:alphabetPoint withFont:font]; + } + CGContextRestoreGState(currentContext); } @end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMProgressView.h b/Classes/VoiceMob/Views/MGMProgressView.h index 15da9d0..4df0011 100644 --- a/Classes/VoiceMob/Views/MGMProgressView.h +++ b/Classes/VoiceMob/Views/MGMProgressView.h @@ -1,9 +1,9 @@ // -// MGMLoginProcessView.h +// MGMProgressView.h // VoiceMac // // Created by Mr. Gecko on 8/19/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import diff --git a/Classes/VoiceMob/Views/MGMProgressView.m b/Classes/VoiceMob/Views/MGMProgressView.m index 07a094d..971823d 100644 --- a/Classes/VoiceMob/Views/MGMProgressView.m +++ b/Classes/VoiceMob/Views/MGMProgressView.m @@ -1,16 +1,16 @@ // -// MGMLoginProcessView.m +// MGMProgressView.m // VoiceMac // // Created by Mr. Gecko on 8/19/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMProgressView.h" @implementation MGMProgressView - (id)initWithFrame:(CGRect)frameRect { - if (self = [super initWithFrame:frameRect]) { + if ((self = [super initWithFrame:frameRect])) { [self setBackgroundColor:[UIColor clearColor]]; progress = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; [progress setFrame:CGRectMake((frameRect.size.width-37)/2, (frameRect.size.height-37)/2, 37, 37)]; @@ -31,12 +31,12 @@ return self; } - (void)dealloc { - if (progress) - [progress release]; - if (pleaseWaitField!=nil) - [pleaseWaitField release]; - if (progressField!=nil) - [progressField release]; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [progress release]; + [pleaseWaitField release]; + [progressField release]; [super dealloc]; } - (void)layoutSubviews { diff --git a/Classes/VoiceMob/Views/MGMRecordingView.h b/Classes/VoiceMob/Views/MGMRecordingView.h new file mode 100644 index 0000000..570aac7 --- /dev/null +++ b/Classes/VoiceMob/Views/MGMRecordingView.h @@ -0,0 +1,18 @@ +// +// MGMRecordingView.h +// VoiceMob +// +// Created by Mr. Gecko on 10/14/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import + +@interface MGMRecordingView : UITableViewCell { + UILabel *nameField; + UILabel *dateField; + + NSDictionary *recording; +} +- (void)setRecording:(NSDictionary *)theRecording; +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMRecordingView.m b/Classes/VoiceMob/Views/MGMRecordingView.m new file mode 100644 index 0000000..b68a8c3 --- /dev/null +++ b/Classes/VoiceMob/Views/MGMRecordingView.m @@ -0,0 +1,65 @@ +// +// MGMRecordingView.m +// VoiceMob +// +// Created by Mr. Gecko on 10/14/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMRecordingView.h" +#import "MGMSIPRecordings.h" + +@implementation MGMRecordingView +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { + nameField = [[UILabel alloc] initWithFrame:CGRectZero]; + [nameField setBackgroundColor:[UIColor clearColor]]; + [nameField setFont:[UIFont boldSystemFontOfSize:18.0]]; + [[self contentView] addSubview:nameField]; + dateField = [[UILabel alloc] initWithFrame:CGRectZero]; + [dateField setBackgroundColor:[UIColor clearColor]]; + [dateField setFont:[UIFont systemFontOfSize:12.0]]; + [dateField setTextAlignment:UITextAlignmentRight]; + [dateField setTextColor:[UIColor blueColor]]; + [[self contentView] addSubview:dateField]; + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [nameField release]; + [dateField release]; + [recording release]; + [super dealloc]; +} + +- (void)setRecording:(NSDictionary *)theRecording { + [recording release]; + recording = [theRecording retain]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + CGRect frameRect = [[self contentView] bounds]; + + if (recording!=nil) { + [nameField setText:[recording objectForKey:MGMRName]]; + NSDate *today = [NSDate dateWithTimeIntervalSinceNow:-86400]; + if ([[recording objectForKey:MGMRDate] earlierDate:today]==today) { + NSDateFormatter *formatter = [[NSDateFormatter new] autorelease]; + [formatter setDateFormat:@"h:mm a"]; + [dateField setText:[formatter stringFromDate:[recording objectForKey:MGMRDate]]]; + } else { + NSDateFormatter *formatter = [[NSDateFormatter new] autorelease]; + [formatter setDateFormat:@"M/d/yy"]; + [dateField setText:[formatter stringFromDate:[recording objectForKey:MGMRDate]]]; + } + } + + [nameField setFrame:CGRectMake(8, (frameRect.size.height-20)/2, frameRect.size.width-74, 20)]; + [dateField setFrame:CGRectMake(frameRect.size.width-64, (frameRect.size.height-20)/2, 60, 20)]; +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Views/MGMSMSBottomView.h b/Classes/VoiceMob/Views/MGMSMSBottomView.h index 4893839..a103ce8 100644 --- a/Classes/VoiceMob/Views/MGMSMSBottomView.h +++ b/Classes/VoiceMob/Views/MGMSMSBottomView.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 10/1/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import diff --git a/Classes/VoiceMob/Views/MGMSMSBottomView.m b/Classes/VoiceMob/Views/MGMSMSBottomView.m index d8afa3b..695fd85 100644 --- a/Classes/VoiceMob/Views/MGMSMSBottomView.m +++ b/Classes/VoiceMob/Views/MGMSMSBottomView.m @@ -3,11 +3,11 @@ // VoiceMob // // Created by Mr. Gecko on 10/1/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMSMSBottomView.h" -#import "MGMPath.h" +#import @implementation MGMSMSBottomView - (void)drawRect:(CGRect)frameRect { diff --git a/Classes/VoiceMob/Views/MGMSMSTextView.h b/Classes/VoiceMob/Views/MGMSMSTextView.h index e01cb2f..57ed1e5 100644 --- a/Classes/VoiceMob/Views/MGMSMSTextView.h +++ b/Classes/VoiceMob/Views/MGMSMSTextView.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 10/1/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import diff --git a/Classes/VoiceMob/Views/MGMSMSTextView.m b/Classes/VoiceMob/Views/MGMSMSTextView.m index f0a10e5..2c29d25 100644 --- a/Classes/VoiceMob/Views/MGMSMSTextView.m +++ b/Classes/VoiceMob/Views/MGMSMSTextView.m @@ -3,11 +3,11 @@ // VoiceMob // // Created by Mr. Gecko on 10/1/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMSMSTextView.h" -#import "MGMPath.h" +#import @implementation MGMSMSTextView - (void)awakeFromNib { diff --git a/Classes/VoiceMob/Voice/MGMVoiceContacts.h b/Classes/VoiceMob/Voice/MGMVoiceContacts.h index 67e4a34..cc34c2e 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceContacts.h +++ b/Classes/VoiceMob/Voice/MGMVoiceContacts.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import @@ -11,11 +11,10 @@ @class MGMVoiceUser; -@interface MGMVoiceContacts : MGMContactsController { +@interface MGMVoiceContacts : MGMContactsController { MGMVoiceUser *voiceUser; IBOutlet UIView *view; - NSDictionary *selectedContact; } + (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser; - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser; diff --git a/Classes/VoiceMob/Voice/MGMVoiceContacts.m b/Classes/VoiceMob/Voice/MGMVoiceContacts.m index cf7ca57..0a655ab 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceContacts.m +++ b/Classes/VoiceMob/Voice/MGMVoiceContacts.m @@ -3,11 +3,13 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMVoiceContacts.h" #import "MGMVoiceUser.h" +#import "MGMAccountController.h" +#import "MGMController.h" #import "MGMVoiceSMS.h" #import "MGMVMAddons.h" #import @@ -17,11 +19,18 @@ return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease]; } - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser { - if (self = [super initWithAccountController:[theVoiceUser accountController]]) { + if ((self = [super initWithAccountController:[theVoiceUser accountController]])) { voiceUser = theVoiceUser; } return self; } +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [self releaseView]; + [super dealloc]; +} - (MGMVoiceUser *)voiceUser { return voiceUser; @@ -34,8 +43,6 @@ if (view==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceContacts"] owner:self options:nil]) { NSLog(@"Unable to load Voice Contacts"); - [self release]; - self = nil; } else { [super awakeFromNib]; } @@ -43,32 +50,16 @@ return view; } - (void)releaseView { - if (view!=nil) { - [view release]; - view = nil; - } +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [view release]; + view = nil; [super releaseView]; } - (void)selectedContact:(NSDictionary *)theContact { - selectedContact = theContact; - UIActionSheet *theAction = [[UIActionSheet new] autorelease]; - [theAction addButtonWithTitle:@"Call"]; - [theAction addButtonWithTitle:@"SMS"]; - [theAction addButtonWithTitle:@"Reverse Lookup"]; - [theAction addButtonWithTitle:@"Cancel"]; - [theAction setCancelButtonIndex:3]; - [theAction setDelegate:self]; - [theAction showInView:[voiceUser view]]; -} - -- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { - if (buttonIndex==0) { - [voiceUser call:[selectedContact objectForKey:MGMCNumber]]; - } else if (buttonIndex==1) { - [[[voiceUser tabObjects] objectAtIndex:MGMSMSTabIndex] messageWithNumber:[selectedContact objectForKey:MGMCNumber] instance:[voiceUser instance]]; - } - selectedContact = nil; + [voiceUser showOptionsForNumber:[theContact objectForKey:MGMCNumber]]; [contactsTable deselectRowAtIndexPath:[contactsTable indexPathForSelectedRow] animated:YES]; } @end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoiceInbox.h b/Classes/VoiceMob/Voice/MGMVoiceInbox.h index e8fe920..f0700ad 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceInbox.h +++ b/Classes/VoiceMob/Voice/MGMVoiceInbox.h @@ -3,23 +3,27 @@ // VoiceMob // // Created by Mr. Gecko on 9/30/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import +#import -@class MGMVoiceUser, MGMProgressView, MGMInstance; +@class MGMVoiceUser, MGMProgressView, MGMInstance, MGMURLConnectionManager, AVAudioPlayer; -@interface MGMVoiceInbox : NSObject { +@interface MGMVoiceInbox : NSObject { MGMVoiceUser *voiceUser; - IBOutlet UITableView *inboxesTable; - IBOutlet UITableView *messagesTable; - MGMProgressView *progressView; + NSDate *lastUpdate; + int currentView; + NSArray *inboxItems; + NSArray *recordingItems; - NSArray *messagesItems; - + IBOutlet UITableView *inboxesTable; + IBOutlet UITableView *inboxTable; + IBOutlet UIWebView *recordingView; + MGMProgressView *progressView; int progressStartCount; int currentInbox; @@ -27,23 +31,32 @@ unsigned int start; int resultsCount; - float rightMax; - float leftMax; NSMutableArray *currentData; NSDate *lastDate; + + int currentRecording; + MGMURLConnectionManager *recordingConnection; + AVAudioPlayer *recordingPlayer; + NSTimer *recordingUpdater; } + (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser; - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser; +- (void)registerSettings; + - (MGMVoiceUser *)voiceUser; +- (void)checkVoicemail; + - (UIView *)view; - (void)releaseView; -- (void)startProgress; +- (void)startProgress:(NSString *)theTitle; - (void)stopProgress; - (void)loadInbox; - (void)addData:(NSArray *)theData; - (int)currentInbox; + +- (void)setRecording:(int)theRecording; @end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoiceInbox.m b/Classes/VoiceMob/Voice/MGMVoiceInbox.m index 38538d2..6aca519 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceInbox.m +++ b/Classes/VoiceMob/Voice/MGMVoiceInbox.m @@ -3,20 +3,29 @@ // VoiceMob // // Created by Mr. Gecko on 9/30/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMVoiceInbox.h" #import "MGMVoiceUser.h" #import "MGMAccountController.h" +#import "MGMController.h" #import "MGMVoiceSMS.h" +#import "MGMBadgeView.h" #import "MGMInboxMessageView.h" #import "MGMProgressView.h" #import "MGMVMAddons.h" +#import #import static NSMutableArray *MGMInboxItems; +NSString * const MGMSInboxPlist = @"inbox.plist"; +NSString * const MGMSInbox = @"MGMSInbox"; +NSString * const MGMSLastUpdate = @"MGMSLastUpdate"; +NSString * const MGMSResultsCount = @"MGMSResultsCount"; +NSString * const MGMSStart = @"MGMSStart"; + NSString * const MGMSName = @"name"; NSString * const MGMSID = @"id"; @@ -24,12 +33,15 @@ NSString * const MGMInboxesCellIdentifier = @"MGMInboxesCellIdentifier"; NSString * const MGMInboxMessageCellIdentifier = @"MGMInboxMessageCellIdentifier"; NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellIdentifier"; +NSString * const MGMITLoading = @"Loading..."; +NSString * const MGMITDeleting = @"Deleting..."; + @implementation MGMVoiceInbox + (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser { return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease]; } - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser { - if (self = [super init]) { + if ((self = [super init])) { if (MGMInboxItems==nil) { MGMInboxItems = [NSMutableArray new]; [MGMInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Inbox", MGMSName, [NSNumber numberWithInt:0], MGMSID, nil]]; @@ -44,68 +56,141 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId [MGMInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Missed", MGMSName, [NSNumber numberWithInt:9], MGMSID, nil]]; } voiceUser = theVoiceUser; - currentView = -1; - currentInbox = 0; + + [self registerSettings]; + + lastUpdate = [[[voiceUser user] settingForKey:MGMSLastUpdate] retain]; + + currentView = 1; + currentInbox = [[[voiceUser user] settingForKey:MGMSInbox] intValue]; maxResults = 10; - start = 0; - resultsCount = 0; - messagesItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inboxes" style:UIBarButtonItemStyleBordered target:self action:@selector(showInboxes:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain]; + start = [[[voiceUser user] settingForKey:MGMSStart] intValue]; + resultsCount = [[[voiceUser user] settingForKey:MGMSResultsCount] intValue]; + inboxItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inboxes" style:UIBarButtonItemStyleBordered target:self action:@selector(showInboxes:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain]; + recordingItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inbox" style:UIBarButtonItemStyleBordered target:self action:@selector(showInbox:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain]; currentData = [NSMutableArray new]; + currentRecording = -1; } return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [self releaseView]; + [lastUpdate release]; + [inboxItems release]; + [recordingItems release]; + [currentData release]; + [lastDate release]; + [recordingConnection cancelAll]; + [recordingConnection release]; + [recordingPlayer release]; [super dealloc]; } +- (void)registerSettings { + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMSInbox]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMSResultsCount]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMSStart]; + [[voiceUser user] registerSettings:settings]; +} + - (MGMVoiceUser *)voiceUser { return voiceUser; } +- (NSString *)title { + if (currentRecording!=-1) + return [[[currentData objectAtIndex:currentRecording] objectForKey:MGMIPhoneNumber] readableNumber]; + return [voiceUser title]; +} + +- (void)checkVoicemail { + [[[voiceUser instance] inbox] getVoicemailForPage:1 delegate:self didFailWithError:@selector(voicemail:didFailWithError:instance:) didReceiveInfo:@selector(voicemailGotInfo:instance:)]; +} +- (void)voicemail:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { + NSLog(@"Voicemail Error: %@ for instance: %@", theError, theInstance); +} +- (void)voicemailGotInfo:(NSArray *)theMessages instance:(MGMInstance *)theInstance { + NSDate *newestDate = [NSDate distantPast]; + BOOL newMessage = NO; + for (unsigned int i=0; i<[theMessages count]; i++) { + if (![[[theMessages objectAtIndex:i] objectForKey:MGMIRead] boolValue] && (lastDate==nil || (![lastDate isEqual:[[theMessages objectAtIndex:i] objectForKey:MGMITime]] && [lastDate earlierDate:[[theMessages objectAtIndex:i] objectForKey:MGMITime]]==lastDate))) { + newMessage = YES; + if ([newestDate earlierDate:[[theMessages objectAtIndex:i] objectForKey:MGMITime]]==newestDate) + newestDate = [[theMessages objectAtIndex:i] objectForKey:MGMITime]; + } + } + if (newMessage) { + [lastDate release]; + lastDate = [newestDate copy]; + [[[[voiceUser accountController] controller] themeManager] playSound:MGMTSVoicemail]; + } +} - (UIView *)view { - if (currentView==-1) { - currentView = 1; - [self loadInbox]; - } if (inboxesTable==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceInbox"] owner:self options:nil]) { NSLog(@"Unable to load Voice Inbox"); - [self release]; - self = nil; } else { + if (lastUpdate==nil || [lastUpdate earlierDate:[NSDate dateWithTimeIntervalSinceNow:-300]]==lastUpdate) { + start = 0; + resultsCount = 0; + [self loadInbox]; + } else if ([currentData count]<=0 && [[NSFileManager defaultManager] fileExistsAtPath:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSInboxPlist]]) { + [currentData addObjectsFromArray:[NSArray arrayWithContentsOfFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSInboxPlist]]]; + } CGSize contentSize = [[voiceUser tabView] frame].size; progressView = [[MGMProgressView alloc] initWithFrame:CGRectMake(0, 0, contentSize.width, contentSize.height)]; - [progressView setProgressTitle:@"Loading..."]; - [progressView setHidden:(progressStartCount<=0)]; + if (progressStartCount>0) { + [progressView startProgess]; + [progressView setProgressTitle:MGMITLoading]; + [[voiceUser tabView] performSelector:@selector(addSubview:) withObject:progressView afterDelay:0.1]; + } + [recordingView setDelegate:self]; + [recordingView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"recording" ofType:@"html"]]]]; if (currentView==1) - [[voiceUser accountController] setItems:messagesItems animated:YES]; + [[voiceUser accountController] setItems:inboxItems animated:YES]; + else if (currentView==2) + [[voiceUser accountController] setItems:recordingItems animated:YES]; else [[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES]; - + [[voiceUser accountController] setTitle:[self title]]; } } if (currentView==1) - return messagesTable; + return inboxTable; + if (currentView==2) + return recordingView; return inboxesTable; } - (void)releaseView { - if (inboxesTable!=nil) { - [inboxesTable release]; - inboxesTable = nil; - } - if (messagesTable!=nil) { - [messagesTable release]; - messagesTable = nil; - } - if (progressView!=nil) { - [progressView release]; - progressView = nil; - } +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [inboxesTable release]; + inboxesTable = nil; + [inboxTable release]; + inboxTable = nil; + [progressView release]; + progressView = nil; + [recordingView release]; + recordingView = nil; + [recordingUpdater invalidate]; + [recordingUpdater release]; + recordingUpdater = nil; + [recordingPlayer pause]; + [currentData writeToFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSInboxPlist] atomically:YES]; + [currentData removeAllObjects]; } -- (void)startProgress { +- (void)startProgress:(NSString *)theTitle { if (progressView!=nil) { + [progressView setProgressTitle:theTitle]; + CGRect viewFrame = [progressView frame]; + viewFrame.size = [[voiceUser tabView] frame].size; + [progressView setFrame:viewFrame]; if ([progressView superview]==nil) [[voiceUser tabView] addSubview:progressView]; [progressView startProgess]; @@ -114,17 +199,17 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId progressStartCount++; } - (void)stopProgress { - if (progressView!=nil) { - if (progressStartCount==1) { - [progressView stopProgess]; - [progressView removeFromSuperview]; - } + if (progressStartCount==1) { + [progressView stopProgess]; + [progressView removeFromSuperview]; } progressStartCount--; } - (IBAction)showInboxes:(id)sender { + CGRect outViewFrame = [inboxTable frame]; CGRect inViewFrame = [inboxesTable frame]; + inViewFrame.size = outViewFrame.size; inViewFrame.origin.x = -inViewFrame.size.width; [inboxesTable setFrame:inViewFrame]; [[voiceUser tabView] addSubview:inboxesTable]; @@ -133,56 +218,84 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(inboxesAnimationDidStop:finished:context:)]; - [inboxesTable setFrame:[messagesTable frame]]; - CGRect outViewFrame = [messagesTable frame]; + [inboxesTable setFrame:outViewFrame]; outViewFrame.origin.x = +outViewFrame.size.width; - [messagesTable setFrame:outViewFrame]; + [inboxTable setFrame:outViewFrame]; [UIView commitAnimations]; [[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES]; currentView = 0; } - (void)inboxesAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { - [messagesTable removeFromSuperview]; + [inboxTable removeFromSuperview]; currentInbox = -1; start = 0; resultsCount = 0; [currentData removeAllObjects]; - [messagesTable reloadData]; + [inboxTable reloadData]; } - (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section { if (theTableView==inboxesTable) return [MGMInboxItems count]; - else if (theTableView==messagesTable) + else if (theTableView==inboxTable) return (resultsCount==maxResults ? [currentData count]+1 : [currentData count]); return 0; } - (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (theTableView==inboxesTable) { - UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMInboxesCellIdentifier]; + MGMBadgeView *cell = (MGMBadgeView *)[inboxesTable dequeueReusableCellWithIdentifier:MGMInboxesCellIdentifier]; if (cell==nil) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxesCellIdentifier] autorelease]; + cell = [[[MGMBadgeView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxesCellIdentifier] autorelease]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } - [cell setText:[[MGMInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMSName]]; + NSDictionary *info = [MGMInboxItems objectAtIndex:[indexPath indexAtPosition:1]]; + [cell setName:[info objectForKey:MGMSName]]; + NSString *countName = @""; + int sid = [[info objectForKey:MGMSID] intValue]; + if (sid==0) + countName = MGMUCInbox; + else if (sid==1) + countName = MGMUCStarred; + else if (sid==2) + countName = MGMUCSpam; + else if (sid==3) + countName = MGMUCTrash; + else if (sid==4) + countName = MGMUCVoicemail; + else if (sid==5) + countName = MGMUCSMS; + else if (sid==6) + countName = MGMUCRecorded; + else if (sid==7) + countName = MGMUCPlaced; + else if (sid==8) + countName = MGMUCReceived; + else if (sid==9) + countName = MGMUCMissed; + if ([[[[voiceUser instance] unreadCounts] objectForKey:countName] intValue]!=0) + [cell setBadge:[[[[voiceUser instance] unreadCounts] objectForKey:countName] stringValue]]; + else + [cell setBadge:nil]; return cell; - } else if (theTableView==messagesTable) { + } else if (theTableView==inboxTable) { if ([currentData count]<=[indexPath indexAtPosition:1]) { UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMInboxMessageLoadCellIdentifier]; if (cell==nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxMessageLoadCellIdentifier] autorelease]; - [cell setText:@"Load More..."]; + NSString *text = @"Load More..."; if ([cell respondsToSelector:@selector(textLabel)]) { + [[cell textLabel] setText:text]; [[cell textLabel] setTextColor:[UIColor blueColor]]; [[cell textLabel] setTextAlignment:UITextAlignmentCenter]; } else { + [cell setText:text]; [cell setTextColor:[UIColor blueColor]]; [cell setTextAlignment:UITextAlignmentCenter]; } } return cell; } else { - MGMInboxMessageView *cell = (MGMInboxMessageView *)[messagesTable dequeueReusableCellWithIdentifier:MGMInboxMessageCellIdentifier]; + MGMInboxMessageView *cell = (MGMInboxMessageView *)[inboxTable dequeueReusableCellWithIdentifier:MGMInboxMessageCellIdentifier]; if (cell==nil) { cell = [[[MGMInboxMessageView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxMessageCellIdentifier] autorelease]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; @@ -203,64 +316,94 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId return UITableViewCellEditingStyleDelete; } - (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { - return @"Delete"; + return (currentInbox==3 ? @"Delete Forever" : @"Delete"); } - (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { - + NSDictionary *data = [currentData objectAtIndex:[indexPath indexAtPosition:1]]; + [self startProgress:MGMITDeleting]; + if (currentInbox==3) + [[[voiceUser instance] inbox] deleteEntriesForever:[NSArray arrayWithObject:[data objectForKey:MGMIID]] delegate:self]; + else + [[[voiceUser instance] inbox] deleteEntries:[NSArray arrayWithObject:[data objectForKey:MGMIID]] delegate:self]; +} +- (void)delete:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { + NSLog(@"Delete Error: %@ for instance: %@", theError, theInstance); + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error deleting"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + [self stopProgress]; +} +- (void)deleteDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance { + int dataCount = [currentData count]-1; + for (int i=0; i=[currentData count]) { start += maxResults; [self loadInbox]; } else { - NSDictionary *data = [currentData objectAtIndex:[indexPath indexAtPosition:1]]; - int type = [[data objectForKey:MGMIType] intValue]; - if (type==MGMIVoicemailType) { - - } else if (type==MGMIRecordedType) { - - } else if (type==MGMISMSIn || type==MGMISMSOut) { - [[[voiceUser tabObjects] objectAtIndex:MGMSMSTabIndex] messageWithData:data instance:[voiceUser instance]]; - } else { - - } + NSMutableDictionary *data = [[[currentData objectAtIndex:[indexPath indexAtPosition:1]] mutableCopy] autorelease]; if (![[data objectForKey:MGMIRead] boolValue]) { - + [[[voiceUser instance] inbox] markEntries:[NSArray arrayWithObject:[data objectForKey:MGMIID]] read:![[data objectForKey:MGMIRead] boolValue] delegate:self]; + [data setObject:[NSNumber numberWithBool:![[data objectForKey:MGMIRead] boolValue]] forKey:MGMIRead]; + [currentData replaceObjectAtIndex:[indexPath indexAtPosition:1] withObject:data]; + [inboxTable reloadData]; + } + int type = [[data objectForKey:MGMIType] intValue]; + if (type==MGMIVoicemailType || type==MGMIRecordedType) { + [self setRecording:[indexPath indexAtPosition:1]]; + } else if (type==MGMISMSInType || type==MGMISMSOutType) { + [[[voiceUser tabObjects] objectAtIndex:MGMVUSMSTabIndex] messageWithData:data instance:[voiceUser instance]]; + } else { + [voiceUser showOptionsForNumber:[data objectForKey:MGMIPhoneNumber]]; + [inboxTable deselectRowAtIndexPath:[inboxTable indexPathForSelectedRow] animated:YES]; } } } } -- (void)messagesAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { +- (void)inboxAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { [inboxesTable removeFromSuperview]; [inboxesTable deselectRowAtIndexPath:[inboxesTable indexPathForSelectedRow] animated:NO]; - [[messagesItems objectAtIndex:0] setEnabled:YES]; + [[inboxItems objectAtIndex:0] setEnabled:YES]; } - (void)loadInbox { + [lastUpdate release]; + lastUpdate = [NSDate new]; + [[voiceUser user] setSetting:lastUpdate forKey:MGMSLastUpdate]; + [[voiceUser user] setSetting:[NSNumber numberWithInt:start] forKey:MGMSStart]; int page = (start/maxResults)+1; - [self startProgress]; + [self startProgress:MGMITLoading]; switch (currentInbox) { case 0: [[[voiceUser instance] inbox] getInboxForPage:page delegate:self didFailWithError:@selector(inbox:didFailWithError:instance:) didReceiveInfo:@selector(inboxGotInfo:instance:)]; @@ -294,13 +437,13 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId break; } } -- (void)inbox:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { +- (void)inbox:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { NSLog(@"Inbox Error: %@ for instance: %@", theError, theInstance); - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Error loading inbox"]; - [theAlert setMessage:[theError localizedDescription]]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error loading inbox"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; [self stopProgress]; } - (void)inboxGotInfo:(NSArray *)theInfo instance:(MGMInstance *)theInstance { @@ -312,10 +455,173 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId } - (void)addData:(NSArray *)theData { resultsCount = [theData count]; + [[voiceUser user] setSetting:[NSNumber numberWithInt:resultsCount] forKey:MGMSResultsCount]; [currentData addObjectsFromArray:theData]; - [messagesTable reloadData]; + [inboxTable reloadData]; } - (int)currentInbox { return currentInbox; } + +- (void)setRecording:(int)theRecording { + currentRecording = theRecording; + if (currentRecording==-1) + return; + NSMutableDictionary *data = [currentData objectAtIndex:currentRecording]; + int type = [[data objectForKey:MGMIType] intValue]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerLoading()"]; + NSString *transcript = @""; + if (type==MGMIVoicemailType) + transcript = [data objectForKey:MGMIText]; + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setTranscription('%@')", [transcript javascriptEscape]]]; + + [[recordingItems objectAtIndex:0] setEnabled:NO]; + [[voiceUser accountController] setItems:recordingItems animated:YES]; + + if (recordingConnection==nil) + recordingConnection = [[MGMURLConnectionManager managerWithCookieStorage:[[voiceUser instance] cookieStorage]] retain]; + MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:MGMIVoiceMailDownloadURL, [[data objectForKey:MGMIID] addPercentEscapes]]]] delegate:self]; + [recordingConnection addHandler:handler]; + + CGRect outViewFrame = [inboxTable frame]; + CGRect inViewFrame = [recordingView frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = +inViewFrame.size.width; + [recordingView setFrame:inViewFrame]; + [[voiceUser tabView] addSubview:recordingView]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(recordingAnimationDidStop:finished:context:)]; + [recordingView setFrame:outViewFrame]; + outViewFrame.origin.x = -outViewFrame.size.width; + [inboxTable setFrame:outViewFrame]; + [UIView commitAnimations]; + currentView = 2; + [[voiceUser accountController] setTitle:[self title]]; +} +- (void)recordingAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [inboxTable removeFromSuperview]; + [inboxTable deselectRowAtIndexPath:[inboxTable indexPathForSelectedRow] animated:NO]; + [[recordingItems objectAtIndex:0] setEnabled:YES]; +} + +- (void)request:(MGMURLBasicHandler *)theHandler didFailWithError:(NSError *)theError { + NSLog(@"Starting Audio Error: %@", theError); + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error loading audio"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; +} +- (void)requestDidFinish:(MGMURLBasicHandler *)theHandler { + recordingPlayer = [[AVAudioPlayer alloc] initWithData:[theHandler data] error:nil]; + [recordingPlayer setDelegate:self]; + if (recordingView!=nil) { + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setCurrent(0)"]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"]; + [recordingPlayer play]; + recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain]; + } +} +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPaused()"]; +} +- (void)updateRecording { + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]]; +} +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + NSURL *url = [request URL]; + NSString *scheme = [[url scheme] lowercaseString]; + NSString *data = [url resourceSpecifier]; + NSString *queryData = [url query]; + NSDictionary *query; + if (queryData) { + NSMutableArray *dataArr = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:@"?"]]; + [dataArr removeLastObject]; + data = [dataArr componentsJoinedByString:@"?"]; + NSMutableDictionary *dataDic = [NSMutableDictionary dictionary]; + NSArray *parameters = [queryData componentsSeparatedByString:@"&"]; + for (int i=0; i<[parameters count]; i++) { + NSArray *info = [[parameters objectAtIndex:i] componentsSeparatedByString:@"="]; + [dataDic setObject:[[[info subarrayWithRange:NSMakeRange(1, [info count]-1)] componentsJoinedByString:@"="] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[info objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + } + query = [NSDictionary dictionaryWithDictionary:dataDic]; + } + if ([data hasPrefix:@"//"]) + data = [data substringFromIndex:2]; + + if ([scheme isEqual:@"voicemob"]) { + if ([data isEqual:@"pause"]) + [recordingPlayer pause]; + else if ([data isEqual:@"play"]) + [recordingPlayer play]; + else if ([data isEqual:@"start"]) + [recordingPlayer setCurrentTime:[[query objectForKey:@"time"] intValue]]; + } else if ([scheme isEqual:@"tel"]) { + [voiceUser call:[data phoneFormatWithAreaCode:[voiceUser areaCode]]]; + } else if ([scheme isEqual:@"file"]) { + return YES; + } else { + [[UIApplication sharedApplication] openURL:url]; + } + return NO; +} +- (void)webViewDidFinishLoad:(UIWebView *)webView { + if (currentRecording!=-1) { + if (recordingPlayer!=nil) { + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]]; + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]]; + [recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"]; + [recordingPlayer play]; + recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain]; + } + + NSMutableDictionary *data = [currentData objectAtIndex:currentRecording]; + int type = [[data objectForKey:MGMIType] intValue]; + NSString *transcript = @""; + if (type==MGMIVoicemailType) + transcript = [data objectForKey:MGMIText]; + [recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setTranscription('%@')", [transcript javascriptEscape]]]; + } +} + +- (IBAction)showInbox:(id)sender { + [[inboxItems objectAtIndex:0] setEnabled:NO]; + [[voiceUser accountController] setItems:inboxItems animated:YES]; + + [recordingPlayer release]; + recordingPlayer = nil; + [recordingUpdater invalidate]; + [recordingUpdater release]; + recordingUpdater = nil; + [recordingConnection cancelAll]; + [recordingConnection release]; + recordingConnection = nil; + + CGRect outViewFrame = [recordingView frame]; + CGRect inViewFrame = [inboxTable frame]; + inViewFrame.size = outViewFrame.size; + inViewFrame.origin.x = -inViewFrame.size.width; + [inboxTable setFrame:inViewFrame]; + [[voiceUser tabView] addSubview:inboxTable]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(showInboxAnimationDidStop:finished:context:)]; + [inboxTable setFrame:outViewFrame]; + outViewFrame.origin.x = +outViewFrame.size.width; + [recordingView setFrame:outViewFrame]; + [UIView commitAnimations]; + currentView = 1; +} +- (void)showInboxAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { + [recordingView removeFromSuperview]; + [[inboxItems objectAtIndex:0] setEnabled:YES]; + currentRecording = -1; + [[voiceUser accountController] setTitle:[self title]]; +} @end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoiceMultiSMS.h b/Classes/VoiceMob/Voice/MGMVoiceMultiSMS.h new file mode 100644 index 0000000..b643e59 --- /dev/null +++ b/Classes/VoiceMob/Voice/MGMVoiceMultiSMS.h @@ -0,0 +1,86 @@ +// +// MGMVoiceMultiSMS.h +// VoiceMob +// +// Created by James on 12/2/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import +#import "MGMContactsController.h" + +@class MGMInstance, MGMController, MGMNumberView; + +@interface MGMVoiceMultiSMS : MGMContactsController { + MGMInstance *instance; + MGMController *controller; + + IBOutlet UIView *view; + IBOutlet UIBarButtonItem *sendButton; + IBOutlet UIBarButtonItem *cancelButton; + IBOutlet UITextView *SMSTextView; + IBOutlet UILabel *SMSTextCountField; + + NSArray *groups; + IBOutlet UIButton *groupButton; + IBOutlet UIView *groupView; + IBOutlet UIPickerView *groupPicker; + + NSMutableArray *additional; + IBOutlet UIButton *additionalButton; + IBOutlet UIView *additionalView; + int currentTab; + IBOutlet UIView *tabView; + IBOutlet UITabBar *tabBar; + + IBOutlet UIView *keypadView; + IBOutlet UIView *contactsView; + IBOutlet UITableView *selectedView; + + IBOutlet MGMNumberView *numberView; + IBOutlet MGMNumberView *number1View; + IBOutlet MGMNumberView *number2View; + IBOutlet MGMNumberView *number3View; + IBOutlet MGMNumberView *number4View; + IBOutlet MGMNumberView *number5View; + IBOutlet MGMNumberView *number6View; + IBOutlet MGMNumberView *number7View; + IBOutlet MGMNumberView *number8View; + IBOutlet MGMNumberView *number9View; + IBOutlet MGMNumberView *numberStarView; + IBOutlet MGMNumberView *number0View; + IBOutlet MGMNumberView *numberPondView; + IBOutlet MGMNumberView *numberRemoveView; + IBOutlet MGMNumberView *numberAddView; + IBOutlet MGMNumberView *numberDeleteView; + + IBOutlet UITableView *numbersTable; +} +- (id)initWithInstance:(MGMInstance *)theInstance controller:(MGMController *)theController; + +- (MGMInstance *)instance; +- (MGMController *)controller; +- (UIView *)view; + +- (IBAction)chooseGroup:(id)sender; +- (IBAction)closeGroups:(id)sender; + +- (IBAction)chooseAdditional:(id)sender; + +- (IBAction)numberDecide:(id)sender; +- (IBAction)dial:(id)sender; +- (IBAction)delete:(id)sender; +- (IBAction)add:(id)sender; +- (IBAction)remove:(id)sender; + +- (IBAction)closeAdditional:(id)sender; + +- (IBAction)close:(id)sender; +- (IBAction)send:(id)sender; +@end + +@interface MGMMultiSMSTextView : UITextView { + +} + +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoiceMultiSMS.m b/Classes/VoiceMob/Voice/MGMVoiceMultiSMS.m new file mode 100644 index 0000000..2123860 --- /dev/null +++ b/Classes/VoiceMob/Voice/MGMVoiceMultiSMS.m @@ -0,0 +1,457 @@ +// +// MGMVoiceMultiSMS.m +// VoiceMob +// +// Created by James on 12/2/10. +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// + +#import "MGMVoiceMultiSMS.h" +#import "MGMController.h" +#import "MGMNumberView.h" +#import "MGMVMAddons.h" +#import +#import + +NSString * const MGMAdditionalCellIdentifier = @"MGMAdditionalCellIdentifier"; +NSString * const MGMKeyboardBoundsM = @"UIKeyboardBoundsUserInfoKey"; + +@implementation MGMVoiceMultiSMS +- (id)initWithInstance:(MGMInstance *)theInstance controller:(MGMController *)theController { + if ((self = [super init])) { + if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceMultiSMS"] owner:self options:nil]) { + NSLog(@"Unable to load Multi SMS"); + [self release]; + self = nil; + } else { + instance = theInstance; + controller = theController; + accountController = [controller accountController]; + + groups = [[[instance contacts] groups] retain]; + + additional = [NSMutableArray new]; + + [tabView addSubview:keypadView]; + [tabBar setSelectedItem:[[tabBar items] objectAtIndex:0]]; + + [numberView setNumber:@""]; + [numberView setStartColor:[UIColor colorWithRed:0.19 green:0.22 blue:0.37 alpha:1.0]]; + [numberView setEndColor:[UIColor colorWithRed:0.04 green:0.16 blue:0.33 alpha:1.0]]; + [numberView setGlass:YES]; + [number1View setNumber:@"1"]; + [number1View setAlphabet:@""]; + [number2View setNumber:@"2"]; + [number2View setAlphabet:@"ABC"]; + [number3View setNumber:@"3"]; + [number3View setAlphabet:@"DEF"]; + [number4View setNumber:@"4"]; + [number4View setAlphabet:@"GHI"]; + [number5View setNumber:@"5"]; + [number5View setAlphabet:@"JKL"]; + [number6View setNumber:@"6"]; + [number6View setAlphabet:@"MNO"]; + [number7View setNumber:@"7"]; + [number7View setAlphabet:@"PQRS"]; + [number8View setNumber:@"8"]; + [number8View setAlphabet:@"TUV"]; + [number9View setNumber:@"9"]; + [number9View setAlphabet:@"WXYZ"]; + [numberStarView setNumber:@"✱"]; + [numberStarView setAlphabet:@""]; + [number0View setNumber:@"0"]; + [number0View setAlphabet:@"+"]; + [numberPondView setNumber:@"#"]; + [numberPondView setAlphabet:@""]; + [numberRemoveView setNumber:@"−"]; + [numberRemoveView setStartColor:[UIColor colorWithRed:0.79 green:0.18 blue:0.07 alpha:1.0]]; + [numberRemoveView setEndColor:[UIColor colorWithRed:0.76 green:0.19 blue:0.13 alpha:1.0]]; + [numberRemoveView setGlass:YES]; + [numberAddView setNumber:@"+"]; + [numberAddView setStartColor:[UIColor colorWithRed:0.13 green:0.81 blue:0.1 alpha:1.0]]; + [numberAddView setEndColor:[UIColor colorWithRed:0.11 green:0.69 blue:0.09 alpha:1.0]]; + [numberAddView setGlass:YES]; + [numberDeleteView setImage:[[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DeleteKey" ofType:@"png"]] autorelease]]; + UIColor *darkColor = [UIColor colorWithRed:0.02 green:0.09 blue:0.19 alpha:1.0]; + [numberDeleteView setStartColor:darkColor]; + [numberDeleteView setEndColor:darkColor]; + [numberDeleteView setGlass:YES]; + + + NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter]; + [notifications addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [notifications addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + } + } + return self; +} +- (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [groups release]; + [view release]; + [sendButton release]; + [cancelButton release]; + [SMSTextView release]; + [SMSTextCountField release]; + [groupButton release]; + [groupView release]; + [groupPicker release]; + [tabView release]; + [tabBar release]; + [keypadView release]; + [contactsView release]; + [selectedView release]; + [additional release]; + [additionalButton release]; + [additionalView release]; + [numberView release]; + [number1View release]; + [number2View release]; + [number3View release]; + [number4View release]; + [number5View release]; + [number6View release]; + [number7View release]; + [number8View release]; + [number9View release]; + [numberStarView release]; + [number0View release]; + [numberPondView release]; + [numberRemoveView release]; + [numberAddView release]; + [numberDeleteView release]; + [numbersTable release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (MGMInstance *)instance { + return instance; +} +- (MGMController *)controller { + return controller; +} +- (UIView *)view { + return view; +} + +- (IBAction)chooseGroup:(id)sender { + [SMSTextView resignFirstResponder]; + CGRect inViewFrame = [groupView frame]; + inViewFrame.origin.y = +[[self view] frame].size.height; + [groupView setFrame:inViewFrame]; + [[self view] addSubview:groupView]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [groupView frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [groupView setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { + return 1; +} +- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)theComponent { + return [groups count]+1; +} +- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)theRow forComponent:(NSInteger)theComponent { + if (theRow!=0) { + NSDictionary *group = [groups objectAtIndex:theRow-1]; + return [NSString stringWithFormat:@"%@ (%@)", [group objectForKey:MGMCName], [[instance contacts] membersCountOfGroup:group]]; + } + return @"None"; +} +- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)theRow inComponent:(NSInteger)theComponent { + NSString *title = [self pickerView:thePickerView titleForRow:theRow forComponent:theComponent]; + [groupButton setTitle:title forState:UIControlStateNormal]; +} +- (IBAction)closeGroups:(id)sender { + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:groups:)]; + CGRect outViewFrame = [groupView frame]; + outViewFrame.origin.y = +[[self view] frame].size.height; + [groupView setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished groups:(id)context { + [groupView removeFromSuperview]; +} + +- (IBAction)chooseAdditional:(id)sender { + [SMSTextView resignFirstResponder]; + CGRect inViewFrame = [additionalView frame]; + inViewFrame.origin.y = +[[self view] frame].size.height; + [additionalView setFrame:inViewFrame]; + [[self view] addSubview:additionalView]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [additionalView frame]; + outViewFrame.origin.y -= outViewFrame.size.height; + [additionalView setFrame:outViewFrame]; + [UIView commitAnimations]; +} + +- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)theItem { + int tabIndex = [[tabBar items] indexOfObject:theItem]; + if (tabIndex==currentTab) + return; + + UIView *newTabView = nil; + if (tabIndex==0) + newTabView = keypadView; + else if (tabIndex==1) { + [super awakeFromNib]; + newTabView = contactsView; + } else if (tabIndex==2) { + [selectedView reloadData]; + newTabView = selectedView; + } + CGRect tabFrame = [newTabView frame]; + tabFrame.size = [tabView frame].size; + [newTabView setFrame:tabFrame]; + [tabView addSubview:newTabView]; + if (currentTab==0) + [keypadView removeFromSuperview]; + else if (currentTab==1) { + [super cleanup]; + [contactsView removeFromSuperview]; + } else if (currentTab==2) + [selectedView removeFromSuperview]; + currentTab = tabIndex; +} + +- (IBAction)numberDecide:(id)sender { + UIActionSheet *theAction = [[UIActionSheet new] autorelease]; + [theAction addButtonWithTitle:@"Copy"]; + BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil); + if (pasteEnabled) + [theAction addButtonWithTitle:@"Paste"]; + [theAction addButtonWithTitle:@"Reverse Lookup"]; + [theAction addButtonWithTitle:@"Cancel"]; + [theAction setCancelButtonIndex:(pasteEnabled ? 3 : 2)]; + [theAction setDelegate:self]; + [theAction showInView:additionalView]; +} +- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { + BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil); + if (buttonIndex==0) { + [[UIPasteboard generalPasteboard] setString:[numberView number]]; + } else if (pasteEnabled && buttonIndex==1) { + [numberView setNumber:[[[UIPasteboard generalPasteboard] string] readableNumber]]; + } else if ((pasteEnabled && buttonIndex==2) || (!pasteEnabled && buttonIndex==1)) { + [controller showReverseLookupWithNumber:[[numberView number] phoneFormatWithAreaCode:[instance userAreaCode]]]; + } +} + +- (IBAction)dial:(id)sender { + NSString *number = [numberView number]; + if ([number length]==0 && [sender tag]==0) { + [numberView setNumber:@"+"]; + } else { + NSString *numberAdd = nil; + switch ([sender tag]) { + case 10: + case 11: + break; + default: + numberAdd = [[NSNumber numberWithInt:[sender tag]] stringValue]; + break; + } + if (numberAdd!=nil) + number = [number stringByAppendingString:numberAdd]; + [numberView setNumber:[number readableNumber]]; + } +} +- (IBAction)delete:(id)sender { + NSString *number = [numberView number]; + if ([number length]!=0) { + number = [number substringToIndex:[number length]-1]; + [numberView setNumber:[number readableNumber]]; + } +} +- (IBAction)add:(id)sender { + NSString *number = [[numberView number] phoneFormatWithAreaCode:[instance userAreaCode]]; + if (![additional containsObject:number]) + [additional addObject:number]; + [numberView setNumber:@""]; +} +- (IBAction)remove:(id)sender { + NSString *number = [[numberView number] phoneFormatWithAreaCode:[instance userAreaCode]]; + [additional removeObject:number]; +} + + +- (MGMContacts *)contacts { + return [instance contacts]; +} + +- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)theSection { + if (theTableView!=numbersTable) + return [super tableView:theTableView numberOfRowsInSection:theSection]; + return [additional count]; +} +- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)theIndexPath { + if (theTableView!=numbersTable) + return [super tableView:theTableView cellForRowAtIndexPath:theIndexPath]; + + UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:MGMAdditionalCellIdentifier]; + if (cell==nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMAdditionalCellIdentifier] autorelease]; + } + NSString *number = [[additional objectAtIndex:[theIndexPath indexAtPosition:1]] readableNumber]; + NSString *name = [[instance contacts] nameForNumber:[additional objectAtIndex:[theIndexPath indexAtPosition:1]]]; + if (name!=nil && ![name isEqual:number]) + number = [NSString stringWithFormat:@"%@ (%@)", number, name]; + if ([cell respondsToSelector:@selector(textLabel)]) + [[cell textLabel] setText:number]; + else + [cell setText:number]; + return cell; +} +- (BOOL)tableView:(UITableView *)theTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + if (theTableView==selectedView) + return YES; + return NO; +} +- (UITableViewCellEditingStyle)tableView:(UITableView *)theTableView editingStyleForRowAtIndexPath:(NSIndexPath *)theIndexPath { + return UITableViewCellEditingStyleDelete; +} +- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)theIndexPath { + return @"Remove"; +} +- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)theIndexPath { + [additional removeObjectAtIndex:[theIndexPath indexAtPosition:1]]; + [selectedView reloadData]; +} +- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)theIndexPath { + if (theTableView!=numbersTable) + [super tableView:theTableView didSelectRowAtIndexPath:theIndexPath]; +} + +- (void)selectedContact:(NSDictionary *)theContact { + NSString *number = [theContact objectForKey:MGMCNumber]; + if (![additional containsObject:number]) + [additional addObject:number]; + [contactsTable deselectRowAtIndexPath:[contactsTable indexPathForSelectedRow] animated:YES]; +} + +- (IBAction)closeAdditional:(id)sender { + NSString *numbers = @"None"; + if ([additional count]==1) { + numbers = [[additional objectAtIndex:0] readableNumber]; + } else if ([additional count]>1) { + numbers = [NSString stringWithFormat:@"%@, …", [[additional objectAtIndex:0] readableNumber]]; + } + [additionalButton setTitle:numbers forState:UIControlStateNormal]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:additional:)]; + CGRect outViewFrame = [additionalView frame]; + outViewFrame.origin.y = +[[self view] frame].size.height; + [additionalView setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished additional:(id)context { + [additionalView removeFromSuperview]; +} + + +- (void)keyboardWillShow:(NSNotification *)theNotification { + CGSize keyboardSize = CGSizeZero; + if ([[theNotification userInfo] objectForKey:MGMKeyboardBoundsM]!=nil) + keyboardSize = [[[theNotification userInfo] objectForKey:MGMKeyboardBoundsM] CGRectValue].size; + else + keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + CGRect frame = [SMSTextView frame]; + frame.size.height -= keyboardSize.height; + [SMSTextView setFrame:frame]; +} +- (void)textViewDidChange:(UITextView *)textView { + [SMSTextCountField setText:[[NSNumber numberWithInt:160-[[SMSTextView text] length]] stringValue]]; +} +- (void)keyboardWillHide:(NSNotification *)theNotification { + CGSize keyboardSize = CGSizeZero; + if ([[theNotification userInfo] objectForKey:MGMKeyboardBoundsM]!=nil) + keyboardSize = [[[theNotification userInfo] objectForKey:MGMKeyboardBoundsM] CGRectValue].size; + else + keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + CGRect frame = [SMSTextView frame]; + frame.size.height += keyboardSize.height; + [SMSTextView setFrame:frame]; +} + +- (IBAction)close:(id)sender { + [SMSTextView resignFirstResponder]; + [controller dismissMultiSMS:self]; +} +- (IBAction)send:(id)sender { + NSMutableArray *SMSNumbers = [NSMutableArray arrayWithArray:additional]; + if ([groupPicker selectedRowInComponent:0]!=0) { + NSArray *members = [[instance contacts] membersOfGroupID:[[groups objectAtIndex:[groupPicker selectedRowInComponent:0]-1] objectForKey:MGMCDocID]]; + for (unsigned int i=0; i<[members count]; i++) { + [SMSNumbers addObject:[[members objectAtIndex:i] objectForKey:MGMCNumber]]; + } + } + if ([SMSNumbers count]<=0) { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error sending a SMS Message"]; + [alert setMessage:@"You need to at least have 1 contact to send to."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } else if ([[SMSTextView text] isEqual:@""]) { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error sending a SMS Message"]; + [alert setMessage:@"Message is blank."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } else { + [SMSTextView resignFirstResponder]; + [SMSTextView setEditable:NO]; + [sendButton setTitle:@"Sending..."]; + [sendButton setEnabled:NO]; + [cancelButton setEnabled:NO]; + [[instance inbox] sendMessage:[SMSTextView text] phoneNumbers:SMSNumbers smsID:@"" delegate:self]; + } +} + +- (void)message:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { + [SMSTextView setEditable:YES]; + [sendButton setTitle:@"Send"]; + [sendButton setEnabled:YES]; + [cancelButton setEnabled:YES]; + [SMSTextView becomeFirstResponder]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error sending a SMS Message"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; +} +- (void)messageDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance { + [controller dismissMultiSMS:self]; +} +@end + +@implementation MGMMultiSMSTextView +- (void)awakeFromNib { + [self setContentInset:UIEdgeInsetsMake(0.0, 0.0, 5.0, 0.0)]; +} + +- (void)setContentOffset:(CGPoint)theOffset { + if ([self isTracking] || [self isDecelerating]) { + [self setContentInset:UIEdgeInsetsMake(0.0, 0.0, 5.0, 0.0)]; + [super setContentOffset:theOffset]; + } else { + [super setContentOffset:theOffset]; + [self setContentInset:UIEdgeInsetsMake(0.0, 0.0, 5.0, 0.0)]; + } +} +@end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoicePad.h b/Classes/VoiceMob/Voice/MGMVoicePad.h index 08037cc..2480b7b 100644 --- a/Classes/VoiceMob/Voice/MGMVoicePad.h +++ b/Classes/VoiceMob/Voice/MGMVoicePad.h @@ -3,20 +3,40 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import @class MGMVoiceUser, MGMNumberView; -@interface MGMVoicePad : NSObject { +@interface MGMVoicePad : NSObject { MGMVoiceUser *voiceUser; IBOutlet UIView *view; + NSString *info; + NSString *credit; NSString *numberString; IBOutlet MGMNumberView *numberView; + IBOutlet MGMNumberView *number1View; + IBOutlet MGMNumberView *number2View; + IBOutlet MGMNumberView *number3View; + IBOutlet MGMNumberView *number4View; + IBOutlet MGMNumberView *number5View; + IBOutlet MGMNumberView *number6View; + IBOutlet MGMNumberView *number7View; + IBOutlet MGMNumberView *number8View; + IBOutlet MGMNumberView *number9View; + IBOutlet MGMNumberView *numberStarView; + IBOutlet MGMNumberView *number0View; + IBOutlet MGMNumberView *numberPondView; + IBOutlet MGMNumberView *numberSMSView; + IBOutlet MGMNumberView *numberCallView; + IBOutlet MGMNumberView *numberDeleteView; + + IBOutlet UIView *phonesView; + IBOutlet UIPickerView *phonesPicker; } + (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser; - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser; @@ -26,7 +46,15 @@ - (UIView *)view; - (void)releaseView; +- (void)updateInfo; +- (void)setCredit:(NSString *)theCredit; + +- (IBAction)numberDecide:(id)sender; + +- (IBAction)closePhones:(id)sender; + - (IBAction)dial:(id)sender; - (IBAction)delete:(id)sender; - (IBAction)call:(id)sender; +- (IBAction)sms:(id)sender; @end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoicePad.m b/Classes/VoiceMob/Voice/MGMVoicePad.m index 6bee9e3..9a736b2 100644 --- a/Classes/VoiceMob/Voice/MGMVoicePad.m +++ b/Classes/VoiceMob/Voice/MGMVoicePad.m @@ -3,29 +3,37 @@ // VoiceMob // // Created by Mr. Gecko on 9/29/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMVoicePad.h" #import "MGMVoiceUser.h" +#import "MGMAccountController.h" +#import "MGMController.h" +#import "MGMVoiceSMS.h" #import "MGMNumberView.h" #import "MGMVMAddons.h" #import +#import @implementation MGMVoicePad + (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser { return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease]; } - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser { - if (self = [super init]) { + if ((self = [super init])) { voiceUser = theVoiceUser; } return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [self releaseView]; - if (numberString!=nil) - [numberString release]; + [info release]; + [credit release]; + [numberString release]; [super dealloc]; } @@ -37,22 +45,187 @@ if (view==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoicePad"] owner:self options:nil]) { NSLog(@"Unable to load Voice Pad"); - [self release]; - self = nil; } else { if (numberString!=nil) [numberView setNumber:numberString]; else [numberView setNumber:@""]; + [numberView setInfo:info]; + [numberView setCredit:credit]; + [numberView setStartColor:[UIColor colorWithRed:0.19 green:0.22 blue:0.37 alpha:1.0]]; + [numberView setEndColor:[UIColor colorWithRed:0.04 green:0.16 blue:0.33 alpha:1.0]]; + [numberView setGlass:YES]; + [number1View setNumber:@"1"]; + [number1View setAlphabet:@""]; + [number2View setNumber:@"2"]; + [number2View setAlphabet:@"ABC"]; + [number3View setNumber:@"3"]; + [number3View setAlphabet:@"DEF"]; + [number4View setNumber:@"4"]; + [number4View setAlphabet:@"GHI"]; + [number5View setNumber:@"5"]; + [number5View setAlphabet:@"JKL"]; + [number6View setNumber:@"6"]; + [number6View setAlphabet:@"MNO"]; + [number7View setNumber:@"7"]; + [number7View setAlphabet:@"PQRS"]; + [number8View setNumber:@"8"]; + [number8View setAlphabet:@"TUV"]; + [number9View setNumber:@"9"]; + [number9View setAlphabet:@"WXYZ"]; + [numberStarView setNumber:@"✱"]; + [numberStarView setAlphabet:@""]; + [number0View setNumber:@"0"]; + [number0View setAlphabet:@"+"]; + [numberPondView setNumber:@"#"]; + [numberPondView setAlphabet:@""]; + [numberSMSView setNumber:@"SMS"]; + UIColor *darkColor = [UIColor colorWithRed:0.02 green:0.09 blue:0.19 alpha:1.0]; + [numberSMSView setStartColor:darkColor]; + [numberSMSView setEndColor:darkColor]; + [numberSMSView setGlass:YES]; + [numberCallView setNumber:@"Call"]; + [numberCallView setStartColor:[UIColor colorWithRed:0.13 green:0.81 blue:0.1 alpha:1.0]]; + [numberCallView setEndColor:[UIColor colorWithRed:0.11 green:0.69 blue:0.09 alpha:1.0]]; + [numberCallView setGlass:YES]; + [numberDeleteView setImage:[[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DeleteKey" ofType:@"png"]] autorelease]]; + [numberDeleteView setStartColor:darkColor]; + [numberDeleteView setEndColor:darkColor]; + [numberDeleteView setGlass:YES]; } } return view; } - (void)releaseView { - if (view!=nil) { - [view release]; - view = nil; +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [view release]; + view = nil; + [numberView release]; + numberView = nil; + [number1View release]; + number1View = nil; + [number2View release]; + number2View = nil; + [number3View release]; + number3View = nil; + [number4View release]; + number4View = nil; + [number5View release]; + number5View = nil; + [number6View release]; + number6View = nil; + [number7View release]; + number7View = nil; + [number8View release]; + number8View = nil; + [number9View release]; + number9View = nil; + [numberStarView release]; + numberStarView = nil; + [number0View release]; + number0View = nil; + [numberPondView release]; + numberPondView = nil; + [numberSMSView release]; + numberSMSView = nil; + [numberCallView release]; + numberCallView = nil; + [numberDeleteView release]; + numberDeleteView = nil; + [phonesView release]; + phonesView = nil; + [phonesPicker release]; + phonesPicker = nil; +} + +- (void)updateInfo { + [info release]; + info = nil; + if ([[[voiceUser instance] userPhoneNumbers] count]>=1) { + if ([[[voiceUser instance] userPhoneNumbers] count]<([[[voiceUser user] settingForKey:MGMLastUserPhoneKey] intValue]+1)) + [[voiceUser user] setSetting:[NSNumber numberWithInt:0] forKey:MGMLastUserPhoneKey]; + + NSDictionary *phone = [[[voiceUser instance] userPhoneNumbers] objectAtIndex:[[[voiceUser user] settingForKey:MGMLastUserPhoneKey] intValue]]; + info = [[NSString stringWithFormat:@"%@ [%@]", [[phone objectForKey:MGMPhoneNumber] readableNumber], [phone objectForKey:MGMName]] retain]; } + [numberView setInfo:info]; +} +- (void)setCredit:(NSString *)theCredit { + [credit release]; + credit = [theCredit retain]; + [numberView setCredit:credit]; +} + +- (IBAction)numberDecide:(id)sender { + UIActionSheet *theAction = [[UIActionSheet new] autorelease]; + [theAction addButtonWithTitle:@"Copy"]; + BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil); + if (pasteEnabled) + [theAction addButtonWithTitle:@"Paste"]; + [theAction addButtonWithTitle:@"Reverse Lookup"]; + [theAction addButtonWithTitle:@"Change Ring Phone"]; + [theAction addButtonWithTitle:@"Cancel"]; + [theAction setCancelButtonIndex:(pasteEnabled ? 4 : 3)]; + [theAction setDelegate:self]; + [theAction showInView:[voiceUser view]]; +} +- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { + BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil); + if (buttonIndex==0) { + [[UIPasteboard generalPasteboard] setString:numberString]; + } else if (pasteEnabled && buttonIndex==1) { + [numberString release]; + numberString = [[[[UIPasteboard generalPasteboard] string] readableNumber] copy]; + [numberView setNumber:numberString]; + } else if ((pasteEnabled && buttonIndex==2) || (!pasteEnabled && buttonIndex==1)) { + [[[voiceUser accountController] controller] showReverseLookupWithNumber:[numberString phoneFormatWithAreaCode:[voiceUser areaCode]]]; + } else if ((pasteEnabled && buttonIndex==3) || (!pasteEnabled && buttonIndex==2)) { + [phonesPicker reloadAllComponents]; + [phonesPicker selectRow:[[[voiceUser user] settingForKey:MGMLastUserPhoneKey] intValue] inComponent:0 animated:NO]; + + CGRect inViewFrame = [phonesView frame]; + inViewFrame.origin.y = +([[self view] frame].size.height+[[voiceUser tabBar] frame].size.height); + [phonesView setFrame:inViewFrame]; + [[self view] addSubview:phonesView]; + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + CGRect outViewFrame = [phonesView frame]; + outViewFrame.origin.y -= outViewFrame.size.height+[[voiceUser tabBar] frame].size.height; + [phonesView setFrame:outViewFrame]; + [UIView commitAnimations]; + } +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { + return 1; +} +- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)theComponent { + return [[[voiceUser instance] userPhoneNumbers] count]; +} +- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)theRow forComponent:(NSInteger)theComponent { + NSDictionary *phone = [[[voiceUser instance] userPhoneNumbers] objectAtIndex:theRow]; + return [NSString stringWithFormat:@"%@ [%@]", [[phone objectForKey:MGMPhoneNumber] readableNumber], [phone objectForKey:MGMName]]; +} +- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)theRow inComponent:(NSInteger)theComponent { + [[voiceUser user] setSetting:[NSNumber numberWithInt:theRow] forKey:MGMLastUserPhoneKey]; + [self updateInfo]; +} +- (IBAction)closePhones:(id)sender { + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.5]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:groups:)]; + CGRect outViewFrame = [phonesView frame]; + outViewFrame.origin.y = +([[self view] frame].size.height+[[voiceUser tabBar] frame].size.height); + [phonesView setFrame:outViewFrame]; + [UIView commitAnimations]; +} +- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished groups:(id)context { + [phonesView removeFromSuperview]; } - (IBAction)dial:(id)sender { @@ -71,7 +244,7 @@ } if (numberAdd!=nil) number = [number stringByAppendingString:numberAdd]; - if (numberString!=nil) [numberString release]; + [numberString release]; numberString = [[number readableNumber] copy]; [numberView setNumber:numberString]; } @@ -80,7 +253,7 @@ NSString *number = [numberView number]; if ([number length]!=0) { number = [number substringToIndex:[number length]-1]; - if (numberString!=nil) [numberString release]; + [numberString release]; numberString = [[number readableNumber] copy]; [numberView setNumber:numberString]; } @@ -89,11 +262,22 @@ if ([numberString isPhoneComplete]) { [voiceUser call:[numberString phoneFormatWithAreaCode:[voiceUser areaCode]]]; } else { - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Incorrect Number"]; - [theAlert setMessage:@"The phone number you have entered is incorrect."]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Incorrect Number"]; + [alert setMessage:@"The phone number you have entered is incorrect."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + } +} +- (IBAction)sms:(id)sender { + if ([numberString isPhoneComplete]) { + [[[voiceUser tabObjects] objectAtIndex:MGMVUSMSTabIndex] messageWithNumber:[numberString phoneFormatWithAreaCode:[voiceUser areaCode]] instance:[voiceUser instance]]; + } else { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Incorrect Number"]; + [alert setMessage:@"The phone number you have entered is incorrect."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } } @end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoiceSMS.h b/Classes/VoiceMob/Voice/MGMVoiceSMS.h index 3227289..378ac69 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceSMS.h +++ b/Classes/VoiceMob/Voice/MGMVoiceSMS.h @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/30/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import @@ -14,6 +14,7 @@ MGMVoiceUser *voiceUser; NSArray *messageItems; + NSArray *messagesItems; NSMutableArray *SMSMessages; int currentSMSMessage; diff --git a/Classes/VoiceMob/Voice/MGMVoiceSMS.m b/Classes/VoiceMob/Voice/MGMVoiceSMS.m index 48a53d3..08e82f8 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceSMS.m +++ b/Classes/VoiceMob/Voice/MGMVoiceSMS.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/30/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMVoiceSMS.h" @@ -14,6 +14,9 @@ #import "MGMInboxMessageView.h" #import "MGMVMAddons.h" #import +#import + +NSString * const MGMSMSDB = @"sms.db"; NSString * const MGMMessageViewText = @"MGMMessageViewText"; NSString * const MGMKeyboardBounds = @"UIKeyboardBoundsUserInfoKey"; @@ -27,11 +30,13 @@ const float updateTimeInterval = 300.0; return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease]; } - (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser { - if (self = [super init]) { + if ((self = [super init])) { voiceUser = theVoiceUser; messageItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Messages" style:UIBarButtonItemStyleBordered target:self action:@selector(showMessages:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain]; + messagesItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Accounts" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showAccounts:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showMulti:)] autorelease], nil] retain]; + SMSMessages = [NSMutableArray new]; currentSMSMessage = -1; updateTimer = [[NSTimer scheduledTimerWithTimeInterval:updateTimeInterval target:self selector:@selector(update) userInfo:nil repeats:YES] retain]; @@ -39,7 +44,16 @@ const float updateTimeInterval = 300.0; return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [self releaseView]; + [messageItems release]; + [messagesItems release]; + [SMSMessages release]; + [lastDate release]; + [updateTimer invalidate]; + [updateTimer release]; [super dealloc]; } @@ -49,14 +63,20 @@ const float updateTimeInterval = 300.0; - (MGMThemeManager *)themeManager { return [[[voiceUser accountController] controller] themeManager]; } +- (NSString *)title { + if (currentSMSMessage!=-1) + return [[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMIPhoneNumber] readableNumber]; + return [voiceUser title]; +} - (UIView *)view { if (messageView==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceSMS"] owner:self options:nil]) { NSLog(@"Unable to load Voice SMS"); - [self release]; - self = nil; } else { + if ([SMSMessages count]<=0 && [[NSFileManager defaultManager] fileExistsAtPath:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSMSDB]]) + [SMSMessages addObjectsFromArray:[NSArray arrayWithContentsOfFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSMSDB]]]; + [SMSTextCountField setHidden:YES]; [SMSView setDelegate:self]; if (currentSMSMessage!=-1) { @@ -65,10 +85,12 @@ const float updateTimeInterval = 300.0; [self buildHTML]; [[voiceUser accountController] setItems:messageItems animated:YES]; } else { - [[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES]; + [[voiceUser accountController] setItems:messagesItems animated:YES]; } - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter]; + [notifications addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [notifications addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + [[voiceUser accountController] setTitle:[self title]]; } } if (currentSMSMessage!=-1) @@ -76,25 +98,33 @@ const float updateTimeInterval = 300.0; return messagesTable; } - (void)releaseView { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif [[NSNotificationCenter defaultCenter] removeObserver:self]; - if (messagesTable!=nil) { - [messagesTable release]; - messagesTable = nil; - } + [messagesTable release]; + messagesTable = nil; if (messageView!=nil) { if (currentSMSMessage!=-1) { - NSMutableDictionary *messageInfo = [[SMSMessages objectAtIndex:currentSMSMessage] mutableCopy]; + NSMutableDictionary *messageInfo = [NSMutableDictionary dictionaryWithDictionary:[SMSMessages objectAtIndex:currentSMSMessage]]; [messageInfo setObject:[SMSTextView text] forKey:MGMMessageViewText]; [SMSMessages replaceObjectAtIndex:currentSMSMessage withObject:messageInfo]; - [messageInfo release]; } [messageView release]; messageView = nil; - SMSView = nil; - SMSBottomView = nil; - SMSTextView = nil; - SMSTextCountField = nil; } + [SMSView release]; + SMSView = nil; + [SMSBottomView release]; + SMSBottomView = nil; + [SMSTextView release]; + SMSTextView = nil; + [SMSTextCountField release]; + SMSTextCountField = nil; + [SMSSendButton release]; + SMSSendButton = nil; + [SMSMessages writeToFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSMSDB] atomically:YES]; + [SMSMessages removeAllObjects]; } @@ -106,15 +136,13 @@ const float updateTimeInterval = 300.0; - (void)checkSMSMessages { [[[voiceUser instance] inbox] getSMSForPage:1 delegate:self]; } -- (void)inbox:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { +- (void)inbox:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { NSLog(@"SMS Error: %@ for instance: %@", theError, theInstance); } - (void)inboxGotInfo:(NSArray *)theMessages instance:(MGMInstance *)theInstance { - if (updateTimer!=nil) { - [updateTimer invalidate]; - [updateTimer release]; - updateTimer = [[NSTimer scheduledTimerWithTimeInterval:updateTimeInterval target:self selector:@selector(update) userInfo:nil repeats:YES] retain]; - } + [updateTimer invalidate]; + [updateTimer release]; + updateTimer = [[NSTimer scheduledTimerWithTimeInterval:updateTimeInterval target:self selector:@selector(update) userInfo:nil repeats:YES] retain]; NSDate *newestDate = [NSDate distantPast]; BOOL newMessage = NO; BOOL newTab = NO; @@ -144,7 +172,7 @@ const float updateTimeInterval = 300.0; } } if (newMessage) { - if (lastDate!=nil) [lastDate release]; + [lastDate release]; lastDate = [newestDate copy]; [[self themeManager] playSound:MGMTSSMSMessage]; if (currentSMSMessage==-1 && messagesTable!=nil) @@ -165,7 +193,7 @@ const float updateTimeInterval = 300.0; [self view]; NSMutableDictionary *messageInfo = [NSMutableDictionary dictionary]; [messageInfo setObject:[NSArray array] forKey:MGMIMessages]; - [messageInfo setObject:[NSNumber numberWithInt:MGMISMSOut] forKey:MGMIType]; + [messageInfo setObject:[NSNumber numberWithInt:MGMISMSOutType] forKey:MGMIType]; [messageInfo setObject:[NSDate date] forKey:MGMITime]; [messageInfo setObject:[[theInstance contacts] nameForNumber:theNumber] forKey:MGMTInName]; [messageInfo setObject:theNumber forKey:MGMIPhoneNumber]; @@ -180,11 +208,15 @@ const float updateTimeInterval = 300.0; if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil) [SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]]; [self buildHTML]; - UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex]; + UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex]; [[voiceUser tabBar] setSelectedItem:thisTab]; [voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab]; + CGRect viewFrame = [messageView frame]; + viewFrame.size = [[voiceUser tabView] frame].size; + [messageView setFrame:viewFrame]; [[voiceUser tabView] addSubview:messageView]; [messagesTable removeFromSuperview]; + [[voiceUser accountController] setTitle:[self title]]; break; } } @@ -195,11 +227,15 @@ const float updateTimeInterval = 300.0; if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil) [SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]]; [self buildHTML]; - UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex]; + UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex]; [[voiceUser tabBar] setSelectedItem:thisTab]; [voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab]; + CGRect viewFrame = [messageView frame]; + viewFrame.size = [[voiceUser tabView] frame].size; + [messageView setFrame:viewFrame]; [[voiceUser tabView] addSubview:messageView]; [messagesTable removeFromSuperview]; + [[voiceUser accountController] setTitle:[self title]]; } [[voiceUser accountController] setItems:messageItems animated:YES]; } @@ -215,7 +251,7 @@ const float updateTimeInterval = 300.0; [SMSView loadHTMLString:@"" baseURL:nil]; } [self view]; - NSMutableDictionary *messageInfo = [NSMutableDictionary dictionaryWithDictionary:theData]; + NSMutableDictionary *messageInfo = [[theData mutableCopy] autorelease]; [messageInfo setObject:[[theInstance contacts] nameForNumber:[messageInfo objectForKey:MGMIPhoneNumber]] forKey:MGMTInName]; [messageInfo setObject:[theInstance userNumber] forKey:MGMTUserNumber]; BOOL window = NO; @@ -227,11 +263,15 @@ const float updateTimeInterval = 300.0; if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil) [SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]]; [self buildHTML]; - UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex]; + UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex]; [[voiceUser tabBar] setSelectedItem:thisTab]; [voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab]; + CGRect viewFrame = [messageView frame]; + viewFrame.size = [[voiceUser tabView] frame].size; + [messageView setFrame:viewFrame]; [[voiceUser tabView] addSubview:messageView]; [messagesTable removeFromSuperview]; + [[voiceUser accountController] setTitle:[self title]]; break; } } @@ -242,22 +282,30 @@ const float updateTimeInterval = 300.0; if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil) [SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]]; [self buildHTML]; - UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex]; + UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex]; [[voiceUser tabBar] setSelectedItem:thisTab]; [voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab]; + CGRect viewFrame = [messageView frame]; + viewFrame.size = [[voiceUser tabView] frame].size; + [messageView setFrame:viewFrame]; [[voiceUser tabView] addSubview:messageView]; [messagesTable removeFromSuperview]; + [[voiceUser accountController] setTitle:[self title]]; } [[voiceUser accountController] setItems:messageItems animated:YES]; } +- (IBAction)showMulti:(id)sender { + [[[voiceUser accountController] controller] showMultiSMSWithInstance:[voiceUser instance]]; +} + - (IBAction)showMessages:(id)sender { if (sendingMessage) { - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Sending a SMS Message"]; - [theAlert setMessage:@"Your SMS Message is currently being sent, please wait for it to be sent."]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Sending a SMS Message"]; + [alert setMessage:@"Your SMS Message is currently being sent, please wait for it to be sent."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } else if (marking) { } else if (![[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMIRead] boolValue]) { @@ -265,7 +313,9 @@ const float updateTimeInterval = 300.0; [[[voiceUser instance] inbox] markEntries:[NSArray arrayWithObject:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMIID]] read:YES delegate:self]; } else { [messagesTable reloadData]; + CGRect outViewFrame = [messageView frame]; CGRect inViewFrame = [messagesTable frame]; + inViewFrame.size = outViewFrame.size; inViewFrame.origin.x = -inViewFrame.size.width; [messagesTable setFrame:inViewFrame]; [[voiceUser tabView] addSubview:messagesTable]; @@ -274,23 +324,22 @@ const float updateTimeInterval = 300.0; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(messagesAnimationDidStop:finished:context:)]; - [messagesTable setFrame:[messageView frame]]; - CGRect outViewFrame = [messageView frame]; + [messagesTable setFrame:outViewFrame]; outViewFrame.origin.x = +outViewFrame.size.width; [messageView setFrame:outViewFrame]; [UIView commitAnimations]; - [[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES]; + [[voiceUser accountController] setItems:messagesItems animated:YES]; } } -- (void)mark:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { +- (void)mark:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { marking = NO; - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Error marking as read"]; - [theAlert setMessage:[theError localizedDescription]]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error marking as read"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } -- (void)markDidFinish:(NSDictionary *)theInfo instance:(MGMInstance *)theInstance { +- (void)markDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance { marking = NO; [self setMessage:currentSMSMessage read:YES]; [self showMessages:self]; @@ -305,6 +354,7 @@ const float updateTimeInterval = 300.0; [self textViewDidChange:SMSTextView]; currentSMSMessage = -1; [SMSView loadHTMLString:@"" baseURL:nil]; + [[voiceUser accountController] setTitle:[self title]]; } - (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section { @@ -341,7 +391,9 @@ const float updateTimeInterval = 300.0; [[messageItems objectAtIndex:0] setEnabled:NO]; [[voiceUser accountController] setItems:messageItems animated:YES]; + CGRect outViewFrame = [messagesTable frame]; CGRect inViewFrame = [messageView frame]; + inViewFrame.size = outViewFrame.size; inViewFrame.origin.x = +inViewFrame.size.width; [messageView setFrame:inViewFrame]; [[voiceUser tabView] addSubview:messageView]; @@ -350,8 +402,7 @@ const float updateTimeInterval = 300.0; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(messageAnimationDidStop:finished:context:)]; - [messageView setFrame:[messagesTable frame]]; - CGRect outViewFrame = [messagesTable frame]; + [messageView setFrame:outViewFrame]; outViewFrame.origin.x = -outViewFrame.size.width; [messagesTable setFrame:outViewFrame]; [UIView commitAnimations]; @@ -360,6 +411,7 @@ const float updateTimeInterval = 300.0; [messagesTable removeFromSuperview]; [messagesTable deselectRowAtIndexPath:[messagesTable indexPathForSelectedRow] animated:NO]; [[messageItems objectAtIndex:0] setEnabled:YES]; + [[voiceUser accountController] setTitle:[self title]]; } - (void)setMessage:(int)theMessage read:(BOOL)isRead { @@ -460,9 +512,8 @@ const float updateTimeInterval = 300.0; UIScrollView *SMSScrollView = [[SMSView subviews] objectAtIndex:0]; [SMSScrollView setContentInset:UIEdgeInsetsZero]; [SMSScrollView setScrollIndicatorInsets:UIEdgeInsetsZero]; - if (heightDifference<0) { + if (heightDifference<0) [SMSScrollView scrollRectToVisible:CGRectMake(0, [SMSScrollView contentSize].height-44, 320, 44) animated:NO]; - } } if (![SMSTextCountField isHidden]) [SMSTextCountField setText:[[NSNumber numberWithInt:160-[[SMSTextView text] length]] stringValue]]; @@ -486,7 +537,7 @@ const float updateTimeInterval = 300.0; [SMSView setFrame:SMSViewFrame]; UIScrollView *SMSScrollView = [[SMSView subviews] objectAtIndex:0]; UIEdgeInsets SMSScrollContentInset = [SMSScrollView contentInset]; - SMSScrollContentInset.bottom += (keyboardSize.height-SMSBottomFrame.size.height)-SMSViewHeightDifference; + //SMSScrollContentInset.bottom -= (keyboardSize.height-SMSBottomFrame.size.height)-SMSViewHeightDifference; [SMSScrollView setContentInset:SMSScrollContentInset]; UIEdgeInsets SMSScrollInset = [SMSScrollView scrollIndicatorInsets]; SMSScrollInset.bottom += (keyboardSize.height-SMSBottomFrame.size.height)-SMSViewHeightDifference; @@ -518,14 +569,15 @@ const float updateTimeInterval = 300.0; [message setObject:[messageInfo objectForKey:MGMIPhoneNumber] forKey:MGMIPhoneNumber]; } [messageArray addObject:message]; - }NSString *html = [[self themeManager] buildHTMLWithMessages:messageArray messageInfo:messageInfo]; + } + NSString *html = [[self themeManager] buildHTMLWithMessages:messageArray messageInfo:messageInfo]; [SMSView loadHTMLString:html baseURL:[NSURL fileURLWithPath:[[self themeManager] currentThemeVariantPath]]]; } - (void)webViewDidFinishLoad:(UIWebView *)webView { [SMSView stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"]; } - (void)addMessage:(NSDictionary *)theMessage withInfo:(NSMutableDictionary *)theMessageInfo { - NSArray *messages = [theMessageInfo objectForKey:MGMIMessage]; + NSArray *messages = [theMessageInfo objectForKey:MGMIMessages]; NSString *yPhotoPath = [[[voiceUser instance] contacts] cachedPhotoForNumber:[theMessageInfo objectForKey:MGMTUserNumber]]; if (yPhotoPath==nil) yPhotoPath = [[[self themeManager] outgoingIconPath] filePath]; @@ -534,21 +586,31 @@ const float updateTimeInterval = 300.0; tPhotoPath = [[[self themeManager] incomingIconPath] filePath]; NSMutableDictionary *message = [NSMutableDictionary dictionaryWithDictionary:theMessage]; [message setObject:[[NSNumber numberWithInt:[messages count]-1] stringValue] forKey:MGMIID]; + NSMutableArray *classes = [NSMutableArray array]; int type = 1; if ([[message objectForKey:MGMIYou] boolValue]) { + [classes addObject:MGMTCOutgoing]; type = (([[message objectForKey:MGMIID] intValue]==0 || ![[[messages objectAtIndex:[[message objectForKey:MGMIID] intValue]-1] objectForKey:MGMIYou] boolValue]) ? 1 : 2); + if (type==2) + [classes addObject:MGMTCNext]; [message setObject:yPhotoPath forKey:MGMTPhoto]; [message setObject:NSFullUserName() forKey:MGMTName]; [message setObject:[theMessageInfo objectForKey:MGMTUserNumber] forKey:MGMIPhoneNumber]; } else { + [classes addObject:MGMTCIncoming]; type = (([[message objectForKey:MGMIID] intValue]==0 || [[[messages objectAtIndex:[[message objectForKey:MGMIID] intValue]-1] objectForKey:MGMIYou] boolValue]) ? 3 : 4); + if (type==4) + [classes addObject:MGMTCNext]; [message setObject:tPhotoPath forKey:MGMTPhoto]; [message setObject:[theMessageInfo objectForKey:MGMTInName] forKey:MGMTName]; [message setObject:[theMessageInfo objectForKey:MGMIPhoneNumber] forKey:MGMIPhoneNumber]; } + [classes addObject:MGMTCMessage]; + if (![[NSUserDefaults standardUserDefaults] boolForKey:MGMTShowIcons]) + [classes addObject:MGMTCHideIcons]; NSDateFormatter *formatter = [[NSDateFormatter new] autorelease]; [formatter setDateFormat:[[[self themeManager] variant] objectForKey:MGMTDate]]; - [SMSView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"newMessage('%@', '%@', '%@', %@, '%@', '%@', '%@', %d);", [[message objectForKey:MGMIText] escapeSMS], [[message objectForKey:MGMTPhoto] escapeSMS], [[message objectForKey:MGMITime] escapeSMS], [message objectForKey:MGMIID], [[message objectForKey:MGMTName] escapeSMS], [[[message objectForKey:MGMIPhoneNumber] readableNumber] escapeSMS], [formatter stringFromDate:[theMessageInfo objectForKey:MGMITime]], type]]; + [SMSView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"newMessage('%@', '%@', '%@', %@, '%@', '%@', '%@', %d, '%@');", [[[self themeManager] htmlTextFromMessage:message] javascriptEscape], [[message objectForKey:MGMTPhoto] javascriptEscape], [[message objectForKey:MGMITime] javascriptEscape], [message objectForKey:MGMIID], [[message objectForKey:MGMTName] javascriptEscape], [[[message objectForKey:MGMIPhoneNumber] readableNumber] javascriptEscape], [formatter stringFromDate:[theMessageInfo objectForKey:MGMITime]], type, [classes componentsJoinedByString:@" "]]]; [SMSView stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"]; } @@ -561,25 +623,25 @@ const float updateTimeInterval = 300.0; [SMSTextView setText:@""]; [self textViewDidChange:SMSTextView]; } -- (void)message:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { +- (void)message:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance { sendingMessage = NO; [SMSSendButton setEnabled:YES]; - [SMSTextView setText:[[theInfo objectForKey:MGMIMessage] stringByAppendingFormat:@" %@", [SMSTextView text]]]; + [SMSTextView setText:[[theInfo message] stringByAppendingFormat:@" %@", [SMSTextView text]]]; [self textViewDidChange:SMSTextView]; [SMSTextView becomeFirstResponder]; - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Error sending a SMS Message"]; - [theAlert setMessage:[theError localizedDescription]]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error sending a SMS Message"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } -- (void)messageDidFinish:(NSDictionary *)theInfo instance:(MGMInstance *)theInstance { +- (void)messageDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance { sendingMessage = NO; NSDateFormatter *formatter = [[NSDateFormatter new] autorelease]; [formatter setDateFormat:@"h:mm a"]; NSMutableDictionary *messageInfo = [[SMSMessages objectAtIndex:currentSMSMessage] mutableCopy]; NSMutableArray *messages = [[messageInfo objectForKey:MGMIMessages] mutableCopy]; - NSDictionary *message = [NSDictionary dictionaryWithObjectsAndKeys:[theInfo objectForKey:MGMIMessage], MGMIText, [formatter stringFromDate:[NSDate date]], MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]; + NSDictionary *message = [NSDictionary dictionaryWithObjectsAndKeys:[theInfo message], MGMIText, [formatter stringFromDate:[NSDate date]], MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]; [messages addObject:message]; [messageInfo setObject:messages forKey:MGMIMessages]; [messageInfo setObject:[NSDate date] forKey:MGMITime]; diff --git a/Classes/VoiceMob/Voice/MGMVoiceUser.h b/Classes/VoiceMob/Voice/MGMVoiceUser.h index 33cf462..48c39b1 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceUser.h +++ b/Classes/VoiceMob/Voice/MGMVoiceUser.h @@ -3,17 +3,19 @@ // VoiceMob // // Created by Mr. Gecko on 9/28/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // -#import +#import @class MGMVoiceUser, MGMAccountController, MGMUser, MGMInstance, MGMProgressView; -extern const int MGMKeypadTabIndex; -extern const int MGMContactsTabIndex; -extern const int MGMSMSTabIndex; -extern const int MGMInboxTabIndex; +extern const int MGMVUKeypadTabIndex; +extern const int MGMVUContactsTabIndex; +extern const int MGMVUSMSTabIndex; +extern const int MGMVUInboxTabIndex; + +extern NSString * const MGMLastUserPhoneKey; @protocol MGMVoiceUserTabProtocol + (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser; @@ -25,7 +27,7 @@ extern const int MGMInboxTabIndex; - (void)releaseView; @end -@interface MGMVoiceUser : NSObject { +@interface MGMVoiceUser : NSObject { MGMAccountController *accountController; MGMUser *user; MGMInstance *instance; @@ -34,6 +36,8 @@ extern const int MGMInboxTabIndex; NSMutableArray *tabObjects; MGMProgressView *progressView; + UIAlertView *verificationView; + UITextField *verificationField; IBOutlet UIView *view; IBOutlet UIView *tabView; IBOutlet UITabBar *tabBar; @@ -41,10 +45,18 @@ extern const int MGMInboxTabIndex; BOOL placingCall; NSTimer *callTimer; UIAlertView *callCancelView; + + NSString *currentPhoneNumber; + + NSString *optionsNumber; + + int unreadCount; } + (id)voiceUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController; - (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController; +- (void)registerSettings; + - (MGMAccountController *)accountController; - (MGMUser *)user; - (MGMInstance *)instance; @@ -61,7 +73,11 @@ extern const int MGMInboxTabIndex; - (void)setInstanceInfo; - (BOOL)isPlacingCall; +- (void)donePlacingCall; +- (NSString *)currentPhoneNumber; - (void)call:(NSString *)theNumber; - (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item; + +- (void)showOptionsForNumber:(NSString *)theNumber; @end \ No newline at end of file diff --git a/Classes/VoiceMob/Voice/MGMVoiceUser.m b/Classes/VoiceMob/Voice/MGMVoiceUser.m index 03acb82..aa1be32 100644 --- a/Classes/VoiceMob/Voice/MGMVoiceUser.m +++ b/Classes/VoiceMob/Voice/MGMVoiceUser.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/28/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import "MGMVoiceUser.h" @@ -13,43 +13,69 @@ #import "MGMVoiceInbox.h" #import "MGMProgressView.h" #import "MGMAccountController.h" +#import "MGMController.h" #import "MGMVMAddons.h" #import #import -const int MGMKeypadTabIndex = 0; -const int MGMContactsTabIndex = 1; -const int MGMSMSTabIndex = 2; -const int MGMInboxTabIndex = 3; +const int MGMVUKeypadTabIndex = 0; +const int MGMVUContactsTabIndex = 1; +const int MGMVUSMSTabIndex = 2; +const int MGMVUInboxTabIndex = 3; + +NSString * const MGMVUCurrentTab = @"MGMVUCurrentTab"; +NSString * const MGMLastUserPhoneKey = @"MGMLastUserPhone"; @implementation MGMVoiceUser + (id)voiceUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController { return [[[self alloc] initWithUser:theUser accountController:theAccountController] autorelease]; } - (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController { - if (self = [super init]) { + if ((self = [super init])) { accountController = theAccountController; user = [theUser retain]; + [self registerSettings]; - currentTab = 0; - tabObjects = [NSMutableArray new]; - [tabObjects addObject:[MGMVoicePad tabWithVoiceUser:self]]; - [tabObjects addObject:[MGMVoiceContacts tabWithVoiceUser:self]]; - [tabObjects addObject:[MGMVoiceSMS tabWithVoiceUser:self]]; - [tabObjects addObject:[MGMVoiceInbox tabWithVoiceUser:self]]; - - if ([user isStarted]) + if ([user isStarted]) { + currentTab = [[user settingForKey:MGMVUCurrentTab] intValue]; + tabObjects = [NSMutableArray new]; + [tabObjects addObject:[MGMVoicePad tabWithVoiceUser:self]]; + [tabObjects addObject:[MGMVoiceContacts tabWithVoiceUser:self]]; + [tabObjects addObject:[MGMVoiceSMS tabWithVoiceUser:self]]; + [tabObjects addObject:[MGMVoiceInbox tabWithVoiceUser:self]]; + instance = [[MGMInstance instanceWithUser:user delegate:self] retain]; + } + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(becameActive) name:UIApplicationDidBecomeActiveNotification object:nil]; } return self; } - (void)dealloc { +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [[NSNotificationCenter defaultCenter] removeObserver:self]; [self releaseView]; - if (user!=nil) - [user release]; + [tabObjects release]; + [callTimer invalidate]; + [callTimer release]; + [callCancelView release]; + [optionsNumber release]; + [instance stop]; + [instance release]; + [user release]; + [currentPhoneNumber release]; + [optionsNumber release]; [super dealloc]; } +- (void)registerSettings { + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings setObject:[NSNumber numberWithInt:0] forKey:MGMLastUserPhoneKey]; + [settings setObject:[NSNumber numberWithInt:MGMVUKeypadTabIndex] forKey:MGMVUCurrentTab]; + [user registerSettings:settings]; +} + - (MGMAccountController *)accountController { return accountController; } @@ -74,8 +100,6 @@ const int MGMInboxTabIndex = 3; if (view==nil) { if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceUser"] owner:self options:nil]) { NSLog(@"Unable to load Voice User"); - [self release]; - self = nil; } else { [tabView addSubview:[[tabObjects objectAtIndex:currentTab] view]]; [tabBar setSelectedItem:[[tabBar items] objectAtIndex:currentTab]]; @@ -88,6 +112,10 @@ const int MGMInboxTabIndex = 3; [progressView becomeFirstResponder]; } else { [self setInstanceInfo]; + if (unreadCount!=0) + [[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:[[NSNumber numberWithInt:unreadCount] stringValue]]; + else + [[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:nil]; } } } @@ -103,37 +131,67 @@ const int MGMInboxTabIndex = 3; return tabBar; } - (void)releaseView { - if (view!=nil) { - [view release]; - view = nil; - [[tabObjects objectAtIndex:currentTab] releaseView]; - } +#if releaseDebug + NSLog(@"%s Releasing", __PRETTY_FUNCTION__); +#endif + [[tabObjects objectAtIndex:currentTab] releaseView]; + [view release]; + view = nil; + [tabView release]; + tabView = nil; + [tabBar release]; + tabBar = nil; + [progressView stopProgess]; + [progressView release]; + progressView = nil; } - (void)loginError:(NSError *)theError { - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Error logging in"]; - [theAlert setMessage:[theError localizedDescription]]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Error logging in"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; - if (progressView!=nil) { - [progressView stopProgess]; - [progressView removeFromSuperview]; - [progressView release]; - progressView = nil; - } + [verificationView release]; + verificationView = nil; + [verificationField release]; + verificationField = nil; + [progressView stopProgess]; + [progressView removeFromSuperview]; + [progressView release]; + progressView = nil; +} +- (void)loginVerificationRequested { + [verificationView release]; + verificationView = [UIAlertView new]; + [verificationView setTitle:@"Account Verification"]; + [verificationView setMessage:@" "]; + [verificationView addButtonWithTitle:@"Cancel"]; + [verificationView addButtonWithTitle:@"Verify"]; + [verificationView setCancelButtonIndex:1]; + [verificationView setDelegate:self]; + [verificationField release]; + verificationField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)]; + [verificationField setBorderStyle:UITextBorderStyleLine]; + [verificationField setBackgroundColor:[UIColor whiteColor]]; + [verificationField setKeyboardType:UIKeyboardTypeNumbersAndPunctuation]; + [verificationView addSubview:verificationField]; + [verificationView show]; + [verificationField becomeFirstResponder]; } - (void)loginSuccessful { - if (progressView!=nil) { - [progressView stopProgess]; - [progressView setNeedsDisplay]; - } + [verificationView release]; + verificationView = nil; + [verificationField release]; + verificationField = nil; + [progressView stopProgess]; + [progressView setNeedsDisplay]; [self setInstanceInfo]; if ([accountController isCurrent:self]) - [accountController setTitle:[[instance userNumber] readableNumber]]; + [accountController setTitle:[self title]]; if (progressView!=nil) { [UIView beginAnimations:nil context:nil]; @@ -146,92 +204,163 @@ const int MGMInboxTabIndex = 3; } } - (void)setInstanceInfo { - + [[tabObjects objectAtIndex:MGMVUKeypadTabIndex] updateInfo]; } - (void)progressFadeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { - if (progressView!=nil) { - [progressView removeFromSuperview]; - [progressView release]; - progressView = nil; - } + [progressView removeFromSuperview]; + [progressView release]; + progressView = nil; +} + +- (void)becameActive { + [instance checkPhones]; +} +- (void)updatedUserPhones { + [[tabObjects objectAtIndex:MGMVUKeypadTabIndex] updateInfo]; } - (void)updatedContacts { - [[tabObjects objectAtIndex:MGMContactsTabIndex] updatedContacts]; + [[tabObjects objectAtIndex:MGMVUContactsTabIndex] updatedContacts]; +} +- (void)updateUnreadCount:(int)theCount { + unreadCount = theCount; + [accountController setBadge:unreadCount forInstance:instance]; + if (unreadCount!=0) + [[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:[[NSNumber numberWithInt:unreadCount] stringValue]]; + else + [[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:nil]; } - (void)updateSMS { - [[tabObjects objectAtIndex:MGMSMSTabIndex] checkSMSMessages]; + [[tabObjects objectAtIndex:MGMVUSMSTabIndex] checkSMSMessages]; +} +- (void)updateVoicemail { + [[tabObjects objectAtIndex:MGMVUInboxTabIndex] checkVoicemail]; +} +- (void)updateCredit:(NSString *)theCredit { + [[tabObjects objectAtIndex:MGMVUKeypadTabIndex] setCredit:theCredit]; } - (BOOL)isPlacingCall { return (callTimer!=nil); } +- (void)donePlacingCall { + [callTimer fire]; +} +- (NSString *)currentPhoneNumber { + return currentPhoneNumber; +} - (void)call:(NSString *)theNumber { + if ([[instance userPhoneNumbers] count]<=0) { + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Call Failed"]; + [alert setMessage:@"You need to have a phone number setup with your Google Voice account. To add one, visit voice.google.com and in the settings add a phone number. Once you got a phone number setup with Google Voice, reopen VoiceMob."]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; + return; + } + + [currentPhoneNumber release]; + currentPhoneNumber = [theNumber copy]; placingCall = YES; callTimer = [[NSTimer scheduledTimerWithTimeInterval:20.0 target:self selector:@selector(callTimer) userInfo:nil repeats:NO] retain]; - [instance placeCall:theNumber usingPhone:0 delegate:self]; + [instance placeCall:theNumber usingPhone:[[user settingForKey:MGMLastUserPhoneKey] intValue] delegate:self]; callCancelView = [UIAlertView new]; [callCancelView setTitle:@"Placing Call"]; [callCancelView addButtonWithTitle:@"Cancel Call"]; [callCancelView setDelegate:self]; [callCancelView show]; } -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - if (alertView==callCancelView) { - if (callTimer!=nil) { - [callTimer invalidate]; - [callTimer release]; - callTimer = nil; - } +- (void)alertView:(UIAlertView *)theAlertView clickedButtonAtIndex:(NSInteger)theIndex { + if (theAlertView==callCancelView) { + [currentPhoneNumber release]; + currentPhoneNumber = nil; + placingCall = NO; + [callTimer invalidate]; + [callTimer release]; + callTimer = nil; [callCancelView release]; callCancelView = nil; [instance cancelCallWithDelegate:self]; + } else if (theAlertView==verificationView) { + if (theIndex==1) + [instance verifyWithCode:[verificationField text]]; + else + [instance cancelVerification]; } } - (void)call:(NSDictionary *)theInfo didFailWithError:(NSError *)theError { + [currentPhoneNumber release]; + currentPhoneNumber = nil; placingCall = NO; - if (callTimer!=nil) - [callTimer fire]; - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Call Failed"]; - [theAlert setMessage:[theError localizedDescription]]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + [callTimer fire]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Call Failed"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } - (void)callDidFinish:(NSDictionary *)theInfo { + [currentPhoneNumber release]; + currentPhoneNumber = nil; placingCall = NO; NSLog(@"YEA! We Made The Call!"); } - (void)callCancel:(NSDictionary *)theInfo didFailWithError:(NSError *)theError { - UIAlertView *theAlert = [[UIAlertView new] autorelease]; - [theAlert setTitle:@"Call Cancel Failed"]; - [theAlert setMessage:[theError localizedDescription]]; - [theAlert addButtonWithTitle:MGMOkButtonTitle]; - [theAlert show]; + UIAlertView *alert = [[UIAlertView new] autorelease]; + [alert setTitle:@"Call Cancel Failed"]; + [alert setMessage:[theError localizedDescription]]; + [alert addButtonWithTitle:MGMOkButtonTitle]; + [alert show]; } - (void)callTimer { - if (callTimer!=nil) { - [callTimer invalidate]; - [callTimer release]; - callTimer = nil; - } + [callTimer invalidate]; + [callTimer release]; + callTimer = nil; [callCancelView dismissWithClickedButtonIndex:0 animated:YES]; [callCancelView release]; callCancelView = nil; } -- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item { - int tabIndex = [[tabBar items] indexOfObject:item]; +- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)theItem { + int tabIndex = [[tabBar items] indexOfObject:theItem]; if (tabIndex==currentTab) return; - if (tabIndex!=MGMSMSTabIndex && tabIndex!=MGMInboxTabIndex) + if (tabIndex!=MGMVUSMSTabIndex && tabIndex!=MGMVUInboxTabIndex) { + [accountController setTitle:[self title]]; [accountController setItems:[accountController accountItems] animated:YES]; + } id tab = [tabObjects objectAtIndex:currentTab]; currentTab = tabIndex; + [user setSetting:[NSNumber numberWithInt:currentTab] forKey:MGMVUCurrentTab]; id newTab = [tabObjects objectAtIndex:currentTab]; + CGRect tabFrame = [[newTab view] frame]; + tabFrame.size = [tabView frame].size; + [[newTab view] setFrame:tabFrame]; [tabView addSubview:[newTab view]]; [[tab view] removeFromSuperview]; [tab releaseView]; } + +- (void)showOptionsForNumber:(NSString *)theNumber { + optionsNumber = [theNumber copy]; + UIActionSheet *theAction = [[UIActionSheet new] autorelease]; + [theAction addButtonWithTitle:@"Call"]; + [theAction addButtonWithTitle:@"SMS"]; + [theAction addButtonWithTitle:@"Reverse Lookup"]; + [theAction addButtonWithTitle:@"Cancel"]; + [theAction setCancelButtonIndex:3]; + [theAction setDelegate:self]; + [theAction showInView:view]; +} +- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { + if (buttonIndex==0) + [self call:optionsNumber]; + else if (buttonIndex==1) + [[tabObjects objectAtIndex:MGMVUSMSTabIndex] messageWithNumber:optionsNumber instance:instance]; + else if (buttonIndex==2) + [[accountController controller] showReverseLookupWithNumber:optionsNumber]; + [optionsNumber release]; + optionsNumber = nil; +} @end \ No newline at end of file diff --git a/Classes/VoiceMob/ZipArchive/ZipArchive.h b/Classes/VoiceMob/ZipArchive/ZipArchive.h new file mode 100644 index 0000000..9ace9b2 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/ZipArchive.h @@ -0,0 +1,48 @@ +// +// ZipArchive.h +// +// +// Created by aish on 08-9-11. +// acsolu@gmail.com +// Copyright 2008 Inc. All rights reserved. +// +// History: +// 09-11-2008 version 1.0 release +// 10-18-2009 version 1.1 support password protected zip files +// 10-21-2009 version 1.2 fix date bug + +#import + +#include "minizip/zip.h" +#include "minizip/unzip.h" + + +@protocol ZipArchiveDelegate +@optional +-(void) ErrorMessage:(NSString*) msg; +-(BOOL) OverWriteOperation:(NSString*) file; + +@end + + +@interface ZipArchive : NSObject { +@private + zipFile _zipFile; + unzFile _unzFile; + + NSString* _password; + id _delegate; +} + +@property (nonatomic, retain) id delegate; + +-(BOOL) CreateZipFile2:(NSString*) zipFile; +-(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password; +-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname; +-(BOOL) CloseZipFile2; + +-(BOOL) UnzipOpenFile:(NSString*) zipFile; +-(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password; +-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite; +-(BOOL) UnzipCloseFile; +@end diff --git a/Classes/VoiceMob/ZipArchive/ZipArchive.mm b/Classes/VoiceMob/ZipArchive/ZipArchive.mm new file mode 100644 index 0000000..624311e --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/ZipArchive.mm @@ -0,0 +1,336 @@ +// +// ZipArchive.mm +// +// +// Created by aish on 08-9-11. +// acsolu@gmail.com +// Copyright 2008 Inc. All rights reserved. +// + +#import "ZipArchive.h" +#import "zlib.h" +#import "zconf.h" + + + +@interface ZipArchive (Private) + +-(void) OutputErrorMessage:(NSString*) msg; +-(BOOL) OverWrite:(NSString*) file; +-(NSDate*) Date1980; +@end + + + +@implementation ZipArchive +@synthesize delegate = _delegate; + +-(id) init +{ + if ((self=[super init])) { + _zipFile = NULL ; + } + return self; +} + +-(void) dealloc +{ + [self CloseZipFile2]; + [super dealloc]; +} + +-(BOOL) CreateZipFile2:(NSString*) zipFile +{ + _zipFile = zipOpen( (const char*)[zipFile UTF8String], 0 ); + if( !_zipFile ) + return NO; + return YES; +} + +-(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password +{ + _password = password; + return [self CreateZipFile2:zipFile]; +} + +-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname; +{ + if( !_zipFile ) + return NO; +// tm_zip filetime; + time_t current; + time( ¤t ); + + zip_fileinfo zipInfo = {0}; +// zipInfo.dosDate = (unsigned long) current; + + NSDictionary* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil]; + if( attr ) + { + NSDate* fileDate = (NSDate*)[attr objectForKey:NSFileModificationDate]; + if( fileDate ) + { + // some application does use dosDate, but tmz_date instead + // zipInfo.dosDate = [fileDate timeIntervalSinceDate:[self Date1980] ]; + NSCalendar* currCalendar = [NSCalendar currentCalendar]; + uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | + NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ; + NSDateComponents* dc = [currCalendar components:flags fromDate:fileDate]; + zipInfo.tmz_date.tm_sec = [dc second]; + zipInfo.tmz_date.tm_min = [dc minute]; + zipInfo.tmz_date.tm_hour = [dc hour]; + zipInfo.tmz_date.tm_mday = [dc day]; + zipInfo.tmz_date.tm_mon = [dc month] - 1; + zipInfo.tmz_date.tm_year = [dc year]; + } + } + + int ret ; + NSData* data = nil; + if( [_password length] == 0 ) + { + ret = zipOpenNewFileInZip( _zipFile, + (const char*) [newname UTF8String], + &zipInfo, + NULL,0, + NULL,0, + NULL,//comment + Z_DEFLATED, + Z_DEFAULT_COMPRESSION ); + } + else + { + data = [ NSData dataWithContentsOfFile:file]; + uLong crcValue = crc32( 0L,NULL, 0L ); + crcValue = crc32( crcValue, (const Bytef*)[data bytes], [data length] ); + ret = zipOpenNewFileInZip3( _zipFile, + (const char*) [newname UTF8String], + &zipInfo, + NULL,0, + NULL,0, + NULL,//comment + Z_DEFLATED, + Z_DEFAULT_COMPRESSION, + 0, + 15, + 8, + Z_DEFAULT_STRATEGY, + [_password cStringUsingEncoding:NSASCIIStringEncoding], + crcValue ); + } + if( ret!=Z_OK ) + { + return NO; + } + if( data==nil ) + { + data = [ NSData dataWithContentsOfFile:file]; + } + unsigned int dataLen = [data length]; + ret = zipWriteInFileInZip( _zipFile, (const void*)[data bytes], dataLen); + if( ret!=Z_OK ) + { + return NO; + } + ret = zipCloseFileInZip( _zipFile ); + if( ret!=Z_OK ) + return NO; + return YES; +} + +-(BOOL) CloseZipFile2 +{ + _password = nil; + if( _zipFile==NULL ) + return NO; + BOOL ret = zipClose( _zipFile,NULL )==Z_OK?YES:NO; + _zipFile = NULL; + return ret; +} + +-(BOOL) UnzipOpenFile:(NSString*) zipFile +{ + _unzFile = unzOpen( (const char*)[zipFile UTF8String] ); + if( _unzFile ) + { + unz_global_info globalInfo = {0}; + if( unzGetGlobalInfo(_unzFile, &globalInfo )==UNZ_OK ) + { + NSLog(@"%ld entries in the zip file",globalInfo.number_entry ); + } + } + return _unzFile!=NULL; +} + +-(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password +{ + _password = password; + return [self UnzipOpenFile:zipFile]; +} + +-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite +{ + BOOL success = YES; + int ret = unzGoToFirstFile( _unzFile ); + unsigned char buffer[4096] = {0}; + NSFileManager* fman = [NSFileManager defaultManager]; + if( ret!=UNZ_OK ) + { + [self OutputErrorMessage:@"Failed"]; + } + + do{ + if( [_password length]==0 ) + ret = unzOpenCurrentFile( _unzFile ); + else + ret = unzOpenCurrentFilePassword( _unzFile, [_password cStringUsingEncoding:NSASCIIStringEncoding] ); + if( ret!=UNZ_OK ) + { + [self OutputErrorMessage:@"Error occurs"]; + success = NO; + break; + } + // reading data and write to file + int read ; + unz_file_info fileInfo ={0}; + ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + if( ret!=UNZ_OK ) + { + [self OutputErrorMessage:@"Error occurs while getting file info"]; + success = NO; + unzCloseCurrentFile( _unzFile ); + break; + } + char* filename = (char*) malloc( fileInfo.size_filename +1 ); + unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0); + filename[fileInfo.size_filename] = '\0'; + + // check if it contains directory + NSString * strPath = [NSString stringWithUTF8String:filename]; + BOOL isDirectory = NO; + if( filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\') + isDirectory = YES; + free( filename ); + if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound ) + {// contains a path + strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; + } + NSString* fullPath = [path stringByAppendingPathComponent:strPath]; + + if( isDirectory ) + [fman createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil]; + else + [fman createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; + if( [fman fileExistsAtPath:fullPath] && !isDirectory && !overwrite ) + { + if( ![self OverWrite:fullPath] ) + { + unzCloseCurrentFile( _unzFile ); + ret = unzGoToNextFile( _unzFile ); + continue; + } + } + FILE* fp = fopen( (const char*)[fullPath UTF8String], "wb"); + while( fp ) + { + read=unzReadCurrentFile(_unzFile, buffer, 4096); + if( read > 0 ) + { + fwrite(buffer, read, 1, fp ); + } + else if( read<0 ) + { + [self OutputErrorMessage:@"Failed to reading zip file"]; + break; + } + else + break; + } + if( fp ) + { + fclose( fp ); + // set the orignal datetime property + NSDate* orgDate = nil; + + //{{ thanks to brad.eaton for the solution + NSDateComponents *dc = [[NSDateComponents alloc] init]; + + dc.second = fileInfo.tmu_date.tm_sec; + dc.minute = fileInfo.tmu_date.tm_min; + dc.hour = fileInfo.tmu_date.tm_hour; + dc.day = fileInfo.tmu_date.tm_mday; + dc.month = fileInfo.tmu_date.tm_mon+1; + dc.year = fileInfo.tmu_date.tm_year; + + NSCalendar *gregorian = [[NSCalendar alloc] + initWithCalendarIdentifier:NSGregorianCalendar]; + + orgDate = [gregorian dateFromComponents:dc] ; + [dc release]; + [gregorian release]; + //}} + + + NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES]; + if( attr ) + { + // [attr setValue:orgDate forKey:NSFileCreationDate]; + if( ![[NSFileManager defaultManager] setAttributes:attr ofItemAtPath:fullPath error:nil] ) + { + // cann't set attributes + NSLog(@"Failed to set attributes"); + } + + } + + + + } + unzCloseCurrentFile( _unzFile ); + ret = unzGoToNextFile( _unzFile ); + }while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE ); + return success; +} + +-(BOOL) UnzipCloseFile +{ + _password = nil; + if( _unzFile ) + return unzClose( _unzFile )==UNZ_OK; + return YES; +} + +#pragma mark wrapper for delegate +-(void) OutputErrorMessage:(NSString*) msg +{ + if( _delegate && [_delegate respondsToSelector:@selector(ErrorMessage)] ) + [_delegate ErrorMessage:msg]; +} + +-(BOOL) OverWrite:(NSString*) file +{ + if( _delegate && [_delegate respondsToSelector:@selector(OverWriteOperation)] ) + return [_delegate OverWriteOperation:file]; + return YES; +} + +#pragma mark get NSDate object for 1980-01-01 +-(NSDate*) Date1980 +{ + NSDateComponents *comps = [[NSDateComponents alloc] init]; + [comps setDay:1]; + [comps setMonth:1]; + [comps setYear:1980]; + NSCalendar *gregorian = [[NSCalendar alloc] + initWithCalendarIdentifier:NSGregorianCalendar]; + NSDate *date = [gregorian dateFromComponents:comps]; + + [comps release]; + [gregorian release]; + return date; +} + + +@end + + diff --git a/Classes/VoiceMob/ZipArchive/minizip/crypt.h b/Classes/VoiceMob/ZipArchive/minizip/crypt.h new file mode 100644 index 0000000..f14a628 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/crypt.h @@ -0,0 +1,132 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/Classes/VoiceMob/ZipArchive/minizip/ioapi.c b/Classes/VoiceMob/ZipArchive/minizip/ioapi.c new file mode 100644 index 0000000..7f20c18 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/ioapi.c @@ -0,0 +1,177 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +#include "zlib.h" +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_file_func OF(( + voidpf opaque, + voidpf stream)); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/Classes/VoiceMob/ZipArchive/minizip/ioapi.h b/Classes/VoiceMob/ZipArchive/minizip/ioapi.h new file mode 100644 index 0000000..e73a3b2 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Classes/VoiceMob/ZipArchive/minizip/mztools.c b/Classes/VoiceMob/ZipArchive/minizip/mztools.c new file mode 100644 index 0000000..bc5c798 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/mztools.c @@ -0,0 +1,281 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[256]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char header[46]; + char* comment = ""; + int comsize = (int) strlen(comment); + WRITE_32(header, 0x02014b50); + WRITE_16(header + 4, version); + WRITE_16(header + 6, version); + WRITE_16(header + 8, gpflag); + WRITE_16(header + 10, method); + WRITE_16(header + 12, filetime); + WRITE_16(header + 14, filedate); + WRITE_32(header + 16, crc); + WRITE_32(header + 20, cpsize); + WRITE_32(header + 24, uncpsize); + WRITE_16(header + 28, fnsize); + WRITE_16(header + 30, extsize); + WRITE_16(header + 32, comsize); + WRITE_16(header + 34, 0); /* disk # */ + WRITE_16(header + 36, 0); /* int attrb */ + WRITE_32(header + 38, 0); /* ext attrb */ + WRITE_32(header + 42, currentOffset); + /* Header */ + if (fwrite(header, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char header[22]; + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(header, 0x06054b50); + WRITE_16(header + 4, 0); /* disk # */ + WRITE_16(header + 6, 0); /* disk # */ + WRITE_16(header + 8, entriesZip); /* hack */ + WRITE_16(header + 10, entriesZip); /* hack */ + WRITE_32(header + 12, offsetCD); /* size of CD */ + WRITE_32(header + 16, offset); /* offset to CD */ + WRITE_16(header + 20, comsize); /* comment */ + + /* Header */ + if (fwrite(header, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +} diff --git a/Classes/VoiceMob/ZipArchive/minizip/mztools.h b/Classes/VoiceMob/ZipArchive/minizip/mztools.h new file mode 100644 index 0000000..82d1597 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/mztools.h @@ -0,0 +1,31 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + +#endif diff --git a/Classes/VoiceMob/ZipArchive/minizip/unzip.c b/Classes/VoiceMob/ZipArchive/minizip/unzip.c new file mode 100644 index 0000000..da16de7 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/unzip.c @@ -0,0 +1,1597 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/Classes/VoiceMob/ZipArchive/minizip/unzip.h b/Classes/VoiceMob/ZipArchive/minizip/unzip.h new file mode 100644 index 0000000..c3206a0 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/Classes/VoiceMob/ZipArchive/minizip/zip.c b/Classes/VoiceMob/ZipArchive/minizip/zip.c new file mode 100644 index 0000000..400e2ba --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/zip.c @@ -0,0 +1,1219 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.01e, February 12th, 2005 + + 27 Dec 2004 Rolf Kalbermatter + Modification to zipOpen2 to support globalComment retrieval. + + Copyright (C) 1998-2005 Gilles Vollant + + Read zip.h for more info +*/ + + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] = + " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + uLong pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralheader; /* size of the central header for cur file */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile_info; + +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile_info ci; /* info on the file curretly writing */ + + uLong begin_pos; /* position of the beginning of the zipfile */ + uLong add_position_when_writting_offset; + uLong number_entry; +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif +} zip_internal; + + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(ldi) + linkedlist_datablock_internal* ldi; +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(ll) + linkedlist_data* ll; +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(ll) + linkedlist_data* ll; +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(ll,buf,len) + linkedlist_data* ll; + const void* buf; + uLong len; +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 or 4 (byte, short or long) +*/ + +local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, uLong x, int nbByte)); +local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong x; + int nbByte; +{ + unsigned char buf[4]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); +local void ziplocal_putValue_inmemory (dest, x, nbByte) + void* dest; + uLong x; + int nbByte; +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) + const tm_zip* ptm; + uLong dosDate; +{ + uLong year = (uLong)ptm->tm_year; + if (year>1980) + year-=1980; + else if (year>80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int ziplocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int ziplocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int ziplocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong ziplocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + +/************************************************************/ +extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) + const char *pathname; + int append; + zipcharpc* globalcomment; + zlib_filefunc_def* pzlib_filefunc_def; +{ + zip_internal ziinit; + zip_internal* zi; + int err=ZIP_OK; + + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&ziinit.z_filefunc); + else + ziinit.z_filefunc = *pzlib_filefunc_def; + + ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) + (ziinit.z_filefunc.opaque, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writting_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + zi = (zip_internal*)ALLOC(sizeof(zip_internal)); + if (zi==NULL) + { + ZCLOSE(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory */ + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry; + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong size_comment; + + central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); + if (central_pos==0) + err=ZIP_ERRNO; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* zipfile global comment length */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((central_pos0) + { + ziinit.globalcomment = ALLOC(size_comment+1); + if (ziinit.globalcomment) + { + size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); + ziinit.globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - + (offset_central_dir+size_central_dir); + ziinit.add_position_when_writting_offset = byte_before_the_zipfile; + + { + uLong size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir + byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + uLong read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&ziinit.central_dir,buf_read, + (uLong)read_this); + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + ziinit.begin_pos = byte_before_the_zipfile; + ziinit.number_entry = number_entry_CD; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen (pathname, append) + const char *pathname; + int append; +{ + return zipOpen2(pathname,append,NULL,NULL); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; + int windowBits; + int memLevel; + int strategy; + const char* password; + uLong crcForCrypting; +{ + zip_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); + } + + zi->ci.flag = 0; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if ((level==2)) + zi->ci.flag |= 4; + if ((level==1)) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + + size_extrafield_global + size_comment; + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); + + ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + /* write the local header */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); + + if ((err==ZIP_OK) && (size_filename>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + + if ((err==ZIP_OK) && (size_extrafield_local>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) + !=size_extrafield_local) + err = ZIP_ERRNO; + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, + Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = 1; + } +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; +{ + return zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; +{ + return zipOpenNewFileInZip2 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0); +} + +local int zipFlushWriteBuffer(zi) + zip_internal* zi; +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, + zi->ci.buffered_data[i],t); +#endif + } + if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) + !=zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (file, buf, len) + zipFile file; + const void* buf; + unsigned len; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.stream.next_in = (void*)buf; + zi->ci.stream.avail_in = len; + zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + for (i=0;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) + zipFile file; + uLong uncompressed_size; + uLong crc32; +{ + zip_internal* zi; + uLong compressed_size; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = (uLong)zi->ci.stream.total_in; + } + compressed_size = (uLong)zi->ci.stream.total_out; +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + compressed_size,4); /*compr size*/ + if (zi->ci.stream.data_type == Z_ASCII) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + ziplocal_putValue_inmemory(zi->ci.central_header+24, + uncompressed_size,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (ZSEEK(zi->z_filefunc,zi->filestream, + zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + + if (ZSEEK(zi->z_filefunc,zi->filestream, + cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (file) + zipFile file; +{ + return zipCloseFileInZipRaw (file,0,0); +} + +extern int ZEXPORT zipClose (file, global_comment) + zipFile file; + const char* global_comment; +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = (uInt)strlen(global_comment); + + centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + ldi->data,ldi->filled_in_this_block) + !=ldi->filled_in_this_block ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, + (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + global_comment,size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + + if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} diff --git a/Classes/VoiceMob/ZipArchive/minizip/zip.h b/Classes/VoiceMob/ZipArchive/minizip/zip.h new file mode 100644 index 0000000..cd38b67 --- /dev/null +++ b/Classes/VoiceMob/ZipArchive/minizip/zip.h @@ -0,0 +1,235 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCtypting)); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCtypting : crc of file to compress (needed for crypting) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); +/* + Close the current file in the zipfile, for fiel opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/Classes/VoiceMob/main.m b/Classes/VoiceMob/main.m index 0f5dac7..0b72a7b 100644 --- a/Classes/VoiceMob/main.m +++ b/Classes/VoiceMob/main.m @@ -3,7 +3,7 @@ // VoiceMob // // Created by Mr. Gecko on 9/24/10. -// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/ +// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ // #import diff --git a/Classes/VoiceMob/VoiceMob_Prefix.pch b/Classes/VoiceMob/prefix.pch similarity index 90% rename from Classes/VoiceMob/VoiceMob_Prefix.pch rename to Classes/VoiceMob/prefix.pch index 0aea062..e60f7f4 100644 --- a/Classes/VoiceMob/VoiceMob_Prefix.pch +++ b/Classes/VoiceMob/prefix.pch @@ -6,4 +6,5 @@ #import #import #define MGMOkButtonTitle @"Ok" + #define releaseDebug 0 #endif diff --git a/FFmpeg/install b/FFmpeg/install index 3bbcfde..fc90477 100755 --- a/FFmpeg/install +++ b/FFmpeg/install @@ -1,25 +1,27 @@ #!/bin/bash -#PPCFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch ppc" -PPCFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch ppc" -PPCCC="/usr/bin/gcc-4.0" -PPCHOST="ppc-apple-darwin8" +PPCFLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch ppc -ggdb" +PPCCC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2" +PPCCXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2" +PPCAR="/Applications/Xcode.app/Contents/Developer/usr/bin/ar rv" +PPCRANLIB="/Applications/Xcode.app/Contents/Developer/usr/bin/ranlib" +PPCHOST="ppc-apple-darwin10" PPCPATH="${PWD}/opt-ppc" -PPCLDFLAGS="${PPCFLAGS}" +PPCLDFLAGS="-arch ppc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk" -#I386FLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch i386" -I386FLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch i386" -I386CC="/usr/bin/gcc-4.0" -I386HOST="i386-apple-darwin8" +I386FLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch i386 -ggdb" +I386CC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2" +I386CXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2" +I386HOST="i386-apple-darwin10" I386PATH="${PWD}/opt-i386" -I386LDFLAGS="${I386FLAGS}" +I386LDFLAGS="-arch i386" -#X86_64FLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.5 -arch x86_64" -X86_64FLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch x86_64" -X86_64CC="/usr/bin/gcc-4.0" -X86_64HOST="x86_64-apple-darwin9" +X86_64FLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch x86_64 -ggdb" +X86_64CC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2" +X86_64CXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2" +X86_64HOST="x86_64-apple-darwin10" X86_64PATH="${PWD}/opt-x86_64" -X86_64LDFLAGS="${X86_64FLAGS}" +X86_64LDFLAGS="-arch x86_64" STANDARD="--disable-bzlib --enable-pthreads --disable-network --enable-small --disable-ffprobe --disable-ffplay --disable-ffserver --disable-decoder=atrac3 --disable-shared --enable-static \ --disable-decoders \ @@ -240,11 +242,11 @@ if [ "$1" = "" ]; then echo "Configuring FFmpeg" cd ${FFMPEGNAME}-ppc - LDFLAGS="${PPCLDFLAGS} -L${PPCPATH}/lib" CFLAGS="${PPCFLAGS} -I${PPCPATH}/include -mdynamic-no-pic" CC="${PPCCC}" ./configure --prefix="${PPCPATH}" --arch=ppc ${STANDARD} + LDFLAGS="${PPCLDFLAGS} -L${PPCPATH}/lib" CFLAGS="${PPCFLAGS} -I${PPCPATH}/include -mdynamic-no-pic" ./configure --enable-cross-compile --prefix="${PPCPATH}" --enable-memalign-hack --target-os=darwin --cc="${PPCCC}" --arch=ppc ${STANDARD} cd ../${FFMPEGNAME}-i386 - LDFLAGS="${I386LDFLAGS} -L${I386PATH}/lib" CFLAGS="${I386FLAGS} -I${I386PATH}/include -mdynamic-no-pic" CC="${I386CC}" ./configure --prefix="${I386PATH}" --arch=i386 ${STANDARD} + LDFLAGS="${I386LDFLAGS} -L${I386PATH}/lib" CFLAGS="${I386FLAGS} -I${I386PATH}/include -mdynamic-no-pic" ./configure --enable-cross-compile --prefix="${I386PATH}" --enable-memalign-hack --target-os=darwin --cc="${I386CC}" --arch=i386 ${STANDARD} cd ../${FFMPEGNAME}-x86_64 - LDFLAGS="${X86_64LDFLAGS} -L${X86_64PATH}/lib" CFLAGS="${X86_64FLAGS} -I${X86_64PATH}/include -mdynamic-no-pic" CC="${X86_64CC}" ./configure --prefix="${X86_64PATH}" --enable-cross-compile --target-os=darwin --arch=x86_64 ${STANDARD} + LDFLAGS="${X86_64LDFLAGS} -L${X86_64PATH}/lib" CFLAGS="${X86_64FLAGS} -I${X86_64PATH}/include -mdynamic-no-pic" ./configure --prefix="${X86_64PATH}" --target-os=darwin --cc="${X86_64CC}" --arch=x86_64 ${STANDARD} echo "Compiling FFmpeg" cd ../${FFMPEGNAME}-ppc diff --git a/Frameworks/Growl.framework/Versions/A/Growl b/Frameworks/Growl.framework/Versions/A/Growl index 496b628..b5dc2b8 100755 Binary files a/Frameworks/Growl.framework/Versions/A/Growl and b/Frameworks/Growl.framework/Versions/A/Growl differ diff --git a/Frameworks/Growl.framework/Versions/A/Headers/Growl.h b/Frameworks/Growl.framework/Versions/A/Headers/Growl.h index e2a4425..7b1a324 100644 --- a/Frameworks/Growl.framework/Versions/A/Headers/Growl.h +++ b/Frameworks/Growl.framework/Versions/A/Headers/Growl.h @@ -1,6 +1,5 @@ -#include "GrowlDefines.h" +#include #ifdef __OBJC__ -# include "GrowlApplicationBridge.h" +# include #endif -#include "GrowlApplicationBridge-Carbon.h" diff --git a/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h b/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h deleted file mode 100644 index e35663f..0000000 --- a/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h +++ /dev/null @@ -1,780 +0,0 @@ -// -// GrowlApplicationBridge-Carbon.h -// Growl -// -// Created by Mac-arena the Bored Zo on Wed Jun 18 2004. -// Based on GrowlApplicationBridge.h by Evan Schoenberg. -// This source code is in the public domain. You may freely link it into any -// program. -// - -#ifndef _GROWLAPPLICATIONBRIDGE_CARBON_H_ -#define _GROWLAPPLICATIONBRIDGE_CARBON_H_ - -#include -#include - -#ifndef GROWL_EXPORT -#define GROWL_EXPORT __attribute__((visibility("default"))) -#endif - -/*! @header GrowlApplicationBridge-Carbon.h - * @abstract Declares an API that Carbon applications can use to interact with Growl. - * @discussion GrowlApplicationBridge uses a delegate to provide information //XXX - * to Growl (such as your application's name and what notifications it may - * post) and to provide information to your application (such as that Growl - * is listening for notifications or that a notification has been clicked). - * - * You can set the Growldelegate with Growl_SetDelegate and find out the - * current delegate with Growl_GetDelegate. See struct Growl_Delegate for more - * information about the delegate. - */ - -__BEGIN_DECLS - -/*! @struct Growl_Delegate - * @abstract Delegate to supply GrowlApplicationBridge with information and respond to events. - * @discussion The Growl delegate provides your interface to - * GrowlApplicationBridge. When GrowlApplicationBridge needs information about - * your application, it looks for it in the delegate; when Growl or the user - * does something that you might be interested in, GrowlApplicationBridge - * looks for a callback in the delegate and calls it if present - * (meaning, if it is not NULL). - * XXX on all of that - * @field size The size of the delegate structure. - * @field applicationName The name of your application. - * @field registrationDictionary A dictionary describing your application and the notifications it can send out. - * @field applicationIconData Your application's icon. - * @field growlInstallationWindowTitle The title of the installation window. - * @field growlInstallationInformation Text to display in the installation window. - * @field growlUpdateWindowTitle The title of the update window. - * @field growlUpdateInformation Text to display in the update window. - * @field referenceCount A count of owners of the delegate. - * @field retain Called when GrowlApplicationBridge receives this delegate. - * @field release Called when GrowlApplicationBridge no longer needs this delegate. - * @field growlIsReady Called when GrowlHelperApp is listening for notifications. - * @field growlNotificationWasClicked Called when a Growl notification is clicked. - * @field growlNotificationTimedOut Called when a Growl notification timed out. - */ -struct Growl_Delegate { - /* @discussion This should be sizeof(struct Growl_Delegate). - */ - size_t size; - - /*All of these attributes are optional. - *Optional attributes can be NULL; required attributes that - * are NULL cause setting the Growl delegate to fail. - *XXX - move optional/required status into the discussion for each field - */ - - /* This name is used both internally and in the Growl preferences. - * - * This should remain stable between different versions and incarnations of - * your application. - * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and - * "SurfWriter Lite" are not. - * - * This can be NULL if it is provided elsewhere, namely in an - * auto-discoverable plist file in your app bundle - * (XXX refer to more information on that) or in registrationDictionary. - */ - CFStringRef applicationName; - - /* - * Must contain at least these keys: - * GROWL_NOTIFICATIONS_ALL (CFArray): - * Contains the names of all notifications your application may post. - * - * Can also contain these keys: - * GROWL_NOTIFICATIONS_DEFAULT (CFArray): - * Names of notifications that should be enabled by default. - * If omitted, GROWL_NOTIFICATIONS_ALL will be used. - * GROWL_APP_NAME (CFString): - * Same as the applicationName member of this structure. - * If both are present, the applicationName member shall prevail. - * If this key is present, you may omit applicationName (set it to NULL). - * GROWL_APP_ICON (CFData): - * Same as the iconData member of this structure. - * If both are present, the iconData member shall prevail. - * If this key is present, you may omit iconData (set it to NULL). - * - * If you change the contents of this dictionary after setting the delegate, - * be sure to call Growl_Reregister. - * - * This can be NULL if you have an auto-discoverable plist file in your app - * bundle. (XXX refer to more information on that) - */ - CFDictionaryRef registrationDictionary; - - /* The data can be in any format supported by NSImage. As of - * Mac OS X 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and - * PICT formats. - * - * If this is not supplied, Growl will look up your application's icon by - * its application name. - */ - CFDataRef applicationIconData; - - /* Installer display attributes - * - * These four attributes are used by the Growl installer, if this framework - * supports it. - * For any of these being NULL, a localised default will be - * supplied. - */ - - /* If this is NULL, Growl will use a default, - * localized title. - * - * Only used if you're using Growl-WithInstaller.framework. Otherwise, - * this member is ignored. - */ - CFStringRef growlInstallationWindowTitle; - /* This information may be as long or short as desired (the - * window will be sized to fit it). If Growl is not installed, it will - * be displayed to the user as an explanation of what Growl is and what - * it can do in your application. - * It should probably note that no download is required to install. - * - * If this is NULL, Growl will use a default, localized - * explanation. - * - * Only used if you're using Growl-WithInstaller.framework. Otherwise, - * this member is ignored. - */ - CFStringRef growlInstallationInformation; - /* If this is NULL, Growl will use a default, - * localized title. - * - * Only used if you're using Growl-WithInstaller.framework. Otherwise, - * this member is ignored. - */ - CFStringRef growlUpdateWindowTitle; - /* This information may be as long or short as desired (the - * window will be sized to fit it). If an older version of Growl is - * installed, it will be displayed to the user as an explanation that an - * updated version of Growl is included in your application and - * no download is required. - * - * If this is NULL, Growl will use a default, localized - * explanation. - * - * Only used if you're using Growl-WithInstaller.framework. Otherwise, - * this member is ignored. - */ - CFStringRef growlUpdateInformation; - - /* This member is provided for use by your retain and release - * callbacks (see below). - * - * GrowlApplicationBridge never directly uses this member. Instead, it - * calls your retain callback (if non-NULL) and your release - * callback (if non-NULL). - */ - unsigned referenceCount; - - //Functions. Currently all of these are optional (any of them can be NULL). - - /* When you call Growl_SetDelegate(newDelegate), it will call - * oldDelegate->release(oldDelegate), and then it will call - * newDelegate->retain(newDelegate), and the return value from retain - * is what will be set as the delegate. - * (This means that this member works like CFRetain and -[NSObject retain].) - * This member is optional (it can be NULL). - * For a delegate allocated with malloc, this member would be - * NULL. - * @result A delegate to which GrowlApplicationBridge holds a reference. - */ - void *(*retain)(void *); - /* When you call Growl_SetDelegate(newDelegate), it will call - * oldDelegate->release(oldDelegate), and then it will call - * newDelegate->retain(newDelegate), and the return value from retain - * is what will be set as the delegate. - * (This means that this member works like CFRelease and - * -[NSObject release].) - * This member is optional (it can be NULL). - * For a delegate allocated with malloc, this member might be - * free(3). - */ - void (*release)(void *); - - /* Informs the delegate that Growl (specifically, the GrowlHelperApp) was - * launched successfully (or was already running). The application can - * take actions with the knowledge that Growl is installed and functional. - */ - void (*growlIsReady)(void); - - /* Informs the delegate that a Growl notification was clicked. It is only - * sent for notifications sent with a non-NULL clickContext, - * so if you want to receive a message when a notification is clicked, - * clickContext must not be NULL when calling - * Growl_PostNotification or - * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext. - */ - void (*growlNotificationWasClicked)(CFPropertyListRef clickContext); - - /* Informs the delegate that a Growl notification timed out. It is only - * sent for notifications sent with a non-NULL clickContext, - * so if you want to receive a message when a notification is clicked, - * clickContext must not be NULL when calling - * Growl_PostNotification or - * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext. - */ - void (*growlNotificationTimedOut)(CFPropertyListRef clickContext); -}; - -/*! @struct Growl_Notification - * @abstract Structure describing a Growl notification. - * @discussion XXX - * @field size The size of the notification structure. - * @field name Identifies the notification. - * @field title Short synopsis of the notification. - * @field description Additional text. - * @field iconData An icon for the notification. - * @field priority An indicator of the notification's importance. - * @field reserved Bits reserved for future usage. - * @field isSticky Requests that a notification stay on-screen until dismissed explicitly. - * @field clickContext An identifier to be passed to your click callback when a notification is clicked. - * @field clickCallback A callback to call when the notification is clicked. - */ -struct Growl_Notification { - /* This should be sizeof(struct Growl_Notification). - */ - size_t size; - - /* The notification name distinguishes one type of - * notification from another. The name should be human-readable, as it - * will be displayed in the Growl preference pane. - * - * The name is used in the GROWL_NOTIFICATIONS_ALL and - * GROWL_NOTIFICATIONS_DEFAULT arrays in the registration dictionary, and - * in this member of the Growl_Notification structure. - */ - CFStringRef name; - - /* A notification's title describes the notification briefly. - * It should be easy to read quickly by the user. - */ - CFStringRef title; - - /* The description supplements the title with more - * information. It is usually longer and sometimes involves a list of - * subjects. For example, for a 'Download complete' notification, the - * description might have one filename per line. GrowlMail in Growl 0.6 - * uses a description of '%d new mail(s)' (formatted with the number of - * messages). - */ - CFStringRef description; - - /* The notification icon usually indicates either what - * happened (it may have the same icon as e.g. a toolbar item that - * started the process that led to the notification), or what it happened - * to (e.g. a document icon). - * - * The icon data is optional, so it can be NULL. In that - * case, the application icon is used alone. Not all displays support - * icons. - * - * The data can be in any format supported by NSImage. As of Mac OS X - * 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and PICT form - * ats. - */ - CFDataRef iconData; - - /* Priority is new in Growl 0.6, and is represented as a - * signed integer from -2 to +2. 0 is Normal priority, -2 is Very Low - * priority, and +2 is Very High priority. - * - * Not all displays support priority. If you do not wish to assign a - * priority to your notification, assign 0. - */ - signed int priority; - - /* These bits are not used in Growl 0.6. Set them to 0. - */ - unsigned reserved: 31; - - /* When the sticky bit is clear, in most displays, - * notifications disappear after a certain amount of time. Sticky - * notifications, however, remain on-screen until the user dismisses them - * explicitly, usually by clicking them. - * - * Sticky notifications were introduced in Growl 0.6. Most notifications - * should not be sticky. Not all displays support sticky notifications, - * and the user may choose in Growl's preference pane to force the - * notification to be sticky or non-sticky, in which case the sticky bit - * in the notification will be ignored. - */ - unsigned isSticky: 1; - - /* If this is not NULL, and your click callback - * is not NULL either, this will be passed to the callback - * when your notification is clicked by the user. - * - * Click feedback was introduced in Growl 0.6, and it is optional. Not - * all displays support click feedback. - */ - CFPropertyListRef clickContext; - - /* If this is not NULL, it will be called instead - * of the Growl delegate's click callback when clickContext is - * non-NULL and the notification is clicked on by the user. - * - * Click feedback was introduced in Growl 0.6, and it is optional. Not - * all displays support click feedback. - * - * The per-notification click callback is not yet supported as of Growl - * 0.7. - */ - void (*clickCallback)(CFPropertyListRef clickContext); - - CFStringRef identifier; -}; - -#pragma mark - -#pragma mark Easy initialisers - -/*! @defined InitGrowlDelegate - * @abstract Callable macro. Initializes a Growl delegate structure to defaults. - * @discussion Call with a pointer to a struct Growl_Delegate. All of the - * members of the structure will be set to 0 or NULL, except for - * size (which will be set to sizeof(struct Growl_Delegate)) and - * referenceCount (which will be set to 1). - */ -#define InitGrowlDelegate(delegate) \ - do { \ - if (delegate) { \ - (delegate)->size = sizeof(struct Growl_Delegate); \ - (delegate)->applicationName = NULL; \ - (delegate)->registrationDictionary = NULL; \ - (delegate)->applicationIconData = NULL; \ - (delegate)->growlInstallationWindowTitle = NULL; \ - (delegate)->growlInstallationInformation = NULL; \ - (delegate)->growlUpdateWindowTitle = NULL; \ - (delegate)->growlUpdateInformation = NULL; \ - (delegate)->referenceCount = 1U; \ - (delegate)->retain = NULL; \ - (delegate)->release = NULL; \ - (delegate)->growlIsReady = NULL; \ - (delegate)->growlNotificationWasClicked = NULL; \ - (delegate)->growlNotificationTimedOut = NULL; \ - } \ - } while(0) - -/*! @defined InitGrowlNotification - * @abstract Callable macro. Initializes a Growl notification structure to defaults. - * @discussion Call with a pointer to a struct Growl_Notification. All of - * the members of the structure will be set to 0 or NULL, except - * for size (which will be set to - * sizeof(struct Growl_Notification)). - */ -#define InitGrowlNotification(notification) \ - do { \ - if (notification) { \ - (notification)->size = sizeof(struct Growl_Notification); \ - (notification)->name = NULL; \ - (notification)->title = NULL; \ - (notification)->description = NULL; \ - (notification)->iconData = NULL; \ - (notification)->priority = 0; \ - (notification)->reserved = 0U; \ - (notification)->isSticky = false; \ - (notification)->clickContext = NULL; \ - (notification)->clickCallback = NULL; \ - (notification)->identifier = NULL; \ - } \ - } while(0) - -#pragma mark - -#pragma mark Public API - -// @functiongroup Managing the Growl delegate - -/*! @function Growl_SetDelegate - * @abstract Replaces the current Growl delegate with a new one, or removes - * the Growl delegate. - * @param newDelegate - * @result Returns false and does nothing else if a pointer that was passed in - * is unsatisfactory (because it is non-NULL, but at least one - * required member of it is NULL). Otherwise, sets or unsets the - * delegate and returns true. - * @discussion When newDelegate is non-NULL, sets - * the delegate to newDelegate. When it is NULL, - * the current delegate will be unset, and no delegate will be in place. - * - * It is legal for newDelegate to be the current delegate; - * nothing will happen, and Growl_SetDelegate will return true. It is also - * legal for it to be NULL, as described above; again, it will - * return true. - * - * If there was a delegate in place before the call, Growl_SetDelegate will - * call the old delegate's release member if it was non-NULL. If - * newDelegate is non-NULL, Growl_SetDelegate will - * call newDelegate->retain, and set the delegate to its return - * value. - * - * If you are using Growl-WithInstaller.framework, and an older version of - * Growl is installed on the user's system, the user will automatically be - * prompted to update. - * - * GrowlApplicationBridge currently does not copy this structure, nor does it - * retain any of the CF objects in the structure (it regards the structure as - * a container that retains the objects when they are added and releases them - * when they are removed or the structure is destroyed). Also, - * GrowlApplicationBridge currently does not modify any member of the - * structure, except possibly the referenceCount by calling the retain and - * release members. - */ -GROWL_EXPORT Boolean Growl_SetDelegate(struct Growl_Delegate *newDelegate); - -/*! @function Growl_GetDelegate - * @abstract Returns the current Growl delegate, if any. - * @result The current Growl delegate. - * @discussion Returns the last pointer passed into Growl_SetDelegate, or - * NULL if no such call has been made. - * - * This function follows standard Core Foundation reference-counting rules. - * Because it is a Get function, not a Copy function, it will not retain the - * delegate on your behalf. You are responsible for retaining and releasing - * the delegate as needed. - */ -GROWL_EXPORT struct Growl_Delegate *Growl_GetDelegate(void); - -#pragma mark - - -// @functiongroup Posting Growl notifications - -/*! @function Growl_PostNotification - * @abstract Posts a Growl notification. - * @param notification The notification to post. - * @discussion This is the preferred means for sending a Growl notification. - * The notification name and at least one of the title and description are - * required (all three are preferred). All other parameters may be - * NULL (or 0 or false as appropriate) to accept default values. - * - * If using the Growl-WithInstaller framework, if Growl is not installed the - * user will be prompted to install Growl. - * If the user cancels, this function will have no effect until the next - * application session, at which time when it is called the user will be - * prompted again. The user is also given the option to not be prompted again. - * If the user does choose to install Growl, the requested notification will - * be displayed once Growl is installed and running. - */ -GROWL_EXPORT void Growl_PostNotification(const struct Growl_Notification *notification); - -/*! @function Growl_PostNotificationWithDictionary -* @abstract Notifies using a userInfo dictionary suitable for passing to -* CFDistributedNotificationCenter. -* @param userInfo The dictionary to notify with. -* @discussion Before Growl 0.6, your application would have posted -* notifications using CFDistributedNotificationCenter by creating a userInfo -* dictionary with the notification data. This had the advantage of allowing -* you to add other data to the dictionary for programs besides Growl that -* might be listening. -* -* This function allows you to use such dictionaries without being restricted -* to using CFDistributedNotificationCenter. The keys for this dictionary - * can be found in GrowlDefines.h. -*/ -GROWL_EXPORT void Growl_PostNotificationWithDictionary(CFDictionaryRef userInfo); - -/*! @function Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext - * @abstract Posts a Growl notification using parameter values. - * @param title The title of the notification. - * @param description The description of the notification. - * @param notificationName The name of the notification as listed in the - * registration dictionary. - * @param iconData Data representing a notification icon. Can be NULL. - * @param priority The priority of the notification (-2 to +2, with -2 - * being Very Low and +2 being Very High). - * @param isSticky If true, requests that this notification wait for a - * response from the user. - * @param clickContext An object to pass to the clickCallback, if any. Can - * be NULL, in which case the clickCallback is not called. - * @discussion Creates a temporary Growl_Notification, fills it out with the - * supplied information, and calls Growl_PostNotification on it. - * See struct Growl_Notification and Growl_PostNotification for more - * information. - * - * The icon data can be in any format supported by NSImage. As of Mac OS X - * 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and PICT formats. - */ -GROWL_EXPORT void Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext( - /*inhale*/ - CFStringRef title, - CFStringRef description, - CFStringRef notificationName, - CFDataRef iconData, - signed int priority, - Boolean isSticky, - CFPropertyListRef clickContext); - -#pragma mark - - -// @functiongroup Registering - -/*! @function Growl_RegisterWithDictionary - * @abstract Register your application with Growl without setting a delegate. - * @discussion When you call this function with a dictionary, - * GrowlApplicationBridge registers your application using that dictionary. - * If you pass NULL, GrowlApplicationBridge will ask the delegate - * (if there is one) for a dictionary, and if that doesn't work, it will look - * in your application's bundle for an auto-discoverable plist. - * (XXX refer to more information on that) - * - * If you pass a dictionary to this function, it must include the - * GROWL_APP_NAME key, unless a delegate is set. - * - * This function is mainly an alternative to the delegate system introduced - * with Growl 0.6. Without a delegate, you cannot receive callbacks such as - * growlIsReady (since they are sent to the delegate). You can, - * however, set a delegate after registering without one. - * - * This function was introduced in Growl.framework 0.7. - * @result false if registration failed (e.g. if Growl isn't installed). - */ -GROWL_EXPORT Boolean Growl_RegisterWithDictionary(CFDictionaryRef regDict); - -/*! @function Growl_Reregister - * @abstract Updates your registration with Growl. - * @discussion If your application changes the contents of the - * GROWL_NOTIFICATIONS_ALL key in the registrationDictionary member of the - * Growl delegate, or if it changes the value of that member, or if it - * changes the contents of its auto-discoverable plist, call this function - * to have Growl update its registration information for your application. - * - * Otherwise, this function does not normally need to be called. If you're - * using a delegate, your application will be registered when you set the - * delegate if both the delegate and its registrationDictionary member are - * non-NULL. - * - * This function is now implemented using - * Growl_RegisterWithDictionary. - */ -GROWL_EXPORT void Growl_Reregister(void); - -#pragma mark - - -/*! @function Growl_SetWillRegisterWhenGrowlIsReady - * @abstract Tells GrowlApplicationBridge to register with Growl when Growl - * launches (or not). - * @discussion When Growl has started listening for notifications, it posts a - * GROWL_IS_READY notification on the Distributed Notification - * Center. GrowlApplicationBridge listens for this notification, using it to - * perform various tasks (such as calling your delegate's - * growlIsReady callback, if it has one). If this function is - * called with true, one of those tasks will be to reregister - * with Growl (in the manner of Growl_Reregister). - * - * This attribute is automatically set back to false - * (the default) after every GROWL_IS_READY notification. - * @param flag true if you want GrowlApplicationBridge to register with - * Growl when next it is ready; false if not. - */ -GROWL_EXPORT void Growl_SetWillRegisterWhenGrowlIsReady(Boolean flag); -/*! @function Growl_WillRegisterWhenGrowlIsReady - * @abstract Reports whether GrowlApplicationBridge will register with Growl - * when Growl next launches. - * @result true if GrowlApplicationBridge will register with - * Growl when next it posts GROWL_IS_READY; false if not. - */ -GROWL_EXPORT Boolean Growl_WillRegisterWhenGrowlIsReady(void); - -#pragma mark - - -// @functiongroup Obtaining registration dictionaries - -/*! @function Growl_CopyRegistrationDictionaryFromDelegate - * @abstract Asks the delegate for a registration dictionary. - * @discussion If no delegate is set, or if the delegate's - * registrationDictionary member is NULL, this - * function returns NULL. - * - * This function does not attempt to clean up the dictionary in any way - for - * example, if it is missing the GROWL_APP_NAME key, the result - * will be missing it too. Use - * Growl_CreateRegistrationDictionaryByFillingInDictionary or - * Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys - * to try to fill in missing keys. - * - * This function was introduced in Growl.framework 0.7. - * @result A registration dictionary. - */ -GROWL_EXPORT CFDictionaryRef Growl_CopyRegistrationDictionaryFromDelegate(void); - -/*! @function Growl_CopyRegistrationDictionaryFromBundle - * @abstract Looks in a bundle for a registration dictionary. - * @discussion This function looks in a bundle for an auto-discoverable - * registration dictionary file using CFBundleCopyResourceURL. - * If it finds one, it loads the file using CFPropertyList and - * returns the result. - * - * If you pass NULL as the bundle, the main bundle is examined. - * - * This function does not attempt to clean up the dictionary in any way - for - * example, if it is missing the GROWL_APP_NAME key, the result - * will be missing it too. Use - * Growl_CreateRegistrationDictionaryByFillingInDictionary: or - * Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys - * to try to fill in missing keys. - * - * This function was introduced in Growl.framework 0.7. - * @result A registration dictionary. - */ -GROWL_EXPORT CFDictionaryRef Growl_CopyRegistrationDictionaryFromBundle(CFBundleRef bundle); - -/*! @function Growl_CreateBestRegistrationDictionary - * @abstract Obtains a registration dictionary, filled out to the best of - * GrowlApplicationBridge's knowledge. - * @discussion This function creates a registration dictionary as best - * GrowlApplicationBridge knows how. - * - * First, GrowlApplicationBridge examines the Growl delegate (if there is - * one) and gets the registration dictionary from that. If no such dictionary - * was obtained, GrowlApplicationBridge looks in your application's main - * bundle for an auto-discoverable registration dictionary file. If that - * doesn't exist either, this function returns NULL. - * - * Second, GrowlApplicationBridge calls - * Growl_CreateRegistrationDictionaryByFillingInDictionary with - * whatever dictionary was obtained. The result of that function is the - * result of this function. - * - * GrowlApplicationBridge uses this function when you call - * Growl_SetDelegate, or when you call - * Growl_RegisterWithDictionary with NULL. - * - * This function was introduced in Growl.framework 0.7. - * @result A registration dictionary. - */ -GROWL_EXPORT CFDictionaryRef Growl_CreateBestRegistrationDictionary(void); - -#pragma mark - - -// @functiongroup Filling in registration dictionaries - -/*! @function Growl_CreateRegistrationDictionaryByFillingInDictionary - * @abstract Tries to fill in missing keys in a registration dictionary. - * @param regDict The dictionary to fill in. - * @result The dictionary with the keys filled in. - * @discussion This function examines the passed-in dictionary for missing keys, - * and tries to work out correct values for them. As of 0.7, it uses: - * - * Key Value - * --- ----- - * GROWL_APP_NAME CFBundleExecutableName - * GROWL_APP_ICON The icon of the application. - * GROWL_APP_LOCATION The location of the application. - * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL - * - * Keys are only filled in if missing; if a key is present in the dictionary, - * its value will not be changed. - * - * This function was introduced in Growl.framework 0.7. - */ -GROWL_EXPORT CFDictionaryRef Growl_CreateRegistrationDictionaryByFillingInDictionary(CFDictionaryRef regDict); -/*! @function Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys - * @abstract Tries to fill in missing keys in a registration dictionary. - * @param regDict The dictionary to fill in. - * @param keys The keys to fill in. If NULL, any missing keys are filled in. - * @result The dictionary with the keys filled in. - * @discussion This function examines the passed-in dictionary for missing keys, - * and tries to work out correct values for them. As of 0.7, it uses: - * - * Key Value - * --- ----- - * GROWL_APP_NAME CFBundleExecutableName - * GROWL_APP_ICON The icon of the application. - * GROWL_APP_LOCATION The location of the application. - * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL - * - * Only those keys that are listed in keys will be filled in. - * Other missing keys are ignored. Also, keys are only filled in if missing; - * if a key is present in the dictionary, its value will not be changed. - * - * This function was introduced in Growl.framework 0.7. - */ -GROWL_EXPORT CFDictionaryRef Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys(CFDictionaryRef regDict, CFSetRef keys); - -/*! @brief Tries to fill in missing keys in a notification dictionary. - * @param notifDict The dictionary to fill in. - * @return The dictionary with the keys filled in. This will be a separate instance from \a notifDict. - * @discussion This function examines the \a notifDict for missing keys, and - * tries to get them from the last known registration dictionary. As of 1.1, - * the keys that it will look for are: - * - * \li GROWL_APP_NAME - * \li GROWL_APP_ICON - * - * @since Growl.framework 1.1 - */ -GROWL_EXPORT CFDictionaryRef Growl_CreateNotificationDictionaryByFillingInDictionary(CFDictionaryRef notifDict); - -#pragma mark - - -// @functiongroup Querying Growl's status - -/*! @function Growl_IsInstalled - * @abstract Determines whether the Growl prefpane and its helper app are - * installed. - * @result Returns true if Growl is installed, false otherwise. - */ -GROWL_EXPORT Boolean Growl_IsInstalled(void); - -/*! @function Growl_IsRunning - * @abstract Cycles through the process list to find whether GrowlHelperApp - * is running. - * @result Returns true if Growl is running, false otherwise. - */ -GROWL_EXPORT Boolean Growl_IsRunning(void); - -#pragma mark - - -// @functiongroup Launching Growl - -/*! @typedef GrowlLaunchCallback - * @abstract Callback to notify you that Growl is running. - * @param context The context pointer passed to Growl_LaunchIfInstalled. - * @discussion Growl_LaunchIfInstalled calls this callback function if Growl - * was already running or if it launched Growl successfully. - */ -typedef void (*GrowlLaunchCallback)(void *context); - -/*! @function Growl_LaunchIfInstalled - * @abstract Launches GrowlHelperApp if it is not already running. - * @param callback A callback function which will be called if Growl was successfully - * launched or was already running. Can be NULL. - * @param context The context pointer to pass to the callback. Can be NULL. - * @result Returns true if Growl was successfully launched or was already - * running; returns false and does not call the callback otherwise. - * @discussion Returns true and calls the callback (if the callback is not - * NULL) if the Growl helper app began launching or was already - * running. Returns false and performs no other action if Growl could not be - * launched (e.g. because the Growl preference pane is not properly installed). - * - * If Growl_CreateBestRegistrationDictionary returns - * non-NULL, this function will register with Growl atomically. - * - * The callback should take a single argument; this is to allow applications - * to have context-relevant information passed back. It is perfectly - * acceptable for context to be NULL. The callback itself can be - * NULL if you don't want one. - */ -GROWL_EXPORT Boolean Growl_LaunchIfInstalled(GrowlLaunchCallback callback, void *context); - -#pragma mark - -#pragma mark Constants - -/*! @defined GROWL_PREFPANE_BUNDLE_IDENTIFIER - * @abstract The CFBundleIdentifier of the Growl preference pane bundle. - * @discussion GrowlApplicationBridge uses this to determine whether Growl is - * currently installed, by searching for the Growl preference pane. Your - * application probably does not need to use this macro itself. - */ -#ifndef GROWL_PREFPANE_BUNDLE_IDENTIFIER -#define GROWL_PREFPANE_BUNDLE_IDENTIFIER CFSTR("com.growl.prefpanel") -#endif - -__END_DECLS - -#endif /* _GROWLAPPLICATIONBRIDGE_CARBON_H_ */ diff --git a/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h b/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h index 6c42b14..3639757 100644 --- a/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +++ b/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h @@ -18,14 +18,11 @@ #import #import -#import "GrowlDefines.h" +#import //Forward declarations @protocol GrowlApplicationBridgeDelegate; -//Internal notification when the user chooses not to install (to avoid continuing to cache notifications awaiting installation) -#define GROWL_USER_CHOSE_NOT_TO_INSTALL_NOTIFICATION @"User chose not to install" - //------------------------------------------------------------------------------ #pragma mark - @@ -45,9 +42,9 @@ * @method isGrowlInstalled * @abstract Detects whether Growl is installed. * @discussion Determines if the Growl prefpane and its helper app are installed. - * @result Returns YES if Growl is installed, NO otherwise. + * @result this method will forever return YES. */ -+ (BOOL) isGrowlInstalled; ++ (BOOL) isGrowlInstalled __attribute__((deprecated)); /*! * @method isGrowlRunning @@ -57,6 +54,34 @@ */ + (BOOL) isGrowlRunning; + +/*! + * @method isMistEnabled + * @abstract Gives the caller a fairly good indication of whether or not built-in notifications(Mist) will be used. + * @discussion since this call makes use of isGrowlRunning it is entirely possible for this value to change between call and + * executing a notification dispatch + * @result Returns YES if Growl isn't reachable and the developer has not opted-out of + * Mist and the user hasn't set the global mist enable key to false. + */ ++ (BOOL)isMistEnabled; + +/*! + * @method setShouldUseBuiltInNotifications + * @abstract opt-out mechanism for the mist notification style in the event growl can't be reached. + * @discussion if growl is unavailable due to not being installed or as a result of being turned off then + * this option can enable/disable a built-in fire and forget display style + * @param should Specifies whether or not the developer wants to opt-in (default) or opt out + * of the built-in Mist style in the event Growl is unreachable. + */ ++ (void)setShouldUseBuiltInNotifications:(BOOL)should; + +/*! + * @method shouldUseBuiltInNotifications + * @abstract returns the current opt-in state of the framework's use of the Mist display style. + * @result Returns NO if the developer opt-ed out of Mist, the default value is YES. + */ ++ (BOOL)shouldUseBuiltInNotifications; + #pragma mark - /*! @@ -87,7 +112,7 @@ * * @param inDelegate The delegate for the GrowlApplicationBridge. It must conform to the GrowlApplicationBridgeDelegate protocol. */ -+ (void) setGrowlDelegate:(NSObject *)inDelegate; ++ (void) setGrowlDelegate:(id)inDelegate; /*! * @method growlDelegate @@ -95,7 +120,7 @@ * @discussion See setGrowlDelegate: for details. * @result The Growl delegate. */ -+ (NSObject *) growlDelegate; ++ (id) growlDelegate; #pragma mark - @@ -165,40 +190,6 @@ clickContext:(id)clickContext identifier:(NSString *)identifier; -/*! - * @method notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:identifier: - * @abstract Send a Growl notification. - * @discussion This is the preferred means for sending a Growl notification. - * The notification name and at least one of the title and description are - * required (all three are preferred). All other parameters may be - * nil (or 0 or NO as appropriate) to accept default values. - * - * If using the Growl-WithInstaller framework, if Growl is not installed the - * user will be prompted to install Growl. If the user cancels, this method - * will have no effect until the next application session, at which time when - * it is called the user will be prompted again. The user is also given the - * option to not be prompted again. If the user does choose to install Growl, - * the requested notification will be displayed once Growl is installed and - * running. - * - * @param title The title of the notification displayed to the user. - * @param description The full description of the notification displayed to the user. - * @param notifName The internal name of the notification. Should be human-readable, as it will be displayed in the Growl preference pane. - * @param iconData NSData object to show with the notification as its icon. If nil, the application's icon will be used instead. - * @param priority The priority of the notification. The default value is 0; positive values are higher priority and negative values are lower priority. Not all Growl displays support priority. - * @param isSticky If YES, the notification will remain on screen until clicked. Not all Growl displays support sticky notifications. - * @param clickContext A context passed back to the Growl delegate if it implements -(void)growlNotificationWasClicked: and the notification is clicked. Not all display plugins support clicking. The clickContext must be plist-encodable (completely of NSString, NSArray, NSNumber, NSDictionary, and NSData types). - * @param identifier An identifier for this notification. Notifications with equal identifiers are coalesced. - */ -+ (void) notifyWithTitle:(NSString *)title - description:(NSString *)description - notificationName:(NSString *)notifName - iconData:(NSData *)iconData - priority:(signed int)priority - isSticky:(BOOL)isSticky - clickContext:(id)clickContext - identifier:(NSString *)identifier; - /*! @method notifyWithDictionary: * @abstract Notifies using a userInfo dictionary suitable for passing to * NSDistributedNotificationCenter. @@ -269,6 +260,7 @@ * Growl when next it is ready; NO if not. */ + (void) setWillRegisterWhenGrowlIsReady:(BOOL)flag; + /*! @method willRegisterWhenGrowlIsReady * @abstract Reports whether GrowlApplicationBridge will register with Growl * when Growl next launches. @@ -357,7 +349,7 @@ * Key Value * --- ----- * GROWL_APP_NAME CFBundleExecutableName - * GROWL_APP_ICON The icon of the application. + * GROWL_APP_ICON_DATA The data of the icon of the application. * GROWL_APP_LOCATION The location of the application. * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL * @@ -370,6 +362,7 @@ * copy of regDict. */ + (NSDictionary *) registrationDictionaryByFillingInDictionary:(NSDictionary *)regDict; + /*! @method registrationDictionaryByFillingInDictionary:restrictToKeys: * @abstract Tries to fill in missing keys in a registration dictionary. * @discussion This method examines the passed-in dictionary for missing keys, @@ -378,7 +371,7 @@ * Key Value * --- ----- * GROWL_APP_NAME CFBundleExecutableName - * GROWL_APP_ICON The icon of the application. + * GROWL_APP_ICON_DATA The data of the icon of the application. * GROWL_APP_LOCATION The location of the application. * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL * @@ -402,13 +395,39 @@ * the keys that it will look for are: * * \li GROWL_APP_NAME - * \li GROWL_APP_ICON + * \li GROWL_APP_ICON_DATA * * @since Growl.framework 1.1 */ + (NSDictionary *) notificationDictionaryByFillingInDictionary:(NSDictionary *)regDict; + (NSDictionary *) frameworkInfoDictionary; + +#pragma mark - + +/*! + *@method growlURLSchemeAvailable + *@abstract Lets the app know whether growl:// is registered on the system, used for certain methods below this + *@return Returns whether growl:// is registered on the system + *@discussion Methods such as openGrowlPreferences rely on the growl:// URL scheme to function + * Further, this method can provide a check on whether Growl is installed, + * however, the framework will not be relying on this method for choosing when/how to notify, + * and it is not recommended that the app rely on it for other than whether to use growl:// methods + *@since Growl.framework 1.4 + */ ++ (BOOL) isGrowlURLSchemeAvailable; + +/*! + * @method openGrowlPreferences: + * @abstract Open Growl preferences, optionally to this app's settings, growl:// method + * @param showApp Whether to show the application's settings, otherwise just opens to the last position + * @return Return's whether opening the URL was succesfull or not. + * @discussion Will launch if Growl is installed, but not running, and open the preferences window + * Uses growl:// URL scheme + * @since Growl.framework 1.4 + */ ++ (BOOL) openGrowlPreferences:(BOOL)showApp; + @end //------------------------------------------------------------------------------ @@ -417,27 +436,15 @@ /*! * @protocol GrowlApplicationBridgeDelegate * @abstract Required protocol for the Growl delegate. - * @discussion The methods in this protocol are required and are called + * @discussion The methods in this protocol are optional and are called * automatically as needed by GrowlApplicationBridge. See * +[GrowlApplicationBridge setGrowlDelegate:]. * See also GrowlApplicationBridgeDelegate_InformalProtocol. */ -@protocol GrowlApplicationBridgeDelegate +@protocol GrowlApplicationBridgeDelegate -// -registrationDictionaryForGrowl has moved to the informal protocol as of 0.7. - -@end - -//------------------------------------------------------------------------------ -#pragma mark - - -/*! - * @category NSObject(GrowlApplicationBridgeDelegate_InformalProtocol) - * @abstract Methods which may be optionally implemented by the GrowlDelegate. - * @discussion The methods in this informal protocol will only be called if implemented by the delegate. - */ -@interface NSObject (GrowlApplicationBridgeDelegate_InformalProtocol) +@optional /*! * @method registrationDictionaryForGrowl @@ -507,7 +514,7 @@ * object to use as the application icon; if this is not implemented, the * application's own icon is used. This is not generally needed. * @result The NSData to treat as the application icon. - * @deprecated In version 0.8, in favor of {{{-applicationIconForGrowl}}}. + * @deprecated In version 1.1, in favor of {{{-applicationIconForGrowl}}}. */ - (NSData *) applicationIconDataForGrowl; @@ -544,66 +551,17 @@ */ - (void) growlNotificationTimedOut:(id)clickContext; + +/*! + * @method hasNetworkClientEntitlement + * @abstract Used only in sandboxed situations since we don't know whether the app has com.apple.security.network.client entitlement + * @discussion GrowlDelegate calls to find out if we have the com.apple.security.network.client entitlement, + * since we can't find this out without hitting the sandbox. We only call it if we detect that the application is sandboxed. + */ +- (BOOL) hasNetworkClientEntitlement; + @end #pragma mark - -/*! - * @category NSObject(GrowlApplicationBridgeDelegate_Installation_InformalProtocol) - * @abstract Methods which may be optionally implemented by the Growl delegate when used with Growl-WithInstaller.framework. - * @discussion The methods in this informal protocol will only be called if - * implemented by the delegate. They allow greater control of the information - * presented to the user when installing or upgrading Growl from within your - * application when using Growl-WithInstaller.framework. - */ -@interface NSObject (GrowlApplicationBridgeDelegate_Installation_InformalProtocol) - -/*! - * @method growlInstallationWindowTitle - * @abstract Return the title of the installation window. - * @discussion If not implemented, Growl will use a default, localized title. - * @result An NSString object to use as the title. - */ -- (NSString *)growlInstallationWindowTitle; - -/*! - * @method growlUpdateWindowTitle - * @abstract Return the title of the upgrade window. - * @discussion If not implemented, Growl will use a default, localized title. - * @result An NSString object to use as the title. - */ -- (NSString *)growlUpdateWindowTitle; - -/*! - * @method growlInstallationInformation - * @abstract Return the information to display when installing. - * @discussion This information may be as long or short as desired (the window - * will be sized to fit it). It will be displayed to the user as an - * explanation of what Growl is and what it can do in your application. It - * should probably note that no download is required to install. - * - * If this is not implemented, Growl will use a default, localized explanation. - * @result An NSAttributedString object to display. - */ -- (NSAttributedString *)growlInstallationInformation; - -/*! - * @method growlUpdateInformation - * @abstract Return the information to display when upgrading. - * @discussion This information may be as long or short as desired (the window - * will be sized to fit it). It will be displayed to the user as an - * explanation that an updated version of Growl is included in your - * application and no download is required. - * - * If this is not implemented, Growl will use a default, localized explanation. - * @result An NSAttributedString object to display. - */ -- (NSAttributedString *)growlUpdateInformation; - -@end - -//private -@interface GrowlApplicationBridge (GrowlInstallationPrompt_private) -+ (void) _userChoseNotToInstallGrowl; -@end #endif /* __GrowlApplicationBridge_h__ */ diff --git a/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h b/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h index a332a6b..0a196f1 100644 --- a/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h +++ b/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h @@ -7,10 +7,8 @@ #ifdef __OBJC__ #define XSTR(x) (@x) -#define STRING NSString * #else #define XSTR CFSTR -#define STRING CFStringRef #endif /*! @header GrowlDefines.h @@ -56,7 +54,7 @@ * This key is optional. */ #define GROWL_APP_ID XSTR("ApplicationId") -/*! @defined GROWL_APP_ICON +/*! @defined GROWL_APP_ICON_DATA * @abstract The image data for your application's icon. * @discussion Image data representing your application's icon. This may be * superimposed on a notification icon as a badge, used as the notification @@ -66,7 +64,7 @@ * * Optional. Not supported by all display plugins. */ -#define GROWL_APP_ICON XSTR("ApplicationIcon") +#define GROWL_APP_ICON_DATA XSTR("ApplicationIcon") /*! @defined GROWL_NOTIFICATIONS_DEFAULT * @abstract The array of notifications to turn on by default. * @discussion These are the names of the notifications that should be enabled @@ -101,6 +99,14 @@ * This key is optional. */ #define GROWL_NOTIFICATIONS_DESCRIPTIONS XSTR("NotificationDescriptions") +/*! @defined GROWL_NOTIFICATIONS_ICONS + * @abstract A dictionary of icons for each notification + * @discussion This is an NSDictionary whose keys are GROWL_NOTIFICATION_NAME strings and whose objects are + * icons for each notification, for GNTP spec + * + * This key is optional. + */ +#define GROWL_NOTIFICATIONS_ICONS XSTR("NotificationIcons") /*! @defined GROWL_TICKET_VERSION * @abstract The version of your registration ticket. @@ -144,20 +150,20 @@ */ #define GROWL_NOTIFICATION_DESCRIPTION XSTR("NotificationDescription") /*! @defined GROWL_NOTIFICATION_ICON - * @discussion Image data for the notification icon. Must be in a format + * @discussion Image data for the notification icon. Image data must be in a format * supported by NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. * * Optional. Not supported by all display plugins. */ -#define GROWL_NOTIFICATION_ICON XSTR("NotificationIcon") +#define GROWL_NOTIFICATION_ICON_DATA XSTR("NotificationIcon") /*! @defined GROWL_NOTIFICATION_APP_ICON * @discussion Image data for the application icon, in case GROWL_APP_ICON does - * not apply for some reason. Must be in a format supported by NSImage, such + * not apply for some reason. Image data be in a format supported by NSImage, such * as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. * * Optional. Not supported by all display plugins. */ -#define GROWL_NOTIFICATION_APP_ICON XSTR("NotificationAppIcon") +#define GROWL_NOTIFICATION_APP_ICON_DATA XSTR("NotificationAppIcon") /*! @defined GROWL_NOTIFICATION_PRIORITY * @discussion The priority of the notification as an integer number from * -2 to +2 (+2 being highest). @@ -185,16 +191,6 @@ */ #define GROWL_NOTIFICATION_CLICK_CONTEXT XSTR("NotificationClickContext") -/*! @defined GROWL_DISPLAY_PLUGIN - * @discussion The name of a display plugin which should be used for this notification. - * Optional. If this key is not set or the specified display plugin does not - * exist, the display plugin stored in the application ticket is used. This key - * allows applications to use different default display plugins for their - * notifications. The user can still override those settings in the preference - * pane. - */ -#define GROWL_DISPLAY_PLUGIN XSTR("NotificationDisplayPlugin") - /*! @defined GROWL_NOTIFICATION_IDENTIFIER * @abstract An identifier for the notification for coalescing purposes. * Notifications with the same identifier fall into the same class; only @@ -224,6 +220,19 @@ */ #define GROWL_NOTIFICATION_PROGRESS XSTR("NotificationProgress") +/*! @defined GROWL_NOTIFICATION_ALREADY_SHOWN + * @abstract If this key is set, it should contain a bool value wrapped + * in a NSNumber which describes whether the notification has + * already been displayed, for instance by built in Notification + * Center support. This value can be used to allow display + * plugins to skip a notification, while still allowing Growl + * actions to run on them. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_ALREADY_SHOWN XSTR("AlreadyShown") + + // Notifications #pragma mark Notifications @@ -245,7 +254,7 @@ * The userInfo dictionary for this notification can contain these keys: *
    *
  • GROWL_APP_NAME
  • - *
  • GROWL_APP_ICON
  • + *
  • GROWL_APP_ICON_DATA
  • *
  • GROWL_NOTIFICATIONS_ALL
  • *
  • GROWL_NOTIFICATIONS_DEFAULT
  • *
@@ -288,12 +297,6 @@ * Growl_PostNotification. */ #define GROWL_NOTIFICATION XSTR("GrowlNotification") -/*! @defined GROWL_SHUTDOWN -* @abstract The distributed notification name that tells Growl to shutdown. -* @discussion The Growl preference pane posts this notification when the -* "Stop Growl" button is clicked. -*/ -#define GROWL_SHUTDOWN XSTR("GrowlShutdown") /*! @defined GROWL_PING * @abstract A distributed notification to check whether Growl is running. * @discussion This is used by the Growl preference pane. If it receives a @@ -313,15 +316,48 @@ * registration dictionary supplied by its delegate. */ #define GROWL_IS_READY XSTR("Lend Me Some Sugar; I Am Your Neighbor!") -/*! @defined GROWL_NOTIFICATION_CLICKED - * @abstract The distributed notification sent when a supported notification is clicked. + + +/*! @defined GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX + * @abstract Part of the name of the distributed notification sent when a supported notification is clicked. * @discussion When a Growl notification with a click context is clicked on by - * the user, Growl posts this distributed notification. - * The GrowlApplicationBridge responds to this notification by calling a - * callback in its delegate. + * the user, Growl posts a distributed notification whose name is in the format: + * [NSString stringWithFormat:@"%@-%d-%@", appName, pid, GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX] + * The GrowlApplicationBridge responds to this notification by calling a callback in its delegate. */ -#define GROWL_NOTIFICATION_CLICKED XSTR("GrowlClicked!") -#define GROWL_NOTIFICATION_TIMED_OUT XSTR("GrowlTimedOut!") +#define GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX XSTR("GrowlClicked!") + +/*! @defined GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX + * @abstract Part of the name of the distributed notification sent when a supported notification times out without being clicked. + * @discussion When a Growl notification with a click context times out, Growl posts a distributed notification + * whose name is in the format: + * [NSString stringWithFormat:@"%@-%d-%@", appName, pid, GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX] + * The GrowlApplicationBridge responds to this notification by calling a callback in its delegate. + * NOTE: The user may have actually clicked the 'close' button; this triggers an *immediate* time-out of the notification. + */ +#define GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX XSTR("GrowlTimedOut!") + +/*! @defined GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_ON + * @abstract The distributed notification sent when the Notification Center support is toggled on in Growl 2.0 + * @discussion When the user enables Notification Center support in Growl 2.0, this notification is sent + * to inform all running apps that they should now speak to Notification Center directly. + */ +#define GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_ON XSTR("GrowlNotificationCenterOn!") + +/*! @defined GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_OFF + * @abstract The distributed notification sent when the Notification Center support is toggled off in Growl 2.0 + * @discussion When the user enables Notification Center support in Growl 2.0, this notification is sent + * to inform all running apps that they should no longer speak to Notification Center directly. + */ +#define GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_OFF XSTR("GrowlNotificationCenterOff!") + +/*! @defined GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_QUERY + * @abstract The distributed notification sent by an application to query Growl 2.0's notification center support. + * @discussion When an app starts up, it will send this query to get Growl 2.0 to spit out whether notification + * center support is on or off. + */ +#define GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_QUERY XSTR("GrowlNotificationCenterYN?") + /*! @group Other symbols */ /* Symbols which don't fit into any of the other categories. */ @@ -345,4 +381,6 @@ #define GROWL_POSITION_PREFERENCE_KEY @"GrowlSelectedPosition" +#define GROWL_PLUGIN_CONFIG_ID XSTR("GrowlPluginConfigurationID") + #endif //ndef _GROWLDEFINES_H diff --git a/Frameworks/Growl.framework/Versions/A/Resources/Info.plist b/Frameworks/Growl.framework/Versions/A/Resources/Info.plist index 0513cfa..eab6527 100644 --- a/Frameworks/Growl.framework/Versions/A/Resources/Info.plist +++ b/Frameworks/Growl.framework/Versions/A/Resources/Info.plist @@ -2,6 +2,8 @@ + BuildMachineOSBuild + 12C60 CFBundleDevelopmentRegion English CFBundleExecutable @@ -13,11 +15,25 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.8 + 2.0 CFBundleSignature GRRR CFBundleVersion - exported + 2.0 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4G1004 + DTPlatformVersion + GM + DTSDKBuild + 12C37 + DTSDKName + macosx10.8 + DTXcode + 0451 + DTXcodeBuild + 4G1004 NSPrincipalClass GrowlApplicationBridge diff --git a/Resources/VoiceMac/English.lproj/AccountSetup.xib b/Resources/VoiceMac/English.lproj/AccountSetup.xib index 046ba84..0b023ac 100644 --- a/Resources/VoiceMac/English.lproj/AccountSetup.xib +++ b/Resources/VoiceMac/English.lproj/AccountSetup.xib @@ -2,10 +2,10 @@ 1050 - 10J567 - 823 - 1038.35 - 462.00 + 12E55 + 3084 + 1187.39 + 626.00 YES @@ -13,29 +13,39 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.WebKitIBPlugin - + YES - 823 - 823 + 3084 + 2053 - + YES - + NSButton + NSButtonCell + NSCustomObject + NSImageCell + NSImageView + NSMatrix + NSProgressIndicator + NSSecureTextField + NSSecureTextFieldCell + NSTabView + NSTabViewItem + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate + WebView YES - com.apple.WebKitIBPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin - YES - - YES - - - YES - + PluginDependencyRecalculationVersion + YES @@ -56,7 +66,7 @@ VoiceMac NSWindow - {3.40282e+38, 3.40282e+38} + 256 @@ -79,9 +89,11 @@ {{0, 25}, {330, 360}} + + YES - 130560 + 134217728 33554432 NSImage @@ -92,6 +104,7 @@ 0 YES + NO YES @@ -99,9 +112,11 @@ 268 {{158, 381}, {404, 21}} + + YES - 68288064 + 68157504 272630784 Welcome to VoiceMac @@ -116,7 +131,7 @@ controlColor 3 - MC42NjY2NjY2ODY1AA + MC42NjY2NjY2NjY3AA @@ -129,15 +144,18 @@ + NO 268 {{371, 6}, {97, 32}} + + YES - 67239424 + 67108864 134217728 Go Back @@ -146,39 +164,44 @@ 1044 - -2038284033 + -2038284288 129 Gw 200 25 + NO 268 {{468, 6}, {97, 32}} + YES - 67239424 + 67108864 134217728 Continue - -2038284033 + -2038284288 129 DQ 200 25 + NO 12 {{137, 49}, {422, 326}} + + YES @@ -193,9 +216,11 @@ 268 {{16, 33}, {388, 272}} + + YES - 67239424 + 67108864 272891904 VGhlIGZpcnN0IEdvb2dsZSBWb2ljZSBjbGllbnQgZm9yIHRoZSBNYWMuIFNlbmQgbXVsdGlwbGUgU01T IE1lc3NhZ2VzLCBzZW5kIFNNUyBNZXNzYWdlcywgcmVjZWl2ZSBTTVMgTWVzc2FnZXMsIHBsYWNlIGNh @@ -218,15 +243,18 @@ aXRoIHNpbXBsZSBIVE1MIG9yIGJ5IGRvd25sb2FkaW5nIGEgdGhlbWUuA + NO 268 {{269, 19}, {134.904, 14}} + + YES - 68288064 + 68157504 272761856 Press Continue to begin. @@ -238,10 +266,13 @@ aXRoIHNpbXBsZSBIVE1MIG9yIGJ5IGRvd25sb2FkaW5nIGEgdGhlbWUuA + NO {{1, 1}, {420, 324}} + + Welcome To VoiceMac @@ -259,9 +290,10 @@ aXRoIHNpbXBsZSBIVE1MIG9yIGJ5IGRvd25sb2FkaW5nIGEgdGhlbWUuA 268 {{16, 237}, {388, 68}} + YES - 67239424 + 67108864 272891904 Choose an account type to set up and press continue. When you set up a Google Voice account, it will automatically add a second account for Google Contacts to receive contacts from that account. @@ -269,25 +301,28 @@ aXRoIHNpbXBsZSBIVE1MIG9yIGJ5IGRvd25sb2FkaW5nIGEgdGhlbWUuA + NO 268 {{19, 171}, {382, 58}} + YES + NO 3 1 YES - -2080244224 + -2080374784 0 Google Voice and Google Contacts 1 - 1211912703 + 1211912448 0 NSRadioButton @@ -298,12 +333,12 @@ aXRoIHNpbXBsZSBIVE1MIG9yIGJ5IGRvd25sb2FkaW5nIGEgdGhlbWUuA 25 - 67239424 + 67108864 0 Google Contacts - 1211912703 + 1211912448 0 549453824 @@ -406,12 +441,12 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 75 - 67239424 + 67108864 0 Session Initiation Protocol (SIP) - 1211912703 + 1211912448 0 400 @@ -423,11 +458,11 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1151868928 NSActionCell - 67239424 + 67108864 0 Radio - 1211912703 + 1211912448 0 549453824 @@ -484,6 +519,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {420, 324}} + Account Type @@ -535,7 +571,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA WebKitDefaultFontSize WebKitMinimumFontSize - + YES @@ -548,6 +584,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{1, 1}, {420, 324}} + Google Voice Privacy Policy @@ -565,25 +602,28 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 254}, {388, 51}} + YES - 67239424 + 67108864 272891904 - To set up the Google Voice account, type in your email address (If it's a gmail address you can skip @gmail.com.), password, and press continue. + To set up the Google Voice account, type in your email address, password, and press continue. + NO 268 {{16, 226}, {104, 17}} + YES - 68288064 + 68157504 71304192 Email Address: @@ -595,15 +635,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{22, 196}, {98, 17}} + YES - 68288064 + 68157504 71304192 Password: @@ -611,15 +653,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{125, 224}, {276, 22}} + YES - -1804468671 + -1804599231 272630784 @@ -639,15 +683,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{125, 194}, {276, 22}} + YES - 343014976 + 342884416 272630784 @@ -660,9 +706,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSAllRomanInputSourcesLocaleIdentifier + NO {{1, 1}, {420, 324}} + Google Voice Setup @@ -680,25 +728,28 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 254}, {388, 51}} + YES - 67239424 + 67108864 272891904 - To set up the Google Contacts account, type in your email address (If it's a gmail address you can skip @gmail.com.), password, and press continue. + To set up the Google Contacts account, type in your email address, password, and press continue. + NO 268 {{16, 226}, {104, 17}} + YES - 68288064 + 68157504 71304192 Email Address: @@ -706,15 +757,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{22, 196}, {98, 17}} + YES - 68288064 + 68157504 71304192 Password: @@ -722,15 +775,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{125, 224}, {276, 22}} + YES - -1804468671 + -1804599231 272630784 @@ -740,15 +795,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{125, 194}, {276, 22}} + YES - 343014976 + 342884416 272630784 @@ -761,9 +818,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSAllRomanInputSourcesLocaleIdentifier + NO {{1, 1}, {420, 324}} + Google Contacts Setup @@ -781,9 +840,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 192}, {76, 17}} + YES - 68288064 + 68157504 71304192 Full Name: @@ -791,15 +851,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{16, 162}, {76, 17}} + YES - 68288064 + 68157504 71304192 Domain: @@ -807,15 +869,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{16, 132}, {76, 17}} + YES - 68288064 + 68157504 71304192 Registrar: @@ -823,15 +887,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{16, 102}, {76, 17}} + YES - 68288064 + 68157504 71304192 UserName: @@ -839,15 +905,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{16, 72}, {76, 17}} + YES - 68288064 + 68157504 71304192 Password: @@ -855,15 +923,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{16, 220}, {388, 85}} + YES - 67239424 + 67108864 272629760 To set up your SIP account, go to your SIP provider and find out the information needed to fill these forms. The full name is just so you can easily identify the account with the Window menu. After you filled out the information, press continue. @@ -871,15 +941,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{97, 190}, {304, 22}} + YES - -1804468671 + -1804599231 272630784 @@ -889,49 +961,57 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{97, 160}, {304, 22}} + YES - -1804468671 + -1804599231 272630784 + Providers usually require * YES + NO 268 {{97, 130}, {304, 22}} + YES - -1804468671 + -1804599231 272630784 + proxy.example.com YES + NO 268 {{97, 100}, {304, 22}} + YES - -1804468671 + -1804599231 272630784 @@ -940,15 +1020,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{97, 70}, {304, 22}} + YES - 343014976 + 342884416 272630784 @@ -961,9 +1043,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSAllRomanInputSourcesLocaleIdentifier + NO {{1, 1}, {420, 324}} + SIP Setup @@ -981,9 +1065,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 199}, {388, 17}} + YES - 68288064 + 68157504 138413056 Please wait... @@ -991,13 +1076,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 1292 - {{194, 146}, {32, 32}} + 20490 100 @@ -1006,9 +1092,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 108}, {388, 17}} + YES - 68288064 + 68157504 138413056 Checking Login Credentials. @@ -1016,15 +1103,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{16, 271}, {388, 34}} + YES - 67239424 + 67108864 272629760 This may take awhile, depending on your internet connection. @@ -1032,9 +1121,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO {{1, 1}, {420, 324}} + Checking Login Credentials @@ -1052,9 +1143,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 19}, {388, 286}} + YES - 67239424 + 67108864 272891904 Unable to set up your ACCOUNTTYPE account, the error we received was ERRORMESSAGE. Please go back and correct the problem. @@ -1062,9 +1154,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO {{1, 1}, {420, 324}} + Setup Error @@ -1082,9 +1176,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{16, 59}, {388, 246}} + YES - 67239424 + 67108864 272891904 You have sucessfully set up your ACCOUNTTYPE account. You may continue to the Application or add another account by pressing "Add Another Account". If you are confused about VoiceMac, please read the documentation which explains all you can do with it. @@ -1092,29 +1187,33 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{122, 11}, {176, 32}} + YES - 67239424 + 67108864 134217728 Add Another Account - -2038284033 + -2038284288 129 200 25 + NO {{1, 1}, {420, 324}} + Setup Successful @@ -1134,9 +1233,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {579, 410} + + - {{0, 0}, {1280, 778}} - {3.40282e+38, 3.40282e+38} + {{0, 0}, {1440, 878}} + {10000000000000, 10000000000000} + YES @@ -1336,11 +1438,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - S6DomainChanged: + S6RegistrarChanged: - + - 159 + 161 @@ -1356,7 +1458,9 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES 0 - + + YES + @@ -2136,19 +2240,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES YES - 1.IBEditorWindowLastContentRect + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency 1.IBPluginDependency 1.IBWindowTemplateEditedContentRect 1.NSWindowTemplate.visibleAtLaunch - 1.WindowOrigin - 1.editorWindowContentRectSynchronizationRect 10.IBPluginDependency 100.IBPluginDependency 101.IBPluginDependency - 101.IBViewBoundsToFrameTransform 102.IBPluginDependency 103.IBPluginDependency - 103.IBViewBoundsToFrameTransform 104.IBPluginDependency 105.IBPluginDependency 106.IBPluginDependency @@ -2164,12 +2266,18 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 115.IBPluginDependency 12.IBPluginDependency 13.IBPluginDependency + 132.IBPluginDependency + 133.IBPluginDependency 134.IBPluginDependency 135.IBPluginDependency 14.IBPluginDependency 15.CustomClassName 15.IBPluginDependency 2.IBPluginDependency + 20.IBPluginDependency + 21.IBPluginDependency + 22.IBPluginDependency + 23.IBPluginDependency 24.IBPluginDependency 25.IBPluginDependency 26.IBPluginDependency @@ -2180,6 +2288,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 34.IBPluginDependency 35.IBPluginDependency 36.IBPluginDependency + 37.IBPluginDependency + 40.IBPluginDependency + 41.IBPluginDependency + 42.IBPluginDependency + 43.IBPluginDependency + 44.IBPluginDependency + 45.IBPluginDependency 46.IBPluginDependency 47.IBPluginDependency 48.IBPluginDependency @@ -2191,6 +2306,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 64.IBPluginDependency 65.IBPluginDependency 66.IBPluginDependency + 67.IBPluginDependency + 68.IBPluginDependency + 69.IBPluginDependency + 7.IBPluginDependency + 70.IBPluginDependency + 71.IBPluginDependency + 72.IBPluginDependency 73.IBPluginDependency 74.IBPluginDependency 75.IBPluginDependency @@ -2198,55 +2320,44 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 77.IBPluginDependency 78.IBPluginDependency 79.IBPluginDependency + 8.IBPluginDependency 80.IBPluginDependency 81.IBPluginDependency 82.IBPluginDependency 83.IBPluginDependency - 83.IBViewBoundsToFrameTransform 84.IBPluginDependency 85.IBPluginDependency - 85.IBViewBoundsToFrameTransform 86.IBPluginDependency 87.IBPluginDependency - 87.IBViewBoundsToFrameTransform 88.IBPluginDependency 89.IBPluginDependency - 89.IBViewBoundsToFrameTransform 9.IBPluginDependency 90.IBPluginDependency 91.IBPluginDependency - 91.IBViewBoundsToFrameTransform 92.IBPluginDependency 93.IBPluginDependency 94.IBPluginDependency 95.IBPluginDependency - 95.IBViewBoundsToFrameTransform 96.IBPluginDependency 97.IBPluginDependency - 97.IBViewBoundsToFrameTransform 98.IBPluginDependency 99.IBPluginDependency - 99.IBViewBoundsToFrameTransform - + YES - {{334, 336}, {579, 410}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{334, 336}, {579, 410}} - {196, 240} - {{202, 428}, {480, 270}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCwgAAwrAAAA - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCwgAAwmgAAA - + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2278,6 +2389,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.WebKitIBPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2300,66 +2422,46 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABBgAAAwy8AAA - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABBgAAAwxEAAA - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABBgAAAwuYAAA - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABBgAAAwqoAAA - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABBgAAAwlwAAA - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCwgAAwzIAAA - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCwgAAwxQAAA - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCwgAAwuwAAA - + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin YES - - YES - + YES - - YES - + - 160 + 161 @@ -2371,14 +2473,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES YES - S6DomainChanged: + S6RegistrarChanged: S6UserNameChanged: S9AddAnotherAccount: back: continue: showSetupWindow: - + YES id id @@ -2392,17 +2494,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES YES - S6DomainChanged: + S6RegistrarChanged: S6UserNameChanged: S9AddAnotherAccount: back: continue: showSetupWindow: - + YES - S6DomainChanged: + S6RegistrarChanged: id @@ -2452,7 +2554,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA stepView titleField - + YES NSMatrix WebView @@ -2501,7 +2603,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA stepView titleField - + YES S2AccountTypeMatrix @@ -2587,7 +2689,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA IBProjectSource - Classes/VoiceMac/MGMAccountSetup.h + ./Classes/MGMAccountSetup.h @@ -2595,750 +2697,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSTabView IBProjectSource - Classes/VoiceMac/Views/MGMTranslucentTabView.h - - - - - YES - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSImageCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSImageCell.h - - - - NSImageView - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSImageView.h - - - - NSMatrix - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSMatrix.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - Growl.framework/Headers/GrowlApplicationBridge.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureDecompressedVideoOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureFileOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureVideoPreviewOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureView.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTMovie.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTMovieView.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSProgressIndicator - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSProgressIndicator.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSSecureTextField - NSTextField - - IBFrameworkSource - AppKit.framework/Headers/NSSecureTextField.h - - - - NSSecureTextFieldCell - NSTextFieldCell - - - - NSTabView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTabView.h - - - - NSTabViewItem - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTabViewItem.h - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - MGMUsers.framework/Headers/MGMPreferences.h - - - - WebView - NSView - - YES - - YES - goBack: - goForward: - makeTextLarger: - makeTextSmaller: - makeTextStandardSize: - reload: - stopLoading: - takeStringURLFrom: - toggleContinuousSpellChecking: - toggleSmartInsertDelete: - - - YES - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - goBack: - goForward: - makeTextLarger: - makeTextSmaller: - makeTextStandardSize: - reload: - stopLoading: - takeStringURLFrom: - toggleContinuousSpellChecking: - toggleSmartInsertDelete: - - - YES - - goBack: - id - - - goForward: - id - - - makeTextLarger: - id - - - makeTextSmaller: - id - - - makeTextStandardSize: - id - - - reload: - id - - - stopLoading: - id - - - takeStringURLFrom: - id - - - toggleContinuousSpellChecking: - id - - - toggleSmartInsertDelete: - id - - - - - IBFrameworkSource - WebKit.framework/Headers/WebView.h + ./Classes/MGMTranslucentTabView.h @@ -3354,7 +2713,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - ../../../VoiceMac.xcodeproj 3 VoiceMac Setup diff --git a/Resources/VoiceMac/English.lproj/InboxWindow.xib b/Resources/VoiceMac/English.lproj/InboxWindow.xib index 3ed69c4..fbe3d28 100644 --- a/Resources/VoiceMac/English.lproj/InboxWindow.xib +++ b/Resources/VoiceMac/English.lproj/InboxWindow.xib @@ -2,30 +2,40 @@ 1050 - 10F569 - 788 - 1038.29 - 461.00 + 12C60 + 2843 + 1187.34 + 625.00 com.apple.InterfaceBuilder.CocoaPlugin - 788 + 2843 - + YES - + NSButton + NSButtonCell + NSCustomObject + NSCustomView + NSOutlineView + NSProgressIndicator + NSScrollView + NSScroller + NSSplitView + NSTableColumn + NSTableHeaderView + NSTableView + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate YES com.apple.InterfaceBuilder.CocoaPlugin - YES - - YES - - - YES - + PluginDependencyRecalculationVersion + YES @@ -46,7 +56,7 @@ Inbox NSWindow - {3.40282e+38, 3.40282e+38} + {620, 240} @@ -68,6 +78,8 @@ 290 {122, 22} + + MGMBottomView @@ -85,7 +97,11 @@ 4352 {122, 218} + + YES + NO + YES -2147483392 @@ -98,7 +114,7 @@ 16 1000 - 75628096 + 75497536 2048 @@ -121,7 +137,7 @@ - 337772096 + 337641536 2048 Text Cell @@ -136,7 +152,7 @@ controlBackgroundColor 3 - MC42NjY2NjY2ODY1AA + MC42NjY2NjY2NjY3AA @@ -176,10 +192,12 @@ 0 YES 0 + 1 {{1, 1}, {122, 218}} + @@ -190,6 +208,9 @@ -2147483392 {{224, 17}, {15, 102}} + + + NO _doScroller: 0.99628251791000366 @@ -199,6 +220,9 @@ -2147483392 {{1, 119}, {238, 15}} + + + NO 1 _doScroller: @@ -207,16 +231,22 @@ {{-1, 21}, {124, 220}} + - 562 + 133682 QSAAAEEgAABBmAAAQZgAAA + 0.25 + 4 + 1 {122, 240} + + NSView @@ -232,9 +262,10 @@ 1313 - {{367, -1}, {112, 20}} + + 24586 100 @@ -243,9 +274,11 @@ 292 {{85, 1}, {43, 17}} + + YES - 67239424 + 67108864 134348800 Next @@ -254,42 +287,48 @@ 16 - -2038152961 + -2038153216 173 400 75 + NO 292 {{9, 1}, {68, 17}} + + YES - 67239424 + 67108864 134348800 Previous - -2038152961 + -2038153216 173 400 75 + NO 289 {{376, 3}, {104, 14}} + + YES - 68288064 + 68157504 71435264 Page @@ -302,10 +341,13 @@ + NO {497, 22} + + MGMBottomView @@ -321,9 +363,22 @@ 4352 - {497, 218} + {497, 202} + + YES + NO + YES + + + 256 + {497, 17} + + + + + -2147483392 @@ -337,7 +392,7 @@ 10 10 - 75628096 + 75497536 2048 @@ -348,7 +403,7 @@ - 337772096 + 337641536 2048 Text Cell @@ -364,15 +419,15 @@ 40 1000 - 75628096 + 75497536 2048 - + Phone - 337772096 + 337641536 2048 Text Cell @@ -390,9 +445,9 @@ 40 1000 - 75628096 + 75497536 2048 - + Info 6 @@ -406,7 +461,7 @@ - 337772096 + 337641536 2048 Text Cell @@ -424,15 +479,15 @@ 159 159 - 75628096 + 75497536 67110912 - + Date - 337772096 + 337641536 2048 Text Cell @@ -456,10 +511,12 @@ 0 YES 0 + 1 - {{1, 1}, {497, 218}} + {{1, 17}, {497, 202}} + @@ -470,48 +527,81 @@ -2147483392 {{-100, -100}, {15, 200}} + + + NO _doScroller: - 0.93119263648986816 + 0.99507389162561577 -2147483392 {{-100, -100}, {497, 15}} + + + NO 1 _doScroller: 0.99799197912216187 + + + 2304 + + YES + + + {{1, 0}, {497, 17}} + + + + + + 4 + {{-1, 21}, {499, 220}} - - 530 + + + 133650 + QSAAAEEgAABBmAAAQZgAAA + 0.25 + 4 + 1 {{123, 0}, {497, 240}} + + NSView {620, 240} + + YES 2 {620, 240} + + - {{0, 0}, {1280, 778}} + {{0, 0}, {1440, 878}} {620, 262} - {3.40282e+38, 3.40282e+38} + {10000000000000, 10000000000000} + YES @@ -573,6 +663,38 @@ 46 + + + previous: + + + + 53 + + + + next: + + + + 54 + + + + progress + + + + 56 + + + + delegate + + + + 52 + delegate @@ -613,38 +735,6 @@ 51 - - - delegate - - - - 52 - - - - previous: - - - - 53 - - - - next: - - - - 54 - - - - progress - - - - 56 - inboxWindow @@ -659,7 +749,9 @@ YES 0 - + + YES + @@ -781,6 +873,7 @@ + @@ -926,22 +1019,23 @@ + + 58 + + + YES YES - 1.IBEditorWindowLastContentRect + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency 1.IBPluginDependency 1.IBWindowTemplateEditedContentRect 1.NSWindowTemplate.visibleAtLaunch - 1.WindowOrigin - 1.editorWindowContentRectSynchronizationRect - 1.windowTemplate.hasMaxSize - 1.windowTemplate.hasMinSize - 1.windowTemplate.maxSize - 1.windowTemplate.minSize 11.IBPluginDependency 14.IBPluginDependency 15.IBPluginDependency @@ -958,6 +1052,10 @@ 29.IBPluginDependency 3.CustomClassName 3.IBPluginDependency + 30.IBPluginDependency + 31.IBPluginDependency + 32.IBPluginDependency + 33.IBPluginDependency 34.IBPluginDependency 35.IBPluginDependency 36.IBPluginDependency @@ -967,24 +1065,21 @@ 4.IBPluginDependency 5.IBPluginDependency 55.IBPluginDependency + 58.IBPluginDependency 6.IBPluginDependency 7.IBPluginDependency 8.IBPluginDependency 9.CustomClassName 9.IBPluginDependency - + YES - {{181, 167}, {620, 240}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{181, 167}, {620, 240}} - {196, 240} - {{202, 428}, {480, 270}} - - - {620, 240} - {620, 240} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1013,6 +1108,11 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin MGMGradiantOutlineView com.apple.InterfaceBuilder.CocoaPlugin @@ -1020,20 +1120,16 @@ YES - - YES - + YES - - YES - + - 57 + 58 @@ -1043,7 +1139,7 @@ NSView IBProjectSource - Classes/VoiceMac/Views/MGMBottomView.h + ./Classes/MGMBottomView.h @@ -1051,7 +1147,7 @@ NSOutlineView IBProjectSource - Classes/VoiceMac/Views/MGMGradiantView.h + ./Classes/MGMGradiantOutlineView.h @@ -1068,9 +1164,9 @@ MGMInboxWindow - + IBProjectSource - Classes/VoiceMac/Inbox/MGMInboxWindow.h + ./Classes/MGMInboxTableView.h @@ -1085,14 +1181,18 @@ next: previous: showWindow: + spam: + undelete: - + YES id id id id id + id + id @@ -1104,8 +1204,10 @@ next: previous: showWindow: + spam: + undelete: - + YES delete: @@ -1127,6 +1229,14 @@ showWindow: id + + spam: + id + + + undelete: + id + @@ -1142,7 +1252,7 @@ sidebarView splitView - + YES NSTableView NSWindow @@ -1167,7 +1277,7 @@ sidebarView splitView - + YES inboxTable @@ -1203,699 +1313,17 @@ - + + IBProjectSource + ./Classes/MGMInboxWindow.h + MGMSplitView NSSplitView IBProjectSource - Classes/VoiceMac/Views/MGMSplitView.h - - - - - YES - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSObject - - IBFrameworkSource - AddressBook.framework/Headers/ABActions.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - Growl.framework/Headers/GrowlApplicationBridge.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureDecompressedAudioOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureDecompressedVideoOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureFileOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureVideoPreviewOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureView.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTMovie.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTMovieView.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAutomaticUpdateAlert.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUInstaller.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUnarchiver.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdateAlert.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdatePermissionPrompt.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSOutlineView - NSTableView - - - - NSProgressIndicator - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSProgressIndicator.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSSplitView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSSplitView.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableView - NSControl - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - MGMUsers.framework/Headers/MGMPreferences.h + ./Classes/MGMSplitView.h @@ -1911,7 +1339,6 @@ YES - ../../VoiceMac.xcodeproj 3 diff --git a/Resources/VoiceMac/Info.plist b/Resources/VoiceMac/Info.plist index 4373836..0e50dc9 100644 --- a/Resources/VoiceMac/Info.plist +++ b/Resources/VoiceMac/Info.plist @@ -68,7 +68,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.2.1 + 0.3 CFBundleSignature ???? CFBundleURLTypes @@ -105,7 +105,7 @@ CFBundleVersion - 0.2.1 + 0.3 MGMGRBugsEmail bugs@mrgeckosmedia.com MGMGRContactEmail diff --git a/Resources/VoiceMac/Preferences/English.lproj/AccountsPane.xib b/Resources/VoiceMac/Preferences/English.lproj/AccountsPane.xib index c32ebe4..62014df 100644 --- a/Resources/VoiceMac/Preferences/English.lproj/AccountsPane.xib +++ b/Resources/VoiceMac/Preferences/English.lproj/AccountsPane.xib @@ -2,48 +2,45 @@ 1050 - 10J567 - 1294 - 1038.35 - 462.00 + 12E55 + 3084 + 1187.39 + 626.00 com.apple.InterfaceBuilder.CocoaPlugin - 1294 + 3084 YES - NSView + NSBox + NSButton NSButtonCell - NSSecureTextFieldCell - NSPopUpButton - NSTextFieldCell - NSTabViewItem - NSPopUpButtonCell - NSScrollView + NSCustomObject + NSCustomView + NSMatrix NSMenu NSMenuItem - NSSecureTextField - NSTabView - NSCustomView - NSCustomObject - NSTableColumn - NSBox + NSPopUpButton + NSPopUpButtonCell + NSScrollView NSScroller + NSSecureTextField + NSSecureTextFieldCell + NSTabView + NSTabViewItem + NSTableColumn NSTableView NSTextField - NSMatrix - NSButton + NSTextFieldCell + NSView YES com.apple.InterfaceBuilder.CocoaPlugin - YES - - YES - - + PluginDependencyRecalculationVersion + YES @@ -84,7 +81,7 @@ YES - 256 + 274 YES @@ -94,12 +91,13 @@ YES + NO 2 1 YES - -2080244224 + -2080374784 0 Apple Address Book @@ -109,7 +107,7 @@ 1 - 1211912703 + 1211912448 0 NSRadioButton @@ -120,12 +118,12 @@ 25 - 67239424 + 67108864 0 Google Contacts - 1211912703 + 1211912448 0 549453824 @@ -233,11 +231,11 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1151868928 NSActionCell - 67239424 + 67108864 0 Radio - 1211912703 + 1211912448 0 549453824 @@ -291,7 +289,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA controlColor 3 - MC42NjY2NjY2ODY1AA + MC42NjY2NjY2NjY3AA @@ -308,7 +306,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 272630784 Retrieve contacts from: @@ -324,6 +322,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -332,18 +331,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES + NO 2 1 YES - -2080244224 + -2080374784 0 Place a call 1 - 1211912703 + 1211912448 0 @@ -352,12 +352,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 25 - 67239424 + 67108864 0 Start an SMS Message - 1211912703 + 1211912448 0 549453824 @@ -462,11 +462,11 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1151868928 NSActionCell - 67239424 + 67108864 0 Radio - 1211912703 + 1211912448 0 549453824 @@ -526,7 +526,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 272630784 On contacts return or double click: @@ -534,6 +534,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -543,11 +544,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -2076049856 + -2076180416 2048 - 109199615 + 109199360 129 @@ -568,6 +569,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES 2 + NO @@ -577,7 +579,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 UserName: @@ -589,6 +591,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -598,7 +601,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Password: @@ -606,6 +609,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -615,7 +619,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -634,6 +638,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -643,7 +648,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 343014976 + 342884416 272630784 @@ -656,6 +661,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSAllRomanInputSourcesLocaleIdentifier + NO {{1, 1}, {285, 204}} @@ -668,7 +674,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {0, 0} - 67239424 + 67108864 0 Box @@ -710,7 +716,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 256 + 274 YES @@ -721,7 +727,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 UserName: @@ -729,6 +735,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -738,7 +745,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Password: @@ -746,6 +753,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -755,7 +763,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -764,6 +772,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -773,7 +782,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 343014976 + 342884416 272630784 @@ -786,6 +795,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSAllRomanInputSourcesLocaleIdentifier + NO {{1, 1}, {285, 204}} @@ -798,7 +808,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {0, 0} - 67239424 + 67108864 0 Box @@ -854,7 +864,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 UserName: @@ -862,6 +872,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -872,7 +883,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Password: @@ -880,6 +891,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -890,7 +902,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Registrar: @@ -902,6 +914,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -912,7 +925,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Domain: @@ -920,6 +933,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -930,7 +944,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Full Name: @@ -938,6 +952,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -948,7 +963,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -957,6 +972,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -967,16 +983,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 - proxy01.sipphone.com + Usually * YES + NO @@ -987,16 +1004,17 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 - proxy01.sipphone.com + proxy.example.com YES + NO @@ -1007,7 +1025,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -1016,6 +1034,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1026,7 +1045,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 343014976 + 342884416 272630784 @@ -1039,6 +1058,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSAllRomanInputSourcesLocaleIdentifier + NO @@ -1049,7 +1069,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 138413056 You must be logged out to edit. @@ -1057,6 +1077,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1067,7 +1088,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Area Code: @@ -1075,6 +1096,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1085,7 +1107,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -1094,6 +1116,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO {{10, 33}, {297, 188}} @@ -1120,7 +1143,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Registrar Timeout: @@ -1128,6 +1151,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1137,7 +1161,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Proxy Host: @@ -1145,6 +1169,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1154,7 +1179,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Proxy Port: @@ -1162,6 +1187,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1171,7 +1197,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -1180,6 +1206,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1189,7 +1216,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -1199,6 +1226,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1208,7 +1236,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 SIP Address: @@ -1216,6 +1244,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1225,7 +1254,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -1234,6 +1263,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1243,7 +1273,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -1804468671 + -1804599231 272630784 @@ -1253,6 +1283,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1262,7 +1293,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 272630784 Seconds @@ -1270,6 +1301,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1279,7 +1311,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 138413056 You must be logged out to edit. @@ -1287,6 +1319,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1296,7 +1329,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 DTMF Tone: @@ -1304,20 +1337,20 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 268 {{98, 20}, {185, 26}} - YES - -2076049856 + -2076180416 2048 - 109199615 + 109199360 129 @@ -1377,6 +1410,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES 2 + NO @@ -1386,7 +1420,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 71304192 Transport: @@ -1394,6 +1428,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1403,11 +1438,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -2076049856 + -2076180416 2048 - 109199615 + 109199360 129 @@ -1461,6 +1496,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES 2 + NO {{10, 33}, {297, 188}} @@ -1483,18 +1519,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{17, 122}, {154, 38}} YES + NO 2 1 YES - -2080244224 + -2080374784 0 Apple Address Book 1 - 1211912703 + 1211912448 0 @@ -1503,12 +1540,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 25 - 67239424 + 67108864 0 Google Contacts - 1211912703 + 1211912448 0 549453824 @@ -1613,11 +1650,11 @@ QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA 1151868928 NSActionCell - 67239424 + 67108864 0 Radio - 1211912703 + 1211912448 0 549453824 @@ -1676,7 +1713,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - 68288064 + 68157504 272630784 Retrieve contacts from: @@ -1684,6 +1721,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO @@ -1692,11 +1730,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -2076049856 + -2076180416 2048 - 109199615 + 109199360 129 @@ -1717,6 +1755,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES 2 + NO {{10, 33}, {297, 188}} @@ -1775,6 +1814,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES + NO + YES -2147483392 @@ -1788,7 +1829,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 10 1000 - 75628096 + 75497536 2048 @@ -1804,7 +1845,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 337772096 + 337641536 2048 Text Cell @@ -1827,7 +1868,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 10 3.4028230607370965e+38 - 75628096 + 75497536 2048 @@ -1840,7 +1881,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 337772096 + 337641536 2048 Text Cell @@ -1874,6 +1915,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 0 YES 0 + 1 {{1, 1}, {174, 198}} @@ -1891,6 +1933,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO _doScroller: 0.84210532903671265 @@ -1902,6 +1945,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + NO 1 _doScroller: @@ -1912,11 +1956,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 562 + 133682 QSAAAEEgAABBmAAAQZgAAA + 0.25 + 4 + 1 @@ -1927,18 +1974,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -2080244224 + -2080374784 134217728 Login - -2033434369 + -2033434624 162 400 75 + NO @@ -1949,18 +1997,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -2080244224 + -2080374784 134217728 - - -2033434369 + -2033434624 162 400 75 + NO @@ -1971,18 +2020,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES - -2080244224 + -2080374784 134217728 + - -2033434369 + -2033434624 162 400 75 + NO {477, 220} @@ -2043,22 +2093,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 64 - - - dataSource - - - - 65 - - - - delegate - - - - 66 - saveContacts: @@ -2419,13 +2453,31 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 287 + + + dataSource + + + + 65 + + + + delegate + + + + 66 + YES 0 - + + YES + @@ -2788,13 +2840,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - + @@ -3475,11 +3527,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES YES - 1.IBEditorWindowLastContentRect + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency 1.IBPluginDependency - 1.WindowOrigin - 1.editorWindowContentRectSynchronizationRect 100.IBPluginDependency + 101.IBPluginDependency + 102.IBPluginDependency 108.IBPluginDependency 109.IBPluginDependency 110.IBPluginDependency @@ -3527,6 +3581,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 180.IBPluginDependency 181.IBPluginDependency 182.IBPluginDependency + 201.IBPluginDependency + 202.IBPluginDependency 203.IBPluginDependency 204.IBPluginDependency 205.IBPluginDependency @@ -3535,12 +3591,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 208.IBPluginDependency 210.IBPluginDependency 211.IBPluginDependency - 212.IBEditorWindowLastContentRect 212.IBPluginDependency 22.IBPluginDependency 221.IBPluginDependency 222.IBPluginDependency - 223.IBEditorWindowLastContentRect 223.IBPluginDependency 229.IBPluginDependency 23.IBPluginDependency @@ -3570,16 +3624,26 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 269.IBPluginDependency 270.IBPluginDependency 271.IBPluginDependency + 272.IBPluginDependency + 273.IBPluginDependency + 274.IBPluginDependency + 275.IBPluginDependency 278.IBPluginDependency 279.IBPluginDependency 280.IBPluginDependency + 281.IBPluginDependency + 282.IBPluginDependency + 283.IBPluginDependency + 284.IBPluginDependency 285.IBPluginDependency 56.IBPluginDependency 57.IBPluginDependency 58.IBPluginDependency 59.IBPluginDependency + 60.IBPluginDependency 61.IBPluginDependency 62.IBPluginDependency + 63.IBPluginDependency 68.IBPluginDependency 69.IBPluginDependency 70.IBPluginDependency @@ -3600,12 +3664,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 93.IBPluginDependency 94.IBPluginDependency - + YES - {{403, 202}, {477, 220}} - com.apple.InterfaceBuilder.CocoaPlugin - {628, 654} - {{217, 442}, {480, 272}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3662,12 +3722,28 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{629, 248}, {140, 4}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{629, 248}, {140, 4}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3762,7 +3838,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA saveGoogleContactsUser: saveSIP: - + YES id id @@ -3789,7 +3865,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA saveGoogleContactsUser: saveSIP: - + YES add: @@ -3861,7 +3937,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA settingsTab usersTable - + YES NSTextField NSTextField @@ -3924,7 +4000,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA settingsTab usersTable - + YES GCPasswordField @@ -4070,10 +4146,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA NSMenuCheckmark NSMenuMixedState - + YES - {9, 8} - {7, 2} + {11, 11} + {10, 3} diff --git a/Resources/VoiceMac/VoiceVerify.xib b/Resources/VoiceMac/VoiceVerify.xib index a0c908e..7375d04 100644 --- a/Resources/VoiceMac/VoiceVerify.xib +++ b/Resources/VoiceMac/VoiceVerify.xib @@ -2,30 +2,31 @@ 1050 - 10J567 - 823 - 1038.35 - 462.00 + 12E55 + 3084 + 1187.39 + 626.00 com.apple.InterfaceBuilder.CocoaPlugin - 823 + 3084 - + YES - + NSButton + NSButtonCell + NSCustomObject + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate YES com.apple.InterfaceBuilder.CocoaPlugin - YES - - YES - - - YES - + PluginDependencyRecalculationVersion + YES @@ -41,12 +42,12 @@ 1 2 - {{546, 344}, {187, 90}} + {{546, 344}, {187, 116}} 1618477056 Account Verification NSWindow - {3.40282e+38, 3.40282e+38} + 256 @@ -55,11 +56,13 @@ 268 - {{20, 48}, {147, 22}} + {{20, 49}, {147, 22}} + + YES - -1804468671 + -1804599231 272630784 @@ -82,59 +85,102 @@ 6 System textColor - + 3 MAA + NO 268 - {{14, 12}, {77, 32}} + {{14, 13}, {77, 32}} + + YES - 67239424 + 67108864 134217728 Verify - -2038284033 + -2038284288 129 DQ 200 25 + NO 268 - {{91, 12}, {82, 32}} + {{91, 13}, {82, 32}} + YES - 67239424 + 67108864 134217728 Cancel - -2038284033 + -2038284288 129 Gw 200 25 + NO + + + + 268 + {{17, 79}, {153, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Account Name + + _NS:1535 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + + + NO - {187, 90} + {187, 116} + + - {{0, 0}, {1280, 778}} - {3.40282e+38, 3.40282e+38} + {{0, 0}, {1440, 878}} + {10000000000000, 10000000000000} + YES @@ -172,13 +218,23 @@ 12 + + + accountNameField + + + + 15 + YES 0 - + + YES + @@ -217,6 +273,7 @@ + @@ -262,72 +319,74 @@ + + 13 + + + YES + + + + + + 14 + + + YES YES - 1.IBEditorWindowLastContentRect + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency 1.IBPluginDependency 1.IBWindowTemplateEditedContentRect 1.NSWindowTemplate.visibleAtLaunch - 1.WindowOrigin - 1.editorWindowContentRectSynchronizationRect + 13.IBPluginDependency + 14.IBPluginDependency 2.IBPluginDependency 3.IBPluginDependency - 3.IBViewBoundsToFrameTransform 4.IBPluginDependency 5.IBPluginDependency - 5.IBViewBoundsToFrameTransform 6.IBPluginDependency 7.IBPluginDependency - 7.IBViewBoundsToFrameTransform 8.IBPluginDependency - + YES - {{384, 539}, {187, 90}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{384, 539}, {187, 90}} - {196, 240} - {{202, 428}, {480, 270}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCBAAAwsQAAA - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABCoAAAwuAAAA - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - - P4AAAL+AAABDHQAAwuAAAA - + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin YES - - YES - + YES - - YES - + - 12 + 15 @@ -342,7 +401,7 @@ cancel: verify: - + YES id id @@ -355,7 +414,7 @@ cancel: verify: - + YES cancel: @@ -371,12 +430,14 @@ YES YES + accountNameField codeField window - + YES NSTextField + NSTextField NSWindow @@ -384,11 +445,16 @@ YES YES + accountNameField codeField window - + YES + + accountNameField + NSTextField + codeField NSTextField @@ -401,593 +467,7 @@ IBProjectSource - Classes/VoiceMac/MGMVoiceVerify.h - - - - - YES - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - Growl.framework/Headers/GrowlApplicationBridge.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureDecompressedVideoOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureFileOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureVideoPreviewOutput.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTCaptureView.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTMovie.h - - - - NSObject - - IBFrameworkSource - QTKit.framework/Headers/QTMovieView.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUAppcast.h - - - - NSObject - - IBFrameworkSource - Sparkle.framework/Headers/SUUpdater.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSTextField - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSTextField.h - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindow - - IBFrameworkSource - MGMUsers.framework/Headers/MGMPreferences.h + ./Classes/MGMVoiceVerify.h @@ -1003,7 +483,6 @@ YES - ../../VoiceMac.xcodeproj 3 diff --git a/SIP/install b/SIP/install index 2d40817..7e3312e 100755 --- a/SIP/install +++ b/SIP/install @@ -1,23 +1,25 @@ #!/bin/bash -PPCFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch ppc -ggdb" -PPCCC="/usr/bin/gcc-4.0" -PPCCXX="/usr/bin/g++-4.0" -PPCHOST="ppc-apple-darwin8" +PPCFLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch ppc -ggdb" +PPCCC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2" +PPCCXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2" +PPCAR="/Applications/Xcode.app/Contents/Developer/usr/bin/ar rv" +PPCRANLIB="/Applications/Xcode.app/Contents/Developer/usr/bin/ranlib" +PPCHOST="ppc-apple-darwin10" PPCPATH="${PWD}/opt-ppc" -PPCLDFLAGS="-arch ppc -isysroot /Developer/SDKs/MacOSX10.5.sdk" +PPCLDFLAGS="-arch ppc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk" -I386FLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch i386 -ggdb" -I386CC="/usr/bin/gcc-4.0" -I386CXX="/usr/bin/g++-4.0" -I386HOST="i386-apple-darwin8" +I386FLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch i386 -ggdb" +I386CC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2" +I386CXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2" +I386HOST="i386-apple-darwin10" I386PATH="${PWD}/opt-i386" I386LDFLAGS="-arch i386" -X86_64FLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch x86_64 -ggdb" -X86_64CC="/usr/bin/gcc-4.2" -X86_64CXX="/usr/bin/g++-4.2" -X86_64HOST="x86_64-apple-darwin9" +X86_64FLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch x86_64 -ggdb" +X86_64CC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2" +X86_64CXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2" +X86_64HOST="x86_64-apple-darwin10" X86_64PATH="${PWD}/opt-x86_64" X86_64LDFLAGS="-arch x86_64" @@ -48,11 +50,11 @@ if [ "$1" = "ios" ]; then cp -R ${PJPROJECTNAME}-ios6 ${PJPROJECTNAME}-simulator echo "Configuring PJProject" cd ${PJPROJECTNAME}-ios6 - CC="/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv6" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${IOS6PATH}" + CC="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -arch armv6" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${IOS6PATH}" cd ../${PJPROJECTNAME}-ios7 - CC="/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv7" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${IOS7PATH}" + CC="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -arch armv7" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${IOS7PATH}" cd ../${PJPROJECTNAME}-simulator - DEVPATH="/Developer/Platforms/iPhoneSimulator.platform/Developer" CC="/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${SIMULATORPATH}" + DEVPATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer" CC="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${SIMULATORPATH}" cd ../ echo "Compiling PJProject" @@ -79,23 +81,23 @@ if [ "$1" = "ios" ]; then echo "Making PJProject Universal" mkdir -p "${FINALPATH}/lib/pkgconfig" cp -R "${IOS6PATH}/include" "${FINALPATH}" - lipo -create "${IOS6PATH}/lib/libg7221codec-arm-apple-darwin9.a" "${IOS7PATH}/lib/libg7221codec-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libg7221codec-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libg7221codec-ios.a" - lipo -create "${IOS6PATH}/lib/libgsmcodec-arm-apple-darwin9.a" "${IOS7PATH}/lib/libgsmcodec-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libgsmcodec-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libgsmcodec-ios.a" - lipo -create "${IOS6PATH}/lib/libilbccodec-arm-apple-darwin9.a" "${IOS7PATH}/lib/libilbccodec-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libilbccodec-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libilbccodec-ios.a" - lipo -create "${IOS6PATH}/lib/libmilenage-arm-apple-darwin9.a" "${IOS7PATH}/lib/libmilenage-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libmilenage-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libmilenage-ios.a" - lipo -create "${IOS6PATH}/lib/libpj-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpj-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpj-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpj-ios.a" - lipo -create "${IOS6PATH}/lib/libpjlib-util-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjlib-util-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjlib-util-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjlib-util-ios.a" - lipo -create "${IOS6PATH}/lib/libpjmedia-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjmedia-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjmedia-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjmedia-ios.a" - lipo -create "${IOS6PATH}/lib/libpjmedia-audiodev-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjmedia-audiodev-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjmedia-audiodev-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjmedia-audiodev-ios.a" - lipo -create "${IOS6PATH}/lib/libpjmedia-codec-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjmedia-codec-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjmedia-codec-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjmedia-codec-ios.a" - lipo -create "${IOS6PATH}/lib/libpjnath-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjnath-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjnath-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjnath-ios.a" - lipo -create "${IOS6PATH}/lib/libpjsip-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjsip-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjsip-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsip-ios.a" - lipo -create "${IOS6PATH}/lib/libpjsip-simple-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjsip-simple-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjsip-simple-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsip-simple-ios.a" - lipo -create "${IOS6PATH}/lib/libpjsip-ua-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjsip-ua-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjsip-ua-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsip-ua-ios.a" - lipo -create "${IOS6PATH}/lib/libpjsua-arm-apple-darwin9.a" "${IOS7PATH}/lib/libpjsua-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libpjsua-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsua-ios.a" - lipo -create "${IOS6PATH}/lib/libresample-arm-apple-darwin9.a" "${IOS7PATH}/lib/libresample-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libresample-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libresample-ios.a" - lipo -create "${IOS6PATH}/lib/libspeex-arm-apple-darwin9.a" "${IOS7PATH}/lib/libspeex-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libspeex-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libspeex-ios.a" - lipo -create "${IOS6PATH}/lib/libsrtp-arm-apple-darwin9.a" "${IOS7PATH}/lib/libsrtp-arm-apple-darwin9.a" "${SIMULATORPATH}/lib/libsrtp-arm-apple-darwin9.a" -output "${FINALPATH}/lib/libsrtp-ios.a" + lipo -create "${IOS6PATH}/lib/libg7221codec-arm-apple-darwin10.a" "${IOS7PATH}/lib/libg7221codec-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libg7221codec-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libg7221codec-ios.a" + lipo -create "${IOS6PATH}/lib/libgsmcodec-arm-apple-darwin10.a" "${IOS7PATH}/lib/libgsmcodec-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libgsmcodec-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libgsmcodec-ios.a" + lipo -create "${IOS6PATH}/lib/libilbccodec-arm-apple-darwin10.a" "${IOS7PATH}/lib/libilbccodec-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libilbccodec-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libilbccodec-ios.a" + lipo -create "${IOS6PATH}/lib/libmilenage-arm-apple-darwin10.a" "${IOS7PATH}/lib/libmilenage-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libmilenage-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libmilenage-ios.a" + lipo -create "${IOS6PATH}/lib/libpj-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpj-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpj-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpj-ios.a" + lipo -create "${IOS6PATH}/lib/libpjlib-util-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjlib-util-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjlib-util-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjlib-util-ios.a" + lipo -create "${IOS6PATH}/lib/libpjmedia-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjmedia-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjmedia-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjmedia-ios.a" + lipo -create "${IOS6PATH}/lib/libpjmedia-audiodev-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjmedia-audiodev-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjmedia-audiodev-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjmedia-audiodev-ios.a" + lipo -create "${IOS6PATH}/lib/libpjmedia-codec-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjmedia-codec-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjmedia-codec-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjmedia-codec-ios.a" + lipo -create "${IOS6PATH}/lib/libpjnath-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjnath-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjnath-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjnath-ios.a" + lipo -create "${IOS6PATH}/lib/libpjsip-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjsip-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjsip-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsip-ios.a" + lipo -create "${IOS6PATH}/lib/libpjsip-simple-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjsip-simple-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjsip-simple-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsip-simple-ios.a" + lipo -create "${IOS6PATH}/lib/libpjsip-ua-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjsip-ua-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjsip-ua-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsip-ua-ios.a" + lipo -create "${IOS6PATH}/lib/libpjsua-arm-apple-darwin10.a" "${IOS7PATH}/lib/libpjsua-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libpjsua-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsua-ios.a" + lipo -create "${IOS6PATH}/lib/libresample-arm-apple-darwin10.a" "${IOS7PATH}/lib/libresample-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libresample-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libresample-ios.a" + lipo -create "${IOS6PATH}/lib/libspeex-arm-apple-darwin10.a" "${IOS7PATH}/lib/libspeex-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libspeex-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libspeex-ios.a" + lipo -create "${IOS6PATH}/lib/libsrtp-arm-apple-darwin10.a" "${IOS7PATH}/lib/libsrtp-arm-apple-darwin10.a" "${SIMULATORPATH}/lib/libsrtp-arm-apple-darwin10.a" -output "${FINALPATH}/lib/libsrtp-ios.a" fi if [ "$1" = "simulator" ]; then FINALPATH="${PWD}/opt-ios" @@ -116,7 +118,7 @@ if [ "$1" = "simulator" ]; then cd "${OLDDIR}" echo "Configuring PJProject" cd ${PJPROJECTNAME}-simulator - DEVPATH="/Developer/Platforms/iPhoneSimulator.platform/Developer" CC="/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${SIMULATORPATH}" + DEVPATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer" CC="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc" CFLAGS="${IOSCFLAGS}" ./configure-iphone --prefix="${SIMULATORPATH}" cd ../ echo "Compiling PJProject" @@ -133,23 +135,23 @@ if [ "$1" = "simulator" ]; then echo "Making PJProject Universal" mkdir -p "${FINALPATH}/lib/pkgconfig" cp -R "${SIMULATORPATH}/include" "${FINALPATH}" - mv "${SIMULATORPATH}/lib/libg7221codec-arm-apple-darwin9.a" "${FINALPATH}/lib/libg7221codec-ios.a" - mv "${SIMULATORPATH}/lib/libgsmcodec-arm-apple-darwin9.a" "${FINALPATH}/lib/libgsmcodec-ios.a" - mv "${SIMULATORPATH}/lib/libilbccodec-arm-apple-darwin9.a" "${FINALPATH}/lib/libilbccodec-ios.a" - mv "${SIMULATORPATH}/lib/libmilenage-arm-apple-darwin9.a" "${FINALPATH}/lib/libmilenage-ios.a" - mv "${SIMULATORPATH}/lib/libpj-arm-apple-darwin9.a" "${FINALPATH}/lib/libpj-ios.a" - mv "${SIMULATORPATH}/lib/libpjlib-util-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjlib-util-ios.a" - mv "${SIMULATORPATH}/lib/libpjmedia-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjmedia-ios.a" - mv "${SIMULATORPATH}/lib/libpjmedia-audiodev-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjmedia-audiodev-ios.a" - mv "${SIMULATORPATH}/lib/libpjmedia-codec-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjmedia-codec-ios.a" - mv "${SIMULATORPATH}/lib/libpjnath-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjnath-ios.a" - mv "${SIMULATORPATH}/lib/libpjsip-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjsip-ios.a" - mv "${SIMULATORPATH}/lib/libpjsip-simple-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjsip-simple-ios.a" - mv "${SIMULATORPATH}/lib/libpjsip-ua-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjsip-ua-ios.a" - mv "${SIMULATORPATH}/lib/libpjsua-arm-apple-darwin9.a" "${FINALPATH}/lib/libpjsua-ios.a" - mv "${SIMULATORPATH}/lib/libresample-arm-apple-darwin9.a" "${FINALPATH}/lib/libresample-ios.a" - mv "${SIMULATORPATH}/lib/libspeex-arm-apple-darwin9.a" "${FINALPATH}/lib/libspeex-ios.a" - mv "${SIMULATORPATH}/lib/libsrtp-arm-apple-darwin9.a" "${FINALPATH}/lib/libsrtp-ios.a" + mv "${SIMULATORPATH}/lib/libg7221codec-arm-apple-darwin10.a" "${FINALPATH}/lib/libg7221codec-ios.a" + mv "${SIMULATORPATH}/lib/libgsmcodec-arm-apple-darwin10.a" "${FINALPATH}/lib/libgsmcodec-ios.a" + mv "${SIMULATORPATH}/lib/libilbccodec-arm-apple-darwin10.a" "${FINALPATH}/lib/libilbccodec-ios.a" + mv "${SIMULATORPATH}/lib/libmilenage-arm-apple-darwin10.a" "${FINALPATH}/lib/libmilenage-ios.a" + mv "${SIMULATORPATH}/lib/libpj-arm-apple-darwin10.a" "${FINALPATH}/lib/libpj-ios.a" + mv "${SIMULATORPATH}/lib/libpjlib-util-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjlib-util-ios.a" + mv "${SIMULATORPATH}/lib/libpjmedia-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjmedia-ios.a" + mv "${SIMULATORPATH}/lib/libpjmedia-audiodev-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjmedia-audiodev-ios.a" + mv "${SIMULATORPATH}/lib/libpjmedia-codec-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjmedia-codec-ios.a" + mv "${SIMULATORPATH}/lib/libpjnath-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjnath-ios.a" + mv "${SIMULATORPATH}/lib/libpjsip-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjsip-ios.a" + mv "${SIMULATORPATH}/lib/libpjsip-simple-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjsip-simple-ios.a" + mv "${SIMULATORPATH}/lib/libpjsip-ua-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjsip-ua-ios.a" + mv "${SIMULATORPATH}/lib/libpjsua-arm-apple-darwin10.a" "${FINALPATH}/lib/libpjsua-ios.a" + mv "${SIMULATORPATH}/lib/libresample-arm-apple-darwin10.a" "${FINALPATH}/lib/libresample-ios.a" + mv "${SIMULATORPATH}/lib/libspeex-arm-apple-darwin10.a" "${FINALPATH}/lib/libspeex-ios.a" + mv "${SIMULATORPATH}/lib/libsrtp-arm-apple-darwin10.a" "${FINALPATH}/lib/libsrtp-ios.a" fi if [ "$1" = "" ]; then FINALPATH="${PWD}/opt" @@ -163,7 +165,7 @@ if [ "$1" = "" ]; then echo "Configuring PJProject" cd ${PJPROJECTNAME}-ppc - LDFLAGS="${PPCLDFLAGS}" CFLAGS="${PPCFLAGS}" CXXFLAGS="${PPCFLAGS}" ./configure --prefix="${PPCPATH}" --host="${PPCHOST}" --disable-shared --enable-static + LDFLAGS="${PPCLDFLAGS}" AR="${PPCAR}" RANLIB="${PPCRANLIB}" CC="${PPCCC}" CXX="${PPCCXX}" CFLAGS="${PPCFLAGS}" CXXFLAGS="${PPCFLAGS}" ./configure --prefix="${PPCPATH}" --host="${PPCHOST}" --disable-shared --enable-static cd ../${PJPROJECTNAME}-i386 LDFLAGS="${I386LDFLAGS}" CFLAGS="${I386FLAGS}" CXXFLAGS="${I386FLAGS}" ./configure --prefix="${I386PATH}" --host="${I386HOST}" --disable-shared --enable-static cd ../${PJPROJECTNAME}-x86_64 @@ -194,22 +196,22 @@ if [ "$1" = "" ]; then echo "Making PJProject Universal" mkdir -p "${FINALPATH}/lib/pkgconfig" cp -R "${PPCPATH}/include" "${FINALPATH}" - lipo -create "${PPCPATH}/lib/libg7221codec-powerpc-apple-darwin8.a" "${I386PATH}/lib/libg7221codec-i386-apple-darwin8.a" "${X86_64PATH}/lib/libg7221codec-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libg7221codec.a" - lipo -create "${PPCPATH}/lib/libgsmcodec-powerpc-apple-darwin8.a" "${I386PATH}/lib/libgsmcodec-i386-apple-darwin8.a" "${X86_64PATH}/lib/libgsmcodec-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libgsmcodec.a" - lipo -create "${PPCPATH}/lib/libilbccodec-powerpc-apple-darwin8.a" "${I386PATH}/lib/libilbccodec-i386-apple-darwin8.a" "${X86_64PATH}/lib/libilbccodec-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libilbccodec.a" - lipo -create "${PPCPATH}/lib/libmilenage-powerpc-apple-darwin8.a" "${I386PATH}/lib/libmilenage-i386-apple-darwin8.a" "${X86_64PATH}/lib/libmilenage-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libmilenage.a" - lipo -create "${PPCPATH}/lib/libpj-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpj-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpj-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpj.a" - lipo -create "${PPCPATH}/lib/libpjlib-util-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjlib-util-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjlib-util-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjlib-util.a" - lipo -create "${PPCPATH}/lib/libpjmedia-audiodev-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjmedia-audiodev-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjmedia-audiodev-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjmedia-audiodev.a" - lipo -create "${PPCPATH}/lib/libpjmedia-codec-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjmedia-codec-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjmedia-codec-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjmedia-codec.a" - lipo -create "${PPCPATH}/lib/libpjmedia-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjmedia-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjmedia-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjmedia.a" - lipo -create "${PPCPATH}/lib/libpjnath-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjnath-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjnath-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjnath.a" - lipo -create "${PPCPATH}/lib/libpjsip-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjsip-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjsip-simple-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsip-simple.a" - lipo -create "${PPCPATH}/lib/libpjsip-simple-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjsip-simple-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjsip-ua-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsip-ua.a" - lipo -create "${PPCPATH}/lib/libpjsip-ua-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjsip-ua-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjsip-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsip.a" - lipo -create "${PPCPATH}/lib/libpjsua-powerpc-apple-darwin8.a" "${I386PATH}/lib/libpjsua-i386-apple-darwin8.a" "${X86_64PATH}/lib/libpjsua-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libpjsua.a" - lipo -create "${PPCPATH}/lib/libportaudio-powerpc-apple-darwin8.a" "${I386PATH}/lib/libportaudio-i386-apple-darwin8.a" "${X86_64PATH}/lib/libportaudio-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libportaudio.a" - lipo -create "${PPCPATH}/lib/libresample-powerpc-apple-darwin8.a" "${I386PATH}/lib/libresample-i386-apple-darwin8.a" "${X86_64PATH}/lib/libresample-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libresample.a" - lipo -create "${PPCPATH}/lib/libspeex-powerpc-apple-darwin8.a" "${I386PATH}/lib/libspeex-i386-apple-darwin8.a" "${X86_64PATH}/lib/libspeex-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libspeex.a" - lipo -create "${PPCPATH}/lib/libsrtp-powerpc-apple-darwin8.a" "${I386PATH}/lib/libsrtp-i386-apple-darwin8.a" "${X86_64PATH}/lib/libsrtp-x86_64-apple-darwin9.a" -output "${FINALPATH}/lib/libsrtp.a" + lipo -create "${PPCPATH}/lib/libg7221codec-powerpc-apple-darwin10.a" "${I386PATH}/lib/libg7221codec-i386-apple-darwin10.a" "${X86_64PATH}/lib/libg7221codec-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libg7221codec.a" + lipo -create "${PPCPATH}/lib/libgsmcodec-powerpc-apple-darwin10.a" "${I386PATH}/lib/libgsmcodec-i386-apple-darwin10.a" "${X86_64PATH}/lib/libgsmcodec-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libgsmcodec.a" + lipo -create "${PPCPATH}/lib/libilbccodec-powerpc-apple-darwin10.a" "${I386PATH}/lib/libilbccodec-i386-apple-darwin10.a" "${X86_64PATH}/lib/libilbccodec-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libilbccodec.a" + lipo -create "${PPCPATH}/lib/libmilenage-powerpc-apple-darwin10.a" "${I386PATH}/lib/libmilenage-i386-apple-darwin10.a" "${X86_64PATH}/lib/libmilenage-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libmilenage.a" + lipo -create "${PPCPATH}/lib/libpj-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpj-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpj-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpj.a" + lipo -create "${PPCPATH}/lib/libpjlib-util-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjlib-util-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjlib-util-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjlib-util.a" + lipo -create "${PPCPATH}/lib/libpjmedia-audiodev-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjmedia-audiodev-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjmedia-audiodev-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjmedia-audiodev.a" + lipo -create "${PPCPATH}/lib/libpjmedia-codec-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjmedia-codec-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjmedia-codec-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjmedia-codec.a" + lipo -create "${PPCPATH}/lib/libpjmedia-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjmedia-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjmedia-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjmedia.a" + lipo -create "${PPCPATH}/lib/libpjnath-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjnath-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjnath-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjnath.a" + lipo -create "${PPCPATH}/lib/libpjsip-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjsip-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjsip-simple-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsip-simple.a" + lipo -create "${PPCPATH}/lib/libpjsip-simple-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjsip-simple-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjsip-ua-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsip-ua.a" + lipo -create "${PPCPATH}/lib/libpjsip-ua-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjsip-ua-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjsip-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsip.a" + lipo -create "${PPCPATH}/lib/libpjsua-powerpc-apple-darwin10.a" "${I386PATH}/lib/libpjsua-i386-apple-darwin10.a" "${X86_64PATH}/lib/libpjsua-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libpjsua.a" + lipo -create "${PPCPATH}/lib/libportaudio-powerpc-apple-darwin10.a" "${I386PATH}/lib/libportaudio-i386-apple-darwin10.a" "${X86_64PATH}/lib/libportaudio-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libportaudio.a" + lipo -create "${PPCPATH}/lib/libresample-powerpc-apple-darwin10.a" "${I386PATH}/lib/libresample-i386-apple-darwin10.a" "${X86_64PATH}/lib/libresample-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libresample.a" + lipo -create "${PPCPATH}/lib/libspeex-powerpc-apple-darwin10.a" "${I386PATH}/lib/libspeex-i386-apple-darwin10.a" "${X86_64PATH}/lib/libspeex-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libspeex.a" + lipo -create "${PPCPATH}/lib/libsrtp-powerpc-apple-darwin10.a" "${I386PATH}/lib/libsrtp-i386-apple-darwin10.a" "${X86_64PATH}/lib/libsrtp-x86_64-apple-darwin10.a" -output "${FINALPATH}/lib/libsrtp.a" fi \ No newline at end of file diff --git a/SIP/notes.txt b/SIP/notes.txt index 648b71c..ff422f1 100755 --- a/SIP/notes.txt +++ b/SIP/notes.txt @@ -2,8 +2,10 @@ Getting the source code to PJProject. 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 3773 http://svn.pjsip.org/repos/pjproject/trunk pjproject +I am currently using version 2.1 stable. + +//To get the revision that I am using in VoiceMac and VoiceMob, run the command below. +//svn checkout -r 4293 http://svn.pjsip.org/repos/pjproject/trunk pjproject Building. To build for VoiceMac, run the command below. diff --git a/SIP/pjproject.tar.gz b/SIP/pjproject.tar.gz index 0800c9c..ef95400 100644 Binary files a/SIP/pjproject.tar.gz and b/SIP/pjproject.tar.gz differ diff --git a/Theme Tester.xcodeproj/project.pbxproj b/Theme Tester.xcodeproj/project.pbxproj index f81f296..5b43e09 100644 --- a/Theme Tester.xcodeproj/project.pbxproj +++ b/Theme Tester.xcodeproj/project.pbxproj @@ -345,7 +345,11 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = ( + ppc, + i386, + x86_64, + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -356,13 +360,18 @@ ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; SDKROOT = macosx10.5; + VALID_ARCHS = "ppc i386 x86_64"; }; name = Debug; }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = ( + ppc, + i386, + x86_64, + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -370,7 +379,8 @@ MACOSX_DEPLOYMENT_TARGET = 10.4; "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.5; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx10.5; + VALID_ARCHS = "ppc i386 x86_64"; }; name = Release; }; diff --git a/Voice.xcworkspace/xcshareddata/Voice.xccheckout b/Voice.xcworkspace/xcshareddata/Voice.xccheckout new file mode 100644 index 0000000..890a7ae --- /dev/null +++ b/Voice.xcworkspace/xcshareddata/Voice.xccheckout @@ -0,0 +1,39 @@ + + + + + IDESourceControlProjectIdentifier + 75771D5A-78D5-46C4-8C05-13DFF6965F5F + IDESourceControlProjectName + Voice + IDESourceControlProjectOriginsDictionary + + CE70E678-AB55-4060-AF6A-1AD50AE8569A + ssh://mrgeckosmedia.com/public/VoiceMac + + IDESourceControlProjectPath + Voice.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + CE70E678-AB55-4060-AF6A-1AD50AE8569A + .. + + IDESourceControlProjectURL + ssh://mrgeckosmedia.com/public/VoiceMac + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + CE70E678-AB55-4060-AF6A-1AD50AE8569A + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + CE70E678-AB55-4060-AF6A-1AD50AE8569A + IDESourceControlWCCName + VoiceMac + + + + diff --git a/VoiceBase.xcodeproj/project.pbxproj b/VoiceBase.xcodeproj/project.pbxproj index 06eb5b0..a21143c 100644 --- a/VoiceBase.xcodeproj/project.pbxproj +++ b/VoiceBase.xcodeproj/project.pbxproj @@ -697,6 +697,8 @@ OTHER_LDFLAGS = ""; PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = Debug; }; @@ -718,6 +720,8 @@ OTHER_LDFLAGS = ""; PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = Release; }; @@ -746,6 +750,8 @@ OTHER_LDFLAGS = ""; PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = "Debug SIP"; }; @@ -826,6 +832,8 @@ OTHER_LDFLAGS = ""; PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = "Release SIP"; }; diff --git a/VoiceMac.xcodeproj/project.pbxproj b/VoiceMac.xcodeproj/project.pbxproj index 28642a5..1e63a62 100644 --- a/VoiceMac.xcodeproj/project.pbxproj +++ b/VoiceMac.xcodeproj/project.pbxproj @@ -1063,6 +1063,8 @@ ); PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = "Debug SIP"; }; @@ -1124,6 +1126,8 @@ ); PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = "Release SIP"; }; @@ -1231,6 +1235,8 @@ OTHER_LDFLAGS = ""; PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = Debug; }; @@ -1251,6 +1257,8 @@ OTHER_LDFLAGS = ""; PREBINDING = NO; SDKROOT = macosx10.5; + "SDKROOT[arch=x86_64]" = macosx10.7; + VALID_ARCHS = "ppc i386 x86_64"; }; name = Release; }; diff --git a/VoiceMob.xcodeproj/project.pbxproj b/VoiceMob.xcodeproj/project.pbxproj index 9ba3d9b..0e974b0 100755 --- a/VoiceMob.xcodeproj/project.pbxproj +++ b/VoiceMob.xcodeproj/project.pbxproj @@ -389,7 +389,11 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "VoiceMob" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + en, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectReferences = ( diff --git a/VoiceMob.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/VoiceMob.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..c529a99 --- /dev/null +++ b/VoiceMob.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + +