diff --git a/Limelight/App.h b/Limelight/App.h index 2c35cea..5623eff 100644 --- a/Limelight/App.h +++ b/Limelight/App.h @@ -13,5 +13,6 @@ @property NSString* appId; @property NSString* appName; @property UIImage* appImage; +@property BOOL isRunning; @end diff --git a/Limelight/App.m b/Limelight/App.m index f83476d..ade5541 100644 --- a/Limelight/App.m +++ b/Limelight/App.m @@ -10,6 +10,6 @@ #import "HttpManager.h" @implementation App -@synthesize appId, appName, appImage; +@synthesize appId, appName, appImage, isRunning; @end diff --git a/Limelight/Network/HttpManager.h b/Limelight/Network/HttpManager.h index c7c4b36..2d9ca16 100644 --- a/Limelight/Network/HttpManager.h +++ b/Limelight/Network/HttpManager.h @@ -25,6 +25,7 @@ - (NSURLRequest*) newServerInfoRequest; - (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid; - (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId; +- (NSURLRequest*) newQuitAppRequest; - (NSURLRequest*) newAppAssetRequestWithAppId:(NSString*)appId; - (NSData*) executeRequestSynchronously:(NSURLRequest*)request; @end diff --git a/Limelight/Network/HttpManager.m b/Limelight/Network/HttpManager.m index 10b6eb8..e32093b 100644 --- a/Limelight/Network/HttpManager.m +++ b/Limelight/Network/HttpManager.m @@ -54,6 +54,7 @@ static const NSString* PORT = @"47984"; xmlNodePtr appInfoNode = node->xmlChildrenNode; NSString* appName; NSString* appId; + BOOL appIsRunning = NO; while (appInfoNode != NULL) { NSLog(@"appInfoNode: %s", appInfoNode->name); if (!xmlStrcmp(appInfoNode->name, (const xmlChar*)"AppTitle")) { @@ -64,12 +65,17 @@ static const NSString* PORT = @"47984"; xmlChar* nodeVal = xmlNodeListGetString(docPtr, appInfoNode->xmlChildrenNode, 1); appId = [[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding]; xmlFree(nodeVal); + } else if (!xmlStrcmp(appInfoNode->name, (const xmlChar*)"IsRunning")) { + xmlChar* nodeVal = xmlNodeListGetString(docPtr, appInfoNode->xmlChildrenNode, 1); + appIsRunning = [[[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding] isEqualToString:@"1"]; + xmlFree(nodeVal); } appInfoNode = appInfoNode->next; } App* app = [[App alloc] init]; app.appName = appName; app.appId = appId; + app.isRunning = appIsRunning; [appList addObject:app]; } node = node->next; @@ -254,6 +260,11 @@ static const NSString* PORT = @"47984"; return [self createRequestFromString:urlString enableTimeout:FALSE]; } +- (NSURLRequest*) newQuitAppRequest { + NSString* urlString = [NSString stringWithFormat:@"%@/cancel?uniqueid=%@", _baseURL, _uniqueId]; + return [self createRequestFromString:urlString enableTimeout:FALSE]; +} + - (NSURLRequest*) newAppAssetRequestWithAppId:(NSString *)appId { NSString* urlString = [NSString stringWithFormat:@"%@/appasset?uniqueid=%@&appid=%@&AssetType=2&AssetIdx=0", _baseURL, _uniqueId, appId]; return [self createRequestFromString:urlString enableTimeout:FALSE]; diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 72e0b37..7fb3869 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -26,10 +26,11 @@ Computer* _selectedHost; NSString* _uniqueId; NSData* _cert; + NSString* _currentGame; UIAlertView* _pairAlert; UIScrollView* hostScrollView; - int currentPosition; + int currentPosition; } static NSString* deviceName = @"roth"; static NSMutableSet* hostList; @@ -65,7 +66,6 @@ static StreamConfiguration* streamConfig; - (void)alreadyPaired { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.hostName uniqueId:_uniqueId deviceName:deviceName cert:_cert]; NSData* appListResp = [hMan executeRequestSynchronously:[hMan newAppListRequest]]; appList = [HttpManager getAppListFromXML:appListResp]; @@ -73,6 +73,7 @@ static StreamConfiguration* streamConfig; [self updateApps]; _computerNameButton.title = _selectedHost.displayName; }); + [AppManager retrieveAppAssets:appList withManager:hMan andCallback:self]; }); } @@ -157,7 +158,53 @@ static StreamConfiguration* streamConfig; if (currentPosition != FrontViewPositionLeft) { [[self revealViewController] revealToggle:self]; } - [self performSegueWithIdentifier:@"createStreamFrame" sender:nil]; + + App* currentApp = [self findRunningApp]; + if (currentApp != nil) { + UIAlertController* alertController = [UIAlertController alertControllerWithTitle:@"App Already Running" message:[NSString stringWithFormat:@"%@ is currently running", currentApp.appName] preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Resume App" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){ + NSLog(@"Resuming application: %@", currentApp.appName); + [self performSegueWithIdentifier:@"createStreamFrame" sender:nil]; + }]]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Quit App" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){ + NSLog(@"Quitting application: %@", currentApp.appName); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.hostName uniqueId:_uniqueId deviceName:deviceName cert:_cert]; + [hMan executeRequestSynchronously:[hMan newQuitAppRequest]]; + // TODO: handle failure to quit app + currentApp.isRunning = NO; + + if (![app.appId isEqualToString:currentApp.appId]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self performSegueWithIdentifier:@"createStreamFrame" sender:nil]; + }); + } + }); + }]]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:alertController animated:YES completion:nil]; + } else { + [self performSegueWithIdentifier:@"createStreamFrame" sender:nil]; + } +} + + +- (App*) findRunningApp { + for (App* app in appList) { + if (app.isRunning) { + return app; + } + } + return nil; +} + +- (App*) findAppInAppList:(NSString*)appId { + for (App* app in appList) { + if ([app.appId isEqualToString:appId]) { + return app; + } + } + return nil; } - (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position { @@ -222,6 +269,11 @@ static StreamConfiguration* streamConfig; _mDNSManager = [[MDNSManager alloc] initWithCallback:self]; [_mDNSManager searchForHosts]; + + // This will refresh the applist + if (_selectedHost != nil) { + [self hostClicked:_selectedHost]; + } } - (void)viewDidDisappear:(BOOL)animated @@ -281,16 +333,16 @@ static StreamConfiguration* streamConfig; App* app = appList[indexPath.row]; UIAppView* appView = [[UIAppView alloc] initWithApp:app andCallback:self]; [appView updateAppImage]; - + if (appView.bounds.size.width > 10.0) { CGFloat scale = cell.bounds.size.width / appView.bounds.size.width; [appView setCenter:CGPointMake(appView.bounds.size.width / 2 * scale, appView.bounds.size.height / 2 * scale)]; appView.transform = CGAffineTransformMakeScale(scale, scale); } - + [cell.subviews.firstObject removeFromSuperview]; // Remove a view that was previously added [cell addSubview:appView]; - + return cell; }