diff --git a/AppController.h b/AppController.h index 6b43128b..ca58fa02 100644 --- a/AppController.h +++ b/AppController.h @@ -14,11 +14,6 @@ #import #import "NilToStringTransformer.h" -bool runDownloads=NO; -bool runUpdate=NO; -NSDictionary *tvFormats; -NSDictionary *radioFormats; - @interface AppController : NSObject { //General NSString *getiPlayerPath; @@ -28,8 +23,8 @@ NSDictionary *radioFormats; NSString *currentTypeArgument; IBOutlet NSWindow *mainWindow; IBOutlet NSApplication *application; - IBOutlet NSWindow *historyWindow; - IOPMAssertionID powerAssertionID; + IBOutlet NSWindow *historyWindow; + IOPMAssertionID powerAssertionID; //Log Components IBOutlet NSTextView *log; @@ -41,18 +36,19 @@ NSDictionary *radioFormats; NSTask *getiPlayerUpdateTask; NSPipe *getiPlayerUpdatePipe; NSArray *getiPlayerUpdateArgs; - NSMutableArray *typesToCache; + NSMutableArray *typesToCache; BOOL didUpdate; BOOL runSinceChange; - BOOL quickUpdateFailed; - NSUInteger nextToCache; - NSDictionary *updateURLDic; - NSDate *lastUpdate; + BOOL quickUpdateFailed; + NSUInteger nextToCache; + NSDictionary *updateURLDic; + NSDate *lastUpdate; //Main Window: Search IBOutlet NSTextField *searchField; IBOutlet NSProgressIndicator *searchIndicator; IBOutlet NSArrayController *resultsController; + IBOutlet NSTableView *searchResultsTable; NSMutableArray *searchResultsArray; NSTask *searchTask; NSPipe *searchPipe; @@ -63,7 +59,7 @@ NSDictionary *radioFormats; IBOutlet NSProgressIndicator *pvrSearchIndicator; IBOutlet NSArrayController *pvrResultsController; IBOutlet NSArrayController *pvrQueueController; - IBOutlet NSPanel *pvrPanel; + IBOutlet NSPanel *pvrPanel; NSMutableArray *pvrSearchResultsArray; NSTask *pvrSearchTask; NSPipe *pvrSearchPipe; @@ -91,14 +87,14 @@ NSDictionary *radioFormats; //Preferences NSMutableArray *tvFormatList; NSMutableArray *radioFormatList; - NSMutableArray *itvFormatList; + NSMutableArray *itvFormatList; IBOutlet NSArrayController *tvFormatController; IBOutlet NSArrayController *radioFormatController; - IBOutlet NSArrayController *itvFormatController; - IBOutlet NSButton *itvTVCheckbox; - IBOutlet NSPanel *prefsPanel; - IBOutlet NSButton *ch4TVCheckbox; - + IBOutlet NSArrayController *itvFormatController; + IBOutlet NSButton *itvTVCheckbox; + IBOutlet NSPanel *prefsPanel; + IBOutlet NSButton *ch4TVCheckbox; + //Scheduling a Start IBOutlet NSPanel *scheduleWindow; IBOutlet NSDatePicker *datePicker; @@ -116,29 +112,51 @@ NSDictionary *radioFormats; NSTask *mplayerStreamer; NSPipe *liveTVPipe; NSPipe *liveTVError; - - //Download Solutions - IBOutlet NSWindow *solutionsWindow; - IBOutlet NSArrayController *solutionsArrayController; - IBOutlet NSTableView *solutionsTableView; - NSDictionary *solutionsDictionary; - - //Proxy - HTTPProxy *proxy; - NSMutableDictionary *proxyDict; - enum { - kProxyLoadCancelled = 1, - kProxyLoadFailed = 2, - kProxyTestFailed = 3 - }; - - //PVR list editing - NilToStringTransformer *nilToEmptyStringTransformer; - NilToStringTransformer *nilToAsteriskTransformer; - - //Verbose Logging - BOOL verbose; + + //Download Solutions + IBOutlet NSWindow *solutionsWindow; + IBOutlet NSArrayController *solutionsArrayController; + IBOutlet NSTableView *solutionsTableView; + NSDictionary *solutionsDictionary; + + //Proxy + HTTPProxy *proxy; + NSMutableDictionary *proxyDict; + enum { + kProxyLoadCancelled = 1, + kProxyLoadFailed = 2, + kProxyTestFailed = 3 + }; + + + //PVR list editing + NilToStringTransformer *nilToEmptyStringTransformer; + NilToStringTransformer *nilToAsteriskTransformer; + + //Verbose Logging + BOOL verbose; + + //Extended Show Information + IBOutlet NSProgressIndicator *retrievingInfoIndicator; + IBOutlet NSTextField *loadingLabel; + IBOutlet NSView *loadingView; + IBOutlet NSView *infoView; + IBOutlet NSPopover *popover; + IBOutlet NSImageView *imageView; + IBOutlet NSTextField *seriesName; + IBOutlet NSTextField *episodeName; + IBOutlet NSTextField *numbersField; + IBOutlet NSTextField *durationField; + IBOutlet NSTextField *categoriesField; + IBOutlet NSTextField *firstBroadcastField; + IBOutlet NSTextField *lastBroadcastField; + IBOutlet NSTextView *descriptionView; + IBOutlet NSDictionaryController *modeSizeController; } + +//Proxy +- (void)loadProxyInBackgroundForSelector:(SEL)selector withObject:(id)object; + //Update - (void)getiPlayerUpdateFinished; - (IBAction)updateCache:(id)sender; @@ -165,6 +183,7 @@ NSDictionary *radioFormats; - (IBAction)restoreDefaults:(id)sender; - (IBAction)showFeedback:(id)sender; - (IBAction)closeWindow:(id)sender; ++ (AppController*)sharedController; //Queue - (IBAction)addToQueue:(id)sender; @@ -200,11 +219,17 @@ NSDictionary *radioFormats; - (IBAction)startLiveTV:(id)sender; - (IBAction)stopLiveTV:(id)sender; +//Extended Show Information +- (IBAction)showExtendedInformationForSelectedProgramme:(id)sender; +- (void)loadProxyInBackgroundForSelector:(SEL)selector withObject:(id)object onTarget:(id)target; + + //Download Solutions //- (IBAction)saveSolutionsAsText:(id)sender; //Key-Value Coding @property (readwrite) NSMutableAttributedString *log_value; @property (readonly) NSString *getiPlayerPath; +@property (readonly) HTTPProxy *proxy; @end diff --git a/AppController.m b/AppController.m index 83022b10..2dc1eee8 100644 --- a/AppController.m +++ b/AppController.m @@ -19,15 +19,23 @@ #import "Chrome.h" #import "ASIHTTPRequest.h" +static AppController *sharedController; +bool runDownloads=NO; +bool runUpdate=NO; +NSDictionary *tvFormats; +NSDictionary *radioFormats; + @implementation AppController #pragma mark Overriden Methods - (id)description { return @"AppController"; } -- (id)init { +- (id)init { //Initialization if (!(self = [super init])) return nil; + sharedController = self; + NSNotificationCenter *nc; nc = [NSNotificationCenter defaultCenter]; @@ -38,21 +46,21 @@ - (id)init { queueArray = [NSMutableArray array]; //Initialize Log - NSString *version = [NSString stringWithFormat:@"%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]]; - NSLog(@"Get iPlayer Automator %@ Initialized.", version); + NSString *version = [NSString stringWithFormat:@"%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]]; + NSLog(@"Get iPlayer Automator %@ Initialized.", version); log_value = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"Get iPlayer Automator %@ Initialized.", version]]; [self addToLog:@"" :nil]; [nc addObserver:self selector:@selector(addToLogNotification:) name:@"AddToLog" object:nil]; [nc addObserver:self selector:@selector(postLog:) name:@"NeedLog" object:nil]; - - //Look for Start notifications for ASS - [nc addObserver:self selector:@selector(applescriptStartDownloads) name:@"StartDownloads" object:nil]; + + //Look for Start notifications for ASS + [nc addObserver:self selector:@selector(applescriptStartDownloads) name:@"StartDownloads" object:nil]; //Register Default Preferences NSMutableDictionary *defaultValues = [[NSMutableDictionary alloc] init]; - NSString *defaultDownloadDirectory = @"~/Movies/TV Shows"; + NSString *defaultDownloadDirectory = @"~/Movies/TV Shows"; defaultValues[@"DownloadPath"] = [defaultDownloadDirectory stringByExpandingTildeInPath]; defaultValues[@"Proxy"] = @"Provided"; defaultValues[@"CustomProxy"] = @""; @@ -74,14 +82,14 @@ - (id)init { defaultValues[@"XBMC_naming"] = @NO; defaultValues[@"KeepSeriesFor"] = @"30"; defaultValues[@"RemoveOldSeries"] = @NO; - defaultValues[@"AudioDescribed"] = @NO; - defaultValues[@"QuickCache"] = @YES; - defaultValues[@"TagShows"] = @YES; - // TODO: remove 4oD - // set 4oD off by default - defaultValues[@"Cache4oD_TV"] = @NO; - defaultValues[@"TestProxy"] = @YES; - defaultValues[@"ShowDownloadedInSearch"] = @YES; + defaultValues[@"AudioDescribed"] = @NO; + defaultValues[@"QuickCache"] = @YES; + defaultValues[@"TagShows"] = @YES; + // TODO: remove 4oD + // set 4oD off by default + defaultValues[@"Cache4oD_TV"] = @NO; + defaultValues[@"TestProxy"] = @YES; + defaultValues[@"ShowDownloadedInSearch"] = @YES; [[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues]; defaultValues = nil; @@ -116,53 +124,58 @@ - (id)init { getiPlayerPath = [[NSString alloc] initWithString:[[NSBundle mainBundle] bundlePath]]; getiPlayerPath = [getiPlayerPath stringByAppendingString:@"/Contents/Resources/get_iplayer.pl"]; runScheduled=NO; - quickUpdateFailed=NO; - proxyDict = [[NSMutableDictionary alloc] init]; - nilToEmptyStringTransformer = [[NilToStringTransformer alloc] init]; - nilToAsteriskTransformer = [[NilToStringTransformer alloc] initWithString:@"*"]; - [NSValueTransformer setValueTransformer:nilToEmptyStringTransformer forName:@"NilToEmptyStringTransformer"]; - [NSValueTransformer setValueTransformer:nilToAsteriskTransformer forName:@"NilToAsteriskTransformer"]; - verbose = [[NSUserDefaults standardUserDefaults] boolForKey:@"Verbose"]; - return self; + quickUpdateFailed=NO; + proxyDict = [[NSMutableDictionary alloc] init]; + nilToEmptyStringTransformer = [[NilToStringTransformer alloc] init]; + nilToAsteriskTransformer = [[NilToStringTransformer alloc] initWithString:@"*"]; + [NSValueTransformer setValueTransformer:nilToEmptyStringTransformer forName:@"NilToEmptyStringTransformer"]; + [NSValueTransformer setValueTransformer:nilToAsteriskTransformer forName:@"NilToAsteriskTransformer"]; + verbose = [[NSUserDefaults standardUserDefaults] boolForKey:@"Verbose"]; + return self; } #pragma mark Delegate Methods - (void)awakeFromNib { #ifdef __x86_64__ - [itvTVCheckbox setEnabled:YES]; + [itvTVCheckbox setEnabled:YES]; #else - [itvTVCheckbox setEnabled:NO]; - [itvTVCheckbox setState:NSOffState]; - [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:NO] forKey:@"CacheITV_TV"]; + [itvTVCheckbox setEnabled:NO]; + [itvTVCheckbox setState:NSOffState]; + [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:NO] forKey:@"CacheITV_TV"]; #endif - + + //Initialize Search Results Click Actions + [searchResultsTable setTarget:self]; + [searchResultsTable setDoubleAction:@selector(addToQueue:)]; + + //Read Queue & Series-Link from File NSFileManager *fileManager = [NSFileManager defaultManager]; - + NSString *folder = @"~/Library/Application Support/Get iPlayer Automator/"; folder = [folder stringByExpandingTildeInPath]; if ([fileManager fileExistsAtPath: folder] == NO) { [fileManager createDirectoryAtPath:folder withIntermediateDirectories:NO attributes:nil error:nil]; } - - // TODO: remove 4oD - // disable 4oD and delete CH4 cache - [[NSUserDefaults standardUserDefaults] setValue:@NO forKey:@"Cache4oD_TV"]; - [ch4TVCheckbox setState:NSOffState]; - [ch4TVCheckbox setEnabled:NO]; - [fileManager removeItemAtPath:[folder stringByAppendingPathComponent:@"ch4.cache"] error:nil]; - + + // TODO: remove 4oD + // disable 4oD and delete CH4 cache + [[NSUserDefaults standardUserDefaults] setValue:@NO forKey:@"Cache4oD_TV"]; + [ch4TVCheckbox setState:NSOffState]; + [ch4TVCheckbox setEnabled:NO]; + [fileManager removeItemAtPath:[folder stringByAppendingPathComponent:@"ch4.cache"] error:nil]; + NSString *filename = @"Queue.automatorqueue"; NSString *filePath = [folder stringByAppendingPathComponent:filename]; NSDictionary * rootObject; - @try + @try { rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; NSArray *tempQueue = [rootObject valueForKey:@"queue"]; NSArray *tempSeries = [rootObject valueForKey:@"serieslink"]; - lastUpdate = [rootObject valueForKey:@"lastUpdate"]; + lastUpdate = [rootObject valueForKey:@"lastUpdate"]; [queueController addObjects:tempQueue]; [pvrQueueController addObjects:tempSeries]; } @@ -178,7 +191,7 @@ - (void)awakeFromNib filename = @"Formats.automatorqueue"; filePath = [folder stringByAppendingPathComponent:filename]; - @try + @try { rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; [radioFormatController addObjects:[rootObject valueForKey:@"radioFormats"]]; @@ -190,37 +203,37 @@ - (void)awakeFromNib NSLog(@"Unable to load saved application data. Deleted the data file."); rootObject=nil; } - if (!tvFormats || !radioFormats) { - [BBCDownload initFormats]; - } - // clear obsolete formats - NSMutableArray *tempTVFormats = [[NSMutableArray alloc] initWithArray:[tvFormatController arrangedObjects]]; - for (TVFormat *tvFormat in tempTVFormats) { - if (!tvFormats[[tvFormat format]]) { - [tvFormatController removeObject:tvFormat]; - } - } - NSMutableArray *tempRadioFormats = [[NSMutableArray alloc] initWithArray:[radioFormatController arrangedObjects]]; - for (RadioFormat *radioFormat in tempRadioFormats) { - if (!radioFormats[[radioFormat format]]) { - [radioFormatController removeObject:radioFormat]; - } - } - - // TODO: Remove 4oD - BOOL hasCached4oD = [[rootObject valueForKey:@"hasUpdatedCacheFor4oD"] boolValue]; - - filename = @"ITVFormats.automator"; - filePath = [folder stringByAppendingPathComponent:filename]; - @try { - rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - [itvFormatController addObjects:[rootObject valueForKey:@"itvFormats"]]; - } - @catch (NSException *exception) { - [fileManager removeItemAtPath:filePath error:nil]; - rootObject=nil; - } - + if (!tvFormats || !radioFormats) { + [BBCDownload initFormats]; + } + // clear obsolete formats + NSMutableArray *tempTVFormats = [[NSMutableArray alloc] initWithArray:[tvFormatController arrangedObjects]]; + for (TVFormat *tvFormat in tempTVFormats) { + if (!tvFormats[[tvFormat format]]) { + [tvFormatController removeObject:tvFormat]; + } + } + NSMutableArray *tempRadioFormats = [[NSMutableArray alloc] initWithArray:[radioFormatController arrangedObjects]]; + for (RadioFormat *radioFormat in tempRadioFormats) { + if (!radioFormats[[radioFormat format]]) { + [radioFormatController removeObject:radioFormat]; + } + } + + // TODO: Remove 4oD + BOOL hasCached4oD = [[rootObject valueForKey:@"hasUpdatedCacheFor4oD"] boolValue]; + + filename = @"ITVFormats.automator"; + filePath = [folder stringByAppendingPathComponent:filename]; + @try { + rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + [itvFormatController addObjects:[rootObject valueForKey:@"itvFormats"]]; + } + @catch (NSException *exception) { + [fileManager removeItemAtPath:filePath error:nil]; + rootObject=nil; + } + //Adds Defaults to Type Preferences if ([[tvFormatController arrangedObjects] count] == 0) { @@ -240,28 +253,28 @@ - (void)awakeFromNib [format3 setFormat:@"Flash - MP3"]; [radioFormatController addObjects:@[format1,format2,format3]]; } - if ([[itvFormatController arrangedObjects] count] == 0) - { - TVFormat *format1 = [[TVFormat alloc] init]; - [format1 setFormat:@"Flash - High"]; - TVFormat *format2 = [[TVFormat alloc] init]; - [format2 setFormat:@"Flash - Standard"]; - TVFormat *format3 = [[TVFormat alloc] init]; - [format3 setFormat:@"Flash - Low"]; - TVFormat *format4 = [[TVFormat alloc] init]; - [format4 setFormat:@"Flash - Very Low"]; - [itvFormatController addObjects:@[format1,format2,format3,format4]]; - } - + if ([[itvFormatController arrangedObjects] count] == 0) + { + TVFormat *format1 = [[TVFormat alloc] init]; + [format1 setFormat:@"Flash - High"]; + TVFormat *format2 = [[TVFormat alloc] init]; + [format2 setFormat:@"Flash - Standard"]; + TVFormat *format3 = [[TVFormat alloc] init]; + [format3 setFormat:@"Flash - Low"]; + TVFormat *format4 = [[TVFormat alloc] init]; + [format4 setFormat:@"Flash - Very Low"]; + [itvFormatController addObjects:@[format1,format2,format3,format4]]; + } + //Growl Initialization - @try { - [GrowlApplicationBridge setGrowlDelegate:@""]; - } - @catch (NSException *e) { - NSLog(@"ERROR: Growl initialisation failed: %@: %@", [e name], [e description]); - [self addToLog:[NSString stringWithFormat:@"ERROR: Growl initialisation failed: %@: %@", [e name], [e description]]]; - } - + @try { + [GrowlApplicationBridge setGrowlDelegate:@""]; + } + @catch (NSException *e) { + NSLog(@"ERROR: Growl initialisation failed: %@: %@", [e name], [e description]); + [self addToLog:[NSString stringWithFormat:@"ERROR: Growl initialisation failed: %@: %@", [e name], [e description]]]; + } + //Populate Live TV Channel List LiveTVChannel *bbcOne = [[LiveTVChannel alloc] initWithChannelName:@"BBC One"]; LiveTVChannel *bbcTwo = [[LiveTVChannel alloc] initWithChannelName:@"BBC Two"]; @@ -273,13 +286,13 @@ - (void)awakeFromNib NSString *infoPath = @"~/.swfinfo"; infoPath = [infoPath stringByExpandingTildeInPath]; if ([fileManager fileExistsAtPath:infoPath]) [fileManager removeItemAtPath:infoPath error:nil]; - - if (hasCached4oD) - [self updateCache:nil]; - else - [self updateCache:@""]; - // ensure get_iplayer encodes output as UTF-8 - setenv("PERL_UNICODE", "S", 1); + + if (hasCached4oD) + [self updateCache:nil]; + else + [self updateCache:@""]; + // ensure get_iplayer encodes output as UTF-8 + setenv("PERL_UNICODE", "S", 1); } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)application { @@ -287,29 +300,29 @@ - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)applica } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - if (runDownloads) - { - NSAlert *downloadAlert = [NSAlert alertWithMessageText:@"Are you sure you wish to quit?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@"You are currently downloading shows. If you quit, they will be cancelled."]; - NSInteger response = [downloadAlert runModal]; - if (response == NSAlertDefaultReturn) return NSTerminateCancel; - } - else if (runUpdate) - { - NSAlert *updateAlert = [NSAlert alertWithMessageText:@"Are you sure?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@"Get iPlayer Automator is currently updating the cache." - @"If you proceed with quiting, some series-link information will be lost." - @"It is not reccommended to quit during an update. Are you sure you wish to quit?"]; - NSInteger response = [updateAlert runModal]; - if (response == NSAlertDefaultReturn) return NSTerminateCancel; - } - + if (runDownloads) + { + NSAlert *downloadAlert = [NSAlert alertWithMessageText:@"Are you sure you wish to quit?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@"You are currently downloading shows. If you quit, they will be cancelled."]; + NSInteger response = [downloadAlert runModal]; + if (response == NSAlertDefaultReturn) return NSTerminateCancel; + } + else if (runUpdate) + { + NSAlert *updateAlert = [NSAlert alertWithMessageText:@"Are you sure?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@"Get iPlayer Automator is currently updating the cache." + @"If you proceed with quiting, some series-link information will be lost." + @"It is not reccommended to quit during an update. Are you sure you wish to quit?"]; + NSInteger response = [updateAlert runModal]; + if (response == NSAlertDefaultReturn) return NSTerminateCancel; + } + return NSTerminateNow; } - (BOOL)windowShouldClose:(id)sender @@ -318,24 +331,24 @@ - (BOOL)windowShouldClose:(id)sender { if (runUpdate) { - NSAlert *updateAlert = [NSAlert alertWithMessageText:@"Are you sure?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@"Get iPlayer Automator is currently updating the cache." - @"If you proceed with quiting, some series-link information will be lost." - @"It is not reccommended to quit during an update. Are you sure you wish to quit?"]; + NSAlert *updateAlert = [NSAlert alertWithMessageText:@"Are you sure?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@"Get iPlayer Automator is currently updating the cache." + @"If you proceed with quiting, some series-link information will be lost." + @"It is not reccommended to quit during an update. Are you sure you wish to quit?"]; NSInteger response = [updateAlert runModal]; if (response == NSAlertDefaultReturn) return NO; else if (response == NSAlertAlternateReturn) return YES; } else if (runDownloads) { - NSAlert *downloadAlert = [NSAlert alertWithMessageText:@"Are you sure you wish to quit?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@"You are currently downloading shows. If you quit, they will be cancelled."]; + NSAlert *downloadAlert = [NSAlert alertWithMessageText:@"Are you sure you wish to quit?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@"You are currently downloading shows. If you quit, they will be cancelled."]; NSInteger response = [downloadAlert runModal]; if (response == NSAlertDefaultReturn) return NO; else return YES; @@ -354,213 +367,214 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification //End Downloads if Running if (runDownloads) [currentDownload cancelDownload:nil]; - - [self saveAppData]; + + [self saveAppData]; } - (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update { - @try - { - - [GrowlApplicationBridge notifyWithTitle:@"Update Available!" - description:[NSString stringWithFormat:@"Get iPlayer Automator %@ is available.",[update displayVersionString]] - notificationName:@"New Version Available" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; - } - @catch (NSException *e) { - NSLog(@"ERROR: Growl notification failed (updater): %@: %@", [e name], [e description]); - [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (updater): %@: %@", [e name], [e description]]]; - } + @try + { + + [GrowlApplicationBridge notifyWithTitle:@"Update Available!" + description:[NSString stringWithFormat:@"Get iPlayer Automator %@ is available.",[update displayVersionString]] + notificationName:@"New Version Available" + iconData:nil + priority:0 + isSticky:NO + clickContext:nil]; + } + @catch (NSException *e) { + NSLog(@"ERROR: Growl notification failed (updater): %@: %@", [e name], [e description]); + [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (updater): %@: %@", [e name], [e description]]]; + } } #pragma mark Cache Update - (IBAction)updateCache:(id)sender { - @try - { - [searchField setEnabled:NO]; - [stopButton setEnabled:NO]; - [startButton setEnabled:NO]; - [pvrSearchField setEnabled:NO]; - } - @catch (NSException *e) { - NSLog(@"NO UI: updateCache:"); - } - if ((![[[NSUserDefaults standardUserDefaults] objectForKey:@"QuickCache"] boolValue] || quickUpdateFailed) && [[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) - { - [self loadProxyInBackgroundForSelector:@selector(updateCache:proxyError:) withObject:sender]; - } - else - { - [self updateCache:sender proxyError:nil]; - } + @try + { + [searchField setEnabled:NO]; + [stopButton setEnabled:NO]; + [startButton setEnabled:NO]; + [pvrSearchField setEnabled:NO]; + } + @catch (NSException *e) { + NSLog(@"NO UI: updateCache:"); + } + if ((![[[NSUserDefaults standardUserDefaults] objectForKey:@"QuickCache"] boolValue] || quickUpdateFailed) && [[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) + { + [self loadProxyInBackgroundForSelector:@selector(updateCache:proxyError:) withObject:sender]; + } + else + { + [self updateCache:sender proxyError:nil]; + } } - (void)updateCache:(id)sender proxyError:(NSError *)proxyError { - // reset after proxy load - @try - { - [searchField setEnabled:YES]; - [stopButton setEnabled:YES]; - [startButton setEnabled:YES]; - [pvrSearchField setEnabled:YES]; - } - @catch (NSException *e) { - NSLog(@"NO UI: updateCache:proxyError:"); - } - if ([proxyError code] == kProxyLoadCancelled) - return; + // reset after proxy load + @try + { + [searchField setEnabled:YES]; + [stopButton setEnabled:YES]; + [startButton setEnabled:YES]; + [pvrSearchField setEnabled:YES]; + } + @catch (NSException *e) { + NSLog(@"NO UI: updateCache:proxyError:"); + } + if ([proxyError code] == kProxyLoadCancelled) + return; runSinceChange=YES; runUpdate=YES; - didUpdate=NO; + didUpdate=NO; [mainWindow setDocumentEdited:YES]; NSArray *tempQueue = [queueController arrangedObjects]; for (Programme *show in tempQueue) { - if (![[show successful] isEqualToNumber:@NO]) + if (show.successful.boolValue) { [queueController removeObject:show]; } } - - //UI might not be loaded yet - @try - { - //Update Should Be Running: - [currentIndicator setIndeterminate:YES]; - [currentIndicator startAnimation:nil]; - [currentProgress setStringValue:@"Updating Program Indexes..."]; - //Shouldn't search until update is done. - [searchField setEnabled:NO]; - [stopButton setEnabled:NO]; - [startButton setEnabled:NO]; - [pvrSearchField setEnabled:NO]; - } - @catch (NSException *e) { - NSLog(@"NO UI"); - } - - if (![[[NSUserDefaults standardUserDefaults] objectForKey:@"QuickCache"] boolValue] || quickUpdateFailed) - { - quickUpdateFailed=NO; - - NSString *cacheExpiryArg; - if ([[sender class] isEqualTo:[@"" class]]) - { - cacheExpiryArg = @"-e1"; - } - else - { - cacheExpiryArg = [[NSString alloc] initWithFormat:@"-e%d", ([[[NSUserDefaults standardUserDefaults] objectForKey:@"CacheExpiryTime"] intValue]*3600)]; - } + + //UI might not be loaded yet + @try + { + //Update Should Be Running: + [currentIndicator setIndeterminate:YES]; + [currentIndicator startAnimation:nil]; + [currentProgress setStringValue:@"Updating Program Indexes..."]; + //Shouldn't search until update is done. + [searchField setEnabled:NO]; + [stopButton setEnabled:NO]; + [startButton setEnabled:NO]; + [pvrSearchField setEnabled:NO]; + } + @catch (NSException *e) { + NSLog(@"NO UI"); + } + + if (![[[NSUserDefaults standardUserDefaults] objectForKey:@"QuickCache"] boolValue] || quickUpdateFailed) + { + quickUpdateFailed=NO; + + NSString *cacheExpiryArg; + if ([[sender class] isEqualTo:[@"" class]]) + { + cacheExpiryArg = @"-e1"; + } + else + { + cacheExpiryArg = [[NSString alloc] initWithFormat:@"-e%d", ([[[NSUserDefaults standardUserDefaults] objectForKey:@"CacheExpiryTime"] intValue]*3600)]; + } + + NSString *typeArgument = [self typeArgument:nil]; + + getiPlayerUpdateArgs = @[getiPlayerPath,cacheExpiryArg,typeArgument,@"--nopurge",profileDirArg]; - NSString *typeArgument = [self typeArgument:nil]; - - NSString *proxyArg = NULL; - if (proxy && [[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) - { - proxyArg = [[NSString alloc] initWithFormat:@"-p%@", [proxy url]]; - } - - [self addToLog:@"Updating Program Index Feeds...\r" :self]; - - getiPlayerUpdateArgs = @[getiPlayerPath,cacheExpiryArg,typeArgument,@"--nopurge",profileDirArg,proxyArg]; - getiPlayerUpdateTask = [[NSTask alloc] init]; - [getiPlayerUpdateTask setLaunchPath:@"/usr/bin/perl"]; - [getiPlayerUpdateTask setArguments:getiPlayerUpdateArgs]; - getiPlayerUpdatePipe = [[NSPipe alloc] init]; - [getiPlayerUpdateTask setStandardOutput:getiPlayerUpdatePipe]; - [getiPlayerUpdateTask setStandardError:getiPlayerUpdatePipe]; - - NSFileHandle *fh = [getiPlayerUpdatePipe fileHandleForReading]; - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - - [nc addObserver:self - selector:@selector(dataReady:) - name:NSFileHandleReadCompletionNotification - object:fh]; - [getiPlayerUpdateTask launch]; - - [fh readInBackgroundAndNotify]; - } - else - { - [self addToLog:@"Updating Program Index Feeds from Server..." :nil]; - - NSLog(@"DEBUG: Last cache update: %@",lastUpdate); - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - if (!lastUpdate || ([[NSDate date] timeIntervalSinceDate:lastUpdate] > ([[defaults objectForKey:@"CacheExpiryTime"] intValue]*3600)) || [[sender class] isEqualTo:[@"" class]]) - { - typesToCache = [[NSMutableArray alloc] initWithCapacity:5]; - if ([[defaults objectForKey:@"CacheBBC_TV"] boolValue]) [typesToCache addObject:@"tv"]; - if ([[defaults objectForKey:@"CacheITV_TV"] boolValue]) [typesToCache addObject:@"itv"]; - if ([[defaults objectForKey:@"CacheBBC_Radio"] boolValue]) [typesToCache addObject:@"radio"]; - if ([[defaults objectForKey:@"CacheBBC_Podcasts"] boolValue]) [typesToCache addObject:@"Podcast"]; - // TODO: Remove 4oD - if ([[defaults objectForKey:@"Cache4oD_TV"] boolValue]) [typesToCache addObject:@"ch4"]; - - NSArray *urlKeys = @[@"tv",@"itv",@"radio",@"podcast",@"ch4"]; - NSArray *urlObjects = @[@"http://tom-tech.com/get_iplayer/cache/tv.cache", - @"http://tom-tech.com/get_iplayer/cache/itv.cache", - @"http://tom-tech.com/get_iplayer/cache/radio.cache", - @"http://tom-tech.com/get_iplayer/cache/podcast.cache", - @"http://tom-tech.com/get_iplayer/cache/ch4.cache"]; - updateURLDic = [[NSDictionary alloc] initWithObjects:urlObjects forKeys:urlKeys]; - - nextToCache=0; - if ([typesToCache count] > 0) - [self updateCacheForType:typesToCache[0]]; - } - else [self getiPlayerUpdateFinished]; - - } + if (proxy && [[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) + { + getiPlayerUpdateArgs = [getiPlayerUpdateArgs arrayByAddingObject:[[NSString alloc] initWithFormat:@"-p%@", [proxy url]]]; + } + + [self addToLog:@"Updating Program Index Feeds...\r" :self]; + + + getiPlayerUpdateTask = [[NSTask alloc] init]; + [getiPlayerUpdateTask setLaunchPath:@"/usr/bin/perl"]; + [getiPlayerUpdateTask setArguments:getiPlayerUpdateArgs]; + getiPlayerUpdatePipe = [[NSPipe alloc] init]; + [getiPlayerUpdateTask setStandardOutput:getiPlayerUpdatePipe]; + [getiPlayerUpdateTask setStandardError:getiPlayerUpdatePipe]; + + NSFileHandle *fh = [getiPlayerUpdatePipe fileHandleForReading]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + [nc addObserver:self + selector:@selector(dataReady:) + name:NSFileHandleReadCompletionNotification + object:fh]; + [getiPlayerUpdateTask launch]; + + [fh readInBackgroundAndNotify]; + } + else + { + [self addToLog:@"Updating Program Index Feeds from Server..." :nil]; + + NSLog(@"DEBUG: Last cache update: %@",lastUpdate); + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + if (!lastUpdate || ([[NSDate date] timeIntervalSinceDate:lastUpdate] > ([[defaults objectForKey:@"CacheExpiryTime"] intValue]*3600)) || [[sender class] isEqualTo:[@"" class]]) + { + typesToCache = [[NSMutableArray alloc] initWithCapacity:5]; + if ([[defaults objectForKey:@"CacheBBC_TV"] boolValue]) [typesToCache addObject:@"tv"]; + if ([[defaults objectForKey:@"CacheITV_TV"] boolValue]) [typesToCache addObject:@"itv"]; + if ([[defaults objectForKey:@"CacheBBC_Radio"] boolValue]) [typesToCache addObject:@"radio"]; + if ([[defaults objectForKey:@"CacheBBC_Podcasts"] boolValue]) [typesToCache addObject:@"podcast"]; + // TODO: Remove 4oD + if ([[defaults objectForKey:@"Cache4oD_TV"] boolValue]) [typesToCache addObject:@"ch4"]; + + NSArray *urlKeys = @[@"tv",@"itv",@"radio",@"podcast",@"ch4"]; + NSArray *urlObjects = @[@"http://tom-tech.com/get_iplayer/cache/tv.cache", + @"http://tom-tech.com/get_iplayer/cache/itv.cache", + @"http://tom-tech.com/get_iplayer/cache/radio.cache", + @"http://tom-tech.com/get_iplayer/cache/podcast.cache", + @"http://tom-tech.com/get_iplayer/cache/ch4.cache"]; + updateURLDic = [[NSDictionary alloc] initWithObjects:urlObjects forKeys:urlKeys]; + + nextToCache=0; + if ([typesToCache count] > 0) + [self updateCacheForType:typesToCache[0]]; + } + else [self getiPlayerUpdateFinished]; + + } } - (void)updateCacheForType:(NSString *)type { - [self addToLog:[NSString stringWithFormat:@" Retrieving %@ index feeds.",type] :nil]; - [currentProgress setStringValue:[NSString stringWithFormat:@"Updating Program Indexes: Getting %@ index feeds from server...",type]]; - - ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:updateURLDic[type]]]; - [request setDelegate:self]; - [request setDidFinishSelector:@selector(indexRequestFinished:)]; - [request setDidFailSelector:@selector(indexRequestFinished:)]; - [request setTimeOutSeconds:10]; - [request setNumberOfTimesToRetryOnTimeout:2]; - [request setDownloadDestinationPath:[[@"~/Library/Application Support/Get iPlayer Automator" stringByExpandingTildeInPath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.cache",type]]]; - [request startAsynchronous]; + [self addToLog:[NSString stringWithFormat:@" Retrieving %@ index feeds.",type] :nil]; + [currentProgress setStringValue:[NSString stringWithFormat:@"Updating Program Indexes: Getting %@ index feeds from server...",type]]; + + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:updateURLDic[type]]]; + [request setDelegate:self]; + [request setDidFinishSelector:@selector(indexRequestFinished:)]; + [request setDidFailSelector:@selector(indexRequestFinished:)]; + [request setTimeOutSeconds:10]; + [request setNumberOfTimesToRetryOnTimeout:2]; + [request setDownloadDestinationPath:[[@"~/Library/Application Support/Get iPlayer Automator" stringByExpandingTildeInPath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.cache",type]]]; + [request startAsynchronous]; } - (void)indexRequestFinished:(ASIHTTPRequest *)request { - if ([request responseStatusCode] != 200) - { - quickUpdateFailed=YES; - [self updateCache:@""]; - } - else - { - didUpdate=YES; - nextToCache++; - if (nextToCache < [typesToCache count]) - [self updateCacheForType:typesToCache[nextToCache]]; - else - { - [self getiPlayerUpdateFinished]; - } - } + if ([request responseStatusCode] != 200) + { + quickUpdateFailed=YES; + [self updateCache:@""]; + } + else + { + didUpdate=YES; + nextToCache++; + if (nextToCache < [typesToCache count]) + [self updateCacheForType:typesToCache[nextToCache]]; + else + { + [self getiPlayerUpdateFinished]; + } + } } - (void)dataReady:(NSNotification *)n { - NSData *d; - d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; + NSData *d; + d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; BOOL matches=NO; - if ([d length] > 0) { + if ([d length] > 0) { NSString *s = [[NSString alloc] initWithData:d - encoding:NSUTF8StringEncoding]; + encoding:NSUTF8StringEncoding]; if ([s hasPrefix:@"INFO:"]) { [self addToLog:[NSString stringWithString:s] :nil]; @@ -572,10 +586,10 @@ - (void)dataReady:(NSNotification *)n infoMessage = nil; scanner = nil; } - else if ([s hasPrefix:@"WARNING:"] || [s hasPrefix:@"ERROR:"]) - { - [self addToLog:s :nil]; - } + else if ([s hasPrefix:@"WARNING:"] || [s hasPrefix:@"ERROR:"]) + { + [self addToLog:s :nil]; + } else if ([s isEqualToString:@"."]) { NSMutableString *infomessage = [[NSMutableString alloc] initWithFormat:@"%@.", [currentProgress stringValue]]; @@ -590,16 +604,16 @@ - (void)dataReady:(NSNotification *)n getiPlayerUpdateTask=nil; [self getiPlayerUpdateFinished]; } - } + } else { getiPlayerUpdateTask = nil; [self getiPlayerUpdateFinished]; } - // If the task is running, start reading again - if (getiPlayerUpdateTask && !matches) - [[getiPlayerUpdatePipe fileHandleForReading] readInBackgroundAndNotify]; + // If the task is running, start reading again + if (getiPlayerUpdateTask && !matches) + [[getiPlayerUpdatePipe fileHandleForReading] readInBackgroundAndNotify]; } - (void)getiPlayerUpdateFinished { @@ -614,26 +628,26 @@ - (void)getiPlayerUpdateFinished getiPlayerUpdateTask = nil; [startButton setEnabled:YES]; [pvrSearchField setEnabled:YES]; - + if (didUpdate) { - @try - { - [GrowlApplicationBridge notifyWithTitle:@"Index Updated" - description:@"The program index was updated." - notificationName:@"Index Updating Completed" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; - } - @catch (NSException *e) { - NSLog(@"ERROR: Growl notification failed (getiPlayerUpdateFinished): %@: %@", [e name], [e description]); - [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (getiPlayerUpdateFinished): %@: %@", [e name], [e description]]]; - } + @try + { + [GrowlApplicationBridge notifyWithTitle:@"Index Updated" + description:@"The program index was updated." + notificationName:@"Index Updating Completed" + iconData:nil + priority:0 + isSticky:NO + clickContext:nil]; + } + @catch (NSException *e) { + NSLog(@"ERROR: Growl notification failed (getiPlayerUpdateFinished): %@: %@", [e name], [e description]); + [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (getiPlayerUpdateFinished): %@: %@", [e name], [e description]]]; + } [self addToLog:@"Index Updated." :self]; - lastUpdate=[NSDate date]; + lastUpdate=[NSDate date]; } else { @@ -649,101 +663,101 @@ - (void)getiPlayerUpdateFinished { BOOL foundMatch=NO; if ([[show showName] length] > 0) - { - NSTask *pipeTask = [[NSTask alloc] init]; - NSPipe *newPipe = [[NSPipe alloc] init]; - NSFileHandle *readHandle2 = [newPipe fileHandleForReading]; - NSData *someData; - - NSString *name = [[show showName] copy]; - NSScanner *scanner = [NSScanner scannerWithString:name]; - NSString *searchArgument; - [scanner scanUpToString:@" - " intoString:&searchArgument]; - // write handle is closed to this process - [pipeTask setStandardOutput:newPipe]; - [pipeTask setStandardError:newPipe]; - [pipeTask setLaunchPath:@"/usr/bin/perl"]; - [pipeTask setArguments:@[getiPlayerPath,profileDirArg,@"--nopurge",noWarningArg,[self typeArgument:nil],[self cacheExpiryArgument:nil],listFormat, - searchArgument]]; - NSMutableString *taskData = [[NSMutableString alloc] initWithString:@""]; - [pipeTask launch]; - while ((someData = [readHandle2 availableData]) && [someData length]) { - [taskData appendString:[[NSString alloc] initWithData:someData - encoding:NSUTF8StringEncoding]]; - } - NSString *string = [NSString stringWithString:taskData]; - NSUInteger length = [string length]; - NSUInteger paraStart = 0, paraEnd = 0, contentsEnd = 0; - NSMutableArray *array = [NSMutableArray array]; - NSRange currentRange; - while (paraEnd < length) { - [string getParagraphStart:¶Start end:¶End + { + NSTask *pipeTask = [[NSTask alloc] init]; + NSPipe *newPipe = [[NSPipe alloc] init]; + NSFileHandle *readHandle2 = [newPipe fileHandleForReading]; + NSData *someData; + + NSString *name = [[show showName] copy]; + NSScanner *scanner = [NSScanner scannerWithString:name]; + NSString *searchArgument; + [scanner scanUpToString:@" - " intoString:&searchArgument]; + // write handle is closed to this process + [pipeTask setStandardOutput:newPipe]; + [pipeTask setStandardError:newPipe]; + [pipeTask setLaunchPath:@"/usr/bin/perl"]; + [pipeTask setArguments:@[getiPlayerPath,profileDirArg,@"--nopurge",noWarningArg,[self typeArgument:nil],[self cacheExpiryArgument:nil],listFormat, + searchArgument]]; + NSMutableString *taskData = [[NSMutableString alloc] initWithString:@""]; + [pipeTask launch]; + while ((someData = [readHandle2 availableData]) && [someData length]) { + [taskData appendString:[[NSString alloc] initWithData:someData + encoding:NSUTF8StringEncoding]]; + } + NSString *string = [NSString stringWithString:taskData]; + NSUInteger length = [string length]; + NSUInteger paraStart = 0, paraEnd = 0, contentsEnd = 0; + NSMutableArray *array = [NSMutableArray array]; + NSRange currentRange; + while (paraEnd < length) { + [string getParagraphStart:¶Start end:¶End contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; - currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); - [array addObject:[string substringWithRange:currentRange]]; - } - for (NSString *string in array) - { - if (![string isEqualToString:@"Matches:"] && ![string hasPrefix:@"INFO:"] && ![string hasPrefix:@"WARNING:"] && [string length]>0) - { - @try - { - NSScanner *myScanner = [NSScanner scannerWithString:string]; - Programme *p = [[Programme alloc] init]; - NSString *temp_pid, *temp_showName, *temp_tvNetwork, *temp_type, *url; - [myScanner scanUpToString:@":" intoString:&temp_pid]; - [myScanner scanUpToString:@"," intoString:&temp_type]; - [myScanner scanString:@", ~" intoString:NULL]; - [myScanner scanUpToString:@"~," intoString:&temp_showName]; - [myScanner scanString:@"~," intoString:NULL]; - [myScanner scanUpToString:@"," intoString:&temp_tvNetwork]; - [myScanner scanString:@"," intoString:nil]; - [myScanner scanUpToString:@"kljkjkj" intoString:&url]; - - if ([temp_showName hasSuffix:@" - -"]) - { - NSString *temp_showName2; - NSScanner *dashScanner = [NSScanner scannerWithString:temp_showName]; - [dashScanner scanUpToString:@" - -" intoString:&temp_showName2]; - temp_showName = temp_showName2; - temp_showName = [temp_showName stringByAppendingFormat:@" - %@", temp_showName2]; - } - [p setValue:temp_pid forKey:@"pid"]; - [p setValue:temp_showName forKey:@"showName"]; - [p setValue:temp_tvNetwork forKey:@"tvNetwork"]; - [p setUrl:url]; - if ([temp_type isEqualToString:@"radio"]) [p setValue:@YES forKey:@"radio"]; - if ([[p showName] isEqualToString:[show showName]] || ([[p url] isEqualToString:[show url]] && [show url])) - { - [show setValue:[p pid] forKey:@"pid"]; - foundMatch=YES; - break; - } - } - @catch (NSException *e) { - NSAlert *searchException = [[NSAlert alloc] init]; - [searchException addButtonWithTitle:@"OK"]; - [searchException setMessageText:[NSString stringWithFormat:@"Invalid Output!"]]; - [searchException setInformativeText:@"Please check your query. Your query must not alter the output format of Get_iPlayer. (getiPlayerUpdateFinished)"]; - [searchException setAlertStyle:NSWarningAlertStyle]; - [searchException runModal]; - searchException = nil; - } - } - else - { - if ([string hasPrefix:@"Unknown option:"] || [string hasPrefix:@"Option"] || [string hasPrefix:@"Usage"]) - { - NSLog(@"Unknown Option"); - } - } - } - if (!foundMatch) - { - [show setValue:@"Not Currently Available" forKey:@"status"]; - [show setValue:@YES forKey:@"complete"]; - [show setValue:@NO forKey:@"successful"]; - } + currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); + [array addObject:[string substringWithRange:currentRange]]; + } + for (NSString *string in array) + { + if (![string isEqualToString:@"Matches:"] && ![string hasPrefix:@"INFO:"] && ![string hasPrefix:@"WARNING:"] && [string length]>0) + { + @try + { + NSScanner *myScanner = [NSScanner scannerWithString:string]; + Programme *p = [[Programme alloc] init]; + NSString *temp_pid, *temp_showName, *temp_tvNetwork, *temp_type, *url; + [myScanner scanUpToString:@":" intoString:&temp_pid]; + [myScanner scanUpToString:@"," intoString:&temp_type]; + [myScanner scanString:@", ~" intoString:NULL]; + [myScanner scanUpToString:@"~," intoString:&temp_showName]; + [myScanner scanString:@"~," intoString:NULL]; + [myScanner scanUpToString:@"," intoString:&temp_tvNetwork]; + [myScanner scanString:@"," intoString:nil]; + [myScanner scanUpToString:@"kljkjkj" intoString:&url]; + + if ([temp_showName hasSuffix:@" - -"]) + { + NSString *temp_showName2; + NSScanner *dashScanner = [NSScanner scannerWithString:temp_showName]; + [dashScanner scanUpToString:@" - -" intoString:&temp_showName2]; + temp_showName = temp_showName2; + temp_showName = [temp_showName stringByAppendingFormat:@" - %@", temp_showName2]; + } + [p setValue:temp_pid forKey:@"pid"]; + [p setValue:temp_showName forKey:@"showName"]; + [p setValue:temp_tvNetwork forKey:@"tvNetwork"]; + [p setUrl:url]; + if ([temp_type isEqualToString:@"radio"]) [p setValue:@YES forKey:@"radio"]; + if ([[p showName] isEqualToString:[show showName]] || ([[p url] isEqualToString:[show url]] && [show url])) + { + [show setValue:[p pid] forKey:@"pid"]; + foundMatch=YES; + break; + } + } + @catch (NSException *e) { + NSAlert *searchException = [[NSAlert alloc] init]; + [searchException addButtonWithTitle:@"OK"]; + [searchException setMessageText:[NSString stringWithFormat:@"Invalid Output!"]]; + [searchException setInformativeText:@"Please check your query. Your query must not alter the output format of Get_iPlayer. (getiPlayerUpdateFinished)"]; + [searchException setAlertStyle:NSWarningAlertStyle]; + [searchException runModal]; + searchException = nil; + } + } + else + { + if ([string hasPrefix:@"Unknown option:"] || [string hasPrefix:@"Option"] || [string hasPrefix:@"Usage"]) + { + NSLog(@"Unknown Option"); + } + } + } + if (!foundMatch) + { + [show setValue:@"Not Currently Available" forKey:@"status"]; + [show setValue:@YES forKey:@"complete"]; + [show setValue:@NO forKey:@"successful"]; + } } } @@ -756,7 +770,7 @@ - (void)getiPlayerUpdateFinished } else { - if (runScheduled) + if (runScheduled) { [self performSelectorOnMainThread:@selector(startDownloads:) withObject:self waitUntilDone:NO]; } @@ -793,7 +807,7 @@ - (void)postLog:(NSNotification *)note } -(void)addToLog:(NSString *)string { - [self addToLog:string :nil]; + [self addToLog:string :nil]; } -(void)addToLog:(NSString *)string :(id)sender { //Get Current Log @@ -823,8 +837,8 @@ -(void)addToLog:(NSString *)string :(id)sender { //Make the Text White. [current_log addAttribute:NSForegroundColorAttributeName - value:[NSColor whiteColor] - range:NSMakeRange(0, [current_log length])]; + value:[NSColor whiteColor] + range:NSMakeRange(0, [current_log length])]; //Update the log. [self setValue:current_log forKey:@"log_value"]; @@ -849,13 +863,13 @@ - (IBAction)copyLog:(id)sender } #pragma mark Search - (IBAction)goToSearch:(id)sender { - [mainWindow makeKeyAndOrderFront:self]; - [mainWindow makeFirstResponder:searchField]; + [mainWindow makeKeyAndOrderFront:self]; + [mainWindow makeFirstResponder:searchField]; } - (IBAction)mainSearch:(id)sender { - [searchField setEnabled:NO]; - + [searchField setEnabled:NO]; + NSString *searchTerms = [searchField stringValue]; if([searchTerms length] > 0) @@ -868,10 +882,10 @@ - (IBAction)mainSearch:(id)sender NSString *cacheExpiryArg = [self cacheExpiryArgument:nil]; NSString *typeArgument = [self typeArgument:nil]; NSArray *args = @[getiPlayerPath,noWarningArg,cacheExpiryArg,typeArgument,listFormat,@"--long",@"--nopurge",searchArgument,profileDirArg]; - - if (![[[NSUserDefaults standardUserDefaults] valueForKey:@"ShowDownloadedInSearch"] boolValue]) - args=[args arrayByAddingObject:@"--hide"]; - + + if (![[[NSUserDefaults standardUserDefaults] valueForKey:@"ShowDownloadedInSearch"] boolValue]) + args=[args arrayByAddingObject:@"--hide"]; + [searchTask setArguments:args]; [searchTask setStandardOutput:searchPipe]; @@ -880,13 +894,13 @@ - (IBAction)mainSearch:(id)sender NSNotificationCenter *nc; nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self - selector:@selector(searchDataReady:) - name:NSFileHandleReadCompletionNotification - object:fh]; + selector:@selector(searchDataReady:) + name:NSFileHandleReadCompletionNotification + object:fh]; [nc addObserver:self - selector:@selector(searchFinished:) - name:NSTaskDidTerminateNotification - object:searchTask]; + selector:@selector(searchFinished:) + name:NSTaskDidTerminateNotification + object:searchTask]; searchData = [[NSMutableString alloc] init]; [searchTask launch]; [searchIndicator startAnimation:nil]; @@ -896,12 +910,12 @@ - (IBAction)mainSearch:(id)sender - (void)searchDataReady:(NSNotification *)n { - NSData *d; - d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; + NSData *d; + d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; - if ([d length] > 0) { + if ([d length] > 0) { NSString *s = [[NSString alloc] initWithData:d - encoding:NSUTF8StringEncoding]; + encoding:NSUTF8StringEncoding]; [searchData appendString:s]; } else @@ -909,13 +923,13 @@ - (void)searchDataReady:(NSNotification *)n searchTask = nil; } - // If the task is running, start reading again - if (searchTask) - [[searchPipe fileHandleForReading] readInBackgroundAndNotify]; + // If the task is running, start reading again + if (searchTask) + [[searchPipe fileHandleForReading] readInBackgroundAndNotify]; } - (void)searchFinished:(NSNotification *)n { - [searchField setEnabled:YES]; + [searchField setEnabled:YES]; BOOL foundShow=NO; [resultsController removeObjectsAtArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [[resultsController arrangedObjects] count])]]; NSString *string = [NSString stringWithString:searchData]; @@ -925,7 +939,7 @@ - (void)searchFinished:(NSNotification *)n NSRange currentRange; while (paraEnd < length) { [string getParagraphStart:¶Start end:¶End - contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; + contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); [array addObject:[string substringWithRange:currentRange]]; } @@ -943,12 +957,12 @@ - (void)searchFinished:(NSNotification *)n [myScanner scanUpToString:@"~," intoString:&temp_showName]; [myScanner scanUpToCharactersFromSet:[NSCharacterSet alphanumericCharacterSet] intoString:NULL]; [myScanner scanUpToString:@"," intoString:&temp_tvNetwork]; - [myScanner scanUpToCharactersFromSet:[NSCharacterSet alphanumericCharacterSet] intoString:NULL]; - [myScanner scanUpToString:@"kjkjkj" intoString:&url]; - if (temp_pid == nil || temp_showName == nil || temp_tvNetwork == nil || temp_type == nil || url == nil) { - [self addToLog: [NSString stringWithFormat:@"WARNING: Skipped invalid search result: %@", string]]; - continue; - } + [myScanner scanUpToCharactersFromSet:[NSCharacterSet alphanumericCharacterSet] intoString:NULL]; + [myScanner scanUpToString:@"kjkjkj" intoString:&url]; + if (temp_pid == nil || temp_showName == nil || temp_tvNetwork == nil || temp_type == nil || url == nil) { + [self addToLog: [NSString stringWithFormat:@"WARNING: Skipped invalid search result: %@", string]]; + continue; + } if ([temp_showName hasSuffix:@" - -"]) { NSString *temp_showName2; @@ -958,14 +972,14 @@ - (void)searchFinished:(NSNotification *)n temp_showName = [temp_showName stringByAppendingFormat:@" - %@", temp_showName2]; } Programme *p = [[Programme alloc] initWithInfo:nil pid:temp_pid programmeName:temp_showName network:temp_tvNetwork]; - [p setUrl:url]; + [p setUrl:url]; if ([temp_type isEqualToString:@"radio"]) { [p setValue:@YES forKey:@"radio"]; } - else if ([temp_type isEqualToString:@"podcast"]) - [p setPodcast:@YES]; - + else if ([temp_type isEqualToString:@"podcast"]) + [p setPodcast:@YES]; + [resultsController addObject:p]; foundShow=YES; } @@ -992,11 +1006,11 @@ - (void)searchFinished:(NSNotification *)n [searchIndicator stopAnimation:nil]; if (!foundShow) { - NSAlert *noneFound = [NSAlert alertWithMessageText:@"No Shows Found" - defaultButton:@"OK" - alternateButton:nil - otherButton:nil - informativeTextWithFormat:@"0 shows were found for your search terms. Please check your spelling!"]; + NSAlert *noneFound = [NSAlert alertWithMessageText:@"No Shows Found" + defaultButton:@"OK" + alternateButton:nil + otherButton:nil + informativeTextWithFormat:@"0 shows were found for your search terms. Please check your spelling!"]; [noneFound runModal]; } } @@ -1021,7 +1035,7 @@ - (IBAction)addToQueue:(id)sender { if ([[show showName] isEqualToString:[queuedShow showName]] && [show pid] == [queuedShow pid]) add=NO; } - if (add) + if (add) { if (runDownloads) [show setValue:@"Waiting..." forKey:@"status"]; [queueController addObject:show]; @@ -1070,7 +1084,7 @@ - (void)processGetNameData:(NSString *)getNameData forProgramme:(Programme *)p NSRange currentRange; while (paraEnd < length) { [string getParagraphStart:¶Start end:¶End - contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; + contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); [array addObject:[string substringWithRange:currentRange]]; } @@ -1092,10 +1106,10 @@ - (void)processGetNameData:(NSString *)getNameData forProgramme:(Programme *)p [scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:&type]; [scanner scanUpToCharactersFromSet:[NSCharacterSet alphanumericCharacterSet] intoString:NULL]; [scanner scanUpToString:@"," intoString:&showName]; - [scanner scanString:@"," intoString:nil]; - [scanner scanUpToString:@"|" intoString:&tvNetwork]; - [scanner scanString:@"|" intoString:nil]; - [scanner scanUpToString:@"|" intoString:&url]; + [scanner scanString:@"," intoString:nil]; + [scanner scanUpToString:@"|" intoString:&tvNetwork]; + [scanner scanString:@"|" intoString:nil]; + [scanner scanUpToString:@"|" intoString:&url]; scanner = nil; } @catch (NSException *e) { @@ -1112,42 +1126,42 @@ - (void)processGetNameData:(NSString *)getNameData forProgramme:(Programme *)p found=YES; [p setValue:showName forKey:@"showName"]; [p setValue:index forKey:@"pid"]; - [p setValue:tvNetwork forKey:@"tvNetwork"]; - [p setUrl:url]; + [p setValue:tvNetwork forKey:@"tvNetwork"]; + [p setUrl:url]; if ([type isEqualToString:@"radio"]) [p setValue:@YES forKey:@"radio"]; - else if ([type isEqualToString:@"podcast"]) [p setPodcast:@YES]; + else if ([type isEqualToString:@"podcast"]) [p setPodcast:@YES]; } else if ([wantedID isEqualToString:index]) { found=YES; [p setValue:showName forKey:@"showName"]; - [p setValue:tvNetwork forKey:@"tvNetwork"]; - [p setUrl:url]; + [p setValue:tvNetwork forKey:@"tvNetwork"]; + [p setUrl:url]; if ([type isEqualToString:@"radio"]) [p setValue:@YES forKey:@"radio"]; - else if ([type isEqualToString:@"podcast"]) [p setPodcast:@YES]; + else if ([type isEqualToString:@"podcast"]) [p setPodcast:@YES]; } } - + } if (!found) - { - if ([[p showName] isEqualToString:@""] || [[p showName] isEqualToString:@"Unknown: Not in Cache"]) - [p setValue:@"Unknown: Not in Cache" forKey:@"showName"]; - [p setProcessedPID:@NO]; - } + { + if ([[p showName] isEqualToString:@""] || [[p showName] isEqualToString:@"Unknown: Not in Cache"]) + [p setValue:@"Unknown: Not in Cache" forKey:@"showName"]; + [p setProcessedPID:@NO]; + } else [p setProcessedPID:@YES]; } - (IBAction)getCurrentWebpage:(id)sender { - NSString *newShowName=nil; + NSString *newShowName=nil; //Get Default Browser NSString *browser = [[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultBrowser"]; //Prepare Pointer for URL NSString *url = nil; - NSString *source = nil; + NSString *source = nil; //Prepare Alert in Case the Browser isn't Open NSAlert *browserNotOpen = [[NSAlert alloc] init]; @@ -1170,43 +1184,43 @@ - (IBAction)getCurrentWebpage:(id)sender { for (SafariWindow *window in windows) { - SafariTab *tab = [window currentTab]; - if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || - [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/episode/"] || - [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || - [[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/console/"] || - [[tab URL] hasPrefix:@"http://bbc.co.uk/sport"]) - { - url = [NSString stringWithString:[tab URL]]; - NSScanner *nameScanner = [NSScanner scannerWithString:[tab name]]; - [nameScanner scanString:@"BBC iPlayer - " intoString:nil]; - [nameScanner scanString:@"BBC Sport - " intoString:nil]; - [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; - foundURL=YES; - } - else if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/programmes/"]) { - url = [NSString stringWithString:[tab URL]]; - NSScanner *nameScanner = [NSScanner scannerWithString:[tab name]]; - [nameScanner scanUpToString:@" - " intoString:nil]; - [nameScanner scanString:@" - " intoString:nil]; - [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; - foundURL=YES; - source = [Safari doJavaScript:@"document.documentElement.outerHTML" in:tab]; - } - else if ([[tab URL] hasPrefix:@"https://www.itv.com/itvplayer/"] || - [[tab URL] hasPrefix:@"http://www.channel4.com/programmes/"] || - [[tab URL] hasPrefix:@"http://ps3.channel4.com"]) - { - url = [NSString stringWithString:[tab URL]]; - source = [Safari doJavaScript:@"document.documentElement.outerHTML" in:tab]; - newShowName = [[[tab name] stringByReplacingOccurrencesOfString:@" | itvplayer" withString:@""] stringByReplacingOccurrencesOfString:@" - 4oD - Channel 4" withString:@""]; - foundURL=YES; - } + SafariTab *tab = [window currentTab]; + if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || + [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/episode/"] || + [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || + [[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/console/"] || + [[tab URL] hasPrefix:@"http://bbc.co.uk/sport"]) + { + url = [NSString stringWithString:[tab URL]]; + NSScanner *nameScanner = [NSScanner scannerWithString:[tab name]]; + [nameScanner scanString:@"BBC iPlayer - " intoString:nil]; + [nameScanner scanString:@"BBC Sport - " intoString:nil]; + [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; + foundURL=YES; + } + else if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/programmes/"]) { + url = [NSString stringWithString:[tab URL]]; + NSScanner *nameScanner = [NSScanner scannerWithString:[tab name]]; + [nameScanner scanUpToString:@" - " intoString:nil]; + [nameScanner scanString:@" - " intoString:nil]; + [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; + foundURL=YES; + source = [Safari doJavaScript:@"document.documentElement.outerHTML" in:tab]; + } + else if ([[tab URL] hasPrefix:@"https://www.itv.com/itvplayer/"] || + [[tab URL] hasPrefix:@"http://www.channel4.com/programmes/"] || + [[tab URL] hasPrefix:@"http://ps3.channel4.com"]) + { + url = [NSString stringWithString:[tab URL]]; + source = [Safari doJavaScript:@"document.documentElement.outerHTML" in:tab]; + newShowName = [[[tab name] stringByReplacingOccurrencesOfString:@" | itvplayer" withString:@""] stringByReplacingOccurrencesOfString:@" - 4oD - Channel 4" withString:@""]; + foundURL=YES; + } } if (foundURL==NO) { url = [NSString stringWithString:[[windows[0] currentTab] URL]]; - //Might be incorrect + //Might be incorrect } } else @@ -1227,7 +1241,7 @@ - (IBAction)getCurrentWebpage:(id)sender return; } } - else if ([browser isEqualToString:@"Chrome"]) + else if ([browser isEqualToString:@"Chrome"]) { BOOL foundURL=NO; ChromeApplication *Chrome = [SBApplication applicationWithBundleIdentifier:@"com.google.Chrome"]; @@ -1240,43 +1254,43 @@ - (IBAction)getCurrentWebpage:(id)sender { for (ChromeWindow *window in windows) { - ChromeTab *tab = [window activeTab]; - if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || - [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/episode/"] || - [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || - [[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/console/"] || - [[tab URL] hasPrefix:@"http://bbc.co.uk/sport"]) - { - url = [NSString stringWithString:[tab URL]]; - NSScanner *nameScanner = [NSScanner scannerWithString:[tab title]]; - [nameScanner scanString:@"BBC iPlayer - " intoString:nil]; - [nameScanner scanString:@"BBC Sport - " intoString:nil]; - [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; - foundURL=YES; - } - else if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/programmes/"]) { - url = [NSString stringWithString:[tab URL]]; - NSScanner *nameScanner = [NSScanner scannerWithString:[tab title]]; - [nameScanner scanUpToString:@" - " intoString:nil]; - [nameScanner scanString:@" - " intoString:nil]; - [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; - foundURL=YES; - source = [tab executeJavascript:@"document.documentElement.outerHTML"]; - } - else if ([[tab URL] hasPrefix:@"https://www.itv.com/itvplayer/"] || - [[tab URL] hasPrefix:@"http://www.channel4.com/programmes/"] || - [[tab URL] hasPrefix:@"http://ps3.channel4.com"]) - { - url = [NSString stringWithString:[tab URL]]; - source = [tab executeJavascript:@"document.documentElement.outerHTML"]; - newShowName = [[[tab title] stringByReplacingOccurrencesOfString:@" | itvplayer" withString:@""] stringByReplacingOccurrencesOfString:@" - 4oD - Channel 4" withString:@""]; - foundURL=YES; - } + ChromeTab *tab = [window activeTab]; + if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || + [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/episode/"] || + [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || + [[tab URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/console/"] || + [[tab URL] hasPrefix:@"http://bbc.co.uk/sport"]) + { + url = [NSString stringWithString:[tab URL]]; + NSScanner *nameScanner = [NSScanner scannerWithString:[tab title]]; + [nameScanner scanString:@"BBC iPlayer - " intoString:nil]; + [nameScanner scanString:@"BBC Sport - " intoString:nil]; + [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; + foundURL=YES; + } + else if ([[tab URL] hasPrefix:@"http://www.bbc.co.uk/programmes/"]) { + url = [NSString stringWithString:[tab URL]]; + NSScanner *nameScanner = [NSScanner scannerWithString:[tab title]]; + [nameScanner scanUpToString:@" - " intoString:nil]; + [nameScanner scanString:@" - " intoString:nil]; + [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; + foundURL=YES; + source = [tab executeJavascript:@"document.documentElement.outerHTML"]; + } + else if ([[tab URL] hasPrefix:@"https://www.itv.com/itvplayer/"] || + [[tab URL] hasPrefix:@"http://www.channel4.com/programmes/"] || + [[tab URL] hasPrefix:@"http://ps3.channel4.com"]) + { + url = [NSString stringWithString:[tab URL]]; + source = [tab executeJavascript:@"document.documentElement.outerHTML"]; + newShowName = [[[tab title] stringByReplacingOccurrencesOfString:@" | itvplayer" withString:@""] stringByReplacingOccurrencesOfString:@" - 4oD - Channel 4" withString:@""]; + foundURL=YES; + } } if (foundURL==NO) { url = [NSString stringWithString:[[windows[0] activeTab] URL]]; - //Might be incorrect + //Might be incorrect } } else @@ -1298,151 +1312,151 @@ - (IBAction)getCurrentWebpage:(id)sender } } + else + { + [[NSAlert alertWithMessageText:@"Get iPlayer Automator currently only supports Safari and Chrome." defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Please change your preferred browser in the preferences and try again."] runModal]; + return; + } + /*else if ([browser isEqualToString:@"Firefox"]) + { + NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"GetFireFoxURL" ofType:@"applescript"]; + NSURL *scriptLocation = [[NSURL alloc] initFileURLWithPath:scriptPath]; + if (scriptLocation) + { + NSDictionary *errorDic; + NSAppleScript *getFirefoxURL = [[NSAppleScript alloc] initWithContentsOfURL:scriptLocation error:&errorDic]; + if (getFirefoxURL) + { + NSDictionary *executionError; + NSAppleEventDescriptor *result = [getFirefoxURL executeAndReturnError:&executionError]; + if (result) + { + url = [[NSString alloc] initWithString:[result stringValue]]; + if ([url isEqualToString:@"Error"]) + { + [browserNotOpen runModal]; + return; + } + } + } + } + } + else if ([browser isEqualToString:@"Camino"]) + { + //Scripting Bridge Version + CaminoApplication *camino = [SBApplication applicationWithBundleIdentifier:@"org.mozilla.camino"]; + if ([camino isRunning]) + { + BOOL foundURL=NO; + NSMutableArray *tabsArray = [[NSMutableArray alloc] init]; + SBElementArray *windows = [camino browserWindows]; + if ([[NSNumber numberWithUnsignedInteger:[windows count]] intValue]) + { + for (CaminoBrowserWindow *window in windows) + { + SBElementArray *tabs = [window tabs]; + if ([[NSNumber numberWithUnsignedInteger:[tabs count]] intValue]) + { + [tabsArray addObjectsFromArray:tabs]; + } + } + } + else [browserNotOpen runModal]; + if ([[NSNumber numberWithUnsignedInteger:[tabsArray count]] intValue]) + { + for (CaminoTab *tab in tabsArray) + { + if ([[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/episode/"] || [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || [[tab URL] hasPrefix:@"http://www.itv.com/ITVPlayer/Video/default.html?ViewType"]) + { + url = [[NSString alloc] initWithString:[tab URL]]; + foundURL=YES; + break; + } + } + if (foundURL==NO) + { + url = [[NSString alloc] initWithString:[[[tabsArray objectAtIndex:0] URL] path]]; + } + } else { - [[NSAlert alertWithMessageText:@"Get iPlayer Automator currently only supports Safari and Chrome." defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Please change your preferred browser in the preferences and try again."] runModal]; - return; + [browserNotOpen runModal]; + return; + } + } + else + { + [browserNotOpen runModal]; + return; + } } - /*else if ([browser isEqualToString:@"Firefox"]) - { - NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"GetFireFoxURL" ofType:@"applescript"]; - NSURL *scriptLocation = [[NSURL alloc] initFileURLWithPath:scriptPath]; - if (scriptLocation) - { - NSDictionary *errorDic; - NSAppleScript *getFirefoxURL = [[NSAppleScript alloc] initWithContentsOfURL:scriptLocation error:&errorDic]; - if (getFirefoxURL) - { - NSDictionary *executionError; - NSAppleEventDescriptor *result = [getFirefoxURL executeAndReturnError:&executionError]; - if (result) - { - url = [[NSString alloc] initWithString:[result stringValue]]; - if ([url isEqualToString:@"Error"]) - { - [browserNotOpen runModal]; - return; - } - } - } - } - } - else if ([browser isEqualToString:@"Camino"]) - { - //Scripting Bridge Version - CaminoApplication *camino = [SBApplication applicationWithBundleIdentifier:@"org.mozilla.camino"]; - if ([camino isRunning]) - { - BOOL foundURL=NO; - NSMutableArray *tabsArray = [[NSMutableArray alloc] init]; - SBElementArray *windows = [camino browserWindows]; - if ([[NSNumber numberWithUnsignedInteger:[windows count]] intValue]) - { - for (CaminoBrowserWindow *window in windows) - { - SBElementArray *tabs = [window tabs]; - if ([[NSNumber numberWithUnsignedInteger:[tabs count]] intValue]) - { - [tabsArray addObjectsFromArray:tabs]; - } - } - } - else [browserNotOpen runModal]; - if ([[NSNumber numberWithUnsignedInteger:[tabsArray count]] intValue]) - { - for (CaminoTab *tab in tabsArray) - { - if ([[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/episode/"] || [[tab URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || [[tab URL] hasPrefix:@"http://www.itv.com/ITVPlayer/Video/default.html?ViewType"]) - { - url = [[NSString alloc] initWithString:[tab URL]]; - foundURL=YES; - break; - } - } - if (foundURL==NO) - { - url = [[NSString alloc] initWithString:[[[tabsArray objectAtIndex:0] URL] path]]; - } - } - else - { - [browserNotOpen runModal]; - return; - } - } - else - { - [browserNotOpen runModal]; - return; - } - } else if ([browser isEqualToString:@"Chrome"]) { - NSLog(@"Beginning Chrome"); - BOOL foundURL=NO; - ChromeApplication *Chrome = [SBApplication applicationWithBundleIdentifier:@"com.google.Chrome"]; - if ([Chrome isRunning]) - { - NSLog(@"Chrome is running."); - @try - { - SBElementArray *windows = [Chrome windows]; - SBElementArray *tabs; - for (ChromeWindow *chromeWindow1 in windows) - { - [tabs addObject:[chromeWindow1 activeTab]]; - NSLog(@"Adding tab."); - } - if ([tabs count]>0) - { - NSLog(@"Have tabs"); - for (ChromeTab *document in tabs) - { - NSLog(@"Looking at tab"); - if ([[document URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || [[document URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || [[document URL] hasPrefix:@"http://www.itv.com/ITVPlayer/Video/default.html?ViewType"]) - { - url = [NSString stringWithString:[document URL]]; - NSScanner *nameScanner = [NSScanner scannerWithString:[document title]]; - [nameScanner scanString:@"BBC iPlayer - " intoString:nil]; - [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; - foundURL=YES; - } - } - if (foundURL==NO) - { - NSLog(@"Didn't Find URL"); - url = [NSString stringWithString:[[tabs objectAtIndex:0] URL]]; - //Might be incorrect - NSLog(@"%@", url); - } - else - { - NSLog(@"%@", url); - } - } - else - { - NSLog(@"Tab count is 0"); - for (ChromeWindow *chromeWindow in windows) - { - url=[[chromeWindow activeTab] URL]; - } - [browserNotOpen runModal]; - return; - } - } - @catch (NSException *e) - { - [browserNotOpen runModal]; - return; - } - } - else - { - [browserNotOpen runModal]; - return; - } - NSLog(@"%d", foundURL); + NSLog(@"Beginning Chrome"); + BOOL foundURL=NO; + ChromeApplication *Chrome = [SBApplication applicationWithBundleIdentifier:@"com.google.Chrome"]; + if ([Chrome isRunning]) + { + NSLog(@"Chrome is running."); + @try + { + SBElementArray *windows = [Chrome windows]; + SBElementArray *tabs; + for (ChromeWindow *chromeWindow1 in windows) + { + [tabs addObject:[chromeWindow1 activeTab]]; + NSLog(@"Adding tab."); + } + if ([tabs count]>0) + { + NSLog(@"Have tabs"); + for (ChromeTab *document in tabs) + { + NSLog(@"Looking at tab"); + if ([[document URL] hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || [[document URL] hasPrefix:@"http://bbc.co.uk/iplayer/console/"] || [[document URL] hasPrefix:@"http://www.itv.com/ITVPlayer/Video/default.html?ViewType"]) + { + url = [NSString stringWithString:[document URL]]; + NSScanner *nameScanner = [NSScanner scannerWithString:[document title]]; + [nameScanner scanString:@"BBC iPlayer - " intoString:nil]; + [nameScanner scanUpToString:@"kjklgfdjfgkdlj" intoString:&newShowName]; + foundURL=YES; + } + } + if (foundURL==NO) + { + NSLog(@"Didn't Find URL"); + url = [NSString stringWithString:[[tabs objectAtIndex:0] URL]]; + //Might be incorrect + NSLog(@"%@", url); + } + else + { + NSLog(@"%@", url); + } + } + else + { + NSLog(@"Tab count is 0"); + for (ChromeWindow *chromeWindow in windows) + { + url=[[chromeWindow activeTab] URL]; + } + [browserNotOpen runModal]; + return; + } + } + @catch (NSException *e) + { + [browserNotOpen runModal]; + return; + } + } + else + { + [browserNotOpen runModal]; + return; + } + NSLog(@"%d", foundURL); }*/ //Process URL if([url hasPrefix:@"http://www.bbc.co.uk/iplayer/episode/"] || [url hasPrefix:@"http://beta.bbc.co.uk/iplayer/episode"]) @@ -1460,7 +1474,7 @@ - (IBAction)getCurrentWebpage:(id)sender [urlScanner scanUpToString:@"/" intoString:&pid]; Programme *newProg = [[Programme alloc] init]; [newProg setValue:pid forKey:@"pid"]; - if (newShowName) [newProg setShowName:newShowName]; + if (newShowName) [newProg setShowName:newShowName]; [queueController addObject:newProg]; [self getNameForProgramme:newProg]; } @@ -1474,141 +1488,141 @@ - (IBAction)getCurrentWebpage:(id)sender [urlScanner scanString:@"/" intoString:nil]; [urlScanner scanUpToString:@"/" intoString:&pid]; NSScanner *scanner = [NSScanner scannerWithString:source]; - [scanner scanUpToString:[NSString stringWithFormat:@"emp.load(\"http://www.bbc.co.uk/iplayer/playlist/%@\")", pid] intoString:nil]; + [scanner scanUpToString:[NSString stringWithFormat:@"emp.load(\"http://www.bbc.co.uk/iplayer/playlist/%@\")", pid] intoString:nil]; if ([scanner isAtEnd]) { - NSAlert *invalidPage = [[NSAlert alloc] init]; - [invalidPage addButtonWithTitle:@"OK"]; - [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; - [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an iPlayer episode page."]; - [invalidPage setAlertStyle:NSWarningAlertStyle]; - [invalidPage runModal]; - return; - } + NSAlert *invalidPage = [[NSAlert alloc] init]; + [invalidPage addButtonWithTitle:@"OK"]; + [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; + [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an iPlayer episode page."]; + [invalidPage setAlertStyle:NSWarningAlertStyle]; + [invalidPage runModal]; + return; + } Programme *newProg = [[Programme alloc] init]; [newProg setValue:pid forKey:@"pid"]; - if (newShowName) [newProg setShowName:newShowName]; + if (newShowName) [newProg setShowName:newShowName]; [queueController addObject:newProg]; [self getNameForProgramme:newProg]; - } - else if ([url hasPrefix:@"http://www.bbc.co.uk/sport/olympics/2012/live-video/"]) - { - NSString *pid = nil; - NSScanner *urlScanner = [NSScanner scannerWithString:url]; - [urlScanner scanString:@"http://www.bbc.co.uk/sport/olympics/2012/live-video/" intoString:nil]; - [urlScanner scanUpToString:@"kfejklfjklj" intoString:&pid]; - [queueController addObject:[[Programme alloc] initWithInfo:nil pid:pid programmeName:newShowName network:@"BBC Sport"]]; - } + } + else if ([url hasPrefix:@"http://www.bbc.co.uk/sport/olympics/2012/live-video/"]) + { + NSString *pid = nil; + NSScanner *urlScanner = [NSScanner scannerWithString:url]; + [urlScanner scanString:@"http://www.bbc.co.uk/sport/olympics/2012/live-video/" intoString:nil]; + [urlScanner scanUpToString:@"kfejklfjklj" intoString:&pid]; + [queueController addObject:[[Programme alloc] initWithInfo:nil pid:pid programmeName:newShowName network:@"BBC Sport"]]; + } else if ([url hasPrefix:@"https://www.itv.com/itvplayer/"]) { - NSString *progname = nil, *productionId = nil, *pay_rights = nil, *title = nil, *action_type = nil; - progname = newShowName; + NSString *progname = nil, *productionId = nil, *pay_rights = nil, *title = nil, *action_type = nil; + progname = newShowName; NSScanner *scanner = [NSScanner scannerWithString:source]; - [scanner scanUpToString:@"\"productionId\":" intoString:nil]; - [scanner scanString:@"\"productionId\":\"" intoString:nil]; - [scanner scanUpToString:@"\"" intoString:&productionId]; - [scanner scanUpToString:@"\"action_type\":" intoString:nil]; - [scanner scanString:@"\"action_type\":\"" intoString:nil]; - [scanner scanUpToString:@"\"" intoString:&action_type]; - [scanner scanUpToString:@"\"pay_rights\":" intoString:nil]; - [scanner scanString:@"\"pay_rights\":\"" intoString:nil]; - [scanner scanUpToString:@"\"" intoString:&pay_rights]; - [scanner scanUpToString:@"

" intoString:nil]; - [scanner scanString:@">" intoString:nil]; - [scanner scanUpToString:@"<" intoString:&title]; - if (title) progname = title; - if (!progname || !productionId || (![pay_rights isEqualToString:@"free"] && ![action_type isEqualToString:@"free_taster"])) { - NSAlert *invalidPage = [[NSAlert alloc] init]; - [invalidPage addButtonWithTitle:@"OK"]; - [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; - [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an ITV Player free catch-up episode page."]; - [invalidPage setAlertStyle:NSWarningAlertStyle]; - [invalidPage runModal]; - return; - } - NSString *pid = [productionId stringByReplacingOccurrencesOfString:@"\\" withString:@""]; - NSString *showName = [NSString stringWithFormat:@"%@ - %@", progname, pid]; + [scanner scanUpToString:@"\"productionId\":" intoString:nil]; + [scanner scanString:@"\"productionId\":\"" intoString:nil]; + [scanner scanUpToString:@"\"" intoString:&productionId]; + [scanner scanUpToString:@"\"action_type\":" intoString:nil]; + [scanner scanString:@"\"action_type\":\"" intoString:nil]; + [scanner scanUpToString:@"\"" intoString:&action_type]; + [scanner scanUpToString:@"\"pay_rights\":" intoString:nil]; + [scanner scanString:@"\"pay_rights\":\"" intoString:nil]; + [scanner scanUpToString:@"\"" intoString:&pay_rights]; + [scanner scanUpToString:@"

" intoString:nil]; + [scanner scanString:@">" intoString:nil]; + [scanner scanUpToString:@"<" intoString:&title]; + if (title) progname = title; + if (!progname || !productionId || (![pay_rights isEqualToString:@"free"] && ![action_type isEqualToString:@"free_taster"])) { + NSAlert *invalidPage = [[NSAlert alloc] init]; + [invalidPage addButtonWithTitle:@"OK"]; + [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; + [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an ITV Player free catch-up episode page."]; + [invalidPage setAlertStyle:NSWarningAlertStyle]; + [invalidPage runModal]; + return; + } + NSString *pid = [productionId stringByReplacingOccurrencesOfString:@"\\" withString:@""]; + NSString *showName = [NSString stringWithFormat:@"%@ - %@", progname, pid]; Programme *newProg = [[Programme alloc] init]; - [newProg setPid:pid]; - [newProg setShowName:showName]; - [newProg setTvNetwork:@"ITV"]; - [newProg setProcessedPID:@YES]; - [newProg setUrl:url]; + [newProg setPid:pid]; + [newProg setShowName:showName]; + [newProg setTvNetwork:@"ITV"]; + [newProg setProcessedPID:@YES]; + [newProg setUrl:url]; [queueController addObject:newProg]; } -// TODO: remove 4oD -// disable 4oD -// else if ([url hasPrefix:@"http://www.channel4.com/programmes/"]) -// { -// NSString *pid = nil; -// NSScanner *urlScanner = [NSScanner scannerWithString:url]; -// [urlScanner scanUpToString:@"#" intoString:nil]; -// [urlScanner scanString:@"#" intoString:nil]; -// [urlScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&pid]; -// if (!pid) { -// NSScanner *scanner = [NSScanner scannerWithString:source]; -// [scanner scanUpToString:@"data-assetid=\"" intoString:nil]; -// [scanner scanString:@"data-assetid=\"" intoString:nil]; -// [scanner scanUpToString:@"\"" intoString:&pid]; -// } -// if (!pid) -// { -// NSAlert *invalidPage = [[NSAlert alloc] init]; -// [invalidPage addButtonWithTitle:@"OK"]; -// [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; -// [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to a 4oD episode page."]; -// [invalidPage setAlertStyle:NSWarningAlertStyle]; -// [invalidPage runModal]; -// return; -// } -// Programme *newProg = [[Programme alloc] init]; -// [newProg setPid:pid]; -// [queueController addObject:newProg]; -// [self getNameForProgramme:newProg]; -// } -// else if ([url hasPrefix:@"http://ps3.channel4.com"]) -// { -// NSString *pid = nil, *seriesName = nil; -// NSScanner *ps3Scanner = [NSScanner scannerWithString:source]; -// [ps3Scanner scanUpToString:@"brandTitle=" intoString:nil]; -// [ps3Scanner scanString:@"brandTitle=" intoString:nil]; -// [ps3Scanner scanUpToString:@"&" intoString:&seriesName]; -// [ps3Scanner scanUpToString:@"preSelectAsset=" intoString:nil]; -// [ps3Scanner scanString:@"preSelectAsset=" intoString:nil]; -// [ps3Scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&pid]; -// if (!seriesName) seriesName = newShowName; -// if (!pid || !seriesName) -// { -// NSAlert *invalidPage = [[NSAlert alloc] init]; -// [invalidPage addButtonWithTitle:@"OK"]; -// [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; -// [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to a 4oD PS3 episode page."]; -// [invalidPage setAlertStyle:NSWarningAlertStyle]; -// [invalidPage runModal]; -// return; -// } -// NSString *showName = [NSString stringWithFormat:@"%@ - %@", seriesName, pid]; -// Programme *newProg = [[Programme alloc] init]; -// [newProg setPid:pid]; -// [newProg setShowName:showName]; -// [newProg setTvNetwork:@"4oD C4"]; -// [newProg setUrl:url]; -// [newProg setProcessedPID:@YES]; -// [queueController addObject:newProg]; -// } + // TODO: remove 4oD + // disable 4oD + // else if ([url hasPrefix:@"http://www.channel4.com/programmes/"]) + // { + // NSString *pid = nil; + // NSScanner *urlScanner = [NSScanner scannerWithString:url]; + // [urlScanner scanUpToString:@"#" intoString:nil]; + // [urlScanner scanString:@"#" intoString:nil]; + // [urlScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&pid]; + // if (!pid) { + // NSScanner *scanner = [NSScanner scannerWithString:source]; + // [scanner scanUpToString:@"data-assetid=\"" intoString:nil]; + // [scanner scanString:@"data-assetid=\"" intoString:nil]; + // [scanner scanUpToString:@"\"" intoString:&pid]; + // } + // if (!pid) + // { + // NSAlert *invalidPage = [[NSAlert alloc] init]; + // [invalidPage addButtonWithTitle:@"OK"]; + // [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; + // [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to a 4oD episode page."]; + // [invalidPage setAlertStyle:NSWarningAlertStyle]; + // [invalidPage runModal]; + // return; + // } + // Programme *newProg = [[Programme alloc] init]; + // [newProg setPid:pid]; + // [queueController addObject:newProg]; + // [self getNameForProgramme:newProg]; + // } + // else if ([url hasPrefix:@"http://ps3.channel4.com"]) + // { + // NSString *pid = nil, *seriesName = nil; + // NSScanner *ps3Scanner = [NSScanner scannerWithString:source]; + // [ps3Scanner scanUpToString:@"brandTitle=" intoString:nil]; + // [ps3Scanner scanString:@"brandTitle=" intoString:nil]; + // [ps3Scanner scanUpToString:@"&" intoString:&seriesName]; + // [ps3Scanner scanUpToString:@"preSelectAsset=" intoString:nil]; + // [ps3Scanner scanString:@"preSelectAsset=" intoString:nil]; + // [ps3Scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&pid]; + // if (!seriesName) seriesName = newShowName; + // if (!pid || !seriesName) + // { + // NSAlert *invalidPage = [[NSAlert alloc] init]; + // [invalidPage addButtonWithTitle:@"OK"]; + // [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; + // [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to a 4oD PS3 episode page."]; + // [invalidPage setAlertStyle:NSWarningAlertStyle]; + // [invalidPage runModal]; + // return; + // } + // NSString *showName = [NSString stringWithFormat:@"%@ - %@", seriesName, pid]; + // Programme *newProg = [[Programme alloc] init]; + // [newProg setPid:pid]; + // [newProg setShowName:showName]; + // [newProg setTvNetwork:@"4oD C4"]; + // [newProg setUrl:url]; + // [newProg setProcessedPID:@YES]; + // [queueController addObject:newProg]; + // } else { NSAlert *invalidPage = [[NSAlert alloc] init]; [invalidPage addButtonWithTitle:@"OK"]; [invalidPage setMessageText:[NSString stringWithFormat:@"Invalid Page: %@",url]]; - // TODO: remove 4oD - // disable 4oD - // [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an iPlayer episode page, ITV Player free catch-up episode page, 4oD episode page or 4oD PS3 episode page."]; + // TODO: remove 4oD + // disable 4oD + // [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an iPlayer episode page, ITV Player free catch-up episode page, 4oD episode page or 4oD PS3 episode page."]; [invalidPage setInformativeText:@"Please ensure the frontmost browser tab is open to an iPlayer episode page or ITV Player free catch-up episode page. 4oD is no longer supported."]; [invalidPage setAlertStyle:NSWarningAlertStyle]; [invalidPage runModal]; } - + } - (IBAction)removeFromQueue:(id)sender { @@ -1626,12 +1640,12 @@ - (IBAction)removeFromQueue:(id)sender } if (downloading) { - NSAlert *cantRemove = [NSAlert alertWithMessageText:@"A Selected Show is Currently Downloading." - defaultButton:@"OK" - alternateButton:nil - otherButton:nil - informativeTextWithFormat:@"You can not remove a show that is currently downloading. " - @"Please stop the downloads then remove the download if you wish to cancel it."]; + NSAlert *cantRemove = [NSAlert alertWithMessageText:@"A Selected Show is Currently Downloading." + defaultButton:@"OK" + alternateButton:nil + otherButton:nil + informativeTextWithFormat:@"You can not remove a show that is currently downloading. " + @"Please stop the downloads then remove the download if you wish to cancel it."]; [cantRemove runModal]; } else @@ -1660,51 +1674,50 @@ - (IBAction)hidePvrShow:(id)sender #pragma mark Download Controller - (IBAction)startDownloads:(id)sender { - @try - { - [stopButton setEnabled:NO]; - [startButton setEnabled:NO]; - } - @catch (NSException *e) { - NSLog(@"NO UI: startDownloads:"); - } - [self saveAppData]; //Save data in case of crash. - [self loadProxyInBackgroundForSelector:@selector(startDownloads:proxyError:) withObject:sender]; + @try + { + [stopButton setEnabled:NO]; + [startButton setEnabled:NO]; + } + @catch (NSException *e) { + NSLog(@"NO UI: startDownloads:"); + } + [self saveAppData]; //Save data in case of crash. + [self loadProxyInBackgroundForSelector:@selector(startDownloads:proxyError:) withObject:sender]; } - (void)startDownloads:(id)sender proxyError:(NSError *)proxyError { - // reset after proxy load - @try - { - [stopButton setEnabled:YES]; - [startButton setEnabled:YES]; - } - @catch (NSException *e) { - NSLog(@"NO UI: startDownloads:proxyError:"); - } - if ([proxyError code] == kProxyLoadCancelled) - return; + // reset after proxy load + @try + { + [stopButton setEnabled:YES]; + } + @catch (NSException *e) { + NSLog(@"NO UI: startDownloads:proxyError:"); + } + if ([proxyError code] == kProxyLoadCancelled) + return; NSAlert *whatAnIdiot = [NSAlert alertWithMessageText:@"No Shows in Queue!" - defaultButton:nil - alternateButton:nil - otherButton:nil - informativeTextWithFormat:@"Try adding shows to the queue before clicking start; " - @"Get iPlayer Automator needs to know what to download."]; + defaultButton:nil + alternateButton:nil + otherButton:nil + informativeTextWithFormat:@"Try adding shows to the queue before clicking start; " + @"Get iPlayer Automator needs to know what to download."]; if ([[queueController arrangedObjects] count] > 0) { - NSLog(@"Initialising Failure Dictionary"); - if (!solutionsDictionary) - solutionsDictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ReasonsForFailure" ofType:@"plist"]]; - NSLog(@"Failure Dictionary Ready"); - + NSLog(@"Initialising Failure Dictionary"); + if (!solutionsDictionary) + solutionsDictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ReasonsForFailure" ofType:@"plist"]]; + NSLog(@"Failure Dictionary Ready"); + BOOL foundOne=NO; runDownloads=YES; - runScheduled=NO; + runScheduled=NO; [mainWindow setDocumentEdited:YES]; [self addToLog:@"\rAppController: Starting Downloads" :nil]; - //Clean-Up Queue + //Clean-Up Queue NSArray *tempQueue = [queueController arrangedObjects]; for (Programme *show in tempQueue) { @@ -1742,31 +1755,31 @@ - (void)startDownloads:(id)sender proxyError:(NSError *)proxyError if (foundOne) { //Start First Download - IOPMAssertionCreateWithDescription(kIOPMAssertionTypePreventUserIdleSystemSleep, (CFStringRef)@"Downloading Show", (CFStringRef)@"GiA is downloading shows.", NULL, NULL, (double)0, NULL, &powerAssertionID); - - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + IOPMAssertionCreateWithDescription(kIOPMAssertionTypePreventUserIdleSystemSleep, (CFStringRef)@"Downloading Show", (CFStringRef)@"GiA is downloading shows.", NULL, NULL, (double)0, NULL, &powerAssertionID); + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(setPercentage:) name:@"setPercentage" object:nil]; [nc addObserver:self selector:@selector(setProgress:) name:@"setCurrentProgress" object:nil]; [nc addObserver:self selector:@selector(nextDownload:) name:@"DownloadFinished" object:nil]; - + tempQueue = [queueController arrangedObjects]; [self addToLog:[NSString stringWithFormat:@"\rDownloading Show %lu/%lu:\r", - (unsigned long)1, - (unsigned long)[tempQueue count]] - :nil]; + (unsigned long)1, + (unsigned long)[tempQueue count]] + :nil]; for (Programme *show in tempQueue) { if ([[show complete] isEqualToNumber:@NO]) { - if ([[show tvNetwork] hasPrefix:@"ITV"]) - currentDownload = [[ITVDownload alloc] initWithProgramme:show itvFormats:[itvFormatController arrangedObjects] proxy:proxy]; - /*else if ([[show tvNetwork] hasPrefix:@"4oD"]) - currentDownload = [[FourODDownload alloc] initWithProgramme:show proxy:proxy];*/ - else - currentDownload = [[BBCDownload alloc] initWithProgramme:show - tvFormats:[tvFormatController arrangedObjects] - radioFormats:[radioFormatController arrangedObjects] - proxy:proxy]; + if ([[show tvNetwork] hasPrefix:@"ITV"]) + currentDownload = [[ITVDownload alloc] initWithProgramme:show itvFormats:[itvFormatController arrangedObjects] proxy:proxy]; + /*else if ([[show tvNetwork] hasPrefix:@"4oD"]) + currentDownload = [[FourODDownload alloc] initWithProgramme:show proxy:proxy];*/ + else + currentDownload = [[BBCDownload alloc] initWithProgramme:show + tvFormats:[tvFormatController arrangedObjects] + radioFormats:[radioFormatController arrangedObjects] + proxy:proxy]; break; } } @@ -1783,26 +1796,26 @@ - (void)startDownloads:(id)sender proxyError:(NSError *)proxyError } else { - runDownloads=NO; - [mainWindow setDocumentEdited:NO]; + runDownloads=NO; + [mainWindow setDocumentEdited:NO]; if (!runScheduled) - [whatAnIdiot runModal]; - else if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"AutoRetryFailed"] boolValue]) - { - NSDate *scheduledDate = [NSDate dateWithTimeIntervalSinceNow:60*[[[NSUserDefaults standardUserDefaults] valueForKey:@"AutoRetryTime"] doubleValue]]; - [datePicker setDateValue:scheduledDate]; - [self scheduleStart:self]; - } - else if (runScheduled) - runScheduled=NO; + [whatAnIdiot runModal]; + else if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"AutoRetryFailed"] boolValue]) + { + NSDate *scheduledDate = [NSDate dateWithTimeIntervalSinceNow:60*[[[NSUserDefaults standardUserDefaults] valueForKey:@"AutoRetryTime"] doubleValue]]; + [datePicker setDateValue:scheduledDate]; + [self scheduleStart:self]; + } + else if (runScheduled) + runScheduled=NO; } } - (IBAction)stopDownloads:(id)sender { - IOPMAssertionRelease(powerAssertionID); - + IOPMAssertionRelease(powerAssertionID); + runDownloads=NO; - runScheduled=NO; + runScheduled=NO; [currentDownload cancelDownload:self]; [[currentDownload show] setStatus:@"Cancelled"]; if (!runUpdate) @@ -1817,15 +1830,15 @@ - (IBAction)stopDownloads:(id)sender } NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self name:@"setPercentage" object:nil]; - [nc removeObserver:self name:@"setCurrentProgress" object:nil]; - [nc removeObserver:self name:@"DownloadFinished" object:nil]; + [nc removeObserver:self name:@"setPercentage" object:nil]; + [nc removeObserver:self name:@"setCurrentProgress" object:nil]; + [nc removeObserver:self name:@"DownloadFinished" object:nil]; NSArray *tempQueue = [queueController arrangedObjects]; for (Programme *show in tempQueue) if ([[show status] isEqualToString:@"Waiting..."]) [show setStatus:@""]; - [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(fixDownloadStatus:) userInfo:currentDownload repeats:NO]; + [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(fixDownloadStatus:) userInfo:currentDownload repeats:NO]; } - (void)fixDownloadStatus:(NSNotification *)note { @@ -1839,14 +1852,14 @@ - (void)fixDownloadStatus:(NSNotification *)note NSLog(@"fixDownloadStatus handler did not run because downloads appear to be running again"); } - (void)setPercentage:(NSNotification *)note -{ +{ if ([note userInfo]) { NSDictionary *userInfo = [note userInfo]; [currentIndicator setIndeterminate:NO]; [currentIndicator startAnimation:nil]; - [currentIndicator setMinValue:0]; - [currentIndicator setMaxValue:100]; + [currentIndicator setMinValue:0]; + [currentIndicator setMaxValue:100]; [currentIndicator setDoubleValue:[[userInfo valueForKey:@"nsDouble"] doubleValue]]; } else @@ -1884,53 +1897,53 @@ - (void)nextDownload:(NSNotification *)note else [finishedShow setValue:@"Download Complete" forKey:@"status"]; - @try - { - [GrowlApplicationBridge notifyWithTitle:@"Download Finished" - description:[NSString stringWithFormat:@"%@ Completed Successfully",[finishedShow showName]] - notificationName:@"Download Finished" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; - } - @catch (NSException *e) { - NSLog(@"ERROR: Growl notification failed (nextDownload - finished): %@: %@", [e name], [e description]); - [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (nextDownload - finished): %@: %@", [e name], [e description]]]; - } - } + @try + { + [GrowlApplicationBridge notifyWithTitle:@"Download Finished" + description:[NSString stringWithFormat:@"%@ Completed Successfully",[finishedShow showName]] + notificationName:@"Download Finished" + iconData:nil + priority:0 + isSticky:NO + clickContext:nil]; + } + @catch (NSException *e) { + NSLog(@"ERROR: Growl notification failed (nextDownload - finished): %@: %@", [e name], [e description]); + [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (nextDownload - finished): %@: %@", [e name], [e description]]]; + } + } else { - @try - { - [GrowlApplicationBridge notifyWithTitle:@"Download Failed" - description:[NSString stringWithFormat:@"%@ failed. See log for details.",[finishedShow showName]] - notificationName:@"Download Failed" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; - } - @catch (NSException *e) { - NSLog(@"ERROR: Growl notification failed (nextDownload - failed): %@: %@", [e name], [e description]); - [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (nextDownload - failed): %@: %@", [e name], [e description]]]; - } - - ReasonForFailure *showSolution = [[ReasonForFailure alloc] init]; - [showSolution setShowName:[finishedShow showName]]; - [showSolution setSolution:[solutionsDictionary valueForKey:[finishedShow reasonForFailure]]]; - if (![showSolution solution]) - [showSolution setSolution:@"Problem Unknown.\nPlease submit a bug report from the application menu."]; - NSLog(@"Reason for Failure: %@", [finishedShow reasonForFailure]); - NSLog(@"Dictionary Lookup: %@", [solutionsDictionary valueForKey:[finishedShow reasonForFailure]]); - NSLog(@"Solution: %@", [showSolution solution]); - [solutionsArrayController addObject:showSolution]; - NSLog(@"Added Solution"); - [solutionsTableView setRowHeight:68]; + @try + { + [GrowlApplicationBridge notifyWithTitle:@"Download Failed" + description:[NSString stringWithFormat:@"%@ failed. See log for details.",[finishedShow showName]] + notificationName:@"Download Failed" + iconData:nil + priority:0 + isSticky:NO + clickContext:nil]; + } + @catch (NSException *e) { + NSLog(@"ERROR: Growl notification failed (nextDownload - failed): %@: %@", [e name], [e description]); + [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (nextDownload - failed): %@: %@", [e name], [e description]]]; + } + + ReasonForFailure *showSolution = [[ReasonForFailure alloc] init]; + [showSolution setShowName:[finishedShow showName]]; + [showSolution setSolution:[solutionsDictionary valueForKey:[finishedShow reasonForFailure]]]; + if (![showSolution solution]) + [showSolution setSolution:@"Problem Unknown.\nPlease submit a bug report from the application menu."]; + NSLog(@"Reason for Failure: %@", [finishedShow reasonForFailure]); + NSLog(@"Dictionary Lookup: %@", [solutionsDictionary valueForKey:[finishedShow reasonForFailure]]); + NSLog(@"Solution: %@", [showSolution solution]); + [solutionsArrayController addObject:showSolution]; + NSLog(@"Added Solution"); + [solutionsTableView setRowHeight:68]; } - - [self saveAppData]; //Save app data in case of crash. - + + [self saveAppData]; //Save app data in case of crash. + NSArray *tempQueue = [queueController arrangedObjects]; Programme *nextShow=nil; NSUInteger showNum=0; @@ -1951,27 +1964,27 @@ - (void)nextDownload:(NSNotification *)note [noneLeft raise]; } [self addToLog:[NSString stringWithFormat:@"\rDownloading Show %lu/%lu:\r", - (unsigned long)([tempQueue indexOfObject:nextShow]+1), - (unsigned long)[tempQueue count]] - :nil]; + (unsigned long)([tempQueue indexOfObject:nextShow]+1), + (unsigned long)[tempQueue count]] + :nil]; if ([[nextShow complete] isEqualToNumber:@NO]) - { - if ([[nextShow tvNetwork] hasPrefix:@"ITV"]) - currentDownload = [[ITVDownload alloc] initWithProgramme:nextShow itvFormats:[itvFormatController arrangedObjects] proxy:proxy]; - /*else if ([[nextShow tvNetwork] hasPrefix:@"4oD"]) - currentDownload = [[FourODDownload alloc] initWithProgramme:nextShow proxy:proxy];*/ - else - currentDownload = [[BBCDownload alloc] initWithProgramme:nextShow - tvFormats:[tvFormatController arrangedObjects] - radioFormats:[radioFormatController arrangedObjects] - proxy:proxy]; - } + { + if ([[nextShow tvNetwork] hasPrefix:@"ITV"]) + currentDownload = [[ITVDownload alloc] initWithProgramme:nextShow itvFormats:[itvFormatController arrangedObjects] proxy:proxy]; + /*else if ([[nextShow tvNetwork] hasPrefix:@"4oD"]) + currentDownload = [[FourODDownload alloc] initWithProgramme:nextShow proxy:proxy];*/ + else + currentDownload = [[BBCDownload alloc] initWithProgramme:nextShow + tvFormats:[tvFormatController arrangedObjects] + radioFormats:[radioFormatController arrangedObjects] + proxy:proxy]; + } } @catch (NSException *e) { //Downloads must be finished. - IOPMAssertionRelease(powerAssertionID); - + IOPMAssertionRelease(powerAssertionID); + [stopButton setEnabled:NO]; [startButton setEnabled:YES]; [currentProgress setStringValue:@""]; @@ -1981,9 +1994,9 @@ - (void)nextDownload:(NSNotification *)note [currentIndicator setIndeterminate:NO]; [self addToLog:@"\rAppController: Downloads Finished" :nil]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self name:@"setPercentage" object:nil]; - [nc removeObserver:self name:@"setCurrentProgress" object:nil]; - [nc removeObserver:self name:@"DownloadFinished" object:nil]; + [nc removeObserver:self name:@"setPercentage" object:nil]; + [nc removeObserver:self name:@"setCurrentProgress" object:nil]; + [nc removeObserver:self name:@"DownloadFinished" object:nil]; runDownloads=NO; [mainWindow setDocumentEdited:NO]; @@ -2002,25 +2015,25 @@ - (void)nextDownload:(NSNotification *)note } } tempQueue=nil; - @try - { - [GrowlApplicationBridge notifyWithTitle:@"Downloads Finished" - description:[NSString stringWithFormat:@"Downloads Successful = %lu\nDownload Failed = %lu", - (unsigned long)downloadsSuccessful,(unsigned long)downloadsFailed] - notificationName:@"Downloads Finished" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; - } - @catch (NSException *e) { - NSLog(@"ERROR: Growl notification failed (nextDownload - complete): %@: %@", [e name], [e description]); - [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (nextDownload - complete): %@: %@", [e name], [e description]]]; - } + @try + { + [GrowlApplicationBridge notifyWithTitle:@"Downloads Finished" + description:[NSString stringWithFormat:@"Downloads Successful = %lu\nDownload Failed = %lu", + (unsigned long)downloadsSuccessful,(unsigned long)downloadsFailed] + notificationName:@"Downloads Finished" + iconData:nil + priority:0 + isSticky:NO + clickContext:nil]; + } + @catch (NSException *e) { + NSLog(@"ERROR: Growl notification failed (nextDownload - complete): %@: %@", [e name], [e description]); + [self addToLog:[NSString stringWithFormat:@"ERROR: Growl notification failed (nextDownload - complete): %@: %@", [e name], [e description]]]; + } [[SUUpdater sharedUpdater] checkForUpdatesInBackground]; if (downloadsFailed>0) - [solutionsWindow makeKeyAndOrderFront:self]; + [solutionsWindow makeKeyAndOrderFront:self]; if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"AutoRetryFailed"] boolValue] && downloadsFailed>0) { NSDate *scheduledDate = [NSDate dateWithTimeIntervalSinceNow:60*[[[NSUserDefaults standardUserDefaults] valueForKey:@"AutoRetryTime"] doubleValue]]; @@ -2049,7 +2062,7 @@ - (IBAction)pvrSearch:(id)sender NSString *cacheExpiryArg = [self cacheExpiryArgument:nil]; NSString *typeArgument = [self typeArgument:nil]; NSArray *args = @[getiPlayerPath,noWarningArg,cacheExpiryArg,typeArgument,@"--nopurge", - @"--listformat=: , ~ - ~, , ",searchArgument,profileDirArg]; + @"--listformat=: , ~ - ~, , ",searchArgument,profileDirArg]; [pvrSearchTask setArguments:args]; [pvrSearchTask setStandardOutput:pvrSearchPipe]; @@ -2058,13 +2071,13 @@ - (IBAction)pvrSearch:(id)sender NSNotificationCenter *nc; nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self - selector:@selector(pvrSearchDataReady:) - name:NSFileHandleReadCompletionNotification - object:fh]; + selector:@selector(pvrSearchDataReady:) + name:NSFileHandleReadCompletionNotification + object:fh]; [nc addObserver:self - selector:@selector(pvrSearchFinished:) - name:NSTaskDidTerminateNotification - object:pvrSearchTask]; + selector:@selector(pvrSearchFinished:) + name:NSTaskDidTerminateNotification + object:pvrSearchTask]; pvrSearchData = [[NSMutableString alloc] init]; [pvrSearchTask launch]; [pvrSearchIndicator startAnimation:nil]; @@ -2074,12 +2087,12 @@ - (IBAction)pvrSearch:(id)sender - (void)pvrSearchDataReady:(NSNotification *)n { - NSData *d; - d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; + NSData *d; + d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; - if ([d length] > 0) { + if ([d length] > 0) { NSString *s = [[NSString alloc] initWithData:d - encoding:NSUTF8StringEncoding]; + encoding:NSUTF8StringEncoding]; [pvrSearchData appendString:s]; @@ -2089,9 +2102,9 @@ - (void)pvrSearchDataReady:(NSNotification *)n pvrSearchTask = nil; } - // If the task is running, start reading again - if (pvrSearchTask) - [[pvrSearchPipe fileHandleForReading] readInBackgroundAndNotify]; + // If the task is running, start reading again + if (pvrSearchTask) + [[pvrSearchPipe fileHandleForReading] readInBackgroundAndNotify]; } - (void)pvrSearchFinished:(NSNotification *)n { @@ -2103,7 +2116,7 @@ - (void)pvrSearchFinished:(NSNotification *)n NSRange currentRange; while (paraEnd < length) { [string getParagraphStart:¶Start end:¶End - contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; + contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); [array addObject:[string substringWithRange:currentRange]]; } @@ -2168,17 +2181,17 @@ - (IBAction)addToAutoRecord:(id)sender [show setValue:[programme timeadded] forKey:@"added"]; [show setValue:[programme tvNetwork] forKey:@"tvNetwork"]; [show setValue:[NSDate date] forKey:@"lastFound"]; - //Check to make sure the programme isn't already in the queue before adding it. - NSArray *queuedObjects = [pvrQueueController arrangedObjects]; - BOOL add=YES; - for (Programme *queuedShow in queuedObjects) - { - if ([[show showName] isEqualToString:[queuedShow showName]] && [show tvNetwork] == [queuedShow tvNetwork]) add=NO; - } - if (add) - { - [pvrQueueController addObject:show]; - } + //Check to make sure the programme isn't already in the queue before adding it. + NSArray *queuedObjects = [pvrQueueController arrangedObjects]; + BOOL add=YES; + for (Programme *queuedShow in queuedObjects) + { + if ([[show showName] isEqualToString:[queuedShow showName]] && [show tvNetwork] == [queuedShow tvNetwork]) add=NO; + } + if (add) + { + [pvrQueueController addObject:show]; + } } } - (IBAction)addSeriesLinkToQueue:(id)sender @@ -2213,18 +2226,18 @@ - (void)seriesLinkToQueueTimerSelector { if (!runDownloads) [currentProgress performSelectorOnMainThread:@selector(setStringValue:) withObject:[NSString stringWithFormat:@"Updating Series Link - %lu/%lu - %@",(unsigned long)[seriesLink indexOfObject:series]+1,(unsigned long)[seriesLink count],[series showName]] waitUntilDone:YES]; - if ([[series showName] length] == 0) { - [seriesToBeRemoved addObject:series]; - continue; - } else if ([[series tvNetwork] length] == 0) { - [series setTvNetwork:@"*"]; - } + if ([[series showName] length] == 0) { + [seriesToBeRemoved addObject:series]; + continue; + } else if ([[series tvNetwork] length] == 0) { + [series setTvNetwork:@"*"]; + } NSString *cacheExpiryArgument = [self cacheExpiryArgument:nil]; NSString *typeArgument = [self typeArgument:nil]; NSMutableArray *autoRecordArgs = [[NSMutableArray alloc] initWithObjects:getiPlayerPath, noWarningArg,@"--nopurge", - @"--listformat=: , ~ - ~, , , ,", cacheExpiryArgument, - typeArgument, profileDirArg,@"--hide",[self escapeSpecialCharactersInString:[series showName]],nil]; + @"--listformat=: , ~ - ~, , , ,", cacheExpiryArgument, + typeArgument, profileDirArg,@"--hide",[self escapeSpecialCharactersInString:[series showName]],nil]; NSTask *autoRecordTask = [[NSTask alloc] init]; NSPipe *autoRecordPipe = [[NSPipe alloc] init]; @@ -2259,14 +2272,14 @@ - (void)seriesLinkFinished:(NSNotification *)note [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NSThreadWillExitNotification" object:nil]; //If this is an update initiated by the scheduler, run the downloads. - if (runScheduled && !scheduleTimer) + if (runScheduled && !scheduleTimer) { [self performSelectorOnMainThread:@selector(startDownloads:) withObject:self waitUntilDone:NO]; } [self performSelectorOnMainThread:@selector(scheduleTimerForFinished:) withObject:nil waitUntilDone:NO]; NSLog(@"Series-Link Thread Finished"); } - + - (void)scheduleTimerForFinished:(id)sender { [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(seriesLinkFinished2:) userInfo:currentProgress repeats:NO]; @@ -2293,7 +2306,7 @@ - (BOOL)processAutoRecordData:(NSString *)autoRecordData2 forSeries:(Series *)se NSRange currentRange; while (paraEnd < length) { [string getParagraphStart:¶Start end:¶End - contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; + contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); [array addObject:[string substringWithRange:currentRange]]; } @@ -2318,8 +2331,8 @@ - (BOOL)processAutoRecordData:(NSString *)autoRecordData2 forSeries:(Series *)se [myScanner scanUpToString:@", " intoString:nil]; [myScanner scanString:@", " intoString:nil]; [myScanner scanUpToString:@"," intoString:&temp_realPID]; - [myScanner scanString:@"," intoString:nil]; - [myScanner scanUpToString:@"kjkjkj" intoString:&url]; + [myScanner scanString:@"," intoString:nil]; + [myScanner scanUpToString:@"kjkjkj" intoString:&url]; NSScanner *seriesEpisodeScanner = [NSScanner scannerWithString:temp_showName]; NSString *series_Name, *episode_Name; @@ -2335,41 +2348,41 @@ - (BOOL)processAutoRecordData:(NSString *)autoRecordData2 forSeries:(Series *)se temp_showName = [temp_showName stringByAppendingFormat:@" - %@", temp_showName2]; } if (([[series2 added] integerValue] > timeadded) && - ([temp_tvNetwork isEqualToString:[series2 tvNetwork]] || [[[series2 tvNetwork] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:@"*"] || [[series2 tvNetwork] length] == 0)) - { - [series2 setAdded:@(timeadded)]; - } + ([temp_tvNetwork isEqualToString:[series2 tvNetwork]] || [[[series2 tvNetwork] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:@"*"] || [[series2 tvNetwork] length] == 0)) + { + [series2 setAdded:@(timeadded)]; + } if (([[series2 added] integerValue] <= timeadded) && - ([temp_tvNetwork isEqualToString:[series2 tvNetwork]] || [[[series2 tvNetwork] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:@"*"] || [[series2 tvNetwork] length] == 0)) + ([temp_tvNetwork isEqualToString:[series2 tvNetwork]] || [[[series2 tvNetwork] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:@"*"] || [[series2 tvNetwork] length] == 0)) { - @try { - oneFound=YES; - Programme *p = [[Programme alloc] initWithInfo:nil pid:temp_pid programmeName:temp_showName network:temp_tvNetwork]; - [p setRealPID:temp_realPID]; - [p setSeriesName:series_Name]; - [p setEpisodeName:episode_Name]; - [p setUrl:url]; - if ([temp_type isEqualToString:@"radio"]) [p setValue:@YES forKey:@"radio"]; - else if ([temp_type isEqualToString:@"podcast"]) [p setPodcast:@YES]; - [p setValue:@"Added by Series-Link" forKey:@"status"]; - BOOL inQueue=NO; - for (Programme *show in currentQueue) - if ([[show showName] isEqualToString:[p showName]] && [[show pid] isEqualToString:[p pid]]) inQueue=YES; - if (!inQueue) - { - if (runDownloads) [p setValue:@"Waiting..." forKey:@"status"]; - [queueController performSelectorOnMainThread:@selector(addObject:) withObject:p waitUntilDone:NO]; - } - } - @catch (NSException *e) { - NSAlert *queueException = [[NSAlert alloc] init]; - [queueException addButtonWithTitle:@"OK"]; - [queueException setMessageText:[NSString stringWithFormat:@"Series-Link to Queue Transfer Failed"]]; - [queueException setInformativeText:@"The recording queue is in an unknown state. Please restart GiA and clear the recording queue."]; - [queueException setAlertStyle:NSWarningAlertStyle]; - [queueException runModal]; - queueException = nil; - } + @try { + oneFound=YES; + Programme *p = [[Programme alloc] initWithInfo:nil pid:temp_pid programmeName:temp_showName network:temp_tvNetwork]; + [p setRealPID:temp_realPID]; + [p setSeriesName:series_Name]; + [p setEpisodeName:episode_Name]; + [p setUrl:url]; + if ([temp_type isEqualToString:@"radio"]) [p setValue:@YES forKey:@"radio"]; + else if ([temp_type isEqualToString:@"podcast"]) [p setPodcast:@YES]; + [p setValue:@"Added by Series-Link" forKey:@"status"]; + BOOL inQueue=NO; + for (Programme *show in currentQueue) + if ([[show showName] isEqualToString:[p showName]] && [[show pid] isEqualToString:[p pid]]) inQueue=YES; + if (!inQueue) + { + if (runDownloads) [p setValue:@"Waiting..." forKey:@"status"]; + [queueController performSelectorOnMainThread:@selector(addObject:) withObject:p waitUntilDone:NO]; + } + } + @catch (NSException *e) { + NSAlert *queueException = [[NSAlert alloc] init]; + [queueException addButtonWithTitle:@"OK"]; + [queueException setMessageText:[NSString stringWithFormat:@"Series-Link to Queue Transfer Failed"]]; + [queueException setInformativeText:@"The recording queue is in an unknown state. Please restart GiA and clear the recording queue."]; + [queueException setAlertStyle:NSWarningAlertStyle]; + [queueException runModal]; + queueException = nil; + } } } @catch (NSException *e) { @@ -2408,27 +2421,27 @@ - (BOOL)processAutoRecordData:(NSString *)autoRecordData2 forSeries:(Series *)se #pragma mark Misc. - (void)saveAppData { - //Save Queue & Series-Link + //Save Queue & Series-Link NSMutableArray *tempQueue = [[NSMutableArray alloc] initWithArray:[queueController arrangedObjects]]; NSMutableArray *tempSeries = [[NSMutableArray alloc] initWithArray:[pvrQueueController arrangedObjects]]; NSMutableArray *temptempQueue = [[NSMutableArray alloc] initWithArray:tempQueue]; for (Programme *show in temptempQueue) { if (([[show complete] isEqualToNumber:@YES] && [[show successful] isEqualToNumber:@YES]) - || [[show status] isEqualToString:@"Added by Series-Link"]) [tempQueue removeObject:show]; + || [[show status] isEqualToString:@"Added by Series-Link"]) [tempQueue removeObject:show]; } NSMutableArray *temptempSeries = [[NSMutableArray alloc] initWithArray:tempSeries]; for (Series *series in temptempSeries) { - if ([[series showName] length] == 0) { - [tempSeries removeObject:series]; - } else if ([[series tvNetwork] length] == 0) { - [series setTvNetwork:@"*"]; - } - + if ([[series showName] length] == 0) { + [tempSeries removeObject:series]; + } else if ([[series tvNetwork] length] == 0) { + [series setTvNetwork:@"*"]; + } + } NSFileManager *fileManager = [NSFileManager defaultManager]; - + NSString *folder = @"~/Library/Application Support/Get iPlayer Automator/"; folder = [folder stringByExpandingTildeInPath]; if ([fileManager fileExistsAtPath: folder] == NO) @@ -2440,10 +2453,10 @@ - (void)saveAppData NSMutableDictionary * rootObject; rootObject = [NSMutableDictionary dictionary]; - + [rootObject setValue:tempQueue forKey:@"queue"]; [rootObject setValue:tempSeries forKey:@"serieslink"]; - [rootObject setValue:lastUpdate forKey:@"lastUpdate"]; + [rootObject setValue:lastUpdate forKey:@"lastUpdate"]; [NSKeyedArchiver archiveRootObject: rootObject toFile: filePath]; filename = @"Formats.automatorqueue"; @@ -2453,48 +2466,48 @@ - (void)saveAppData [rootObject setValue:[tvFormatController arrangedObjects] forKey:@"tvFormats"]; [rootObject setValue:[radioFormatController arrangedObjects] forKey:@"radioFormats"]; - [rootObject setValue:@YES forKey:@"hasUpdatedCacheFor4oD"]; + [rootObject setValue:@YES forKey:@"hasUpdatedCacheFor4oD"]; [NSKeyedArchiver archiveRootObject:rootObject toFile:filePath]; - - filename = @"ITVFormats.automator"; - filePath = [folder stringByAppendingPathComponent:filename]; - rootObject = [NSMutableDictionary dictionary]; - [rootObject setValue:[itvFormatController arrangedObjects] forKey:@"itvFormats"]; - [NSKeyedArchiver archiveRootObject:rootObject toFile:filePath]; - - //Store Preferences in case of crash - [[NSUserDefaults standardUserDefaults] synchronize]; + + filename = @"ITVFormats.automator"; + filePath = [folder stringByAppendingPathComponent:filename]; + rootObject = [NSMutableDictionary dictionary]; + [rootObject setValue:[itvFormatController arrangedObjects] forKey:@"itvFormats"]; + [NSKeyedArchiver archiveRootObject:rootObject toFile:filePath]; + + //Store Preferences in case of crash + [[NSUserDefaults standardUserDefaults] synchronize]; } - (IBAction)closeWindow:(id)sender { - if ([logWindow isKeyWindow]) [logWindow performClose:self]; - else if ([historyWindow isKeyWindow]) [historyWindow performClose:self]; - else if ([pvrPanel isKeyWindow]) [pvrPanel performClose:self]; - else if ([prefsPanel isKeyWindow]) [prefsPanel performClose:self]; - else if ([mainWindow isKeyWindow]) - { - NSAlert *downloadAlert = [NSAlert alertWithMessageText:@"Are you sure you wish to quit?" - defaultButton:@"Yes" - alternateButton:@"No" - otherButton:nil - informativeTextWithFormat:nil]; - NSInteger response = [downloadAlert runModal]; - if (response == NSAlertDefaultReturn) [mainWindow performClose:self]; - } + if ([logWindow isKeyWindow]) [logWindow performClose:self]; + else if ([historyWindow isKeyWindow]) [historyWindow performClose:self]; + else if ([pvrPanel isKeyWindow]) [pvrPanel performClose:self]; + else if ([prefsPanel isKeyWindow]) [prefsPanel performClose:self]; + else if ([mainWindow isKeyWindow]) + { + NSAlert *downloadAlert = [NSAlert alertWithMessageText:@"Are you sure you wish to quit?" + defaultButton:@"Yes" + alternateButton:@"No" + otherButton:nil + informativeTextWithFormat:nil]; + NSInteger response = [downloadAlert runModal]; + if (response == NSAlertDefaultReturn) [mainWindow performClose:self]; + } } - (NSString *)escapeSpecialCharactersInString:(NSString *)string { - NSArray *characters = @[@"+",@"-",@"&",@"!",@"(",@")",@"{",@"}", + NSArray *characters = @[@"+",@"-",@"&",@"!",@"(",@")",@"{",@"}", @"[",@"]"@"^",@"~",@"*",@"?",@":",@"\""]; - for (NSString *character in characters) - string = [string stringByReplacingOccurrencesOfString:character withString:[NSString stringWithFormat:@"\\%@",character]]; - - return string; + for (NSString *character in characters) + string = [string stringByReplacingOccurrencesOfString:character withString:[NSString stringWithFormat:@"\\%@",character]]; + + return string; } - (void)thirtyTwoBitModeAlert { - if ([[NSAlert alertWithMessageText:@"File could not be added to iTunes," defaultButton:@"Help Me!" alternateButton:@"Do nothing" otherButton:nil informativeTextWithFormat:@"This is usually fixed by running iTunes in 32-bit mode. Would you like instructions to do this?"] runModal] == NSAlertDefaultReturn) - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://support.apple.com/kb/TS3771"]]; + if ([[NSAlert alertWithMessageText:@"File could not be added to iTunes," defaultButton:@"Help Me!" alternateButton:@"Do nothing" otherButton:nil informativeTextWithFormat:@"This is usually fixed by running iTunes in 32-bit mode. Would you like instructions to do this?"] runModal] == NSAlertDefaultReturn) + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://support.apple.com/kb/TS3771"]]; } - (void)addToiTunes:(Programme *)show { @@ -2512,7 +2525,7 @@ - (void)addToiTunes:(Programme *)show if ([ext isEqualToString:@"mov"] || [ext isEqualToString:@"mp4"] || [ext isEqualToString:@"mp3"] || [ext isEqualToString:@"m4a"]) { iTunesTrack *track = [iTunes add:fileToAdd to:nil]; - NSLog(@"Track exists = %@", ([track exists] ? @"YES" : @"NO")); + NSLog(@"Track exists = %@", ([track exists] ? @"YES" : @"NO")); if ([track exists] && ([ext isEqualToString:@"mov"] || [ext isEqualToString:@"mp4"])) { if ([ext isEqualToString:@"mov"]) @@ -2525,21 +2538,21 @@ - (void)addToiTunes:(Programme *)show if ([show episode]>0) [track setEpisodeNumber:[show episode]]; } [track setUnplayed:YES]; - [show setValue:@"Complete & in iTunes" forKey:@"status"]; + [show setValue:@"Complete & in iTunes" forKey:@"status"]; } else if ([track exists] && ([ext isEqualToString:@"mp3"] || [ext isEqualToString:@"m4a"])) { [track setBookmarkable:YES]; [track setUnplayed:YES]; - [show setValue:@"Complete & in iTunes" forKey:@"status"]; + [show setValue:@"Complete & in iTunes" forKey:@"status"]; } else - { - [self performSelectorOnMainThread:@selector(addToLog:) withObject:@"iTunes did not accept file." waitUntilDone:YES]; - [self performSelectorOnMainThread:@selector(addToLog:) withObject:@"Try setting iTunes to open in 32-bit mode." waitUntilDone:YES]; - [self performSelectorOnMainThread:@selector(thirtyTwoBitModeAlert) withObject:nil waitUntilDone:NO]; - [show setValue:@"Complete: Not in iTunes" forKey:@"status"]; - } + { + [self performSelectorOnMainThread:@selector(addToLog:) withObject:@"iTunes did not accept file." waitUntilDone:YES]; + [self performSelectorOnMainThread:@selector(addToLog:) withObject:@"Try setting iTunes to open in 32-bit mode." waitUntilDone:YES]; + [self performSelectorOnMainThread:@selector(thirtyTwoBitModeAlert) withObject:nil waitUntilDone:NO]; + [show setValue:@"Complete: Not in iTunes" forKey:@"status"]; + } } else { @@ -2551,20 +2564,20 @@ - (void)addToiTunes:(Programme *)show @catch (NSException *e) { [self performSelectorOnMainThread:@selector(addToLog:) withObject:@"Unable to Add to iTunes" waitUntilDone:YES]; - NSLog(@"Unable %@ to iTunes",show); + NSLog(@"Unable %@ to iTunes",show); [show setValue:@"Complete, Could not add to iTunes." forKey:@"status"]; } } - (void)cleanUpPath:(Programme *)show { - + //Process Show Name into Parts NSString *originalShowName, *originalEpisodeName; NSScanner *nameScanner = [NSScanner scannerWithString:[show showName]]; [nameScanner scanUpToString:@" - " intoString:&originalShowName]; [nameScanner scanString:@"-" intoString:nil]; [nameScanner scanUpToString:@"Scan to End" intoString:&originalEpisodeName]; - + //Replace :'s with -'s NSString *showName = [originalShowName stringByReplacingOccurrencesOfString:@":" withString:@" -"]; @@ -2626,7 +2639,7 @@ - (IBAction)chooseDownloadPath:(id)sender [openPanel setCanChooseFiles:NO]; [openPanel setCanChooseDirectories:YES]; [openPanel setAllowsMultipleSelection:NO]; - [openPanel setCanCreateDirectories:YES]; + [openPanel setCanCreateDirectories:YES]; [openPanel runModal]; NSArray *urls = [openPanel URLs]; [[NSUserDefaults standardUserDefaults] setValue:[urls[0] path] forKey:@"DownloadPath"]; @@ -2636,7 +2649,7 @@ - (IBAction)showFeedback:(id)sender [JRFeedbackController showFeedback]; } - (IBAction)restoreDefaults:(id)sender -{ +{ NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults]; [sharedDefaults removeObjectForKey:@"DownloadPath"]; [sharedDefaults removeObjectForKey:@"Proxy"]; @@ -2651,7 +2664,7 @@ - (IBAction)restoreDefaults:(id)sender [sharedDefaults removeObjectForKey:@"CacheITV_TV"]; [sharedDefaults removeObjectForKey:@"CacheBBC_Radio"]; [sharedDefaults removeObjectForKey:@"CacheBBC_Podcasts"]; - [sharedDefaults removeObjectForKey:@"Cache4oD_TV"]; + [sharedDefaults removeObjectForKey:@"Cache4oD_TV"]; [sharedDefaults removeObjectForKey:@"CacheExpiryTime"]; [sharedDefaults removeObjectForKey:@"Verbose"]; [sharedDefaults removeObjectForKey:@"SeriesLinkStartup"]; @@ -2661,8 +2674,13 @@ - (IBAction)restoreDefaults:(id)sender } - (void)applescriptStartDownloads { - runScheduled=YES; - [self forceUpdate:self]; + runScheduled=YES; + [self forceUpdate:self]; +} + ++ (AppController *)sharedController +{ + return sharedController; } #pragma mark Argument Retrieval - (NSString *)typeArgument:(id)sender @@ -2671,15 +2689,15 @@ - (NSString *)typeArgument:(id)sender { NSMutableString *typeArgument = [[NSMutableString alloc] initWithString:@"--type="]; if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"CacheBBC_TV"] isEqualTo:@YES]) - [typeArgument appendString:@"tv,"]; + [typeArgument appendString:@"tv,"]; if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"CacheITV_TV"] isEqualTo:@YES]) - [typeArgument appendString:@"itv,"]; + [typeArgument appendString:@"itv,"]; if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"CacheBBC_Radio"] isEqualTo:@YES]) - [typeArgument appendString:@"radio,"]; + [typeArgument appendString:@"radio,"]; if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"CacheBBC_Podcasts"] isEqualTo:@YES]) - [typeArgument appendString:@"podcast,"]; - if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"Cache4oD_TV"] isEqualTo:@YES]) - [typeArgument appendString:@"ch4,"]; + [typeArgument appendString:@"podcast,"]; + if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"Cache4oD_TV"] isEqualTo:@YES]) + [typeArgument appendString:@"ch4,"]; [typeArgument deleteCharactersInRange:NSMakeRange([typeArgument length]-1,1)]; currentTypeArgument = [typeArgument copy]; return [NSString stringWithString:typeArgument]; @@ -2709,11 +2727,11 @@ - (IBAction)showScheduleWindow:(id)sender } else { - NSAlert *alert = [NSAlert alertWithMessageText:@"Downloads are already running." - defaultButton:@"OK" - alternateButton:nil - otherButton:nil - informativeTextWithFormat:@"You cannot schedule downloads to start if they are already running."]; + NSAlert *alert = [NSAlert alertWithMessageText:@"Downloads are already running." + defaultButton:@"OK" + alternateButton:nil + otherButton:nil + informativeTextWithFormat:@"You cannot schedule downloads to start if they are already running."]; [alert runModal]; } } @@ -2724,17 +2742,17 @@ - (IBAction)cancelSchedule:(id)sender - (IBAction)scheduleStart:(id)sender { NSDate *startTime = [datePicker dateValue]; - scheduleTimer = [[NSTimer alloc] initWithFireDate:startTime - interval:1 - target:self - selector:@selector(runScheduledDownloads:) - userInfo:nil - repeats:NO]; + scheduleTimer = [[NSTimer alloc] initWithFireDate:startTime + interval:1 + target:self + selector:@selector(runScheduledDownloads:) + userInfo:nil + repeats:NO]; interfaceTimer = [NSTimer scheduledTimerWithTimeInterval:1 - target:self - selector:@selector(updateScheduleStatus:) - userInfo:nil - repeats:YES]; + target:self + selector:@selector(updateScheduleStatus:) + userInfo:nil + repeats:YES]; if ([scheduleWindow isVisible]) [scheduleWindow close]; [startButton setEnabled:NO]; @@ -2766,8 +2784,8 @@ - (void)updateScheduleStatus:(NSTimer *)theTimer NSDateComponents *conversionInfo = [[NSCalendar currentCalendar] components:unitFlags fromDate:currentTime toDate:startTime options:0]; NSString *status = [NSString stringWithFormat:@"Time until Start (DD:HH:MM:SS): %02ld:%02ld:%02ld:%02ld", - (long)[conversionInfo day], (long)[conversionInfo hour], - (long)[conversionInfo minute],(long)[conversionInfo second]]; + (long)[conversionInfo day], (long)[conversionInfo hour], + (long)[conversionInfo minute],(long)[conversionInfo second]]; if (!runUpdate) [currentProgress setStringValue:status]; [currentIndicator setIndeterminate:YES]; @@ -2797,11 +2815,11 @@ - (IBAction)showLiveTVWindow:(id)sender } else { - NSAlert *downloadRunning = [NSAlert alertWithMessageText:@"Downloads are Running!" - defaultButton:@"Continue" - alternateButton:@"Cancel" - otherButton:nil - informativeTextWithFormat:@"You may experience choppy playback while downloads are running."]; + NSAlert *downloadRunning = [NSAlert alertWithMessageText:@"Downloads are Running!" + defaultButton:@"Continue" + alternateButton:@"Cancel" + otherButton:nil + informativeTextWithFormat:@"You may experience choppy playback while downloads are running."]; NSInteger response = [downloadRunning runModal]; if (response == NSAlertDefaultReturn) { @@ -2812,13 +2830,13 @@ - (IBAction)showLiveTVWindow:(id)sender - (IBAction)startLiveTV:(id)sender { - [self loadProxyInBackgroundForSelector:@selector(startLiveTV:proxyError:) withObject:sender]; + [self loadProxyInBackgroundForSelector:@selector(startLiveTV:proxyError:) withObject:sender]; } - (IBAction)startLiveTV:(id)sender proxyError:(NSError *)proxyError { - if ([proxyError code] == kProxyLoadCancelled) - return; + if ([proxyError code] == kProxyLoadCancelled) + return; getiPlayerStreamer = [[NSTask alloc] init]; mplayerStreamer = [[NSTask alloc] init]; liveTVPipe = [[NSPipe alloc] init]; @@ -2838,26 +2856,26 @@ - (IBAction)startLiveTV:(id)sender proxyError:(NSError *)proxyError //Set Proxy Arguments NSString *proxyArg = NULL; NSString *partialProxyArg = NULL; - if (proxy) - { - proxyArg = [[NSString alloc] initWithFormat:@"-p%@", [proxy url]]; - if (![[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) - { - partialProxyArg = @"--partial-proxy"; - } - } - - //Prepare Arguments + if (proxy) + { + proxyArg = [[NSString alloc] initWithFormat:@"-p%@", [proxy url]]; + if (![[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) + { + partialProxyArg = @"--partial-proxy"; + } + } + + //Prepare Arguments NSArray *args = @[[[NSBundle mainBundle] pathForResource:@"get_iplayer" ofType:@"pl"], - profileDirArg, - @"--stream", - @"--modes=flashnormal", - @"--type=livetv", - [selectedChannel channel], - //@"--player=mplayer -cache 3072 -", - // [NSString stringWithFormat:@"--player=\"%@\" -cache 3072 -", [[NSBundle mainBundle] pathForResource:@"mplayer" ofType:nil]], - proxyArg, - partialProxyArg]; + profileDirArg, + @"--stream", + @"--modes=flashnormal", + @"--type=livetv", + [selectedChannel channel], + //@"--player=mplayer -cache 3072 -", + // [NSString stringWithFormat:@"--player=\"%@\" -cache 3072 -", [[NSBundle mainBundle] pathForResource:@"mplayer" ofType:nil]], + proxyArg, + partialProxyArg]; [getiPlayerStreamer setArguments:args]; [mplayerStreamer setArguments:@[@"-cache",@"3072",@"-"]]; @@ -2880,280 +2898,378 @@ - (IBAction)stopLiveTV:(id)sender #pragma mark Proxy - (void)loadProxyInBackgroundForSelector:(SEL)selector withObject:(id)object { - [self updateProxyLoadStatus:YES message:@"Loading proxy settings..."]; - NSLog(@"INFO: Loading proxy settings..."); - [self addToLog:@"\n\nINFO: Loading proxy settings..."]; - [proxyDict removeAllObjects]; - proxyDict[@"selector"] = [NSValue valueWithPointer:selector]; - if (object) - proxyDict[@"object"] = object; - proxy = nil; - NSString *proxyOption = [[NSUserDefaults standardUserDefaults] valueForKey:@"Proxy"]; + [self loadProxyInBackgroundForSelector:selector withObject:object onTarget:self]; +} + +- (void)loadProxyInBackgroundForSelector:(SEL)selector withObject:(id)object onTarget:(id)target +{ + [self updateProxyLoadStatus:YES message:@"Loading proxy settings..."]; + NSLog(@"INFO: Loading proxy settings..."); + [self addToLog:@"\n\nINFO: Loading proxy settings..."]; + [proxyDict removeAllObjects]; + proxyDict[@"selector"] = [NSValue valueWithPointer:selector]; + proxyDict[@"target"] = target; + if (object) + proxyDict[@"object"] = object; + proxy = nil; + NSString *proxyOption = [[NSUserDefaults standardUserDefaults] valueForKey:@"Proxy"]; if ([proxyOption isEqualToString:@"Custom"]) { - NSString *customProxy = [[NSUserDefaults standardUserDefaults] valueForKey:@"CustomProxy"]; - NSLog(@"INFO: Custom Proxy: address=[%@] length=%ld", customProxy, [customProxy length]); - [self addToLog:[NSString stringWithFormat:@"INFO: Custom Proxy: address=[%@] length=%ld", customProxy, [customProxy length]]]; - NSString *proxyValue = [[customProxy lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if ([proxyValue length] == 0) - { - NSLog(@"WARNING: Custom proxy setting was blank. No proxy will be used."); - [self addToLog:@"WARNING: Custom proxy setting was blank. No proxy will be used."]; - if (!runScheduled) + NSString *customProxy = [[NSUserDefaults standardUserDefaults] valueForKey:@"CustomProxy"]; + NSLog(@"INFO: Custom Proxy: address=[%@] length=%ld", customProxy, [customProxy length]); + [self addToLog:[NSString stringWithFormat:@"INFO: Custom Proxy: address=[%@] length=%ld", customProxy, [customProxy length]]]; + NSString *proxyValue = [[customProxy lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if ([proxyValue length] == 0) + { + NSLog(@"WARNING: Custom proxy setting was blank. No proxy will be used."); + [self addToLog:@"WARNING: Custom proxy setting was blank. No proxy will be used."]; + if (!runScheduled) + { + NSAlert *alert = [NSAlert alertWithMessageText:@"Custom proxy setting was blank.\nDownloads may fail.\nDo you wish to continue?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@""]; + [alert setAlertStyle:NSCriticalAlertStyle]; + if ([alert runModal] == NSAlertDefaultReturn) { - NSAlert *alert = [NSAlert alertWithMessageText:@"Custom proxy setting was blank.\nDownloads may fail.\nDo you wish to continue?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@""]; - [alert setAlertStyle:NSCriticalAlertStyle]; - if ([alert runModal] == NSAlertDefaultReturn) - { - [self cancelProxyLoad]; - } - else - { - [self failProxyLoad]; - } + [self cancelProxyLoad]; + } + else + { + [self failProxyLoad]; } - } - else - { - proxy = [[HTTPProxy alloc] initWithString:proxyValue]; - [self finishProxyLoad]; - } + } + } + else + { + proxy = [[HTTPProxy alloc] initWithString:proxyValue]; + [self finishProxyLoad]; + } } else if ([proxyOption isEqualToString:@"Provided"]) { - ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://tom-tech.com/get_iplayer/proxy.txt"]]; - [request setUserInfo:@{@"selector": [NSValue valueWithPointer:selector], @"object": object}]; - [request setDelegate:self]; - [request setDidFailSelector:@selector(providedProxyDidFinish:)]; - [request setDidFinishSelector:@selector(providedProxyDidFinish:)]; - [request setTimeOutSeconds:10]; - [request setNumberOfTimesToRetryOnTimeout:2]; - [self updateProxyLoadStatus:YES message:[NSString stringWithFormat:@"Loading provided proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]]]; - NSLog(@"INFO: Loading provided proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]); - [self addToLog:[NSString stringWithFormat:@"INFO: Loading provided proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]*2]]; - [request startAsynchronous]; - } - else - { - NSLog(@"INFO: No proxy to load"); - [self addToLog:@"INFO: No proxy to load"]; - [self finishProxyLoad]; - } + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://tom-tech.com/get_iplayer/proxy.txt"]]; + [request setUserInfo:@{@"selector": [NSValue valueWithPointer:selector], @"object": object}]; + [request setDelegate:self]; + [request setDidFailSelector:@selector(providedProxyDidFinish:)]; + [request setDidFinishSelector:@selector(providedProxyDidFinish:)]; + [request setTimeOutSeconds:10]; + [request setNumberOfTimesToRetryOnTimeout:2]; + [self updateProxyLoadStatus:YES message:[NSString stringWithFormat:@"Loading provided proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]]]; + NSLog(@"INFO: Loading provided proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]); + [self addToLog:[NSString stringWithFormat:@"INFO: Loading provided proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]*2]]; + [request startAsynchronous]; + } + else + { + NSLog(@"INFO: No proxy to load"); + [self addToLog:@"INFO: No proxy to load"]; + [self finishProxyLoad]; + } } - (void)providedProxyDidFinish:(ASIHTTPRequest *)request { - NSData *urlData = [request responseData]; - if ([request responseStatusCode] != 200 || !urlData) - { - NSLog(@"WARNING: Provided proxy could not be retrieved. No proxy will be used."); - [self addToLog:@"WARNING: Provided proxy could not be retrieved. No proxy will be used."]; - if (!runScheduled) - { - NSError *error = [request error]; - NSAlert *alert = [NSAlert alertWithMessageText:@"Provided proxy could not be retrieved.\nDownloads may fail.\nDo you wish to continue?" + NSData *urlData = [request responseData]; + if ([request responseStatusCode] != 200 || !urlData) + { + NSLog(@"WARNING: Provided proxy could not be retrieved. No proxy will be used."); + [self addToLog:@"WARNING: Provided proxy could not be retrieved. No proxy will be used."]; + if (!runScheduled) + { + NSError *error = [request error]; + NSAlert *alert = [NSAlert alertWithMessageText:@"Provided proxy could not be retrieved.\nDownloads may fail.\nDo you wish to continue?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@"Error: %@", (error ? [error localizedDescription] : @"Unknown error")]; + [alert setAlertStyle:NSCriticalAlertStyle]; + if ([alert runModal] == NSAlertDefaultReturn) + [self cancelProxyLoad]; + else + [self failProxyLoad]; + } + } + else + { + NSString *proxyValue = [[[[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding] lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if ([proxyValue length] == 0) + { + NSLog(@"WARNING: Provided proxy value was blank. No proxy will be used."); + [self addToLog:@"WARNING: Provided proxy value was blank. No proxy will be used."]; + if (!runScheduled) + { + NSAlert *alert = [NSAlert alertWithMessageText:@"Provided proxy value was blank.\nDownloads may fail.\nDo you wish to continue?" defaultButton:@"No" alternateButton:@"Yes" otherButton:nil - informativeTextWithFormat:@"Error: %@", (error ? [error localizedDescription] : @"Unknown error")]; + informativeTextWithFormat:@""]; [alert setAlertStyle:NSCriticalAlertStyle]; if ([alert runModal] == NSAlertDefaultReturn) - [self cancelProxyLoad]; + [self cancelProxyLoad]; else - [self failProxyLoad]; - } - } - else - { - NSString *proxyValue = [[[[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding] lowercaseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if ([proxyValue length] == 0) - { - NSLog(@"WARNING: Provided proxy value was blank. No proxy will be used."); - [self addToLog:@"WARNING: Provided proxy value was blank. No proxy will be used."]; - if (!runScheduled) - { - NSAlert *alert = [NSAlert alertWithMessageText:@"Provided proxy value was blank.\nDownloads may fail.\nDo you wish to continue?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@""]; - [alert setAlertStyle:NSCriticalAlertStyle]; - if ([alert runModal] == NSAlertDefaultReturn) - [self cancelProxyLoad]; - else - [self failProxyLoad]; - } - } - else - { - proxy = [[HTTPProxy alloc] initWithString:proxyValue]; - [self finishProxyLoad]; - } - } + [self failProxyLoad]; + } + } + else + { + proxy = [[HTTPProxy alloc] initWithString:proxyValue]; + [self finishProxyLoad]; + } + } } - (void)cancelProxyLoad { - [self returnFromProxyLoadWithError:[NSError errorWithDomain:@"Proxy" code:kProxyLoadCancelled userInfo:@{NSLocalizedDescriptionKey: @"Proxy Load Cancelled"}]]; + [self returnFromProxyLoadWithError:[NSError errorWithDomain:@"Proxy" code:kProxyLoadCancelled userInfo:@{NSLocalizedDescriptionKey: @"Proxy Load Cancelled"}]]; } - (void)failProxyLoad { - [self returnFromProxyLoadWithError:[NSError errorWithDomain:@"Proxy" code:kProxyLoadFailed userInfo:@{NSLocalizedDescriptionKey: @"Proxy Load Failed"}]]; + [self returnFromProxyLoadWithError:[NSError errorWithDomain:@"Proxy" code:kProxyLoadFailed userInfo:@{NSLocalizedDescriptionKey: @"Proxy Load Failed"}]]; } - (void)finishProxyLoad { - NSLog(@"INFO: Proxy load complete."); - [self addToLog:@"INFO: Proxy load complete."]; - if (proxy && [[NSUserDefaults standardUserDefaults] boolForKey:@"TestProxy"]) - { - [self testProxyOnLoad]; - return; - } - [self returnFromProxyLoadWithError:nil]; + NSLog(@"INFO: Proxy load complete."); + [self addToLog:@"INFO: Proxy load complete."]; + if (proxy && [[NSUserDefaults standardUserDefaults] boolForKey:@"TestProxy"]) + { + [self testProxyOnLoad]; + return; + } + [self returnFromProxyLoadWithError:nil]; } - (void)testProxyOnLoad { - if (proxy) - { - if (!proxy.host || [proxy.host length] == 0 || [proxy.host rangeOfString:@"(null)"].location != NSNotFound) - { - NSLog(@"WARNING: Invalid proxy host: address=%@ length=%ld", proxy.host, [proxy.host length]); - [self addToLog:[NSString stringWithFormat:@"WARNING: Invalid proxy host: address=%@ length=%ld", proxy.host, [proxy.host length]]]; - if (!runScheduled) - { - NSAlert *alert = [NSAlert alertWithMessageText:@"Invalid proxy host.\nDownloads may fail.\nDo you wish to continue?" - defaultButton:@"No" - alternateButton:@"Yes" - otherButton:nil - informativeTextWithFormat:@"Invalid proxy host: address=[%@] length=%ld", proxy.host, [proxy.host length]]; - [alert setAlertStyle:NSCriticalAlertStyle]; - if ([alert runModal] == NSAlertDefaultReturn) - [self cancelProxyLoad]; - else - [self failProxyTest]; - } - return; - } - NSString *testURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"ProxyTestURL"]; - if (!testURL) - testURL = @"http://www.google.com"; - ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:testURL]]; - [request setDelegate:self]; - [request setDidFailSelector:@selector(proxyTestDidFinish:)]; - [request setDidFinishSelector:@selector(proxyTestDidFinish:)]; - [request setTimeOutSeconds:30]; - [request setProxyType:proxy.type]; - [request setProxyHost:proxy.host]; - if (proxy.port) { - [request setProxyPort:proxy.port]; - } else { - if ([proxy.type isEqualToString:(NSString *)kCFProxyTypeHTTPS]) { - [request setProxyPort:443]; - } else { - [request setProxyPort:80]; - } - } - if (proxy.user) { - [request setProxyUsername:proxy.user]; - [request setProxyPassword:proxy.password]; - } - [self updateProxyLoadStatus:YES message:[NSString stringWithFormat:@"Testing proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]]]; - NSLog(@"INFO: Testing proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]); - [self addToLog:[NSString stringWithFormat:@"INFO: Testing proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]]]; - [request startAsynchronous]; - } - else - { - NSLog(@"INFO: No proxy to test"); - [self addToLog:@"INFO: No proxy to test"]; - [self finishProxyTest]; - } -} - -- (void)proxyTestDidFinish:(ASIHTTPRequest *)request -{ - if ([request responseStatusCode] != 200) - { - NSLog(@"WARNING: Proxy failed to load test page: %@", [request url]); - [self addToLog:[NSString stringWithFormat:@"WARNING: Proxy failed to load test page: %@", [request url]]]; - if (!runScheduled) - { - NSError *error = [request error]; - NSAlert *alert = [NSAlert alertWithMessageText:@"Proxy failed to load test page.\nDownloads may fail.\nDo you wish to continue?" + if (proxy) + { + if (!proxy.host || [proxy.host length] == 0 || [proxy.host rangeOfString:@"(null)"].location != NSNotFound) + { + NSLog(@"WARNING: Invalid proxy host: address=%@ length=%ld", proxy.host, [proxy.host length]); + [self addToLog:[NSString stringWithFormat:@"WARNING: Invalid proxy host: address=%@ length=%ld", proxy.host, [proxy.host length]]]; + if (!runScheduled) + { + NSAlert *alert = [NSAlert alertWithMessageText:@"Invalid proxy host.\nDownloads may fail.\nDo you wish to continue?" defaultButton:@"No" alternateButton:@"Yes" otherButton:nil - informativeTextWithFormat:@"Failed to load %@ within %ld seconds\nUsing proxy: %@\nError: %@", [request url], (NSInteger)[request timeOutSeconds], [proxy url], (error ? [error localizedDescription] : @"Unknown error")]; + informativeTextWithFormat:@"Invalid proxy host: address=[%@] length=%ld", proxy.host, [proxy.host length]]; [alert setAlertStyle:NSCriticalAlertStyle]; if ([alert runModal] == NSAlertDefaultReturn) - [self cancelProxyLoad]; + [self cancelProxyLoad]; else - [self failProxyTest]; - } - } - else - { - [self finishProxyTest]; - } + [self failProxyTest]; + } + return; + } + NSString *testURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"ProxyTestURL"]; + if (!testURL) + testURL = @"http://www.google.com"; + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:testURL]]; + [request setDelegate:self]; + [request setDidFailSelector:@selector(proxyTestDidFinish:)]; + [request setDidFinishSelector:@selector(proxyTestDidFinish:)]; + [request setTimeOutSeconds:30]; + [request setProxyType:proxy.type]; + [request setProxyHost:proxy.host]; + if (proxy.port) { + [request setProxyPort:proxy.port]; + } else { + if ([proxy.type isEqualToString:(NSString *)kCFProxyTypeHTTPS]) { + [request setProxyPort:443]; + } else { + [request setProxyPort:80]; + } + } + if (proxy.user) { + [request setProxyUsername:proxy.user]; + [request setProxyPassword:proxy.password]; + } + [self updateProxyLoadStatus:YES message:[NSString stringWithFormat:@"Testing proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]]]; + NSLog(@"INFO: Testing proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]); + [self addToLog:[NSString stringWithFormat:@"INFO: Testing proxy (may take up to %ld seconds)...", (NSInteger)[request timeOutSeconds]]]; + [request startAsynchronous]; + } + else + { + NSLog(@"INFO: No proxy to test"); + [self addToLog:@"INFO: No proxy to test"]; + [self finishProxyTest]; + } +} + +- (void)proxyTestDidFinish:(ASIHTTPRequest *)request +{ + if ([request responseStatusCode] != 200) + { + NSLog(@"WARNING: Proxy failed to load test page: %@", [request url]); + [self addToLog:[NSString stringWithFormat:@"WARNING: Proxy failed to load test page: %@", [request url]]]; + if (!runScheduled) + { + NSError *error = [request error]; + NSAlert *alert = [NSAlert alertWithMessageText:@"Proxy failed to load test page.\nDownloads may fail.\nDo you wish to continue?" + defaultButton:@"No" + alternateButton:@"Yes" + otherButton:nil + informativeTextWithFormat:@"Failed to load %@ within %ld seconds\nUsing proxy: %@\nError: %@", [request url], (NSInteger)[request timeOutSeconds], [proxy url], (error ? [error localizedDescription] : @"Unknown error")]; + [alert setAlertStyle:NSCriticalAlertStyle]; + if ([alert runModal] == NSAlertDefaultReturn) + [self cancelProxyLoad]; + else + [self failProxyTest]; + } + } + else + { + [self finishProxyTest]; + } } - (void)failProxyTest { - [self returnFromProxyLoadWithError:[NSError errorWithDomain:@"Proxy" code:kProxyLoadFailed userInfo:@{NSLocalizedDescriptionKey: @"Proxy Test Failed"}]]; + [self returnFromProxyLoadWithError:[NSError errorWithDomain:@"Proxy" code:kProxyLoadFailed userInfo:@{NSLocalizedDescriptionKey: @"Proxy Test Failed"}]]; } - (void)finishProxyTest { - NSLog(@"INFO: Proxy test complete."); - [self addToLog:@"INFO: Proxy test complete."]; - [self returnFromProxyLoadWithError:nil]; + NSLog(@"INFO: Proxy test complete."); + [self addToLog:@"INFO: Proxy test complete."]; + [self returnFromProxyLoadWithError:nil]; } - (void)returnFromProxyLoadWithError:(NSError *)error { - if (proxy) - { - NSLog(@"INFO: Using proxy: %@", proxy.url); - [self addToLog:[NSString stringWithFormat:@"INFO: Using proxy: %@", proxy.url]]; - } - else - { - NSLog(@"INFO: No proxy will be used"); - [self addToLog:@"INFO: No proxy will be used"]; - } - [self updateProxyLoadStatus:NO message:nil]; - [self performSelector:[proxyDict[@"selector"] pointerValue] withObject:proxyDict[@"object"] withObject:error]; + if (proxy) + { + NSLog(@"INFO: Using proxy: %@", proxy.url); + [self addToLog:[NSString stringWithFormat:@"INFO: Using proxy: %@", proxy.url]]; + } + else + { + NSLog(@"INFO: No proxy will be used"); + [self addToLog:@"INFO: No proxy will be used"]; + } + [self updateProxyLoadStatus:NO message:nil]; + [proxyDict[@"target"] performSelector:[proxyDict[@"selector"] pointerValue] withObject:proxyDict[@"object"] withObject:error]; } - (void)updateProxyLoadStatus:(BOOL)working message:(NSString *)message { - @try - { - if (working) - { - [currentIndicator setIndeterminate:YES]; - [currentIndicator startAnimation:nil]; - [currentProgress setStringValue:message]; - } - else - { - [currentIndicator setIndeterminate:NO]; - [currentIndicator stopAnimation:nil]; - [currentProgress setStringValue:@""]; - } - } - @catch (NSException *e) { - NSLog(@"NO UI: updateProxyLoadStatus:message:"); - } + @try + { + if (working) + { + [currentIndicator setIndeterminate:YES]; + [currentIndicator startAnimation:nil]; + [currentProgress setStringValue:message]; + } + else + { + [currentIndicator setIndeterminate:NO]; + [currentIndicator stopAnimation:nil]; + [currentProgress setStringValue:@""]; + } + } + @catch (NSException *e) { + NSLog(@"NO UI: updateProxyLoadStatus:message:"); + } +} + +#pragma mark Extended Show Information +- (IBAction)showExtendedInformationForSelectedProgramme:(id)sender { + popover.behavior = NSPopoverBehaviorTransient; + [self addToLog:@"Retrieving Information." :self]; + Programme *programme = searchResultsArray[[searchResultsTable selectedRow]]; + if (programme) { + infoView.alphaValue = 0.1; + loadingView.alphaValue = 1.0; + [retrievingInfoIndicator startAnimation:self]; + + @try { + [popover showRelativeToRect:[searchResultsTable frameOfCellAtColumn:1 row:[searchResultsTable selectedRow]] ofView:(NSView *)searchResultsTable preferredEdge:NSMaxYEdge]; + } + @catch (NSException *exception) { + NSLog(@"%@",[exception description]); + NSLog(@"%@",searchResultsTable); + return; + } + if (!programme.extendedMetadataRetrieved.boolValue) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(informationRetrieved:) name:@"ExtendedInfoRetrieved" object:programme]; + [programme retrieveExtendedMetadata]; + } + else { + [self informationRetrieved:[NSNotification notificationWithName:@"" object:programme]]; + } + } +} +- (void)informationRetrieved:(NSNotification *)note { + Programme *programme = note.object; + + if (programme.successfulRetrieval.boolValue) { + if (programme.thumbnail) + imageView.image = programme.thumbnail; + + if (programme.seriesName) + seriesName.stringValue = programme.seriesName; + else + seriesName.stringValue = @"Unable to Retrieve"; + + if (programme.episodeName) + episodeName.stringValue = programme.episodeName; + else + seriesName.stringValue = @""; + + if (programme.season && programme.episode) + numbersField.stringValue = [NSString stringWithFormat:@"Series: %ld Episode: %ld",(long)programme.season,(long)programme.episode]; + else + numbersField.stringValue = @""; + + if (programme.duration) + durationField.stringValue = [NSString stringWithFormat:@"Duration: %d minutes",programme.duration.intValue]; + else + durationField.stringValue = @""; + + if (programme.categories) + categoriesField.stringValue = [NSString stringWithFormat:@"Categories: %@",programme.categories]; + else + categoriesField.stringValue = @""; + + if (programme.firstBroadcast) + firstBroadcastField.stringValue = [NSString stringWithFormat:@"First Broadcast: %@",[programme.firstBroadcast description]]; + else + firstBroadcastField.stringValue = @""; + + if (programme.lastBroadcast) + lastBroadcastField.stringValue = [NSString stringWithFormat:@"Last Broadcast: %@", [programme.lastBroadcast description]]; + else + lastBroadcastField.stringValue = @""; + + if (programme.desc) + descriptionView.string = programme.desc; + else + descriptionView.string = @""; + + if (programme.modeSizes) + modeSizeController.content = programme.modeSizes; + else + modeSizeController.content = [NSDictionary dictionary]; + + [retrievingInfoIndicator stopAnimation:self]; + infoView.alphaValue = 1.0; + loadingView.alphaValue = 0.0; + [self addToLog:@"Info Retrieved" :self]; + } + else { + [retrievingInfoIndicator stopAnimation:self]; + loadingLabel.stringValue = @"Info could not be retrieved."; + [self addToLog:@"Info could not be retrieved" :self]; + } } @synthesize log_value; @synthesize getiPlayerPath; +@synthesize proxy; @end diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 57f7d7a5..f12dcd1d 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -18,21 +18,34 @@ + + + + + + + + + + + + + @@ -43,9 +56,12 @@ + + + @@ -236,6 +252,7 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA + @@ -504,11 +521,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -557,7 +574,7 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + @@ -591,11 +608,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -630,17 +647,17 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + - + @@ -651,7 +668,7 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + @@ -659,7 +676,22 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + + + + + + + + + + + + + + + + @@ -681,15 +713,15 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + - + @@ -877,11 +909,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -925,11 +957,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -953,7 +985,7 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + @@ -1023,7 +1055,7 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + @@ -1665,11 +1697,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -1951,11 +1983,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -1967,11 +1999,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -2005,11 +2037,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -2089,11 +2121,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -2127,11 +2159,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -2221,11 +2253,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -2271,7 +2303,7 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + @@ -2301,11 +2333,11 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + @@ -2453,17 +2485,17 @@ AQABAAEAAQAB//+dkAEA//+PgAAE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAABA - + - + - + - + @@ -2725,6 +2757,226 @@ DQ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Get_iPlayer GUI.xcodeproj/project.pbxproj b/Get_iPlayer GUI.xcodeproj/project.pbxproj index cb352339..347b496e 100644 --- a/Get_iPlayer GUI.xcodeproj/project.pbxproj +++ b/Get_iPlayer GUI.xcodeproj/project.pbxproj @@ -586,7 +586,6 @@ buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Get iPlayer Automator" */; buildPhases = ( D9CCF443102349ED009205BE /* Copy Frameworks */, - D9279DD6182045CA008DBB09 /* ShellScript */, 8D1107290486CEB800E47090 /* Resources */, 8D11072C0486CEB800E47090 /* Sources */, 8D11072E0486CEB800E47090 /* Frameworks */, @@ -684,22 +683,6 @@ }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - D9279DD6182045CA008DBB09 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "LOCATION=\"${BUILT_PRODUCTS_DIR}\"/\"${FRAMEWORKS_FOLDER_PATH}\"\nIDENTITY=\"Developer ID Application: Thomas Willson\"\ncodesign --verbose --force --sign \"$IDENTITY\" \"$LOCATION/Sparkle.framework/Versions/A\""; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 8D11072C0486CEB800E47090 /* Sources */ = { isa = PBXSourcesBuildPhase; diff --git a/Get_iPlayer GUI.xcodeproj/project.xcworkspace/xcuserdata/thomaswillson.xcuserdatad/UserInterfaceState.xcuserstate b/Get_iPlayer GUI.xcodeproj/project.xcworkspace/xcuserdata/thomaswillson.xcuserdatad/UserInterfaceState.xcuserstate index 6c9a217d..737f84db 100644 Binary files a/Get_iPlayer GUI.xcodeproj/project.xcworkspace/xcuserdata/thomaswillson.xcuserdatad/UserInterfaceState.xcuserstate and b/Get_iPlayer GUI.xcodeproj/project.xcworkspace/xcuserdata/thomaswillson.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Programme.h b/Programme.h index 80fafbca..6f0a6817 100644 --- a/Programme.h +++ b/Programme.h @@ -6,7 +6,7 @@ // Copyright 2009 __MyCompanyName__. All rights reserved. // -#import +#import @interface Programme : NSObject { @@ -34,12 +34,25 @@ NSNumber *podcast; //Extended Metadata + NSNumber *extendedMetadataRetrieved; + NSNumber *successfulRetrieval; NSNumber *duration; + NSString *categories; + NSDate *__strong firstBroadcast; + NSDate *__strong lastBroadcast; + NSDictionary *modeSizes; + NSImage *thumbnail; + + NSMutableString *taskOutput; + NSPipe *pipe; + volatile bool taskRunning; + } - (id)initWithInfo:(id)sender pid:(NSString *)PID programmeName:(NSString *)SHOWNAME network:(NSString *)TVNETWORK; - (id)initWithShow:(Programme *)show; - (void)printLongDescription; +- (void)retrieveExtendedMetadata; @property (readwrite) NSString *showName; @property (readwrite) NSString *tvNetwork; @@ -63,4 +76,13 @@ @property (readwrite, strong) NSDate *dateAired; @property (readwrite) NSString *desc; @property (readwrite) NSNumber *podcast; + +@property (readwrite) NSNumber *extendedMetadataRetrieved; +@property (readwrite) NSNumber *successfulRetrieval; +@property (readwrite) NSNumber *duration; +@property (readwrite) NSString *categories; +@property (readwrite) NSDate *firstBroadcast; +@property (readwrite) NSDate *lastBroadcast; +@property (readwrite) NSDictionary *modeSizes; +@property (readwrite) NSImage *thumbnail; @end diff --git a/Programme.m b/Programme.m index 1bcbb083..dd8ba68f 100644 --- a/Programme.m +++ b/Programme.m @@ -8,7 +8,10 @@ #import "Programme.h" #import "NSString+HTML.h" -extern BOOL runDownloads; +#import "AppController.h" +#import "HTTPProxy.h" +#import "ASIHTTPRequest.h" +//extern bool runDownloads; @implementation Programme @@ -29,10 +32,11 @@ - (id)initWithInfo:(id)sender pid:(NSString *)PID programmeName:(NSString *)SHOW radio = @NO; subtitlePath=[[NSString alloc] init]; realPID=[[NSString alloc] init]; - reasonForFailure=[[NSString alloc] init]; - availableModes=[[NSString alloc] init]; - desc=[[NSString alloc] init]; - podcast=@NO; + reasonForFailure=[[NSString alloc] init]; + availableModes=[[NSString alloc] init]; + desc=[[NSString alloc] init]; + podcast=@NO; + extendedMetadataRetrieved=@NO; return self; } - (id)initWithShow:(Programme *)show @@ -51,10 +55,11 @@ - (id)initWithShow:(Programme *)show radio = [show radio]; realPID = [show realPID]; subtitlePath = [show subtitlePath]; - reasonForFailure=[show reasonForFailure]; - availableModes=[[NSString alloc] init]; - desc=[[NSString alloc] init]; - podcast = [show podcast]; + reasonForFailure=[show reasonForFailure]; + availableModes=[[NSString alloc] init]; + desc=[[NSString alloc] init]; + podcast = [show podcast]; + extendedMetadataRetrieved=@NO; return self; } - (id)init @@ -78,13 +83,14 @@ - (id)init path = @"Unknown"; processedPID = @NO; radio = @NO; - url = [[NSString alloc] init]; + url = [[NSString alloc] init]; realPID=[[NSString alloc] init]; subtitlePath=[[NSString alloc] init]; - reasonForFailure=[[NSString alloc] init]; - availableModes=[[NSString alloc] init]; - desc=[[NSString alloc] init]; - podcast=@NO; + reasonForFailure=[[NSString alloc] init]; + availableModes=[[NSString alloc] init]; + desc=[[NSString alloc] init]; + podcast=@NO; + extendedMetadataRetrieved=@NO; return self; } - (id)description @@ -104,8 +110,8 @@ - (void) encodeWithCoder: (NSCoder *)coder [coder encodeObject:processedPID forKey:@"processedPID"]; [coder encodeObject:radio forKey:@"radio"]; [coder encodeObject:realPID forKey:@"realPID"]; - [coder encodeObject:url forKey:@"url"]; - [coder encodeObject:podcast forKey:@"podcast"]; + [coder encodeObject:url forKey:@"url"]; + [coder encodeObject:podcast forKey:@"podcast"]; } - (id) initWithCoder: (NSCoder *)coder { @@ -123,39 +129,221 @@ - (id) initWithCoder: (NSCoder *)coder processedPID = [coder decodeObjectForKey:@"processedPID"]; radio = [coder decodeObjectForKey:@"radio"]; realPID = [coder decodeObjectForKey:@"realPID"]; - url = [coder decodeObjectForKey:@"url"]; + url = [coder decodeObjectForKey:@"url"]; subtitlePath=[[NSString alloc] init]; - reasonForFailure=[[NSString alloc] init]; - availableModes=[[NSString alloc] init]; - desc=[[NSString alloc] init]; - podcast = [coder decodeObjectForKey:@"podcast"]; + reasonForFailure=[[NSString alloc] init]; + availableModes=[[NSString alloc] init]; + desc=[[NSString alloc] init]; + podcast = [coder decodeObjectForKey:@"podcast"]; + extendedMetadataRetrieved=@NO; return self; } /* -- (id)pasteboardPropertyListForType:(NSString *)type + - (id)pasteboardPropertyListForType:(NSString *)type + { + if ([type isEqualToString:@"com.thomaswillson.programme"]) + { + return [NSKeyedArchiver archivedDataWithRootObject:self]; + } + } + - (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard + { + return [NSArray arrayWithObject:@"com.thomaswillson.programme"]; + } + */ +-(void)setPid:(NSString *)newPID { - if ([type isEqualToString:@"com.thomaswillson.programme"]) - { - return [NSKeyedArchiver archivedDataWithRootObject:self]; + self->pid = [newPID stringByReplacingOccurrencesOfString:@"amp;" withString:@""]; +} +-(NSString *)pid +{ + return pid; +} +-(void)printLongDescription +{ + NSLog(@"%@:\n TV Network: %@\n Processed PID: %@\n Real PID: %@\n Available Modes: %@\n URL: %@\n", + showName,tvNetwork,processedPID,realPID,availableModes,url); +} + +-(void)retrieveExtendedMetadata +{ + [[AppController sharedController] addToLog:@"Retrieving Extended Metadata" :self]; + [[AppController sharedController] loadProxyInBackgroundForSelector:@selector(proxyRetrievalFinished:proxyError:) withObject:nil onTarget:self]; +} + +-(void)proxyRetrievalFinished:(id)sender proxyError:(NSError *)proxyError +{ + taskOutput = [[NSMutableString alloc] init]; + NSTask *task = [[NSTask alloc] init]; + pipe = [[NSPipe alloc] init]; + + [task setLaunchPath:@"/usr/bin/perl"]; + NSMutableArray *args = [NSMutableArray arrayWithArray:@[[[NSBundle mainBundle] pathForResource:@"get_iplayer" ofType:@"pl"], + @"--nopurge", + @"--nocopyright", + @"-e60480000000000000", + @"-i", + [NSString stringWithFormat:@"--profile-dir=%@",[@"~/Library/Application Support/Get iPlayer Automator/" stringByExpandingTildeInPath]],pid]]; + if ([AppController sharedController].proxy) { + [args addObject:[AppController sharedController].proxy.url]; + + if (![[[NSUserDefaults standardUserDefaults] valueForKey:@"AlwaysUseProxy"] boolValue]) + { + [args addObject:@"--partial-proxy"]; + } + + } + + [task setArguments:args]; + + [task setStandardOutput:pipe]; + NSFileHandle *fh = [pipe fileHandleForReading]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(metadataRetrievalDataReady:) name:NSFileHandleReadCompletionNotification object:fh]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(metadataRetrievalFinished:) name:NSTaskDidTerminateNotification object:task]; + + [task launch]; + [fh readInBackgroundAndNotify]; +} + +-(void)metadataRetrievalDataReady:(NSNotification *)n +{ + NSData *d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; + + if ([d length] > 0) { + NSString *s = [[NSString alloc] initWithData:d + encoding:NSUTF8StringEncoding]; + + [taskOutput appendString:s]; + [[AppController sharedController] addToLog:s :self]; + [[pipe fileHandleForReading] readInBackgroundAndNotify]; } + else { + [self metadataRetrievalFinished:nil]; + } } -- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard + +-(void)metadataRetrievalFinished:(NSNotification *)n { - return [NSArray arrayWithObject:@"com.thomaswillson.programme"]; + taskRunning=NO; + categories = [self scanField:@"categories" fromList:taskOutput]; + + NSString *descTemp = [self scanField:@"desc" fromList:taskOutput]; + if (descTemp) { + desc = descTemp; + } + + NSString *durationTemp = [self scanField:@"duration" fromList:taskOutput]; + if (durationTemp) { + if ([durationTemp hasSuffix:@"min"]) + duration = [NSNumber numberWithInteger:[durationTemp integerValue]]; + else + duration = [NSNumber numberWithInteger:[durationTemp integerValue]/60]; + } + + firstBroadcast = [self processDate:[self scanField:@"firstbcast" fromList:taskOutput]]; + lastBroadcast = [self processDate:[self scanField:@"lastbcast" fromList:taskOutput]]; + + seriesName = [self scanField:@"longname" fromList:taskOutput]; + + episodeName = [self scanField:@"episode" fromList:taskOutput]; + + NSString *seasonNumber = [self scanField:@"seriesnum" fromList:taskOutput]; + if (seasonNumber) { + season = [seasonNumber integerValue]; + } + + NSString *episodeNumber = [self scanField:@"episodenum" fromList:taskOutput]; + if (episodeNumber) { + episode = [episodeNumber integerValue]; + } + NSString *modeSizesString = [self scanField:@"modesizes" fromList:taskOutput]; + if (modeSizesString) { + NSScanner *sizeScanner = [NSScanner scannerWithString:modeSizesString]; + [sizeScanner scanString:@"default:" intoString:nil]; + NSString *newSizesString; + [sizeScanner scanUpToString:@":" intoString:&newSizesString]; + + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[a-z]*[0-2]=[0-9]*MB" options:0 error:nil]; + NSArray *matches = [regex matchesInString:newSizesString options:0 range:NSMakeRange(0, [newSizesString length])]; + if ([matches count] > 0) { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + for (NSTextCheckingResult *modesizeResult in matches) { + NSString *modesize = [newSizesString substringWithRange:modesizeResult.range]; + if ([modesize hasPrefix:@"rtsp"] || [modesize hasPrefix:@"wma"]) { + continue; + } + NSArray *comps = [modesize componentsSeparatedByString:@"="]; + if ([comps count] == 2) { + [dictionary setObject:comps[1] forKey:comps[0]]; + } + } + modeSizes = dictionary; + } + } + NSString *thumbURL = [self scanField:@"thumbnail4" fromList:taskOutput]; + if (!thumbURL) { + thumbURL = [self scanField:@"thumbnail" fromList:taskOutput]; + } + if (thumbURL) { + NSLog(@"URL: %@", thumbURL); + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:thumbURL]]; + [request setDelegate:self]; + [request setDidFinishSelector:@selector(thumbnailRequestFinished:)]; + [request setDidFailSelector:@selector(thumbnailRequestFinished:)]; + [request setTimeOutSeconds:3]; + [request setNumberOfTimesToRetryOnTimeout:3]; + [request startAsynchronous]; + } } - */ --(void)setPid:(NSString *)newPID + +- (void)thumbnailRequestFinished:(ASIHTTPRequest *)request { - self->pid = [newPID stringByReplacingOccurrencesOfString:@"amp;" withString:@""]; + if (request.responseStatusCode == 200) { + thumbnail = [[NSImage alloc] initWithData:request.responseData]; + } + successfulRetrieval = @YES; + extendedMetadataRetrieved = @YES; + [[NSNotificationCenter defaultCenter] postNotificationName:@"ExtendedInfoRetrieved" object:self]; + } --(NSString *)pid + +-(NSString *)scanField:(NSString *)field fromList:(NSString *)list { - return pid; + NSString __autoreleasing *buffer; + + NSScanner *scanner = [NSScanner scannerWithString:list]; + [scanner scanUpToString:[NSString stringWithFormat:@"%@:",field] intoString:nil]; + [scanner scanString:[NSString stringWithFormat:@"%@:",field] intoString:nil]; + [scanner scanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:nil]; + [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&buffer]; + + return [buffer copy]; } --(void)printLongDescription + +-(NSDate *)processDate:(NSString *)date { - NSLog(@"%@:\n TV Network: %@\n Processed PID: %@\n Real PID: %@\n Available Modes: %@\n URL: %@\n", - showName,tvNetwork,processedPID,realPID,availableModes,url); + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_8) //10.8, 10.9 + [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZZZ"]; + else //10.7 + [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZ"]; + + if (date) { + date = [self scanField:@"default" fromList:date]; + if (date) { + if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_8) { //Before 10.8 doesn't recognize the Z + if ([date hasSuffix:@"Z"]) { + date = [date stringByReplacingOccurrencesOfString:@"Z" withString:@"+00:00"]; + } + } + if (NSAppKitVersionNumber < NSAppKitVersionNumber10_8) { + date = [date stringByReplacingCharactersInRange:NSMakeRange(date.length - 3, 1) withString:@""]; + } + return [dateFormatter dateFromString:date]; + } + } + return nil; } @synthesize showName; @@ -179,4 +367,13 @@ -(void)printLongDescription @synthesize dateAired; @synthesize desc; @synthesize podcast; + +@synthesize extendedMetadataRetrieved; +@synthesize successfulRetrieval; +@synthesize duration; +@synthesize categories; +@synthesize firstBroadcast; +@synthesize lastBroadcast; +@synthesize modeSizes; +@synthesize thumbnail; @end